Repository: mina-sshd Updated Branches: refs/heads/master a2e925648 -> ed064a091
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java new file mode 100644 index 0000000..85222ef --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java @@ -0,0 +1,657 @@ +/* + * 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.util.security; + +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.nio.file.Path; +import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.PublicKey; +import java.security.Signature; +import java.security.cert.CertificateFactory; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.crypto.Cipher; +import javax.crypto.KeyAgreement; +import javax.crypto.Mac; +import javax.crypto.spec.DHParameterSpec; + +import org.apache.sshd.common.config.keys.FilePasswordProvider; +import org.apache.sshd.common.config.keys.KeyUtils; +import org.apache.sshd.common.config.keys.PublicKeyEntryDecoder; +import org.apache.sshd.common.keyprovider.AbstractClassLoadableResourceKeyPairProvider; +import org.apache.sshd.common.keyprovider.AbstractFileKeyPairProvider; +import org.apache.sshd.common.keyprovider.KeyPairProvider; +import org.apache.sshd.common.random.JceRandomFactory; +import org.apache.sshd.common.random.RandomFactory; +import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.ReflectionUtils; +import org.apache.sshd.common.util.ValidateUtils; +import org.apache.sshd.common.util.buffer.Buffer; +import org.apache.sshd.common.util.security.bouncycastle.BouncyCastleClassLoadableResourceKeyPairProvider; +import org.apache.sshd.common.util.security.bouncycastle.BouncyCastleFileKeyPairProvider; +import org.apache.sshd.common.util.security.bouncycastle.BouncyCastleGeneratorHostKeyProvider; +import org.apache.sshd.common.util.security.bouncycastle.BouncyCastleInputStreamLoader; +import org.apache.sshd.common.util.security.bouncycastle.BouncyCastleRandomFactory; +import org.apache.sshd.common.util.security.eddsa.EdDSASecurityProvider; +import org.apache.sshd.common.util.threads.ThreadUtils; +import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvider; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Specific security providers related code + * + * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> + */ +public final class SecurityUtils { + /** + * Bouncycastle JCE provider name + */ + public static final String BOUNCY_CASTLE = "BC"; + + /** + * EDDSA support + */ + public static final String EDDSA = "EdDSA"; + + /** + * System property used to configure the value for the maximum supported Diffie-Hellman + * Group Exchange key size. If not set, then an internal auto-discovery mechanism is employed. + * If set to negative value then Diffie-Hellman Group Exchange is disabled. If set to a + * negative value then Diffie-Hellman Group Exchange is disabled + */ + public static final String MAX_DHGEX_KEY_SIZE_PROP = "org.apache.sshd.maxDHGexKeySize"; + + /** + * The min. key size value used for testing whether Diffie-Hellman Group Exchange + * is supported or not. According to <A HREF="https://tools.ietf.org/html/rfc4419">RFC 4419</A> + * section 3: "Servers and clients SHOULD support groups with a modulus length of k + * bits, where 1024 <= k <= 8192". + * </code> + */ + public static final int MIN_DHGEX_KEY_SIZE = 1024; + // Keys of size > 1024 are not support by default with JCE + public static final int DEFAULT_DHGEX_KEY_SIZE = MIN_DHGEX_KEY_SIZE; + public static final int PREFERRED_DHGEX_KEY_SIZE = 4096; + public static final int MAX_DHGEX_KEY_SIZE = 8192; + + /** + * System property used to control whether to automatically register the + * {@code Bouncyastle} JCE provider + */ + public static final String REGISTER_BOUNCY_CASTLE_PROP = "org.apache.sshd.registerBouncyCastle"; + + /** + * System property used to control whether Elliptic Curves are supported or not. + * If not set then the support is auto-detected. <B>Note:</B> if set to {@code true} + * it is up to the user to make sure that indeed there is a provider for them + */ + public static final String ECC_SUPPORTED_PROP = "org.apache.sshd.eccSupport"; + + /** + * System property used to decide whether EDDSA curves are supported or not + * (in addition or even in spite of {@link #isEDDSACurveSupported()}). If not + * set or set to {@code true}, then the existence of the optional support classes + * determines the support. + */ + public static final String EDDSA_SUPPORTED_PROP = "org.apache.sshd.eddsaSupport"; + + private static final AtomicInteger MAX_DHG_KEY_SIZE_HOLDER = new AtomicInteger(0); + + private static final Map<String, Provider> REGISTERED_PROVIDERS = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + private static String defaultProvider; + private static Boolean registerBouncyCastle; + private static boolean registrationDone; + private static Boolean hasEcc; + private static Boolean eddsaSupported; + + private SecurityUtils() { + throw new UnsupportedOperationException("No instance"); + } + + /** + * @return {@code true} if Elliptic Curve Cryptography is supported + * @see #ECC_SUPPORTED_PROP + */ + public static boolean hasEcc() { + if (hasEcc == null) { + String propValue = System.getProperty(ECC_SUPPORTED_PROP); + if (GenericUtils.isEmpty(propValue)) { + try { + getKeyPairGenerator(KeyUtils.EC_ALGORITHM); + hasEcc = Boolean.TRUE; + } catch (Throwable t) { + hasEcc = Boolean.FALSE; + } + } else { + Logger logger = LoggerFactory.getLogger(SecurityUtils.class); + logger.info("Override ECC support value: " + propValue); + hasEcc = Boolean.valueOf(propValue); + } + } + + return hasEcc; + } + + /** + * @return {@code true} if Diffie-Hellman Group Exchange is supported + * @see #getMaxDHGroupExchangeKeySize() + */ + public static boolean isDHGroupExchangeSupported() { + return getMaxDHGroupExchangeKeySize() > 0; + } + + /** + * @param keySize The expected key size + * @return {@code true} if Oakely Diffie-Hellman Group Exchange is supported + * for the specified key size + * @see #getMaxDHGroupExchangeKeySize() + */ + public static boolean isDHOakelyGroupSupported(int keySize) { + return getMaxDHGroupExchangeKeySize() >= keySize; + } + + /** + * @return The maximum supported Diffie-Hellman Group Exchange key size, + * or non-positive if not supported + */ + public static int getMaxDHGroupExchangeKeySize() { + int maxSupportedKeySize; + synchronized (MAX_DHG_KEY_SIZE_HOLDER) { + maxSupportedKeySize = MAX_DHG_KEY_SIZE_HOLDER.get(); + if (maxSupportedKeySize != 0) { // 1st time we are called ? + return maxSupportedKeySize; + } + + String propValue = System.getProperty(MAX_DHGEX_KEY_SIZE_PROP); + if (GenericUtils.isEmpty(propValue)) { + maxSupportedKeySize = -1; + // Go down from max. to min. to ensure we stop at 1st maximum value success + for (int testKeySize = MAX_DHGEX_KEY_SIZE; testKeySize >= MIN_DHGEX_KEY_SIZE; testKeySize -= 1024) { + if (isDHGroupExchangeSupported(testKeySize)) { + maxSupportedKeySize = testKeySize; + break; + } + } + } else { + Logger logger = LoggerFactory.getLogger(SecurityUtils.class); + logger.info("Override max. DH group exchange key size: " + propValue); + maxSupportedKeySize = Integer.parseInt(propValue); + // negative is OK - means user wants to disable DH group exchange + ValidateUtils.checkTrue(maxSupportedKeySize != 0, + "Configured " + MAX_DHGEX_KEY_SIZE_PROP + " value must be non-zero: %d", maxSupportedKeySize); + } + + MAX_DHG_KEY_SIZE_HOLDER.set(maxSupportedKeySize); + } + + return maxSupportedKeySize; + } + + /** + * Set programmatically the reported value for {@link #getMaxDHGroupExchangeKeySize()} + * @param keySize The reported key size - if zero, then it will be auto-detected, if + * negative then DH group exchange will be disabled + */ + public static void setMaxDHGroupExchangeKeySize(int keySize) { + synchronized (MAX_DHG_KEY_SIZE_HOLDER) { + MAX_DHG_KEY_SIZE_HOLDER.set(keySize); + } + } + + public static boolean isDHGroupExchangeSupported(int maxKeySize) { + ValidateUtils.checkTrue(maxKeySize > Byte.SIZE, "Invalid max. key size: %d", maxKeySize); + + try { + BigInteger r = new BigInteger("0").setBit(maxKeySize - 1); + DHParameterSpec dhSkipParamSpec = new DHParameterSpec(r, r); + KeyPairGenerator kpg = getKeyPairGenerator("DH"); + kpg.initialize(dhSkipParamSpec); + return true; + } catch (GeneralSecurityException t) { + return false; + } + } + + public static synchronized void setRegisterBouncyCastle(boolean registerBouncyCastle) { + SecurityUtils.registerBouncyCastle = registerBouncyCastle; + registrationDone = false; + } + + public static synchronized String getDefaultProvider() { + return defaultProvider; + } + + public static synchronized void setDefaultProvider(String provider) { + defaultProvider = provider; + registrationDone = false; + } + + /** + * @return A <U>copy</U> of the currently registered security providers + */ + public static synchronized Set<String> getRegisteredProviders() { + register(); + + // returns a COPY of the providers in order to avoid modifications + synchronized (REGISTERED_PROVIDERS) { + return new TreeSet<>(REGISTERED_PROVIDERS.keySet()); + } + } + + public static synchronized boolean isBouncyCastleRegistered() { + register(); + return isBouncyCastleListed(); + } + + private static boolean isBouncyCastleListed() { + return isProviderRegistered(BOUNCY_CASTLE); + } + + private static boolean isEDDSAListed() { + return isProviderRegistered(EDDSA); + } + + private static boolean isProviderRegistered(String provider) { + Objects.requireNonNull(provider, "No provider name specified"); + synchronized (REGISTERED_PROVIDERS) { + return REGISTERED_PROVIDERS.containsKey(provider); + } + } + + @SuppressWarnings("synthetic-access") + private static void register() { + if (!registrationDone) { + if (registerBouncyCastle == null) { + String propValue = System.getProperty(REGISTER_BOUNCY_CASTLE_PROP); + if (!GenericUtils.isEmpty(propValue)) { + Logger logger = LoggerFactory.getLogger(SecurityUtils.class); + logger.info("Override BouncyCastle registration value: " + propValue); + registerBouncyCastle = Boolean.valueOf(propValue); + } + } + + if ((defaultProvider == null) && (!isBouncyCastleListed()) && ((registerBouncyCastle == null) || registerBouncyCastle)) { + // Use an inner class to avoid a strong dependency from SshServer on BouncyCastle + try { + new BouncyCastleRegistration().call(); + defaultProvider = BOUNCY_CASTLE; + } catch (Throwable t) { + Logger logger = LoggerFactory.getLogger(SecurityUtils.class); + if (registerBouncyCastle == null) { + logger.info("BouncyCastle not registered, using the default JCE provider"); + } else { + logger.error("Failed {} to register BouncyCastle as a JCE provider: {}", t.getClass().getSimpleName(), t.getMessage()); + throw new RuntimeException("Failed to register BouncyCastle as a JCE provider", t); + } + } + } + + if ((!isEDDSAListed()) && isEDDSACurveSupported()) { + try { + new EdDSARegistration().call(); + } catch (Throwable t) { + Logger logger = LoggerFactory.getLogger(SecurityUtils.class); + logger.error("Failed {} to register " + EDDSA + " as a JCE provider: {}", t.getClass().getSimpleName(), t.getMessage()); + throw new RuntimeException("Failed to register " + EDDSA + " as a JCE provider", t); + } + } + + registrationDone = true; + } + } + + ///////////////// Bouncycastle specific implementations ////////////////// + + private static class BouncyCastleRegistration implements Callable<Void> { + @SuppressWarnings("synthetic-access") + @Override + public Void call() throws Exception { + // no need for a logger specific to this class since this is a one-time call + Logger logger = LoggerFactory.getLogger(SecurityUtils.class); + Provider p = java.security.Security.getProvider(BOUNCY_CASTLE); + if (p == null) { + logger.info("Trying to register BouncyCastle as a JCE provider"); + p = new BouncyCastleProvider(); + java.security.Security.addProvider(p); + MessageDigest.getInstance("MD5", BOUNCY_CASTLE); + KeyAgreement.getInstance("DH", BOUNCY_CASTLE); + logger.info("Registration succeeded"); + } else { + logger.info("BouncyCastle already registered as a JCE provider"); + } + + synchronized (REGISTERED_PROVIDERS) { + REGISTERED_PROVIDERS.put(BOUNCY_CASTLE, p); + } + return null; + } + } + + /* -------------------------------------------------------------------- */ + + /** + * @param resourceKey An identifier of the key being loaded - used as + * argument to the {@link FilePasswordProvider#getPassword(String)} + * invocation + * @param inputStream The {@link InputStream} for the <U>private</U> key + * @param provider A {@link FilePasswordProvider} - may be {@code null} + * if the loaded key is <U>guaranteed</U> not to be encrypted + * @return The loaded {@link KeyPair} + * @throws IOException If failed to read/parse the input stream + * @throws GeneralSecurityException If failed to generate the keys - specifically, + * {@link NoSuchProviderException} is thrown also if {@link #isBouncyCastleRegistered()} + * is {@code false} + */ + public static KeyPair loadKeyPairIdentity(String resourceKey, InputStream inputStream, FilePasswordProvider provider) + throws IOException, GeneralSecurityException { + if (!isBouncyCastleRegistered()) { + throw new NoSuchProviderException("BouncyCastle not registered"); + } + + return BouncyCastleInputStreamLoader.loadKeyPair(resourceKey, inputStream, provider); + } + + /* -------------------------------------------------------------------- */ + + public static AbstractFileKeyPairProvider createFileKeyPairProvider() { + ValidateUtils.checkTrue(isBouncyCastleRegistered(), "BouncyCastle not registered"); + return new BouncyCastleFileKeyPairProvider(); + } + + public static AbstractClassLoadableResourceKeyPairProvider createClassLoadableResourceKeyPairProvider() { + ValidateUtils.checkTrue(isBouncyCastleRegistered(), "BouncyCastle not registered"); + return new BouncyCastleClassLoadableResourceKeyPairProvider(); + } + + /* -------------------------------------------------------------------- */ + + public static AbstractGeneratorHostKeyProvider createGeneratorHostKeyProvider(Path path) { + ValidateUtils.checkTrue(isBouncyCastleRegistered(), "BouncyCastle not registered"); + return new BouncyCastleGeneratorHostKeyProvider(path); + } + + /** + * @return If {@link #isBouncyCastleRegistered()} then a {@link BouncyCastleRandomFactory} + * instance, otherwise a {@link JceRandomFactory} one + */ + public static RandomFactory getRandomFactory() { + if (isBouncyCastleRegistered()) { + return BouncyCastleRandomFactory.INSTANCE; + } else { + return JceRandomFactory.INSTANCE; + } + } + + ///////////////////////////// ED25519 support /////////////////////////////// + + /** + * @return {@code true} if EDDSA curves (e.g., {@code ed25519}) are supported + */ + public static synchronized boolean isEDDSACurveSupported() { + if (eddsaSupported == null) { + String propValue = System.getProperty(EDDSA_SUPPORTED_PROP); + if (GenericUtils.isEmpty(propValue) || "true".equals(propValue)) { + ClassLoader cl = ThreadUtils.resolveDefaultClassLoader(SecurityUtils.class); + eddsaSupported = ReflectionUtils.isClassAvailable(cl, "net.i2p.crypto.eddsa.EdDSAKey"); + } else { + eddsaSupported = Boolean.FALSE; + Logger logger = LoggerFactory.getLogger(SecurityUtils.class); + logger.info("Override EDDSA support value: " + propValue); + } + } + + return eddsaSupported; + } + + /* -------------------------------------------------------------------- */ + + private static class EdDSARegistration implements Callable<Void> { + EdDSARegistration() { + super(); + } + + @SuppressWarnings("synthetic-access") + @Override + public Void call() throws Exception { + // no need for a logger specific to this class since this is a one-time call + Logger logger = LoggerFactory.getLogger(SecurityUtils.class); + Provider p = java.security.Security.getProvider(EDDSA); + if (p == null) { + logger.info("Trying to register " + EDDSA + " as a JCE provider"); + p = new EdDSASecurityProvider(); + java.security.Security.addProvider(p); + KeyFactory.getInstance(EDDSA, EDDSA); + logger.info("Registration succeeded"); + } else { + logger.info(EDDSA + " already registered as a JCE provider"); + } + + synchronized (REGISTERED_PROVIDERS) { + REGISTERED_PROVIDERS.put(EDDSA, p); + } + + return null; + } + } + + /* -------------------------------------------------------------------- */ + + public static PublicKeyEntryDecoder<? extends PublicKey, ? extends PrivateKey> getEDDSAPublicKeyEntryDecoder() { + if (!isEDDSACurveSupported()) { + throw new UnsupportedOperationException(EDDSA + " provider N/A"); + } + + return EdDSASecurityProvider.getEDDSAPublicKeyEntryDecoder(); + } + + public static org.apache.sshd.common.signature.Signature getEDDSASigner() { + if (isEDDSACurveSupported()) { + return EdDSASecurityProvider.getEDDSASignature(); + } + + throw new UnsupportedOperationException(EDDSA + " Signer not available"); + } + + public static int getEDDSAKeySize(Key key) { + return EdDSASecurityProvider.getEDDSAKeySize(key); + } + + public static Class<? extends PublicKey> getEDDSAPublicKeyType() { + return isEDDSACurveSupported() ? EdDSASecurityProvider.getEDDSAPublicKeyType() : PublicKey.class; + } + + public static Class<? extends PrivateKey> getEDDSAPrivateKeyType() { + return isEDDSACurveSupported() ? EdDSASecurityProvider.getEDDSAPrivateKeyType() : PrivateKey.class; + } + + public static boolean compareEDDSAPPublicKeys(PublicKey k1, PublicKey k2) { + return isEDDSACurveSupported() ? EdDSASecurityProvider.compareEDDSAPPublicKeys(k1, k2) : false; + } + + public static boolean compareEDDSAPrivateKeys(PrivateKey k1, PrivateKey k2) { + return isEDDSACurveSupported() ? EdDSASecurityProvider.compareEDDSAPrivateKeys(k1, k2) : false; + } + + public static PublicKey generateEDDSAPublicKey(String keyType, byte[] seed) throws GeneralSecurityException { + if (!KeyPairProvider.SSH_ED25519.equals(keyType)) { + throw new InvalidKeyException("Unsupported key type: " + keyType); + } + + if (!isEDDSACurveSupported()) { + throw new NoSuchAlgorithmException(EDDSA + " provider not supported"); + } + + return EdDSASecurityProvider.generateEDDSAPublicKey(seed); + } + + public static <B extends Buffer> B putRawEDDSAPublicKey(B buffer, PublicKey key) { + if (!isEDDSACurveSupported()) { + throw new UnsupportedOperationException(EDDSA + " provider not supported"); + } + + return EdDSASecurityProvider.putRawEDDSAPublicKey(buffer, key); + } + + public static <B extends Buffer> B putEDDSAKeyPair(B buffer, KeyPair kp) { + return putEDDSAKeyPair(buffer, Objects.requireNonNull(kp, "No key pair").getPublic(), kp.getPrivate()); + } + + public static <B extends Buffer> B putEDDSAKeyPair(B buffer, PublicKey pubKey, PrivateKey prvKey) { + if (!isEDDSACurveSupported()) { + throw new UnsupportedOperationException(EDDSA + " provider not supported"); + } + + return EdDSASecurityProvider.putEDDSAKeyPair(buffer, pubKey, prvKey); + } + + public static KeyPair extractEDDSAKeyPair(Buffer buffer, String keyType) throws GeneralSecurityException { + if (!KeyPairProvider.SSH_ED25519.equals(keyType)) { + throw new InvalidKeyException("Unsupported key type: " + keyType); + } + + if (!isEDDSACurveSupported()) { + throw new NoSuchAlgorithmException(EDDSA + " provider not supported"); + } + + throw new GeneralSecurityException("Full SSHD-440 implementation N/A"); + } + + ////////////////////////////////////////////////////////////////////////// + + public static synchronized KeyFactory getKeyFactory(String algorithm) throws GeneralSecurityException { + register(); + + String providerName = getDefaultProvider(); + if (isEDDSACurveSupported() && EdDSASecurityProvider.isEDDSAKeyFactoryAlgorithm(algorithm)) { + providerName = EDDSA; + } + + if (GenericUtils.isEmpty(providerName)) { + return KeyFactory.getInstance(algorithm); + } else { + return KeyFactory.getInstance(algorithm, providerName); + } + } + + public static synchronized Cipher getCipher(String transformation) throws GeneralSecurityException { + register(); + + String providerName = getDefaultProvider(); + if (GenericUtils.isEmpty(providerName)) { + return Cipher.getInstance(transformation); + } else { + return Cipher.getInstance(transformation, providerName); + } + } + + public static synchronized MessageDigest getMessageDigest(String algorithm) throws GeneralSecurityException { + register(); + + String providerName = getDefaultProvider(); + if (GenericUtils.isEmpty(providerName)) { + return MessageDigest.getInstance(algorithm); + } else { + return MessageDigest.getInstance(algorithm, providerName); + } + } + + public static synchronized KeyPairGenerator getKeyPairGenerator(String algorithm) throws GeneralSecurityException { + register(); + + String providerName = getDefaultProvider(); + if (isEDDSACurveSupported() && EdDSASecurityProvider.isEDDSAKeyPairGeneratorAlgorithm(algorithm)) { + providerName = EDDSA; + } + + if (GenericUtils.isEmpty(providerName)) { + return KeyPairGenerator.getInstance(algorithm); + } else { + return KeyPairGenerator.getInstance(algorithm, providerName); + } + } + + public static synchronized KeyAgreement getKeyAgreement(String algorithm) throws GeneralSecurityException { + register(); + + String providerName = getDefaultProvider(); + if (GenericUtils.isEmpty(providerName)) { + return KeyAgreement.getInstance(algorithm); + } else { + return KeyAgreement.getInstance(algorithm, providerName); + } + } + + public static synchronized Mac getMac(String algorithm) throws GeneralSecurityException { + register(); + + String providerName = getDefaultProvider(); + if (GenericUtils.isEmpty(providerName)) { + return Mac.getInstance(algorithm); + } else { + return Mac.getInstance(algorithm, providerName); + } + } + + public static synchronized Signature getSignature(String algorithm) throws GeneralSecurityException { + register(); + + String providerName = getDefaultProvider(); + if (isEDDSACurveSupported() && EdDSASecurityProvider.isEDDSASignatureAlgorithm(algorithm)) { + providerName = EDDSA; + } + + if (GenericUtils.isEmpty(providerName)) { + return Signature.getInstance(algorithm); + } else { + return Signature.getInstance(algorithm, providerName); + } + } + + public static synchronized CertificateFactory getCertificateFactory(String type) throws GeneralSecurityException { + register(); + + String providerName = getDefaultProvider(); + if (GenericUtils.isEmpty(providerName)) { + return CertificateFactory.getInstance(type); + } else { + return CertificateFactory.getInstance(type, providerName); + } + } +} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleClassLoadableResourceKeyPairProvider.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleClassLoadableResourceKeyPairProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleClassLoadableResourceKeyPairProvider.java new file mode 100644 index 0000000..7626e13 --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleClassLoadableResourceKeyPairProvider.java @@ -0,0 +1,42 @@ +/* + * 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.util.security.bouncycastle; + +import java.io.IOException; +import java.io.InputStream; +import java.security.GeneralSecurityException; +import java.security.KeyPair; + +import org.apache.sshd.common.config.keys.FilePasswordProvider; +import org.apache.sshd.common.keyprovider.AbstractClassLoadableResourceKeyPairProvider; + +/** + * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> + */ +public class BouncyCastleClassLoadableResourceKeyPairProvider extends AbstractClassLoadableResourceKeyPairProvider { + public BouncyCastleClassLoadableResourceKeyPairProvider() { + super(); + } + + @Override + protected KeyPair doLoadKey(String resourceKey, InputStream inputStream, FilePasswordProvider provider) + throws IOException, GeneralSecurityException { + return BouncyCastleInputStreamLoader.loadKeyPair(resourceKey, inputStream, provider); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleFileKeyPairProvider.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleFileKeyPairProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleFileKeyPairProvider.java new file mode 100644 index 0000000..a078644 --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleFileKeyPairProvider.java @@ -0,0 +1,42 @@ +/* + * 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.util.security.bouncycastle; + +import java.io.IOException; +import java.io.InputStream; +import java.security.GeneralSecurityException; +import java.security.KeyPair; + +import org.apache.sshd.common.config.keys.FilePasswordProvider; +import org.apache.sshd.common.keyprovider.AbstractFileKeyPairProvider; + +/** + * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> + */ +public class BouncyCastleFileKeyPairProvider extends AbstractFileKeyPairProvider { + public BouncyCastleFileKeyPairProvider() { + super(); + } + + @Override + protected KeyPair doLoadKey(String resourceKey, InputStream inputStream, FilePasswordProvider provider) + throws IOException, GeneralSecurityException { + return BouncyCastleInputStreamLoader.loadKeyPair(resourceKey, inputStream, provider); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java new file mode 100644 index 0000000..2eb874c --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleGeneratorHostKeyProvider.java @@ -0,0 +1,54 @@ +/* + * 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.util.security.bouncycastle; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.security.GeneralSecurityException; +import java.security.KeyPair; + +import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvider; + +/** + * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> + */ +public class BouncyCastleGeneratorHostKeyProvider extends AbstractGeneratorHostKeyProvider { + public BouncyCastleGeneratorHostKeyProvider(Path path) { + setPath(path); + } + + @Override + protected KeyPair doReadKeyPair(String resourceKey, InputStream inputStream) throws IOException, GeneralSecurityException { + return BouncyCastleInputStreamLoader.loadKeyPair(resourceKey, inputStream, null); + } + + @SuppressWarnings("deprecation") + @Override + protected void doWriteKeyPair(String resourceKey, KeyPair kp, OutputStream outputStream) throws IOException, GeneralSecurityException { + try (org.bouncycastle.openssl.PEMWriter w = + new org.bouncycastle.openssl.PEMWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8))) { + w.writeObject(kp); + w.flush(); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleInputStreamLoader.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleInputStreamLoader.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleInputStreamLoader.java new file mode 100644 index 0000000..214802c --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleInputStreamLoader.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sshd.common.util.security.bouncycastle; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.security.GeneralSecurityException; +import java.security.KeyPair; + +import org.apache.sshd.common.config.keys.FilePasswordProvider; +import org.apache.sshd.common.util.ValidateUtils; +import org.apache.sshd.common.util.security.SecurityUtils; +import org.bouncycastle.openssl.PEMDecryptorProvider; +import org.bouncycastle.openssl.PEMEncryptedKeyPair; +import org.bouncycastle.openssl.PEMKeyPair; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; + +/** + * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> + */ +public interface BouncyCastleInputStreamLoader { + static KeyPair loadKeyPair(String resourceKey, InputStream inputStream, FilePasswordProvider provider) + throws IOException, GeneralSecurityException { + try (PEMParser r = new PEMParser(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { + Object o = r.readObject(); + + JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter(); + pemConverter.setProvider(SecurityUtils.BOUNCY_CASTLE); + if (o instanceof PEMEncryptedKeyPair) { + ValidateUtils.checkNotNull(provider, "No password provider for resource=%s", resourceKey); + + String password = ValidateUtils.checkNotNullAndNotEmpty(provider.getPassword(resourceKey), "No password provided for resource=%s", resourceKey); + JcePEMDecryptorProviderBuilder decryptorBuilder = new JcePEMDecryptorProviderBuilder(); + PEMDecryptorProvider pemDecryptor = decryptorBuilder.build(password.toCharArray()); + o = ((PEMEncryptedKeyPair) o).decryptKeyPair(pemDecryptor); + } + + if (o instanceof PEMKeyPair) { + return pemConverter.getKeyPair((PEMKeyPair) o); + } else if (o instanceof KeyPair) { + return (KeyPair) o; + } else { + throw new IOException("Failed to read " + resourceKey + " - unknown result object: " + o); + } + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandom.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandom.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandom.java new file mode 100644 index 0000000..36c23e7 --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandom.java @@ -0,0 +1,88 @@ +/* + * 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.util.security.bouncycastle; + +import java.security.SecureRandom; + +import org.apache.sshd.common.random.AbstractRandom; +import org.apache.sshd.common.util.ValidateUtils; +import org.apache.sshd.common.util.security.SecurityUtils; +import org.bouncycastle.crypto.prng.RandomGenerator; +import org.bouncycastle.crypto.prng.VMPCRandomGenerator; + +/** + * BouncyCastle <code>Random</code>. + * This pseudo random number generator uses the a very fast PRNG from BouncyCastle. + * The JRE random will be used when creating a new generator to add some random + * data to the seed. + * + * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> + */ +public final class BouncyCastleRandom extends AbstractRandom { + public static final String NAME = SecurityUtils.BOUNCY_CASTLE; + private final RandomGenerator random; + + public BouncyCastleRandom() { + ValidateUtils.checkTrue(SecurityUtils.isBouncyCastleRegistered(), "BouncyCastle not registered"); + this.random = new VMPCRandomGenerator(); + byte[] seed = new SecureRandom().generateSeed(8); + this.random.addSeedMaterial(seed); + } + + @Override + public String getName() { + return NAME; + } + + @Override + public void fill(byte[] bytes, int start, int len) { + this.random.nextBytes(bytes, start, len); + } + + /** + * Returns a pseudo-random uniformly distributed {@code int} + * in the half-open range [0, n). + */ + @Override + public int random(int n) { + ValidateUtils.checkTrue(n > 0, "Limit must be positive: %d", n); + if ((n & -n) == n) { + return (int) ((n * (long) next(31)) >> 31); + } + + int bits; + int val; + do { + bits = next(31); + val = bits % n; + } while (bits - val + (n - 1) < 0); + return val; + } + + private int next(int numBits) { + int bytes = (numBits + 7) / 8; + byte next[] = new byte[bytes]; + int ret = 0; + random.nextBytes(next); + for (int i = 0; i < bytes; i++) { + ret = (next[i] & 0xFF) | (ret << 8); + } + return ret >>> (bytes * 8 - numBits); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandomFactory.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandomFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandomFactory.java new file mode 100644 index 0000000..720c7a5 --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleRandomFactory.java @@ -0,0 +1,45 @@ +/* + * 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.util.security.bouncycastle; + +import org.apache.sshd.common.random.AbstractRandomFactory; +import org.apache.sshd.common.random.Random; +import org.apache.sshd.common.util.security.SecurityUtils; + +/** + * Named factory for the BouncyCastle <code>Random</code> + */ +public final class BouncyCastleRandomFactory extends AbstractRandomFactory { + public static final String NAME = "bouncycastle"; + public static final BouncyCastleRandomFactory INSTANCE = new BouncyCastleRandomFactory(); + + public BouncyCastleRandomFactory() { + super(NAME); + } + + @Override + public boolean isSupported() { + return SecurityUtils.isBouncyCastleRegistered(); + } + + @Override + public Random create() { + return new BouncyCastleRandom(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/Ed25519PublicKeyDecoder.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/Ed25519PublicKeyDecoder.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/Ed25519PublicKeyDecoder.java new file mode 100644 index 0000000..a482bbe --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/Ed25519PublicKeyDecoder.java @@ -0,0 +1,107 @@ +/* + * 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.util.security.eddsa; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.GeneralSecurityException; +import java.security.KeyFactory; +import java.security.KeyPairGenerator; +import java.util.Collections; +import java.util.Objects; + +import net.i2p.crypto.eddsa.EdDSAPrivateKey; +import net.i2p.crypto.eddsa.EdDSAPublicKey; +import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec; +import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec; + +import org.apache.sshd.common.config.keys.AbstractPublicKeyEntryDecoder; +import org.apache.sshd.common.config.keys.PublicKeyEntryDecoder; +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 final class Ed25519PublicKeyDecoder extends AbstractPublicKeyEntryDecoder<EdDSAPublicKey, EdDSAPrivateKey> { + public static final Ed25519PublicKeyDecoder INSTANCE = new Ed25519PublicKeyDecoder(); + + private Ed25519PublicKeyDecoder() { + super(EdDSAPublicKey.class, EdDSAPrivateKey.class, Collections.unmodifiableList(Collections.singletonList(KeyPairProvider.SSH_ED25519))); + } + + @Override + public EdDSAPublicKey clonePublicKey(EdDSAPublicKey key) throws GeneralSecurityException { + if (key == null) { + return null; + } else { + return generatePublicKey(new EdDSAPublicKeySpec(key.getA(), key.getParams())); + } + } + + @Override + public EdDSAPrivateKey clonePrivateKey(EdDSAPrivateKey key) throws GeneralSecurityException { + if (key == null) { + return null; + } else { + return generatePrivateKey(new EdDSAPrivateKeySpec(key.getSeed(), key.getParams())); + } + } + + @Override + public KeyPairGenerator getKeyPairGenerator() throws GeneralSecurityException { + return SecurityUtils.getKeyPairGenerator(SecurityUtils.EDDSA); + } + + @Override + public String encodePublicKey(OutputStream s, EdDSAPublicKey key) throws IOException { + Objects.requireNonNull(key, "No public key provided"); + PublicKeyEntryDecoder.encodeString(s, KeyPairProvider.SSH_ED25519); + byte[] seed = getSeedValue(key); + PublicKeyEntryDecoder.writeRLEBytes(s, seed); + return KeyPairProvider.SSH_ED25519; + } + + @Override + public KeyFactory getKeyFactoryInstance() throws GeneralSecurityException { + return SecurityUtils.getKeyFactory(SecurityUtils.EDDSA); + } + + @Override + public EdDSAPublicKey decodePublicKey(String keyType, InputStream keyData) throws IOException, GeneralSecurityException { + byte[] seed = PublicKeyEntryDecoder.readRLEBytes(keyData); + return EdDSAPublicKey.class.cast(SecurityUtils.generateEDDSAPublicKey(keyType, seed)); + } + + public static byte[] getSeedValue(EdDSAPublicKey key) { + // a bit of reverse-engineering on the EdDSAPublicKeySpec + return (key == null) ? null : key.getAbyte(); + } + + public static EdDSAPublicKey fromPrivateKey(EdDSAPrivateKey prvKey) throws GeneralSecurityException { + if (prvKey == null) { + return null; + } + + EdDSAPublicKeySpec keySpec = new EdDSAPublicKeySpec(prvKey.getSeed(), prvKey.getParams()); + KeyFactory factory = SecurityUtils.getKeyFactory(SecurityUtils.EDDSA); + return EdDSAPublicKey.class.cast(factory.generatePublic(keySpec)); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProvider.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProvider.java new file mode 100644 index 0000000..daaac49 --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProvider.java @@ -0,0 +1,174 @@ +/* + * 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.util.security.eddsa; + +import java.security.GeneralSecurityException; +import java.security.Key; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.PublicKey; +import java.util.Arrays; +import java.util.Objects; + +import net.i2p.crypto.eddsa.EdDSAKey; +import net.i2p.crypto.eddsa.EdDSAPrivateKey; +import net.i2p.crypto.eddsa.EdDSAPublicKey; +import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable; +import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec; +import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec; + +import org.apache.sshd.common.config.keys.PublicKeyEntryDecoder; +import org.apache.sshd.common.keyprovider.KeyPairProvider; +import org.apache.sshd.common.util.ValidateUtils; +import org.apache.sshd.common.util.buffer.Buffer; +import org.apache.sshd.common.util.security.SecurityUtils; + +/** + * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> + */ +public class EdDSASecurityProvider extends Provider { + private static final long serialVersionUID = -6183277432144104981L; + + public EdDSASecurityProvider() { + super(SecurityUtils.EDDSA, 0.1, "net.i2p security provider wrapper"); + + // see https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/HowToImplAProvider.html + put("KeyPairGenerator." + SecurityUtils.EDDSA, "net.i2p.crypto.eddsa.KeyPairGenerator"); + put("KeyFactory." + SecurityUtils.EDDSA, "net.i2p.crypto.eddsa.KeyFactory"); + put("Signature." + EdDSANamedCurveTable.CURVE_ED25519_SHA512, "net.i2p.crypto.eddsa.EdDSAEngine"); + } + + public static Class<? extends PublicKey> getEDDSAPublicKeyType() { + return EdDSAPublicKey.class; + } + + public static Class<? extends PrivateKey> getEDDSAPrivateKeyType() { + return EdDSAPrivateKey.class; + } + + public static int getEDDSAKeySize(Key key) { + return (SecurityUtils.isEDDSACurveSupported() && (key instanceof EdDSAKey)) ? 256 : -1; + } + + public static boolean compareEDDSAPPublicKeys(PublicKey k1, PublicKey k2) { + if (!SecurityUtils.isEDDSACurveSupported()) { + return false; + } + + if ((k1 instanceof EdDSAPublicKey) && (k2 instanceof EdDSAPublicKey)) { + if (Objects.equals(k1, k2)) { + return true; + } else if (k1 == null || k2 == null) { + return false; // both null is covered by Objects#equals + } + + EdDSAPublicKey ed1 = (EdDSAPublicKey) k1; + EdDSAPublicKey ed2 = (EdDSAPublicKey) k2; + return Arrays.equals(ed1.getAbyte(), ed2.getAbyte()) + && compareEDDSAKeyParams(ed1.getParams(), ed2.getParams()); + } + + return false; + } + + public static boolean isEDDSASignatureAlgorithm(String algorithm) { + return EdDSANamedCurveTable.CURVE_ED25519_SHA512.equalsIgnoreCase(algorithm); + } + + public static org.apache.sshd.common.signature.Signature getEDDSASignature() { + ValidateUtils.checkTrue(SecurityUtils.isEDDSACurveSupported(), SecurityUtils.EDDSA + " not supported"); + return new SignatureEd25519(); + } + + public static boolean isEDDSAKeyFactoryAlgorithm(String algorithm) { + return SecurityUtils.EDDSA.equalsIgnoreCase(algorithm); + } + + public static boolean isEDDSAKeyPairGeneratorAlgorithm(String algorithm) { + return SecurityUtils.EDDSA.equalsIgnoreCase(algorithm); + } + + public static PublicKeyEntryDecoder<? extends PublicKey, ? extends PrivateKey> getEDDSAPublicKeyEntryDecoder() { + ValidateUtils.checkTrue(SecurityUtils.isEDDSACurveSupported(), SecurityUtils.EDDSA + " not supported"); + return Ed25519PublicKeyDecoder.INSTANCE; + } + + public static boolean compareEDDSAPrivateKeys(PrivateKey k1, PrivateKey k2) { + if (!SecurityUtils.isEDDSACurveSupported()) { + return false; + } + + if ((k1 instanceof EdDSAPrivateKey) && (k2 instanceof EdDSAPrivateKey)) { + if (Objects.equals(k1, k2)) { + return true; + } else if (k1 == null || k2 == null) { + return false; // both null is covered by Objects#equals + } + + EdDSAPrivateKey ed1 = (EdDSAPrivateKey) k1; + EdDSAPrivateKey ed2 = (EdDSAPrivateKey) k2; + return Arrays.equals(ed1.getSeed(), ed2.getSeed()) + && compareEDDSAKeyParams(ed1.getParams(), ed2.getParams()); + } + + return false; + } + + public static boolean compareEDDSAKeyParams(EdDSAParameterSpec s1, EdDSAParameterSpec s2) { + if (Objects.equals(s1, s2)) { + return true; + } else if (s1 == null || s2 == null) { + return false; // both null is covered by Objects#equals + } else { + return Objects.equals(s1.getHashAlgorithm(), s2.getHashAlgorithm()) + && Objects.equals(s1.getCurve(), s2.getCurve()) + && Objects.equals(s1.getB(), s2.getB()); + } + } + + public static PublicKey generateEDDSAPublicKey(byte[] seed) throws GeneralSecurityException { + if (!SecurityUtils.isEDDSACurveSupported()) { + throw new NoSuchAlgorithmException(SecurityUtils.EDDSA + " not supported"); + } + + EdDSAParameterSpec params = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512); + EdDSAPublicKeySpec keySpec = new EdDSAPublicKeySpec(seed, params); + KeyFactory factory = SecurityUtils.getKeyFactory(SecurityUtils.EDDSA); + return factory.generatePublic(keySpec); + } + + public static <B extends Buffer> B putRawEDDSAPublicKey(B buffer, PublicKey key) { + ValidateUtils.checkTrue(SecurityUtils.isEDDSACurveSupported(), SecurityUtils.EDDSA + " not supported"); + EdDSAPublicKey edKey = ValidateUtils.checkInstanceOf(key, EdDSAPublicKey.class, "Not an EDDSA public key: %s", key); + byte[] seed = Ed25519PublicKeyDecoder.getSeedValue(edKey); + ValidateUtils.checkNotNull(seed, "No seed extracted from key: %s", edKey.getA()); + buffer.putString(KeyPairProvider.SSH_ED25519); + buffer.putBytes(seed); + return buffer; + } + + public static <B extends Buffer> B putEDDSAKeyPair(B buffer, PublicKey pubKey, PrivateKey prvKey) { + ValidateUtils.checkTrue(SecurityUtils.isEDDSACurveSupported(), SecurityUtils.EDDSA + " not supported"); + ValidateUtils.checkInstanceOf(pubKey, EdDSAPublicKey.class, "Not an EDDSA public key: %s", pubKey); + ValidateUtils.checkInstanceOf(prvKey, EdDSAPrivateKey.class, "Not an EDDSA private key: %s", prvKey); + throw new UnsupportedOperationException("Full SSHD-440 implementation N/A"); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/SignatureEd25519.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/SignatureEd25519.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/SignatureEd25519.java new file mode 100644 index 0000000..97a7cf9 --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/SignatureEd25519.java @@ -0,0 +1,48 @@ +/* + * 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.util.security.eddsa; + +import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable; + +import org.apache.sshd.common.keyprovider.KeyPairProvider; +import org.apache.sshd.common.signature.AbstractSignature; +import org.apache.sshd.common.util.Pair; +import org.apache.sshd.common.util.ValidateUtils; + +/** + * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> + */ +public class SignatureEd25519 extends AbstractSignature { + public SignatureEd25519() { + super(EdDSANamedCurveTable.CURVE_ED25519_SHA512); + } + + @Override + public boolean verify(byte[] sig) throws Exception { + byte[] data = sig; + Pair<String, byte[]> encoding = extractEncodedSignature(data); + if (encoding != null) { + String keyType = encoding.getFirst(); + ValidateUtils.checkTrue(KeyPairProvider.SSH_ED25519.equals(keyType), "Mismatched key type: %s", keyType); + data = encoding.getSecond(); + } + + return doVerify(data); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java b/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java index 53278e1..aa06c44 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java @@ -57,8 +57,8 @@ import org.apache.sshd.common.keyprovider.KeyPairProvider; import org.apache.sshd.common.keyprovider.MappedKeyPairProvider; import org.apache.sshd.common.session.helpers.AbstractSession; import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.common.util.ValidateUtils; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.server.auth.UserAuth; import org.apache.sshd.server.auth.gss.GSSAuthenticator; import org.apache.sshd.server.auth.hostbased.HostBasedAuthenticator; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/main/java/org/apache/sshd/server/auth/hostbased/UserAuthHostBased.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/hostbased/UserAuthHostBased.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/hostbased/UserAuthHostBased.java index c48ebb6..20e7b31 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/auth/hostbased/UserAuthHostBased.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/hostbased/UserAuthHostBased.java @@ -35,11 +35,11 @@ import org.apache.sshd.common.config.keys.KeyUtils; import org.apache.sshd.common.signature.Signature; import org.apache.sshd.common.signature.SignatureFactoriesManager; import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.buffer.BufferUtils; import org.apache.sshd.common.util.buffer.ByteArrayBuffer; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.server.auth.AbstractUserAuth; import org.apache.sshd.server.session.ServerSession; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/main/java/org/apache/sshd/server/config/keys/ServerIdentity.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/config/keys/ServerIdentity.java b/sshd-core/src/main/java/org/apache/sshd/server/config/keys/ServerIdentity.java index f31db14..5e61879 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/config/keys/ServerIdentity.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/config/keys/ServerIdentity.java @@ -44,7 +44,7 @@ import org.apache.sshd.server.SshServer; * Loads server identity key files - e.g., {@code /etc/ssh/ssh_host_rsa_key} * * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - * @see org.apache.sshd.common.util.SecurityUtils#isBouncyCastleRegistered() + * @see org.apache.sshd.common.util.security.SecurityUtils#isBouncyCastleRegistered() */ public final class ServerIdentity { http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java index 623a7bd..f107165 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java @@ -44,11 +44,11 @@ import org.apache.sshd.common.random.Random; import org.apache.sshd.common.session.Session; import org.apache.sshd.common.signature.Signature; import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.buffer.BufferUtils; import org.apache.sshd.common.util.buffer.ByteArrayBuffer; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.server.ServerFactoryManager; import org.apache.sshd.server.session.ServerSession; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java b/sshd-core/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java index fbf709d..8799a8a 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java @@ -40,8 +40,8 @@ import org.apache.sshd.common.cipher.ECCurves; import org.apache.sshd.common.config.keys.BuiltinIdentities; import org.apache.sshd.common.config.keys.KeyUtils; import org.apache.sshd.common.keyprovider.AbstractKeyPairProvider; -import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.common.util.io.IoUtils; +import org.apache.sshd.common.util.security.SecurityUtils; /** * Holds a <U>single</U> {@link KeyPair} which is generated the 1st time http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java b/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java index 3ebff89..2f0e01d 100644 --- a/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java @@ -52,8 +52,8 @@ import org.apache.sshd.common.kex.KeyExchange; import org.apache.sshd.common.session.Session; import org.apache.sshd.common.session.SessionListener; import org.apache.sshd.common.subsystem.sftp.SftpConstants; -import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.common.util.io.NullOutputStream; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.server.SshServer; import org.apache.sshd.util.test.BaseTestSupport; import org.apache.sshd.util.test.JSchLogger; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java b/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java index bdf7321..3442042 100644 --- a/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java @@ -37,7 +37,7 @@ import org.apache.sshd.client.channel.ChannelShell; import org.apache.sshd.client.session.ClientSession; import org.apache.sshd.common.keyprovider.KeyPairProvider; import org.apache.sshd.common.util.Pair; -import org.apache.sshd.common.util.SecurityUtils; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.server.Command; import org.apache.sshd.server.Environment; import org.apache.sshd.server.SshServer; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityTest.java b/sshd-core/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityTest.java index 4618a8c..6f41196 100644 --- a/sshd-core/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityTest.java @@ -32,8 +32,8 @@ import org.apache.sshd.common.config.keys.BuiltinIdentities; import org.apache.sshd.common.config.keys.IdentityUtils; import org.apache.sshd.common.keyprovider.KeyIdentityProvider; import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.common.util.io.IoUtils; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.util.test.BaseTestSupport; import org.junit.Assume; import org.junit.FixMethodOrder; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java b/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java index 35fa9e0..b9e47f3 100644 --- a/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java @@ -38,7 +38,7 @@ import org.apache.sshd.common.NamedFactory; import org.apache.sshd.common.channel.Channel; import org.apache.sshd.common.kex.BuiltinDHFactories; import org.apache.sshd.common.kex.KeyExchange; -import org.apache.sshd.common.util.SecurityUtils; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.server.SshServer; import org.apache.sshd.util.test.BaseTestSupport; import org.apache.sshd.util.test.TeeOutputStream; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/common/cipher/BaseCipherTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/cipher/BaseCipherTest.java b/sshd-core/src/test/java/org/apache/sshd/common/cipher/BaseCipherTest.java index 195fcb1..2608be9 100644 --- a/sshd-core/src/test/java/org/apache/sshd/common/cipher/BaseCipherTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/common/cipher/BaseCipherTest.java @@ -28,7 +28,7 @@ import javax.crypto.spec.SecretKeySpec; import org.apache.sshd.common.NamedFactory; import org.apache.sshd.common.cipher.Cipher.Mode; -import org.apache.sshd.common.util.SecurityUtils; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.util.test.BaseTestSupport; import org.junit.Assume; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/common/config/keys/AuthorizedKeysTestSupport.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/config/keys/AuthorizedKeysTestSupport.java b/sshd-core/src/test/java/org/apache/sshd/common/config/keys/AuthorizedKeysTestSupport.java index ae8483e..b85fb1e 100644 --- a/sshd-core/src/test/java/org/apache/sshd/common/config/keys/AuthorizedKeysTestSupport.java +++ b/sshd-core/src/test/java/org/apache/sshd/common/config/keys/AuthorizedKeysTestSupport.java @@ -36,10 +36,10 @@ import java.util.Objects; import org.apache.sshd.common.cipher.ECCurves; import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.common.util.io.IoUtils; import org.apache.sshd.common.util.io.NoCloseInputStream; import org.apache.sshd.common.util.io.NoCloseReader; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.server.config.keys.AuthorizedKeysAuthenticator; import org.apache.sshd.util.test.BaseTestSupport; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/common/config/keys/BuiltinIdentitiesTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/config/keys/BuiltinIdentitiesTest.java b/sshd-core/src/test/java/org/apache/sshd/common/config/keys/BuiltinIdentitiesTest.java index 27a73ff..eec81c7 100644 --- a/sshd-core/src/test/java/org/apache/sshd/common/config/keys/BuiltinIdentitiesTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/common/config/keys/BuiltinIdentitiesTest.java @@ -25,7 +25,7 @@ import java.security.GeneralSecurityException; import java.security.KeyPair; import java.security.KeyPairGenerator; -import org.apache.sshd.common.util.SecurityUtils; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.util.test.BaseTestSupport; import org.junit.FixMethodOrder; import org.junit.Test; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyRandomArtTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyRandomArtTest.java b/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyRandomArtTest.java index 6d131fb..b3ff78f 100644 --- a/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyRandomArtTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyRandomArtTest.java @@ -27,7 +27,7 @@ import java.util.List; import org.apache.sshd.common.cipher.ECCurves; import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.SecurityUtils; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.util.test.BaseTestSupport; import org.apache.sshd.util.test.Utils; import org.junit.AfterClass; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsCloneTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsCloneTest.java b/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsCloneTest.java index 7a7b923..6185de2 100644 --- a/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsCloneTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsCloneTest.java @@ -30,8 +30,8 @@ import java.util.List; import org.apache.sshd.common.cipher.ECCurves; import org.apache.sshd.common.keyprovider.KeyPairProvider; -import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.common.util.ValidateUtils; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.util.test.BaseTestSupport; import org.junit.FixMethodOrder; import org.junit.Test; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/common/random/RandomFactoryTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/random/RandomFactoryTest.java b/sshd-core/src/test/java/org/apache/sshd/common/random/RandomFactoryTest.java index 17e420c..254bc8e 100644 --- a/sshd-core/src/test/java/org/apache/sshd/common/random/RandomFactoryTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/common/random/RandomFactoryTest.java @@ -22,7 +22,7 @@ import java.util.Collection; import java.util.LinkedList; import java.util.concurrent.TimeUnit; -import org.apache.sshd.common.util.SecurityUtils; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.util.test.BaseTestSupport; import org.junit.Assume; import org.junit.FixMethodOrder; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureFactoriesTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureFactoriesTest.java b/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureFactoriesTest.java index 54e7531..d85b7f9 100644 --- a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureFactoriesTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureFactoriesTest.java @@ -38,8 +38,8 @@ import org.apache.sshd.common.config.keys.ECDSAPublicKeyEntryDecoder; import org.apache.sshd.common.config.keys.PublicKeyEntryDecoder; import org.apache.sshd.common.config.keys.RSAPublicKeyDecoder; import org.apache.sshd.common.keyprovider.KeyPairProvider; -import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.common.util.ValidateUtils; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.server.SshServer; import org.apache.sshd.util.test.BaseTestSupport; import org.apache.sshd.util.test.Utils; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureRSATest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureRSATest.java b/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureRSATest.java index b631be7..3534d32 100644 --- a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureRSATest.java +++ b/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureRSATest.java @@ -29,7 +29,7 @@ import org.apache.sshd.common.Factory; import org.apache.sshd.common.config.keys.KeyUtils; import org.apache.sshd.common.util.Base64; import org.apache.sshd.common.util.Pair; -import org.apache.sshd.common.util.SecurityUtils; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.util.test.BaseTestSupport; import org.junit.BeforeClass; import org.junit.FixMethodOrder; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/common/util/EDDSAProviderTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/util/EDDSAProviderTest.java b/sshd-core/src/test/java/org/apache/sshd/common/util/EDDSAProviderTest.java index babe463..ab25821 100644 --- a/sshd-core/src/test/java/org/apache/sshd/common/util/EDDSAProviderTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/common/util/EDDSAProviderTest.java @@ -34,6 +34,7 @@ import org.apache.sshd.common.config.keys.KeyUtils; import org.apache.sshd.common.keyprovider.KeyPairProvider; import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.buffer.ByteArrayBuffer; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.util.test.BaseTestSupport; import org.junit.Assume; import org.junit.BeforeClass; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/common/util/SecurityUtilsTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/util/SecurityUtilsTest.java b/sshd-core/src/test/java/org/apache/sshd/common/util/SecurityUtilsTest.java index 310fb79..3fbfc3d 100644 --- a/sshd-core/src/test/java/org/apache/sshd/common/util/SecurityUtilsTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/common/util/SecurityUtilsTest.java @@ -43,6 +43,7 @@ import org.apache.sshd.common.config.keys.KeyUtils; import org.apache.sshd.common.keyprovider.AbstractClassLoadableResourceKeyPairProvider; import org.apache.sshd.common.keyprovider.AbstractFileKeyPairProvider; import org.apache.sshd.common.keyprovider.AbstractResourceKeyPairProvider; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.util.test.BaseTestSupport; import org.junit.Assume; import org.junit.FixMethodOrder; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/server/config/keys/ServerIdentityTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/server/config/keys/ServerIdentityTest.java b/sshd-core/src/test/java/org/apache/sshd/server/config/keys/ServerIdentityTest.java index 7f654ba..7738669 100644 --- a/sshd-core/src/test/java/org/apache/sshd/server/config/keys/ServerIdentityTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/server/config/keys/ServerIdentityTest.java @@ -33,8 +33,8 @@ import org.apache.sshd.common.config.keys.BuiltinIdentities; import org.apache.sshd.common.config.keys.IdentityUtils; import org.apache.sshd.common.keyprovider.KeyPairProvider; import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.common.util.io.IoUtils; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.util.test.BaseTestSupport; import org.junit.Assume; import org.junit.FixMethodOrder; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java b/sshd-core/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java index f6844d1..6f35a61 100644 --- a/sshd-core/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java @@ -30,8 +30,8 @@ import java.security.spec.ECGenParameterSpec; import org.apache.sshd.common.cipher.ECCurves; import org.apache.sshd.common.config.keys.KeyUtils; import org.apache.sshd.common.keyprovider.KeyPairProvider; -import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.common.util.io.IoUtils; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.util.test.BaseTestSupport; import org.junit.Assume; import org.junit.FixMethodOrder; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java b/sshd-core/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java index c349aad..2b8db21 100644 --- a/sshd-core/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java @@ -28,8 +28,8 @@ import java.security.spec.ECGenParameterSpec; import org.apache.sshd.common.cipher.ECCurves; import org.apache.sshd.common.config.keys.KeyUtils; import org.apache.sshd.common.keyprovider.KeyPairProvider; -import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.common.util.io.IoUtils; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.util.test.BaseTestSupport; import org.junit.Assume; import org.junit.FixMethodOrder; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/server/subsystem/sftp/SshFsMounter.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/server/subsystem/sftp/SshFsMounter.java b/sshd-core/src/test/java/org/apache/sshd/server/subsystem/sftp/SshFsMounter.java index 6287a50..e67cf23 100644 --- a/sshd-core/src/test/java/org/apache/sshd/server/subsystem/sftp/SshFsMounter.java +++ b/sshd-core/src/test/java/org/apache/sshd/server/subsystem/sftp/SshFsMounter.java @@ -38,9 +38,9 @@ import org.apache.sshd.common.io.IoServiceFactory; import org.apache.sshd.common.io.mina.MinaServiceFactory; import org.apache.sshd.common.io.nio2.Nio2ServiceFactory; import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.logging.AbstractLoggingBean; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.common.util.threads.ThreadUtils; import org.apache.sshd.server.Command; import org.apache.sshd.server.CommandFactory; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ed064a09/sshd-core/src/test/java/org/apache/sshd/util/test/Utils.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/util/test/Utils.java b/sshd-core/src/test/java/org/apache/sshd/util/test/Utils.java index 8aada83..d5439fe 100644 --- a/sshd-core/src/test/java/org/apache/sshd/util/test/Utils.java +++ b/sshd-core/src/test/java/org/apache/sshd/util/test/Utils.java @@ -61,9 +61,9 @@ import org.apache.sshd.common.keyprovider.KeyPairProvider; import org.apache.sshd.common.keyprovider.KeyPairProviderHolder; import org.apache.sshd.common.random.Random; import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.io.IoUtils; +import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.server.SshServer; import org.apache.sshd.server.auth.pubkey.AcceptAllPublickeyAuthenticator; import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
