mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-06 15:20:54 +03:00
Merge pull request #226 from hierynomus/ecdsa_fix
Correctly calculating ECDSA key fingerprint (Fixes #225)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
package net.schmizz.sshj.transport.kex;
|
||||
package com.hierynomus.sshj.secg;
|
||||
|
||||
import net.schmizz.sshj.common.SSHRuntimeException;
|
||||
|
||||
@@ -7,11 +7,11 @@ import java.security.spec.ECPoint;
|
||||
import java.security.spec.EllipticCurve;
|
||||
import java.util.Arrays;
|
||||
|
||||
class SecgUtils {
|
||||
public class SecgUtils {
|
||||
/**
|
||||
* SECG 2.3.4 Octet String to ECPoint
|
||||
*/
|
||||
static ECPoint getDecoded(byte[] M, EllipticCurve curve) {
|
||||
public static ECPoint getDecoded(byte[] M, EllipticCurve curve) {
|
||||
int elementSize = getElementSize(curve);
|
||||
if (M.length != 2 * elementSize + 1 || M[0] != 0x04) {
|
||||
throw new SSHRuntimeException("Invalid 'f' for Elliptic Curve " + curve.toString());
|
||||
@@ -26,7 +26,7 @@ class SecgUtils {
|
||||
/**
|
||||
* SECG 2.3.3 ECPoint to Octet String
|
||||
*/
|
||||
static byte[] getEncoded(ECPoint point, EllipticCurve curve) {
|
||||
public static byte[] getEncoded(ECPoint point, EllipticCurve curve) {
|
||||
int elementSize = getElementSize(curve);
|
||||
byte[] M = new byte[2 * elementSize + 1];
|
||||
M[0] = 0x04;
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package net.schmizz.sshj.common;
|
||||
|
||||
import com.hierynomus.sshj.secg.SecgUtils;
|
||||
import org.bouncycastle.asn1.nist.NISTNamedCurves;
|
||||
import org.bouncycastle.asn1.x9.X9ECParameters;
|
||||
import org.bouncycastle.jce.spec.ECParameterSpec;
|
||||
@@ -151,17 +152,11 @@ public enum KeyType {
|
||||
@Override
|
||||
public void putPubKeyIntoBuffer(PublicKey pk, Buffer<?> buf) {
|
||||
final ECPublicKey ecdsa = (ECPublicKey) pk;
|
||||
final java.security.spec.ECPoint point = ecdsa.getW();
|
||||
final byte[] x = trimStartingZeros(point.getAffineX().toByteArray());
|
||||
final byte[] y = trimStartingZeros(point.getAffineY().toByteArray());
|
||||
byte[] encoded = SecgUtils.getEncoded(ecdsa.getW(), ecdsa.getParams().getCurve());
|
||||
|
||||
buf.putString(sType)
|
||||
.putString(NISTP_CURVE)
|
||||
.putUInt32(1 + x.length + y.length)
|
||||
.putRawBytes(new byte[] { (byte) 0x04 })
|
||||
.putRawBytes(x)
|
||||
.putRawBytes(y)
|
||||
;
|
||||
.putBytes(encoded);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.schmizz.sshj.transport.kex;
|
||||
|
||||
import net.schmizz.sshj.common.SSHRuntimeException;
|
||||
import net.schmizz.sshj.common.SecurityUtils;
|
||||
|
||||
import java.math.BigInteger;
|
||||
@@ -10,10 +9,9 @@ import java.security.KeyPair;
|
||||
import java.security.PublicKey;
|
||||
import java.security.interfaces.ECPublicKey;
|
||||
import java.security.spec.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static net.schmizz.sshj.transport.kex.SecgUtils.getDecoded;
|
||||
import static net.schmizz.sshj.transport.kex.SecgUtils.getEncoded;
|
||||
import static com.hierynomus.sshj.secg.SecgUtils.getDecoded;
|
||||
import static com.hierynomus.sshj.secg.SecgUtils.getEncoded;
|
||||
|
||||
public class ECDH extends DHBase {
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ public class OpenSSHKeyFile
|
||||
try {
|
||||
final String keydata = br.readLine();
|
||||
if (keydata != null) {
|
||||
String[] parts = keydata.split(" ");
|
||||
String[] parts = keydata.trim().split(" ");
|
||||
assert parts.length >= 2;
|
||||
type = KeyType.fromString(parts[0]);
|
||||
pubKey = new Buffer.PlainBuffer(Base64.decode(parts[1])).readPublicKey();
|
||||
|
||||
@@ -30,9 +30,12 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.PublicKey;
|
||||
import java.util.Arrays;
|
||||
import java.util.Scanner;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@@ -127,6 +130,16 @@ public class OpenSSHKeyFileTest {
|
||||
assertEquals(KeyUtil.newDSAPrivateKey(x, p, q, g), dsa.getPrivate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHaveCorrectFingerprintForECDSA() throws IOException, GeneralSecurityException {
|
||||
OpenSSHKeyFile keyFile = new OpenSSHKeyFile();
|
||||
keyFile.init(new File("src/test/resources/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";
|
||||
PublicKey aPublic = keyFile.getPublic();
|
||||
String sshjFingerprintSshjKey = net.schmizz.sshj.common.SecurityUtils.getFingerprint(aPublic);
|
||||
assertThat(expected, containsString(sshjFingerprintSshjKey));
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
throws UnsupportedEncodingException, GeneralSecurityException {
|
||||
|
||||
5
src/test/resources/test_ecdsa_nistp256
Normal file
5
src/test/resources/test_ecdsa_nistp256
Normal file
@@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIJUMlsSlXqCZmCjlN4kV7hzP+p9pu0fwJ8r4m1qle58SoAoGCCqGSM49
|
||||
AwEHoUQDQgAE4RBy+jCJXeKB1E7uso+tmtqjWEJCucLi2CzGpIl1AJsAEj68et1s
|
||||
lF9Zk25KTjxoC0BEnMlWaSf+vrcQ8mCSHw==
|
||||
-----END EC PRIVATE KEY-----
|
||||
1
src/test/resources/test_ecdsa_nistp256.pub
Normal file
1
src/test/resources/test_ecdsa_nistp256.pub
Normal file
@@ -0,0 +1 @@
|
||||
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOEQcvowiV3igdRO7rKPrZrao1hCQrnC4tgsxqSJdQCbABI+vHrdbJRfWZNuSk48aAtARJzJVmkn/r63EPJgkh8= root@itgcpkerberosstack-cbgateway-0-20151117031915
|
||||
Reference in New Issue
Block a user