Repository: mina-sshd Updated Branches: refs/heads/master 080c52878 -> d3e55205e
[SSHD-727] Upgrade used EdDSA artifact version to 0.2.0 Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/d3e55205 Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/d3e55205 Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/d3e55205 Branch: refs/heads/master Commit: d3e55205e6feab230a8a87cdb0085210e7082aa9 Parents: 080c528 Author: Lyor Goldstein <lyor.goldst...@gmail.com> Authored: Tue Apr 4 21:29:10 2017 +0300 Committer: Lyor Goldstein <lyor.goldst...@gmail.com> Committed: Tue Apr 4 21:29:10 2017 +0300 ---------------------------------------------------------------------- pom.xml | 6 +- .../common/util/security/SecurityUtils.java | 31 +-- .../security/eddsa/EdDSASecurityProvider.java | 205 ------------------- .../eddsa/EdDSASecurityProviderRegistrar.java | 2 +- .../eddsa/EdDSASecurityProviderUtils.java | 201 ++++++++++++++++++ .../OpenSSHEd25519PrivateKeyEntryDecoder.java | 4 +- .../util/security/eddsa/SignatureEd25519.java | 4 +- .../server/subsystem/sftp/SftpSubsystem.java | 10 +- .../common/signature/SignaturesDevelopment.java | 6 +- .../util/security/eddsa/EDDSAProviderTest.java | 6 +- .../util/security/eddsa/Ed25519VectorsTest.java | 12 +- .../EdDSASecurityProviderRegistrarTest.java | 2 + 12 files changed, 245 insertions(+), 244 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d3e55205/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 806f7fb..bc06820 100644 --- a/pom.xml +++ b/pom.xml @@ -104,7 +104,7 @@ <gmaven.plugin.version>2.0</gmaven.plugin.version> <groovy.major.version>2</groovy.major.version> <groovy.minor.version>4</groovy.minor.version> - <groovy.release.version>8</groovy.release.version> + <groovy.release.version>9</groovy.release.version> <groovy.compliance.level>2.0</groovy.compliance.level> <groovy.version>${groovy.major.version}.${groovy.minor.version}.${groovy.release.version}</groovy.version> @@ -202,7 +202,7 @@ <dependency> <groupId>net.i2p.crypto</groupId> <artifactId>eddsa</artifactId> - <version>0.1.0</version> + <version>0.2.0</version> </dependency> <dependency> @@ -594,7 +594,7 @@ <dependency> <groupId>com.puppycrawl.tools</groupId> <artifactId>checkstyle</artifactId> - <version>7.5.1</version> + <version>7.6</version> <exclusions> <!-- MCHECKSTYLE-156 --> <exclusion> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d3e55205/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 index 6aff088..55d1a62 100644 --- 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 @@ -73,7 +73,7 @@ import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.security.bouncycastle.BouncyCastleGeneratorHostKeyProvider; import org.apache.sshd.common.util.security.bouncycastle.BouncyCastleKeyPairResourceParser; import org.apache.sshd.common.util.security.bouncycastle.BouncyCastleRandomFactory; -import org.apache.sshd.common.util.security.eddsa.EdDSASecurityProvider; +import org.apache.sshd.common.util.security.eddsa.EdDSASecurityProviderUtils; import org.apache.sshd.common.util.threads.ThreadUtils; import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvider; import org.slf4j.Logger; @@ -91,12 +91,13 @@ public final class SecurityUtils { public static final String BOUNCY_CASTLE = "BC"; /** - * EDDSA support + * EDDSA support - should match {@code EdDSAKey.KEY_ALGORITHM} */ public static final String EDDSA = "EdDSA"; // A copy-paste from the original, but we don't want to drag the classes into the classpath - public static final String CURVE_ED25519_SHA512 = "ed25519-sha-512"; + // See EdDSAEngine.SIGNATURE_ALGORITHM + public static final String CURVE_ED25519_SHA512 = "NONEwithEdDSA"; /** * System property used to configure the value for the maximum supported Diffie-Hellman @@ -538,7 +539,7 @@ public final class SecurityUtils { throw new UnsupportedOperationException(EDDSA + " provider N/A"); } - return EdDSASecurityProvider.getEDDSAPublicKeyEntryDecoder(); + return EdDSASecurityProviderUtils.getEDDSAPublicKeyEntryDecoder(); } public static PrivateKeyEntryDecoder<? extends PublicKey, ? extends PrivateKey> getOpenSSHEDDSAPrivateKeyEntryDecoder() { @@ -546,35 +547,35 @@ public final class SecurityUtils { throw new UnsupportedOperationException(EDDSA + " provider N/A"); } - return EdDSASecurityProvider.getOpenSSHEDDSAPrivateKeyEntryDecoder(); + return EdDSASecurityProviderUtils.getOpenSSHEDDSAPrivateKeyEntryDecoder(); } public static org.apache.sshd.common.signature.Signature getEDDSASigner() { if (isEDDSACurveSupported()) { - return EdDSASecurityProvider.getEDDSASignature(); + return EdDSASecurityProviderUtils.getEDDSASignature(); } throw new UnsupportedOperationException(EDDSA + " Signer not available"); } public static int getEDDSAKeySize(Key key) { - return EdDSASecurityProvider.getEDDSAKeySize(key); + return EdDSASecurityProviderUtils.getEDDSAKeySize(key); } public static Class<? extends PublicKey> getEDDSAPublicKeyType() { - return isEDDSACurveSupported() ? EdDSASecurityProvider.getEDDSAPublicKeyType() : PublicKey.class; + return isEDDSACurveSupported() ? EdDSASecurityProviderUtils.getEDDSAPublicKeyType() : PublicKey.class; } public static Class<? extends PrivateKey> getEDDSAPrivateKeyType() { - return isEDDSACurveSupported() ? EdDSASecurityProvider.getEDDSAPrivateKeyType() : PrivateKey.class; + return isEDDSACurveSupported() ? EdDSASecurityProviderUtils.getEDDSAPrivateKeyType() : PrivateKey.class; } public static boolean compareEDDSAPPublicKeys(PublicKey k1, PublicKey k2) { - return isEDDSACurveSupported() ? EdDSASecurityProvider.compareEDDSAPPublicKeys(k1, k2) : false; + return isEDDSACurveSupported() ? EdDSASecurityProviderUtils.compareEDDSAPPublicKeys(k1, k2) : false; } public static boolean compareEDDSAPrivateKeys(PrivateKey k1, PrivateKey k2) { - return isEDDSACurveSupported() ? EdDSASecurityProvider.compareEDDSAPrivateKeys(k1, k2) : false; + return isEDDSACurveSupported() ? EdDSASecurityProviderUtils.compareEDDSAPrivateKeys(k1, k2) : false; } public static PublicKey recoverEDDSAPublicKey(PrivateKey key) throws GeneralSecurityException { @@ -582,7 +583,7 @@ public final class SecurityUtils { throw new NoSuchAlgorithmException(EDDSA + " provider not supported"); } - return EdDSASecurityProvider.recoverEDDSAPublicKey(key); + return EdDSASecurityProviderUtils.recoverEDDSAPublicKey(key); } public static PublicKey generateEDDSAPublicKey(String keyType, byte[] seed) throws GeneralSecurityException { @@ -594,7 +595,7 @@ public final class SecurityUtils { throw new NoSuchAlgorithmException(EDDSA + " provider not supported"); } - return EdDSASecurityProvider.generateEDDSAPublicKey(seed); + return EdDSASecurityProviderUtils.generateEDDSAPublicKey(seed); } public static <B extends Buffer> B putRawEDDSAPublicKey(B buffer, PublicKey key) { @@ -602,7 +603,7 @@ public final class SecurityUtils { throw new UnsupportedOperationException(EDDSA + " provider not supported"); } - return EdDSASecurityProvider.putRawEDDSAPublicKey(buffer, key); + return EdDSASecurityProviderUtils.putRawEDDSAPublicKey(buffer, key); } public static <B extends Buffer> B putEDDSAKeyPair(B buffer, KeyPair kp) { @@ -614,7 +615,7 @@ public final class SecurityUtils { throw new UnsupportedOperationException(EDDSA + " provider not supported"); } - return EdDSASecurityProvider.putEDDSAKeyPair(buffer, pubKey, prvKey); + return EdDSASecurityProviderUtils.putEDDSAKeyPair(buffer, pubKey, prvKey); } public static KeyPair extractEDDSAKeyPair(Buffer buffer, String keyType) throws GeneralSecurityException { http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d3e55205/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 deleted file mode 100644 index e039547..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProvider.java +++ /dev/null @@ -1,205 +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.util.security.eddsa; - -import java.security.GeneralSecurityException; -import java.security.InvalidKeyException; -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.EdDSAPrivateKeySpec; -import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec; - -import org.apache.sshd.common.config.keys.PrivateKeyEntryDecoder; -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:d...@mina.apache.org">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 EdDSAPublicKey recoverEDDSAPublicKey(PrivateKey key) throws GeneralSecurityException { - ValidateUtils.checkTrue(SecurityUtils.isEDDSACurveSupported(), SecurityUtils.EDDSA + " not supported"); - if (!(key instanceof EdDSAPrivateKey)) { - throw new InvalidKeyException("Private key is not " + SecurityUtils.EDDSA); - } - - EdDSAPrivateKey prvKey = (EdDSAPrivateKey) key; - EdDSAPublicKeySpec keySpec = new EdDSAPublicKeySpec(prvKey.getSeed(), prvKey.getParams()); - KeyFactory factory = SecurityUtils.getKeyFactory(SecurityUtils.EDDSA); - return EdDSAPublicKey.class.cast(factory.generatePublic(keySpec)); - } - - 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 PrivateKeyEntryDecoder<? extends PublicKey, ? extends PrivateKey> getOpenSSHEDDSAPrivateKeyEntryDecoder() { - ValidateUtils.checkTrue(SecurityUtils.isEDDSACurveSupported(), SecurityUtils.EDDSA + " not supported"); - return OpenSSHEd25519PrivateKeyEntryDecoder.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 PrivateKey generateEDDSAPrivateKey(byte[] seed) throws GeneralSecurityException { - if (!SecurityUtils.isEDDSACurveSupported()) { - throw new NoSuchAlgorithmException(SecurityUtils.EDDSA + " not supported"); - } - - EdDSAParameterSpec params = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512); - EdDSAPrivateKeySpec keySpec = new EdDSAPrivateKeySpec(seed, params); - KeyFactory factory = SecurityUtils.getKeyFactory(SecurityUtils.EDDSA); - return factory.generatePrivate(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/d3e55205/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrar.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrar.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrar.java index b463d27..2bb3f95 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrar.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrar.java @@ -36,7 +36,7 @@ import org.apache.sshd.common.util.threads.ThreadUtils; * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> */ public class EdDSASecurityProviderRegistrar extends AbstractSecurityProviderRegistrar { - public static final String PROVIDER_CLASS = "org.apache.sshd.common.util.security.eddsa.EdDSASecurityProvider"; + public static final String PROVIDER_CLASS = "net.i2p.crypto.eddsa.EdDSASecurityProvider"; // Do not define a static registrar instance to minimize class loading issues private final AtomicReference<Boolean> supportHolder = new AtomicReference<>(null); http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d3e55205/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderUtils.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderUtils.java new file mode 100644 index 0000000..24e7e5c --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderUtils.java @@ -0,0 +1,201 @@ +/* + * 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.InvalidKeyException; +import java.security.Key; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.util.Arrays; +import java.util.Objects; + +import net.i2p.crypto.eddsa.EdDSAEngine; +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.EdDSAPrivateKeySpec; +import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec; + +import org.apache.sshd.common.config.keys.PrivateKeyEntryDecoder; +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:d...@mina.apache.org">Apache MINA SSHD Project</a> + */ +public final class EdDSASecurityProviderUtils { + // See EdDSANamedCurveTable + public static final String CURVE_ED25519_SHA512 = "Ed25519"; + + private EdDSASecurityProviderUtils() { + throw new UnsupportedOperationException("No instance"); + } + + 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 EdDSAEngine.SIGNATURE_ALGORITHM.equalsIgnoreCase(algorithm); + } + + public static EdDSAPublicKey recoverEDDSAPublicKey(PrivateKey key) throws GeneralSecurityException { + ValidateUtils.checkTrue(SecurityUtils.isEDDSACurveSupported(), SecurityUtils.EDDSA + " not supported"); + if (!(key instanceof EdDSAPrivateKey)) { + throw new InvalidKeyException("Private key is not " + SecurityUtils.EDDSA); + } + + EdDSAPrivateKey prvKey = (EdDSAPrivateKey) key; + EdDSAPublicKeySpec keySpec = new EdDSAPublicKeySpec(prvKey.getSeed(), prvKey.getParams()); + KeyFactory factory = SecurityUtils.getKeyFactory(SecurityUtils.EDDSA); + return EdDSAPublicKey.class.cast(factory.generatePublic(keySpec)); + } + + 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 PrivateKeyEntryDecoder<? extends PublicKey, ? extends PrivateKey> getOpenSSHEDDSAPrivateKeyEntryDecoder() { + ValidateUtils.checkTrue(SecurityUtils.isEDDSACurveSupported(), SecurityUtils.EDDSA + " not supported"); + return OpenSSHEd25519PrivateKeyEntryDecoder.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(CURVE_ED25519_SHA512); + EdDSAPublicKeySpec keySpec = new EdDSAPublicKeySpec(seed, params); + KeyFactory factory = SecurityUtils.getKeyFactory(SecurityUtils.EDDSA); + return factory.generatePublic(keySpec); + } + + public static PrivateKey generateEDDSAPrivateKey(byte[] seed) throws GeneralSecurityException { + if (!SecurityUtils.isEDDSACurveSupported()) { + throw new NoSuchAlgorithmException(SecurityUtils.EDDSA + " not supported"); + } + + EdDSAParameterSpec params = EdDSANamedCurveTable.getByName(CURVE_ED25519_SHA512); + EdDSAPrivateKeySpec keySpec = new EdDSAPrivateKeySpec(seed, params); + KeyFactory factory = SecurityUtils.getKeyFactory(SecurityUtils.EDDSA); + return factory.generatePrivate(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/d3e55205/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/OpenSSHEd25519PrivateKeyEntryDecoder.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/OpenSSHEd25519PrivateKeyEntryDecoder.java b/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/OpenSSHEd25519PrivateKeyEntryDecoder.java index b05a4cc..e83a328 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/OpenSSHEd25519PrivateKeyEntryDecoder.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/util/security/eddsa/OpenSSHEd25519PrivateKeyEntryDecoder.java @@ -70,7 +70,7 @@ public class OpenSSHEd25519PrivateKeyEntryDecoder extends AbstractPrivateKeyEntr throw new InvalidKeyException("Mismatched signature (" + signature.length + ") vs. seed (" + seed.length + ") length"); } - EdDSAParameterSpec params = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512); + EdDSAParameterSpec params = EdDSANamedCurveTable.getByName(EdDSASecurityProviderUtils.CURVE_ED25519_SHA512); EdDSAPrivateKeySpec keySpec = new EdDSAPrivateKeySpec(seed, params); return generatePrivateKey(keySpec); } @@ -98,7 +98,7 @@ public class OpenSSHEd25519PrivateKeyEntryDecoder extends AbstractPrivateKeyEntr @Override public EdDSAPublicKey recoverPublicKey(EdDSAPrivateKey prvKey) throws GeneralSecurityException { - return EdDSASecurityProvider.recoverEDDSAPublicKey(prvKey); + return EdDSASecurityProviderUtils.recoverEDDSAPublicKey(prvKey); } @Override http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d3e55205/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 index 97a7cf9..cd601f6 100644 --- 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 @@ -18,7 +18,7 @@ */ package org.apache.sshd.common.util.security.eddsa; -import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable; +import net.i2p.crypto.eddsa.EdDSAEngine; import org.apache.sshd.common.keyprovider.KeyPairProvider; import org.apache.sshd.common.signature.AbstractSignature; @@ -30,7 +30,7 @@ import org.apache.sshd.common.util.ValidateUtils; */ public class SignatureEd25519 extends AbstractSignature { public SignatureEd25519() { - super(EdDSANamedCurveTable.CURVE_ED25519_SHA512); + super(EdDSAEngine.SIGNATURE_ALGORITHM); } @Override http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d3e55205/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java index fcdb4ad..f328990 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java @@ -2714,7 +2714,7 @@ public class SftpSubsystem * @throws IOException If failed to generate an entry */ protected int doReadDir( - int id, String handle, DirectoryHandle dir, Buffer buffer, int maxSize, LinkOption ... options) throws IOException { + int id, String handle, DirectoryHandle dir, Buffer buffer, int maxSize, LinkOption... options) throws IOException { int nb = 0; Map<String, Path> entries = new TreeMap<>(Comparator.naturalOrder()); while ((dir.isSendDot() || dir.isSendDotDot() || dir.hasNext()) && (buffer.wpos() < maxSize)) { @@ -2722,7 +2722,8 @@ public class SftpSubsystem writeDirEntry(id, dir, entries, buffer, nb, dir.getFile(), ".", options); dir.markDotSent(); // do not send it again } else if (dir.isSendDotDot()) { - writeDirEntry(id, dir, entries, buffer, nb, dir.getFile().getParent(), "..", options); + Path dirPath = dir.getFile(); + writeDirEntry(id, dir, entries, buffer, nb, dirPath.getParent(), "..", options); dir.markDotDotSent(); // do not send it again } else { Path f = dir.next(); @@ -2749,8 +2750,9 @@ public class SftpSubsystem * @param options The {@link LinkOption}s to use for querying the entry-s attributes * @throws IOException If failed to generate the entry data */ - protected void writeDirEntry(int id, DirectoryHandle dir, Map<String, Path> entries, Buffer buffer, int index, Path f, String shortName, LinkOption... options) - throws IOException { + protected void writeDirEntry( + int id, DirectoryHandle dir, Map<String, Path> entries, Buffer buffer, int index, Path f, String shortName, LinkOption... options) + throws IOException { Map<String, ?> attrs = resolveFileAttributes(f, SftpConstants.SSH_FILEXFER_ATTR_ALL, options); entries.put(shortName, f); http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d3e55205/sshd-core/src/test/java/org/apache/sshd/common/signature/SignaturesDevelopment.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignaturesDevelopment.java b/sshd-core/src/test/java/org/apache/sshd/common/signature/SignaturesDevelopment.java index 6c4929a..180e997 100644 --- a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignaturesDevelopment.java +++ b/sshd-core/src/test/java/org/apache/sshd/common/signature/SignaturesDevelopment.java @@ -25,7 +25,7 @@ import java.security.PublicKey; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.buffer.BufferUtils; -import org.apache.sshd.common.util.security.eddsa.EdDSASecurityProvider; +import org.apache.sshd.common.util.security.eddsa.EdDSASecurityProviderUtils; import org.apache.sshd.util.test.BaseTestSupport; /** @@ -64,9 +64,9 @@ public class SignaturesDevelopment extends BaseTestSupport { SignatureFactory factory = BuiltinSignatures.resolveFactory(args[0]); // TODO recover public/private keys according to factory name byte[] publicKey = BufferUtils.decodeHex(':', args[1]); - PublicKey pubKey = EdDSASecurityProvider.generateEDDSAPublicKey(publicKey); + PublicKey pubKey = EdDSASecurityProviderUtils.generateEDDSAPublicKey(publicKey); byte[] privateKey = BufferUtils.decodeHex(':', args[2]); - PrivateKey prvKey = EdDSASecurityProvider.generateEDDSAPrivateKey(privateKey); + PrivateKey prvKey = EdDSASecurityProviderUtils.generateEDDSAPrivateKey(privateKey); String op = args[3]; byte[] data = BufferUtils.decodeHex(':', args[4]); byte[] signature = GenericUtils.EMPTY_BYTE_ARRAY; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d3e55205/sshd-core/src/test/java/org/apache/sshd/common/util/security/eddsa/EDDSAProviderTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/util/security/eddsa/EDDSAProviderTest.java b/sshd-core/src/test/java/org/apache/sshd/common/util/security/eddsa/EDDSAProviderTest.java index f7461a3..b69f1ea 100644 --- a/sshd-core/src/test/java/org/apache/sshd/common/util/security/eddsa/EDDSAProviderTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/common/util/security/eddsa/EDDSAProviderTest.java @@ -27,7 +27,7 @@ import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; -import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable; +import net.i2p.crypto.eddsa.EdDSAEngine; import org.apache.sshd.common.config.keys.AuthorizedKeyEntry; import org.apache.sshd.common.config.keys.KeyUtils; @@ -75,7 +75,7 @@ public class EDDSAProviderTest extends BaseTestSupport { @Test public void testSignature() throws GeneralSecurityException { - Signature s = SecurityUtils.getSignature(EdDSANamedCurveTable.CURVE_ED25519_SHA512); + Signature s = SecurityUtils.getSignature(EdDSAEngine.SIGNATURE_ALGORITHM); assertNotNull("No signature instance", s); s.initSign(keyPair.getPrivate()); @@ -83,7 +83,7 @@ public class EDDSAProviderTest extends BaseTestSupport { s.update(data); byte[] signed = s.sign(); - s = SecurityUtils.getSignature(EdDSANamedCurveTable.CURVE_ED25519_SHA512); + s = SecurityUtils.getSignature(EdDSAEngine.SIGNATURE_ALGORITHM); s.initVerify(keyPair.getPublic()); s.update(data); assertTrue("Failed to verify", s.verify(signed)); http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d3e55205/sshd-core/src/test/java/org/apache/sshd/common/util/security/eddsa/Ed25519VectorsTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/util/security/eddsa/Ed25519VectorsTest.java b/sshd-core/src/test/java/org/apache/sshd/common/util/security/eddsa/Ed25519VectorsTest.java index fab3294..b58aad3 100644 --- a/sshd-core/src/test/java/org/apache/sshd/common/util/security/eddsa/Ed25519VectorsTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/common/util/security/eddsa/Ed25519VectorsTest.java @@ -60,9 +60,9 @@ public class Ed25519VectorsTest extends BaseTestSupport { public Ed25519VectorsTest(String name, String prvKey, String pubKey, String msg, String signature) throws GeneralSecurityException { prvBytes = BufferUtils.decodeHex(BufferUtils.EMPTY_HEX_SEPARATOR, prvKey); - privateKey = EdDSASecurityProvider.generateEDDSAPrivateKey(prvBytes.clone()); + privateKey = EdDSASecurityProviderUtils.generateEDDSAPrivateKey(prvBytes.clone()); pubBytes = BufferUtils.decodeHex(BufferUtils.EMPTY_HEX_SEPARATOR, pubKey); - publicKey = EdDSASecurityProvider.generateEDDSAPublicKey(pubBytes.clone()); + publicKey = EdDSASecurityProviderUtils.generateEDDSAPublicKey(pubBytes.clone()); msgBytes = BufferUtils.decodeHex(BufferUtils.EMPTY_HEX_SEPARATOR, msg); expSignature = BufferUtils.decodeHex(BufferUtils.EMPTY_HEX_SEPARATOR, signature); } @@ -200,14 +200,14 @@ public class Ed25519VectorsTest extends BaseTestSupport { @Test public void testSignature() throws Exception { - Signature signer = EdDSASecurityProvider.getEDDSASignature(); + Signature signer = EdDSASecurityProviderUtils.getEDDSASignature(); signer.initSigner(privateKey); signer.update(msgBytes.clone()); byte[] actSignature = signer.sign(); assertArrayEquals("Mismatched signature", expSignature, actSignature); - Signature verifier = EdDSASecurityProvider.getEDDSASignature(); + Signature verifier = EdDSASecurityProviderUtils.getEDDSASignature(); verifier.initVerifier(publicKey); verifier.update(msgBytes.clone()); assertTrue("Verification failed", verifier.verify(expSignature)); @@ -222,14 +222,14 @@ public class Ed25519VectorsTest extends BaseTestSupport { System.arraycopy(msgBytes, 0, dataBuf, offset, msgBytes.length); System.arraycopy(extraData, offset, dataBuf, offset + msgBytes.length, extraData.length - offset); - Signature signer = EdDSASecurityProvider.getEDDSASignature(); + Signature signer = EdDSASecurityProviderUtils.getEDDSASignature(); signer.initSigner(privateKey); signer.update(dataBuf.clone(), offset, msgBytes.length); byte[] actSignature = signer.sign(); assertArrayEquals("Mismatched signature", expSignature, actSignature); - Signature verifier = EdDSASecurityProvider.getEDDSASignature(); + Signature verifier = EdDSASecurityProviderUtils.getEDDSASignature(); verifier.initVerifier(publicKey); verifier.update(dataBuf.clone(), offset, msgBytes.length); assertTrue("Verification failed", verifier.verify(expSignature)); http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d3e55205/sshd-core/src/test/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrarTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrarTest.java b/sshd-core/src/test/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrarTest.java index 9e12fab..f2c1f3f 100644 --- a/sshd-core/src/test/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrarTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrarTest.java @@ -26,6 +26,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import net.i2p.crypto.eddsa.EdDSASecurityProvider; + import org.apache.sshd.common.util.security.SecurityProviderRegistrar; import org.apache.sshd.common.util.security.SecurityProviderRegistrarTestSupport; import org.apache.sshd.common.util.security.SecurityUtils;