- Formal generation of ASN.1 encoding for the ecdsa signature

- Support ecdsa-sha2-nistp521
This commit is contained in:
Iger
2017-06-25 11:16:12 +03:00
committed by Jeroen van Erp
parent f8cad120a6
commit 3685f9dc36
3 changed files with 69 additions and 32 deletions

View File

@@ -48,7 +48,9 @@ import net.schmizz.sshj.transport.cipher.BlowfishCBC;
import net.schmizz.sshj.transport.cipher.Cipher; import net.schmizz.sshj.transport.cipher.Cipher;
import net.schmizz.sshj.transport.cipher.TripleDESCBC; import net.schmizz.sshj.transport.cipher.TripleDESCBC;
import net.schmizz.sshj.transport.compression.NoneCompression; 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.DHGexSHA1;
import net.schmizz.sshj.transport.kex.DHGexSHA256;
import net.schmizz.sshj.transport.kex.ECDHNistP; import net.schmizz.sshj.transport.kex.ECDHNistP;
import net.schmizz.sshj.transport.mac.HMACMD5; import net.schmizz.sshj.transport.mac.HMACMD5;
import net.schmizz.sshj.transport.mac.HMACMD596; import net.schmizz.sshj.transport.mac.HMACMD596;
@@ -125,8 +127,8 @@ public class DefaultConfig
protected void initKeyExchangeFactories(boolean bouncyCastleRegistered) { protected void initKeyExchangeFactories(boolean bouncyCastleRegistered) {
if (bouncyCastleRegistered) { if (bouncyCastleRegistered) {
setKeyExchangeFactories(/*new Curve25519SHA256.Factory(), setKeyExchangeFactories(new Curve25519SHA256.Factory(),
new DHGexSHA256.Factory(),*/ new DHGexSHA256.Factory(),
new ECDHNistP.Factory521(), new ECDHNistP.Factory521(),
new ECDHNistP.Factory384(), new ECDHNistP.Factory384(),
new ECDHNistP.Factory256(), new ECDHNistP.Factory256(),
@@ -229,6 +231,7 @@ public class DefaultConfig
setSignatureFactories( setSignatureFactories(
new SignatureECDSA.Factory256(), new SignatureECDSA.Factory256(),
new SignatureECDSA.Factory384(), new SignatureECDSA.Factory384(),
new SignatureECDSA.Factory521(),
new SignatureRSA.Factory(), new SignatureRSA.Factory(),
new SignatureDSA.Factory(), new SignatureDSA.Factory(),
new SignatureEdDSA.Factory() new SignatureEdDSA.Factory()

View File

@@ -155,6 +155,27 @@ public enum KeyType {
} }
}, },
/** 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") { ED25519("ssh-ed25519") {
private final Logger log = LoggerFactory.getLogger(KeyType.class); private final Logger log = LoggerFactory.getLogger(KeyType.class);
@Override @Override

View File

@@ -15,9 +15,16 @@
*/ */
package net.schmizz.sshj.signature; package net.schmizz.sshj.signature;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.SignatureException; 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.Buffer;
import net.schmizz.sshj.common.KeyType; import net.schmizz.sshj.common.KeyType;
import net.schmizz.sshj.common.SSHRuntimeException; import net.schmizz.sshj.common.SSHRuntimeException;
@@ -56,6 +63,22 @@ public class SignatureECDSA
return KeyType.ECDSA384.toString(); return KeyType.ECDSA384.toString();
} }
}
/** A named factory for ECDSA-521 signature */
public static class Factory521
implements net.schmizz.sshj.common.Factory.Named<Signature> {
@Override
public Signature create() {
return new SignatureECDSA("SHA512withECDSA", KeyType.ECDSA521.toString());
}
@Override
public String getName() {
return KeyType.ECDSA521.toString();
}
} }
private String keyTypeName; private String keyTypeName;
@@ -107,6 +130,16 @@ public class SignatureECDSA
throw new SSHRuntimeException(e); 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 rLen = r.length;
int sLen = s.length; int sLen = s.length;
@@ -120,37 +153,17 @@ public class SignatureECDSA
/* Calculate total output length */ /* Calculate total output length */
int length = 6 + rLen + sLen; int length = 6 + rLen + sLen;
byte[] asn1 = new byte[length];
/* ASN.1 SEQUENCE tag */ ASN1EncodableVector vector = new ASN1EncodableVector();
asn1[0] = (byte) 0x30; vector.add(new ASN1Integer(r));
vector.add(new ASN1Integer(s));
/* Size of SEQUENCE */ ByteArrayOutputStream baos = new ByteArrayOutputStream(length);
asn1[1] = (byte) (4 + rLen + sLen); ASN1OutputStream asnOS = new ASN1OutputStream(baos);
/* ASN.1 INTEGER tag */ asnOS.writeObject(new DERSequence(vector));
asn1[2] = (byte) 0x02; asnOS.flush();
/* "r" INTEGER length */ return baos.toByteArray();
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);
}
} }
} }