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

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

commit 834a078ad4583ef8937f54eec02fdea9b961a7f0
Author: Thomas Wolf <[email protected]>
AuthorDate: Sat Sep 6 00:31:53 2025 +0200

    More ed25519 simplifications
    
    Introduce a PublicKeyFactory interface for something that can recover a
    public key from a private key. On the ScurityProviderRegistrars
    implement this interface, and use that in SecurityUtils to recover
    ed25519 public keys.
    
    With that, the EdDSASupport interface and its per-registrar instances
    become obsolete. Remove them altogether.
    
    Move all EdDSA things that are not specific to a provider (which is
    actually everything but public key recovery) into the "eddsa.generic"
    package.
---
 .../apache/sshd/common/config/keys/KeyUtils.java   |  3 +-
 .../keys/impl/SkED25519PublicKeyEntryDecoder.java  |  4 +-
 .../loader/pem/PKCS8PEMResourceKeyPairParser.java  |  7 +-
 .../sshd/common/signature/BuiltinSignatures.java   |  2 +-
 .../sshd/common/signature/SignatureSkED25519.java  |  2 +-
 ...eKeyEntryDecoder.java => PublicKeyFactory.java} | 25 +++---
 .../util/security/SecurityProviderRegistrar.java   | 14 ++--
 .../sshd/common/util/security/SecurityUtils.java   | 92 ++++++++-------------
 .../bouncycastle/BouncyCastlePublicKeyFactory.java | 49 +++++++++++
 .../BouncyCastleSecurityProviderRegistrar.java     | 22 +++--
 .../eddsa/Ed25519PEMResourceKeyParser.java         | 63 --------------
 .../security/eddsa/Ed25519PublicKeyDecoder.java    | 42 ----------
 .../eddsa/EdDSASecurityProviderRegistrar.java      | 19 +++--
 .../security/eddsa/EdDSASecurityProviderUtils.java | 11 +--
 .../security/eddsa/NetI2pCryptoEdDSASupport.java   | 51 ------------
 .../bouncycastle/BouncyCastleEdDSASupport.java     | 60 --------------
 ...arser.java => Ed25519PEMResourceKeyParser.java} | 34 ++++++--
 ...eyDecoder.java => Ed25519PublicKeyDecoder.java} | 14 ++--
 .../util/security/eddsa/generic/EdDSASupport.java  | 96 ----------------------
 .../util/security/eddsa/generic/EdDSAUtils.java    | 34 ++++++--
 ...a => OpenSSHEd25519PrivateKeyEntryDecoder.java} | 15 ++--
 .../eddsa/{ => generic}/SignatureEd25519.java      |  2 +-
 .../util/security/eddsa/Ed25519VectorsTest.java    | 53 +++++-------
 .../common/signature/SignatureFactoriesTest.java   |  3 +-
 24 files changed, 233 insertions(+), 484 deletions(-)

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 059b3a4c3..ab6f70273 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
@@ -84,6 +84,7 @@ import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
 import org.apache.sshd.common.util.io.IoUtils;
 import org.apache.sshd.common.util.security.SecurityUtils;
+import 
org.apache.sshd.common.util.security.eddsa.generic.Ed25519PublicKeyDecoder;
 
 /**
  * Utility class for keys
@@ -172,7 +173,7 @@ public final class KeyUtils {
         registerPublicKeyEntryDecoder(ECDSAPublicKeyEntryDecoder.INSTANCE);
 
         if (SecurityUtils.isEDDSACurveSupported()) {
-            
registerPublicKeyEntryDecoder(SecurityUtils.getEDDSAPublicKeyEntryDecoder());
+            registerPublicKeyEntryDecoder(Ed25519PublicKeyDecoder.INSTANCE);
         }
 
         registerPublicKeyEntryDecoder(SkECDSAPublicKeyEntryDecoder.INSTANCE);
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/SkED25519PublicKeyEntryDecoder.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/SkED25519PublicKeyEntryDecoder.java
index 2a2e90b15..de2656de6 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/SkED25519PublicKeyEntryDecoder.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/SkED25519PublicKeyEntryDecoder.java
@@ -36,7 +36,7 @@ import 
org.apache.sshd.common.config.keys.u2f.SkED25519PublicKey;
 import org.apache.sshd.common.keyprovider.KeyPairProvider;
 import org.apache.sshd.common.session.SessionContext;
 import org.apache.sshd.common.util.ValidateUtils;
-import org.apache.sshd.common.util.security.SecurityUtils;
+import 
org.apache.sshd.common.util.security.eddsa.generic.Ed25519PublicKeyDecoder;
 import org.apache.sshd.common.util.security.eddsa.generic.EdDSAUtils;
 
 /**
@@ -65,7 +65,7 @@ public class SkED25519PublicKeyEntryDecoder extends 
AbstractPublicKeyEntryDecode
 
         boolean noTouchRequired = parseBooleanHeader(headers, 
NO_TOUCH_REQUIRED_HEADER, false);
         boolean verifyRequired = parseBooleanHeader(headers, 
VERIFY_REQUIRED_HEADER, false);
-        PublicKey pk = 
SecurityUtils.getEDDSAPublicKeyEntryDecoder().decodePublicKey(session, 
KeyPairProvider.SSH_ED25519,
+        PublicKey pk = 
Ed25519PublicKeyDecoder.INSTANCE.decodePublicKey(session, 
KeyPairProvider.SSH_ED25519,
                 keyData, headers);
         String appName = KeyEntryResolver.decodeString(keyData, 
MAX_APP_NAME_LENGTH);
         return new SkED25519PublicKey(appName, noTouchRequired, 
verifyRequired, pk);
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParser.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParser.java
index 38134fc83..74a5a221b 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParser.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParser.java
@@ -49,7 +49,8 @@ import org.apache.sshd.common.util.io.der.ASN1Type;
 import org.apache.sshd.common.util.io.der.DERParser;
 import org.apache.sshd.common.util.security.Decryptor;
 import org.apache.sshd.common.util.security.SecurityUtils;
-import org.apache.sshd.common.util.security.eddsa.generic.EdDSASupport;
+import 
org.apache.sshd.common.util.security.eddsa.generic.Ed25519PEMResourceKeyParser;
+import org.apache.sshd.common.util.security.eddsa.generic.EdDSAUtils;
 
 /**
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
@@ -146,9 +147,9 @@ public class PKCS8PEMResourceKeyPairParser extends 
AbstractPEMResourceKeyPairPar
                 kp = ECDSAPEMResourceKeyPairParser.parseECKeyPair(curve, 
parser);
             }
         } else if (SecurityUtils.isEDDSACurveSupported()
-                && EdDSASupport.ED25519_OID.endsWith(oid)) {
+                && EdDSAUtils.ED25519_OID.equals(oid)) {
             ASN1Object privateKeyBytes = pkcs8Info.getPrivateKeyBytes();
-            kp = 
EdDSASupport.decodeEd25519KeyPair(privateKeyBytes.getPureValueBytes());
+            kp = 
Ed25519PEMResourceKeyParser.decodeEd25519KeyPair(privateKeyBytes.getPureValueBytes());
         } else {
             PrivateKey prvKey = decodePEMPrivateKeyPKCS8(oidAlgorithm, 
encBytes);
             PublicKey pubKey = 
ValidateUtils.checkNotNull(KeyUtils.recoverPublicKey(prvKey),
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 bb3444351..b943e9eea 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
@@ -44,7 +44,7 @@ import org.apache.sshd.common.keyprovider.KeyPairProvider;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.security.SecurityUtils;
-import org.apache.sshd.common.util.security.eddsa.SignatureEd25519;
+import org.apache.sshd.common.util.security.eddsa.generic.SignatureEd25519;
 
 /**
  * Provides easy access to the currently implemented signatures
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureSkED25519.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureSkED25519.java
index 9c43ab64d..12510ce70 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureSkED25519.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureSkED25519.java
@@ -20,7 +20,7 @@ package org.apache.sshd.common.signature;
 
 import org.apache.sshd.common.config.keys.impl.SkED25519PublicKeyEntryDecoder;
 import org.apache.sshd.common.keyprovider.KeyPairProvider;
-import org.apache.sshd.common.util.security.eddsa.SignatureEd25519;
+import org.apache.sshd.common.util.security.eddsa.generic.SignatureEd25519;
 
 public class SignatureSkED25519 extends AbstractSecurityKeySignature {
 
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/OpenSSHEd25519PrivateKeyEntryDecoder.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/PublicKeyFactory.java
similarity index 58%
rename from 
sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/OpenSSHEd25519PrivateKeyEntryDecoder.java
rename to 
sshd-common/src/main/java/org/apache/sshd/common/util/security/PublicKeyFactory.java
index 7cfb3555b..a2903d1b1 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/OpenSSHEd25519PrivateKeyEntryDecoder.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/PublicKeyFactory.java
@@ -16,23 +16,24 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.sshd.common.util.security;
 
-package org.apache.sshd.common.util.security.eddsa;
-
-import 
org.apache.sshd.common.util.security.eddsa.generic.GenericOpenSSHEd25519PrivateKeyEntryDecoder;
+import java.security.PrivateKey;
+import java.security.PublicKey;
 
 /**
- * An implementation of {@link GenericOpenSSHEd25519PrivateKeyEntryDecoder} 
tied to the {@code net.i2p.crypto} EdDSA
- * security provider
+ * Something that can compute a {@link PublicKey} from a given {@link 
PrivateKey}.
  *
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  */
-public class OpenSSHEd25519PrivateKeyEntryDecoder
-        extends GenericOpenSSHEd25519PrivateKeyEntryDecoder {
-    public static final OpenSSHEd25519PrivateKeyEntryDecoder INSTANCE = new 
OpenSSHEd25519PrivateKeyEntryDecoder();
-
-    public OpenSSHEd25519PrivateKeyEntryDecoder() {
-        super(new NetI2pCryptoEdDSASupport());
-    }
+@FunctionalInterface
+public interface PublicKeyFactory {
 
+    /**
+     * Given a {@link PrivateKey} computes the corresponding {@link PublicKey}.
+     *
+     * @param  key {@link PrivateKey} to get the {@link PublicKey} for
+     * @return     the {@link PublicKey}, or {@code null} if no public key 
could be computed
+     */
+    PublicKey getPublicKey(PrivateKey key);
 }
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityProviderRegistrar.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityProviderRegistrar.java
index ec39cdf89..68c9756a4 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityProviderRegistrar.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityProviderRegistrar.java
@@ -22,7 +22,9 @@ package org.apache.sshd.common.util.security;
 import java.security.KeyFactory;
 import java.security.KeyPairGenerator;
 import java.security.MessageDigest;
+import java.security.PrivateKey;
 import java.security.Provider;
+import java.security.PublicKey;
 import java.security.Security;
 import java.security.Signature;
 import java.security.cert.CertificateFactory;
@@ -32,7 +34,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.function.Predicate;
 
 import javax.crypto.Cipher;
@@ -46,12 +47,11 @@ import org.apache.sshd.common.SyspropsMapWrapper;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.IgnoringEmptyMap;
 import org.apache.sshd.common.util.ValidateUtils;
-import org.apache.sshd.common.util.security.eddsa.generic.EdDSASupport;
 
 /**
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  */
-public interface SecurityProviderRegistrar extends SecurityProviderChoice, 
OptionalFeature, PropertyResolver {
+public interface SecurityProviderRegistrar extends SecurityProviderChoice, 
OptionalFeature, PublicKeyFactory, PropertyResolver {
     /**
      * Base name for configuration properties related to security providers
      */
@@ -190,11 +190,9 @@ public interface SecurityProviderRegistrar extends 
SecurityProviderChoice, Optio
         return isSecurityEntitySupported(CertificateFactory.class, type);
     }
 
-    /**
-     * @return the EdDSA support implementation associated with the security 
provider (if applicable)
-     */
-    default Optional<EdDSASupport> getEdDSASupport() {
-        return Optional.empty();
+    @Override
+    default PublicKey getPublicKey(PrivateKey key) {
+        return null;
     }
 
     /**
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
index dcfb98101..609cd0b0d 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
@@ -42,7 +42,6 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.TreeSet;
@@ -60,7 +59,6 @@ import org.apache.sshd.common.NamedResource;
 import org.apache.sshd.common.PropertyResolverUtils;
 import org.apache.sshd.common.config.keys.FilePasswordProvider;
 import org.apache.sshd.common.config.keys.PrivateKeyEntryDecoder;
-import org.apache.sshd.common.config.keys.PublicKeyEntryDecoder;
 import org.apache.sshd.common.config.keys.loader.KeyPairResourceParser;
 import 
org.apache.sshd.common.config.keys.loader.openssh.OpenSSHKeyPairResourceParser;
 import org.apache.sshd.common.config.keys.loader.pem.PEMResourceParserUtils;
@@ -76,8 +74,8 @@ import 
org.apache.sshd.common.util.security.bouncycastle.BouncyCastleEncryptedPr
 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.generic.EdDSASupport;
 import org.apache.sshd.common.util.security.eddsa.generic.EdDSAUtils;
+import 
org.apache.sshd.common.util.security.eddsa.generic.OpenSSHEd25519PrivateKeyEntryDecoder;
 import org.apache.sshd.common.util.threads.ThreadUtils;
 import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvider;
 import org.slf4j.Logger;
@@ -168,6 +166,8 @@ public final class SecurityUtils {
 
     private static final AtomicReference<Boolean> FIPS_MODE = new 
AtomicReference<>();
 
+    private static final AtomicReference<Boolean> EDDSA_SUPPORT_PRESENT = new 
AtomicReference<>();
+
     private SecurityUtils() {
         throw new UnsupportedOperationException("No instance");
     }
@@ -556,7 +556,26 @@ public final class SecurityUtils {
      * @return {@code true} if EDDSA curves (e.g., {@code ed25519}) are 
supported
      */
     public static boolean isEDDSACurveSupported() {
-        return getEdDSASupport().isPresent();
+        Boolean isSupported = EDDSA_SUPPORT_PRESENT.get();
+        if (isSupported == null) {
+            register();
+            // Currently we can only support ed25519 through libraries and 
thus we require a registrar.
+            // TODO: GH-585 (needs a multi-release JAR)
+            boolean supported = false;
+            synchronized (REGISTERED_PROVIDERS) {
+                for (SecurityProviderRegistrar r : 
REGISTERED_PROVIDERS.values()) {
+                    supported = r.isEnabled() && r.isSupported() && 
r.isKeyFactorySupported(ED25519);
+                    if (supported) {
+                        break;
+                    }
+                }
+            }
+            isSupported = Boolean.valueOf(supported);
+            if (!EDDSA_SUPPORT_PRESENT.compareAndSet(null, 
Boolean.valueOf(supported))) {
+                isSupported = EDDSA_SUPPORT_PRESENT.get();
+            }
+        }
+        return isSupported != null && isSupported.booleanValue();
     }
 
     public static boolean isNetI2pCryptoEdDSARegistered() {
@@ -564,73 +583,30 @@ public final class SecurityUtils {
         return isProviderRegistered(EDDSA);
     }
 
-    public static Optional<EdDSASupport> getEdDSASupport() {
-        if (isFipsMode()) {
-            return Optional.empty();
-        }
-        register();
-
-        synchronized (REGISTERED_PROVIDERS) {
-            // Prefer the net.i2p.crypto provider if it's available for 
backwards compatibility
-            SecurityProviderRegistrar netI2pCryptoProvider = 
REGISTERED_PROVIDERS.get(EDDSA);
-            if (netI2pCryptoProvider != null) {
-                Optional<EdDSASupport> support = 
netI2pCryptoProvider.getEdDSASupport();
-                if (support.isPresent()) {
-                    return support;
-                }
-            }
-
-            for (Map.Entry<String, SecurityProviderRegistrar> entry : 
REGISTERED_PROVIDERS.entrySet()) {
-                Optional<EdDSASupport> support = 
entry.getValue().getEdDSASupport();
-                if (support.isPresent()) {
-                    return support;
-                }
-            }
-        }
-        return Optional.empty();
-    }
-
     /* -------------------------------------------------------------------- */
 
-    public static PublicKeyEntryDecoder getEDDSAPublicKeyEntryDecoder() {
-        Optional<EdDSASupport> support = getEdDSASupport();
-        if (!support.isPresent()) {
-            throw new UnsupportedOperationException(EDDSA + " provider N/A");
-        }
-
-        return support.get().getEDDSAPublicKeyEntryDecoder();
-    }
-
     public static PrivateKeyEntryDecoder 
getOpenSSHEDDSAPrivateKeyEntryDecoder() {
-        Optional<EdDSASupport> support = getEdDSASupport();
-        if (!support.isPresent()) {
-            throw new UnsupportedOperationException(EDDSA + " provider N/A");
-        }
-
-        return support.get().getOpenSSHEDDSAPrivateKeyEntryDecoder();
+        return OpenSSHEd25519PrivateKeyEntryDecoder.INSTANCE;
     }
 
     public static boolean compareEDDSAPPublicKeys(PublicKey k1, PublicKey k2) {
-        if (k1 == null && k2 == null) {
-            return true;
-        }
-        return k1 != null && k2 != null && EdDSAUtils.equals(k1, k2);
+        return EdDSAUtils.equals(k1, k2);
     }
 
     public static boolean compareEDDSAPrivateKeys(PrivateKey k1, PrivateKey 
k2) {
-        if (k1 == null && k2 == null) {
-            return true;
-        }
-        return k1 != null && k2 != null && EdDSAUtils.equals(k1, k2);
+        return EdDSAUtils.equals(k1, k2);
     }
 
     public static PublicKey recoverEDDSAPublicKey(PrivateKey key) throws 
GeneralSecurityException {
-        Optional<EdDSASupport> support = getEdDSASupport();
-        if (!support.isPresent()) {
-            throw new NoSuchAlgorithmException(EDDSA + " provider not 
supported");
+        synchronized (REGISTERED_PROVIDERS) {
+            for (SecurityProviderRegistrar registrar : 
REGISTERED_PROVIDERS.values()) {
+                PublicKey pk = registrar.getPublicKey(key);
+                if (pk != null) {
+                    return pk;
+                }
+            }
         }
-
-        return support.get().recoverEDDSAPublicKey(key);
+        return null;
     }
 
     public static KeyPair extractEDDSAKeyPair(Buffer buffer, String keyType) 
throws GeneralSecurityException {
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastlePublicKeyFactory.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastlePublicKeyFactory.java
new file mode 100644
index 000000000..70a1a0aaa
--- /dev/null
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastlePublicKeyFactory.java
@@ -0,0 +1,49 @@
+/*
+ * 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.PrivateKey;
+import java.security.PublicKey;
+
+import org.apache.sshd.common.util.security.PublicKeyFactory;
+import org.apache.sshd.common.util.security.SecurityUtils;
+import org.bouncycastle.jcajce.interfaces.EdDSAPrivateKey;
+
+public class BouncyCastlePublicKeyFactory implements PublicKeyFactory {
+
+    public BouncyCastlePublicKeyFactory() {
+        super();
+    }
+
+    @Override
+    public PublicKey getPublicKey(PrivateKey key) {
+        if (SecurityUtils.ED25519.equals(key.getAlgorithm())) {
+            return getPublicEdDSAKey(key);
+        }
+        return null;
+    }
+
+    public PublicKey getPublicEdDSAKey(PrivateKey key) {
+        if (key instanceof EdDSAPrivateKey) {
+            EdDSAPrivateKey edDSAKey = (EdDSAPrivateKey) key;
+            return edDSAKey.getPublicKey();
+        }
+        return null;
+    }
+}
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleSecurityProviderRegistrar.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleSecurityProviderRegistrar.java
index 206a1e95a..fbd1de662 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleSecurityProviderRegistrar.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleSecurityProviderRegistrar.java
@@ -21,17 +21,17 @@ package org.apache.sshd.common.util.security.bouncycastle;
 import java.lang.reflect.Field;
 import java.security.KeyFactory;
 import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
 import java.security.Provider;
+import java.security.PublicKey;
 import java.security.Security;
 import java.security.Signature;
-import java.util.Optional;
 import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.sshd.common.util.ExceptionUtils;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.security.AbstractSecurityProviderRegistrar;
 import org.apache.sshd.common.util.security.SecurityUtils;
-import org.apache.sshd.common.util.security.eddsa.generic.EdDSASupport;
 import org.apache.sshd.common.util.threads.ThreadUtils;
 
 /**
@@ -104,14 +104,12 @@ public class BouncyCastleSecurityProviderRegistrar 
extends AbstractSecurityProvi
 
         if (KeyPairGenerator.class.isAssignableFrom(entityType)
                 || KeyFactory.class.isAssignableFrom(entityType)) {
-            if (SecurityUtils.ED25519.equalsIgnoreCase(name)
-                    && SecurityUtils.isNetI2pCryptoEdDSARegistered()) {
-                return false;
+            if (SecurityUtils.ED25519.equalsIgnoreCase(name)) {
+                return !SecurityUtils.isNetI2pCryptoEdDSARegistered() && 
isEdDSASupported();
             }
         } else if (Signature.class.isAssignableFrom(entityType)) {
-            if (SecurityUtils.ED25519.equalsIgnoreCase(name)
-                    && SecurityUtils.isNetI2pCryptoEdDSARegistered()) {
-                return false;
+            if (SecurityUtils.ED25519.equalsIgnoreCase(name)) {
+                return !SecurityUtils.isNetI2pCryptoEdDSARegistered() && 
isEdDSASupported();
             }
         }
 
@@ -172,11 +170,11 @@ public class BouncyCastleSecurityProviderRegistrar 
extends AbstractSecurityProvi
     }
 
     @Override
-    public Optional<EdDSASupport> getEdDSASupport() {
-        if (!isEdDSASupported()) {
-            return Optional.empty();
+    public PublicKey getPublicKey(PrivateKey key) {
+        if (isEnabled() && isEdDSASupported() && 
key.getClass().getPackage().getName().startsWith("org.bouncycastle.")) {
+            return new BouncyCastlePublicKeyFactory().getPublicKey(key);
         }
-        return Optional.of(new 
org.apache.sshd.common.util.security.eddsa.bouncycastle.BouncyCastleEdDSASupport());
+        return super.getPublicKey(key);
     }
 
     private boolean isEdDSASupported() {
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/Ed25519PEMResourceKeyParser.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/Ed25519PEMResourceKeyParser.java
deleted file mode 100644
index 63ddddac3..000000000
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/Ed25519PEMResourceKeyParser.java
+++ /dev/null
@@ -1,63 +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.io.IOException;
-import java.security.GeneralSecurityException;
-import java.security.KeyFactory;
-import java.security.NoSuchAlgorithmException;
-
-import net.i2p.crypto.eddsa.EdDSAPrivateKey;
-import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
-import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
-import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
-import org.apache.sshd.common.util.security.SecurityUtils;
-import org.apache.sshd.common.util.security.eddsa.generic.EdDSASupport;
-import 
org.apache.sshd.common.util.security.eddsa.generic.GenericEd25519PEMResourceKeyParser;
-
-/**
- * An implementation of {@link GenericEd25519PEMResourceKeyParser} tied to the 
{@code net.i2p.crypto} EdDSA security
- * provider.
- *
- * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
- */
-public class Ed25519PEMResourceKeyParser extends 
GenericEd25519PEMResourceKeyParser {
-
-    public static final Ed25519PEMResourceKeyParser INSTANCE = new 
Ed25519PEMResourceKeyParser();
-
-    public Ed25519PEMResourceKeyParser() {
-        super();
-    }
-
-    public static EdDSAPrivateKey decodeEdDSAPrivateKey(byte[] keyData) throws 
IOException, GeneralSecurityException {
-        return 
EdDSAPrivateKey.class.cast(EdDSASupport.decodeEdDSAPrivateKey(keyData));
-    }
-
-    public static EdDSAPrivateKey generateEdDSAPrivateKey(byte[] seed) throws 
GeneralSecurityException {
-        if (!SecurityUtils.isEDDSACurveSupported()) {
-            throw new NoSuchAlgorithmException(SecurityUtils.EDDSA + " 
provider not supported");
-        }
-
-        EdDSAParameterSpec params = 
EdDSANamedCurveTable.getByName(SecurityUtils.ED25519);
-        EdDSAPrivateKeySpec keySpec = new EdDSAPrivateKeySpec(seed, params);
-        KeyFactory factory = 
SecurityUtils.getKeyFactory(SecurityUtils.ED25519);
-        return EdDSAPrivateKey.class.cast(factory.generatePrivate(keySpec));
-    }
-}
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/Ed25519PublicKeyDecoder.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/Ed25519PublicKeyDecoder.java
deleted file mode 100644
index eb1ffcd45..000000000
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/Ed25519PublicKeyDecoder.java
+++ /dev/null
@@ -1,42 +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 net.i2p.crypto.eddsa.EdDSAPublicKey;
-import 
org.apache.sshd.common.util.security.eddsa.generic.GenericEd25519PublicKeyDecoder;
-
-/**
- * An implementation of {@link GenericEd25519PublicKeyDecoder} tied to the 
{@code net.i2p.crypto} EdDSA security
- * provider.
- *
- * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
- */
-public final class Ed25519PublicKeyDecoder extends 
GenericEd25519PublicKeyDecoder {
-
-    public static final Ed25519PublicKeyDecoder INSTANCE = new 
Ed25519PublicKeyDecoder();
-
-    private Ed25519PublicKeyDecoder() {
-        super(new NetI2pCryptoEdDSASupport());
-    }
-
-    public static byte[] getSeedValue(EdDSAPublicKey key) {
-        // a bit of reverse-engineering on the EdDSAPublicKeySpec
-        return (key == null) ? null : key.getAbyte();
-    }
-}
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrar.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrar.java
index 3697bdf24..b351153ca 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrar.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrar.java
@@ -21,16 +21,16 @@ package org.apache.sshd.common.util.security.eddsa;
 import java.security.GeneralSecurityException;
 import java.security.KeyFactory;
 import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
 import java.security.Provider;
+import java.security.PublicKey;
 import java.security.Signature;
-import java.util.Optional;
 import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.sshd.common.util.ExceptionUtils;
 import org.apache.sshd.common.util.security.AbstractSecurityProviderRegistrar;
 import org.apache.sshd.common.util.security.SecurityEntityFactory;
 import org.apache.sshd.common.util.security.SecurityUtils;
-import org.apache.sshd.common.util.security.eddsa.generic.EdDSASupport;
 import org.apache.sshd.common.util.threads.ThreadUtils;
 
 /**
@@ -131,14 +131,19 @@ public class EdDSASecurityProviderRegistrar extends 
AbstractSecurityProviderRegi
     }
 
     @Override
-    public Optional<EdDSASupport> getEdDSASupport() {
-        if (!isSupported()) {
-            return Optional.empty();
+    public PublicKey getPublicKey(PrivateKey key) {
+        if (isEnabled() && isSupported() && "EdDSA".equals(key.getAlgorithm())
+                && 
key.getClass().getPackage().getName().startsWith("net.i2p.")) {
+            try {
+                return EdDSASecurityProviderUtils.recoverEDDSAPublicKey(key);
+            } catch (GeneralSecurityException e) {
+                return null;
+            }
         }
-        return Optional.of(new NetI2pCryptoEdDSASupport());
+        return super.getPublicKey(key);
     }
 
-    private static abstract class DelegatingSecurityEntityFactory<F> 
implements SecurityEntityFactory<F> {
+    private abstract static class DelegatingSecurityEntityFactory<F> 
implements SecurityEntityFactory<F> {
 
         private SecurityEntityFactory<F> delegate;
 
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderUtils.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderUtils.java
index 2fe0705c6..e6d0c9f9f 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderUtils.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderUtils.java
@@ -34,19 +34,19 @@ import net.i2p.crypto.eddsa.EdDSAPrivateKey;
 import net.i2p.crypto.eddsa.EdDSAPublicKey;
 import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
 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.util.ValidateUtils;
 import org.apache.sshd.common.util.security.SecurityUtils;
-import org.apache.sshd.common.util.security.eddsa.generic.EdDSASupport;
+import 
org.apache.sshd.common.util.security.eddsa.generic.Ed25519PublicKeyDecoder;
 import org.apache.sshd.common.util.security.eddsa.generic.EdDSAUtils;
+import org.apache.sshd.common.util.security.eddsa.generic.SignatureEd25519;
 
 /**
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  */
 public final class EdDSASecurityProviderUtils {
     // See EdDSANamedCurveTable
-    public static final int KEY_SIZE = EdDSASupport.KEY_SIZE;
+    public static final int KEY_SIZE = EdDSAUtils.ED25519_LENGTH * Byte.SIZE;
 
     private EdDSASecurityProviderUtils() {
         throw new UnsupportedOperationException("No instance");
@@ -105,11 +105,6 @@ public final class EdDSASecurityProviderUtils {
         return Ed25519PublicKeyDecoder.INSTANCE;
     }
 
-    public static PrivateKeyEntryDecoder 
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;
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/NetI2pCryptoEdDSASupport.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/NetI2pCryptoEdDSASupport.java
deleted file mode 100644
index da8a64eee..000000000
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/NetI2pCryptoEdDSASupport.java
+++ /dev/null
@@ -1,51 +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.PrivateKey;
-
-import net.i2p.crypto.eddsa.EdDSAPublicKey;
-import org.apache.sshd.common.config.keys.PrivateKeyEntryDecoder;
-import org.apache.sshd.common.config.keys.PublicKeyEntryDecoder;
-import org.apache.sshd.common.util.security.eddsa.generic.EdDSASupport;
-
-public class NetI2pCryptoEdDSASupport implements EdDSASupport {
-
-    public NetI2pCryptoEdDSASupport() {
-        super();
-    }
-
-    @Override
-    public PublicKeyEntryDecoder getEDDSAPublicKeyEntryDecoder() {
-        return Ed25519PublicKeyDecoder.INSTANCE;
-    }
-
-    @Override
-    public PrivateKeyEntryDecoder getOpenSSHEDDSAPrivateKeyEntryDecoder() {
-        return OpenSSHEd25519PrivateKeyEntryDecoder.INSTANCE;
-    }
-
-    @Override
-    public EdDSAPublicKey recoverEDDSAPublicKey(PrivateKey key) throws 
GeneralSecurityException {
-        return EdDSASecurityProviderUtils.recoverEDDSAPublicKey(key);
-    }
-
-}
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/bouncycastle/BouncyCastleEdDSASupport.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/bouncycastle/BouncyCastleEdDSASupport.java
deleted file mode 100644
index ea679e906..000000000
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/bouncycastle/BouncyCastleEdDSASupport.java
+++ /dev/null
@@ -1,60 +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.bouncycastle;
-
-import java.security.GeneralSecurityException;
-import java.security.InvalidKeyException;
-import java.security.PrivateKey;
-
-import org.apache.sshd.common.config.keys.PrivateKeyEntryDecoder;
-import org.apache.sshd.common.config.keys.PublicKeyEntryDecoder;
-import org.apache.sshd.common.util.security.SecurityUtils;
-import org.apache.sshd.common.util.security.eddsa.generic.EdDSASupport;
-import 
org.apache.sshd.common.util.security.eddsa.generic.GenericEd25519PublicKeyDecoder;
-import 
org.apache.sshd.common.util.security.eddsa.generic.GenericOpenSSHEd25519PrivateKeyEntryDecoder;
-import org.bouncycastle.jcajce.interfaces.EdDSAPrivateKey;
-import org.bouncycastle.jcajce.interfaces.EdDSAPublicKey;
-
-public class BouncyCastleEdDSASupport implements EdDSASupport {
-
-    public BouncyCastleEdDSASupport() {
-        super();
-    }
-
-    @Override
-    public PublicKeyEntryDecoder getEDDSAPublicKeyEntryDecoder() {
-        return new GenericEd25519PublicKeyDecoder(this);
-    }
-
-    @Override
-    public PrivateKeyEntryDecoder getOpenSSHEDDSAPrivateKeyEntryDecoder() {
-        return new GenericOpenSSHEd25519PrivateKeyEntryDecoder(this);
-    }
-
-    @Override
-    public EdDSAPublicKey recoverEDDSAPublicKey(PrivateKey key) throws 
GeneralSecurityException {
-        if (!(key instanceof EdDSAPrivateKey)) {
-            throw new InvalidKeyException("Private key is not " + 
SecurityUtils.EDDSA);
-        }
-        EdDSAPrivateKey edDSAKey = (EdDSAPrivateKey) key;
-        return edDSAKey.getPublicKey();
-    }
-
-}
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/GenericEd25519PEMResourceKeyParser.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/Ed25519PEMResourceKeyParser.java
similarity index 80%
rename from 
sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/GenericEd25519PEMResourceKeyParser.java
rename to 
sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/Ed25519PEMResourceKeyParser.java
index 7ee7c47f2..f32985d77 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/GenericEd25519PEMResourceKeyParser.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/Ed25519PEMResourceKeyParser.java
@@ -25,6 +25,8 @@ import java.io.StreamCorruptedException;
 import java.math.BigInteger;
 import java.security.GeneralSecurityException;
 import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -44,7 +46,7 @@ import org.apache.sshd.common.util.security.SecurityUtils;
 /**
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  */
-public class GenericEd25519PEMResourceKeyParser extends 
AbstractPEMResourceKeyPairParser {
+public class Ed25519PEMResourceKeyParser extends 
AbstractPEMResourceKeyPairParser {
 
     // From an early draft of RFC 8410 
(https://datatracker.ietf.org/doc/html/draft-ietf-curdle-pkix-eddsa-00).
     // The final RFC 8410 dropped the "EDDSA" and moved to PKCS#8 using just 
"BEGIN PRIVATE KEY".
@@ -59,11 +61,11 @@ public class GenericEd25519PEMResourceKeyParser extends 
AbstractPEMResourceKeyPa
     public static final String END_ED25519_MARKER = "END ED25519 PRIVATE KEY";
     public static final List<String> ENDERS = 
GenericUtils.unmodifiableList(END_MARKER, END_ED25519_MARKER);
 
-    public static final String ED25519_OID = EdDSASupport.ED25519_OID;
+    public static final String ED25519_OID = EdDSAUtils.ED25519_OID;
 
-    public static final GenericEd25519PEMResourceKeyParser INSTANCE = new 
GenericEd25519PEMResourceKeyParser();
+    public static final Ed25519PEMResourceKeyParser INSTANCE = new 
Ed25519PEMResourceKeyParser();
 
-    public GenericEd25519PEMResourceKeyParser() {
+    public Ed25519PEMResourceKeyParser() {
         super(SecurityUtils.ED25519, ED25519_OID, BEGINNERS, ENDERS);
     }
 
@@ -145,7 +147,29 @@ public class GenericEd25519PEMResourceKeyParser extends 
AbstractPEMResourceKeyPa
     }
 
     public static KeyPair decodeEd25519KeyPair(byte[] keyData) throws 
IOException, GeneralSecurityException {
-        return EdDSASupport.decodeEd25519KeyPair(keyData);
+        PrivateKey privateKey = decodeEdDSAPrivateKey(keyData);
+        PublicKey publicKey = SecurityUtils.recoverEDDSAPublicKey(privateKey);
+        return new KeyPair(publicKey, privateKey);
+    }
+
+    /**
+     * @param  keyData the raw private key bytes.
+     * @return         the associated private key.
+     */
+    private static PrivateKey decodeEdDSAPrivateKey(byte[] keyData) throws 
IOException, GeneralSecurityException {
+        try (DERParser parser = new DERParser(keyData)) {
+            ASN1Object obj = parser.readObject();
+            if (obj == null) {
+                throw new StreamCorruptedException("Missing key data 
container");
+            }
+
+            ASN1Type objType = obj.getObjType();
+            if (objType != ASN1Type.OCTET_STRING) {
+                throw new StreamCorruptedException("Mismatched key data 
container type: " + objType);
+            }
+
+            return EdDSAUtils.getPrivateKey(obj.getValue());
+        }
     }
 
 }
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/GenericEd25519PublicKeyDecoder.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/Ed25519PublicKeyDecoder.java
similarity index 86%
rename from 
sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/GenericEd25519PublicKeyDecoder.java
rename to 
sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/Ed25519PublicKeyDecoder.java
index 084bfe0c9..712defeac 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/GenericEd25519PublicKeyDecoder.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/Ed25519PublicKeyDecoder.java
@@ -36,16 +36,18 @@ import org.apache.sshd.common.session.SessionContext;
 import org.apache.sshd.common.util.security.SecurityUtils;
 
 /**
+ * An {@link AbstractPublicKeyEntryDecoder} for ed25519 keys.
+ *
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  */
-public class GenericEd25519PublicKeyDecoder extends 
AbstractPublicKeyEntryDecoder {
+public final class Ed25519PublicKeyDecoder extends 
AbstractPublicKeyEntryDecoder {
+
     public static final int MAX_ALLOWED_SEED_LEN = 1024; // in reality it is 
much less than this
 
-    protected final EdDSASupport edDSASupport;
+    public static final Ed25519PublicKeyDecoder INSTANCE = new 
Ed25519PublicKeyDecoder();
 
-    public GenericEd25519PublicKeyDecoder(EdDSASupport edDSASupport) {
+    private Ed25519PublicKeyDecoder() {
         super(Collections.singletonList(KeyPairProvider.SSH_ED25519));
-        this.edDSASupport = edDSASupport;
     }
 
     @Override
@@ -67,11 +69,9 @@ public class GenericEd25519PublicKeyDecoder extends 
AbstractPublicKeyEntryDecode
     }
 
     @Override
-    public PublicKey decodePublicKey(
-            SessionContext session, String keyType, InputStream keyData, 
Map<String, String> headers)
+    public PublicKey decodePublicKey(SessionContext session, String keyType, 
InputStream keyData, Map<String, String> headers)
             throws IOException, GeneralSecurityException {
         byte[] seed = KeyEntryResolver.readRLEBytes(keyData, 
MAX_ALLOWED_SEED_LEN);
         return EdDSAUtils.getPublicKey(seed);
     }
-
 }
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/EdDSASupport.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/EdDSASupport.java
deleted file mode 100644
index 02ff2e18c..000000000
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/EdDSASupport.java
+++ /dev/null
@@ -1,96 +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.generic;
-
-import java.io.IOException;
-import java.io.StreamCorruptedException;
-import java.security.GeneralSecurityException;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-
-import org.apache.sshd.common.config.keys.PrivateKeyEntryDecoder;
-import org.apache.sshd.common.config.keys.PublicKeyEntryDecoder;
-import org.apache.sshd.common.util.io.der.ASN1Object;
-import org.apache.sshd.common.util.io.der.ASN1Type;
-import org.apache.sshd.common.util.io.der.DERParser;
-import org.apache.sshd.common.util.security.SecurityUtils;
-
-/**
- * Provides generic operations required of a security provider to support 
EdDSA and Ed25519.
- *
- * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
- */
-public interface EdDSASupport {
-
-    int KEY_SIZE = 256;
-
-    /**
-     * @see <A HREF="https://tools.ietf.org/html/rfc8410#section-3";>RFC8412 
section 3</A>
-     */
-    String ED25519_OID = "1.3.101.112";
-
-    /**
-     * @param  keyData the raw private key bytes.
-     * @return         a {@link KeyPair} from the given raw private key data.
-     */
-    static KeyPair decodeEd25519KeyPair(byte[] keyData) throws IOException, 
GeneralSecurityException {
-        PrivateKey privateKey = decodeEdDSAPrivateKey(keyData);
-        PublicKey publicKey = SecurityUtils.recoverEDDSAPublicKey(privateKey);
-        return new KeyPair(publicKey, privateKey);
-    }
-
-    /**
-     * @param  keyData the raw private key bytes.
-     * @return         the associated private key.
-     */
-    static PrivateKey decodeEdDSAPrivateKey(byte[] keyData) throws 
IOException, GeneralSecurityException {
-        try (DERParser parser = new DERParser(keyData)) {
-            ASN1Object obj = parser.readObject();
-            if (obj == null) {
-                throw new StreamCorruptedException("Missing key data 
container");
-            }
-
-            ASN1Type objType = obj.getObjType();
-            if (objType != ASN1Type.OCTET_STRING) {
-                throw new StreamCorruptedException("Mismatched key data 
container type: " + objType);
-            }
-
-            return EdDSAUtils.getPrivateKey(obj.getValue());
-        }
-    }
-
-    /**
-     * @return the public key entry decoder implementation associated with the 
security provider.
-     */
-    PublicKeyEntryDecoder getEDDSAPublicKeyEntryDecoder();
-
-    /**
-     * @return the private key entry decoder implementation associated with 
the security provider.
-     */
-    PrivateKeyEntryDecoder getOpenSSHEDDSAPrivateKeyEntryDecoder();
-
-    /**
-     * @param  key the private key
-     * @return     the public key associated with the private key.
-     */
-    PublicKey recoverEDDSAPublicKey(PrivateKey key) throws 
GeneralSecurityException;
-
-}
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/EdDSAUtils.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/EdDSAUtils.java
index 61460c46c..838c50e3d 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/EdDSAUtils.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/EdDSAUtils.java
@@ -28,6 +28,7 @@ import java.security.spec.KeySpec;
 import java.security.spec.PKCS8EncodedKeySpec;
 import java.security.spec.X509EncodedKeySpec;
 import java.util.Arrays;
+import java.util.Objects;
 
 import org.apache.sshd.common.util.io.der.DERParser;
 import org.apache.sshd.common.util.security.SecurityUtils;
@@ -40,9 +41,19 @@ import org.apache.sshd.common.util.security.SecurityUtils;
  */
 public final class EdDSAUtils {
 
-    private static final int ED25519_LENGTH = 32; // bytes
+    /**
+     * @see <a href="https://tools.ietf.org/html/rfc8410#section-3";>RFC8412 
section 3</a>
+     */
+    public static final String ED25519_OID = "1.3.101.112";
+
+    /**
+     * @see <a href="https://tools.ietf.org/html/rfc8410#section-3";>RFC8412 
section 3</a>
+     */
+    public static final String ED448_OID = "1.3.101.113";
+
+    public static final int ED25519_LENGTH = 32; // bytes
 
-    private static final int ED448_LENGTH = 57; // bytes
+    public static final int ED448_LENGTH = 57; // bytes
 
     // These are the constant prefixes of X.509 encodings of ed25519 and ed448 
keys. Appending the actual 32
     // or 57 key bytes yields valid encodings.
@@ -69,8 +80,8 @@ public final class EdDSAUtils {
             0x04, 0x3b, 0x04, 0x39 };
 
     // The first two numbers of the dotted notation are combined into one 
byte: (1 * 40 + 3) = 43 = 0x2b
-    private static final byte[] ED25519_OID = { 0x2b, 0x65, 0x70 }; // 
1.3.101.112
-    private static final byte[] ED448_OID = { 0x2b, 0x65, 0x71 }; // 
1.3.101.113
+    private static final byte[] ED25519_OID_BYTES = { 0x2b, 0x65, 0x70 }; // 
1.3.101.112
+    private static final byte[] ED448_OID_BYTES = { 0x2b, 0x65, 0x71 }; // 
1.3.101.113
 
     private EdDSAUtils() {
         throw new IllegalStateException("No instantiation");
@@ -199,9 +210,9 @@ public final class EdDSAUtils {
             int n;
             try (DERParser algorithmIdentifier = 
oneAsymmetricKey.readObject().createParser()) {
                 byte[] oid = algorithmIdentifier.readObject().getValue();
-                if (arrayEq(ED25519_OID, oid)) {
+                if (arrayEq(ED25519_OID_BYTES, oid)) {
                     n = ED25519_LENGTH;
-                } else if (arrayEq(ED448_OID, oid)) {
+                } else if (arrayEq(ED448_OID_BYTES, oid)) {
                     n = ED448_LENGTH;
                 } else {
                     throw new IllegalArgumentException("Private key is neither 
ed25519 nor ed448");
@@ -325,7 +336,10 @@ public final class EdDSAUtils {
      * @throws IllegalArgumentException if one of the keys is neither an 
ed25519 nor an ed448 key
      */
     public static boolean equals(PublicKey k1, PublicKey k2) throws 
IllegalArgumentException {
-        return arrayEq(getBytes(k1), getBytes(k2));
+        if (Objects.equals(k1, k2)) {
+            return true;
+        }
+        return k1 != null && k2 != null && arrayEq(getBytes(k1), getBytes(k2));
     }
 
     /**
@@ -337,6 +351,12 @@ public final class EdDSAUtils {
      * @throws IllegalArgumentException if one of the keys is neither an 
ed25519 nor an ed448 key
      */
     public static boolean equals(PrivateKey k1, PrivateKey k2) throws 
IllegalArgumentException {
+        if (Objects.equals(k1, k2)) {
+            return true;
+        }
+        if (k1 == null || k2 == null) {
+            return false;
+        }
         byte[] k1Data = null;
         byte[] k2Data = null;
         try {
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/GenericOpenSSHEd25519PrivateKeyEntryDecoder.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/OpenSSHEd25519PrivateKeyEntryDecoder.java
similarity index 92%
rename from 
sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/GenericOpenSSHEd25519PrivateKeyEntryDecoder.java
rename to 
sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/OpenSSHEd25519PrivateKeyEntryDecoder.java
index e1285fb55..aafd8a717 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/GenericOpenSSHEd25519PrivateKeyEntryDecoder.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/OpenSSHEd25519PrivateKeyEntryDecoder.java
@@ -45,16 +45,16 @@ import org.apache.sshd.common.util.security.SecurityUtils;
 /**
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  */
-public class GenericOpenSSHEd25519PrivateKeyEntryDecoder extends 
AbstractPrivateKeyEntryDecoder {
+public class OpenSSHEd25519PrivateKeyEntryDecoder extends 
AbstractPrivateKeyEntryDecoder {
+
+    public static final OpenSSHEd25519PrivateKeyEntryDecoder INSTANCE = new 
OpenSSHEd25519PrivateKeyEntryDecoder();
+
     private static final int PK_SIZE = 32;
     private static final int SK_SIZE = 32;
     private static final int KEYPAIR_SIZE = PK_SIZE + SK_SIZE;
 
-    protected final EdDSASupport edDSASupport;
-
-    public GenericOpenSSHEd25519PrivateKeyEntryDecoder(EdDSASupport 
edDSASupport) {
+    public OpenSSHEd25519PrivateKeyEntryDecoder() {
         super(Collections.singletonList(KeyPairProvider.SSH_ED25519));
-        this.edDSASupport = edDSASupport;
     }
 
     @Override
@@ -99,7 +99,8 @@ public class GenericOpenSSHEd25519PrivateKeyEntryDecoder 
extends AbstractPrivate
             PrivateKey privateKey = EdDSAUtils.getPrivateKey(sk);
 
             // we can now verify the generated pk matches the one we read
-            if 
(!Arrays.equals(EdDSAUtils.getBytes(recoverPublicKey(privateKey)), pk)) {
+            PublicKey recoveredPk = recoverPublicKey(privateKey);
+            if (recoveredPk != null && 
!Arrays.equals(EdDSAUtils.getBytes(recoveredPk), pk)) {
                 throw new InvalidKeyException("The provided pk does NOT match 
the computed pk for the given sk.");
             }
 
@@ -148,7 +149,7 @@ public class GenericOpenSSHEd25519PrivateKeyEntryDecoder 
extends AbstractPrivate
 
     @Override
     public PublicKey recoverPublicKey(PrivateKey prvKey) throws 
GeneralSecurityException {
-        return edDSASupport.recoverEDDSAPublicKey(prvKey);
+        return SecurityUtils.recoverEDDSAPublicKey(prvKey);
     }
 
     @Override
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/SignatureEd25519.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/SignatureEd25519.java
similarity index 96%
rename from 
sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/SignatureEd25519.java
rename to 
sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/SignatureEd25519.java
index 7823acc31..3e7e1eb1d 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/SignatureEd25519.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/SignatureEd25519.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.sshd.common.util.security.eddsa;
+package org.apache.sshd.common.util.security.eddsa.generic;
 
 import java.util.Map;
 
diff --git 
a/sshd-common/src/test/java/org/apache/sshd/common/util/security/eddsa/Ed25519VectorsTest.java
 
b/sshd-common/src/test/java/org/apache/sshd/common/util/security/eddsa/Ed25519VectorsTest.java
index a7deabcd0..29ad12af8 100644
--- 
a/sshd-common/src/test/java/org/apache/sshd/common/util/security/eddsa/Ed25519VectorsTest.java
+++ 
b/sshd-common/src/test/java/org/apache/sshd/common/util/security/eddsa/Ed25519VectorsTest.java
@@ -33,8 +33,8 @@ import org.apache.sshd.common.signature.Signature;
 import org.apache.sshd.common.util.buffer.BufferUtils;
 import org.apache.sshd.common.util.security.SecurityProviderRegistrar;
 import org.apache.sshd.common.util.security.SecurityUtils;
-import org.apache.sshd.common.util.security.eddsa.generic.EdDSASupport;
 import org.apache.sshd.common.util.security.eddsa.generic.EdDSAUtils;
+import org.apache.sshd.common.util.security.eddsa.generic.SignatureEd25519;
 import org.apache.sshd.util.test.JUnitTestSupport;
 import org.junit.jupiter.api.Assumptions;
 import org.junit.jupiter.api.BeforeAll;
@@ -61,7 +61,7 @@ class Ed25519VectorsTest extends JUnitTestSupport {
     private byte[] expSignature;
 
     void initEd25519VectorsTest(
-            String name, EdDSASupport support, String prvKey, String pubKey, 
String msg, String signature)
+            String name, String prvKey, String pubKey, String msg, String 
signature)
             throws GeneralSecurityException, IOException {
         prvBytes = BufferUtils.decodeHex(BufferUtils.EMPTY_HEX_SEPARATOR, 
prvKey);
         privateKey = EdDSAUtils.getPrivateKey(prvBytes.clone());
@@ -80,28 +80,27 @@ class Ed25519VectorsTest extends JUnitTestSupport {
         if (registrar == null) {
             throw new IllegalStateException("Neither net.i2p nor BC 
registered");
         }
-        EdDSASupport support = registrar.getEdDSASupport().orElseThrow(() -> 
new IllegalStateException("No EdDSA support"));
-        String supportClassName = support.getClass().getSimpleName();
+        String supportClassName = registrar.getClass().getSimpleName();
         parameters.add(new Object[] {
-                supportClassName + " TEST1 - empty message", support,
+                supportClassName + " TEST1 - empty message",
                 
"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
                 
"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", "",
                 "e5564300c360ac729086e2cc806e828a" + 
"84877f1eb8e5d974d873e06522490155" + "5fb8821590a33bacc61e39701cf9b46b"
                                                                                
         + "d25bf5f0595bbe24655141438e7a100b" });
         parameters.add(new Object[] {
-                supportClassName + " TEST2 - one byte", support,
+                supportClassName + " TEST2 - one byte",
                 
"4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb",
                 
"3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", "72",
                 "92a009a9f0d4cab8720e820b5f642540" + 
"a2b27b5416503f8fb3762223ebdb69da" + "085ac1e43e15996e458f3613d0f11d8c"
                                                                                
           + "387b2eaeb4302aeeb00d291612bb0c00" });
         parameters.add(new Object[] {
-                supportClassName + " TEST3 - 2 bytes", support,
+                supportClassName + " TEST3 - 2 bytes",
                 
"c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7",
                 
"fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", "af82",
                 "6291d657deec24024827e69c3abe01a3" + 
"0ce548a284743a445e3680d7db5ac3ac" + "18ff9b538d16f290ae67f760984dc659"
                                                                                
             + "4a7c15e9716ed28dc027beceea1ec40a" });
         parameters.add(new Object[] {
-                supportClassName + " TEST1024 - large message", support,
+                supportClassName + " TEST1024 - large message",
                 
"f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5",
                 
"278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e",
                 "08b8b2b733424243760fe426a4b54908" + 
"632110a66c2f6591eabd3345e3e4eb98" + "fa6e264bf09efe12ee50f8f54e9f77b1"
@@ -180,9 +179,8 @@ class Ed25519VectorsTest extends JUnitTestSupport {
     @MethodSource("parameters")
     @ParameterizedTest(name = "{0}")
     void publicKeyBytes(
-            String name, EdDSASupport support, String prvKey, String pubKey, 
String msg,
-            String signature) throws Exception {
-        initEd25519VectorsTest(name, support, prvKey, pubKey, msg, signature);
+            String name, String prvKey, String pubKey, String msg, String 
signature) throws Exception {
+        initEd25519VectorsTest(name, prvKey, pubKey, msg, signature);
         byte[] publicSeed = EdDSAUtils.getBytes(publicKey);
         assertArrayEquals(pubBytes, publicSeed, "Mismatched public seed 
value");
     }
@@ -190,9 +188,8 @@ class Ed25519VectorsTest extends JUnitTestSupport {
     @MethodSource("parameters")
     @ParameterizedTest(name = "{0}")
     void privateKeyBytes(
-            String name, EdDSASupport support, String prvKey, String pubKey, 
String msg,
-            String signature) throws Exception {
-        initEd25519VectorsTest(name, support, prvKey, pubKey, msg, signature);
+            String name, String prvKey, String pubKey, String msg, String 
signature) throws Exception {
+        initEd25519VectorsTest(name, prvKey, pubKey, msg, signature);
         byte[] privateSeed = EdDSAUtils.getBytes(privateKey);
         assertArrayEquals(prvBytes, privateSeed, "Mismatched private seed 
value");
     }
@@ -200,9 +197,8 @@ class Ed25519VectorsTest extends JUnitTestSupport {
     @MethodSource("parameters")
     @ParameterizedTest(name = "{0}")
     void signature(
-            String name, EdDSASupport support, String prvKey, String pubKey, 
String msg,
-            String signature) throws Exception {
-        initEd25519VectorsTest(name, support, prvKey, pubKey, msg, signature);
+            String name, String prvKey, String pubKey, String msg, String 
signature) throws Exception {
+        initEd25519VectorsTest(name, prvKey, pubKey, msg, signature);
         Signature signer = new SignatureEd25519();
         signer.initSigner(null, privateKey);
         signer.update(null, msgBytes.clone());
@@ -219,10 +215,8 @@ class Ed25519VectorsTest extends JUnitTestSupport {
     @MethodSource("parameters")
     @ParameterizedTest(name = "{0}")
     void partialBufferSignature(
-            String name, EdDSASupport support, String prvKey, String pubKey, 
String msg,
-            String signature)
-            throws Exception {
-        initEd25519VectorsTest(name, support, prvKey, pubKey, msg, signature);
+            String name, String prvKey, String pubKey, String msg, String 
signature) throws Exception {
+        initEd25519VectorsTest(name, prvKey, pubKey, msg, signature);
         byte[] extraData = 
getCurrentTestName().getBytes(StandardCharsets.UTF_8);
         byte[] dataBuf = new byte[msgBytes.length + extraData.length];
         int offset = extraData.length / 2;
@@ -246,10 +240,9 @@ class Ed25519VectorsTest extends JUnitTestSupport {
     @MethodSource("parameters")
     @ParameterizedTest(name = "{0}")
     void recoverEDDSAPublicKey(
-            String name, EdDSASupport support, String prvKey, String pubKey, 
String msg,
-            String signature) throws Exception {
-        initEd25519VectorsTest(name, support, prvKey, pubKey, msg, signature);
-        PublicKey recoveredKey = support.recoverEDDSAPublicKey(privateKey);
+            String name, String prvKey, String pubKey, String msg, String 
signature) throws Exception {
+        initEd25519VectorsTest(name, prvKey, pubKey, msg, signature);
+        PublicKey recoveredKey = 
SecurityUtils.recoverEDDSAPublicKey(privateKey);
         assertTrue(SecurityUtils.compareEDDSAPPublicKeys(publicKey, 
recoveredKey), "Recovered key is not equal");
         byte[] recoveredBytes = EdDSAUtils.getBytes(recoveredKey);
         assertArrayEquals(pubBytes, recoveredBytes, "Mismatched public seed 
value");
@@ -258,9 +251,8 @@ class Ed25519VectorsTest extends JUnitTestSupport {
     @MethodSource("parameters")
     @ParameterizedTest(name = "{0}")
     void createPublicKeySpec(
-            String name, EdDSASupport support, String prvKey, String pubKey, 
String msg,
-            String signature) throws Exception {
-        initEd25519VectorsTest(name, support, prvKey, pubKey, msg, signature);
+            String name, String prvKey, String pubKey, String msg, String 
signature) throws Exception {
+        initEd25519VectorsTest(name, prvKey, pubKey, msg, signature);
         KeySpec keySpec = EdDSAUtils.createKeySpec(publicKey);
         KeyFactory keyFactory = 
SecurityUtils.getKeyFactory(SecurityUtils.ED25519);
         PublicKey generatedKey = keyFactory.generatePublic(keySpec);
@@ -272,9 +264,8 @@ class Ed25519VectorsTest extends JUnitTestSupport {
     @MethodSource("parameters")
     @ParameterizedTest(name = "{0}")
     void createPrivateKeySpec(
-            String name, EdDSASupport support, String prvKey, String pubKey, 
String msg,
-            String signature) throws Exception {
-        initEd25519VectorsTest(name, support, prvKey, pubKey, msg, signature);
+            String name, String prvKey, String pubKey, String msg, String 
signature) throws Exception {
+        initEd25519VectorsTest(name, prvKey, pubKey, msg, signature);
         KeySpec keySpec = EdDSAUtils.createKeySpec(privateKey);
         KeyFactory keyFactory = 
SecurityUtils.getKeyFactory(SecurityUtils.ED25519);
         PrivateKey generatedKey = keyFactory.generatePrivate(keySpec);
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 fc2072918..27fc492dc 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
@@ -43,6 +43,7 @@ import org.apache.sshd.common.keyprovider.KeyTypeIndicator;
 import org.apache.sshd.common.session.SessionContext;
 import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.security.SecurityUtils;
+import 
org.apache.sshd.common.util.security.eddsa.generic.Ed25519PublicKeyDecoder;
 import org.apache.sshd.server.SshServer;
 import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.CoreTestSupportUtils;
@@ -94,7 +95,7 @@ class SignatureFactoriesTest extends BaseTestSupport 
implements KeyTypeIndicator
                     curve.isSupported() ? ECDSAPublicKeyEntryDecoder.INSTANCE 
: null);
         }
         addTests(list, KeyPairProvider.SSH_ED25519, BuiltinSignatures.ed25519, 
ED25519_SIZES,
-                SecurityUtils.isEDDSACurveSupported() ? 
SecurityUtils.getEDDSAPublicKeyEntryDecoder() : null);
+                SecurityUtils.isEDDSACurveSupported() ? 
Ed25519PublicKeyDecoder.INSTANCE : null);
         return Collections.unmodifiableList(list);
     }
 

Reply via email to