Skip to content

Commit

Permalink
Support ECDSA PuTTY keys.
Browse files Browse the repository at this point in the history
  • Loading branch information
vladimirlagunov committed Jan 8, 2021
1 parent 8076fb8 commit 4696ab9
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@
import net.schmizz.sshj.common.Base64;
import net.schmizz.sshj.common.Buffer;
import net.schmizz.sshj.common.KeyType;
import net.schmizz.sshj.common.SecurityUtils;
import net.schmizz.sshj.userauth.password.PasswordUtils;
import org.bouncycastle.asn1.nist.NISTNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.util.encoders.Hex;

import javax.crypto.Cipher;
Expand Down Expand Up @@ -165,6 +169,35 @@ protected KeyPair readKeyPair() throws IOException {
EdDSAPrivateKeySpec privateSpec = new EdDSAPrivateKeySpec(privateKeyReader.readBytes(), ed25519);
return new KeyPair(new EdDSAPublicKey(publicSpec), new EdDSAPrivateKey(privateSpec));
}
final int ecdsaCurve;
switch (this.getType()) {
case ECDSA256:
ecdsaCurve = 256;
break;
case ECDSA384:
ecdsaCurve = 384;
break;
case ECDSA521:
ecdsaCurve = 521;
break;
default:
ecdsaCurve = -1;
break;
}
if (ecdsaCurve > 0) {
BigInteger s = new BigInteger(1, privateKeyReader.readBytes());
String name = "P-" + ecdsaCurve;
X9ECParameters ecParams = NISTNamedCurves.getByName(name);
ECNamedCurveSpec ecCurveSpec =
new ECNamedCurveSpec(name, ecParams.getCurve(), ecParams.getG(), ecParams.getN());
ECPrivateKeySpec pks = new ECPrivateKeySpec(s, ecCurveSpec);
try {
PrivateKey privateKey = SecurityUtils.getKeyFactory(KeyAlgorithm.ECDSA).generatePrivate(pks);
return new KeyPair(getType().readPubKeyFromBuffer(publicKeyReader), privateKey);
} catch (GeneralSecurityException e) {
throw new IOException(e.getMessage(), e);
}
}
throw new IOException(String.format("Unknown key type %s", this.getType()));
}

Expand Down
49 changes: 49 additions & 0 deletions src/test/java/net/schmizz/sshj/keyprovider/PuTTYKeyFileTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package net.schmizz.sshj.keyprovider;

import com.hierynomus.sshj.userauth.keyprovider.OpenSSHKeyV1KeyFile;
import net.schmizz.sshj.userauth.keyprovider.PKCS8KeyFile;
import net.schmizz.sshj.userauth.keyprovider.PuTTYKeyFile;
import net.schmizz.sshj.userauth.password.PasswordFinder;
import net.schmizz.sshj.userauth.password.Resource;
Expand Down Expand Up @@ -292,6 +293,54 @@ public boolean shouldRetry(Resource<?> resource) {
assertEquals(key.getPublic(), referenceKey.getPublic());
}

@Test
public void testEcDsa256() throws Exception {
// Generated with
// puttygen src/test/resources/keytypes/test_ecdsa_nistp256 -O private \
// -o src/test/resources/keytypes/test_ecdsa_nistp256_puttygen.ppk
PuTTYKeyFile key = new PuTTYKeyFile();
key.init(new File("src/test/resources/keytypes/test_ecdsa_nistp256_puttygen.ppk"));
assertNotNull(key.getPrivate());
assertNotNull(key.getPublic());

PKCS8KeyFile referenceKey = new PKCS8KeyFile();
referenceKey.init(new File("src/test/resources/keytypes/test_ecdsa_nistp256"));
assertEquals(key.getPrivate(), referenceKey.getPrivate());
assertEquals(key.getPublic(), referenceKey.getPublic());
}

@Test
public void testEcDsa384() throws Exception {
// Generated with
// puttygen src/test/resources/keytypes/test_ecdsa_nistp384_2 -O private \
// -o src/test/resources/keytypes/test_ecdsa_nistp384_2_puttygen.ppk
PuTTYKeyFile key = new PuTTYKeyFile();
key.init(new File("src/test/resources/keytypes/test_ecdsa_nistp384_2_puttygen.ppk"));
assertNotNull(key.getPrivate());
assertNotNull(key.getPublic());

OpenSSHKeyV1KeyFile referenceKey = new OpenSSHKeyV1KeyFile();
referenceKey.init(new File("src/test/resources/keytypes/test_ecdsa_nistp384_2"));
assertEquals(key.getPrivate(), referenceKey.getPrivate());
assertEquals(key.getPublic(), referenceKey.getPublic());
}

@Test
public void testEcDsa521() throws Exception {
// Generated with
// puttygen src/test/resources/keytypes/test_ecdsa_nistp521_2 -O private \
// -o src/test/resources/keytypes/test_ecdsa_nistp521_2_puttygen.ppk
PuTTYKeyFile key = new PuTTYKeyFile();
key.init(new File("src/test/resources/keytypes/test_ecdsa_nistp521_2_puttygen.ppk"));
assertNotNull(key.getPrivate());
assertNotNull(key.getPublic());

OpenSSHKeyV1KeyFile referenceKey = new OpenSSHKeyV1KeyFile();
referenceKey.init(new File("src/test/resources/keytypes/test_ecdsa_nistp521_2"));
assertEquals(key.getPrivate(), referenceKey.getPrivate());
assertEquals(key.getPublic(), referenceKey.getPublic());
}

@Test
public void testCorrectPassphraseRsa() throws Exception {
PuTTYKeyFile key = new PuTTYKeyFile();
Expand Down
10 changes: 10 additions & 0 deletions src/test/resources/keytypes/test_ecdsa_nistp256_puttygen.ppk
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
PuTTY-User-Key-File-2: ecdsa-sha2-nistp256
Encryption: none
Comment: imported-openssh-key
Public-Lines: 3
AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOEQcvowiV3i
gdRO7rKPrZrao1hCQrnC4tgsxqSJdQCbABI+vHrdbJRfWZNuSk48aAtARJzJVmkn
/r63EPJgkh8=
Private-Lines: 1
AAAAIQCVDJbEpV6gmZgo5TeJFe4cz/qfabtH8CfK+JtapXufEg==
Private-MAC: 48f3a17cf5f65f4f225e7a21f007d8270d7c8c8f
10 changes: 10 additions & 0 deletions src/test/resources/keytypes/test_ecdsa_nistp384_2
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNlY2RzYS
1zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQTItEGNGyMGn9tCIM4oC3fpU7jVxDQP
RRkB/Qv8lfM4mmSuYLPcakV6av0ATlM6mKD/TObWQNOJAYzp3MsUn1EMgVLe/sd9TY/hP6
8Vn+zumMqjmtdX70Ty5ftEoH9zBlgAAADYhfSye4X0snsAAAATZWNkc2Etc2hhMi1uaXN0
cDM4NAAAAAhuaXN0cDM4NAAAAGEEyLRBjRsjBp/bQiDOKAt36VO41cQ0D0UZAf0L/JXzOJ
pkrmCz3GpFemr9AE5TOpig/0zm1kDTiQGM6dzLFJ9RDIFS3v7HfU2P4T+vFZ/s7pjKo5rX
V+9E8uX7RKB/cwZYAAAAMGvH38HMnj6cELCBVQnAQYHlA/Vz1+RVZHj08cey/P3PALx7MR
pV135UZNZAtWQm+wAAAAlyb290QHNzaGoBAgMEBQYH
-----END OPENSSH PRIVATE KEY-----
1 change: 1 addition & 0 deletions src/test/resources/keytypes/test_ecdsa_nistp384_2.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBMi0QY0bIwaf20IgzigLd+lTuNXENA9FGQH9C/yV8ziaZK5gs9xqRXpq/QBOUzqYoP9M5tZA04kBjOncyxSfUQyBUt7+x31Nj+E/rxWf7O6YyqOa11fvRPLl+0Sgf3MGWA== root@sshj
11 changes: 11 additions & 0 deletions src/test/resources/keytypes/test_ecdsa_nistp384_2_puttygen.ppk
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
PuTTY-User-Key-File-2: ecdsa-sha2-nistp384
Encryption: none
Comment: root@sshj
Public-Lines: 3
AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBMi0QY0bIwaf
20IgzigLd+lTuNXENA9FGQH9C/yV8ziaZK5gs9xqRXpq/QBOUzqYoP9M5tZA04kB
jOncyxSfUQyBUt7+x31Nj+E/rxWf7O6YyqOa11fvRPLl+0Sgf3MGWA==
Private-Lines: 2
AAAAMGvH38HMnj6cELCBVQnAQYHlA/Vz1+RVZHj08cey/P3PALx7MRpV135UZNZA
tWQm+w==
Private-MAC: aa4d48441934e15491af0a30f75a02f4e324e652
12 changes: 12 additions & 0 deletions src/test/resources/keytypes/test_ecdsa_nistp521_2
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNlY2RzYS
1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQA3ilD2XkhjkSuEj8KcIXWjhjKSOfQ
QEZBFZyoPT4QV8oRiGT1NRVcN86Paymq8M8WgANFVEAZp7eDqTnsKJ6LEpoAM93DJa1ERO
RWwSeDTDy5GIxMDYgg+CKZVhAMJmS/iavsSXyKUf1ibYo9b5S8y8rpzvmiRg/dQGkfloJR
BLu7czAAAAEI8uaocPLmqHAAAAATZWNkc2Etc2hhMi1uaXN0cDUyMQAAAAhuaXN0cDUyMQ
AAAIUEAN4pQ9l5IY5ErhI/CnCF1o4Yykjn0EBGQRWcqD0+EFfKEYhk9TUVXDfOj2spqvDP
FoADRVRAGae3g6k57CieixKaADPdwyWtRETkVsEng0w8uRiMTA2IIPgimVYQDCZkv4mr7E
l8ilH9Ym2KPW+UvMvK6c75okYP3UBpH5aCUQS7u3MwAAAAQSlrwjeSrVTc6OyiA3OTfac4
+3nKcf/PRSjIhOLsGUIs2pVCxGYP8/ZfbVfkv7nHMn5Cc0fDZEs2cSWi2QhVKBSfAAAACX
Jvb3RAc3NoagEC
-----END OPENSSH PRIVATE KEY-----
1 change: 1 addition & 0 deletions src/test/resources/keytypes/test_ecdsa_nistp521_2.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBADeKUPZeSGORK4SPwpwhdaOGMpI59BARkEVnKg9PhBXyhGIZPU1FVw3zo9rKarwzxaAA0VUQBmnt4OpOewonosSmgAz3cMlrURE5FbBJ4NMPLkYjEwNiCD4IplWEAwmZL+Jq+xJfIpR/WJtij1vlLzLyunO+aJGD91AaR+WglEEu7tzMA== root@sshj
12 changes: 12 additions & 0 deletions src/test/resources/keytypes/test_ecdsa_nistp521_2_puttygen.ppk
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
PuTTY-User-Key-File-2: ecdsa-sha2-nistp521
Encryption: none
Comment: root@sshj
Public-Lines: 4
AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBADeKUPZeSGO
RK4SPwpwhdaOGMpI59BARkEVnKg9PhBXyhGIZPU1FVw3zo9rKarwzxaAA0VUQBmn
t4OpOewonosSmgAz3cMlrURE5FbBJ4NMPLkYjEwNiCD4IplWEAwmZL+Jq+xJfIpR
/WJtij1vlLzLyunO+aJGD91AaR+WglEEu7tzMA==
Private-Lines: 2
AAAAQSlrwjeSrVTc6OyiA3OTfac4+3nKcf/PRSjIhOLsGUIs2pVCxGYP8/ZfbVfk
v7nHMn5Cc0fDZEs2cSWi2QhVKBSf
Private-MAC: 052d1a2fe2c5837aec9dbe0bf10f2ccc376eda43

0 comments on commit 4696ab9

Please sign in to comment.