Repository: mina-sshd
Updated Branches:
  refs/heads/master 1e8254794 -> 3668d92e4


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/DSSPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/DSSPuttyKeyDecoder.java
 
b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/DSSPuttyKeyDecoder.java
new file mode 100644
index 0000000..366aead
--- /dev/null
+++ 
b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/DSSPuttyKeyDecoder.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.sshd.common.config.keys.loader.putty;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.DSAPublicKey;
+import java.security.spec.DSAPrivateKeySpec;
+import java.security.spec.DSAPublicKeySpec;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.util.security.SecurityUtils;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class DSSPuttyKeyDecoder extends AbstractPuttyKeyDecoder<DSAPublicKey, 
DSAPrivateKey> {
+    public static final DSSPuttyKeyDecoder INSTANCE = new DSSPuttyKeyDecoder();
+
+    public DSSPuttyKeyDecoder() {
+        super(DSAPublicKey.class, DSAPrivateKey.class, 
Collections.singletonList(KeyPairProvider.SSH_DSS));
+    }
+
+    @Override
+    public Collection<KeyPair> loadKeyPairs(String resourceKey, PuttyKeyReader 
pubReader, PuttyKeyReader prvReader)
+            throws IOException, GeneralSecurityException {
+        pubReader.skip();   // skip version
+
+        BigInteger p = pubReader.readInt();
+        BigInteger q = pubReader.readInt();
+        BigInteger g = pubReader.readInt();
+        BigInteger y = pubReader.readInt();
+        BigInteger x = prvReader.readInt();
+        KeyFactory kf = SecurityUtils.getKeyFactory(KeyUtils.DSS_ALGORITHM);
+        PublicKey pubKey = kf.generatePublic(new DSAPublicKeySpec(y, p, q, g));
+        PrivateKey prvKey = kf.generatePrivate(new DSAPrivateKeySpec(x, p, q, 
g));
+        return Collections.singletonList(new KeyPair(pubKey, prvKey));
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/ECDSAPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/ECDSAPuttyKeyDecoder.java
 
b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/ECDSAPuttyKeyDecoder.java
new file mode 100644
index 0000000..a257ff8
--- /dev/null
+++ 
b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/ECDSAPuttyKeyDecoder.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.sshd.common.config.keys.loader.putty;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPoint;
+import java.security.spec.ECPrivateKeySpec;
+import java.security.spec.ECPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.sshd.common.cipher.ECCurves;
+import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.util.buffer.BufferUtils;
+import org.apache.sshd.common.util.security.SecurityUtils;
+
+/**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class ECDSAPuttyKeyDecoder extends AbstractPuttyKeyDecoder<ECPublicKey, 
ECPrivateKey> {
+    public static final ECDSAPuttyKeyDecoder INSTANCE = new 
ECDSAPuttyKeyDecoder();
+
+    public ECDSAPuttyKeyDecoder() {
+        super(ECPublicKey.class, ECPrivateKey.class, ECCurves.KEY_TYPES);
+    }
+
+    @Override
+    public Collection<KeyPair> loadKeyPairs(String resourceKey, PuttyKeyReader 
pubReader, PuttyKeyReader prvReader)
+            throws IOException, GeneralSecurityException {
+        if (!SecurityUtils.isECCSupported()) {
+            throw new NoSuchAlgorithmException("ECC not supported for " + 
resourceKey);
+        }
+
+        String keyType = pubReader.readString();
+        ECCurves curve = ECCurves.fromKeyType(keyType);
+        if (curve == null) {
+            throw new InvalidKeySpecException("Not an EC curve name: " + 
keyType);
+        }
+
+        String encCurveName = pubReader.readString();
+        String keyCurveName = curve.getName();
+        if (!keyCurveName.equals(encCurveName)) {
+            throw new InvalidKeySpecException("Mismatched key curve name (" + 
keyCurveName + ") vs. encoded one (" + encCurveName + ")");
+        }
+
+        byte[] octets = pubReader.read();
+        ECPoint w;
+        try {
+            w = ECCurves.octetStringToEcPoint(octets);
+            if (w == null) {
+                throw new InvalidKeySpecException("No public ECPoint generated 
for curve=" + keyCurveName
+                        + " from octets=" + BufferUtils.toHex(':', octets));
+            }
+        } catch (RuntimeException e) {
+            throw new InvalidKeySpecException("Failed (" + 
e.getClass().getSimpleName() + ")"
+                    + " to generate public ECPoint for curve=" + keyCurveName
+                    + " from octets=" + BufferUtils.toHex(':', octets)
+                    + ": " + e.getMessage());
+        }
+
+        KeyFactory kf = SecurityUtils.getKeyFactory(KeyUtils.EC_ALGORITHM);
+        ECParameterSpec paramSpec = curve.getParameters();
+        PublicKey pubKey = kf.generatePublic(new ECPublicKeySpec(w, 
paramSpec));
+
+        BigInteger s = prvReader.readInt();
+        PrivateKey prvKey = kf.generatePrivate(new ECPrivateKeySpec(s, 
paramSpec));
+        return Collections.singletonList(new KeyPair(pubKey, prvKey));
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/EdDSAPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/EdDSAPuttyKeyDecoder.java
 
b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/EdDSAPuttyKeyDecoder.java
new file mode 100644
index 0000000..f5980ab
--- /dev/null
+++ 
b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/EdDSAPuttyKeyDecoder.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.sshd.common.config.keys.loader.putty;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.util.security.SecurityUtils;
+import org.apache.sshd.common.util.security.eddsa.EdDSASecurityProviderUtils;
+
+import net.i2p.crypto.eddsa.EdDSAPrivateKey;
+import net.i2p.crypto.eddsa.EdDSAPublicKey;
+
+/**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class EdDSAPuttyKeyDecoder extends 
AbstractPuttyKeyDecoder<EdDSAPublicKey, EdDSAPrivateKey> {
+    public static final EdDSAPuttyKeyDecoder INSTANCE = new 
EdDSAPuttyKeyDecoder();
+
+    public EdDSAPuttyKeyDecoder() {
+        super(EdDSAPublicKey.class, EdDSAPrivateKey.class, 
Collections.singletonList(KeyPairProvider.SSH_ED25519));
+    }
+
+    @Override
+    public Collection<KeyPair> loadKeyPairs(String resourceKey, PuttyKeyReader 
pubReader, PuttyKeyReader prvReader)
+            throws IOException, GeneralSecurityException {
+        if (!SecurityUtils.isEDDSACurveSupported()) {
+            throw new NoSuchAlgorithmException(SecurityUtils.EDDSA + " 
provider not supported for " + resourceKey);
+        }
+
+        String keyType = pubReader.readString();
+        if (!KeyPairProvider.SSH_ED25519.equals(keyType)) {
+            throw new InvalidKeySpecException("Not an " + SecurityUtils.EDDSA 
+ " key: " + keyType);
+        }
+
+        byte[] seed = pubReader.read();
+        PublicKey pubKey = 
EdDSASecurityProviderUtils.generateEDDSAPublicKey(seed);
+        seed = prvReader.read();
+        PrivateKey prvKey = 
EdDSASecurityProviderUtils.generateEDDSAPrivateKey(seed);
+        return Collections.singletonList(new KeyPair(pubKey, prvKey));
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyPairResourceParser.java
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyPairResourceParser.java
 
b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyPairResourceParser.java
new file mode 100644
index 0000000..06443d9
--- /dev/null
+++ 
b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyPairResourceParser.java
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.sshd.common.config.keys.loader.putty;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.sshd.common.config.keys.IdentityResourceLoader;
+import org.apache.sshd.common.config.keys.loader.KeyPairResourceParser;
+import org.apache.sshd.common.digest.BuiltinDigests;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.security.SecurityUtils;
+
+//CHECKSTYLE:OFF
+/**
+ * Loads a {@link KeyPair} from PuTTY's &quot;.ppk&quot; file.
+ * <P>Note(s):</P>
+ * <UL>
+ *      <P><LI>
+ *      The file appears to be a text file but it doesn't have a fixed 
encoding like UTF-8.
+ *      We use UTF-8 as the default encoding - since the important part is all 
ASCII,
+ *      this shouldn't really hurt the interpretation of the key.
+ *      </LI></P>
+ *
+ *      <P><LI>
+ *      Based on code from <A 
HREF="https://github.com/kohsuke/trilead-putty-extension";>Kohsuke's Trilead 
Putty Extension</A>
+ *      </LI></P>
+ *
+ *      <P><LI>
+ *      Encrypted keys requires AES-256-CBC support, which is available only 
if the
+ *      <A 
HREF="http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html";>
+ *      Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction 
Policy Files</A> are installed
+ *      </LI></P>
+ * </UL>
+ *
+ * <P>Sample PuTTY file format</P>
+ * <PRE>
+ * PuTTY-User-Key-File-2: ssh-rsa
+ * Encryption: none
+ * Comment: rsa-key-20080514
+ * Public-Lines: 4
+ * AAAAB3NzaC1yc2EAAAABJQAAAIEAiPVUpONjGeVrwgRPOqy3Ym6kF/f8bltnmjA2
+ * BMdAtaOpiD8A2ooqtLS5zWYuc0xkW0ogoKvORN+RF4JI+uNUlkxWxnzJM9JLpnvA
+ * HrMoVFaQ0cgDMIHtE1Ob1cGAhlNInPCRnGNJpBNcJ/OJye3yt7WqHP4SPCCLb6nL
+ * nmBUrLM=
+ * Private-Lines: 8
+ * AAAAgGtYgJzpktzyFjBIkSAmgeVdozVhgKmF6WsDMUID9HKwtU8cn83h6h7ug8qA
+ * hUWcvVxO201/vViTjWVz9ALph3uMnpJiuQaaNYIGztGJBRsBwmQW9738pUXcsUXZ
+ * 79KJP01oHn6Wkrgk26DIOsz04QOBI6C8RumBO4+F1WdfueM9AAAAQQDmA4hcK8Bx
+ * nVtEpcF310mKD3nsbJqARdw5NV9kCxPnEsmy7Sy1L4Ob/nTIrynbc3MA9HQVJkUz
+ * 7V0va5Pjm/T7AAAAQQCYbnG0UEekwk0LG1Hkxh1OrKMxCw2KWMN8ac3L0LVBg/Tk
+ * 8EnB2oT45GGeJaw7KzdoOMFZz0iXLsVLNUjNn2mpAAAAQQCN6SEfWqiNzyc/w5n/
+ * lFVDHExfVUJp0wXv+kzZzylnw4fs00lC3k4PZDSsb+jYCMesnfJjhDgkUA0XPyo8
+ * Emdk
+ * Private-MAC: 50c45751d18d74c00fca395deb7b7695e3ed6f77
+ * </PRE>
+ * @param <PUB> Generic public key type
+ * @param <PRV> Generic private key type
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+//CHECKSTYLE:ON
+public interface PuttyKeyPairResourceParser<PUB extends PublicKey, PRV extends 
PrivateKey>
+        extends IdentityResourceLoader<PUB, PRV>, KeyPairResourceParser {
+    String KEY_FILE_HEADER_PREFIX = "PuTTY-User-Key-File";
+    String PUBLIC_LINES_HEADER = "Public-Lines";
+    String PRIVATE_LINES_HEADER = "Private-Lines";
+    String PPK_FILE_SUFFIX = ".ppk";
+
+    List<String> KNOWN_HEADERS =
+            Collections.unmodifiableList(
+                    Arrays.asList(
+                            KEY_FILE_HEADER_PREFIX,
+                            PUBLIC_LINES_HEADER,
+                            PRIVATE_LINES_HEADER));
+
+    /**
+     * Value (case insensitive) used to denote that private key is not 
encrypted
+     */
+    String NO_PRIVATE_KEY_ENCRYPTION_VALUE = "none";
+
+    @Override
+    default boolean canExtractKeyPairs(String resourceKey, List<String> lines)
+            throws IOException, GeneralSecurityException {
+        if (GenericUtils.isEmpty(lines)) {
+            return false;
+        }
+
+        for (String l : lines) {
+            l = GenericUtils.trimToEmpty(l);
+            for (String hdr : KNOWN_HEADERS) {
+                if (l.startsWith(hdr)) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    static byte[] decodePrivateKeyBytes(byte[] prvBytes, String algName, int 
numBits, String algMode, String password)
+            throws GeneralSecurityException {
+        Objects.requireNonNull(prvBytes, "No encrypted key bytes");
+        ValidateUtils.checkNotNullAndNotEmpty(algName, "No encryption 
algorithm", GenericUtils.EMPTY_OBJECT_ARRAY);
+        ValidateUtils.checkTrue(numBits > 0, "Invalid encryption key size: 
%d", numBits);
+        ValidateUtils.checkNotNullAndNotEmpty(algMode, "No encryption mode", 
GenericUtils.EMPTY_OBJECT_ARRAY);
+        ValidateUtils.checkNotNullAndNotEmpty(password, "No encryption 
password", GenericUtils.EMPTY_OBJECT_ARRAY);
+
+        if (!"AES".equalsIgnoreCase(algName)) {
+            throw new NoSuchAlgorithmException("decodePrivateKeyBytes(" + 
algName + "-" + numBits + "-" + algMode + ") N/A");
+        }
+
+        return decodePrivateKeyBytes(prvBytes, algName, algMode, numBits, new 
byte[16], toEncryptionKey(password));
+    }
+
+    static byte[] decodePrivateKeyBytes(
+            byte[] encBytes, String cipherName, String cipherMode, int 
numBits, byte[] initVector, byte[] keyValue)
+                    throws GeneralSecurityException {
+        String xform = cipherName + "/" + cipherMode + "/NoPadding";
+        int maxAllowedBits = Cipher.getMaxAllowedKeyLength(xform);
+        // see 
http://www.javamex.com/tutorials/cryptography/unrestricted_policy_files.shtml
+        if (numBits > maxAllowedBits) {
+            throw new InvalidKeySpecException("decodePrivateKeyBytes(" + xform 
+ ")"
+                    + " required key length (" + numBits + ") exceeds max. 
available: " + maxAllowedBits);
+        }
+
+        SecretKeySpec skeySpec = new SecretKeySpec(keyValue, cipherName);
+        IvParameterSpec ivspec = new IvParameterSpec(initVector);
+        Cipher cipher = SecurityUtils.getCipher(xform);
+        cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivspec);
+
+        return cipher.doFinal(encBytes);
+    }
+
+    /**
+     * Converts a pass-phrase into a key, by following the convention that 
PuTTY uses.
+     * Used to decrypt the private key when it's encrypted.
+     * @param passphrase the Password to be used as seed for the key - ignored
+     * if {@code null}/empty
+     * @return The encryption key bytes - {@code null} if no pass-phrase
+     * @throws GeneralSecurityException If cannot retrieve SHA-1 digest
+     * @see <A 
HREF="http://security.stackexchange.com/questions/71341/how-does-putty-derive-the-encryption-key-in-its-ppk-format";>
+     * How does Putty derive the encryption key in its .ppk format ?</A>
+     */
+    static byte[] toEncryptionKey(String passphrase) throws 
GeneralSecurityException {
+        if (GenericUtils.isEmpty(passphrase)) {
+            return null;
+        }
+
+        MessageDigest hash = 
SecurityUtils.getMessageDigest(BuiltinDigests.sha1.getAlgorithm());
+        byte[] stateValue = {0, 0, 0, 0};
+        byte[] passBytes = passphrase.getBytes(StandardCharsets.UTF_8);
+        byte[] keyValue = new byte[32];
+        for (int i = 0, remLen = keyValue.length; i < 2; i++) {
+            hash.reset(); // just making sure
+
+            stateValue[3] = (byte) i;
+            hash.update(stateValue);
+            hash.update(passBytes);
+
+            byte[] digest = hash.digest();
+            System.arraycopy(digest, 0, keyValue, i * 20, Math.min(20, 
remLen));
+            remLen -= 20;
+        }
+
+        return keyValue;
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyReader.java
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyReader.java
 
b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyReader.java
new file mode 100644
index 0000000..4fb63d1
--- /dev/null
+++ 
b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyReader.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.sshd.common.config.keys.loader.putty;
+
+import java.io.Closeable;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StreamCorruptedException;
+import java.math.BigInteger;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Helper class for {@code Putty} key files decoders
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class PuttyKeyReader implements Closeable {
+    private final DataInputStream di;
+
+    public PuttyKeyReader(InputStream s) {
+        di = new DataInputStream(s);
+    }
+
+    public void skip() throws IOException {
+        int skipSize = di.readInt();
+        int effectiveSkip = di.skipBytes(skipSize);
+        if (skipSize != effectiveSkip) {
+            throw new StreamCorruptedException("Mismatched skip size: 
expected" + skipSize + ", actual=" + effectiveSkip);
+        }
+    }
+
+    public String readString() throws IOException {
+        return readString(StandardCharsets.UTF_8);
+    }
+
+    public String readString(Charset cs) throws IOException {
+        byte[] data = read();
+        return new String(data, cs);
+    }
+
+    public BigInteger readInt() throws IOException {
+        byte[] bytes = read();
+        return new BigInteger(bytes);
+    }
+
+    public byte[] read() throws IOException {
+        int len = di.readInt();
+        byte[] r = new byte[len];
+        di.readFully(r);
+        return r;
+    }
+
+    @Override
+    public void close() throws IOException {
+        di.close();
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtils.java
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtils.java
 
b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtils.java
new file mode 100644
index 0000000..e750ace
--- /dev/null
+++ 
b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtils.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.sshd.common.config.keys.loader.putty;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.NavigableMap;
+import java.util.TreeMap;
+
+import org.apache.sshd.common.config.keys.loader.KeyPairResourceParser;
+import org.apache.sshd.common.util.security.SecurityUtils;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public final class PuttyKeyUtils {
+    public static final List<PuttyKeyPairResourceParser<?, ?>> DEFAULT_PARSERS;
+
+    public static final NavigableMap<String, PuttyKeyPairResourceParser<?, ?>> 
BY_KEY_TYPE;
+
+    public static final KeyPairResourceParser DEFAULT_INSTANCE;
+
+    static {
+        List<PuttyKeyPairResourceParser<?, ?>> parsers = new ArrayList<>();
+        parsers.add(RSAPuttyKeyDecoder.INSTANCE);
+        parsers.add(DSSPuttyKeyDecoder.INSTANCE);
+        if (SecurityUtils.isECCSupported()) {
+            parsers.add(ECDSAPuttyKeyDecoder.INSTANCE);
+        }
+        if (SecurityUtils.isEDDSACurveSupported()) {
+            parsers.add(EdDSAPuttyKeyDecoder.INSTANCE);
+        }
+        NavigableMap<String, PuttyKeyPairResourceParser<?, ?>> map = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+        for (PuttyKeyPairResourceParser<?, ?> p : parsers) {
+            Collection<String> supported = p.getSupportedTypeNames();
+            for (String k : supported) {
+                map.put(k, p);
+            }
+        }
+        DEFAULT_PARSERS = Collections.unmodifiableList(parsers);
+        BY_KEY_TYPE = Collections.unmodifiableNavigableMap(map);
+        DEFAULT_INSTANCE = KeyPairResourceParser.aggregate(parsers);
+    }
+
+    private PuttyKeyUtils() {
+        throw new UnsupportedOperationException("No instance");
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
 
b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
new file mode 100644
index 0000000..0a55d55
--- /dev/null
+++ 
b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.sshd.common.config.keys.loader.putty;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.RSAPrivateCrtKeySpec;
+import java.security.spec.RSAPrivateKeySpec;
+import java.security.spec.RSAPublicKeySpec;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.util.security.SecurityUtils;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class RSAPuttyKeyDecoder extends AbstractPuttyKeyDecoder<RSAPublicKey, 
RSAPrivateKey> {
+    public static final RSAPuttyKeyDecoder INSTANCE = new RSAPuttyKeyDecoder();
+
+    public RSAPuttyKeyDecoder() {
+        super(RSAPublicKey.class, RSAPrivateKey.class, 
Collections.singletonList(KeyPairProvider.SSH_RSA));
+    }
+
+    @Override
+    public Collection<KeyPair> loadKeyPairs(String resourceKey, PuttyKeyReader 
pubReader, PuttyKeyReader prvReader)
+            throws IOException, GeneralSecurityException {
+        pubReader.skip();   // skip version
+
+        KeyFactory kf = SecurityUtils.getKeyFactory(KeyUtils.RSA_ALGORITHM);
+        BigInteger publicExp = pubReader.readInt();
+        BigInteger modulus = pubReader.readInt();
+        PublicKey pubKey = kf.generatePublic(new RSAPublicKeySpec(modulus, 
publicExp));
+
+        BigInteger privateExp = prvReader.readInt();
+        BigInteger primeP = prvReader.readInt();
+        BigInteger primeQ = prvReader.readInt();
+        BigInteger crtCoef = prvReader.readInt();
+        BigInteger primeExponentP = 
privateExp.mod(primeP.subtract(BigInteger.ONE));
+        BigInteger primeExponentQ = 
privateExp.mod(primeQ.subtract(BigInteger.ONE));
+        RSAPrivateKeySpec prvSpec = new RSAPrivateCrtKeySpec(
+                modulus, publicExp, privateExp, primeP, primeQ, 
primeExponentP, primeExponentQ, crtCoef);
+        PrivateKey prvKey = kf.generatePrivate(prvSpec);
+        return Collections.singletonList(new KeyPair(pubKey, prvKey));
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/main/resources/.gitignore
----------------------------------------------------------------------
diff --git a/sshd-putty/src/main/resources/.gitignore 
b/sshd-putty/src/main/resources/.gitignore
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java
 
b/sshd-putty/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java
new file mode 100644
index 0000000..b9f030f
--- /dev/null
+++ 
b/sshd-putty/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.sshd.common.config.keys.loader.putty;
+
+import java.io.IOException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.sshd.common.cipher.BuiltinCiphers;
+import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.config.keys.PrivateKeyEntryDecoder;
+import 
org.apache.sshd.common.config.keys.loader.openssh.OpenSSHKeyPairResourceParser;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.io.IoUtils;
+import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.Assume;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized.UseParametersRunnerFactory;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class)   // see 
https://github.com/junit-team/junit/wiki/Parameterized-tests
+@UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
+@Category({ NoIoTestCase.class })
+public class PuttyKeyUtilsTest extends JUnitTestSupport {
+    public static final String PASSWORD = "super secret passphrase";
+
+    private final String keyType;
+    private final String regularFile;
+    private final String encryptedFile;
+    private final PuttyKeyPairResourceParser<?, ?> parser;
+
+    public PuttyKeyUtilsTest(String keyType) {
+        this.keyType = keyType;
+        this.parser = PuttyKeyUtils.BY_KEY_TYPE.get(keyType);
+        this.regularFile = getClass().getSimpleName()
+                + "-" + keyType + "-" + KeyPair.class.getSimpleName()
+                + PuttyKeyPairResourceParser.PPK_FILE_SUFFIX;
+        this.encryptedFile = PASSWORD.replace(' ', '-') + "-AES-256-CBC"
+                + "-" + keyType + "-" + KeyPair.class.getSimpleName()
+                + PuttyKeyPairResourceParser.PPK_FILE_SUFFIX;
+    }
+
+    @Parameters(name = "{0}")
+    public static List<Object[]> parameters() {
+        return parameterize(PuttyKeyUtils.BY_KEY_TYPE.keySet());
+    }
+
+    @Test
+    public void testCanDecodePuttyKeyFile() throws IOException, 
GeneralSecurityException {
+        for (String resource : new String[]{regularFile, encryptedFile}) {
+            URL url = getClass().getResource(resource);
+            if (GenericUtils.isSameReference(regularFile, resource)) {
+                assertNotNull("Missing test resource: " + resource, url);
+            } else {
+                if (url == null) {
+                    outputDebugMessage("Skip non-existing encrypted file: %s", 
resource);
+                    continue;
+                }
+            }
+
+            List<String> lines = IoUtils.readAllLines(url);
+            assertTrue(resource + " - can extract key pair", 
parser.canExtractKeyPairs(resource, lines));
+
+            for (PuttyKeyPairResourceParser<?, ?> other : 
PuttyKeyUtils.BY_KEY_TYPE.values()) {
+                if (parser == other) {
+                    continue;
+                }
+
+                assertFalse(other.getClass().getSimpleName() + "/" + resource 
+ " - unexpected extraction capability",
+                        other.canExtractKeyPairs(resource, lines));
+            }
+        }
+    }
+
+    @Test
+    public void testDecodePuttyKeyFile() throws IOException, 
GeneralSecurityException {
+        URL url = getClass().getResource(regularFile);
+        assertNotNull("Missing test resource: " + regularFile, url);
+
+        Collection<KeyPair> keys = parser.loadKeyPairs(url, null);
+        assertEquals("Mismatched loaded keys count from " + regularFile, 1, 
GenericUtils.size(keys));
+        assertLoadedKeyPair(regularFile, keys.iterator().next());
+    }
+
+    @Test
+    public void testDecodeEncryptedPuttyKeyFile() throws IOException, 
GeneralSecurityException {
+        Assume.assumeTrue(BuiltinCiphers.aes256cbc.getTransformation() + " 
N/A", BuiltinCiphers.aes256cbc.isSupported());
+        URL url = getClass().getResource(encryptedFile);
+        Assume.assumeTrue("Skip non-existent encrypted file: " + 
encryptedFile, url != null);
+        assertNotNull("Missing test resource: " + encryptedFile, url);
+
+        Collection<KeyPair> keys = parser.loadKeyPairs(url, r -> PASSWORD);
+        assertEquals("Mismatched loaded keys count from " + encryptedFile, 1, 
GenericUtils.size(keys));
+
+        assertLoadedKeyPair(encryptedFile, keys.iterator().next());
+    }
+
+    private void assertLoadedKeyPair(String prefix, KeyPair kp) throws 
GeneralSecurityException {
+        assertNotNull(prefix + ": no key pair loaded", kp);
+
+        PublicKey pubKey = kp.getPublic();
+        assertNotNull(prefix + ": no public key loaded", pubKey);
+        assertEquals(prefix + ": mismatched public key type", keyType, 
KeyUtils.getKeyType(pubKey));
+
+        PrivateKey prvKey = kp.getPrivate();
+        assertNotNull(prefix + ": no private key loaded", prvKey);
+        assertEquals(prefix + ": mismatched private key type", keyType, 
KeyUtils.getKeyType(prvKey));
+
+        @SuppressWarnings("rawtypes")
+        PrivateKeyEntryDecoder decoder =
+            OpenSSHKeyPairResourceParser.getPrivateKeyEntryDecoder(prvKey);
+        assertNotNull("No private key decoder", decoder);
+
+        if (decoder.isPublicKeyRecoverySupported()) {
+            @SuppressWarnings("unchecked")
+            PublicKey recKey = decoder.recoverPublicKey(prvKey);
+            assertKeyEquals("Mismatched recovered public key", pubKey, recKey);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/test/resources/.gitignore
----------------------------------------------------------------------
diff --git a/sshd-putty/src/test/resources/.gitignore 
b/sshd-putty/src/test/resources/.gitignore
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/sshd-putty/src/test/resources/log4j.properties 
b/sshd-putty/src/test/resources/log4j.properties
new file mode 100644
index 0000000..351467b
--- /dev/null
+++ b/sshd-putty/src/test/resources/log4j.properties
@@ -0,0 +1,38 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+#
+
+#
+# The logging properties used during tests..
+#
+log4j.rootLogger=INFO, stdout, logfile
+#log4j.logger.org.apache.sshd=TRACE
+#log4j.logger.org.apache.sshd.common.channel.Window=DEBUG
+
+# CONSOLE appender
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} 
- %m%n
+
+# File appender
+log4j.appender.logfile=org.apache.log4j.FileAppender
+log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
+log4j.appender.logfile.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} 
- %m%n
+log4j.appender.logfile.file=target/sshd-putty-tests.log
+log4j.appender.logfile.append=true

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp256-KeyPair.ppk
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp256-KeyPair.ppk
 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp256-KeyPair.ppk
new file mode 100644
index 0000000..509538a
--- /dev/null
+++ 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp256-KeyPair.ppk
@@ -0,0 +1,10 @@
+PuTTY-User-Key-File-2: ecdsa-sha2-nistp256
+Encryption: none
+Comment: ecdsa-key-20170917
+Public-Lines: 3
+AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM99zj2+E6AN
+xMZ/2SKFP/fAvPfUJUdsgJyn4g7nf36vNpoaRyq1FyHLxyT34AgTl1n3DwcaBXXC
+O5pCv6xFwYk=
+Private-Lines: 1
+AAAAIQDdmu/Dr68r6a0PNbQUN1bX+zS6J5jFsOlEAx8sR73Tuw==
+Private-MAC: 012e0d61593a431ae84beb6216dd29e4b203c1c0

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp384-KeyPair.ppk
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp384-KeyPair.ppk
 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp384-KeyPair.ppk
new file mode 100644
index 0000000..238261c
--- /dev/null
+++ 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp384-KeyPair.ppk
@@ -0,0 +1,11 @@
+PuTTY-User-Key-File-2: ecdsa-sha2-nistp384
+Encryption: none
+Comment: ecdsa-key-20170917
+Public-Lines: 3
+AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBNHjIMrdMfXw
+CUqBAhkZw0vXB+qypkiTcL1CmcopmPrKvGHFieFmedeCQotjwJkoAAeb5isZNOXy
+h+7TnHGNrE/pZkHuNwACilpOt659hbhR2OGHX0jdpb8y4RVkuPQssg==
+Private-Lines: 2
+AAAAMHNGt3UPG3evJVl1GRoXXnqTafWLDQdWA2A1tXi8oRW0hhHMRe9/v0SCGL7S
+nL3asg==
+Private-MAC: 6fb6e93559ecacfa468aa5ff9776e4d4283db5ba

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp521-KeyPair.ppk
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp521-KeyPair.ppk
 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp521-KeyPair.ppk
new file mode 100644
index 0000000..f60a78e
--- /dev/null
+++ 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp521-KeyPair.ppk
@@ -0,0 +1,12 @@
+PuTTY-User-Key-File-2: ecdsa-sha2-nistp521
+Encryption: none
+Comment: ecdsa-key-20170917
+Public-Lines: 4
+AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBADGM237T9rT
+zE++sOFDN0VWfYfojlQ8dYP82OlgA24Yh0ZpOsezBBiHtHfMHl9tWHmch1YKmH7B
+lOfqbOgcIhz9cwA2V7Nu3IUGqxZT18LOXEpcdyDSphJ6jsy1urqBLrOz4DF6Udyr
+rFV4OQELovf8YdUsM91YPfe1DfnSRi1I5v20uA==
+Private-Lines: 2
+AAAAQgE28iZoHARx+2VzL7Y45FaY44TngX2b4StlC8wOlYF7NY/ba+Pt2RT/WcNL
+ytmLdj5QeV/fFJ9x8i00mTU6KCF2AA==
+Private-MAC: 7379e9986066087dff9339d2b0b968c2b31f45c7

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-dss-KeyPair.ppk
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-dss-KeyPair.ppk
 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-dss-KeyPair.ppk
new file mode 100644
index 0000000..59a8fac
--- /dev/null
+++ 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-dss-KeyPair.ppk
@@ -0,0 +1,17 @@
+PuTTY-User-Key-File-2: ssh-dss
+Encryption: none
+Comment: dsa-key-20130709
+Public-Lines: 10
+AAAAB3NzaC1kc3MAAACBAMg/IxsG5BxnF5gM7IKqqR0rftxZC+n5GlbO+J4H+iIb
+/KR8NBehkxG3CrBZMF96M2K1sEGYLob+3k4r71oWaPul8n5rt9kpd+JSq4iD2ygO
+yg6Kd1/YDBHoxneizy6I/bGsLwhAAKWcRNrXmYVKGzhrhvZWN12AJDq2mGdj3szL
+AAAAFQD7a2MltdUSF7FU3//SpW4WGjZbeQAAAIBf0nNsfKQL/TEMo7IpTrEMg5V0
+RnSigCX0+yUERS42GW/ZeCZBJw7oL2XZbuBtu63vMjDgVpnb92BdrcPgjJ7EFW6D
+lcyeuywStmg1ygXmDR2AQCxv0eX2CQgrdUczmRa155SDVUTvTQlO1IyKx0vwKAh1
+H7E3yJUfkTAJstbGYQAAAIEAtv+cdRfNevYFkp55jVqazc8zRLvfb64jzgc5oSJV
+c64kFs4yx+abYpGX9WxNxDlG6g2WiY8voDBB0YnUJsn0kVRjBKX9OceROxrfT4K4
+dVbQZsdt+SLaXWL4lGJFrFZL3LZqvySvq6xfhJfakQDDivW4hUOhFPXPHrE5/Ia3
+T7A=
+Private-Lines: 1
+AAAAFQCE6flGnmVCAbzo9YsbdJWBnxMnBA==
+Private-MAC: 6ace0a5e5bf23649c1375e91dcd71d1def6c6aa1

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-ed25519-KeyPair.ppk
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-ed25519-KeyPair.ppk
 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-ed25519-KeyPair.ppk
new file mode 100644
index 0000000..614ac69
--- /dev/null
+++ 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-ed25519-KeyPair.ppk
@@ -0,0 +1,9 @@
+PuTTY-User-Key-File-2: ssh-ed25519
+Encryption: none
+Comment: ed25519-key-20170917
+Public-Lines: 2
+AAAAC3NzaC1lZDI1NTE5AAAAIN7fuKSIM5TbAX/1I1Ts3tfyo5eEs7JpmKsegHs/
+9fIi
+Private-Lines: 1
+AAAAIADKJJPxsUp7JXLzm1zwk8UswW/lkiwPJ73CbqGvalgP
+Private-MAC: 28a22234152feaf1d9a6a10ca0ae3a51b5e6dd52

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-rsa-KeyPair.ppk
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-rsa-KeyPair.ppk
 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-rsa-KeyPair.ppk
new file mode 100644
index 0000000..da2868e
--- /dev/null
+++ 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-rsa-KeyPair.ppk
@@ -0,0 +1,18 @@
+PuTTY-User-Key-File-2: ssh-rsa
+Encryption: none
+Comment: rsa-key-20130709
+Public-Lines: 4
+AAAAB3NzaC1yc2EAAAABJQAAAIBLSj7+SllQdWjkD8EN4sA/fUv/jhc+ssGmCYx3
+uoiPMxjKH3xUPWu4zxJzhdlgFy4gchzjU51fDS4Oel6xGoWbGKGe4ZLQdE/t8N8l
+jAfOm/5lGp5tFhHs9UHoSm/h3RsErWNjKPjTGIlID35IcOXVhfhp9fX0RU6y/ZBI
+PhM20w==
+Private-Lines: 8
+AAAAgBx89T2fl2qNSkh0qemUEWQhkmCyTfwMSUW+bIBUawXATpGrDHLmztBOWgIy
+pUb0A52S9iyAgLwugCEnYhl/qCxvoARH7ZyTdYAL4KjJDySxVuqeo/ZhLscYcMAz
+MOyn8g5cR4dRgEwJ1/pRuK8r4+Z96zJG4NlxlHsUjHuj7t1dAAAAQQCTrj48XKIX
+M3dxWLSsSXbUCOpmAOTviuz9LD0H1ik7a6ebr0P6GTl9z7iscBgzdjBIHMFcdvar
+ophUJ5iRanCvAAAAQQCCg1VU1H5FHMipRvvw8b/zRqDsx6GTZs03ffhyKrTl1Dcd
+0oKy5/U3kQwdXPOSlVZeyX8nUVE2o7DOh7INsX0dAAAAQHkPjxivrN0SQuVAx+tK
+uRJ8vGL7sBOZ9gdTS25T3BVEkhRt37aDcshrodzDCzd515cwhmbLSsOsgyxcTwcX
+7SA=
+Private-MAC: 2416438f1a7ebdd33d519f6102d843b5f2c565d4

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp256-KeyPair.ppk
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp256-KeyPair.ppk
 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp256-KeyPair.ppk
new file mode 100644
index 0000000..4c601c7
--- /dev/null
+++ 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp256-KeyPair.ppk
@@ -0,0 +1,10 @@
+PuTTY-User-Key-File-2: ecdsa-sha2-nistp256
+Encryption: aes256-cbc
+Comment: ecdsa-key-20170917
+Public-Lines: 3
+AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM99zj2+E6AN
+xMZ/2SKFP/fAvPfUJUdsgJyn4g7nf36vNpoaRyq1FyHLxyT34AgTl1n3DwcaBXXC
+O5pCv6xFwYk=
+Private-Lines: 1
+/8MdniIqAaST5t3/bRx4mFdFxqN8jIwI0Hh7VTy8IV143j+PktgGIoHsUwTiEujQ
+Private-MAC: be4b37d4b65ad09e6890534a2ba355599da796c6

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp384-KeyPair.ppk
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp384-KeyPair.ppk
 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp384-KeyPair.ppk
new file mode 100644
index 0000000..f57f5fd
--- /dev/null
+++ 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp384-KeyPair.ppk
@@ -0,0 +1,11 @@
+PuTTY-User-Key-File-2: ecdsa-sha2-nistp384
+Encryption: aes256-cbc
+Comment: ecdsa-key-20170917
+Public-Lines: 3
+AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBNHjIMrdMfXw
+CUqBAhkZw0vXB+qypkiTcL1CmcopmPrKvGHFieFmedeCQotjwJkoAAeb5isZNOXy
+h+7TnHGNrE/pZkHuNwACilpOt659hbhR2OGHX0jdpb8y4RVkuPQssg==
+Private-Lines: 2
+MOgJnSZ8ZqGHFVtQvYKpOyTGWjMVIjIOMIUwhbxBuTiQ7WEyNPn9jjTsSwXtJxrG
+UI6NGeIqZ41P2e8JINhMIg==
+Private-MAC: 5ec40946270150ddfca35cce61f4265d7bfe7b7f

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp521-KeyPair.ppk
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp521-KeyPair.ppk
 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp521-KeyPair.ppk
new file mode 100644
index 0000000..97077fd
--- /dev/null
+++ 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp521-KeyPair.ppk
@@ -0,0 +1,12 @@
+PuTTY-User-Key-File-2: ecdsa-sha2-nistp521
+Encryption: aes256-cbc
+Comment: ecdsa-key-20170917
+Public-Lines: 4
+AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBADGM237T9rT
+zE++sOFDN0VWfYfojlQ8dYP82OlgA24Yh0ZpOsezBBiHtHfMHl9tWHmch1YKmH7B
+lOfqbOgcIhz9cwA2V7Nu3IUGqxZT18LOXEpcdyDSphJ6jsy1urqBLrOz4DF6Udyr
+rFV4OQELovf8YdUsM91YPfe1DfnSRi1I5v20uA==
+Private-Lines: 2
++44AQO4aflPquBZbdB3UtdLuXuHV2u1YoghxYXPFGdhskMt+XjJhUlrOHNX8rmgR
+E9nni474zGw9ni/3LIZwMILQI/xTfiQm3t6nKFV8nyI=
+Private-MAC: 99c25e348a84de4876163758ad13b2ad1dc43629

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-dss-KeyPair.ppk
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-dss-KeyPair.ppk
 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-dss-KeyPair.ppk
new file mode 100644
index 0000000..9da31f1
--- /dev/null
+++ 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-dss-KeyPair.ppk
@@ -0,0 +1,17 @@
+PuTTY-User-Key-File-2: ssh-dss
+Encryption: aes256-cbc
+Comment: dsa-key-20130909
+Public-Lines: 10
+AAAAB3NzaC1kc3MAAACBALVdprWfZ7+FiITCILnDkeMZ2ntkV2WjW5RcyiQvJvBO
+jCNiVtK87xATEOfBb20YvNZ/CibBjGS1TL5TBqRV5XleucPHMJZ5rXdJ2FH5oZnL
+kna3Et+L1/O/GQMmp2vfSFrO3n3+mI1Jozx3FoQO8jr1zIerJ5Mc4LKqsIQB9hvR
+AAAAFQD+z1y1/4ll4ax3rri8mkYgGDhqIQAAAIBVU4VJ7V7GoEQJ5WBMbpDEcLIZ
+KUgSHsJMQzWnLOi/DcsPjVMDX6FWGPLtrjd7fgInlPMCC/SPAhXdaXMvHZSkvBHV
+DfNjpsDgsxBnK1FKqRGtD49rETFGDl92EOsyBhv+9ymdOPX6R0hCqS+ulZheQPXI
+iHXdIvQK2Ev5Dy3xNgAAAIA8qhumHZcKss+Puuw+mY5J5Qt7Omv16MuDsYiVqrBq
+1V2C9gutx3Tu+n5QYi0xPlkkP/knMtkUZS+Wt3Dr8zPcEzNBc/Tm2EdYp11jZNx4
+4PM4ing+aCU5oGcg/7RS5CrY5Fn/rvgHqK22XiC8/U55iti44bWKvI6HCejExeZX
+iA==
+Private-Lines: 1
+64IdcIX48CNGjhcxsVN0vSNpT7S72e3FVdQ3t4ENAvI=
+Private-MAC: 8e62b44b5c080965e361936520be4feaa50285b1

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-ed25519-KeyPair.ppk
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-ed25519-KeyPair.ppk
 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-ed25519-KeyPair.ppk
new file mode 100644
index 0000000..668ef1e
--- /dev/null
+++ 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-ed25519-KeyPair.ppk
@@ -0,0 +1,9 @@
+PuTTY-User-Key-File-2: ssh-ed25519
+Encryption: aes256-cbc
+Comment: ed25519-key-20170917
+Public-Lines: 2
+AAAAC3NzaC1lZDI1NTE5AAAAIN7fuKSIM5TbAX/1I1Ts3tfyo5eEs7JpmKsegHs/
+9fIi
+Private-Lines: 1
+0cPG5BR80jQcJmHKs6IjpHS3R4/CTnudnJB4BcjaqKlRk0l603GVMDzTxkaICCb8
+Private-MAC: 381cff136b2516331ff4511cf382533fc14f0aeb

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-rsa-KeyPair.ppk
----------------------------------------------------------------------
diff --git 
a/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-rsa-KeyPair.ppk
 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-rsa-KeyPair.ppk
new file mode 100644
index 0000000..2a11d04
--- /dev/null
+++ 
b/sshd-putty/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-rsa-KeyPair.ppk
@@ -0,0 +1,18 @@
+PuTTY-User-Key-File-2: ssh-rsa
+Encryption: aes256-cbc
+Comment: rsa-key-20130909
+Public-Lines: 4
+AAAAB3NzaC1yc2EAAAABJQAAAIEAhY5eZJrX0a3+rtEZCq0nu2zvAHp16nk93jhi
+p7c9tTDlGm9QEAgqzmuilEeUQ4BssxAvhCFEo/7Qbg4M7PwcA5cFkjXE4gj0YDJM
+ay7l2mb5aIoS/hACgNz54p/w/UgfQC1Vygt6QtvXXAW8Lh/YCN4Zw4ViROUhoYuy
+3K5SBYs=
+Private-Lines: 8
+mqcGPnrv9d1tYkJZSGaCy5REslPZ2xh8m7qAbN+bD1m7iQ77pLxlKyzs82rbRaC9
+KSnKwsbFl7o92NT+9yYKJ7ehXyWyrUXkn9KcPk7MzNVwMuWVDXwvHodGLCyVCLYq
+PNipvg2USHvnCjnnvtMysBRNJiHTMOaf/gSZLyaEuznYo3FEClMPzggY9b2nrxnV
+O1ttk1FJatkRflwFjn3A/R/GpowmBnkDyCkVlTvR+uBAg8iIy1Vzj5zIV9zmzfgx
+DxPot+Y81y+Xe3ohVh2s1FVvLw+KQbYbCQam5j0V/dTQ+oVWjCJBlibD3aVTGK0M
+Jswz8wPwXFo5N0yX/6ZTrshbvTzoO1bg0+HUu581ZSAeqttk9C1RLmWFS8YDm0Hn
+GhDXrjuAvKJ3cjeVJsumgVw45NYGARuzV24TlHUtU+eze8Y/0NsPJXoCfVoYjTjb
+fjlMh9rYbRdyNHXwYTzwbw==
+Private-MAC: f4c50b3da0b73c34e8989411fc48c884c09e20a0

Reply via email to