mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-06 07:10:53 +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.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()
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<Signature> {
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user