From 9a6516f640b293984b9ada7860b28a8c9212a129 Mon Sep 17 00:00:00 2001 From: Iger Date: Fri, 23 Jun 2017 19:33:51 +0300 Subject: [PATCH 01/12] - A separate enum members take with lots of code duplication --- .../java/net/schmizz/sshj/common/KeyType.java | 79 +++++++++- .../sshj/signature/SignatureECDSA.java | 2 +- .../sshj/signature/SignatureECDSA384.java | 137 ++++++++++++++++++ 3 files changed, 211 insertions(+), 7 deletions(-) create mode 100644 src/main/java/net/schmizz/sshj/signature/SignatureECDSA384.java diff --git a/src/main/java/net/schmizz/sshj/common/KeyType.java b/src/main/java/net/schmizz/sshj/common/KeyType.java index 9d2ea94df..c93d3ea72 100644 --- a/src/main/java/net/schmizz/sshj/common/KeyType.java +++ b/src/main/java/net/schmizz/sshj/common/KeyType.java @@ -119,8 +119,8 @@ protected boolean isMyType(Key key) { }, - /** SSH identifier for ECDSA keys */ - ECDSA("ecdsa-sha2-nistp256") { + /** SSH identifier for ECDSA-256 keys */ + ECDSA256("ecdsa-sha2-nistp256") { private final Logger log = LoggerFactory.getLogger(getClass()); @Override @@ -149,7 +149,7 @@ public PublicKey readPubKeyFromBuffer(Buffer buf) ); } - if (!NISTP_CURVE.equals(curveName)) { + if (!NISTP_CURVE_256.equals(curveName)) { throw new GeneralSecurityException(String.format("Unknown curve %s", curveName)); } @@ -175,16 +175,82 @@ protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer buf) { final ECPublicKey ecdsa = (ECPublicKey) pk; byte[] encoded = SecgUtils.getEncoded(ecdsa.getW(), ecdsa.getParams().getCurve()); - buf.putString(NISTP_CURVE) + buf.putString(NISTP_CURVE_256) .putBytes(encoded); } @Override protected boolean isMyType(Key key) { - return ("ECDSA".equals(key.getAlgorithm())); + return ("ECDSA".equals(key.getAlgorithm()) && ((ECPublicKey) key).getParams().getCurve().getField().getFieldSize() == 256); } }, + /** SSH identifier for ECDSA-384 keys */ + ECDSA384("ecdsa-sha2-nistp384") { + private final Logger log = LoggerFactory.getLogger(getClass()); + + @Override + public PublicKey readPubKeyFromBuffer(Buffer buf) + throws GeneralSecurityException { + if (!SecurityUtils.isBouncyCastleRegistered()) { + 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 + protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer buf) { + final ECPublicKey ecdsa = (ECPublicKey) pk; + byte[] encoded = SecgUtils.getEncoded(ecdsa.getW(), ecdsa.getParams().getCurve()); + + buf.putString(NISTP_CURVE_384) + .putBytes(encoded); + } + + @Override + protected boolean isMyType(Key key) { + return ("ECDSA".equals(key.getAlgorithm()) && ((ECPublicKey) key).getParams().getCurve().getField().getFieldSize() == 384); + } + }, + ED25519("ssh-ed25519") { private final Logger log = LoggerFactory.getLogger(KeyType.class); @Override @@ -285,7 +351,8 @@ protected boolean isMyType(Key key) { }; - private static final String NISTP_CURVE = "nistp256"; + private static final String NISTP_CURVE_256 = "nistp256"; + private static final String NISTP_CURVE_384 = "nistp384"; protected final String sType; diff --git a/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java b/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java index 93e228a61..32273285f 100644 --- a/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java +++ b/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java @@ -37,7 +37,7 @@ public Signature create() { @Override public String getName() { - return KeyType.ECDSA.toString(); + return KeyType.ECDSA256.toString(); } } diff --git a/src/main/java/net/schmizz/sshj/signature/SignatureECDSA384.java b/src/main/java/net/schmizz/sshj/signature/SignatureECDSA384.java new file mode 100644 index 000000000..33fcdc54a --- /dev/null +++ b/src/main/java/net/schmizz/sshj/signature/SignatureECDSA384.java @@ -0,0 +1,137 @@ +/* + * 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 { + + @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); + } + } +} From e8a954e1f5575e595b8265f5609cf8e51e55cc41 Mon Sep 17 00:00:00 2001 From: Iger Date: Sat, 24 Jun 2017 17:33:54 +0300 Subject: [PATCH 02/12] - Pretty honed up implementation of -384 --- .../java/net/schmizz/sshj/DefaultConfig.java | 40 +++-- .../sshj/common/ECDSAVariationsAdapter.java | 92 ++++++++++++ .../java/net/schmizz/sshj/common/KeyType.java | 118 ++------------- .../sshj/signature/SignatureECDSA.java | 39 +++-- .../sshj/signature/SignatureECDSA384.java | 137 ------------------ 5 files changed, 160 insertions(+), 266 deletions(-) create mode 100644 src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java delete mode 100644 src/main/java/net/schmizz/sshj/signature/SignatureECDSA384.java diff --git a/src/main/java/net/schmizz/sshj/DefaultConfig.java b/src/main/java/net/schmizz/sshj/DefaultConfig.java index 4a264d11c..86d6fc074 100644 --- a/src/main/java/net/schmizz/sshj/DefaultConfig.java +++ b/src/main/java/net/schmizz/sshj/DefaultConfig.java @@ -15,12 +15,22 @@ */ 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.transport.cipher.BlockCiphers; import com.hierynomus.sshj.transport.cipher.StreamCiphers; import com.hierynomus.sshj.transport.kex.DHGroups; import com.hierynomus.sshj.transport.kex.ExtendedDHGroups; import com.hierynomus.sshj.userauth.keyprovider.OpenSSHKeyV1KeyFile; + import net.schmizz.keepalive.KeepAliveProvider; import net.schmizz.sshj.common.Factory; import net.schmizz.sshj.common.LoggerFactory; @@ -28,13 +38,24 @@ import net.schmizz.sshj.signature.SignatureDSA; import net.schmizz.sshj.signature.SignatureECDSA; 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.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.*; +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.JCERandom; import net.schmizz.sshj.transport.random.SingletonRandomFactory; @@ -42,10 +63,6 @@ import net.schmizz.sshj.userauth.keyprovider.PKCS5KeyFile; import net.schmizz.sshj.userauth.keyprovider.PKCS8KeyFile; 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 @@ -108,8 +125,8 @@ public void setLoggerFactory(LoggerFactory loggerFactory) { 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(), @@ -210,7 +227,8 @@ protected void initCipherFactories() { protected void initSignatureFactories() { setSignatureFactories( - new SignatureECDSA.Factory(), + new SignatureECDSA.Factory256(), + new SignatureECDSA.Factory384(), new SignatureRSA.Factory(), new SignatureDSA.Factory(), new SignatureEdDSA.Factory() diff --git a/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java b/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java new file mode 100644 index 000000000..f492f1ac5 --- /dev/null +++ b/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java @@ -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 SUPPORTED_CURVES = new HashMap(); + public final static Map NIST_CURVES_NAMES = new HashMap(); + + 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(); + } + +} diff --git a/src/main/java/net/schmizz/sshj/common/KeyType.java b/src/main/java/net/schmizz/sshj/common/KeyType.java index c93d3ea72..20ab87ed8 100644 --- a/src/main/java/net/schmizz/sshj/common/KeyType.java +++ b/src/main/java/net/schmizz/sshj/common/KeyType.java @@ -35,15 +35,9 @@ import java.util.List; 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; import com.hierynomus.sshj.signature.Ed25519PublicKey; import com.hierynomus.sshj.userauth.certificate.Certificate; @@ -121,133 +115,43 @@ protected boolean isMyType(Key key) { /** SSH identifier for ECDSA-256 keys */ ECDSA256("ecdsa-sha2-nistp256") { - private final Logger log = LoggerFactory.getLogger(getClass()); @Override public PublicKey readPubKeyFromBuffer(Buffer buf) throws GeneralSecurityException { - if (!SecurityUtils.isBouncyCastleRegistered()) { - 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); - } + return ECDSAVariationsAdapter.readPubKeyFromBuffer(buf, "256"); } @Override protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer buf) { - final ECPublicKey ecdsa = (ECPublicKey) pk; - byte[] encoded = SecgUtils.getEncoded(ecdsa.getW(), ecdsa.getParams().getCurve()); - - buf.putString(NISTP_CURVE_256) - .putBytes(encoded); + ECDSAVariationsAdapter.writePubKeyContentsIntoBuffer(pk, buf); } @Override 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 */ ECDSA384("ecdsa-sha2-nistp384") { - private final Logger log = LoggerFactory.getLogger(getClass()); - - @Override + + @Override public PublicKey readPubKeyFromBuffer(Buffer buf) throws GeneralSecurityException { - if (!SecurityUtils.isBouncyCastleRegistered()) { - 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); - } + return ECDSAVariationsAdapter.readPubKeyFromBuffer(buf, "384"); } @Override protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer buf) { - final ECPublicKey ecdsa = (ECPublicKey) pk; - byte[] encoded = SecgUtils.getEncoded(ecdsa.getW(), ecdsa.getParams().getCurve()); - - buf.putString(NISTP_CURVE_384) - .putBytes(encoded); + ECDSAVariationsAdapter.writePubKeyContentsIntoBuffer(pk, buf); } @Override 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 @@ protected boolean isMyType(Key key) { } }; - - private static final String NISTP_CURVE_256 = "nistp256"; - private static final String NISTP_CURVE_384 = "nistp384"; - + private static String NISTP_CURVE_256 = "qqq"; + private static String NISTP_CURVE_384 = "qqq"; protected final String sType; private KeyType(String type) { diff --git a/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java b/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java index 32273285f..182645075 100644 --- a/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java +++ b/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java @@ -15,24 +15,24 @@ */ package net.schmizz.sshj.signature; +import java.math.BigInteger; +import java.security.SignatureException; + 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 SignatureECDSA extends AbstractSignature { - /** A named factory for ECDSA signature */ - public static class Factory + /** A named factory for ECDSA-256 signature */ + public static class Factory256 implements net.schmizz.sshj.common.Factory.Named { @Override public Signature create() { - return new SignatureECDSA(); + return new SignatureECDSA("SHA256withECDSA", KeyType.ECDSA256.toString()); } @Override @@ -42,10 +42,29 @@ public String getName() { } - public SignatureECDSA() { - super("SHA256withECDSA"); + /** A named factory for ECDSA-384 signature */ + public static class Factory384 + implements net.schmizz.sshj.common.Factory.Named { + + @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 public byte[] encode(byte[] sig) { int rIndex = 3; @@ -75,8 +94,8 @@ public boolean verify(byte[] sig) { try { Buffer sigbuf = new Buffer.PlainBuffer(sig); final String algo = new String(sigbuf.readBytes()); - if (!"ecdsa-sha2-nistp256".equals(algo)) { - throw new SSHRuntimeException(String.format("Signature :: ecdsa-sha2-nistp256 expected, got %s", algo)); + if (!keyTypeName.equals(algo)) { + throw new SSHRuntimeException(String.format("Signature :: " + keyTypeName + " expected, got %s", algo)); } final int rsLen = sigbuf.readUInt32AsInt(); if (sigbuf.available() != rsLen) { diff --git a/src/main/java/net/schmizz/sshj/signature/SignatureECDSA384.java b/src/main/java/net/schmizz/sshj/signature/SignatureECDSA384.java deleted file mode 100644 index 33fcdc54a..000000000 --- a/src/main/java/net/schmizz/sshj/signature/SignatureECDSA384.java +++ /dev/null @@ -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 { - - @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); - } - } -} From f7bc5eec4c2e525ac3004cc1e5ebf22a44084ecb Mon Sep 17 00:00:00 2001 From: Iger Date: Sun, 25 Jun 2017 11:16:12 +0300 Subject: [PATCH 03/12] - 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 | 77 +++++++++++-------- 3 files changed, 71 insertions(+), 34 deletions(-) diff --git a/src/main/java/net/schmizz/sshj/DefaultConfig.java b/src/main/java/net/schmizz/sshj/DefaultConfig.java index 86d6fc074..256b4e317 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.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 void setLoggerFactory(LoggerFactory loggerFactory) { 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 @@ protected void initSignatureFactories() { 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 20ab87ed8..ce16e7422 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 @@ protected boolean isMyType(Key key) { 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 182645075..605d49e58 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 String getName() { } + /** 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 boolean verify(byte[] sig) { 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 boolean verify(byte[] sig) { /* 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); - } + + ASN1EncodableVector vector = new ASN1EncodableVector(); + vector.add(new ASN1Integer(r)); + vector.add(new ASN1Integer(s)); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(length); + ASN1OutputStream asnOS = new ASN1OutputStream(baos); + + asnOS.writeObject(new DERSequence(vector)); + asnOS.flush(); + + return baos.toByteArray(); } } From d0a0480881e4897bb78fe57f4c79b064ef6cc89a Mon Sep 17 00:00:00 2001 From: Iger Date: Sun, 25 Jun 2017 11:26:23 +0300 Subject: [PATCH 04/12] - cleanup --- src/main/java/net/schmizz/sshj/common/KeyType.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/net/schmizz/sshj/common/KeyType.java b/src/main/java/net/schmizz/sshj/common/KeyType.java index ce16e7422..4ab634f1d 100644 --- a/src/main/java/net/schmizz/sshj/common/KeyType.java +++ b/src/main/java/net/schmizz/sshj/common/KeyType.java @@ -275,8 +275,6 @@ protected boolean isMyType(Key key) { } }; - private static String NISTP_CURVE_256 = "qqq"; - private static String NISTP_CURVE_384 = "qqq"; protected final String sType; private KeyType(String type) { From 43c914f756c44fd9550575e627413049be231a11 Mon Sep 17 00:00:00 2001 From: Iger Date: Sun, 25 Jun 2017 11:40:19 +0300 Subject: [PATCH 05/12] - Ident in spaces --- .../sshj/common/ECDSAVariationsAdapter.java | 120 +++++++++--------- .../java/net/schmizz/sshj/common/KeyType.java | 2 +- .../sshj/signature/SignatureECDSA.java | 51 ++++---- 3 files changed, 86 insertions(+), 87 deletions(-) diff --git a/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java b/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java index f492f1ac5..656843cc0 100644 --- a/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java +++ b/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java @@ -21,72 +21,72 @@ 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 SUPPORTED_CURVES = new HashMap(); - public final static Map NIST_CURVES_NAMES = new HashMap(); - - 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); - } - } + private final static String BASE_ALGORITHM_NAME = "ecdsa-sha2-nistp"; + + private final static Logger log = LoggerFactory.getLogger(ECDSAVariationsAdapter.class); + + public final static Map SUPPORTED_CURVES = new HashMap(); + public final static Map NIST_CURVES_NAMES = new HashMap(); + + 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); + .putBytes(encoded); } - public static int fieldSizeFromKey(ECPublicKey ecPublicKey) { - return ecPublicKey.getParams().getCurve().getField().getFieldSize(); - } + public static int fieldSizeFromKey(ECPublicKey ecPublicKey) { + return ecPublicKey.getParams().getCurve().getField().getFieldSize(); + } } diff --git a/src/main/java/net/schmizz/sshj/common/KeyType.java b/src/main/java/net/schmizz/sshj/common/KeyType.java index 4ab634f1d..5f8cecbfb 100644 --- a/src/main/java/net/schmizz/sshj/common/KeyType.java +++ b/src/main/java/net/schmizz/sshj/common/KeyType.java @@ -372,7 +372,7 @@ static Certificate toCertificate(PublicKey key) { } return ((Certificate) key); } - + private static Date dateFromEpoch(long seconds) { return new Date(seconds * 1000); } diff --git a/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java b/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java index 605d49e58..7125173f4 100644 --- a/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java +++ b/src/main/java/net/schmizz/sshj/signature/SignatureECDSA.java @@ -30,12 +30,10 @@ import net.schmizz.sshj.common.SSHRuntimeException; /** ECDSA {@link Signature} */ -public class SignatureECDSA - extends AbstractSignature { +public class SignatureECDSA extends AbstractSignature { /** A named factory for ECDSA-256 signature */ - public static class Factory256 - implements net.schmizz.sshj.common.Factory.Named { + public static class Factory256 implements net.schmizz.sshj.common.Factory.Named { @Override public Signature create() { @@ -50,8 +48,7 @@ public String getName() { } /** A named factory for ECDSA-384 signature */ - public static class Factory384 - implements net.schmizz.sshj.common.Factory.Named { + public static class Factory384 implements net.schmizz.sshj.common.Factory.Named { @Override public Signature create() { @@ -66,8 +63,7 @@ public String getName() { } /** A named factory for ECDSA-521 signature */ - public static class Factory521 - implements net.schmizz.sshj.common.Factory.Named { + public static class Factory521 implements net.schmizz.sshj.common.Factory.Named { @Override public Signature create() { @@ -80,14 +76,14 @@ public String getName() { } } - - private String keyTypeName; + + private String keyTypeName; public SignatureECDSA(String algorithm, String keyTypeName) { super(algorithm); this.keyTypeName = keyTypeName; } - + @Override public byte[] encode(byte[] sig) { int rIndex = 3; @@ -135,15 +131,18 @@ public boolean verify(byte[] sig) { } catch (SignatureException e) { throw new SSHRuntimeException(e); } catch (IOException e) { - throw new SSHRuntimeException(e); + throw new SSHRuntimeException(e); } } - + private byte[] asnEncode(byte[] r, byte[] s) throws IOException { 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. */ + /* + * We can't have the high bit set, so add an extra zero at the beginning + * if so. + */ if ((r[0] & 0x80) != 0) { rLen++; } @@ -153,17 +152,17 @@ private byte[] asnEncode(byte[] r, byte[] s) throws IOException { /* Calculate total output length */ int length = 6 + rLen + sLen; - - ASN1EncodableVector vector = new ASN1EncodableVector(); - vector.add(new ASN1Integer(r)); - vector.add(new ASN1Integer(s)); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(length); - ASN1OutputStream asnOS = new ASN1OutputStream(baos); - - asnOS.writeObject(new DERSequence(vector)); - asnOS.flush(); - - return baos.toByteArray(); + + ASN1EncodableVector vector = new ASN1EncodableVector(); + vector.add(new ASN1Integer(r)); + vector.add(new ASN1Integer(s)); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(length); + ASN1OutputStream asnOS = new ASN1OutputStream(baos); + + asnOS.writeObject(new DERSequence(vector)); + asnOS.flush(); + + return baos.toByteArray(); } } From 32cd5070448be4b4d3e69bab50305bab11088032 Mon Sep 17 00:00:00 2001 From: Iger Date: Sun, 25 Jun 2017 11:49:05 +0300 Subject: [PATCH 06/12] - Some more indentation fixes --- .../sshj/common/ECDSAVariationsAdapter.java | 2 +- .../java/net/schmizz/sshj/common/KeyType.java | 50 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java b/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java index 656843cc0..b7959d7a3 100644 --- a/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java +++ b/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java @@ -82,7 +82,7 @@ public static void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer buf) { byte[] encoded = SecgUtils.getEncoded(ecdsa.getW(), ecdsa.getParams().getCurve()); buf.putString(Integer.toString(fieldSizeFromKey(ecdsa))) - .putBytes(encoded); + .putBytes(encoded); } public static int fieldSizeFromKey(ECPublicKey ecPublicKey) { diff --git a/src/main/java/net/schmizz/sshj/common/KeyType.java b/src/main/java/net/schmizz/sshj/common/KeyType.java index 5f8cecbfb..ba6251473 100644 --- a/src/main/java/net/schmizz/sshj/common/KeyType.java +++ b/src/main/java/net/schmizz/sshj/common/KeyType.java @@ -70,7 +70,7 @@ public PublicKey readPubKeyFromBuffer(Buffer buf) protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer buf) { final RSAPublicKey rsaKey = (RSAPublicKey) pk; buf.putMPInt(rsaKey.getPublicExponent()) // e - .putMPInt(rsaKey.getModulus()); // n + .putMPInt(rsaKey.getModulus()); // n } @Override @@ -101,9 +101,9 @@ public PublicKey readPubKeyFromBuffer(Buffer buf) protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer buf) { final DSAPublicKey dsaKey = (DSAPublicKey) pk; buf.putMPInt(dsaKey.getParams().getP()) // p - .putMPInt(dsaKey.getParams().getQ()) // q - .putMPInt(dsaKey.getParams().getG()) // g - .putMPInt(dsaKey.getY()); // y + .putMPInt(dsaKey.getParams().getQ()) // q + .putMPInt(dsaKey.getParams().getG()) // g + .putMPInt(dsaKey.getY()); // y } @Override @@ -119,7 +119,7 @@ protected boolean isMyType(Key key) { @Override public PublicKey readPubKeyFromBuffer(Buffer buf) throws GeneralSecurityException { - return ECDSAVariationsAdapter.readPubKeyFromBuffer(buf, "256"); + return ECDSAVariationsAdapter.readPubKeyFromBuffer(buf, "256"); } @@ -136,11 +136,11 @@ protected boolean isMyType(Key key) { /** SSH identifier for ECDSA-384 keys */ ECDSA384("ecdsa-sha2-nistp384") { - - @Override + + @Override public PublicKey readPubKeyFromBuffer(Buffer buf) throws GeneralSecurityException { - return ECDSAVariationsAdapter.readPubKeyFromBuffer(buf, "384"); + return ECDSAVariationsAdapter.readPubKeyFromBuffer(buf, "384"); } @@ -157,11 +157,11 @@ protected boolean isMyType(Key key) { /** SSH identifier for ECDSA-521 keys */ ECDSA521("ecdsa-sha2-nistp521") { - - @Override + + @Override public PublicKey readPubKeyFromBuffer(Buffer buf) throws GeneralSecurityException { - return ECDSAVariationsAdapter.readPubKeyFromBuffer(buf, "521"); + return ECDSAVariationsAdapter.readPubKeyFromBuffer(buf, "521"); } @@ -175,7 +175,7 @@ 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); @Override @@ -189,7 +189,7 @@ public PublicKey readPubKeyFromBuffer(Buffer buf) throws GeneralSecurityExcep sType, keyLen, Arrays.toString(p)) - ); + ); } EdDSANamedCurveSpec ed25519 = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512); @@ -343,16 +343,16 @@ static void writePubKeyContentsIntoBuffer(PublicKey publicKey, KeyType innerKeyT buf.putBytes(certificate.getNonce()); innerKeyType.writePubKeyContentsIntoBuffer(certificate.getKey(), buf); buf.putUInt64(certificate.getSerial()) - .putUInt32(certificate.getType()) - .putString(certificate.getId()) - .putBytes(packList(certificate.getValidPrincipals())) - .putUInt64(epochFromDate(certificate.getValidAfter())) - .putUInt64(epochFromDate(certificate.getValidBefore())) - .putBytes(packMap(certificate.getCritOptions())) - .putBytes(packMap(certificate.getExtensions())) - .putString("") // reserved - .putBytes(certificate.getSignatureKey()) - .putBytes(certificate.getSignature()); + .putUInt32(certificate.getType()) + .putString(certificate.getId()) + .putBytes(packList(certificate.getValidPrincipals())) + .putUInt64(epochFromDate(certificate.getValidAfter())) + .putUInt64(epochFromDate(certificate.getValidBefore())) + .putBytes(packMap(certificate.getCritOptions())) + .putBytes(packMap(certificate.getExtensions())) + .putString("") // reserved + .putBytes(certificate.getSignatureKey()) + .putBytes(certificate.getSignature()); } static boolean isCertificateOfType(Key key, KeyType innerKeyType) { @@ -368,11 +368,11 @@ static boolean isCertificateOfType(Key key, KeyType innerKeyType) { static Certificate toCertificate(PublicKey key) { if (!(key instanceof Certificate)) { throw new UnsupportedOperationException("Can't convert non-certificate key " + - key.getAlgorithm() + " to certificate"); + key.getAlgorithm() + " to certificate"); } return ((Certificate) key); } - + private static Date dateFromEpoch(long seconds) { return new Date(seconds * 1000); } From 7a97fcb3d9ec785a183f871ecfc582a6a955e998 Mon Sep 17 00:00:00 2001 From: Iger Date: Sun, 25 Jun 2017 11:57:08 +0300 Subject: [PATCH 07/12] - Some more indentation fixes --- .../java/net/schmizz/sshj/common/KeyType.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/java/net/schmizz/sshj/common/KeyType.java b/src/main/java/net/schmizz/sshj/common/KeyType.java index ba6251473..a54620f77 100644 --- a/src/main/java/net/schmizz/sshj/common/KeyType.java +++ b/src/main/java/net/schmizz/sshj/common/KeyType.java @@ -70,7 +70,7 @@ public PublicKey readPubKeyFromBuffer(Buffer buf) protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer buf) { final RSAPublicKey rsaKey = (RSAPublicKey) pk; buf.putMPInt(rsaKey.getPublicExponent()) // e - .putMPInt(rsaKey.getModulus()); // n + .putMPInt(rsaKey.getModulus()); // n } @Override @@ -101,9 +101,9 @@ public PublicKey readPubKeyFromBuffer(Buffer buf) protected void writePubKeyContentsIntoBuffer(PublicKey pk, Buffer buf) { final DSAPublicKey dsaKey = (DSAPublicKey) pk; buf.putMPInt(dsaKey.getParams().getP()) // p - .putMPInt(dsaKey.getParams().getQ()) // q - .putMPInt(dsaKey.getParams().getG()) // g - .putMPInt(dsaKey.getY()); // y + .putMPInt(dsaKey.getParams().getQ()) // q + .putMPInt(dsaKey.getParams().getG()) // g + .putMPInt(dsaKey.getY()); // y } @Override @@ -189,7 +189,7 @@ public PublicKey readPubKeyFromBuffer(Buffer buf) throws GeneralSecurityExcep sType, keyLen, Arrays.toString(p)) - ); + ); } EdDSANamedCurveSpec ed25519 = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512); @@ -343,16 +343,16 @@ static void writePubKeyContentsIntoBuffer(PublicKey publicKey, KeyType innerKeyT buf.putBytes(certificate.getNonce()); innerKeyType.writePubKeyContentsIntoBuffer(certificate.getKey(), buf); buf.putUInt64(certificate.getSerial()) - .putUInt32(certificate.getType()) - .putString(certificate.getId()) - .putBytes(packList(certificate.getValidPrincipals())) - .putUInt64(epochFromDate(certificate.getValidAfter())) - .putUInt64(epochFromDate(certificate.getValidBefore())) - .putBytes(packMap(certificate.getCritOptions())) - .putBytes(packMap(certificate.getExtensions())) - .putString("") // reserved - .putBytes(certificate.getSignatureKey()) - .putBytes(certificate.getSignature()); + .putUInt32(certificate.getType()) + .putString(certificate.getId()) + .putBytes(packList(certificate.getValidPrincipals())) + .putUInt64(epochFromDate(certificate.getValidAfter())) + .putUInt64(epochFromDate(certificate.getValidBefore())) + .putBytes(packMap(certificate.getCritOptions())) + .putBytes(packMap(certificate.getExtensions())) + .putString("") // reserved + .putBytes(certificate.getSignatureKey()) + .putBytes(certificate.getSignature()); } static boolean isCertificateOfType(Key key, KeyType innerKeyType) { From 8c26f309fa2dac5244e04746c24ec6555577c214 Mon Sep 17 00:00:00 2001 From: Iger Date: Sun, 25 Jun 2017 12:17:32 +0300 Subject: [PATCH 08/12] - license header --- .../sshj/common/ECDSAVariationsAdapter.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java b/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java index b7959d7a3..b83a6550b 100644 --- a/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java +++ b/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java @@ -1,3 +1,18 @@ +/* + * 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.common; import java.math.BigInteger; From b91443652a0efd117c769173e8f72f478ff25c36 Mon Sep 17 00:00:00 2001 From: Iger Date: Sun, 25 Jun 2017 12:54:51 +0300 Subject: [PATCH 09/12] - Incorrect key format during write --- .../java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java b/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java index b83a6550b..bf810fc72 100644 --- a/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java +++ b/src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java @@ -96,7 +96,7 @@ 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))) + buf.putString("nistp" + Integer.toString(fieldSizeFromKey(ecdsa))) .putBytes(encoded); } From 7c90f7814feb29a565f4b366a89689304c30dac9 Mon Sep 17 00:00:00 2001 From: Iger Date: Mon, 3 Jul 2017 22:01:39 +0300 Subject: [PATCH 10/12] - Test ECDSA fingerprints --- .../sshj/keyprovider/OpenSSHKeyFileTest.java | 22 ++++++++++++++++++- .../keytypes/test_ecdsa_nistp384.pub | 1 + .../keytypes/test_ecdsa_nistp521.pub | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/test/resources/keytypes/test_ecdsa_nistp384.pub create mode 100644 src/test/resources/keytypes/test_ecdsa_nistp521.pub diff --git a/src/test/java/net/schmizz/sshj/keyprovider/OpenSSHKeyFileTest.java b/src/test/java/net/schmizz/sshj/keyprovider/OpenSSHKeyFileTest.java index 67e06411a..18cb3dc66 100644 --- a/src/test/java/net/schmizz/sshj/keyprovider/OpenSSHKeyFileTest.java +++ b/src/test/java/net/schmizz/sshj/keyprovider/OpenSSHKeyFileTest.java @@ -146,7 +146,7 @@ public void fromString() } @Test - public void shouldHaveCorrectFingerprintForECDSA() throws IOException, GeneralSecurityException { + public void shouldHaveCorrectFingerprintForECDSA256() throws IOException, GeneralSecurityException { OpenSSHKeyFile keyFile = new OpenSSHKeyFile(); keyFile.init(new File("src/test/resources/keytypes/test_ecdsa_nistp256")); String expected = "256 MD5:53:ae:db:ed:8f:2d:02:d4:d5:6c:24:bc:a4:66:88:79 root@itgcpkerberosstack-cbgateway-0-20151117031915 (ECDSA)\n"; @@ -155,6 +155,26 @@ public void shouldHaveCorrectFingerprintForECDSA() throws IOException, GeneralSe assertThat(expected, containsString(sshjFingerprintSshjKey)); } + @Test + public void shouldHaveCorrectFingerprintForECDSA384() throws IOException, GeneralSecurityException { + OpenSSHKeyFile keyFile = new OpenSSHKeyFile(); + keyFile.init(new File("src/test/resources/keytypes/test_ecdsa_nistp384")); + String expected = "384 MD5:ee:9b:82:d1:47:01:16:1b:27:da:f5:27:fd:b2:eb:e2"; + PublicKey aPublic = keyFile.getPublic(); + String sshjFingerprintSshjKey = net.schmizz.sshj.common.SecurityUtils.getFingerprint(aPublic); + assertThat(expected, containsString(sshjFingerprintSshjKey)); + } + + @Test + public void shouldHaveCorrectFingerprintForECDSA521() throws IOException, GeneralSecurityException { + OpenSSHKeyFile keyFile = new OpenSSHKeyFile(); + keyFile.init(new File("src/test/resources/keytypes/test_ecdsa_nistp521")); + String expected = "521 MD5:22:e2:f4:3c:61:ae:e9:85:a1:4d:d9:6c:13:aa:eb:00"; + PublicKey aPublic = keyFile.getPublic(); + String sshjFingerprintSshjKey = net.schmizz.sshj.common.SecurityUtils.getFingerprint(aPublic); + assertThat(expected, containsString(sshjFingerprintSshjKey)); + } + @Test public void shouldHaveCorrectFingerprintForED25519() throws IOException { OpenSSHKeyV1KeyFile keyFile = new OpenSSHKeyV1KeyFile(); diff --git a/src/test/resources/keytypes/test_ecdsa_nistp384.pub b/src/test/resources/keytypes/test_ecdsa_nistp384.pub new file mode 100644 index 000000000..55e81bfc0 --- /dev/null +++ b/src/test/resources/keytypes/test_ecdsa_nistp384.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBGk0vVkVNYPm6YMwd8G+HtKSFQ6g5CiUPHhuOh7IJQbv521UQ+0A4t82XocxRL4OBkzNZoU76N5PzUDQ0xXWoIXl6w84oPRJ9nHs6iZkJquPLiQR4lkoEGh7Mgh6MdefXw== diff --git a/src/test/resources/keytypes/test_ecdsa_nistp521.pub b/src/test/resources/keytypes/test_ecdsa_nistp521.pub new file mode 100644 index 000000000..3a4a628cb --- /dev/null +++ b/src/test/resources/keytypes/test_ecdsa_nistp521.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAHIN0C3k19elYzS8He+vCmZvmaFuzv4akhLBzixbahNDJ+T4MRAtdAyzbyvS275seDct/m/6Ci2Oivm+8l94KfKkQBRJbc8RWuUczzDFgaAu+R65tuLeZaCF6Z/ScaPw2lEdFWN0Vp6bet/J7XGk0muhvXUqVWc/IXhfqJ/YAniRo/WHA== From 7a465597b6b7e9a699bd865fd69965f8c199bf0b Mon Sep 17 00:00:00 2001 From: Iger Date: Mon, 3 Jul 2017 22:02:01 +0300 Subject: [PATCH 11/12] - Test ECDSA signature verifications --- .../sshj/signature/VerificationTest.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/test/java/net/schmizz/sshj/signature/VerificationTest.java diff --git a/src/test/java/net/schmizz/sshj/signature/VerificationTest.java b/src/test/java/net/schmizz/sshj/signature/VerificationTest.java new file mode 100644 index 000000000..4008e7997 --- /dev/null +++ b/src/test/java/net/schmizz/sshj/signature/VerificationTest.java @@ -0,0 +1,67 @@ +package net.schmizz.sshj.signature; + +import java.security.PublicKey; + +import org.junit.Assert; +import org.junit.Test; + +import net.schmizz.sshj.common.Buffer; +import net.schmizz.sshj.common.Buffer.BufferException; + +public class VerificationTest { + + @Test + public void testECDSA256Verifies() throws BufferException { + byte[] K_S = fromString("0, 0, 0, 19, 101, 99, 100, 115, 97, 45, 115, 104, 97, 50, 45, 110, 105, 115, 116, 112, 50, 53, 54, 0, 0, 0, 8, 110, 105, 115, 116, 112, 50, 53, 54, 0, 0, 0, 65, 4, -8, 35, 96, -97, 65, -33, -128, -58, -64, -73, -51, 10, -28, 20, -59, 86, -88, -24, 126, 29, 115, 26, -88, 31, -115, 87, -109, -4, 61, 108, 28, 31, -66, 79, 107, 17, 24, 93, 114, -25, 121, 57, -58, 10, 26, -36, -100, -120, -7, -103, 86, 72, -109, -82, 111, 73, 4, -98, 58, 28, -3, -91, 28, 84"); + byte[] H = fromString("61, 55, -62, -122, -93, 82, -63, 25, -52, -13, -41, -29, 78, 101, 22, -75, 113, 59, -72, -92, -2, 39, -52, -89, 127, 80, -77, -82, 67, 3, -21, -53"); + byte[] sig = fromString("0, 0, 0, 19, 101, 99, 100, 115, 97, 45, 115, 104, 97, 50, 45, 110, 105, 115, 116, 112, 50, 53, 54, 0, 0, 0, 73, 0, 0, 0, 33, 0, -19, 50, -123, -35, 93, 50, 3, 40, -79, 110, -99, 6, -78, 40, -31, -26, -119, 113, -101, 109, -27, 12, 47, -119, -83, 107, -7, 116, 2, 97, 84, 32, 0, 0, 0, 32, 69, -44, 52, -119, 22, -60, -33, -105, -41, 45, 36, 112, -59, 49, -90, -110, -13, -114, 115, -86, 29, 30, 127, -44, 96, 57, -49, 39, -83, 50, -8, 123"); + + PublicKey hostKey = new Buffer.PlainBuffer(K_S).readPublicKey(); + + Signature signature = new SignatureECDSA.Factory256().create(); + signature.init(hostKey, null); + signature.update(H, 0, H.length); + + Assert.assertTrue("ECDSA256 signature verifies", signature.verify(sig)); + } + + @Test + public void testECDSA384Verifies() throws BufferException { + byte[] K_S = fromString("0, 0, 0, 19, 101, 99, 100, 115, 97, 45, 115, 104, 97, 50, 45, 110, 105, 115, 116, 112, 51, 56, 52, 0, 0, 0, 8, 110, 105, 115, 116, 112, 51, 56, 52, 0, 0, 0, 97, 4, 105, 52, -67, 89, 21, 53, -125, -26, -23, -125, 48, 119, -63, -66, 30, -46, -110, 21, 14, -96, -28, 40, -108, 60, 120, 110, 58, 30, -56, 37, 6, -17, -25, 109, 84, 67, -19, 0, -30, -33, 54, 94, -121, 49, 68, -66, 14, 6, 76, -51, 102, -123, 59, -24, -34, 79, -51, 64, -48, -45, 21, -42, -96, -123, -27, -21, 15, 56, -96, -12, 73, -10, 113, -20, -22, 38, 100, 38, -85, -113, 46, 36, 17, -30, 89, 40, 16, 104, 123, 50, 8, 122, 49, -41, -97, 95"); + byte[] H = fromString("-46, 22, -52, 62, -100, -43, -68, -88, 98, 31, 116, -77, 27, -92, 127, 25, -43, -63, -42, -106, -53, 26, -61, 69, -38, -73, 94, -70, -99, -6, -78, 61"); + byte[] sig = fromString("0, 0, 0, 19, 101, 99, 100, 115, 97, 45, 115, 104, 97, 50, 45, 110, 105, 115, 116, 112, 51, 56, 52, 0, 0, 0, 105, 0, 0, 0, 48, 58, -5, -53, 17, -127, -32, 74, 123, -84, -1, 80, 96, 49, -77, -109, 22, -90, 115, -111, 40, 2, 4, 56, 51, 92, -30, 39, -61, -92, -76, -105, 45, 52, -31, 116, 44, -32, -65, 57, 44, 26, 45, 59, -115, 95, 113, 114, -89, 0, 0, 0, 49, 0, -56, 65, 59, 111, -26, -72, 127, 47, -15, 14, -34, 56, 5, 34, 28, -78, -13, 26, -22, -41, -86, -36, -112, 10, 91, 48, -77, -84, 93, 111, -84, 59, 42, -128, -22, 91, -4, -31, -89, -37, 107, -27, 28, -119, -36, 93, 25, -49"); + + PublicKey hostKey = new Buffer.PlainBuffer(K_S).readPublicKey(); + + Signature signature = new SignatureECDSA.Factory384().create(); + signature.init(hostKey, null); + signature.update(H, 0, H.length); + + Assert.assertTrue("ECDSA384 signature verifies", signature.verify(sig)); + } + + @Test + public void testECDSA521Verifies() throws BufferException { + byte[] K_S = fromString("0, 0, 0, 19, 101, 99, 100, 115, 97, 45, 115, 104, 97, 50, 45, 110, 105, 115, 116, 112, 53, 50, 49, 0, 0, 0, 8, 110, 105, 115, 116, 112, 53, 50, 49, 0, 0, 0, -123, 4, 1, -56, 55, 64, -73, -109, 95, 94, -107, -116, -46, -16, 119, -66, -68, 41, -103, -66, 102, -123, -69, 59, -8, 106, 72, 75, 7, 56, -79, 109, -88, 77, 12, -97, -109, -32, -60, 64, -75, -48, 50, -51, -68, -81, 75, 110, -7, -79, -32, -36, -73, -7, -65, -24, 40, -74, 58, 43, -26, -5, -55, 125, -32, -89, -54, -111, 0, 81, 37, -73, 60, 69, 107, -108, 115, 60, -61, 22, 6, -128, -69, -28, 122, -26, -37, -117, 121, -106, -126, 23, -90, 127, 73, -58, -113, -61, 105, 68, 116, 85, -115, -47, 90, 122, 109, -21, 127, 39, -75, -58, -109, 73, -82, -122, -11, -44, -87, 85, -100, -4, -123, -31, 126, -94, 127, 96, 9, -30, 70, -113, -42, 28"); + byte[] H = fromString("-36, -107, -95, 2, 93, -111, -19, -107, 118, -7, 116, -33, 58, -90, -63, -60, -5, -23, 7, 56, -128, -22, -15, 26, -97, 2, 50, -93, 21, -21, 69, 105"); + byte[] sig = fromString("0, 0, 0, 19, 101, 99, 100, 115, 97, 45, 115, 104, 97, 50, 45, 110, 105, 115, 116, 112, 53, 50, 49, 0, 0, 0, -117, 0, 0, 0, 66, 1, 31, -111, 69, -37, 33, 24, -95, 53, -124, -33, 41, 65, -96, -112, -102, -33, 123, 30, -108, 102, 127, -27, 72, 101, -108, -123, 6, 107, 83, -72, -121, 87, -86, 75, 114, 50, -60, -75, -46, 7, -63, 84, -114, -91, 113, 52, 26, 102, -11, 76, 99, 9, 19, -73, -42, -3, 57, 41, -42, 13, -81, 18, -3, -49, -50, 0, 0, 0, 65, 102, 60, -2, 123, 91, -8, 120, 42, 118, 118, -9, -112, 72, 8, 61, -49, -45, 63, 112, 61, -55, -122, -109, 4, -39, 95, 3, -4, -43, 98, 39, 4, 63, 78, 78, 51, 77, 75, -23, 19, -46, 117, -115, -95, 90, -43, 108, -47, -90, 84, 98, 50, -97, -37, -14, -115, -76, 14, -61, 91, 107, 23, -112, 22, -15"); + + PublicKey hostKey = new Buffer.PlainBuffer(K_S).readPublicKey(); + + Signature signature = new SignatureECDSA.Factory521().create(); + signature.init(hostKey, null); + signature.update(H, 0, H.length); + + Assert.assertTrue("ECDSA521 signature verifies", signature.verify(sig)); + } + + private byte[] fromString(String string) { + String[] split = string.split(", "); + byte[] res = new byte[split.length]; + + for (int i = 0; i < split.length; i++) + res[i] = Byte.parseByte(split[i]); + + return res; + } +} From 31f6c5a44c2b7a61d974baa875131dbbaf1288dd Mon Sep 17 00:00:00 2001 From: Iger Date: Mon, 3 Jul 2017 22:09:52 +0300 Subject: [PATCH 12/12] - boggle --- .../schmizz/sshj/signature/VerificationTest.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/test/java/net/schmizz/sshj/signature/VerificationTest.java b/src/test/java/net/schmizz/sshj/signature/VerificationTest.java index 4008e7997..c9b9b743f 100644 --- a/src/test/java/net/schmizz/sshj/signature/VerificationTest.java +++ b/src/test/java/net/schmizz/sshj/signature/VerificationTest.java @@ -1,3 +1,18 @@ +/* + * 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 java.security.PublicKey;