http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractPrivateKeyEntryDecoder.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractPrivateKeyEntryDecoder.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractPrivateKeyEntryDecoder.java deleted file mode 100644 index 574412e..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractPrivateKeyEntryDecoder.java +++ /dev/null @@ -1,40 +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.impl; - -import java.security.PrivateKey; -import java.security.PublicKey; -import java.util.Collection; - -import org.apache.sshd.common.config.keys.PrivateKeyEntryDecoder; - -/** - * @param <PUB> Type of {@link PublicKey} - * @param <PRV> Type of {@link PrivateKey} - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public abstract class AbstractPrivateKeyEntryDecoder<PUB extends PublicKey, PRV extends PrivateKey> - extends AbstractKeyEntryResolver<PUB, PRV> - implements PrivateKeyEntryDecoder<PUB, PRV> { - protected AbstractPrivateKeyEntryDecoder(Class<PUB> pubType, Class<PRV> prvType, Collection<String> names) { - super(pubType, prvType, names); - } - -}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractPublicKeyEntryDecoder.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractPublicKeyEntryDecoder.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractPublicKeyEntryDecoder.java deleted file mode 100644 index 59cbf3a..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractPublicKeyEntryDecoder.java +++ /dev/null @@ -1,41 +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.impl; - -import java.security.PrivateKey; -import java.security.PublicKey; -import java.util.Collection; - -import org.apache.sshd.common.config.keys.PublicKeyEntryDecoder; - -/** - * Useful base class implementation for a decoder of an {@code OpenSSH} encoded key data - * - * @param <PUB> Type of {@link PublicKey} - * @param <PRV> Type of {@link PrivateKey} - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public abstract class AbstractPublicKeyEntryDecoder<PUB extends PublicKey, PRV extends PrivateKey> - extends AbstractKeyEntryResolver<PUB, PRV> - implements PublicKeyEntryDecoder<PUB, PRV> { - protected AbstractPublicKeyEntryDecoder(Class<PUB> pubType, Class<PRV> prvType, Collection<String> names) { - super(pubType, prvType, names); - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/DSSPublicKeyEntryDecoder.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/DSSPublicKeyEntryDecoder.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/DSSPublicKeyEntryDecoder.java deleted file mode 100644 index 464d2b0..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/DSSPublicKeyEntryDecoder.java +++ /dev/null @@ -1,119 +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.impl; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.math.BigInteger; -import java.security.GeneralSecurityException; -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.KeyPairGenerator; -import java.security.interfaces.DSAParams; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.DSAPublicKey; -import java.security.spec.DSAPrivateKeySpec; -import java.security.spec.DSAPublicKeySpec; -import java.security.spec.InvalidKeySpecException; -import java.util.Collections; -import java.util.Objects; - -import org.apache.sshd.common.config.keys.KeyEntryResolver; -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 DSSPublicKeyEntryDecoder extends AbstractPublicKeyEntryDecoder<DSAPublicKey, DSAPrivateKey> { - public static final DSSPublicKeyEntryDecoder INSTANCE = new DSSPublicKeyEntryDecoder(); - - public DSSPublicKeyEntryDecoder() { - super(DSAPublicKey.class, DSAPrivateKey.class, Collections.unmodifiableList(Collections.singletonList(KeyPairProvider.SSH_DSS))); - } - - @Override - public DSAPublicKey decodePublicKey(String keyType, InputStream keyData) throws IOException, GeneralSecurityException { - if (!KeyPairProvider.SSH_DSS.equals(keyType)) { // just in case we were invoked directly - throw new InvalidKeySpecException("Unexpected key type: " + keyType); - } - - BigInteger p = KeyEntryResolver.decodeBigInt(keyData); - BigInteger q = KeyEntryResolver.decodeBigInt(keyData); - BigInteger g = KeyEntryResolver.decodeBigInt(keyData); - BigInteger y = KeyEntryResolver.decodeBigInt(keyData); - - return generatePublicKey(new DSAPublicKeySpec(y, p, q, g)); - } - - @Override - public String encodePublicKey(OutputStream s, DSAPublicKey key) throws IOException { - Objects.requireNonNull(key, "No public key provided"); - - DSAParams keyParams = Objects.requireNonNull(key.getParams(), "No DSA params available"); - KeyEntryResolver.encodeString(s, KeyPairProvider.SSH_DSS); - KeyEntryResolver.encodeBigInt(s, keyParams.getP()); - KeyEntryResolver.encodeBigInt(s, keyParams.getQ()); - KeyEntryResolver.encodeBigInt(s, keyParams.getG()); - KeyEntryResolver.encodeBigInt(s, key.getY()); - - return KeyPairProvider.SSH_DSS; - } - - @Override - public DSAPublicKey clonePublicKey(DSAPublicKey key) throws GeneralSecurityException { - if (key == null) { - return null; - } - - DSAParams params = key.getParams(); - if (params == null) { - throw new InvalidKeyException("Missing parameters in key"); - } - - return generatePublicKey(new DSAPublicKeySpec(key.getY(), params.getP(), params.getQ(), params.getG())); - } - - @Override - public DSAPrivateKey clonePrivateKey(DSAPrivateKey key) throws GeneralSecurityException { - if (key == null) { - return null; - } - - DSAParams params = key.getParams(); - if (params == null) { - throw new InvalidKeyException("Missing parameters in key"); - } - - return generatePrivateKey(new DSAPrivateKeySpec(key.getX(), params.getP(), params.getQ(), params.getG())); - } - - @Override - public KeyPairGenerator getKeyPairGenerator() throws GeneralSecurityException { - return SecurityUtils.getKeyPairGenerator(KeyUtils.DSS_ALGORITHM); - } - - @Override - public KeyFactory getKeyFactoryInstance() throws GeneralSecurityException { - return SecurityUtils.getKeyFactory(KeyUtils.DSS_ALGORITHM); - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/ECDSAPublicKeyEntryDecoder.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/ECDSAPublicKeyEntryDecoder.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/ECDSAPublicKeyEntryDecoder.java deleted file mode 100644 index 397a007..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/ECDSAPublicKeyEntryDecoder.java +++ /dev/null @@ -1,178 +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.impl; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.GeneralSecurityException; -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.NoSuchProviderException; -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.Objects; - -import org.apache.sshd.common.cipher.ECCurves; -import org.apache.sshd.common.config.keys.KeyEntryResolver; -import org.apache.sshd.common.config.keys.KeyUtils; -import org.apache.sshd.common.util.buffer.BufferUtils; -import org.apache.sshd.common.util.security.SecurityUtils; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public class ECDSAPublicKeyEntryDecoder extends AbstractPublicKeyEntryDecoder<ECPublicKey, ECPrivateKey> { - public static final ECDSAPublicKeyEntryDecoder INSTANCE = new ECDSAPublicKeyEntryDecoder(); - - // see rfc5480 section 2.2 - public static final byte ECPOINT_UNCOMPRESSED_FORM_INDICATOR = 0x04; - public static final byte ECPOINT_COMPRESSED_VARIANT_2 = 0x02; - public static final byte ECPOINT_COMPRESSED_VARIANT_3 = 0x02; - - public ECDSAPublicKeyEntryDecoder() { - super(ECPublicKey.class, ECPrivateKey.class, ECCurves.KEY_TYPES); - } - - @Override - public ECPublicKey decodePublicKey(String keyType, InputStream keyData) throws IOException, GeneralSecurityException { - ECCurves curve = ECCurves.fromKeyType(keyType); - if (curve == null) { - throw new InvalidKeySpecException("Not an EC curve name: " + keyType); - } - - if (!SecurityUtils.isECCSupported()) { - throw new NoSuchProviderException("ECC not supported"); - } - - String keyCurveName = curve.getName(); - // see rfc5656 section 3.1 - String encCurveName = KeyEntryResolver.decodeString(keyData); - if (!keyCurveName.equals(encCurveName)) { - throw new InvalidKeySpecException("Mismatched key curve name (" + keyCurveName + ") vs. encoded one (" + encCurveName + ")"); - } - - byte[] octets = KeyEntryResolver.readRLEBytes(keyData); - ECPoint w; - try { - w = ECCurves.octetStringToEcPoint(octets); - if (w == null) { - throw new InvalidKeySpecException("No ECPoint generated for curve=" + keyCurveName - + " from octets=" + BufferUtils.toHex(':', octets)); - } - } catch (RuntimeException e) { - throw new InvalidKeySpecException("Failed (" + e.getClass().getSimpleName() + ")" - + " to generate ECPoint for curve=" + keyCurveName - + " from octets=" + BufferUtils.toHex(':', octets) - + ": " + e.getMessage()); - } - - ECParameterSpec paramSpec = curve.getParameters(); - return generatePublicKey(new ECPublicKeySpec(w, paramSpec)); - } - - @Override - public ECPublicKey clonePublicKey(ECPublicKey key) throws GeneralSecurityException { - if (!SecurityUtils.isECCSupported()) { - throw new NoSuchProviderException("ECC not supported"); - } - - if (key == null) { - return null; - } - - ECParameterSpec params = key.getParams(); - if (params == null) { - throw new InvalidKeyException("Missing parameters in key"); - } - - return generatePublicKey(new ECPublicKeySpec(key.getW(), params)); - } - - @Override - public ECPrivateKey clonePrivateKey(ECPrivateKey key) throws GeneralSecurityException { - if (!SecurityUtils.isECCSupported()) { - throw new NoSuchProviderException("ECC not supported"); - } - - if (key == null) { - return null; - } - - ECParameterSpec params = key.getParams(); - if (params == null) { - throw new InvalidKeyException("Missing parameters in key"); - } - - return generatePrivateKey(new ECPrivateKeySpec(key.getS(), params)); - } - - @Override - public String encodePublicKey(OutputStream s, ECPublicKey key) throws IOException { - Objects.requireNonNull(key, "No public key provided"); - - ECParameterSpec params = Objects.requireNonNull(key.getParams(), "No EC parameters available"); - ECCurves curve = Objects.requireNonNull(ECCurves.fromCurveParameters(params), "Cannot determine curve"); - String keyType = curve.getKeyType(); - String curveName = curve.getName(); - KeyEntryResolver.encodeString(s, keyType); - // see rfc5656 section 3.1 - KeyEntryResolver.encodeString(s, curveName); - ECCurves.ECPointCompression.UNCOMPRESSED.writeECPoint(s, curveName, key.getW()); - return keyType; - } - - @Override - public KeyFactory getKeyFactoryInstance() throws GeneralSecurityException { - if (SecurityUtils.isECCSupported()) { - return SecurityUtils.getKeyFactory(KeyUtils.EC_ALGORITHM); - } else { - throw new NoSuchProviderException("ECC not supported"); - } - } - - @Override - public KeyPair generateKeyPair(int keySize) throws GeneralSecurityException { - ECCurves curve = ECCurves.fromCurveSize(keySize); - if (curve == null) { - throw new InvalidKeySpecException("Unknown curve for key size=" + keySize); - } - - KeyPairGenerator gen = getKeyPairGenerator(); - gen.initialize(curve.getParameters()); - return gen.generateKeyPair(); - } - - @Override - public KeyPairGenerator getKeyPairGenerator() throws GeneralSecurityException { - if (SecurityUtils.isECCSupported()) { - return SecurityUtils.getKeyPairGenerator(KeyUtils.EC_ALGORITHM); - } else { - throw new NoSuchProviderException("ECC not supported"); - } - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/RSAPublicKeyDecoder.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/RSAPublicKeyDecoder.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/RSAPublicKeyDecoder.java deleted file mode 100644 index 4550815..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/RSAPublicKeyDecoder.java +++ /dev/null @@ -1,117 +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.impl; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.math.BigInteger; -import java.security.GeneralSecurityException; -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.KeyPairGenerator; -import java.security.interfaces.RSAPrivateCrtKey; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.RSAPrivateCrtKeySpec; -import java.security.spec.RSAPublicKeySpec; -import java.util.Collections; -import java.util.Objects; - -import org.apache.sshd.common.config.keys.KeyEntryResolver; -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 RSAPublicKeyDecoder extends AbstractPublicKeyEntryDecoder<RSAPublicKey, RSAPrivateKey> { - public static final RSAPublicKeyDecoder INSTANCE = new RSAPublicKeyDecoder(); - - public RSAPublicKeyDecoder() { - super(RSAPublicKey.class, RSAPrivateKey.class, Collections.unmodifiableList(Collections.singletonList(KeyPairProvider.SSH_RSA))); - } - - @Override - public RSAPublicKey decodePublicKey(String keyType, InputStream keyData) throws IOException, GeneralSecurityException { - if (!KeyPairProvider.SSH_RSA.equals(keyType)) { // just in case we were invoked directly - throw new InvalidKeySpecException("Unexpected key type: " + keyType); - } - - BigInteger e = KeyEntryResolver.decodeBigInt(keyData); - BigInteger n = KeyEntryResolver.decodeBigInt(keyData); - - return generatePublicKey(new RSAPublicKeySpec(n, e)); - } - - @Override - public String encodePublicKey(OutputStream s, RSAPublicKey key) throws IOException { - Objects.requireNonNull(key, "No public key provided"); - KeyEntryResolver.encodeString(s, KeyPairProvider.SSH_RSA); - KeyEntryResolver.encodeBigInt(s, key.getPublicExponent()); - KeyEntryResolver.encodeBigInt(s, key.getModulus()); - - return KeyPairProvider.SSH_RSA; - } - - @Override - public RSAPublicKey clonePublicKey(RSAPublicKey key) throws GeneralSecurityException { - if (key == null) { - return null; - } else { - return generatePublicKey(new RSAPublicKeySpec(key.getModulus(), key.getPublicExponent())); - } - } - - @Override - public RSAPrivateKey clonePrivateKey(RSAPrivateKey key) throws GeneralSecurityException { - if (key == null) { - return null; - } - - if (!(key instanceof RSAPrivateCrtKey)) { - throw new InvalidKeyException("Cannot clone a non-RSAPrivateCrtKey: " + key.getClass().getSimpleName()); - } - - RSAPrivateCrtKey rsaPrv = (RSAPrivateCrtKey) key; - return generatePrivateKey( - new RSAPrivateCrtKeySpec( - rsaPrv.getModulus(), - rsaPrv.getPublicExponent(), - rsaPrv.getPrivateExponent(), - rsaPrv.getPrimeP(), - rsaPrv.getPrimeQ(), - rsaPrv.getPrimeExponentP(), - rsaPrv.getPrimeExponentQ(), - rsaPrv.getCrtCoefficient())); - } - - @Override - public KeyPairGenerator getKeyPairGenerator() throws GeneralSecurityException { - return SecurityUtils.getKeyPairGenerator(KeyUtils.RSA_ALGORITHM); - } - - @Override - public KeyFactory getKeyFactoryInstance() throws GeneralSecurityException { - return SecurityUtils.getKeyFactory(KeyUtils.RSA_ALGORITHM); - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/AESPrivateKeyObfuscator.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/AESPrivateKeyObfuscator.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/AESPrivateKeyObfuscator.java deleted file mode 100644 index 4437945..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/AESPrivateKeyObfuscator.java +++ /dev/null @@ -1,110 +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; - -import java.security.GeneralSecurityException; -import java.security.Key; -import java.security.spec.InvalidKeySpecException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; - -import org.apache.sshd.common.util.security.SecurityUtils; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public class AESPrivateKeyObfuscator extends AbstractPrivateKeyObfuscator { - public static final String CIPHER_NAME = "AES"; - public static final AESPrivateKeyObfuscator INSTANCE = new AESPrivateKeyObfuscator(); - - public AESPrivateKeyObfuscator() { - super(CIPHER_NAME); - } - - @Override - public List<Integer> getSupportedKeySizes() { - return getAvailableKeyLengths(); - } - - @Override - public byte[] applyPrivateKeyCipher(byte[] bytes, PrivateKeyEncryptionContext encContext, boolean encryptIt) throws GeneralSecurityException { - int keyLength = resolveKeyLength(encContext); - byte[] keyValue = deriveEncryptionKey(encContext, keyLength / Byte.SIZE); - return applyPrivateKeyCipher(bytes, encContext, keyLength, keyValue, encryptIt); - } - - @Override - protected int resolveKeyLength(PrivateKeyEncryptionContext encContext) throws GeneralSecurityException { - String cipherType = encContext.getCipherType(); - try { - int keyLength = Integer.parseInt(cipherType); - List<Integer> sizes = getSupportedKeySizes(); - for (Integer s : sizes) { - if (s.intValue() == keyLength) { - return keyLength; - } - } - - throw new InvalidKeySpecException("Unknown " + getCipherName() + " key length: " + cipherType + " - supported: " + sizes); - } catch (NumberFormatException e) { - throw new InvalidKeySpecException("Bad " + getCipherName() + " key length (" + cipherType + "): " + e.getMessage(), e); - } - } - - /** - * @return A {@link List} of {@link Integer}s holding the available key - * lengths values (in bits) for the JVM. <B>Note:</B> AES 256 requires - * special JCE policy extension installation (e.g., for Java 7 see - * <A HREF="http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html">this link</A>) - */ - @SuppressWarnings("synthetic-access") - public static List<Integer> getAvailableKeyLengths() { - return LazyKeyLengthsHolder.KEY_LENGTHS; - } - - private static final class LazyKeyLengthsHolder { - private static final List<Integer> KEY_LENGTHS = Collections.unmodifiableList(detectSupportedKeySizes()); - - private LazyKeyLengthsHolder() { - throw new UnsupportedOperationException("No instance allowed"); - } - - // AES 256 requires special JCE policy extension installation - private static List<Integer> detectSupportedKeySizes() { - List<Integer> sizes = new ArrayList<>(); - for (int keyLength = 128; keyLength < Short.MAX_VALUE /* just so it doesn't go forever */; keyLength += 64) { - try { - byte[] keyAsBytes = new byte[keyLength / Byte.SIZE]; - Key key = new SecretKeySpec(keyAsBytes, CIPHER_NAME); - Cipher c = SecurityUtils.getCipher(CIPHER_NAME); - c.init(Cipher.DECRYPT_MODE, key); - sizes.add(Integer.valueOf(keyLength)); - } catch (GeneralSecurityException e) { - return sizes; - } - } - - throw new IllegalStateException("No limit encountered: " + sizes); - } - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractKeyPairResourceParser.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractKeyPairResourceParser.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractKeyPairResourceParser.java deleted file mode 100644 index a83bf68..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractKeyPairResourceParser.java +++ /dev/null @@ -1,181 +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; - -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.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; - -import org.apache.sshd.common.config.keys.FilePasswordProvider; -import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.ValidateUtils; -import org.apache.sshd.common.util.buffer.BufferUtils; -import org.apache.sshd.common.util.logging.AbstractLoggingBean; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public abstract class AbstractKeyPairResourceParser extends AbstractLoggingBean implements KeyPairResourceParser { - private final List<String> beginners; - private final List<String> enders; - private final List<List<String>> endingMarkers; - - /** - * @param beginners The markers that indicate the beginning of a parsing block - * @param enders The <U>matching</U> (by position) markers that indicate the end of a parsing block - */ - protected AbstractKeyPairResourceParser(List<String> beginners, List<String> enders) { - this.beginners = ValidateUtils.checkNotNullAndNotEmpty(beginners, "No begin markers"); - this.enders = ValidateUtils.checkNotNullAndNotEmpty(enders, "No end markers"); - ValidateUtils.checkTrue( - beginners.size() == enders.size(), "Mismatched begin(%d)/end(%d) markers sizes", beginners.size(), enders.size()); - endingMarkers = new ArrayList<>(enders.size()); - enders.forEach(m -> endingMarkers.add(Collections.singletonList(m))); - } - - public List<String> getBeginners() { - return beginners; - } - - public List<String> getEnders() { - return enders; - } - - /** - * @return A {@link List} of same size as the ending markers, where - * each ending marker is encapsulated inside a singleton list and - * resides as the <U>same index</U> as the marker it encapsulates - */ - public List<List<String>> getEndingMarkers() { - return endingMarkers; - } - - @Override - public boolean canExtractKeyPairs(String resourceKey, List<String> lines) throws IOException, GeneralSecurityException { - return KeyPairResourceParser.containsMarkerLine(lines, getBeginners()); - } - - @Override - public Collection<KeyPair> loadKeyPairs(String resourceKey, FilePasswordProvider passwordProvider, List<String> lines) - throws IOException, GeneralSecurityException { - Collection<KeyPair> keyPairs = Collections.emptyList(); - List<String> beginMarkers = getBeginners(); - List<List<String>> endMarkers = getEndingMarkers(); - for (Map.Entry<Integer, Integer> markerPos = KeyPairResourceParser.findMarkerLine(lines, beginMarkers); markerPos != null;) { - int startIndex = markerPos.getKey(); - String startLine = lines.get(startIndex); - startIndex++; - - int markerIndex = markerPos.getValue(); - List<String> ender = endMarkers.get(markerIndex); - markerPos = KeyPairResourceParser.findMarkerLine(lines, startIndex, ender); - if (markerPos == null) { - throw new StreamCorruptedException("Missing end marker (" + ender + ") after line #" + startIndex); - } - - int endIndex = markerPos.getKey(); - String endLine = lines.get(endIndex); - Collection<KeyPair> kps = - extractKeyPairs(resourceKey, startLine, endLine, passwordProvider, lines.subList(startIndex, endIndex)); - if (GenericUtils.isNotEmpty(kps)) { - if (GenericUtils.isEmpty(keyPairs)) { - keyPairs = new LinkedList<>(kps); - } else { - keyPairs.addAll(kps); - } - } - - // see if there are more - markerPos = KeyPairResourceParser.findMarkerLine(lines, endIndex + 1, beginMarkers); - } - - return keyPairs; - } - - /** - * Extracts the key pairs within a <U>single</U> delimited by markers block of lines. By - * default cleans up the empty lines, joins them and converts them from BASE64 - * - * @param resourceKey A hint as to the origin of the text lines - * @param beginMarker The line containing the begin marker - * @param endMarker The line containing the end marker - * @param passwordProvider The {@link FilePasswordProvider} to use - * in case the data is encrypted - may be {@code null} if no encrypted - * @param lines The block of lines between the markers - * @return The extracted {@link KeyPair}s - may be {@code null}/empty if none. - * @throws IOException If failed to parse the data - * @throws GeneralSecurityException If failed to generate the keys - * @see #extractKeyPairs(String, String, String, FilePasswordProvider, byte[]) - */ - public Collection<KeyPair> extractKeyPairs( - String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, List<String> lines) - throws IOException, GeneralSecurityException { - return extractKeyPairs(resourceKey, beginMarker, endMarker, passwordProvider, KeyPairResourceParser.extractDataBytes(lines)); - } - - /** - * @param resourceKey A hint as to the origin of the text lines - * @param beginMarker The line containing the begin marker - * @param endMarker The line containing the end marker - * @param passwordProvider The {@link FilePasswordProvider} to use - * in case the data is encrypted - may be {@code null} if no encrypted - * @param bytes The decoded bytes from the lines containing the data - * @return The extracted {@link KeyPair}s - may be {@code null}/empty if none. - * @throws IOException If failed to parse the data - * @throws GeneralSecurityException If failed to generate the keys - * @see #extractKeyPairs(String, String, String, FilePasswordProvider, InputStream) - */ - public Collection<KeyPair> extractKeyPairs( - String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, byte[] bytes) - throws IOException, GeneralSecurityException { - if (log.isTraceEnabled()) { - BufferUtils.dumpHex(getSimplifiedLogger(), Level.FINER, beginMarker, ':', 16, bytes); - } - - try (InputStream bais = new ByteArrayInputStream(bytes)) { - return extractKeyPairs(resourceKey, beginMarker, endMarker, passwordProvider, bais); - } - } - - /** - * @param resourceKey A hint as to the origin of the text lines - * @param beginMarker The line containing the begin marker - * @param endMarker The line containing the end marker - * @param passwordProvider The {@link FilePasswordProvider} to use - * in case the data is encrypted - may be {@code null} if no encrypted - * @param stream The decoded data {@link InputStream} - * @return The extracted {@link KeyPair}s - may be {@code null}/empty if none. - * @throws IOException If failed to parse the data - * @throws GeneralSecurityException If failed to generate the keys - */ - public abstract Collection<KeyPair> extractKeyPairs( - String resourceKey, String beginMarker, String endMarker, FilePasswordProvider passwordProvider, InputStream stream) - throws IOException, GeneralSecurityException; -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractPrivateKeyObfuscator.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractPrivateKeyObfuscator.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractPrivateKeyObfuscator.java deleted file mode 100644 index ac93ab4..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/AbstractPrivateKeyObfuscator.java +++ /dev/null @@ -1,191 +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; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.security.GeneralSecurityException; -import java.security.MessageDigest; -import java.security.SecureRandom; -import java.security.spec.InvalidKeySpecException; -import java.util.Arrays; -import java.util.Objects; -import java.util.Random; - -import javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -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.buffer.BufferUtils; -import org.apache.sshd.common.util.security.SecurityUtils; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public abstract class AbstractPrivateKeyObfuscator implements PrivateKeyObfuscator { - private final String algName; - - protected AbstractPrivateKeyObfuscator(String name) { - algName = ValidateUtils.checkNotNullAndNotEmpty(name, "No name specified"); - } - - @Override - public final String getCipherName() { - return algName; - } - - @Override - public byte[] generateInitializationVector(PrivateKeyEncryptionContext encContext) throws GeneralSecurityException { - return generateInitializationVector(resolveKeyLength(encContext)); - } - - @Override - public <A extends Appendable> A appendPrivateKeyEncryptionContext(A sb, PrivateKeyEncryptionContext encContext) throws IOException { - if (encContext == null) { - return sb; - } - - sb.append("DEK-Info: ").append(encContext.getCipherName()) - .append('-').append(encContext.getCipherType()) - .append('-').append(encContext.getCipherMode()); - - byte[] initVector = encContext.getInitVector(); - Objects.requireNonNull(initVector, "No encryption init vector"); - ValidateUtils.checkTrue(initVector.length > 0, "Empty encryption init vector"); - BufferUtils.appendHex(sb.append(','), BufferUtils.EMPTY_HEX_SEPARATOR, initVector); - sb.append(System.lineSeparator()); - return sb; - } - - protected byte[] generateInitializationVector(int keyLength) { - int keySize = keyLength / Byte.SIZE; - if ((keyLength % Byte.SIZE) != 0) { // e.g., if 36-bits then we need 5 bytes to hold - keySize++; - } - - byte[] initVector = new byte[keySize]; - Random randomizer = new SecureRandom(); // TODO consider using some pre-created singleton instance - randomizer.nextBytes(initVector); - return initVector; - } - - protected abstract int resolveKeyLength(PrivateKeyEncryptionContext encContext) throws GeneralSecurityException; - - // see http://martin.kleppmann.com/2013/05/24/improving-security-of-ssh-private-keys.html - // see http://www.ict.griffith.edu.au/anthony/info/crypto/openssl.hints (Password to Encryption Key section) - // see http://openssl.6102.n7.nabble.com/DES-EDE3-CBC-technical-details-td24883.html - protected byte[] deriveEncryptionKey(PrivateKeyEncryptionContext encContext, int outputKeyLength) throws GeneralSecurityException { - Objects.requireNonNull(encContext, "No encryption context"); - ValidateUtils.checkNotNullAndNotEmpty(encContext.getCipherName(), "No cipher name"); - ValidateUtils.checkNotNullAndNotEmpty(encContext.getCipherType(), "No cipher type"); - ValidateUtils.checkNotNullAndNotEmpty(encContext.getCipherMode(), "No cipher mode"); - - byte[] initVector = Objects.requireNonNull(encContext.getInitVector(), "No encryption init vector"); - ValidateUtils.checkTrue(initVector.length > 0, "Empty encryption init vector"); - - String password = ValidateUtils.checkNotNullAndNotEmpty(encContext.getPassword(), "No encryption password"); - byte[] passBytes = password.getBytes(StandardCharsets.UTF_8); - byte[] keyValue = new byte[outputKeyLength]; - MessageDigest hash = SecurityUtils.getMessageDigest(BuiltinDigests.Constants.MD5); - byte[] prevHash = GenericUtils.EMPTY_BYTE_ARRAY; - for (int index = 0, remLen = keyValue.length; index < keyValue.length;) { - hash.reset(); // just making sure - - hash.update(prevHash, 0, prevHash.length); - hash.update(passBytes, 0, passBytes.length); - hash.update(initVector, 0, Math.min(initVector.length, 8)); - - prevHash = hash.digest(); - - System.arraycopy(prevHash, 0, keyValue, index, Math.min(remLen, prevHash.length)); - index += prevHash.length; - remLen -= prevHash.length; - } - - return keyValue; - } - - protected byte[] applyPrivateKeyCipher(byte[] bytes, PrivateKeyEncryptionContext encContext, int numBits, byte[] keyValue, boolean encryptIt) - throws GeneralSecurityException { - Objects.requireNonNull(encContext, "No encryption context"); - String cipherName = ValidateUtils.checkNotNullAndNotEmpty(encContext.getCipherName(), "No cipher name"); - ValidateUtils.checkNotNullAndNotEmpty(encContext.getCipherType(), "No cipher type"); - String cipherMode = ValidateUtils.checkNotNullAndNotEmpty(encContext.getCipherMode(), "No cipher mode"); - - Objects.requireNonNull(bytes, "No source data"); - Objects.requireNonNull(keyValue, "No encryption key"); - ValidateUtils.checkTrue(keyValue.length > 0, "Empty encryption key"); - - byte[] initVector = Objects.requireNonNull(encContext.getInitVector(), "No encryption init vector"); - ValidateUtils.checkTrue(initVector.length > 0, "Empty encryption init vector"); - - 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("applyPrivateKeyCipher(" + xform + ")[encrypt=" + encryptIt + "]" - + " required key length (" + numBits + ")" - + " exceeds max. available: " + maxAllowedBits); - } - - SecretKeySpec skeySpec = new SecretKeySpec(keyValue, cipherName); - IvParameterSpec ivspec = new IvParameterSpec(initVector); - Cipher cipher = SecurityUtils.getCipher(xform); - int blockSize = cipher.getBlockSize(); - int dataSize = bytes.length; - cipher.init(encryptIt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, skeySpec, ivspec); - if (blockSize <= 0) { - return cipher.doFinal(bytes); - } - - int remLen = dataSize % blockSize; - if (remLen <= 0) { - return cipher.doFinal(bytes); - } - - int updateSize = dataSize - remLen; - byte[] lastBlock = new byte[blockSize]; - Arrays.fill(lastBlock, (byte) 10); - System.arraycopy(bytes, updateSize, lastBlock, 0, remLen); - - // TODO for some reason, calling cipher.update followed by cipher.doFinal does not work - ByteArrayOutputStream baos = new ByteArrayOutputStream(dataSize); - try { - try { - byte[] buf = cipher.update(bytes, 0, updateSize); - baos.write(buf); - - buf = cipher.doFinal(lastBlock); - baos.write(buf); - } finally { - baos.close(); - } - } catch (IOException e) { - throw new GeneralSecurityException("applyPrivateKeyCipher(" + xform + ")[encrypt=" + encryptIt + "]" - + " failed (" + e.getClass().getSimpleName() + ")" - + " to split-write: " + e.getMessage(), e); - } - - return baos.toByteArray(); - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/DESPrivateKeyObfuscator.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/DESPrivateKeyObfuscator.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/DESPrivateKeyObfuscator.java deleted file mode 100644 index 2043f06..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/DESPrivateKeyObfuscator.java +++ /dev/null @@ -1,76 +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; - -import java.security.GeneralSecurityException; -import java.util.Collections; -import java.util.List; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public class DESPrivateKeyObfuscator extends AbstractPrivateKeyObfuscator { - public static final int DEFAULT_KEY_LENGTH = 24 /* hardwired size for 3DES */; - public static final List<Integer> AVAILABLE_KEY_LENGTHS = - Collections.unmodifiableList(Collections.singletonList(Integer.valueOf(DEFAULT_KEY_LENGTH))); - public static final DESPrivateKeyObfuscator INSTANCE = new DESPrivateKeyObfuscator(); - - public DESPrivateKeyObfuscator() { - super("DES"); - } - - @Override - public byte[] applyPrivateKeyCipher(byte[] bytes, PrivateKeyEncryptionContext encContext, boolean encryptIt) throws GeneralSecurityException { - PrivateKeyEncryptionContext effContext = resolveEffectiveContext(encContext); - byte[] keyValue = deriveEncryptionKey(effContext, DEFAULT_KEY_LENGTH); - return applyPrivateKeyCipher(bytes, effContext, keyValue.length * Byte.SIZE, keyValue, encryptIt); - } - - @Override - public List<Integer> getSupportedKeySizes() { - return AVAILABLE_KEY_LENGTHS; - } - - @Override - protected int resolveKeyLength(PrivateKeyEncryptionContext encContext) throws GeneralSecurityException { - return DEFAULT_KEY_LENGTH; - } - - @Override - protected byte[] generateInitializationVector(int keyLength) { - return super.generateInitializationVector(8 * Byte.SIZE); - } - - public static final PrivateKeyEncryptionContext resolveEffectiveContext(PrivateKeyEncryptionContext encContext) { - if (encContext == null) { - return null; - } - - String cipherName = encContext.getCipherName(); - String cipherType = encContext.getCipherType(); - PrivateKeyEncryptionContext effContext = encContext; - if ("EDE3".equalsIgnoreCase(cipherType)) { - cipherName += "ede"; - effContext = encContext.clone(); - effContext.setCipherName(cipherName); - } - - return effContext; - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceLoader.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceLoader.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceLoader.java deleted file mode 100644 index fa6930a..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceLoader.java +++ /dev/null @@ -1,129 +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; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; -import java.net.URL; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.OpenOption; -import java.nio.file.Path; -import java.security.GeneralSecurityException; -import java.security.KeyPair; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -import org.apache.sshd.common.config.keys.FilePasswordProvider; -import org.apache.sshd.common.util.io.IoUtils; - -/** - * Loads {@link KeyPair}s from text resources - * - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -@FunctionalInterface -public interface KeyPairResourceLoader { - /** - * An empty loader that never fails but always returns an empty list - */ - KeyPairResourceLoader EMPTY = (resourceKey, passwordProvider, lines) -> Collections.emptyList(); - - default Collection<KeyPair> loadKeyPairs(Path path, FilePasswordProvider passwordProvider, OpenOption... options) - throws IOException, GeneralSecurityException { - return loadKeyPairs(path, passwordProvider, StandardCharsets.UTF_8, options); - } - - default Collection<KeyPair> loadKeyPairs(Path path, FilePasswordProvider passwordProvider, Charset cs, OpenOption... options) - throws IOException, GeneralSecurityException { - try (InputStream stream = Files.newInputStream(path, options)) { - return loadKeyPairs(path.toString(), passwordProvider, stream, cs); - } - } - - default Collection<KeyPair> loadKeyPairs(URL url, FilePasswordProvider passwordProvider) - throws IOException, GeneralSecurityException { - return loadKeyPairs(url, passwordProvider, StandardCharsets.UTF_8); - } - - default Collection<KeyPair> loadKeyPairs(URL url, FilePasswordProvider passwordProvider, Charset cs) - throws IOException, GeneralSecurityException { - try (InputStream stream = Objects.requireNonNull(url, "No URL").openStream()) { - return loadKeyPairs(url.toExternalForm(), passwordProvider, stream, cs); - } - } - - default Collection<KeyPair> loadKeyPairs(String resourceKey, FilePasswordProvider passwordProvider, String data) - throws IOException, GeneralSecurityException { - try (Reader reader = new StringReader((data == null) ? "" : data)) { - return loadKeyPairs(resourceKey, passwordProvider, reader); - } - } - - default Collection<KeyPair> loadKeyPairs(String resourceKey, FilePasswordProvider passwordProvider, InputStream stream) - throws IOException, GeneralSecurityException { - return loadKeyPairs(resourceKey, passwordProvider, stream, StandardCharsets.UTF_8); - } - - default Collection<KeyPair> loadKeyPairs(String resourceKey, FilePasswordProvider passwordProvider, InputStream stream, Charset cs) - throws IOException, GeneralSecurityException { - try (Reader reader = new InputStreamReader( - Objects.requireNonNull(stream, "No stream instance"), Objects.requireNonNull(cs, "No charset"))) { - return loadKeyPairs(resourceKey, passwordProvider, reader); - } - } - - default Collection<KeyPair> loadKeyPairs(String resourceKey, FilePasswordProvider passwordProvider, Reader r) - throws IOException, GeneralSecurityException { - try (BufferedReader br = new BufferedReader(Objects.requireNonNull(r, "No reader instance"), IoUtils.DEFAULT_COPY_SIZE)) { - return loadKeyPairs(resourceKey, passwordProvider, br); - } - } - - default Collection<KeyPair> loadKeyPairs(String resourceKey, FilePasswordProvider passwordProvider, BufferedReader r) - throws IOException, GeneralSecurityException { - return loadKeyPairs(resourceKey, passwordProvider, IoUtils.readAllLines(r)); - } - - /** - * Loads key pairs from the given resource text lines - * - * @param resourceKey A hint as to the origin of the text lines - * @param passwordProvider The {@link FilePasswordProvider} to use - * in case the data is encrypted - may be {@code null} if no encrypted - * data is expected - * @param lines The {@link List} of lines as read from the resource - * @return The extracted {@link KeyPair}s - may be {@code null}/empty if none. - * <B>Note:</B> the resource loader may decide to skip unknown lines if - * more than one key pair type is encoded in it - * @throws IOException If failed to process the lines - * @throws GeneralSecurityException If failed to generate the keys from the - * parsed data - */ - Collection<KeyPair> loadKeyPairs(String resourceKey, FilePasswordProvider passwordProvider, List<String> lines) - throws IOException, GeneralSecurityException; -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceParser.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceParser.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceParser.java deleted file mode 100644 index 80fc2c5..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/KeyPairResourceParser.java +++ /dev/null @@ -1,192 +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; - -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.KeyPair; -import java.util.AbstractMap.SimpleImmutableEntry; -import java.util.Arrays; -import java.util.Base64; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import org.apache.sshd.common.config.keys.FilePasswordProvider; -import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.ValidateUtils; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public interface KeyPairResourceParser extends KeyPairResourceLoader { - /** - * An empty parser that never fails, but always report that it cannot - * extract key pairs and returns empty list if asked to load - */ - KeyPairResourceParser EMPTY = new KeyPairResourceParser() { - @Override - public Collection<KeyPair> loadKeyPairs(String resourceKey, FilePasswordProvider passwordProvider, List<String> lines) - throws IOException, GeneralSecurityException { - return Collections.emptyList(); - } - - @Override - public boolean canExtractKeyPairs(String resourceKey, List<String> lines) throws IOException, GeneralSecurityException { - return false; - } - - @Override - public String toString() { - return "EMPTY"; - } - }; - - /** - * @param resourceKey A hint as to the origin of the text lines - * @param lines The resource lines - * @return {@code true} if the parser can extract some key pairs from the lines - * @throws IOException If failed to process the lines - * @throws GeneralSecurityException If failed to extract information regarding - * the possibility to extract the key pairs - */ - boolean canExtractKeyPairs(String resourceKey, List<String> lines) - throws IOException, GeneralSecurityException; - - /** - * Converts the lines assumed to contain BASE-64 encoded data into - * the actual content bytes. - * - * @param lines The data lines - empty lines and spaces are automatically - * deleted <U>before</U> BASE-64 decoding takes place. - * @return The decoded data bytes - * @see #joinDataLines(Collection) - */ - static byte[] extractDataBytes(Collection<String> lines) { - String data = joinDataLines(lines); - Base64.Decoder decoder = Base64.getDecoder(); - return decoder.decode(data); - } - - static String joinDataLines(Collection<String> lines) { - String data = GenericUtils.join(lines, ' '); - data = data.replaceAll("\\s", ""); - data = data.trim(); - return data; - } - - static boolean containsMarkerLine(List<String> lines, String marker) { - return containsMarkerLine(lines, Collections.singletonList(ValidateUtils.checkNotNullAndNotEmpty(marker, "No marker"))); - } - - static boolean containsMarkerLine(List<String> lines, List<String> markers) { - return findMarkerLine(lines, markers) != null; - } - - /** - * Attempts to locate a line that contains one of the markers - * - * @param lines The list of lines to scan - ignored if {@code null}/empty - * @param markers The markers to match - ignored if {@code null}/empty - * @return A {@link SimpleImmutableEntry} whose key is the <U>first</U> line index - * that matched and value the matched marker index - {@code null} if no match found - * @see #findMarkerLine(List, int, List) - */ - static SimpleImmutableEntry<Integer, Integer> findMarkerLine(List<String> lines, List<String> markers) { - return findMarkerLine(lines, 0, markers); - } - - /** - * Attempts to locate a line that contains one of the markers - * - * @param lines The list of lines to scan - ignored if {@code null}/empty - * @param startLine The scan start line index - * @param markers The markers to match - ignored if {@code null}/empty - * @return A {@link SimpleImmutableEntry} whose key is the <U>first</U> line index - * that matched and value the matched marker index - {@code null} if no match found - */ - static SimpleImmutableEntry<Integer, Integer> findMarkerLine(List<String> lines, int startLine, List<String> markers) { - if (GenericUtils.isEmpty(lines) || GenericUtils.isEmpty(markers)) { - return null; - } - - for (int lineIndex = startLine; lineIndex < lines.size(); lineIndex++) { - String l = lines.get(lineIndex); - for (int markerIndex = 0; markerIndex < markers.size(); markerIndex++) { - String m = markers.get(markerIndex); - if (l.contains(m)) { - return new SimpleImmutableEntry<>(lineIndex, markerIndex); - } - } - } - - return null; - } - - static KeyPairResourceParser aggregate(KeyPairResourceParser... parsers) { - return aggregate(Arrays.asList(ValidateUtils.checkNotNullAndNotEmpty(parsers, "No parsers to aggregate"))); - } - - static KeyPairResourceParser aggregate(Collection<? extends KeyPairResourceParser> parsers) { - ValidateUtils.checkNotNullAndNotEmpty(parsers, "No parsers to aggregate"); - return new KeyPairResourceParser() { - @Override - public Collection<KeyPair> loadKeyPairs(String resourceKey, FilePasswordProvider passwordProvider, List<String> lines) - throws IOException, GeneralSecurityException { - Collection<KeyPair> keyPairs = Collections.emptyList(); - for (KeyPairResourceParser p : parsers) { - if (!p.canExtractKeyPairs(resourceKey, lines)) { - continue; - } - - Collection<KeyPair> kps = p.loadKeyPairs(resourceKey, passwordProvider, lines); - if (GenericUtils.isEmpty(kps)) { - continue; - } - - if (GenericUtils.isEmpty(keyPairs)) { - keyPairs = new LinkedList<>(kps); - } else { - keyPairs.addAll(kps); - } - } - - return keyPairs; - } - - @Override - public boolean canExtractKeyPairs(String resourceKey, List<String> lines) throws IOException, GeneralSecurityException { - for (KeyPairResourceParser p : parsers) { - if (p.canExtractKeyPairs(resourceKey, lines)) { - return true; - } - } - - return false; - } - - @Override - public String toString() { - return KeyPairResourceParser.class.getSimpleName() + "[aggregate]"; - } - }; - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/PrivateKeyEncryptionContext.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/PrivateKeyEncryptionContext.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/PrivateKeyEncryptionContext.java deleted file mode 100644 index 5e03cdb..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/PrivateKeyEncryptionContext.java +++ /dev/null @@ -1,270 +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; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.NavigableSet; -import java.util.Objects; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.ValidateUtils; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public class PrivateKeyEncryptionContext implements Cloneable { - public static final String DEFAULT_CIPHER_MODE = "CBC"; - - private static final Map<String, PrivateKeyObfuscator> OBFUSCATORS = - Stream.of(AESPrivateKeyObfuscator.INSTANCE, DESPrivateKeyObfuscator.INSTANCE) - .collect(Collectors.toMap(AbstractPrivateKeyObfuscator::getCipherName, Function.identity())); - - private String cipherName; - private String cipherType; - private String cipherMode = DEFAULT_CIPHER_MODE; - private String password; - private byte[] initVector; - private transient PrivateKeyObfuscator obfuscator; - - public PrivateKeyEncryptionContext() { - super(); - } - - public PrivateKeyEncryptionContext(String algInfo) { - parseAlgorithmInfo(algInfo); - } - - public String getCipherName() { - return cipherName; - } - - public void setCipherName(String value) { - cipherName = value; - } - - public String getCipherType() { - return cipherType; - } - - public void setCipherType(String value) { - cipherType = value; - } - - public String getCipherMode() { - return cipherMode; - } - - public void setCipherMode(String value) { - cipherMode = value; - } - - public String getPassword() { - return password; - } - - public void setPassword(String value) { - password = value; - } - - public byte[] getInitVector() { - return initVector; - } - - public void setInitVector(byte... values) { - initVector = values; - } - - public PrivateKeyObfuscator getPrivateKeyObfuscator() { - return obfuscator; - } - - public void setPrivateKeyObfuscator(PrivateKeyObfuscator value) { - obfuscator = value; - } - - public PrivateKeyObfuscator resolvePrivateKeyObfuscator() { - PrivateKeyObfuscator value = getPrivateKeyObfuscator(); - if (value != null) { - return value; - } - - return getRegisteredPrivateKeyObfuscator(getCipherName()); - } - - public static PrivateKeyObfuscator registerPrivateKeyObfuscator(PrivateKeyObfuscator o) { - return registerPrivateKeyObfuscator(Objects.requireNonNull(o, "No instance provided").getCipherName(), o); - } - - public static PrivateKeyObfuscator registerPrivateKeyObfuscator(String cipherName, PrivateKeyObfuscator o) { - ValidateUtils.checkNotNullAndNotEmpty(cipherName, "No cipher name"); - Objects.requireNonNull(o, "No instance provided"); - - synchronized (OBFUSCATORS) { - return OBFUSCATORS.put(cipherName, o); - } - } - - public static boolean unregisterPrivateKeyObfuscator(PrivateKeyObfuscator o) { - Objects.requireNonNull(o, "No instance provided"); - String cipherName = o.getCipherName(); - ValidateUtils.checkNotNullAndNotEmpty(cipherName, "No cipher name"); - - synchronized (OBFUSCATORS) { - PrivateKeyObfuscator prev = OBFUSCATORS.get(cipherName); - if (prev != o) { - return false; - } - - OBFUSCATORS.remove(cipherName); - } - - return true; - } - - public static PrivateKeyObfuscator unregisterPrivateKeyObfuscator(String cipherName) { - ValidateUtils.checkNotNullAndNotEmpty(cipherName, "No cipher name"); - - synchronized (OBFUSCATORS) { - return OBFUSCATORS.remove(cipherName); - } - } - - public static final PrivateKeyObfuscator getRegisteredPrivateKeyObfuscator(String cipherName) { - if (GenericUtils.isEmpty(cipherName)) { - return null; - } - - synchronized (OBFUSCATORS) { - return OBFUSCATORS.get(cipherName); - } - } - - public static final NavigableSet<String> getRegisteredPrivateKeyObfuscatorCiphers() { - synchronized (OBFUSCATORS) { - Collection<String> names = OBFUSCATORS.keySet(); - return GenericUtils.asSortedSet(String.CASE_INSENSITIVE_ORDER, names); - } - } - - public static final List<PrivateKeyObfuscator> getRegisteredPrivateKeyObfuscators() { - synchronized (OBFUSCATORS) { - Collection<? extends PrivateKeyObfuscator> l = OBFUSCATORS.values(); - if (GenericUtils.isEmpty(l)) { - return Collections.emptyList(); - } else { - return new ArrayList<>(l); - } - } - } - - /** - * @param algInfo The algorithm info - format: <I>{@code name-type-mode}</I> - * @return The updated context instance - * @see #parseAlgorithmInfo(PrivateKeyEncryptionContext, String) - */ - public PrivateKeyEncryptionContext parseAlgorithmInfo(String algInfo) { - return parseAlgorithmInfo(this, algInfo); - } - - @Override - public PrivateKeyEncryptionContext clone() { - try { - PrivateKeyEncryptionContext copy = getClass().cast(super.clone()); - byte[] v = copy.getInitVector(); - if (v != null) { - v = v.clone(); - copy.setInitVector(v); - } - return copy; - } catch (CloneNotSupportedException e) { // unexpected - throw new RuntimeException("Failed to clone: " + toString()); - } - } - - @Override - public int hashCode() { - return GenericUtils.hashCode(getCipherName(), Boolean.TRUE) - + GenericUtils.hashCode(getCipherType(), Boolean.TRUE) - + GenericUtils.hashCode(getCipherMode(), Boolean.TRUE) - + Objects.hashCode(getPassword()) - + Arrays.hashCode(getInitVector()); - } - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (this == obj) { - return true; - } - if (getClass() != obj.getClass()) { - return false; - } - - PrivateKeyEncryptionContext other = (PrivateKeyEncryptionContext) obj; - return (GenericUtils.safeCompare(getCipherName(), other.getCipherName(), false) == 0) - && (GenericUtils.safeCompare(getCipherType(), other.getCipherType(), false) == 0) - && (GenericUtils.safeCompare(getCipherMode(), other.getCipherMode(), false) == 0) - && (GenericUtils.safeCompare(getPassword(), other.getPassword(), true) == 0) - && Arrays.equals(getInitVector(), other.getInitVector()); - } - - @Override - public String toString() { - return GenericUtils.join(new String[]{getCipherName(), getCipherType(), getCipherMode()}, '-'); - } - - /** - * @param <C> Generic context type - * @param context The {@link PrivateKeyEncryptionContext} to update - * @param algInfo The algorithm info - format: {@code <I>name</I>-<I>type</I>-<I>mode</I>} - * @return The updated context - */ - public static final <C extends PrivateKeyEncryptionContext> C parseAlgorithmInfo(C context, String algInfo) { - ValidateUtils.checkNotNullAndNotEmpty(algInfo, "No encryption algorithm data"); - - String[] cipherData = GenericUtils.split(algInfo, '-'); - ValidateUtils.checkTrue(cipherData.length == 3, "Bad encryption algorithm data: %s", algInfo); - - context.setCipherName(cipherData[0]); - context.setCipherType(cipherData[1]); - context.setCipherMode(cipherData[2]); - return context; - } - - public static final PrivateKeyEncryptionContext newPrivateKeyEncryptionContext(PrivateKeyObfuscator o, String password) { - return initializeObfuscator(new PrivateKeyEncryptionContext(), o, password); - } - - public static final <C extends PrivateKeyEncryptionContext> C initializeObfuscator(C context, PrivateKeyObfuscator o, String password) { - context.setCipherName(o.getCipherName()); - context.setPrivateKeyObfuscator(o); - context.setPassword(password); - return context; - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/PrivateKeyObfuscator.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/PrivateKeyObfuscator.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/PrivateKeyObfuscator.java deleted file mode 100644 index d8d2db5..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/PrivateKeyObfuscator.java +++ /dev/null @@ -1,64 +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; - -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.util.List; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public interface PrivateKeyObfuscator { - /** - * @return Basic cipher used to obfuscate - */ - String getCipherName(); - - /** - * @return A {@link List} of the supported key sizes - <B>Note:</B> every - * call returns a and <U>un-modifiable</U> instance. - */ - List<Integer> getSupportedKeySizes(); - - /** - * @param <A> Appendable generic type - * @param sb The {@link Appendable} instance to update - * @param encContext - * @return Same appendable instance - * @throws IOException - */ - <A extends Appendable> A appendPrivateKeyEncryptionContext(A sb, PrivateKeyEncryptionContext encContext) throws IOException; - - /** - * @param encContext The encryption context - * @return An initialization vector suitable to the specified context - * @throws GeneralSecurityException - */ - byte[] generateInitializationVector(PrivateKeyEncryptionContext encContext) throws GeneralSecurityException; - - /** - * @param bytes Original bytes - * @param encContext The encryption context - * @param encryptIt If {@code true} then encrypt the original bytes, otherwise decrypt them - * @return The result of applying the cipher to the original bytes - * @throws GeneralSecurityException If cannot encrypt/decrypt - */ - byte[] applyPrivateKeyCipher(byte[] bytes, PrivateKeyEncryptionContext encContext, boolean encryptIt) throws GeneralSecurityException; -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHDSSPrivateKeyEntryDecoder.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHDSSPrivateKeyEntryDecoder.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHDSSPrivateKeyEntryDecoder.java deleted file mode 100644 index 6188a04..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHDSSPrivateKeyEntryDecoder.java +++ /dev/null @@ -1,139 +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.openssh; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.math.BigInteger; -import java.security.GeneralSecurityException; -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.KeyPairGenerator; -import java.security.interfaces.DSAParams; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.DSAPublicKey; -import java.security.spec.DSAPrivateKeySpec; -import java.security.spec.DSAPublicKeySpec; -import java.security.spec.InvalidKeySpecException; -import java.util.Collections; -import java.util.Objects; - -import org.apache.sshd.common.config.keys.FilePasswordProvider; -import org.apache.sshd.common.config.keys.KeyEntryResolver; -import org.apache.sshd.common.config.keys.KeyUtils; -import org.apache.sshd.common.config.keys.impl.AbstractPrivateKeyEntryDecoder; -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 OpenSSHDSSPrivateKeyEntryDecoder extends AbstractPrivateKeyEntryDecoder<DSAPublicKey, DSAPrivateKey> { - public static final OpenSSHDSSPrivateKeyEntryDecoder INSTANCE = new OpenSSHDSSPrivateKeyEntryDecoder(); - - public OpenSSHDSSPrivateKeyEntryDecoder() { - super(DSAPublicKey.class, DSAPrivateKey.class, Collections.unmodifiableList(Collections.singletonList(KeyPairProvider.SSH_DSS))); - } - - @Override - public DSAPrivateKey decodePrivateKey(String keyType, FilePasswordProvider passwordProvider, InputStream keyData) - throws IOException, GeneralSecurityException { - if (!KeyPairProvider.SSH_DSS.equals(keyType)) { // just in case we were invoked directly - throw new InvalidKeySpecException("Unexpected key type: " + keyType); - } - - BigInteger p = KeyEntryResolver.decodeBigInt(keyData); - BigInteger q = KeyEntryResolver.decodeBigInt(keyData); - BigInteger g = KeyEntryResolver.decodeBigInt(keyData); - BigInteger y = KeyEntryResolver.decodeBigInt(keyData); - Objects.requireNonNull(y, "No public key data"); // TODO run some validation on it - BigInteger x = KeyEntryResolver.decodeBigInt(keyData); - - return generatePrivateKey(new DSAPrivateKeySpec(x, p, q, g)); - } - - @Override - public String encodePrivateKey(OutputStream s, DSAPrivateKey key) throws IOException { - Objects.requireNonNull(key, "No private key provided"); - - DSAParams keyParams = Objects.requireNonNull(key.getParams(), "No DSA params available"); - BigInteger p = keyParams.getP(); - KeyEntryResolver.encodeBigInt(s, p); - KeyEntryResolver.encodeBigInt(s, keyParams.getQ()); - - BigInteger g = keyParams.getG(); - KeyEntryResolver.encodeBigInt(s, g); - - BigInteger x = key.getX(); - BigInteger y = g.modPow(x, p); - KeyEntryResolver.encodeBigInt(s, y); - KeyEntryResolver.encodeBigInt(s, x); - return KeyPairProvider.SSH_DSS; - } - - @Override - public boolean isPublicKeyRecoverySupported() { - return true; - } - - @Override - public DSAPublicKey recoverPublicKey(DSAPrivateKey privateKey) throws GeneralSecurityException { - return KeyUtils.recoverDSAPublicKey(privateKey); - } - - @Override - public DSAPublicKey clonePublicKey(DSAPublicKey key) throws GeneralSecurityException { - if (key == null) { - return null; - } - - DSAParams params = key.getParams(); - if (params == null) { - throw new InvalidKeyException("Missing parameters in key"); - } - - return generatePublicKey(new DSAPublicKeySpec(key.getY(), params.getP(), params.getQ(), params.getG())); - } - - @Override - public DSAPrivateKey clonePrivateKey(DSAPrivateKey key) throws GeneralSecurityException { - if (key == null) { - return null; - } - - DSAParams params = key.getParams(); - if (params == null) { - throw new InvalidKeyException("Missing parameters in key"); - } - - return generatePrivateKey(new DSAPrivateKeySpec(key.getX(), params.getP(), params.getQ(), params.getG())); - } - - @Override - public KeyPairGenerator getKeyPairGenerator() throws GeneralSecurityException { - return SecurityUtils.getKeyPairGenerator(KeyUtils.DSS_ALGORITHM); - } - - @Override - public KeyFactory getKeyFactoryInstance() throws GeneralSecurityException { - return SecurityUtils.getKeyFactory(KeyUtils.DSS_ALGORITHM); - } -}
