From 3685f9dc361b6371df28baea527fac0f668d925d Mon Sep 17 00:00:00 2001 From: Iger Date: Sun, 25 Jun 2017 11:16:12 +0300 Subject: [PATCH] - Formal generation of ASN.1 encoding for the ecdsa signature - Support ecdsa-sha2-nistp521 --- .../java/net/schmizz/sshj/DefaultConfig.java | 7 +- .../java/net/schmizz/sshj/common/KeyType.java | 21 ++++++ .../sshj/signature/SignatureECDSA.java | 73 +++++++++++-------- 3 files changed, 69 insertions(+), 32 deletions(-) diff --git a/src/main/java/net/schmizz/sshj/DefaultConfig.java b/src/main/java/net/schmizz/sshj/DefaultConfig.java index 86d6fc07..256b4e31 100644 --- a/src/main/java/net/schmizz/sshj/DefaultConfig.java +++ b/src/main/java/net/schmizz/sshj/DefaultConfig.java @@ -48,7 +48,9 @@ import net.schmizz.sshj.transport.cipher.BlowfishCBC; import net.schmizz.sshj.transport.cipher.Cipher; import net.schmizz.sshj.transport.cipher.TripleDESCBC; import net.schmizz.sshj.transport.compression.NoneCompression; +import net.schmizz.sshj.transport.kex.Curve25519SHA256; import net.schmizz.sshj.transport.kex.DHGexSHA1; +import net.schmizz.sshj.transport.kex.DHGexSHA256; import net.schmizz.sshj.transport.kex.ECDHNistP; import net.schmizz.sshj.transport.mac.HMACMD5; import net.schmizz.sshj.transport.mac.HMACMD596; @@ -125,8 +127,8 @@ public class DefaultConfig protected void initKeyExchangeFactories(boolean bouncyCastleRegistered) { if (bouncyCastleRegistered) { - setKeyExchangeFactories(/*new Curve25519SHA256.Factory(), - new DHGexSHA256.Factory(),*/ + setKeyExchangeFactories(new Curve25519SHA256.Factory(), + new DHGexSHA256.Factory(), new ECDHNistP.Factory521(), new ECDHNistP.Factory384(), new ECDHNistP.Factory256(), @@ -229,6 +231,7 @@ public class DefaultConfig setSignatureFactories( new SignatureECDSA.Factory256(), new SignatureECDSA.Factory384(), + new SignatureECDSA.Factory521(), new SignatureRSA.Factory(), new SignatureDSA.Factory(), new SignatureEdDSA.Factory() diff --git a/src/main/java/net/schmizz/sshj/common/KeyType.java b/src/main/java/net/schmizz/sshj/common/KeyType.java index 20ab87ed..ce16e742 100644 --- a/src/main/java/net/schmizz/sshj/common/KeyType.java +++ b/src/main/java/net/schmizz/sshj/common/KeyType.java @@ -154,6 +154,27 @@ public enum KeyType { return ("ECDSA".equals(key.getAlgorithm()) && ECDSAVariationsAdapter.fieldSizeFromKey((ECPublicKey) key) == 384); } }, + + /** SSH identifier for ECDSA-521 keys */ + ECDSA521("ecdsa-sha2-nistp521") { + + @Override + public PublicKey readPubKeyFromBuffer(Buffer buf) + throws GeneralSecurityException { + return ECDSAVariationsAdapter.readPubKeyFromBuffer(buf, "521"); + } + + + @Override + protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer buf) { + ECDSAVariationsAdapter.writePubKeyContentsIntoBuffer(pk, buf); + } + + @Override + protected boolean isMyType(Key key) { + return ("ECDSA".equals(key.getAlgorithm()) && ECDSAVariationsAdapter.fieldSizeFromKey((ECPublicKey) key) == 521); + } + }, ED25519("ssh-ed25519") { private final Logger log = LoggerFactory.getLogger(KeyType.class); diff --git a/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java b/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java index 18264507..605d49e5 100644 --- a/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java +++ b/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java @@ -15,9 +15,16 @@ */ package net.schmizz.sshj.signature; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.math.BigInteger; import java.security.SignatureException; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1OutputStream; +import org.bouncycastle.asn1.DERSequence; + import net.schmizz.sshj.common.Buffer; import net.schmizz.sshj.common.KeyType; import net.schmizz.sshj.common.SSHRuntimeException; @@ -58,6 +65,22 @@ public class SignatureECDSA } + /** A named factory for ECDSA-521 signature */ + public static class Factory521 + implements net.schmizz.sshj.common.Factory.Named { + + @Override + public Signature create() { + return new SignatureECDSA("SHA512withECDSA", KeyType.ECDSA521.toString()); + } + + @Override + public String getName() { + return KeyType.ECDSA521.toString(); + } + + } + private String keyTypeName; public SignatureECDSA(String algorithm, String keyTypeName) { @@ -107,6 +130,16 @@ public class SignatureECDSA throw new SSHRuntimeException(e); } + try { + return signature.verify(asnEncode(r, s)); + } catch (SignatureException e) { + throw new SSHRuntimeException(e); + } catch (IOException e) { + throw new SSHRuntimeException(e); + } + } + + private byte[] asnEncode(byte[] r, byte[] s) throws IOException { int rLen = r.length; int sLen = s.length; @@ -120,37 +153,17 @@ public class SignatureECDSA /* Calculate total output length */ int length = 6 + rLen + sLen; - byte[] asn1 = new byte[length]; + + ASN1EncodableVector vector = new ASN1EncodableVector(); + vector.add(new ASN1Integer(r)); + vector.add(new ASN1Integer(s)); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(length); + ASN1OutputStream asnOS = new ASN1OutputStream(baos); - /* ASN.1 SEQUENCE tag */ - asn1[0] = (byte) 0x30; + asnOS.writeObject(new DERSequence(vector)); + asnOS.flush(); - /* Size of SEQUENCE */ - asn1[1] = (byte) (4 + rLen + sLen); - - /* ASN.1 INTEGER tag */ - asn1[2] = (byte) 0x02; - - /* "r" INTEGER length */ - asn1[3] = (byte) rLen; - - /* Copy in the "r" INTEGER */ - System.arraycopy(r, 0, asn1, 4, rLen); - - /* ASN.1 INTEGER tag */ - asn1[rLen + 4] = (byte) 0x02; - - /* "s" INTEGER length */ - asn1[rLen + 5] = (byte) sLen; - - /* Copy in the "s" INTEGER */ - System.arraycopy(s, 0, asn1, (6 + rLen), sLen); - - - try { - return signature.verify(asn1); - } catch (SignatureException e) { - throw new SSHRuntimeException(e); - } + return baos.toByteArray(); } }