mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-06 23:30:55 +03:00
- Formal generation of ASN.1 encoding for the ecdsa signature
- Support ecdsa-sha2-nistp521
This commit is contained in:
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user