You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by tw...@apache.org on 2025/09/21 21:09:52 UTC
(mina-sshd) branch dev_3.0 updated (526432a2f -> 31d9bdc8a)
This is an automated email from the ASF dual-hosted git repository.
twolf pushed a change to branch dev_3.0
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git
from 526432a2f Merge branch 'master' into 3.0.0
new 04fe313f2 SecurityProviderRegistrar: binary search needs a sorted array
new 31d9bdc8a Remove reflective calls to security getInstance(algorithm) methods
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../util/security/SecurityEntityFactory.java | 351 ++++++++++++---------
.../util/security/SecurityProviderChoice.java | 6 +-
.../util/security/SecurityProviderRegistrar.java | 8 +-
.../sshd/common/util/security/SecurityUtils.java | 81 ++---
.../BouncyCastleSecurityProviderRegistrar.java | 11 +
.../eddsa/EdDSASecurityProviderRegistrar.java | 73 ++---
6 files changed, 297 insertions(+), 233 deletions(-)
(mina-sshd) 01/02: SecurityProviderRegistrar: binary search needs a sorted array
Posted by tw...@apache.org.
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 04fe313f2b31b32e4c68b65d74702f6c301d9bb5
Author: Thomas Wolf <tw...@apache.org>
AuthorDate: Sun Sep 21 22:00:05 2025 +0200
SecurityProviderRegistrar: binary search needs a sorted array
Somehow I suspect nobody is actually using these configuration
possibilities, otherwise someone surely would have tripped over
this.
---
.../sshd/common/util/security/SecurityProviderRegistrar.java | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
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 68c9756a4..4df4f8022 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
@@ -274,8 +274,12 @@ public interface SecurityProviderRegistrar extends SecurityProviderChoice, Optio
return false;
}
- if ((values.length == 1) && isAllOptionsValue(values[0])) {
- return true;
+ if (values.length == 1) {
+ if (isAllOptionsValue(values[0])) {
+ return true;
+ }
+ } else {
+ Arrays.sort(values, String.CASE_INSENSITIVE_ORDER);
}
String effectiveName = getEffectiveSecurityEntityName(entityType, name);
(mina-sshd) 02/02: Remove reflective calls to security getInstance(algorithm) methods
Posted by tw...@apache.org.
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 31d9bdc8aa25803721e35e467bde76b646b9152c
Author: Thomas Wolf <tw...@apache.org>
AuthorDate: Sun Sep 21 21:58:10 2025 +0200
Remove reflective calls to security getInstance(algorithm) methods
Simplify this setup a little. We always know what kind of security
entity we want to create, so there is no need for some convoluted
reflective way to create factories.
---
.../util/security/SecurityEntityFactory.java | 351 ++++++++++++---------
.../util/security/SecurityProviderChoice.java | 6 +-
.../sshd/common/util/security/SecurityUtils.java | 81 ++---
.../BouncyCastleSecurityProviderRegistrar.java | 11 +
.../eddsa/EdDSASecurityProviderRegistrar.java | 73 ++---
5 files changed, 291 insertions(+), 231 deletions(-)
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityEntityFactory.java b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityEntityFactory.java
index d8648cb83..eab3f0cec 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityEntityFactory.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityEntityFactory.java
@@ -19,169 +19,218 @@
package org.apache.sshd.common.util.security;
-import java.lang.reflect.Method;
import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.KeyPairGenerator;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.security.Provider;
-import java.util.Objects;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.cert.CertificateFactory;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyAgreement;
+import javax.crypto.Mac;
-import org.apache.sshd.common.util.ExceptionUtils;
import org.apache.sshd.common.util.ValidateUtils;
/**
- * @param <T> Type of security entity being generated by this factory
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
-public interface SecurityEntityFactory<T> {
- Class<T> getEntityType();
-
- T getInstance(String algorithm) throws GeneralSecurityException;
-
- /**
- * Uses reflection in order to wrap the {@code getInstance} method(s) as a security entity factory.
- *
- * @param <F> Type of entity being generated by the factor
- * @param entityType The entity type class
- * @param registrar The {@code SecurityProviderRegistrar} to use - if {@code null} then default
- * provider is used (if specified).
- * @param defaultProvider Default provider choice to use if no registrar provided. If
- * {@code null}/empty then JCE default is used
- * @return The {@link SecurityEntityFactory} for the entity
- * @throws ReflectiveOperationException If failed to create the factory
- * @see #toDefaultFactory(Class)
- * @see #toNamedProviderFactory(Class, String)
- * @see #toProviderInstanceFactory(Class, Provider)
- * @see SecurityProviderChoice#isNamedProviderUsed()
- * @see SecurityProviderChoice#getSecurityProvider()
- */
- static <F> SecurityEntityFactory<F> toFactory(
- Class<F> entityType, SecurityProviderChoice registrar, SecurityProviderChoice defaultProvider)
- throws ReflectiveOperationException {
- if (registrar == null) {
- if ((defaultProvider == null) || (defaultProvider == SecurityProviderChoice.EMPTY)) {
- return toDefaultFactory(entityType);
- }
- return defaultProvider.getFactory(entityType);
- }
- return registrar.getFactory(entityType);
+public interface SecurityEntityFactory {
+
+ default CertificateFactory createCertificateFactory(String algorithm) throws GeneralSecurityException {
+ throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
+ }
+
+ default Cipher createCipher(String algorithm) throws GeneralSecurityException {
+ throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
+ }
+
+ default KeyAgreement createKeyAgreement(String algorithm) throws GeneralSecurityException {
+ throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
+ }
+
+ default KeyFactory createKeyFactory(String algorithm) throws GeneralSecurityException {
+ throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
+ }
+
+ default KeyPairGenerator createKeyPairGenerator(String algorithm) throws GeneralSecurityException {
+ throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
}
- static <F> SecurityEntityFactory<F> toDefaultFactory(Class<F> entityType)
- throws ReflectiveOperationException {
- Method m = entityType.getDeclaredMethod("getInstance", String.class);
- return new SecurityEntityFactory<F>() {
- private final String s = SecurityEntityFactory.class.getSimpleName()
- + "[" + entityType.getSimpleName() + "]"
- + "[default]";
-
- @Override
- public Class<F> getEntityType() {
- return entityType;
- }
-
- @Override
- public F getInstance(String algorithm) throws GeneralSecurityException {
- try {
- Object value = m.invoke(null, algorithm);
- return entityType.cast(value);
- } catch (ReflectiveOperationException t) {
- Throwable e = ExceptionUtils.peelException(t);
- if (e instanceof GeneralSecurityException) {
- throw (GeneralSecurityException) e;
- } else if (e instanceof RuntimeException) {
- throw (RuntimeException) e;
- } else if (e instanceof Error) {
- throw (Error) e;
- } else {
- throw new GeneralSecurityException(e);
- }
- }
- }
-
- @Override
- public String toString() {
- return s;
- }
- };
+ default Mac createMac(String algorithm) throws GeneralSecurityException {
+ throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
}
- static <F> SecurityEntityFactory<F> toNamedProviderFactory(Class<F> entityType, String name)
- throws ReflectiveOperationException {
- ValidateUtils.checkNotNullAndNotEmpty(name, "No provider name specified");
- Method m = entityType.getDeclaredMethod("getInstance", String.class, String.class);
- return new SecurityEntityFactory<F>() {
- private final String s = SecurityEntityFactory.class.getSimpleName()
- + "[" + entityType.getSimpleName() + "]"
- + "[" + name + "]";
-
- @Override
- public Class<F> getEntityType() {
- return entityType;
- }
-
- @Override
- public F getInstance(String algorithm) throws GeneralSecurityException {
- try {
- Object value = m.invoke(null, algorithm, name);
- return entityType.cast(value);
- } catch (ReflectiveOperationException t) {
- Throwable e = ExceptionUtils.peelException(t);
- if (e instanceof GeneralSecurityException) {
- throw (GeneralSecurityException) e;
- } else if (e instanceof RuntimeException) {
- throw (RuntimeException) e;
- } else if (e instanceof Error) {
- throw (Error) e;
- } else {
- throw new GeneralSecurityException(e);
- }
- }
- }
-
- @Override
- public String toString() {
- return s;
- }
- };
+ default MessageDigest createMessageDigest(String algorithm) throws GeneralSecurityException {
+ throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
+ }
+
+ default Signature createSignature(String algorithm) throws GeneralSecurityException {
+ throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
+ }
+
+ default SecureRandom createSecureRandom(String algorithm) throws GeneralSecurityException {
+ throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not supported (default)");
+ }
+
+ class Named implements SecurityEntityFactory {
+
+ private final String name;
+
+ public Named(String name) {
+ this.name = ValidateUtils.checkNotNullAndNotEmpty(name, "Security provider name must not be empty");
+ }
+
+ @Override
+ public CertificateFactory createCertificateFactory(String algorithm) throws GeneralSecurityException {
+ return CertificateFactory.getInstance(algorithm, name);
+ }
+
+ @Override
+ public Cipher createCipher(String algorithm) throws GeneralSecurityException {
+ return Cipher.getInstance(algorithm, name);
+ }
+
+ @Override
+ public KeyAgreement createKeyAgreement(String algorithm) throws GeneralSecurityException {
+ return KeyAgreement.getInstance(algorithm, name);
+ }
+
+ @Override
+ public KeyFactory createKeyFactory(String algorithm) throws GeneralSecurityException {
+ return KeyFactory.getInstance(algorithm, name);
+ }
+
+ @Override
+ public KeyPairGenerator createKeyPairGenerator(String algorithm) throws GeneralSecurityException {
+ return KeyPairGenerator.getInstance(algorithm, name);
+ }
+
+ @Override
+ public Mac createMac(String algorithm) throws GeneralSecurityException {
+ return Mac.getInstance(algorithm, name);
+ }
+
+ @Override
+ public MessageDigest createMessageDigest(String algorithm) throws GeneralSecurityException {
+ return MessageDigest.getInstance(algorithm, name);
+ }
+
+ @Override
+ public Signature createSignature(String algorithm) throws GeneralSecurityException {
+ return Signature.getInstance(algorithm, name);
+ }
+
+ @Override
+ public SecureRandom createSecureRandom(String algorithm) throws GeneralSecurityException {
+ return SecureRandom.getInstance(algorithm, name);
+ }
}
- static <F> SecurityEntityFactory<F> toProviderInstanceFactory(Class<F> entityType, Provider provider)
- throws ReflectiveOperationException {
- Objects.requireNonNull(provider, "No provider instance");
- Method m = entityType.getDeclaredMethod("getInstance", String.class, Provider.class);
- return new SecurityEntityFactory<F>() {
- private final String s = SecurityEntityFactory.class.getSimpleName()
- + "[" + entityType.getSimpleName() + "]"
- + "[" + Provider.class.getSimpleName() + "]"
- + "[" + provider.getName() + "]";
-
- @Override
- public Class<F> getEntityType() {
- return entityType;
- }
-
- @Override
- public F getInstance(String algorithm) throws GeneralSecurityException {
- try {
- Object value = m.invoke(null, algorithm, provider);
- return entityType.cast(value);
- } catch (ReflectiveOperationException t) {
- Throwable e = ExceptionUtils.peelException(t);
- if (e instanceof GeneralSecurityException) {
- throw (GeneralSecurityException) e;
- } else if (e instanceof RuntimeException) {
- throw (RuntimeException) e;
- } else if (e instanceof Error) {
- throw (Error) e;
- } else {
- throw new GeneralSecurityException(e);
- }
- }
- }
-
- @Override
- public String toString() {
- return s;
- }
- };
+ class ByProvider implements SecurityEntityFactory {
+
+ private final Provider provider;
+
+ public ByProvider(Provider name) {
+ this.provider = ValidateUtils.checkNotNull(name, "Security provider must not be null");
+ }
+
+ @Override
+ public CertificateFactory createCertificateFactory(String algorithm) throws GeneralSecurityException {
+ return CertificateFactory.getInstance(algorithm, provider);
+ }
+
+ @Override
+ public Cipher createCipher(String algorithm) throws GeneralSecurityException {
+ return Cipher.getInstance(algorithm, provider);
+ }
+
+ @Override
+ public KeyAgreement createKeyAgreement(String algorithm) throws GeneralSecurityException {
+ return KeyAgreement.getInstance(algorithm, provider);
+ }
+
+ @Override
+ public KeyFactory createKeyFactory(String algorithm) throws GeneralSecurityException {
+ return KeyFactory.getInstance(algorithm, provider);
+ }
+
+ @Override
+ public KeyPairGenerator createKeyPairGenerator(String algorithm) throws GeneralSecurityException {
+ return KeyPairGenerator.getInstance(algorithm, provider);
+ }
+
+ @Override
+ public Mac createMac(String algorithm) throws GeneralSecurityException {
+ return Mac.getInstance(algorithm, provider);
+ }
+
+ @Override
+ public MessageDigest createMessageDigest(String algorithm) throws GeneralSecurityException {
+ return MessageDigest.getInstance(algorithm, provider);
+ }
+
+ @Override
+ public Signature createSignature(String algorithm) throws GeneralSecurityException {
+ return Signature.getInstance(algorithm, provider);
+ }
+
+ @Override
+ public SecureRandom createSecureRandom(String algorithm) throws GeneralSecurityException {
+ return SecureRandom.getInstance(algorithm, provider);
+ }
+ }
+
+ enum Default implements SecurityEntityFactory {
+
+ INSTANCE;
+
+ @Override
+ public CertificateFactory createCertificateFactory(String algorithm) throws GeneralSecurityException {
+ return CertificateFactory.getInstance(algorithm);
+ }
+
+ @Override
+ public Cipher createCipher(String algorithm) throws GeneralSecurityException {
+ return Cipher.getInstance(algorithm);
+ }
+
+ @Override
+ public KeyAgreement createKeyAgreement(String algorithm) throws GeneralSecurityException {
+ return KeyAgreement.getInstance(algorithm);
+ }
+
+ @Override
+ public KeyFactory createKeyFactory(String algorithm) throws GeneralSecurityException {
+ return KeyFactory.getInstance(algorithm);
+ }
+
+ @Override
+ public KeyPairGenerator createKeyPairGenerator(String algorithm) throws GeneralSecurityException {
+ return KeyPairGenerator.getInstance(algorithm);
+ }
+
+ @Override
+ public Mac createMac(String algorithm) throws GeneralSecurityException {
+ return Mac.getInstance(algorithm);
+ }
+
+ @Override
+ public MessageDigest createMessageDigest(String algorithm) throws GeneralSecurityException {
+ return MessageDigest.getInstance(algorithm);
+ }
+
+ @Override
+ public Signature createSignature(String algorithm) throws GeneralSecurityException {
+ return Signature.getInstance(algorithm);
+ }
+
+ @Override
+ public SecureRandom createSecureRandom(String algorithm) throws GeneralSecurityException {
+ return SecureRandom.getInstance(algorithm);
+ }
}
}
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityProviderChoice.java b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityProviderChoice.java
index 1da7e6017..82b820a39 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityProviderChoice.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityProviderChoice.java
@@ -71,11 +71,11 @@ public interface SecurityProviderChoice extends NamedResource {
return getName();
}
- default <F> SecurityEntityFactory<F> getFactory(Class<F> entityType) throws ReflectiveOperationException {
+ default SecurityEntityFactory getFactory() {
if (isNamedProviderUsed()) {
- return SecurityEntityFactory.toNamedProviderFactory(entityType, getProviderName());
+ return new SecurityEntityFactory.Named(getProviderName());
}
- return SecurityEntityFactory.toProviderInstanceFactory(entityType, getSecurityProvider());
+ return new SecurityEntityFactory.ByProvider(getSecurityProvider());
}
/**
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 512c09066..dcb93c20c 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
@@ -169,7 +169,10 @@ public final class SecurityUtils {
// If an entry already exists for the named provider, then it overrides its SecurityProviderRegistrar#isEnabled()
private static final Set<String> APRIORI_DISABLED_PROVIDERS = new TreeSet<>();
private static final AtomicBoolean REGISTRATION_STATE_HOLDER = new AtomicBoolean(false);
- private static final Map<Class<?>, Map<String, SecurityEntityFactory<?>>> SECURITY_ENTITY_FACTORIES = new HashMap<>();
+ /*
+ * This map keys security entities by algorithm names to SecurityEntityProviders.
+ */
+ private static final Map<Class<?>, Map<String, SecurityEntityFactory>> SECURITY_ENTITY_FACTORIES = new HashMap<>();
private static final AtomicReference<SecurityProviderChoice> DEFAULT_PROVIDER_HOLDER = new AtomicReference<>();
@@ -667,27 +670,25 @@ public final class SecurityUtils {
//////////////////////////// Security entities factories /////////////////////////////
- @SuppressWarnings("unchecked")
- public static <T> SecurityEntityFactory<T> resolveSecurityEntityFactory(
- Class<T> entityType, String algorithm, Predicate<? super SecurityProviderRegistrar> entitySelector) {
- Map<String, SecurityEntityFactory<?>> factoriesMap;
+ public static SecurityEntityFactory resolveSecurityEntityFactory(
+ Class<?> entityType, String algorithm,
+ Predicate<? super SecurityProviderRegistrar> entitySelector) {
+ Map<String, SecurityEntityFactory> factoriesMap;
synchronized (SECURITY_ENTITY_FACTORIES) {
factoriesMap = SECURITY_ENTITY_FACTORIES.computeIfAbsent(
entityType, k -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER));
}
- String effectiveName = SecurityProviderRegistrar.getEffectiveSecurityEntityName(entityType, algorithm);
- SecurityEntityFactory<?> factoryEntry;
+ SecurityEntityFactory provider;
synchronized (factoriesMap) {
- factoryEntry = factoriesMap.computeIfAbsent(
- effectiveName, k -> createSecurityEntityFactory(entityType, entitySelector));
+ provider = factoriesMap.computeIfAbsent(algorithm, k -> createSecurityEntityFactory(entitySelector));
}
- return (SecurityEntityFactory<T>) factoryEntry;
+ return provider;
}
- public static <T> SecurityEntityFactory<T> createSecurityEntityFactory(
- Class<T> entityType, Predicate<? super SecurityProviderRegistrar> entitySelector) {
+ public static SecurityEntityFactory createSecurityEntityFactory(
+ Predicate<? super SecurityProviderRegistrar> entitySelector) {
register();
SecurityProviderRegistrar registrar;
@@ -696,65 +697,67 @@ public final class SecurityUtils {
entitySelector, REGISTERED_PROVIDERS.values());
}
- try {
- return SecurityEntityFactory.toFactory(entityType, registrar, getDefaultProviderChoice());
- } catch (ReflectiveOperationException t) {
- Throwable e = ExceptionUtils.peelException(t);
- if (e instanceof RuntimeException) {
- throw (RuntimeException) e;
- } else if (e instanceof Error) {
- throw (Error) e;
- } else {
- throw new IllegalArgumentException(e);
+ return getSecurityEntityProvider(registrar, getDefaultProviderChoice());
+ }
+
+ public static SecurityEntityFactory getSecurityEntityProvider(
+ SecurityProviderRegistrar registrar,
+ SecurityProviderChoice defaultProvider) {
+ if (registrar == null) {
+ if ((defaultProvider == null) || (defaultProvider == SecurityProviderChoice.EMPTY)) {
+ return SecurityEntityFactory.Default.INSTANCE;
}
+ return defaultProvider.getFactory();
}
+ return registrar.getFactory();
}
public static KeyFactory getKeyFactory(String algorithm) throws GeneralSecurityException {
- SecurityEntityFactory<KeyFactory> factory = resolveSecurityEntityFactory(KeyFactory.class, algorithm,
+ SecurityEntityFactory factory = resolveSecurityEntityFactory(KeyFactory.class, algorithm,
r -> r.isKeyFactorySupported(algorithm));
- return factory.getInstance(algorithm);
+ return factory.createKeyFactory(algorithm);
}
public static Cipher getCipher(String transformation) throws GeneralSecurityException {
- SecurityEntityFactory<Cipher> factory
- = resolveSecurityEntityFactory(Cipher.class, transformation, r -> r.isCipherSupported(transformation));
- return factory.getInstance(transformation);
+ String algorithm = SecurityProviderRegistrar.getEffectiveSecurityEntityName(Cipher.class, transformation);
+ SecurityEntityFactory factory = resolveSecurityEntityFactory(Cipher.class, algorithm,
+ r -> r.isCipherSupported(algorithm));
+ return factory.createCipher(transformation);
}
public static MessageDigest getMessageDigest(String algorithm) throws GeneralSecurityException {
- SecurityEntityFactory<MessageDigest> factory
+ SecurityEntityFactory factory
= resolveSecurityEntityFactory(MessageDigest.class, algorithm, r -> r.isMessageDigestSupported(algorithm));
- return factory.getInstance(algorithm);
+ return factory.createMessageDigest(algorithm);
}
public static KeyPairGenerator getKeyPairGenerator(String algorithm) throws GeneralSecurityException {
- SecurityEntityFactory<KeyPairGenerator> factory = resolveSecurityEntityFactory(KeyPairGenerator.class, algorithm,
+ SecurityEntityFactory factory = resolveSecurityEntityFactory(KeyPairGenerator.class, algorithm,
r -> r.isKeyPairGeneratorSupported(algorithm));
- return factory.getInstance(algorithm);
+ return factory.createKeyPairGenerator(algorithm);
}
public static KeyAgreement getKeyAgreement(String algorithm) throws GeneralSecurityException {
- SecurityEntityFactory<KeyAgreement> factory
+ SecurityEntityFactory factory
= resolveSecurityEntityFactory(KeyAgreement.class, algorithm, r -> r.isKeyAgreementSupported(algorithm));
- return factory.getInstance(algorithm);
+ return factory.createKeyAgreement(algorithm);
}
public static Mac getMac(String algorithm) throws GeneralSecurityException {
- SecurityEntityFactory<Mac> factory
+ SecurityEntityFactory factory
= resolveSecurityEntityFactory(Mac.class, algorithm, r -> r.isMacSupported(algorithm));
- return factory.getInstance(algorithm);
+ return factory.createMac(algorithm);
}
public static Signature getSignature(String algorithm) throws GeneralSecurityException {
- SecurityEntityFactory<Signature> factory
+ SecurityEntityFactory factory
= resolveSecurityEntityFactory(Signature.class, algorithm, r -> r.isSignatureSupported(algorithm));
- return factory.getInstance(algorithm);
+ return factory.createSignature(algorithm);
}
public static CertificateFactory getCertificateFactory(String type) throws GeneralSecurityException {
- SecurityEntityFactory<CertificateFactory> factory
+ SecurityEntityFactory factory
= resolveSecurityEntityFactory(CertificateFactory.class, type, r -> r.isCertificateFactorySupported(type));
- return factory.getInstance(type);
+ return factory.createCertificateFactory(type);
}
}
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 f5d186044..a6a1bb8d0 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
@@ -50,6 +50,8 @@ public class BouncyCastleSecurityProviderRegistrar extends AbstractSecurityProvi
private String providerClass;
private String providerName;
+ private boolean useName = true;
+
public BouncyCastleSecurityProviderRegistrar() {
super(SecurityUtils.BOUNCY_CASTLE);
}
@@ -59,6 +61,11 @@ public class BouncyCastleSecurityProviderRegistrar extends AbstractSecurityProvi
return providerName;
}
+ @Override
+ public boolean isNamedProviderUsed() {
+ return useName;
+ }
+
@Override
public Provider getSecurityProvider() {
try {
@@ -142,19 +149,23 @@ public class BouncyCastleSecurityProviderRegistrar extends AbstractSecurityProvi
if (fipsInstalled && haveFips) {
providerClass = FIPS_PROVIDER_CLASS;
providerName = BCFIPS_PROVIDER_NAME;
+ useName = true;
supported = Boolean.TRUE;
} else if (bcInstalled && haveBc) {
providerClass = PROVIDER_CLASS;
providerName = BC_PROVIDER_NAME;
+ useName = true;
supported = Boolean.TRUE;
} else if (haveFips) {
providerClass = FIPS_PROVIDER_CLASS;
providerName = BCFIPS_PROVIDER_NAME;
+ useName = false;
supported = Boolean.TRUE;
} else if (haveBc) {
providerClass = PROVIDER_CLASS;
providerName = BC_PROVIDER_NAME;
supported = Boolean.TRUE;
+ useName = false;
} else {
supported = Boolean.FALSE;
}
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 dd9a5f5c0..3c2e1de3d 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
@@ -24,6 +24,7 @@ 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.concurrent.atomic.AtomicReference;
@@ -42,6 +43,8 @@ public class EdDSASecurityProviderRegistrar extends AbstractSecurityProviderRegi
// Do not define a static registrar instance to minimize class loading issues
private final AtomicReference<Boolean> supportHolder = new AtomicReference<>(null);
+ private boolean useName = true;
+
public EdDSASecurityProviderRegistrar() {
super(SecurityUtils.EDDSA);
}
@@ -51,6 +54,11 @@ public class EdDSASecurityProviderRegistrar extends AbstractSecurityProviderRegi
return !SecurityUtils.isFipsMode() && super.isEnabled();
}
+ @Override
+ public boolean isNamedProviderUsed() {
+ return useName;
+ }
+
@Override
public Provider getSecurityProvider() {
try {
@@ -93,6 +101,10 @@ public class EdDSASecurityProviderRegistrar extends AbstractSecurityProviderRegi
}
supported = Boolean.valueOf(EdDSAAccessor.INSTANCE.isSupported());
+ if (supported.booleanValue()) {
+ Provider provider = Security.getProvider(getProviderName());
+ useName = provider != null;
+ }
supportHolder.set(supported);
}
@@ -110,33 +122,8 @@ public class EdDSASecurityProviderRegistrar extends AbstractSecurityProviderRegi
}
@Override
- public <F> SecurityEntityFactory<F> getFactory(Class<F> entityType) throws ReflectiveOperationException {
- // Return factories that map the algorithm names to the non-standard ones used by net.i2p.
- // That way the rest of our code can work with the standard names.
- if (KeyPairGenerator.class.isAssignableFrom(entityType) || KeyFactory.class.isAssignableFrom(entityType)) {
- return new DelegatingSecurityEntityFactory<F>(super.getFactory(entityType)) {
-
- @Override
- protected String effectiveAlgorithm(String originalAlgorithm) {
- if (SecurityUtils.ED25519.equalsIgnoreCase(originalAlgorithm)) {
- return SecurityUtils.EDDSA;
- }
- return originalAlgorithm;
- }
- };
- } else if (Signature.class.isAssignableFrom(entityType)) {
- return new DelegatingSecurityEntityFactory<F>(super.getFactory(entityType)) {
-
- @Override
- protected String effectiveAlgorithm(String originalAlgorithm) {
- if (SecurityUtils.ED25519.equalsIgnoreCase(originalAlgorithm)) {
- return "NONEwithEdDSA";
- }
- return originalAlgorithm;
- }
- };
- }
- return super.getFactory(entityType);
+ public SecurityEntityFactory getFactory() {
+ return new DelegatingSecurityEntityProvider(super.getFactory());
}
@Override
@@ -148,29 +135,39 @@ public class EdDSASecurityProviderRegistrar extends AbstractSecurityProviderRegi
return super.getPublicKey(key);
}
- private abstract static class DelegatingSecurityEntityFactory<F> implements SecurityEntityFactory<F> {
+ private static class DelegatingSecurityEntityProvider implements SecurityEntityFactory {
- private SecurityEntityFactory<F> delegate;
+ private SecurityEntityFactory delegate;
- DelegatingSecurityEntityFactory(SecurityEntityFactory<F> delegate) {
+ DelegatingSecurityEntityProvider(SecurityEntityFactory delegate) {
this.delegate = delegate;
}
@Override
- public Class<F> getEntityType() {
- return delegate.getEntityType();
+ public KeyFactory createKeyFactory(String algorithm) throws GeneralSecurityException {
+ String effective = algorithm;
+ if (SecurityUtils.ED25519.equalsIgnoreCase(effective)) {
+ effective = SecurityUtils.EDDSA;
+ }
+ return delegate.createKeyFactory(effective);
}
@Override
- public F getInstance(String algorithm) throws GeneralSecurityException {
- return delegate.getInstance(effectiveAlgorithm(algorithm));
+ public KeyPairGenerator createKeyPairGenerator(String algorithm) throws GeneralSecurityException {
+ String effective = algorithm;
+ if (SecurityUtils.ED25519.equalsIgnoreCase(effective)) {
+ effective = SecurityUtils.EDDSA;
+ }
+ return delegate.createKeyPairGenerator(effective);
}
- protected abstract String effectiveAlgorithm(String originalAlgorithm);
-
@Override
- public String toString() {
- return delegate.toString();
+ public Signature createSignature(String algorithm) throws GeneralSecurityException {
+ String effective = algorithm;
+ if (SecurityUtils.ED25519.equalsIgnoreCase(effective)) {
+ effective = "NONEwithEdDSA";
+ }
+ return delegate.createSignature(effective);
}
}
}