connectbot/sshlib

View on GitHub
src/main/java/com/trilead/ssh2/signature/RSASHA256Verify.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 RSASHA256Verify implements SSHSignature
{
private static final Logger log = Logger.getLogger(RSASHA256Verify.class);
public static final String ID_RSA_SHA_2_256 = "rsa-sha2-256";
 
private static class InstanceHolder {
private static RSASHA256Verify sInstance = new RSASHA256Verify();
}
 
private RSASHA256Verify() {
}
 
public static RSASHA256Verify get() {
return RSASHA256Verify.InstanceHolder.sInstance;
}
 
private static byte[] decodeRSASHA256Signature(byte[] sig) throws IOException
{
TypesReader tr = new TypesReader(sig);
 
String sig_format = tr.readString();
 
if (!sig_format.equals(ID_RSA_SHA_2_256))
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-256 signature string (length: " + s.length + ")");
}
 
if (tr.remain() != 0)
throw new IOException("Padding in RSA signature!");
 
return s;
}
 
private static byte[] encodeRSASHA256Signature(byte[] s) throws IOException
{
TypesWriter tw = new TypesWriter();
 
tw.writeString(ID_RSA_SHA_2_256);
 
/* 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 {
Signature s = Signature.getInstance("SHA256withRSA");
s.initSign(privateKey, secureRandom);
s.update(message);
return encodeRSASHA256Signature(s.sign());
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
throw new IOException(e);
}
}
 
@Override
public String getKeyFormat() {
return ID_RSA_SHA_2_256;
}
 
@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 dpk) throws IOException
{
byte[] javaSig = decodeRSASHA256Signature(sshSig);
 
try {
Signature s = Signature.getInstance("SHA256withRSA");
s.initVerify(dpk);
s.update(message);
return s.verify(javaSig);
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
throw new IOException(e);
}
}
}