This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit 059ae39f91b0310f63218139e6d7bfd595d9c06d
Author: Lyor Goldstein <[email protected]>
AuthorDate: Sun Feb 17 15:13:54 2019 +0200

    [SSHD-895] Added RSA SHA-256 and SHA-512 signature support
---
 .../sshd/common/config/keys/IdentityUtils.java     |   3 +-
 .../apache/sshd/common/config/keys/KeyUtils.java   | 105 ++++++++++++++++++++-
 .../config/keys/impl/RSAPublicKeyDecoder.java      |  30 +++---
 .../sshd/common/signature/BuiltinSignatures.java   |  36 ++++++-
 .../apache/sshd/common/signature/SignatureRSA.java |  22 +++--
 .../sshd/common/signature/SignatureRSASHA1.java    |  31 ++++++
 .../sshd/common/signature/SignatureRSASHA256.java  |  31 ++++++
 .../sshd/common/signature/SignatureRSASHA512.java  |  31 ++++++
 .../keys/LazyClientIdentityIteratorTest.java       |   3 +-
 .../sshd/common/config/keys/KeyUtilsTest.java      |   8 ++
 .../common/signature/RSASignatureVariantsTest.java |  67 +++++++++++++
 ...atureRSATest.java => SignatureRSASHA1Test.java} |  15 +--
 .../signature/SignatureVariantTestSupport.java     |  80 ++++++++++++++++
 .../org/apache/sshd/common/signature/id_dsa        |  12 +++
 .../org/apache/sshd/common/signature/id_ecdsa      |   5 +
 .../org/apache/sshd/common/signature/id_rsa        |  27 ++++++
 16 files changed, 472 insertions(+), 34 deletions(-)

diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
index 6b15070..178c914 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
@@ -77,7 +77,8 @@ public final class IdentityUtils {
             return null;
         } else {
             return GenericUtils.trimToEmpty(prefix)
-                    + type.toLowerCase() + GenericUtils.trimToEmpty(suffix);
+                 + type.toLowerCase()
+                 + GenericUtils.trimToEmpty(suffix);
         }
     }
 
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java 
b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java
index f788a4c..7ced362 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java
@@ -48,12 +48,14 @@ import java.security.spec.ECParameterSpec;
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.RSAPublicKeySpec;
 import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.NavigableSet;
 import java.util.Objects;
@@ -73,6 +75,7 @@ import org.apache.sshd.common.digest.DigestFactory;
 import org.apache.sshd.common.digest.DigestUtils;
 import org.apache.sshd.common.keyprovider.KeyPairProvider;
 import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.MapEntryUtils.NavigableMapBuilder;
 import org.apache.sshd.common.util.OsUtils;
 import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.buffer.Buffer;
@@ -130,6 +133,10 @@ public final class KeyUtils {
      */
     public static final DigestFactory DEFAULT_FINGERPRINT_DIGEST_FACTORY = 
BuiltinDigests.sha256;
 
+    /** @see <A HREF="">https://tools.ietf.org/html/rfc8332#section-3</A> */
+    public static final String RSA_SHA256_KEY_TYPE_ALIAS = "rsa-sha2-256";
+    public static final String RSA_SHA512_KEY_TYPE_ALIAS = "rsa-sha2-512";
+
     private static final AtomicReference<DigestFactory> DEFAULT_DIGEST_HOLDER 
= new AtomicReference<>();
 
     private static final Map<String, PublicKeyEntryDecoder<?, ?>> 
BY_KEY_TYPE_DECODERS_MAP =
@@ -138,6 +145,12 @@ public final class KeyUtils {
     private static final Map<Class<?>, PublicKeyEntryDecoder<?, ?>> 
BY_KEY_CLASS_DECODERS_MAP =
             new HashMap<>();
 
+    private static final Map<String, String> KEY_TYPE_ALIASES =
+        NavigableMapBuilder.<String, 
String>builder(String.CASE_INSENSITIVE_ORDER)
+            .put(RSA_SHA256_KEY_TYPE_ALIAS, KeyPairProvider.SSH_RSA)
+            .put(RSA_SHA512_KEY_TYPE_ALIAS, KeyPairProvider.SSH_RSA)
+            .build();
+
     static {
         registerPublicKeyEntryDecoder(RSAPublicKeyDecoder.INSTANCE);
         registerPublicKeyEntryDecoder(DSSPublicKeyEntryDecoder.INSTANCE);
@@ -614,7 +627,7 @@ public final class KeyUtils {
     /**
      * @param f The {@link Factory} to create the {@link Digest} to use
      * @param s The {@link String} to digest - ignored if {@code null}/empty,
-     *          otherwise its UTF-8 representation is used as input for the 
fingerprint
+     * otherwise its UTF-8 representation is used as input for the fingerprint
      * @return The fingerprint - {@code null} if {@code null}/empty input.
      * <B>Note:</B> if exception encountered then returns the exception's 
simple class name
      * @see #getFingerPrint(Digest, String, Charset)
@@ -627,7 +640,7 @@ public final class KeyUtils {
      * @param f       The {@link Factory} to create the {@link Digest} to use
      * @param s       The {@link String} to digest - ignored if {@code 
null}/empty
      * @param charset The {@link Charset} to use in order to convert the
-     *                string to its byte representation to use as input for 
the fingerprint
+     * string to its byte representation to use as input for the fingerprint
      * @return The fingerprint - {@code null} if {@code null}/empty input
      * <B>Note:</B> if exception encountered then returns the exception's 
simple class name
      * @see DigestUtils#getFingerPrint(Digest, String, Charset)
@@ -652,7 +665,7 @@ public final class KeyUtils {
      * @param d       The {@link Digest} to use to calculate the fingerprint
      * @param s       The string to digest - ignored if {@code null}/empty
      * @param charset The {@link Charset} to use in order to convert the
-     *                string to its byte representation to use as input for 
the fingerprint
+     * string to its byte representation to use as input for the fingerprint
      * @return The fingerprint - {@code null} if {@code null}/empty input.
      * <B>Note:</B> if exception encountered then returns the exception's 
simple class name
      * @see DigestUtils#getFingerPrint(Digest, String, Charset)
@@ -742,8 +755,8 @@ public final class KeyUtils {
 
     /**
      * @param kp a key pair - ignored if {@code null}. If the private
-     *           key is non-{@code null} then it is used to determine the type,
-     *           otherwise the public one is used.
+     * key is non-{@code null} then it is used to determine the type,
+     * otherwise the public one is used.
      * @return the key type or {@code null} if cannot determine it
      * @see #getKeyType(Key)
      */
@@ -787,6 +800,88 @@ public final class KeyUtils {
     }
 
     /**
+     * @param keyType The available key-type - ignored if {@code null}/empty
+     * @return The canonical key type - same as input if no alias registered
+     * for the provided key type
+     * @see #RSA_SHA256_KEY_TYPE_ALIAS
+     * @see #RSA_SHA512_KEY_TYPE_ALIAS
+     */
+    public static String getCanonicalKeyType(String keyType) {
+        if (GenericUtils.isEmpty(keyType)) {
+            return keyType;
+        }
+
+        String canonicalName;
+        synchronized (KEY_TYPE_ALIASES) {
+            canonicalName = KEY_TYPE_ALIASES.get(keyType);
+        }
+
+        if (GenericUtils.isEmpty(canonicalName)) {
+            return keyType;
+        }
+
+        return canonicalName;
+    }
+
+    /**
+     * @return A case insensitive {@link NavigableSet} of the currently 
registered
+     * key type &quot;aliases&quot;.
+     * @see #getCanonicalKeyType(String)
+     */
+    public static NavigableSet<String> getRegisteredKeyTypeAliases() {
+        synchronized (KEY_TYPE_ALIASES) {
+            return KEY_TYPE_ALIASES.isEmpty()
+                 ? Collections.emptyNavigableSet()
+                 : GenericUtils.asSortedSet(String.CASE_INSENSITIVE_ORDER, 
KEY_TYPE_ALIASES.keySet());
+        }
+    }
+
+    /**
+     * Registers a collection of aliases to a canonical key type
+     *
+     * @param keyType The (never {@code null}/empty) canonical name
+     * @param aliases The (never {@code null}/empty) aliases
+     * @return A {@link List} of the replaced aliases - empty
+     * if no previous aliases for the canonical name
+     */
+    public static List<String> registerCanonicalKeyTypes(String keyType, 
Collection<String> aliases) {
+        ValidateUtils.checkNotNullAndNotEmpty(keyType, "No key type value");
+        ValidateUtils.checkNotNullAndNotEmpty(aliases, "No aliases provided");
+
+        List<String> replaced = Collections.emptyList();
+        synchronized (KEY_TYPE_ALIASES) {
+            for (String a : aliases) {
+                ValidateUtils.checkNotNullAndNotEmpty(a, "Null/empty alias 
registration for %s", keyType);
+                String prev = KEY_TYPE_ALIASES.put(a, keyType);
+                if (GenericUtils.isEmpty(prev)) {
+                    continue;
+                }
+
+                if (replaced.isEmpty()) {
+                    replaced = new ArrayList<>();
+                }
+                replaced.add(prev);
+            }
+        }
+
+        return replaced;
+    }
+
+    /**
+     * @param alias The alias to unregister (ignored if {@code null}/empty)
+     * @return The associated canonical key type - {@code null} if alias not 
registered
+     */
+    public static String unregisterCanonicalKeyTypeAlias(String alias) {
+        if (GenericUtils.isEmpty(alias)) {
+            return alias;
+        }
+
+        synchronized (KEY_TYPE_ALIASES) {
+            return KEY_TYPE_ALIASES.remove(alias);
+        }
+    }
+
+    /**
      * Determines the key size in bits
      *
      * @param key The {@link Key} to examine - ignored if {@code null}
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/RSAPublicKeyDecoder.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/RSAPublicKeyDecoder.java
index 52cabce..9c2730d 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/RSAPublicKeyDecoder.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/RSAPublicKeyDecoder.java
@@ -33,6 +33,7 @@ import java.security.interfaces.RSAPublicKey;
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.RSAPrivateCrtKeySpec;
 import java.security.spec.RSAPublicKeySpec;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Objects;
 
@@ -49,13 +50,20 @@ public class RSAPublicKeyDecoder extends 
AbstractPublicKeyEntryDecoder<RSAPublic
     public static final RSAPublicKeyDecoder INSTANCE = new 
RSAPublicKeyDecoder();
 
     public RSAPublicKeyDecoder() {
-        super(RSAPublicKey.class, RSAPrivateKey.class, 
Collections.unmodifiableList(Collections.singletonList(KeyPairProvider.SSH_RSA)));
+        super(RSAPublicKey.class, RSAPrivateKey.class,
+            Collections.unmodifiableList(
+                Arrays.asList(KeyPairProvider.SSH_RSA,
+                    // Not really required, but allow it
+                    KeyUtils.RSA_SHA256_KEY_TYPE_ALIAS,
+                    KeyUtils.RSA_SHA512_KEY_TYPE_ALIAS)));
     }
 
     @Override
     public RSAPublicKey decodePublicKey(SessionContext session, String 
keyType, InputStream keyData)
             throws IOException, GeneralSecurityException {
-        if (!KeyPairProvider.SSH_RSA.equals(keyType)) { // just in case we 
were invoked directly
+        // Not really required, but allow it
+        String canonicalName = KeyUtils.getCanonicalKeyType(keyType);
+        if (!KeyPairProvider.SSH_RSA.equals(canonicalName)) { // just in case 
we were invoked directly
             throw new InvalidKeySpecException("Unexpected key type: " + 
keyType);
         }
 
@@ -96,15 +104,15 @@ public class RSAPublicKeyDecoder extends 
AbstractPublicKeyEntryDecoder<RSAPublic
 
         RSAPrivateCrtKey rsaPrv = (RSAPrivateCrtKey) key;
         return generatePrivateKey(
-                new RSAPrivateCrtKeySpec(
-                        rsaPrv.getModulus(),
-                        rsaPrv.getPublicExponent(),
-                        rsaPrv.getPrivateExponent(),
-                        rsaPrv.getPrimeP(),
-                        rsaPrv.getPrimeQ(),
-                        rsaPrv.getPrimeExponentP(),
-                        rsaPrv.getPrimeExponentQ(),
-                        rsaPrv.getCrtCoefficient()));
+            new RSAPrivateCrtKeySpec(
+                rsaPrv.getModulus(),
+                rsaPrv.getPublicExponent(),
+                rsaPrv.getPrivateExponent(),
+                rsaPrv.getPrimeP(),
+                rsaPrv.getPrimeQ(),
+                rsaPrv.getPrimeExponentP(),
+                rsaPrv.getPrimeExponentQ(),
+                rsaPrv.getCrtCoefficient()));
     }
 
     @Override
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java
index e9cd416..a0856b0 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java
@@ -31,11 +31,13 @@ import java.util.NavigableSet;
 import java.util.Objects;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.NamedResource;
 import org.apache.sshd.common.cipher.ECCurves;
 import org.apache.sshd.common.config.NamedFactoriesListParseResult;
+import org.apache.sshd.common.config.keys.KeyUtils;
 import org.apache.sshd.common.keyprovider.KeyPairProvider;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.ValidateUtils;
@@ -56,7 +58,39 @@ public enum BuiltinSignatures implements SignatureFactory {
     rsa(KeyPairProvider.SSH_RSA) {
         @Override
         public Signature create() {
-            return new SignatureRSA();
+            return new SignatureRSASHA1();
+        }
+    },
+    rsaSHA256(KeyUtils.RSA_SHA256_KEY_TYPE_ALIAS) {
+        @Override
+        public Signature create() {
+            return new SignatureRSASHA256();
+        }
+    },
+    rsaSHA512(KeyUtils.RSA_SHA512_KEY_TYPE_ALIAS) {
+        private final AtomicReference<Boolean> supportHolder = new 
AtomicReference<>();
+
+        @Override
+        public Signature create() {
+            return new SignatureRSASHA512();
+        }
+
+        @Override
+        public boolean isSupported() {
+            Boolean supported = supportHolder.get();
+            if (supported == null) {
+                try {
+                    java.security.Signature sig =
+                        
SecurityUtils.getSignature(SignatureRSASHA512.ALGORITHM);
+                    supported = sig != null;
+                } catch (Exception e) {
+                    supported = Boolean.FALSE;
+                }
+
+                supportHolder.set(supported);
+            }
+
+            return supported;
         }
     },
     nistp256(KeyPairProvider.ECDSA_SHA2_NISTP256) {
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureRSA.java 
b/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureRSA.java
index ad1d37e..23cc46c 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureRSA.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureRSA.java
@@ -23,6 +23,7 @@ import java.security.PublicKey;
 import java.security.interfaces.RSAKey;
 import java.util.Map;
 
+import org.apache.sshd.common.config.keys.KeyUtils;
 import org.apache.sshd.common.keyprovider.KeyPairProvider;
 import org.apache.sshd.common.util.ValidateUtils;
 
@@ -32,15 +33,9 @@ import org.apache.sshd.common.util.ValidateUtils;
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  * @see <A HREF="https://tools.ietf.org/html/rfc4253#section-6.6";>RFC4253 
section 6.6</A>
  */
-public class SignatureRSA extends AbstractSignature {
-    public static final String DEFAULT_ALGORITHM = "SHA1withRSA";
-
+public abstract class SignatureRSA extends AbstractSignature {
     private int verifierSignatureSize = -1;
 
-    public SignatureRSA() {
-        super(DEFAULT_ALGORITHM);
-    }
-
     protected SignatureRSA(String algorithm) {
         super(algorithm);
     }
@@ -71,7 +66,18 @@ public class SignatureRSA extends AbstractSignature {
         Map.Entry<String, byte[]> encoding = extractEncodedSignature(data);
         if (encoding != null) {
             String keyType = encoding.getKey();
-            ValidateUtils.checkTrue(KeyPairProvider.SSH_RSA.equals(keyType), 
"Mismatched key type: %s", keyType);
+            /*
+             * According to https://tools.ietf.org/html/rfc8332#section-3.2:
+             *
+             *      OpenSSH 7.2 (but not 7.2p2) incorrectly encodes the 
algorithm in the
+             *      signature as "ssh-rsa" when the algorithm in 
SSH_MSG_USERAUTH_REQUEST
+             *      is "rsa-sha2-256" or "rsa-sha2-512".  In this case, the 
signature
+             *      does actually use either SHA-256 or SHA-512.  A server 
MAY, but is
+             *      not required to, accept this variant or another variant 
that
+             *      corresponds to a good-faith implementation and is 
considered safe to accept.
+             */
+            String canonicalName = KeyUtils.getCanonicalKeyType(keyType);
+            
ValidateUtils.checkTrue(KeyPairProvider.SSH_RSA.equals(canonicalName), 
"Mismatched key type: %s", keyType);
             data = encoding.getValue();
         }
 
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureRSASHA1.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureRSASHA1.java
new file mode 100644
index 0000000..a20278f
--- /dev/null
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureRSASHA1.java
@@ -0,0 +1,31 @@
+/*
+ * 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.signature;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class SignatureRSASHA1 extends SignatureRSA {
+    public static final String ALGORITHM = "SHA1withRSA";
+
+    public SignatureRSASHA1() {
+        super(ALGORITHM);
+    }
+}
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureRSASHA256.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureRSASHA256.java
new file mode 100644
index 0000000..fae2354
--- /dev/null
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureRSASHA256.java
@@ -0,0 +1,31 @@
+/*
+ * 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.signature;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class SignatureRSASHA256 extends SignatureRSA {
+    public static final String ALGORITHM = "SHA256withRSA";
+
+    public SignatureRSASHA256() {
+        super(ALGORITHM);
+    }
+}
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureRSASHA512.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureRSASHA512.java
new file mode 100644
index 0000000..eff5b0f
--- /dev/null
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureRSASHA512.java
@@ -0,0 +1,31 @@
+/*
+ * 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.signature;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public class SignatureRSASHA512 extends SignatureRSA {
+    public static final String ALGORITHM = "SHA512withRSA";
+
+    public SignatureRSASHA512() {
+        super(ALGORITHM);
+    }
+}
diff --git 
a/sshd-common/src/test/java/rg/apache/sshd/client/config/keys/LazyClientIdentityIteratorTest.java
 
b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/LazyClientIdentityIteratorTest.java
similarity index 97%
rename from 
sshd-common/src/test/java/rg/apache/sshd/client/config/keys/LazyClientIdentityIteratorTest.java
rename to 
sshd-common/src/test/java/org/apache/sshd/client/config/keys/LazyClientIdentityIteratorTest.java
index 8e072c1..86a3b96 100644
--- 
a/sshd-common/src/test/java/rg/apache/sshd/client/config/keys/LazyClientIdentityIteratorTest.java
+++ 
b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/LazyClientIdentityIteratorTest.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package rg.apache.sshd.client.config.keys;
+package org.apache.sshd.client.config.keys;
 
 import java.security.KeyPair;
 import java.security.PrivateKey;
@@ -27,7 +27,6 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
-import org.apache.sshd.client.config.keys.ClientIdentityProvider;
 import org.apache.sshd.common.session.SessionContext;
 import org.apache.sshd.util.test.JUnitTestSupport;
 import org.junit.FixMethodOrder;
diff --git 
a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java
 
b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java
index 00b273f..b62057d 100644
--- 
a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java
+++ 
b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java
@@ -34,6 +34,7 @@ import org.apache.sshd.common.digest.BaseDigest;
 import org.apache.sshd.common.digest.BuiltinDigests;
 import org.apache.sshd.common.digest.Digest;
 import org.apache.sshd.common.digest.DigestFactory;
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.OsUtils;
 import org.apache.sshd.common.util.io.IoUtils;
@@ -154,4 +155,11 @@ public class KeyUtilsTest extends JUnitTestSupport {
             assertNull("Unexpected Windows violation for file " + file + " 
permissions=" + perms, KeyUtils.validateStrictKeyFilePermissions(file));
         }
     }
+
+    @Test   // see SSHD-895
+    public void testRSAKeyTypeAliases() {
+        for (String alias : new String[] {KeyUtils.RSA_SHA256_KEY_TYPE_ALIAS, 
KeyUtils.RSA_SHA512_KEY_TYPE_ALIAS}) {
+            assertEquals("Mismatched canonical name for " + alias, 
KeyPairProvider.SSH_RSA, KeyUtils.getCanonicalKeyType(alias));
+        }
+    }
 }
diff --git 
a/sshd-common/src/test/java/org/apache/sshd/common/signature/RSASignatureVariantsTest.java
 
b/sshd-common/src/test/java/org/apache/sshd/common/signature/RSASignatureVariantsTest.java
new file mode 100644
index 0000000..806be61
--- /dev/null
+++ 
b/sshd-common/src/test/java/org/apache/sshd/common/signature/RSASignatureVariantsTest.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.signature;
+
+import java.security.KeyPair;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized.UseParametersRunnerFactory;
+
+/**
+ * NOTE: some tests are inherited from parent
+ *
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+@RunWith(Parameterized.class)   // see 
https://github.com/junit-team/junit/wiki/Parameterized-tests
+@UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
+public class RSASignatureVariantsTest extends SignatureVariantTestSupport {
+    private static KeyPair kp;
+
+    public RSASignatureVariantsTest(SignatureFactory factory) {
+        super(factory, kp);
+    }
+
+    @BeforeClass
+    public static void initializeSigningKeyPair() throws Exception {
+        kp = initializeSigningKeyPair(KeyUtils.RSA_ALGORITHM);
+    }
+
+    @Parameters(name = "{0}")
+    public static List<Object[]> parameters() {
+        return parameterize(
+            Arrays.asList(
+                BuiltinSignatures.rsa,
+                BuiltinSignatures.rsaSHA256,
+                BuiltinSignatures.rsaSHA512));
+    }
+}
diff --git 
a/sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureRSATest.java
 
b/sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureRSASHA1Test.java
similarity index 80%
rename from 
sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureRSATest.java
rename to 
sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureRSASHA1Test.java
index 5671ac3..38d9168 100644
--- 
a/sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureRSATest.java
+++ 
b/sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureRSASHA1Test.java
@@ -31,26 +31,29 @@ import org.apache.sshd.common.Factory;
 import org.apache.sshd.common.config.keys.KeyUtils;
 import org.apache.sshd.common.util.security.SecurityUtils;
 import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
 import org.junit.BeforeClass;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runners.MethodSorters;
 
 /**
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  */
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public class SignatureRSATest extends JUnitTestSupport {
+@Category({ NoIoTestCase.class })
+public class SignatureRSASHA1Test extends JUnitTestSupport {
     private static final Base64.Decoder B64_DECODER = Base64.getDecoder();
     @SuppressWarnings("checkstyle:linelength")
     private static final byte[] TEST_MSG =
-            
B64_DECODER.decode("AAAAFPHgK1MeV9zNnok3pwNJhCd8SONqMgAAAAlidWlsZHVzZXIAAAAOc3NoLWNvbm5lY3Rpb24AAAAJcHVibGlja2V5AQAAAAdzc2gtcnNhAAABFQAAAAdzc2gtcnNhAAAAASMAAAEBAMs9HO/NH/Now+6fSnESebaG4wzaYQWA1b/q1TGV1wHNtCg9fGFGVSKs0VxKF4cfVyrSLtgLjnlXQTn+Lm7xiYKGbBbsTQWOqEDaBVBsRbAkxIkpuvr6/EBxwrtDbKmSQYTJZVJSD2bZRYjGsR9gpZXPorOOKFd5EPCMHXsqnhp2hidTGH7cK6RuLk7MNnPISsY0Nbx8/ZvikiPROGcoTZ8bzUv4IaLr3veW6epSeQem8tJqhnrpTHhbLU99zf045M0Gsnk/azjjlBM+qrHZ5FNdC1kowJnLtf2Oy/rUQNpkGJtcBPT8xvreV0wLsn9t
 [...]
+        
B64_DECODER.decode("AAAAFPHgK1MeV9zNnok3pwNJhCd8SONqMgAAAAlidWlsZHVzZXIAAAAOc3NoLWNvbm5lY3Rpb24AAAAJcHVibGlja2V5AQAAAAdzc2gtcnNhAAABFQAAAAdzc2gtcnNhAAAAASMAAAEBAMs9HO/NH/Now+6fSnESebaG4wzaYQWA1b/q1TGV1wHNtCg9fGFGVSKs0VxKF4cfVyrSLtgLjnlXQTn+Lm7xiYKGbBbsTQWOqEDaBVBsRbAkxIkpuvr6/EBxwrtDbKmSQYTJZVJSD2bZRYjGsR9gpZXPorOOKFd5EPCMHXsqnhp2hidTGH7cK6RuLk7MNnPISsY0Nbx8/ZvikiPROGcoTZ8bzUv4IaLr3veW6epSeQem8tJqhnrpTHhbLU99zf045M0Gsnk/azjjlBM+qrHZ5FNdC1kowJnLtf2Oy/rUQNpkGJtcBPT8xvreV0wLsn9t3hSx
 [...]
     @SuppressWarnings("checkstyle:linelength")
     private static final byte[] TEST_SIGNATURE =
-            
B64_DECODER.decode("AAAAB3NzaC1yc2EAAAD/+Ntnf4qfr2J1voDS6I+u3VRjtMn+LdWJsAZfkLDxRkK1rQxP7QAjLdNqpT4CkWHp8dtoTGFlBFt6NieNJCMTA2KSOxJMZKsX7e/lHkh7C+vhQvJ9eLTKWjCxSFUrcM0NvFhmwbRCffwXSHvAKak4wbmofxQMpd+G4jZkNMz5kGpmeICBcNjRLPb7oXzuGr/g4x/3ge5Qaawqrg/gcZr/sKN6SdE8SszgKYO0SB320N4gcUoShVdLYr9uwdJ+kJoobfkUK6Or171JCctP/cu2nM79lDqVnJw/2jOG8OnTc8zRDXAh0RKoR5rOU8cOHm0Ls2MATsFdnyRU5FGUxqZ+");
+        
B64_DECODER.decode("AAAAB3NzaC1yc2EAAAD/+Ntnf4qfr2J1voDS6I+u3VRjtMn+LdWJsAZfkLDxRkK1rQxP7QAjLdNqpT4CkWHp8dtoTGFlBFt6NieNJCMTA2KSOxJMZKsX7e/lHkh7C+vhQvJ9eLTKWjCxSFUrcM0NvFhmwbRCffwXSHvAKak4wbmofxQMpd+G4jZkNMz5kGpmeICBcNjRLPb7oXzuGr/g4x/3ge5Qaawqrg/gcZr/sKN6SdE8SszgKYO0SB320N4gcUoShVdLYr9uwdJ+kJoobfkUK6Or171JCctP/cu2nM79lDqVnJw/2jOG8OnTc8zRDXAh0RKoR5rOU8cOHm0Ls2MATsFdnyRU5FGUxqZ+");
     private static PublicKey testKey;
 
-    public SignatureRSATest() {
+    public SignatureRSASHA1Test() {
         super();
     }
 
@@ -68,7 +71,7 @@ public class SignatureRSATest extends JUnitTestSupport {
         testLeadingZeroes(new Factory<SignatureRSA>() {
             @Override
             public SignatureRSA create() {
-                return new SignatureRSA() {
+                return new SignatureRSASHA1() {
                     @Override
                     protected java.security.Signature doInitSignature(String 
algo, boolean forSigning) throws GeneralSecurityException {
                         assertFalse("Signature not initialized for 
verification", forSigning);
@@ -87,7 +90,7 @@ public class SignatureRSATest extends JUnitTestSupport {
 
     @Test   // see SSHD-642
     public void testLeadingZeroesJCE() throws Throwable {
-        testLeadingZeroes(() -> new SignatureRSA() {
+        testLeadingZeroes(() -> new SignatureRSASHA1() {
             @Override
             protected java.security.Signature doInitSignature(String algo, 
boolean forSigning) throws GeneralSecurityException {
                 assertFalse("Signature not initialized for verification", 
forSigning);
diff --git 
a/sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureVariantTestSupport.java
 
b/sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureVariantTestSupport.java
new file mode 100644
index 0000000..ede85e8
--- /dev/null
+++ 
b/sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureVariantTestSupport.java
@@ -0,0 +1,80 @@
+/*
+ * 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.signature;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.util.Objects;
+
+import org.apache.sshd.client.config.keys.ClientIdentity;
+import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.security.SecurityUtils;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.junit.Assume;
+import org.junit.Test;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public abstract class SignatureVariantTestSupport extends JUnitTestSupport {
+    protected final SignatureFactory factory;
+    protected final KeyPair kp;
+
+    protected SignatureVariantTestSupport(SignatureFactory factory, KeyPair 
kp) {
+        this.factory = Objects.requireNonNull(factory, "No factory provided");
+        this.kp = Objects.requireNonNull(kp, "No key pair provided");
+        Assume.assumeTrue("Unsupported factory: " + factory, 
factory.isSupported());
+    }
+
+    protected static KeyPair initializeSigningKeyPair(String algorithm) throws 
IOException, GeneralSecurityException {
+        String resourceKey = ClientIdentity.getIdentityFileName(algorithm);
+        URL urlKeyPair = 
SignatureVariantTestSupport.class.getResource(resourceKey);
+        assertNotNull("Missing key-pair resource: " + resourceKey, urlKeyPair);
+        try (InputStream stream = urlKeyPair.openStream()) {
+            Iterable<KeyPair> ids =
+                SecurityUtils.loadKeyPairIdentities(null, 
NamedResource.ofName(resourceKey), stream, null);
+            return GenericUtils.head(ids);
+        }
+    }
+
+    @Test
+    public void testSignature() throws Exception {
+        byte[] data = (getClass().getName() + "#" + 
getCurrentTestName()).getBytes(StandardCharsets.UTF_8);
+        Signature signer = factory.create();
+        signer.initSigner(kp.getPrivate());
+        signer.update(data);
+
+        byte[] signature = signer.sign();
+        Signature verifier = factory.create();
+        verifier.initVerifier(kp.getPublic());
+        verifier.update(data);
+        verifier.verify(signature);
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + factory + "]";
+    }
+}
diff --git 
a/sshd-common/src/test/resources/org/apache/sshd/common/signature/id_dsa 
b/sshd-common/src/test/resources/org/apache/sshd/common/signature/id_dsa
new file mode 100644
index 0000000..1d3ef24
--- /dev/null
+++ b/sshd-common/src/test/resources/org/apache/sshd/common/signature/id_dsa
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvAIBAAKBgQDIPyMbBuQcZxeYDOyCqqkdK37cWQvp+RpWzvieB/oiG/ykfDQX
+oZMRtwqwWTBfejNitbBBmC6G/t5OK+9aFmj7pfJ+a7fZKXfiUquIg9soDsoOindf
+2AwR6MZ3os8uiP2xrC8IQAClnETa15mFShs4a4b2VjddgCQ6tphnY97MywIVAPtr
+YyW11RIXsVTf/9KlbhYaNlt5AoGAX9JzbHykC/0xDKOyKU6xDIOVdEZ0ooAl9Psl
+BEUuNhlv2XgmQScO6C9l2W7gbbut7zIw4FaZ2/dgXa3D4IyexBVug5XMnrssErZo
+NcoF5g0dgEAsb9Hl9gkIK3VHM5kWteeUg1VE700JTtSMisdL8CgIdR+xN8iVH5Ew
+CbLWxmECgYEAtv+cdRfNevYFkp55jVqazc8zRLvfb64jzgc5oSJVc64kFs4yx+ab
+YpGX9WxNxDlG6g2WiY8voDBB0YnUJsn0kVRjBKX9OceROxrfT4K4dVbQZsdt+SLa
+XWL4lGJFrFZL3LZqvySvq6xfhJfakQDDivW4hUOhFPXPHrE5/Ia3T7ACFQCE6flG
+nmVCAbzo9YsbdJWBnxMnBA==
+-----END DSA PRIVATE KEY-----
\ No newline at end of file
diff --git 
a/sshd-common/src/test/resources/org/apache/sshd/common/signature/id_ecdsa 
b/sshd-common/src/test/resources/org/apache/sshd/common/signature/id_ecdsa
new file mode 100644
index 0000000..31b1268
--- /dev/null
+++ b/sshd-common/src/test/resources/org/apache/sshd/common/signature/id_ecdsa
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIPKmiQzAASg656IP4PuuElLdLdO/MIXrGxQG6tGkKZ1HoAoGCCqGSM49
+AwEHoUQDQgAEobHtw9wkL332ep9fi8Gw5g8sEGwslNonPUCDR6YUZ9mjOehliLpF
+DLHLxlIFafrVM+LIpagjpRKZcnpGPWQDnA==
+-----END EC PRIVATE KEY-----
diff --git 
a/sshd-common/src/test/resources/org/apache/sshd/common/signature/id_rsa 
b/sshd-common/src/test/resources/org/apache/sshd/common/signature/id_rsa
new file mode 100644
index 0000000..afc6aa8
--- /dev/null
+++ b/sshd-common/src/test/resources/org/apache/sshd/common/signature/id_rsa
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEoQIBAAKCAQEAxr3N5fkt966xJINl0hH7Q6lLDRR1D0yMjcXCE5roE9VFut2c
+tGFuo90TCOxkPOMnwzwConeyScVF4ConZeWsxbG9VtRh61IeZ6R5P5ZTvE9xPdZB
+gIEWvU1bRfrrOfSMihqF98pODspE6NoTtND2eglwSGwxcYFmpdTAmu+8qgxgGxlE
+aaCjqwdiNPZhygrH81Mv2ruolNeZkn4Bj+wFFmZTD/waN1pQaMf+SO1+kEYIYFNl
+5+8JRGuUcr8MhHHJB+gwqMTF2BSBVITJzZUiQR0TMtkK6Vbs7yt1F9hhzDzAFDwh
+V+rsfNQaOHpl3zP07qH+/99A0XG1CVcEdHqVMwIBIwKCAQALW02YHN4OJz1Siypj
+xoNi87slUaBKBF/NlkWauGUIcpZFMTwnkIn6vCz5MhRbQC4oadRDzFNUrC/g7HdH
+prlqYe2P7uEGIfMb3YNFdk3tgOHmRsHqFgFMpVWsOjlTxNTUsQ74N3Isuxnha4wY
+9f90sBULc+WRdRvO9jbkSDaqoYVKAqCFWtocL+ZWwBXWrIrsQW4PElgZ/duc5DX7
+eeJ5DXCSj9dO+1KxsWEOKaoeABEegrRVys1/shcDNPhf/p0QShKIdPcpnDUc8cny
+1bq8GSt6jEQ+tuRoSnYrY+RD+mlkHrx373Xc1a9woV+QKTThmd9TQ8gzHMHNqq0a
+7kR7AoGBAOuPOTRiKaDtQyMTEX7eeHsPNE24EgvONjNpxyQ6gKGthG5SiB0IO7mP
+r7EggbR2EY8eMCY5HjvxzxgH86n2Pqbzsr6UlQq7YTPupCm/7fPgRknu917GA20f
+1cuY8B04Jp4FIGryBmCcScX6usXXhjfAvYCWWfkSytA8gX9+b1TNAoGBANf8shbp
+wRnQfgAzw2S+xs29pdwa6Jb/xuLvHSyklmgidrK4nsVI8G+zeCqwkqkNM02sM+vR
+c8EX7+myrGf+S2V3JS3AMNXEhavrWVH0CuqFHlBjSwHZ0uKuPpWHlCnud+23AdQz
+Bf1H7tYKt5es3J/B37o4YxhAL6U9qq+ewZH/AoGBAOTURjLjA94oT9jt870SoOyS
+bVLQEYfPol3UeE8UQnEsN4Ec+UDGK2PNaNfzsTL2WjNB5aF5UJIA184znD60seQC
+raMxQFORdF5ViYekgMEFwJ+XrnlSpD4e7PGqgtqOUWZOH33VKsRADSa5DTU3xDYo
+8porp9wDoHKD64MqXYWTAoGADFeVJeF4v6WDivukw+2k9dBSntz3WRXuG5iilNY0
+evqnsnDzITdeMkTFCcDycA9iBHA9ezCKRYxW2id3kOn1rgbO7KvliI7jESNkMJGa
+OUlvck7RFgxyc1pp+ep9fr0rbKtfMLJ1Xu4q56jXSn7oCSEFeFr+WSg9PKRwJ0rm
+fV8CgYAkYOiNY8jH5lwwoPWOIPJg62zdzmRQktrU3z7Nzk5udN6JnG3g57QjkozX
+AgHARKQ2MuXW9OfOnYNhbGeavcBQmg5XUx3eL4PRFw8mFZdjpBD/kM/dfCEwEta3
+FpRlVGn0RNqVV5xxClObD/CikkDqKZG4MSj3CrO3JK33gl1Lgg==
+-----END RSA PRIVATE KEY-----

Reply via email to