connectbot/sshlib

View on GitHub
src/main/java/com/trilead/ssh2/signature/RSASHA512Verify.java

Summary

Maintainability
B
6 hrs
Test Coverage
C
75%
Similar blocks of code found in 2 locations. Consider refactoring.
package com.trilead.ssh2.signature;
 
import com.trilead.ssh2.log.Logger;
import com.trilead.ssh2.packets.TypesReader;
import com.trilead.ssh2.packets.TypesWriter;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
 
public class RSASHA512Verify implements SSHSignature
{
private static final Logger log = Logger.getLogger(RSASHA512Verify.class);
public static final String ID_RSA_SHA_2_512 = "rsa-sha2-512";
 
private static class InstanceHolder {
private static final RSASHA512Verify sInstance = new RSASHA512Verify();
}
 
private RSASHA512Verify() {
}
 
public static RSASHA512Verify get() {
return RSASHA512Verify.InstanceHolder.sInstance;
}
 
private static byte[] decodeRSASHA512Signature(byte[] sig) throws IOException
{
TypesReader tr = new TypesReader(sig);
 
String sig_format = tr.readString();
 
if (!sig_format.equals(ID_RSA_SHA_2_512))
throw new IOException("Peer sent wrong signature format");
 
/* S is NOT an MPINT. "The value for 'rsa_signature_blob' is encoded as a string
* containing s (which is an integer, without lengths or padding, unsigned and in
* network byte order)." See also below.
*/
 
byte[] s = tr.readByteString();
 
if (s.length == 0)
throw new IOException("Error in RSA signature, S is empty.");
 
if (log.isEnabled())
{
log.log(80, "Decoding rsa-sha2-512 signature string (length: " + s.length + ")");
}
 
if (tr.remain() != 0)
throw new IOException("Padding in RSA signature!");
 
return s;
}
 
private static byte[] encodeRSASHA512Signature(byte[] s)
{
TypesWriter tw = new TypesWriter();
 
tw.writeString(ID_RSA_SHA_2_512);
 
/* S is NOT an MPINT. "The value for 'rsa_signature_blob' is encoded as a string
* containing s (which is an integer, without lengths or padding, unsigned and in
* network byte order)."
*/
 
/* Remove first zero sign byte, if present */
 
if ((s.length > 1) && (s[0] == 0x00))
tw.writeString(s, 1, s.length - 1);
else
tw.writeString(s, 0, s.length);
 
return tw.getBytes();
}
 
@Override
public byte[] generateSignature(byte[] message, PrivateKey privateKey, SecureRandom secureRandom) throws IOException
{
try {
// Android's Signature is guaranteed to support this instance
Signature s = Signature.getInstance("SHA512withRSA");
s.initSign(privateKey, secureRandom);
s.update(message);
return encodeRSASHA512Signature(s.sign());
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
throw new IOException(e);
}
}
 
@Override
public String getKeyFormat() {
return ID_RSA_SHA_2_512;
}
 
@Override
public PublicKey decodePublicKey(byte[] encoded) throws IOException {
return RSASHA1Verify.get().decodePublicKey(encoded);
}
 
@Override
public byte[] encodePublicKey(PublicKey publicKey) throws IOException {
return RSASHA1Verify.get().encodePublicKey(publicKey);
}
 
@Override
public boolean verifySignature(byte[] message, byte[] sshSig, PublicKey publicKey) throws IOException
{
byte[] javaSig = decodeRSASHA512Signature(sshSig);
try {
Signature s = Signature.getInstance("SHA512withRSA");
s.initVerify(publicKey);
s.update(message);
return s.verify(javaSig);
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
throw new IOException(e);
}
}
}