You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2018/09/06 16:03:12 UTC
[02/51] [abbrv] mina-sshd git commit: [SSHD-842] Split Putty key
files support code to separate artifact
[SSHD-842] Split Putty key files support code to separate artifact
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/f60fcb0a
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/f60fcb0a
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/f60fcb0a
Branch: refs/heads/master
Commit: f60fcb0a547441f001b2a624022af0f73b80ce7f
Parents: 10de190
Author: Goldstein Lyor <ly...@cb4.com>
Authored: Thu Sep 6 10:43:46 2018 +0300
Committer: Lyor Goldstein <ly...@gmail.com>
Committed: Thu Sep 6 19:07:54 2018 +0300
----------------------------------------------------------------------
README.md | 44 +++-
assembly/pom.xml | 5 +
pom.xml | 1 +
sshd-cli/pom.xml | 5 +
.../loader/putty/AbstractPuttyKeyDecoder.java | 218 -------------------
.../keys/loader/putty/DSSPuttyKeyDecoder.java | 65 ------
.../keys/loader/putty/ECDSAPuttyKeyDecoder.java | 98 ---------
.../keys/loader/putty/EdDSAPuttyKeyDecoder.java | 68 ------
.../putty/PuttyKeyPairResourceParser.java | 200 -----------------
.../keys/loader/putty/PuttyKeyReader.java | 75 -------
.../config/keys/loader/putty/PuttyKeyUtils.java | 67 ------
.../keys/loader/putty/RSAPuttyKeyDecoder.java | 72 ------
.../keys/loader/putty/PuttyKeyUtilsTest.java | 153 -------------
...KeyUtilsTest-ecdsa-sha2-nistp256-KeyPair.ppk | 10 -
...KeyUtilsTest-ecdsa-sha2-nistp384-KeyPair.ppk | 11 -
...KeyUtilsTest-ecdsa-sha2-nistp521-KeyPair.ppk | 12 -
.../putty/PuttyKeyUtilsTest-ssh-dss-KeyPair.ppk | 17 --
.../PuttyKeyUtilsTest-ssh-ed25519-KeyPair.ppk | 9 -
.../putty/PuttyKeyUtilsTest-ssh-rsa-KeyPair.ppk | 18 --
...-AES-256-CBC-ecdsa-sha2-nistp256-KeyPair.ppk | 10 -
...-AES-256-CBC-ecdsa-sha2-nistp384-KeyPair.ppk | 11 -
...-AES-256-CBC-ecdsa-sha2-nistp521-KeyPair.ppk | 12 -
...t-passphrase-AES-256-CBC-ssh-dss-KeyPair.ppk | 17 --
...ssphrase-AES-256-CBC-ssh-ed25519-KeyPair.ppk | 9 -
...t-passphrase-AES-256-CBC-ssh-rsa-KeyPair.ppk | 18 --
sshd-putty/pom.xml | 107 +++++++++
.../loader/putty/AbstractPuttyKeyDecoder.java | 218 +++++++++++++++++++
.../keys/loader/putty/DSSPuttyKeyDecoder.java | 65 ++++++
.../keys/loader/putty/ECDSAPuttyKeyDecoder.java | 98 +++++++++
.../keys/loader/putty/EdDSAPuttyKeyDecoder.java | 68 ++++++
.../putty/PuttyKeyPairResourceParser.java | 200 +++++++++++++++++
.../keys/loader/putty/PuttyKeyReader.java | 75 +++++++
.../config/keys/loader/putty/PuttyKeyUtils.java | 67 ++++++
.../keys/loader/putty/RSAPuttyKeyDecoder.java | 72 ++++++
sshd-putty/src/main/resources/.gitignore | 0
.../keys/loader/putty/PuttyKeyUtilsTest.java | 153 +++++++++++++
sshd-putty/src/test/resources/.gitignore | 0
sshd-putty/src/test/resources/log4j.properties | 38 ++++
...KeyUtilsTest-ecdsa-sha2-nistp256-KeyPair.ppk | 10 +
...KeyUtilsTest-ecdsa-sha2-nistp384-KeyPair.ppk | 11 +
...KeyUtilsTest-ecdsa-sha2-nistp521-KeyPair.ppk | 12 +
.../putty/PuttyKeyUtilsTest-ssh-dss-KeyPair.ppk | 17 ++
.../PuttyKeyUtilsTest-ssh-ed25519-KeyPair.ppk | 9 +
.../putty/PuttyKeyUtilsTest-ssh-rsa-KeyPair.ppk | 18 ++
...-AES-256-CBC-ecdsa-sha2-nistp256-KeyPair.ppk | 10 +
...-AES-256-CBC-ecdsa-sha2-nistp384-KeyPair.ppk | 11 +
...-AES-256-CBC-ecdsa-sha2-nistp521-KeyPair.ppk | 12 +
...t-passphrase-AES-256-CBC-ssh-dss-KeyPair.ppk | 17 ++
...ssphrase-AES-256-CBC-ssh-ed25519-KeyPair.ppk | 9 +
...t-passphrase-AES-256-CBC-ssh-rsa-KeyPair.ppk | 18 ++
50 files changed, 1366 insertions(+), 1174 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index cad3ea8..4fb0f17 100644
--- a/README.md
+++ b/README.md
@@ -1578,13 +1578,49 @@ The code contains [support for "wrapper" protocols](https://issues.apache.org/ji
* `SshServer/ServerSession#setServerProxyAcceptor` - sets a proxy that intercept the 1st incoming packet before being processed by the server
-## Useful extra components in _sshd-contrib_
+## Configuration/data files parsing support
+
+Most of the configuration data files parsing support resides in the _sshd-common_ artfiact:
+
+```xml
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-common</artifactId>
+ <version>...same version as the rest of the artifacts...</version>
+ </dependency>
+```
+
+The code contains support for parsing the [_authorized_keys_](http://man.openbsd.org/sshd.8#AUTHORIZED_KEYS_FILE_FORMAT),
+[_known\_hosts_](http://www.manpagez.com/man/8/sshd/), [_ssh\_config_, _sshd\_config_](https://www.freebsd.org/cgi/man.cgi?query=ssh_config&sektion=5),
+and [_~/config_](http://www.gsp.com/cgi-bin/man.cgi?topic=ssh_config) files. The code resides in the _sshd-common_ artifact - specifically
+the `KeyUtils#getPublicKeyEntryDecoder`, `AuthorizedKeyEntry#readAuthorizedKeys`, `KnownHostEntry#readKnownHostEntries`
+and `HostConfigEntry#readHostConfigEntries`.
+
+### PEM/OpenSSH
-* PUTTY key file(s) readers - see `org.apache.sshd.common.config.keys.loader.putty` package - specifically `PuttyKeyUtils#DEFAULT_INSTANCE KeyPairResourceParser`.
+The common code contains built-in support for parsing PEM and/or _OpenSSH_ formatted key files and using them for authentication purposes.
+As mentioned previously, it can leverage _Bouncycastle_ if available, but can do most of the work without it as well. For _ed25519_ support,
+one must provide the _eddsa_ artifact dependency.
+### [PUTTY](https://www.putty.org/)
+
+The code contains built-in support for parsing PUTTY key files (usually _.ppk_) and using them same as SSH ones as key-pair
+providers for autentication purposes. The PUTTY key file(s) readers are contained in the `org.apache.sshd.common.config.keys.loader.putty`
+package (specifically `PuttyKeyUtils#DEFAULT_INSTANCE KeyPairResourceParser`) of the _sshd-putty_ artifact. **Note:** the artifact should
+be included as an extra dependency:
+
+```xml
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-putty</artifactId>
+ <version>...same version as the rest of the artifacts...</version>
+ </dependency>
+```
+
+## Useful extra components in _sshd-contrib_
-* `InteractivePasswordIdentityProvider` - helps implement a `PasswordIdentityProvider` by delegating calls to `UserInteraction#getUpdatedPassword`.
-The way to use it would be as follows:
+* `InteractivePasswordIdentityProvider` - helps implement a `PasswordIdentityProvider` by delegating calls
+to `UserInteraction#getUpdatedPassword`. The way to use it would be as follows:
```java
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/assembly/pom.xml
----------------------------------------------------------------------
diff --git a/assembly/pom.xml b/assembly/pom.xml
index 93011a8..58f20a0 100644
--- a/assembly/pom.xml
+++ b/assembly/pom.xml
@@ -43,6 +43,11 @@
</dependency>
<dependency>
<groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-putty</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>${project.version}</version>
</dependency>
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index a684d78..46d068e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1136,6 +1136,7 @@
<modules>
<module>sshd-common</module>
+ <module>sshd-putty</module>
<module>sshd-core</module>
<module>sshd-mina</module>
<module>sshd-netty</module>
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-cli/pom.xml
----------------------------------------------------------------------
diff --git a/sshd-cli/pom.xml b/sshd-cli/pom.xml
index 3babf6b..7b2c33a 100644
--- a/sshd-cli/pom.xml
+++ b/sshd-cli/pom.xml
@@ -52,6 +52,11 @@
<artifactId>sshd-sftp</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-putty</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<!-- Test dependencies -->
<dependency>
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/AbstractPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/AbstractPuttyKeyDecoder.java b/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/AbstractPuttyKeyDecoder.java
deleted file mode 100644
index d2428e2..0000000
--- a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/AbstractPuttyKeyDecoder.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * 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.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StreamCorruptedException;
-import java.security.GeneralSecurityException;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.util.Base64;
-import java.util.Base64.Decoder;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.sshd.common.config.keys.FilePasswordProvider;
-import org.apache.sshd.common.config.keys.impl.AbstractIdentityResourceLoader;
-import org.apache.sshd.common.config.keys.loader.KeyPairResourceParser;
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.ValidateUtils;
-
-/**
- * @param <PUB> Generic public key type
- * @param <PRV> Generic private key type
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public abstract class AbstractPuttyKeyDecoder<PUB extends PublicKey, PRV extends PrivateKey>
- extends AbstractIdentityResourceLoader<PUB, PRV>
- implements PuttyKeyPairResourceParser<PUB, PRV> {
- public static final String ENCRYPTION_HEADER = "Encryption";
-
- protected AbstractPuttyKeyDecoder(Class<PUB> pubType, Class<PRV> prvType, Collection<String> names) {
- super(pubType, prvType, names);
- }
-
- @Override
- public boolean canExtractKeyPairs(String resourceKey, List<String> lines)
- throws IOException, GeneralSecurityException {
- if (!PuttyKeyPairResourceParser.super.canExtractKeyPairs(resourceKey, lines)) {
- return false;
- }
-
- for (String l : lines) {
- l = GenericUtils.trimToEmpty(l);
- if (!l.startsWith(KEY_FILE_HEADER_PREFIX)) {
- continue;
- }
-
- int pos = l.indexOf(':');
- if ((pos <= 0) || (pos >= (l.length() - 1))) {
- return false;
- }
-
- Collection<String> supported = getSupportedTypeNames();
- String typeValue = l.substring(pos + 1).trim();
- return supported.contains(typeValue);
- }
-
- return false;
- }
-
- @Override
- public Collection<KeyPair> loadKeyPairs(
- String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
- throws IOException, GeneralSecurityException {
- List<String> pubLines = Collections.emptyList();
- List<String> prvLines = Collections.emptyList();
- String prvEncryption = null;
- for (int index = 0, numLines = lines.size(); index < numLines; index++) {
- String l = lines.get(index);
- l = GenericUtils.trimToEmpty(l);
- int pos = l.indexOf(':');
- if ((pos <= 0) || (pos >= (l.length() - 1))) {
- continue;
- }
-
- String hdrName = l.substring(0, pos).trim();
- String hdrValue = l.substring(pos + 1).trim();
- switch (hdrName) {
- case ENCRYPTION_HEADER:
- if (prvEncryption != null) {
- throw new StreamCorruptedException("Duplicate " + hdrName + " in" + resourceKey);
- }
- prvEncryption = hdrValue;
- break;
- case PUBLIC_LINES_HEADER:
- pubLines = extractDataLines(resourceKey, lines, index + 1, hdrName, hdrValue, pubLines);
- index += pubLines.size();
- break;
- case PRIVATE_LINES_HEADER:
- prvLines = extractDataLines(resourceKey, lines, index + 1, hdrName, hdrValue, prvLines);
- index += prvLines.size();
- break;
- default: // ignored
- }
- }
-
- return loadKeyPairs(resourceKey, pubLines, prvLines, prvEncryption, passwordProvider);
- }
-
- public static List<String> extractDataLines(
- String resourceKey, List<String> lines, int startIndex, String hdrName, String hdrValue, List<String> curLines)
- throws IOException {
- if (GenericUtils.size(curLines) > 0) {
- throw new StreamCorruptedException("Duplicate " + hdrName + " in " + resourceKey);
- }
-
- int numLines;
- try {
- numLines = Integer.parseInt(hdrValue);
- } catch (NumberFormatException e) {
- throw new StreamCorruptedException("Bad " + hdrName + " value (" + hdrValue + ") in " + resourceKey);
- }
-
- int endIndex = startIndex + numLines;
- int totalLines = lines.size();
- if (endIndex > totalLines) {
- throw new StreamCorruptedException("Excessive " + hdrName + " value (" + hdrValue + ") in " + resourceKey);
- }
-
- return lines.subList(startIndex, endIndex);
- }
-
- public Collection<KeyPair> loadKeyPairs(
- String resourceKey, List<String> pubLines, List<String> prvLines, String prvEncryption, FilePasswordProvider passwordProvider)
- throws IOException, GeneralSecurityException {
- return loadKeyPairs(resourceKey,
- KeyPairResourceParser.joinDataLines(pubLines), KeyPairResourceParser.joinDataLines(prvLines),
- prvEncryption, passwordProvider);
- }
-
- public Collection<KeyPair> loadKeyPairs(
- String resourceKey, String pubData, String prvData, String prvEncryption, FilePasswordProvider passwordProvider)
- throws IOException, GeneralSecurityException {
- Decoder b64Decoder = Base64.getDecoder();
- byte[] pubBytes = b64Decoder.decode(pubData);
- byte[] prvBytes = b64Decoder.decode(prvData);
- String password = null;
- if ((GenericUtils.length(prvEncryption) > 0)
- && (!NO_PRIVATE_KEY_ENCRYPTION_VALUE.equalsIgnoreCase(prvEncryption))) {
- password = passwordProvider.getPassword(resourceKey);
- }
-
- if (GenericUtils.isEmpty(prvEncryption)
- || NO_PRIVATE_KEY_ENCRYPTION_VALUE.equalsIgnoreCase(prvEncryption)
- || GenericUtils.isEmpty(password)) {
- return loadKeyPairs(resourceKey, pubBytes, prvBytes);
- }
-
- // format is "<cipher><bits>-<mode>" - e.g., "aes256-cbc"
- int pos = prvEncryption.indexOf('-');
- if (pos <= 0) {
- throw new StreamCorruptedException("Missing private key encryption mode in " + prvEncryption);
- }
-
- String mode = prvEncryption.substring(pos + 1).toUpperCase();
- String algName = null;
- int numBits = 0;
- for (int index = 0; index < pos; index++) {
- char ch = prvEncryption.charAt(index);
- if ((ch >= '0') && (ch <= '9')) {
- algName = prvEncryption.substring(0, index).toUpperCase();
- numBits = Integer.parseInt(prvEncryption.substring(index, pos));
- break;
- }
- }
-
- if (GenericUtils.isEmpty(algName) || (numBits <= 0)) {
- throw new StreamCorruptedException("Missing private key encryption algorithm details in " + prvEncryption);
- }
-
- prvBytes = PuttyKeyPairResourceParser.decodePrivateKeyBytes(prvBytes, algName, numBits, mode, password);
- return loadKeyPairs(resourceKey, pubBytes, prvBytes);
- }
-
- public Collection<KeyPair> loadKeyPairs(String resourceKey, byte[] pubData, byte[] prvData)
- throws IOException, GeneralSecurityException {
- ValidateUtils.checkNotNullAndNotEmpty(pubData, "No public key data in %s", resourceKey);
- ValidateUtils.checkNotNullAndNotEmpty(prvData, "No private key data in %s", resourceKey);
- try (InputStream pubStream = new ByteArrayInputStream(pubData);
- InputStream prvStream = new ByteArrayInputStream(prvData)) {
- return loadKeyPairs(resourceKey, pubStream, prvStream);
- }
- }
-
- public Collection<KeyPair> loadKeyPairs(String resourceKey, InputStream pubData, InputStream prvData)
- throws IOException, GeneralSecurityException {
- try (PuttyKeyReader pubReader =
- new PuttyKeyReader(ValidateUtils.checkNotNull(pubData, "No public key data in %s", resourceKey));
- PuttyKeyReader prvReader =
- new PuttyKeyReader(ValidateUtils.checkNotNull(prvData, "No private key data in %s", resourceKey))) {
- return loadKeyPairs(resourceKey, pubReader, prvReader);
- }
- }
-
- public abstract Collection<KeyPair> loadKeyPairs(String resourceKey, PuttyKeyReader pubReader, PuttyKeyReader prvReader)
- throws IOException, GeneralSecurityException;
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/DSSPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/DSSPuttyKeyDecoder.java b/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/DSSPuttyKeyDecoder.java
deleted file mode 100644
index 366aead..0000000
--- a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/DSSPuttyKeyDecoder.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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:dev@mina.apache.org">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-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/ECDSAPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/ECDSAPuttyKeyDecoder.java b/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/ECDSAPuttyKeyDecoder.java
deleted file mode 100644
index a257ff8..0000000
--- a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/ECDSAPuttyKeyDecoder.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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:dev@mina.apache.org">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-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/EdDSAPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/EdDSAPuttyKeyDecoder.java b/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/EdDSAPuttyKeyDecoder.java
deleted file mode 100644
index f5980ab..0000000
--- a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/EdDSAPuttyKeyDecoder.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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:dev@mina.apache.org">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-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyPairResourceParser.java
----------------------------------------------------------------------
diff --git a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyPairResourceParser.java b/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyPairResourceParser.java
deleted file mode 100644
index 06443d9..0000000
--- a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyPairResourceParser.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * 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 ".ppk" 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:dev@mina.apache.org">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-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyReader.java
----------------------------------------------------------------------
diff --git a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyReader.java b/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyReader.java
deleted file mode 100644
index 4fb63d1..0000000
--- a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyReader.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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:dev@mina.apache.org">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-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtils.java
----------------------------------------------------------------------
diff --git a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtils.java b/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtils.java
deleted file mode 100644
index e750ace..0000000
--- a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtils.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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:dev@mina.apache.org">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-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java b/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
deleted file mode 100644
index 0a55d55..0000000
--- a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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:dev@mina.apache.org">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-contrib/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-contrib/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java b/sshd-contrib/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java
deleted file mode 100644
index 8b70f77..0000000
--- a/sshd-contrib/src/test/java/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * 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.BaseTestSupport;
-import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
-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:dev@mina.apache.org">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 BaseTestSupport {
- 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-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp256-KeyPair.ppk
----------------------------------------------------------------------
diff --git a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp256-KeyPair.ppk b/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp256-KeyPair.ppk
deleted file mode 100644
index 509538a..0000000
--- a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp256-KeyPair.ppk
+++ /dev/null
@@ -1,10 +0,0 @@
-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-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp384-KeyPair.ppk
----------------------------------------------------------------------
diff --git a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp384-KeyPair.ppk b/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp384-KeyPair.ppk
deleted file mode 100644
index 238261c..0000000
--- a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp384-KeyPair.ppk
+++ /dev/null
@@ -1,11 +0,0 @@
-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-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp521-KeyPair.ppk
----------------------------------------------------------------------
diff --git a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp521-KeyPair.ppk b/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp521-KeyPair.ppk
deleted file mode 100644
index f60a78e..0000000
--- a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ecdsa-sha2-nistp521-KeyPair.ppk
+++ /dev/null
@@ -1,12 +0,0 @@
-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-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-dss-KeyPair.ppk
----------------------------------------------------------------------
diff --git a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-dss-KeyPair.ppk b/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-dss-KeyPair.ppk
deleted file mode 100644
index 59a8fac..0000000
--- a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-dss-KeyPair.ppk
+++ /dev/null
@@ -1,17 +0,0 @@
-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-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-ed25519-KeyPair.ppk
----------------------------------------------------------------------
diff --git a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-ed25519-KeyPair.ppk b/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-ed25519-KeyPair.ppk
deleted file mode 100644
index 614ac69..0000000
--- a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-ed25519-KeyPair.ppk
+++ /dev/null
@@ -1,9 +0,0 @@
-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-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-rsa-KeyPair.ppk
----------------------------------------------------------------------
diff --git a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-rsa-KeyPair.ppk b/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-rsa-KeyPair.ppk
deleted file mode 100644
index da2868e..0000000
--- a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/PuttyKeyUtilsTest-ssh-rsa-KeyPair.ppk
+++ /dev/null
@@ -1,18 +0,0 @@
-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-contrib/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-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp256-KeyPair.ppk b/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp256-KeyPair.ppk
deleted file mode 100644
index 4c601c7..0000000
--- a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp256-KeyPair.ppk
+++ /dev/null
@@ -1,10 +0,0 @@
-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-contrib/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-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp384-KeyPair.ppk b/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp384-KeyPair.ppk
deleted file mode 100644
index f57f5fd..0000000
--- a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp384-KeyPair.ppk
+++ /dev/null
@@ -1,11 +0,0 @@
-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-contrib/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-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp521-KeyPair.ppk b/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp521-KeyPair.ppk
deleted file mode 100644
index 97077fd..0000000
--- a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ecdsa-sha2-nistp521-KeyPair.ppk
+++ /dev/null
@@ -1,12 +0,0 @@
-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-contrib/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-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-dss-KeyPair.ppk b/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-dss-KeyPair.ppk
deleted file mode 100644
index 9da31f1..0000000
--- a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-dss-KeyPair.ppk
+++ /dev/null
@@ -1,17 +0,0 @@
-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-contrib/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-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-ed25519-KeyPair.ppk b/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-ed25519-KeyPair.ppk
deleted file mode 100644
index 668ef1e..0000000
--- a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-ed25519-KeyPair.ppk
+++ /dev/null
@@ -1,9 +0,0 @@
-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-contrib/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-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-rsa-KeyPair.ppk b/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-rsa-KeyPair.ppk
deleted file mode 100644
index 2a11d04..0000000
--- a/sshd-contrib/src/test/resources/org/apache/sshd/common/config/keys/loader/putty/super-secret-passphrase-AES-256-CBC-ssh-rsa-KeyPair.ppk
+++ /dev/null
@@ -1,18 +0,0 @@
-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
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f60fcb0a/sshd-putty/pom.xml
----------------------------------------------------------------------
diff --git a/sshd-putty/pom.xml b/sshd-putty/pom.xml
new file mode 100644
index 0000000..8e11385
--- /dev/null
+++ b/sshd-putty/pom.xml
@@ -0,0 +1,107 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+
+ <!--
+
+ 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.
+ -->
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd</artifactId>
+ <version>2.0.1-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <artifactId>sshd-putty</artifactId>
+ <name>Apache Mina SSHD :: Putty key files support utilities</name>
+ <packaging>jar</packaging>
+ <inceptionYear>2018</inceptionYear>
+
+ <properties>
+ <projectRoot>${project.basedir}/..</projectRoot>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcpg-jdk15on</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcpkix-jdk15on</artifactId>
+ <optional>true</optional>
+ </dependency>
+
+ <!-- For ed25519 support -->
+ <dependency>
+ <groupId>net.i2p.crypto</groupId>
+ <artifactId>eddsa</artifactId>
+ <optional>true</optional>
+ </dependency>
+
+ <!-- test dependencies -->
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-common</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <redirectTestOutputToFile>true</redirectTestOutputToFile>
+ <reportsDirectory>${project.build.directory}/surefire-reports-putty</reportsDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
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/AbstractPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/AbstractPuttyKeyDecoder.java b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/AbstractPuttyKeyDecoder.java
new file mode 100644
index 0000000..d2428e2
--- /dev/null
+++ b/sshd-putty/src/main/java/org/apache/sshd/common/config/keys/loader/putty/AbstractPuttyKeyDecoder.java
@@ -0,0 +1,218 @@
+/*
+ * 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.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StreamCorruptedException;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.Base64;
+import java.util.Base64.Decoder;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.sshd.common.config.keys.FilePasswordProvider;
+import org.apache.sshd.common.config.keys.impl.AbstractIdentityResourceLoader;
+import org.apache.sshd.common.config.keys.loader.KeyPairResourceParser;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
+
+/**
+ * @param <PUB> Generic public key type
+ * @param <PRV> Generic private key type
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class AbstractPuttyKeyDecoder<PUB extends PublicKey, PRV extends PrivateKey>
+ extends AbstractIdentityResourceLoader<PUB, PRV>
+ implements PuttyKeyPairResourceParser<PUB, PRV> {
+ public static final String ENCRYPTION_HEADER = "Encryption";
+
+ protected AbstractPuttyKeyDecoder(Class<PUB> pubType, Class<PRV> prvType, Collection<String> names) {
+ super(pubType, prvType, names);
+ }
+
+ @Override
+ public boolean canExtractKeyPairs(String resourceKey, List<String> lines)
+ throws IOException, GeneralSecurityException {
+ if (!PuttyKeyPairResourceParser.super.canExtractKeyPairs(resourceKey, lines)) {
+ return false;
+ }
+
+ for (String l : lines) {
+ l = GenericUtils.trimToEmpty(l);
+ if (!l.startsWith(KEY_FILE_HEADER_PREFIX)) {
+ continue;
+ }
+
+ int pos = l.indexOf(':');
+ if ((pos <= 0) || (pos >= (l.length() - 1))) {
+ return false;
+ }
+
+ Collection<String> supported = getSupportedTypeNames();
+ String typeValue = l.substring(pos + 1).trim();
+ return supported.contains(typeValue);
+ }
+
+ return false;
+ }
+
+ @Override
+ public Collection<KeyPair> loadKeyPairs(
+ String resourceKey, FilePasswordProvider passwordProvider, List<String> lines)
+ throws IOException, GeneralSecurityException {
+ List<String> pubLines = Collections.emptyList();
+ List<String> prvLines = Collections.emptyList();
+ String prvEncryption = null;
+ for (int index = 0, numLines = lines.size(); index < numLines; index++) {
+ String l = lines.get(index);
+ l = GenericUtils.trimToEmpty(l);
+ int pos = l.indexOf(':');
+ if ((pos <= 0) || (pos >= (l.length() - 1))) {
+ continue;
+ }
+
+ String hdrName = l.substring(0, pos).trim();
+ String hdrValue = l.substring(pos + 1).trim();
+ switch (hdrName) {
+ case ENCRYPTION_HEADER:
+ if (prvEncryption != null) {
+ throw new StreamCorruptedException("Duplicate " + hdrName + " in" + resourceKey);
+ }
+ prvEncryption = hdrValue;
+ break;
+ case PUBLIC_LINES_HEADER:
+ pubLines = extractDataLines(resourceKey, lines, index + 1, hdrName, hdrValue, pubLines);
+ index += pubLines.size();
+ break;
+ case PRIVATE_LINES_HEADER:
+ prvLines = extractDataLines(resourceKey, lines, index + 1, hdrName, hdrValue, prvLines);
+ index += prvLines.size();
+ break;
+ default: // ignored
+ }
+ }
+
+ return loadKeyPairs(resourceKey, pubLines, prvLines, prvEncryption, passwordProvider);
+ }
+
+ public static List<String> extractDataLines(
+ String resourceKey, List<String> lines, int startIndex, String hdrName, String hdrValue, List<String> curLines)
+ throws IOException {
+ if (GenericUtils.size(curLines) > 0) {
+ throw new StreamCorruptedException("Duplicate " + hdrName + " in " + resourceKey);
+ }
+
+ int numLines;
+ try {
+ numLines = Integer.parseInt(hdrValue);
+ } catch (NumberFormatException e) {
+ throw new StreamCorruptedException("Bad " + hdrName + " value (" + hdrValue + ") in " + resourceKey);
+ }
+
+ int endIndex = startIndex + numLines;
+ int totalLines = lines.size();
+ if (endIndex > totalLines) {
+ throw new StreamCorruptedException("Excessive " + hdrName + " value (" + hdrValue + ") in " + resourceKey);
+ }
+
+ return lines.subList(startIndex, endIndex);
+ }
+
+ public Collection<KeyPair> loadKeyPairs(
+ String resourceKey, List<String> pubLines, List<String> prvLines, String prvEncryption, FilePasswordProvider passwordProvider)
+ throws IOException, GeneralSecurityException {
+ return loadKeyPairs(resourceKey,
+ KeyPairResourceParser.joinDataLines(pubLines), KeyPairResourceParser.joinDataLines(prvLines),
+ prvEncryption, passwordProvider);
+ }
+
+ public Collection<KeyPair> loadKeyPairs(
+ String resourceKey, String pubData, String prvData, String prvEncryption, FilePasswordProvider passwordProvider)
+ throws IOException, GeneralSecurityException {
+ Decoder b64Decoder = Base64.getDecoder();
+ byte[] pubBytes = b64Decoder.decode(pubData);
+ byte[] prvBytes = b64Decoder.decode(prvData);
+ String password = null;
+ if ((GenericUtils.length(prvEncryption) > 0)
+ && (!NO_PRIVATE_KEY_ENCRYPTION_VALUE.equalsIgnoreCase(prvEncryption))) {
+ password = passwordProvider.getPassword(resourceKey);
+ }
+
+ if (GenericUtils.isEmpty(prvEncryption)
+ || NO_PRIVATE_KEY_ENCRYPTION_VALUE.equalsIgnoreCase(prvEncryption)
+ || GenericUtils.isEmpty(password)) {
+ return loadKeyPairs(resourceKey, pubBytes, prvBytes);
+ }
+
+ // format is "<cipher><bits>-<mode>" - e.g., "aes256-cbc"
+ int pos = prvEncryption.indexOf('-');
+ if (pos <= 0) {
+ throw new StreamCorruptedException("Missing private key encryption mode in " + prvEncryption);
+ }
+
+ String mode = prvEncryption.substring(pos + 1).toUpperCase();
+ String algName = null;
+ int numBits = 0;
+ for (int index = 0; index < pos; index++) {
+ char ch = prvEncryption.charAt(index);
+ if ((ch >= '0') && (ch <= '9')) {
+ algName = prvEncryption.substring(0, index).toUpperCase();
+ numBits = Integer.parseInt(prvEncryption.substring(index, pos));
+ break;
+ }
+ }
+
+ if (GenericUtils.isEmpty(algName) || (numBits <= 0)) {
+ throw new StreamCorruptedException("Missing private key encryption algorithm details in " + prvEncryption);
+ }
+
+ prvBytes = PuttyKeyPairResourceParser.decodePrivateKeyBytes(prvBytes, algName, numBits, mode, password);
+ return loadKeyPairs(resourceKey, pubBytes, prvBytes);
+ }
+
+ public Collection<KeyPair> loadKeyPairs(String resourceKey, byte[] pubData, byte[] prvData)
+ throws IOException, GeneralSecurityException {
+ ValidateUtils.checkNotNullAndNotEmpty(pubData, "No public key data in %s", resourceKey);
+ ValidateUtils.checkNotNullAndNotEmpty(prvData, "No private key data in %s", resourceKey);
+ try (InputStream pubStream = new ByteArrayInputStream(pubData);
+ InputStream prvStream = new ByteArrayInputStream(prvData)) {
+ return loadKeyPairs(resourceKey, pubStream, prvStream);
+ }
+ }
+
+ public Collection<KeyPair> loadKeyPairs(String resourceKey, InputStream pubData, InputStream prvData)
+ throws IOException, GeneralSecurityException {
+ try (PuttyKeyReader pubReader =
+ new PuttyKeyReader(ValidateUtils.checkNotNull(pubData, "No public key data in %s", resourceKey));
+ PuttyKeyReader prvReader =
+ new PuttyKeyReader(ValidateUtils.checkNotNull(prvData, "No private key data in %s", resourceKey))) {
+ return loadKeyPairs(resourceKey, pubReader, prvReader);
+ }
+ }
+
+ public abstract Collection<KeyPair> loadKeyPairs(String resourceKey, PuttyKeyReader pubReader, PuttyKeyReader prvReader)
+ throws IOException, GeneralSecurityException;
+}