mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-06 15:20:54 +03:00
- Pretty honed up implementation of -384
This commit is contained in:
@@ -15,12 +15,22 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj;
|
package net.schmizz.sshj;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import com.hierynomus.sshj.signature.SignatureEdDSA;
|
import com.hierynomus.sshj.signature.SignatureEdDSA;
|
||||||
import com.hierynomus.sshj.transport.cipher.BlockCiphers;
|
import com.hierynomus.sshj.transport.cipher.BlockCiphers;
|
||||||
import com.hierynomus.sshj.transport.cipher.StreamCiphers;
|
import com.hierynomus.sshj.transport.cipher.StreamCiphers;
|
||||||
import com.hierynomus.sshj.transport.kex.DHGroups;
|
import com.hierynomus.sshj.transport.kex.DHGroups;
|
||||||
import com.hierynomus.sshj.transport.kex.ExtendedDHGroups;
|
import com.hierynomus.sshj.transport.kex.ExtendedDHGroups;
|
||||||
import com.hierynomus.sshj.userauth.keyprovider.OpenSSHKeyV1KeyFile;
|
import com.hierynomus.sshj.userauth.keyprovider.OpenSSHKeyV1KeyFile;
|
||||||
|
|
||||||
import net.schmizz.keepalive.KeepAliveProvider;
|
import net.schmizz.keepalive.KeepAliveProvider;
|
||||||
import net.schmizz.sshj.common.Factory;
|
import net.schmizz.sshj.common.Factory;
|
||||||
import net.schmizz.sshj.common.LoggerFactory;
|
import net.schmizz.sshj.common.LoggerFactory;
|
||||||
@@ -28,13 +38,24 @@ import net.schmizz.sshj.common.SecurityUtils;
|
|||||||
import net.schmizz.sshj.signature.SignatureDSA;
|
import net.schmizz.sshj.signature.SignatureDSA;
|
||||||
import net.schmizz.sshj.signature.SignatureECDSA;
|
import net.schmizz.sshj.signature.SignatureECDSA;
|
||||||
import net.schmizz.sshj.signature.SignatureRSA;
|
import net.schmizz.sshj.signature.SignatureRSA;
|
||||||
import net.schmizz.sshj.transport.cipher.*;
|
import net.schmizz.sshj.transport.cipher.AES128CBC;
|
||||||
|
import net.schmizz.sshj.transport.cipher.AES128CTR;
|
||||||
|
import net.schmizz.sshj.transport.cipher.AES192CBC;
|
||||||
|
import net.schmizz.sshj.transport.cipher.AES192CTR;
|
||||||
|
import net.schmizz.sshj.transport.cipher.AES256CBC;
|
||||||
|
import net.schmizz.sshj.transport.cipher.AES256CTR;
|
||||||
|
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.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.*;
|
import net.schmizz.sshj.transport.mac.HMACMD5;
|
||||||
|
import net.schmizz.sshj.transport.mac.HMACMD596;
|
||||||
|
import net.schmizz.sshj.transport.mac.HMACSHA1;
|
||||||
|
import net.schmizz.sshj.transport.mac.HMACSHA196;
|
||||||
|
import net.schmizz.sshj.transport.mac.HMACSHA2256;
|
||||||
|
import net.schmizz.sshj.transport.mac.HMACSHA2512;
|
||||||
import net.schmizz.sshj.transport.random.BouncyCastleRandom;
|
import net.schmizz.sshj.transport.random.BouncyCastleRandom;
|
||||||
import net.schmizz.sshj.transport.random.JCERandom;
|
import net.schmizz.sshj.transport.random.JCERandom;
|
||||||
import net.schmizz.sshj.transport.random.SingletonRandomFactory;
|
import net.schmizz.sshj.transport.random.SingletonRandomFactory;
|
||||||
@@ -42,10 +63,6 @@ import net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyFile;
|
|||||||
import net.schmizz.sshj.userauth.keyprovider.PKCS5KeyFile;
|
import net.schmizz.sshj.userauth.keyprovider.PKCS5KeyFile;
|
||||||
import net.schmizz.sshj.userauth.keyprovider.PKCS8KeyFile;
|
import net.schmizz.sshj.userauth.keyprovider.PKCS8KeyFile;
|
||||||
import net.schmizz.sshj.userauth.keyprovider.PuTTYKeyFile;
|
import net.schmizz.sshj.userauth.keyprovider.PuTTYKeyFile;
|
||||||
import org.slf4j.Logger;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link net.schmizz.sshj.Config} that is initialized as follows. Items marked with an asterisk are added to the config only if
|
* A {@link net.schmizz.sshj.Config} that is initialized as follows. Items marked with an asterisk are added to the config only if
|
||||||
@@ -108,8 +125,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(),
|
||||||
@@ -210,7 +227,8 @@ public class DefaultConfig
|
|||||||
|
|
||||||
protected void initSignatureFactories() {
|
protected void initSignatureFactories() {
|
||||||
setSignatureFactories(
|
setSignatureFactories(
|
||||||
new SignatureECDSA.Factory(),
|
new SignatureECDSA.Factory256(),
|
||||||
|
new SignatureECDSA.Factory384(),
|
||||||
new SignatureRSA.Factory(),
|
new SignatureRSA.Factory(),
|
||||||
new SignatureDSA.Factory(),
|
new SignatureDSA.Factory(),
|
||||||
new SignatureEdDSA.Factory()
|
new SignatureEdDSA.Factory()
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package net.schmizz.sshj.common;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.interfaces.ECPublicKey;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.bouncycastle.asn1.nist.NISTNamedCurves;
|
||||||
|
import org.bouncycastle.asn1.x9.X9ECParameters;
|
||||||
|
import org.bouncycastle.jce.spec.ECParameterSpec;
|
||||||
|
import org.bouncycastle.jce.spec.ECPublicKeySpec;
|
||||||
|
import org.bouncycastle.math.ec.ECPoint;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.hierynomus.sshj.secg.SecgUtils;
|
||||||
|
|
||||||
|
public class ECDSAVariationsAdapter {
|
||||||
|
|
||||||
|
private final static String BASE_ALGORITHM_NAME = "ecdsa-sha2-nistp";
|
||||||
|
|
||||||
|
private final static Logger log = LoggerFactory.getLogger(ECDSAVariationsAdapter.class);
|
||||||
|
|
||||||
|
public final static Map<String, String> SUPPORTED_CURVES = new HashMap<String, String>();
|
||||||
|
public final static Map<String, String> NIST_CURVES_NAMES = new HashMap<String, String>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
NIST_CURVES_NAMES.put("256", "p-256");
|
||||||
|
NIST_CURVES_NAMES.put("384", "p-384");
|
||||||
|
NIST_CURVES_NAMES.put("521", "p-521");
|
||||||
|
|
||||||
|
SUPPORTED_CURVES.put("256", "nistp256");
|
||||||
|
SUPPORTED_CURVES.put("384", "nistp384");
|
||||||
|
SUPPORTED_CURVES.put("521", "nistp521");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PublicKey readPubKeyFromBuffer(Buffer<?> buf, String variation) throws GeneralSecurityException {
|
||||||
|
String algorithm = BASE_ALGORITHM_NAME + variation;
|
||||||
|
if (!SecurityUtils.isBouncyCastleRegistered()) {
|
||||||
|
throw new GeneralSecurityException("BouncyCastle is required to read a key of type " + algorithm);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// final String algo = buf.readString(); it has been already read
|
||||||
|
final String curveName = buf.readString();
|
||||||
|
final int keyLen = buf.readUInt32AsInt();
|
||||||
|
final byte x04 = buf.readByte(); // it must be 0x04, but don't think
|
||||||
|
// we need that check
|
||||||
|
final byte[] x = new byte[(keyLen - 1) / 2];
|
||||||
|
final byte[] y = new byte[(keyLen - 1) / 2];
|
||||||
|
buf.readRawBytes(x);
|
||||||
|
buf.readRawBytes(y);
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug(String.format("Key algo: %s, Key curve: %s, Key Len: %s, 0x04: %s\nx: %s\ny: %s",
|
||||||
|
algorithm, curveName, keyLen, x04, Arrays.toString(x), Arrays.toString(y)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SUPPORTED_CURVES.values().contains(curveName)) {
|
||||||
|
throw new GeneralSecurityException(String.format("Unknown curve %s", curveName));
|
||||||
|
}
|
||||||
|
|
||||||
|
BigInteger bigX = new BigInteger(1, x);
|
||||||
|
BigInteger bigY = new BigInteger(1, y);
|
||||||
|
|
||||||
|
X9ECParameters ecParams = NISTNamedCurves.getByName(NIST_CURVES_NAMES.get(variation));
|
||||||
|
ECPoint pPublicPoint = ecParams.getCurve().createPoint(bigX, bigY);
|
||||||
|
ECParameterSpec spec = new ECParameterSpec(ecParams.getCurve(), ecParams.getG(), ecParams.getN());
|
||||||
|
ECPublicKeySpec publicSpec = new ECPublicKeySpec(pPublicPoint, spec);
|
||||||
|
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("ECDSA");
|
||||||
|
return keyFactory.generatePublic(publicSpec);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new GeneralSecurityException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf) {
|
||||||
|
final ECPublicKey ecdsa = (ECPublicKey) pk;
|
||||||
|
byte[] encoded = SecgUtils.getEncoded(ecdsa.getW(), ecdsa.getParams().getCurve());
|
||||||
|
|
||||||
|
buf.putString(Integer.toString(fieldSizeFromKey(ecdsa)))
|
||||||
|
.putBytes(encoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int fieldSizeFromKey(ECPublicKey ecPublicKey) {
|
||||||
|
return ecPublicKey.getParams().getCurve().getField().getFieldSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -35,15 +35,9 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.bouncycastle.asn1.nist.NISTNamedCurves;
|
|
||||||
import org.bouncycastle.asn1.x9.X9ECParameters;
|
|
||||||
import org.bouncycastle.jce.spec.ECParameterSpec;
|
|
||||||
import org.bouncycastle.jce.spec.ECPublicKeySpec;
|
|
||||||
import org.bouncycastle.math.ec.ECPoint;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.hierynomus.sshj.secg.SecgUtils;
|
|
||||||
import com.hierynomus.sshj.signature.Ed25519PublicKey;
|
import com.hierynomus.sshj.signature.Ed25519PublicKey;
|
||||||
import com.hierynomus.sshj.userauth.certificate.Certificate;
|
import com.hierynomus.sshj.userauth.certificate.Certificate;
|
||||||
|
|
||||||
@@ -121,133 +115,43 @@ public enum KeyType {
|
|||||||
|
|
||||||
/** SSH identifier for ECDSA-256 keys */
|
/** SSH identifier for ECDSA-256 keys */
|
||||||
ECDSA256("ecdsa-sha2-nistp256") {
|
ECDSA256("ecdsa-sha2-nistp256") {
|
||||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
|
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
|
||||||
throws GeneralSecurityException {
|
throws GeneralSecurityException {
|
||||||
if (!SecurityUtils.isBouncyCastleRegistered()) {
|
return ECDSAVariationsAdapter.readPubKeyFromBuffer(buf, "256");
|
||||||
throw new GeneralSecurityException("BouncyCastle is required to read a key of type " + sType);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
// final String algo = buf.readString(); it has been already read
|
|
||||||
final String curveName = buf.readString();
|
|
||||||
final int keyLen = buf.readUInt32AsInt();
|
|
||||||
final byte x04 = buf.readByte(); // it must be 0x04, but don't think we need that check
|
|
||||||
final byte[] x = new byte[(keyLen - 1) / 2];
|
|
||||||
final byte[] y = new byte[(keyLen - 1) / 2];
|
|
||||||
buf.readRawBytes(x);
|
|
||||||
buf.readRawBytes(y);
|
|
||||||
if(log.isDebugEnabled()) {
|
|
||||||
log.debug(String.format("Key algo: %s, Key curve: %s, Key Len: %s, 0x04: %s\nx: %s\ny: %s",
|
|
||||||
sType,
|
|
||||||
curveName,
|
|
||||||
keyLen,
|
|
||||||
x04,
|
|
||||||
Arrays.toString(x),
|
|
||||||
Arrays.toString(y))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!NISTP_CURVE_256.equals(curveName)) {
|
|
||||||
throw new GeneralSecurityException(String.format("Unknown curve %s", curveName));
|
|
||||||
}
|
|
||||||
|
|
||||||
BigInteger bigX = new BigInteger(1, x);
|
|
||||||
BigInteger bigY = new BigInteger(1, y);
|
|
||||||
|
|
||||||
X9ECParameters ecParams = NISTNamedCurves.getByName("p-256");
|
|
||||||
ECPoint pPublicPoint = ecParams.getCurve().createPoint(bigX, bigY);
|
|
||||||
ECParameterSpec spec = new ECParameterSpec(ecParams.getCurve(),
|
|
||||||
ecParams.getG(), ecParams.getN());
|
|
||||||
ECPublicKeySpec publicSpec = new ECPublicKeySpec(pPublicPoint, spec);
|
|
||||||
|
|
||||||
KeyFactory keyFactory = KeyFactory.getInstance("ECDSA");
|
|
||||||
return keyFactory.generatePublic(publicSpec);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new GeneralSecurityException(ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf) {
|
protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf) {
|
||||||
final ECPublicKey ecdsa = (ECPublicKey) pk;
|
ECDSAVariationsAdapter.writePubKeyContentsIntoBuffer(pk, buf);
|
||||||
byte[] encoded = SecgUtils.getEncoded(ecdsa.getW(), ecdsa.getParams().getCurve());
|
|
||||||
|
|
||||||
buf.putString(NISTP_CURVE_256)
|
|
||||||
.putBytes(encoded);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isMyType(Key key) {
|
protected boolean isMyType(Key key) {
|
||||||
return ("ECDSA".equals(key.getAlgorithm()) && ((ECPublicKey) key).getParams().getCurve().getField().getFieldSize() == 256);
|
return ("ECDSA".equals(key.getAlgorithm()) && ECDSAVariationsAdapter.fieldSizeFromKey((ECPublicKey) key) == 256);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/** SSH identifier for ECDSA-384 keys */
|
/** SSH identifier for ECDSA-384 keys */
|
||||||
ECDSA384("ecdsa-sha2-nistp384") {
|
ECDSA384("ecdsa-sha2-nistp384") {
|
||||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
|
||||||
|
@Override
|
||||||
@Override
|
|
||||||
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
|
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
|
||||||
throws GeneralSecurityException {
|
throws GeneralSecurityException {
|
||||||
if (!SecurityUtils.isBouncyCastleRegistered()) {
|
return ECDSAVariationsAdapter.readPubKeyFromBuffer(buf, "384");
|
||||||
throw new GeneralSecurityException("BouncyCastle is required to read a key of type " + sType);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
// final String algo = buf.readString(); it has been already read
|
|
||||||
final String curveName = buf.readString();
|
|
||||||
final int keyLen = buf.readUInt32AsInt();
|
|
||||||
final byte x04 = buf.readByte(); // it must be 0x04, but don't think we need that check
|
|
||||||
final byte[] x = new byte[(keyLen - 1) / 2];
|
|
||||||
final byte[] y = new byte[(keyLen - 1) / 2];
|
|
||||||
buf.readRawBytes(x);
|
|
||||||
buf.readRawBytes(y);
|
|
||||||
if(log.isDebugEnabled()) {
|
|
||||||
log.debug(String.format("Key algo: %s, Key curve: %s, Key Len: %s, 0x04: %s\nx: %s\ny: %s",
|
|
||||||
sType,
|
|
||||||
curveName,
|
|
||||||
keyLen,
|
|
||||||
x04,
|
|
||||||
Arrays.toString(x),
|
|
||||||
Arrays.toString(y))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!NISTP_CURVE_384.equals(curveName)) {
|
|
||||||
throw new GeneralSecurityException(String.format("Unknown curve %s", curveName));
|
|
||||||
}
|
|
||||||
|
|
||||||
BigInteger bigX = new BigInteger(1, x);
|
|
||||||
BigInteger bigY = new BigInteger(1, y);
|
|
||||||
|
|
||||||
X9ECParameters ecParams = NISTNamedCurves.getByName("p-384");
|
|
||||||
ECPoint pPublicPoint = ecParams.getCurve().createPoint(bigX, bigY);
|
|
||||||
ECParameterSpec spec = new ECParameterSpec(ecParams.getCurve(),
|
|
||||||
ecParams.getG(), ecParams.getN());
|
|
||||||
ECPublicKeySpec publicSpec = new ECPublicKeySpec(pPublicPoint, spec);
|
|
||||||
|
|
||||||
KeyFactory keyFactory = KeyFactory.getInstance("ECDSA");
|
|
||||||
return keyFactory.generatePublic(publicSpec);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new GeneralSecurityException(ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf) {
|
protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer<?> buf) {
|
||||||
final ECPublicKey ecdsa = (ECPublicKey) pk;
|
ECDSAVariationsAdapter.writePubKeyContentsIntoBuffer(pk, buf);
|
||||||
byte[] encoded = SecgUtils.getEncoded(ecdsa.getW(), ecdsa.getParams().getCurve());
|
|
||||||
|
|
||||||
buf.putString(NISTP_CURVE_384)
|
|
||||||
.putBytes(encoded);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isMyType(Key key) {
|
protected boolean isMyType(Key key) {
|
||||||
return ("ECDSA".equals(key.getAlgorithm()) && ((ECPublicKey) key).getParams().getCurve().getField().getFieldSize() == 384);
|
return ("ECDSA".equals(key.getAlgorithm()) && ECDSAVariationsAdapter.fieldSizeFromKey((ECPublicKey) key) == 384);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -350,10 +254,8 @@ public enum KeyType {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static String NISTP_CURVE_256 = "qqq";
|
||||||
private static final String NISTP_CURVE_256 = "nistp256";
|
private static String NISTP_CURVE_384 = "qqq";
|
||||||
private static final String NISTP_CURVE_384 = "nistp384";
|
|
||||||
|
|
||||||
protected final String sType;
|
protected final String sType;
|
||||||
|
|
||||||
private KeyType(String type) {
|
private KeyType(String type) {
|
||||||
|
|||||||
@@ -15,24 +15,24 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.signature;
|
package net.schmizz.sshj.signature;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.security.SignatureException;
|
|
||||||
|
|
||||||
/** ECDSA {@link Signature} */
|
/** ECDSA {@link Signature} */
|
||||||
public class SignatureECDSA
|
public class SignatureECDSA
|
||||||
extends AbstractSignature {
|
extends AbstractSignature {
|
||||||
|
|
||||||
/** A named factory for ECDSA signature */
|
/** A named factory for ECDSA-256 signature */
|
||||||
public static class Factory
|
public static class Factory256
|
||||||
implements net.schmizz.sshj.common.Factory.Named<Signature> {
|
implements net.schmizz.sshj.common.Factory.Named<Signature> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Signature create() {
|
public Signature create() {
|
||||||
return new SignatureECDSA();
|
return new SignatureECDSA("SHA256withECDSA", KeyType.ECDSA256.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -42,10 +42,29 @@ public class SignatureECDSA
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SignatureECDSA() {
|
/** A named factory for ECDSA-384 signature */
|
||||||
super("SHA256withECDSA");
|
public static class Factory384
|
||||||
|
implements net.schmizz.sshj.common.Factory.Named<Signature> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Signature create() {
|
||||||
|
return new SignatureECDSA("SHA384withECDSA", KeyType.ECDSA384.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return KeyType.ECDSA384.toString();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String keyTypeName;
|
||||||
|
|
||||||
|
public SignatureECDSA(String algorithm, String keyTypeName) {
|
||||||
|
super(algorithm);
|
||||||
|
this.keyTypeName = keyTypeName;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] encode(byte[] sig) {
|
public byte[] encode(byte[] sig) {
|
||||||
int rIndex = 3;
|
int rIndex = 3;
|
||||||
@@ -75,8 +94,8 @@ public class SignatureECDSA
|
|||||||
try {
|
try {
|
||||||
Buffer sigbuf = new Buffer.PlainBuffer(sig);
|
Buffer sigbuf = new Buffer.PlainBuffer(sig);
|
||||||
final String algo = new String(sigbuf.readBytes());
|
final String algo = new String(sigbuf.readBytes());
|
||||||
if (!"ecdsa-sha2-nistp256".equals(algo)) {
|
if (!keyTypeName.equals(algo)) {
|
||||||
throw new SSHRuntimeException(String.format("Signature :: ecdsa-sha2-nistp256 expected, got %s", algo));
|
throw new SSHRuntimeException(String.format("Signature :: " + keyTypeName + " expected, got %s", algo));
|
||||||
}
|
}
|
||||||
final int rsLen = sigbuf.readUInt32AsInt();
|
final int rsLen = sigbuf.readUInt32AsInt();
|
||||||
if (sigbuf.available() != rsLen) {
|
if (sigbuf.available() != rsLen) {
|
||||||
|
|||||||
@@ -1,137 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C)2009 - SSHJ Contributors
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.schmizz.sshj.signature;
|
|
||||||
|
|
||||||
import net.schmizz.sshj.common.Buffer;
|
|
||||||
import net.schmizz.sshj.common.KeyType;
|
|
||||||
import net.schmizz.sshj.common.SSHRuntimeException;
|
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.security.SignatureException;
|
|
||||||
|
|
||||||
/** ECDSA {@link Signature} */
|
|
||||||
public class SignatureECDSA384
|
|
||||||
extends AbstractSignature {
|
|
||||||
|
|
||||||
/** A named factory for ECDSA signature */
|
|
||||||
public static class Factory
|
|
||||||
implements net.schmizz.sshj.common.Factory.Named<Signature> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Signature create() {
|
|
||||||
return new SignatureECDSA384();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return KeyType.ECDSA384.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public SignatureECDSA384() {
|
|
||||||
super("SHA384withECDSA");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] encode(byte[] sig) {
|
|
||||||
int rIndex = 3;
|
|
||||||
int rLen = sig[rIndex++] & 0xff;
|
|
||||||
byte[] r = new byte[rLen];
|
|
||||||
System.arraycopy(sig, rIndex, r, 0, r.length);
|
|
||||||
|
|
||||||
int sIndex = rIndex + rLen + 1;
|
|
||||||
int sLen = sig[sIndex++] & 0xff;
|
|
||||||
byte[] s = new byte[sLen];
|
|
||||||
System.arraycopy(sig, sIndex, s, 0, s.length);
|
|
||||||
|
|
||||||
System.arraycopy(sig, 4, r, 0, rLen);
|
|
||||||
System.arraycopy(sig, 6 + rLen, s, 0, sLen);
|
|
||||||
|
|
||||||
Buffer buf = new Buffer.PlainBuffer();
|
|
||||||
buf.putMPInt(new BigInteger(r));
|
|
||||||
buf.putMPInt(new BigInteger(s));
|
|
||||||
|
|
||||||
return buf.getCompactData();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean verify(byte[] sig) {
|
|
||||||
byte[] r;
|
|
||||||
byte[] s;
|
|
||||||
try {
|
|
||||||
Buffer sigbuf = new Buffer.PlainBuffer(sig);
|
|
||||||
final String algo = new String(sigbuf.readBytes());
|
|
||||||
if (!"ecdsa-sha2-nistp384".equals(algo)) {
|
|
||||||
throw new SSHRuntimeException(String.format("Signature :: ecdsa-sha2-nistp384 expected, got %s", algo));
|
|
||||||
}
|
|
||||||
final int rsLen = sigbuf.readUInt32AsInt();
|
|
||||||
if (sigbuf.available() != rsLen) {
|
|
||||||
throw new SSHRuntimeException("Invalid key length");
|
|
||||||
}
|
|
||||||
r = sigbuf.readBytes();
|
|
||||||
s = sigbuf.readBytes();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new SSHRuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rLen = r.length;
|
|
||||||
int sLen = s.length;
|
|
||||||
|
|
||||||
/* We can't have the high bit set, so add an extra zero at the beginning if so. */
|
|
||||||
if ((r[0] & 0x80) != 0) {
|
|
||||||
rLen++;
|
|
||||||
}
|
|
||||||
if ((s[0] & 0x80) != 0) {
|
|
||||||
sLen++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate total output length */
|
|
||||||
int length = 6 + rLen + sLen;
|
|
||||||
byte[] asn1 = new byte[length];
|
|
||||||
|
|
||||||
/* ASN.1 SEQUENCE tag */
|
|
||||||
asn1[0] = (byte) 0x30;
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user