diff --git a/src/main/java/net/schmizz/sshj/userauth/keyprovider/PuTTYKeyFile.java b/src/main/java/net/schmizz/sshj/userauth/keyprovider/PuTTYKeyFile.java index 818ae7b6..41b95d6a 100644 --- a/src/main/java/net/schmizz/sshj/userauth/keyprovider/PuTTYKeyFile.java +++ b/src/main/java/net/schmizz/sshj/userauth/keyprovider/PuTTYKeyFile.java @@ -45,6 +45,7 @@ import java.util.Map; /** *
* PuTTY-User-Key-File-2: ssh-rsa
* Encryption: none
@@ -70,8 +71,7 @@ import java.util.Map;
*/
public class PuTTYKeyFile extends BaseFileKeyProvider {
- public static class Factory
- implements net.schmizz.sshj.common.Factory.Named {
+ public static class Factory implements net.schmizz.sshj.common.Factory.Named {
@Override
public FileKeyProvider create() {
@@ -88,11 +88,16 @@ public class PuTTYKeyFile extends BaseFileKeyProvider {
private byte[] publicKey;
/**
- * Key type. Either "ssh-rsa" for RSA key, or "ssh-dss" for DSA key.
+ * Key type
*/
@Override
public KeyType getType() throws IOException {
- return KeyType.fromString(headers.get("PuTTY-User-Key-File-2"));
+ for (String h : headers.keySet()) {
+ if (h.startsWith("PuTTY-User-Key-File-")) {
+ return KeyType.fromString(headers.get(h));
+ }
+ }
+ return KeyType.UNKNOWN;
}
public boolean isEncrypted() {
@@ -100,21 +105,18 @@ public class PuTTYKeyFile extends BaseFileKeyProvider {
return "aes256-cbc".equals(headers.get("Encryption"));
}
- private Map payload
- = new HashMap();
+ private Map payload = new HashMap();
/**
* For each line that looks like "Xyz: vvv", it will be stored in this map.
*/
- private final Map headers
- = new HashMap();
-
+ private final Map headers = new HashMap();
protected KeyPair readKeyPair() throws IOException {
this.parseKeyPair();
final Buffer.PlainBuffer publicKeyReader = new Buffer.PlainBuffer(publicKey);
final Buffer.PlainBuffer privateKeyReader = new Buffer.PlainBuffer(privateKey);
- publicKeyReader.readBytes(); // The first part of the payload is a human-readable key format name.
+ publicKeyReader.readBytes(); // The first part of the payload is a human-readable key format name.
if (KeyType.RSA.equals(this.getType())) {
// public key exponent
BigInteger e = publicKeyReader.readMPInt();
@@ -131,10 +133,8 @@ public class PuTTYKeyFile extends BaseFileKeyProvider {
throw new IOException(s.getMessage(), s);
}
try {
- return new KeyPair(
- factory.generatePublic(new RSAPublicKeySpec(n, e)),
- factory.generatePrivate(new RSAPrivateKeySpec(n, d))
- );
+ return new KeyPair(factory.generatePublic(new RSAPublicKeySpec(n, e)),
+ factory.generatePrivate(new RSAPrivateKeySpec(n, d)));
} catch (InvalidKeySpecException i) {
throw new IOException(i.getMessage(), i);
}
@@ -155,10 +155,8 @@ public class PuTTYKeyFile extends BaseFileKeyProvider {
throw new IOException(s.getMessage(), s);
}
try {
- return new KeyPair(
- factory.generatePublic(new DSAPublicKeySpec(y, p, q, g)),
- factory.generatePrivate(new DSAPrivateKeySpec(x, p, q, g))
- );
+ return new KeyPair(factory.generatePublic(new DSAPublicKeySpec(y, p, q, g)),
+ factory.generatePrivate(new DSAPrivateKeySpec(x, p, q, g)));
} catch (InvalidKeySpecException e) {
throw new IOException(e.getMessage(), e);
}
@@ -187,8 +185,8 @@ public class PuTTYKeyFile extends BaseFileKeyProvider {
if (ecdsaCurve != null) {
BigInteger s = new BigInteger(1, privateKeyReader.readBytes());
X9ECParameters ecParams = NISTNamedCurves.getByName(ecdsaCurve);
- ECNamedCurveSpec ecCurveSpec =
- new ECNamedCurveSpec(ecdsaCurve, ecParams.getCurve(), ecParams.getG(), ecParams.getN());
+ ECNamedCurveSpec ecCurveSpec = new ECNamedCurveSpec(ecdsaCurve, ecParams.getCurve(), ecParams.getG(),
+ ecParams.getN());
ECPrivateKeySpec pks = new ECPrivateKeySpec(s, ecCurveSpec);
try {
PrivateKey privateKey = SecurityUtils.getKeyFactory(KeyAlgorithm.ECDSA).generatePrivate(pks);
@@ -247,7 +245,8 @@ public class PuTTYKeyFile extends BaseFileKeyProvider {
}
/**
- * Converts a passphrase into a key, by following the convention that PuTTY uses.
+ * Converts a passphrase into a key, by following the convention that PuTTY
+ * uses.
*
*
* This is used to decrypt the private key when it's encrypted.
@@ -256,15 +255,16 @@ public class PuTTYKeyFile extends BaseFileKeyProvider {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
- // The encryption key is derived from the passphrase by means of a succession of SHA-1 hashes.
+ // The encryption key is derived from the passphrase by means of a succession of
+ // SHA-1 hashes.
// Sequence number 0
- digest.update(new byte[]{0, 0, 0, 0});
+ digest.update(new byte[] { 0, 0, 0, 0 });
digest.update(passphrase.getBytes());
byte[] key1 = digest.digest();
// Sequence number 1
- digest.update(new byte[]{0, 0, 0, 1});
+ digest.update(new byte[] { 0, 0, 0, 1 });
digest.update(passphrase.getBytes());
byte[] key2 = digest.digest();
diff --git a/src/test/java/net/schmizz/sshj/keyprovider/PuTTYKeyFileTest.java b/src/test/java/net/schmizz/sshj/keyprovider/PuTTYKeyFileTest.java
index b22b9840..e00c820b 100644
--- a/src/test/java/net/schmizz/sshj/keyprovider/PuTTYKeyFileTest.java
+++ b/src/test/java/net/schmizz/sshj/keyprovider/PuTTYKeyFileTest.java
@@ -226,6 +226,17 @@ public class PuTTYKeyFileTest {
"nLEIBzB8WEaMMgDz5qwlqq7eBxLPIIi9uHyjMf7NOsQ=\n" +
"Private-MAC: b200c6d801fc8dd8f84a14afc3b94d9f9bb2df90\n";
+ final static String v3_ecdsa = "PuTTY-User-Key-File-3: ecdsa-sha2-nistp256\n" +
+ "Encryption: none\n" +
+ "Comment: ecdsa-key-20210819\n" +
+ "Public-Lines: 3\n" +
+ "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBP5mbdlgVmkw\n" +
+ "LzDkznoY8TXKnok/mlMkpk8FELFNSECnXNdtZ4B8+Bpqnvchhk/jY/0tUU98lFxt\n" +
+ "JR0o0l8B5y0=\n" +
+ "Private-Lines: 1\n" +
+ "AAAAIEblmwyKaGuvc6dLgNeHsc1BuZeQORTSxBF5SBLNyjYc\n" +
+ "Private-MAC: e1aed15a209f48fdaa5228640f1109a7740340764a96f97ec6023da7f92d07ea";
+
@Test
public void test2048() throws Exception {
PuTTYKeyFile key = new PuTTYKeyFile();
@@ -341,6 +352,14 @@ public class PuTTYKeyFileTest {
assertEquals(key.getPublic(), referenceKey.getPublic());
}
+ @Test
+ public void testV3Key() throws Exception {
+ PuTTYKeyFile key = new PuTTYKeyFile();
+ key.init(new StringReader(v3_ecdsa));
+ assertNotNull(key.getPrivate());
+ assertNotNull(key.getPublic());
+ }
+
@Test
public void testCorrectPassphraseRsa() throws Exception {
PuTTYKeyFile key = new PuTTYKeyFile();