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 1152a651a04391c9bb83ecf4e07a339b6ad81169
Merge: c975a971e 8f0c296a2
Author: Thomas Wolf <[email protected]>
AuthorDate: Wed Oct 8 23:41:02 2025 +0200

    Merge branch 'master' into 3.0.0

 docs/server-setup.md                               |   2 +-
 docs/standards.md                                  |   2 +-
 pom.xml                                            |   4 +-
 .../org/apache/sshd/common/cipher/ECCurves.java    | 124 ++++++++-------------
 .../util/security/SecurityEntityFactory.java       |  20 ++++
 .../sshd/common/util/security/SecurityUtils.java   |   8 ++
 .../common/util/security/SecurityUtilsTest.java    |  16 +++
 7 files changed, 92 insertions(+), 84 deletions(-)

diff --cc pom.xml
index 729168748,d15fb01a0..b8d3567e8
--- a/pom.xml
+++ b/pom.xml
@@@ -110,10 -115,10 +110,10 @@@
          <grpc.version>1.75.0</grpc.version> <!-- Used only in tests -->
  
          <maven.archiver.version>3.6.4</maven.archiver.version>
-         <plexus.archiver.version>4.10.1</plexus.archiver.version>
+         <plexus.archiver.version>4.10.2</plexus.archiver.version>
          <!-- See https://pmd.github.io/ for available latest version -->
          <pmd.version>7.17.0</pmd.version>
 -
 +        <japicmp.version>0.23.1</japicmp.version>
          <sshd.tests.timeout.factor>1.0</sshd.tests.timeout.factor>
          <sshd.tests.rerun.count>2</sshd.tests.rerun.count>
  
diff --cc sshd-common/src/main/java/org/apache/sshd/common/cipher/ECCurves.java
index 6db662ed7,5967b079d..a53bd36fd
--- a/sshd-common/src/main/java/org/apache/sshd/common/cipher/ECCurves.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/cipher/ECCurves.java
@@@ -162,13 -100,14 +100,15 @@@ public enum ECCurves implements KeyType
      private final String keyType;
      private final String oidString;
      private final List<Integer> oidValue;
-     private final ECParameterSpec params;
-     private final int keySize;
 -    private ECParameterSpec params;
 -    private volatile int keySize = -1;
      private final int numOctets;
      private final DigestFactory digestFactory;
  
-     ECCurves(String name, int[] oid, ECParameterSpec params, int numOctets, 
DigestFactory digestFactory) {
++    private ECParameterSpec params;
++    private volatile int keySize = -1;
++
+     ECCurves(String name, String secName, int[] oid, int numOctets, 
DigestFactory digestFactory) {
          this.name = ValidateUtils.checkNotNullAndNotEmpty(name, "No curve 
name");
+         this.secName = ValidateUtils.checkNotNullAndNotEmpty(secName, "No SEC 
curve name");
          this.oidString = NumberUtils.join('.', 
ValidateUtils.checkNotNullAndNotEmpty(oid, "No OID"));
          this.oidValue = Collections.unmodifiableList(NumberUtils.asList(oid));
          this.keyType = Constants.ECDSA_SHA2_PREFIX + name;
diff --cc 
sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityEntityFactory.java
index 569abb345,badd54166..00a17f1aa
--- 
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,227 -19,175 +19,247 @@@
  
  package org.apache.sshd.common.util.security;
  
 -import java.lang.reflect.Method;
++import java.security.AlgorithmParameters;
  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:[email protected]";>Apache MINA SSHD 
Project</a>
 + * @author <a href="mailto:[email protected]";>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);
 -            } else if (defaultProvider.isNamedProviderUsed()) {
 -                return toNamedProviderFactory(entityType, 
defaultProvider.getProviderName());
 -            } else {
 -                return toProviderInstanceFactory(entityType, 
defaultProvider.getSecurityProvider());
 -            }
 -        } else if (registrar.isNamedProviderUsed()) {
 -            return toNamedProviderFactory(entityType, 
registrar.getProviderName());
 -        } else {
 -            return toProviderInstanceFactory(entityType, 
registrar.getSecurityProvider());
 -        }
 +public interface SecurityEntityFactory {
 +
++    default AlgorithmParameters createAlgorithmParameters(String algorithm) 
throws GeneralSecurityException {
++        throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not 
supported (default)");
++    }
++
 +    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)");
 +    }
 +
 +    default Mac createMac(String algorithm) throws GeneralSecurityException {
 +        throw new NoSuchAlgorithmException("Algorithm '" + algorithm + "' not 
supported (default)");
 +    }
 +
 +    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)");
 +    }
 +
 +    default KEM createKEM(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;
 -            }
 -        };
 +    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 AlgorithmParameters createAlgorithmParameters(String 
algorithm) throws GeneralSecurityException {
++            return AlgorithmParameters.getInstance(algorithm, name);
++        }
++
 +        @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> 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;
 -            }
 -        };
 +    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 AlgorithmParameters createAlgorithmParameters(String 
algorithm) throws GeneralSecurityException {
++            return AlgorithmParameters.getInstance(algorithm, provider);
++        }
++
 +        @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);
 +        }
      }
  
 -    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;
 -            }
 -        };
 +    enum Default implements SecurityEntityFactory {
 +
 +        INSTANCE;
 +
++        @Override
++        public AlgorithmParameters createAlgorithmParameters(String 
algorithm) throws GeneralSecurityException {
++            return AlgorithmParameters.getInstance(algorithm);
++        }
++
 +        @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);
 +        }
 +
 +        @Override
 +        public KEM createKEM(String algorithm) throws 
GeneralSecurityException {
 +            return JceKEM.INSTANCE.get(algorithm);
 +        }
      }
  }
diff --cc 
sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java
index a2bbe89c2,525b66d01..2686b1ad5
--- 
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
@@@ -22,8 -22,10 +22,9 @@@ import java.io.IOException
  import java.io.InputStream;
  import java.math.BigInteger;
  import java.nio.file.Path;
+ import java.security.AlgorithmParameters;
  import java.security.GeneralSecurityException;
  import java.security.InvalidKeyException;
 -import java.security.Key;
  import java.security.KeyFactory;
  import java.security.KeyPair;
  import java.security.KeyPairGenerator;
@@@ -697,25 -833,31 +698,32 @@@ 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 AlgorithmParameters getAlgorithmParameters(String 
algorithm) throws GeneralSecurityException {
 -        SecurityEntityFactory<AlgorithmParameters> factory
++        SecurityEntityFactory factory
+                 = resolveSecurityEntityFactory(AlgorithmParameters.class, 
algorithm,
+                         r -> 
r.isSecurityEntitySupported(AlgorithmParameters.class, algorithm));
 -        return factory.getInstance(algorithm);
++        return factory.createAlgorithmParameters(algorithm);
+     }
+ 
      public static KeyFactory getKeyFactory(String algorithm) throws 
GeneralSecurityException {
 -        SecurityEntityFactory<KeyFactory> factory
 -                = resolveSecurityEntityFactory(KeyFactory.class, algorithm, r 
-> r.isKeyFactorySupported(algorithm));
 -        return factory.getInstance(algorithm);
 +        SecurityEntityFactory factory = 
resolveSecurityEntityFactory(KeyFactory.class, algorithm,
 +                r -> r.isKeyFactorySupported(algorithm));
 +        return factory.createKeyFactory(algorithm);
      }
  
      public static Cipher getCipher(String transformation) throws 
GeneralSecurityException {
diff --cc 
sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
index e7b3454ce,a67168a61..60f818cbc
--- 
a/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
+++ 
b/sshd-common/src/test/java/org/apache/sshd/common/util/security/SecurityUtilsTest.java
@@@ -23,6 -23,6 +23,7 @@@ import java.io.IOException
  import java.nio.file.Path;
  import java.security.GeneralSecurityException;
  import java.security.KeyPair;
++import java.security.KeyPairGenerator;
  import java.security.PrivateKey;
  import java.security.PublicKey;
  import java.security.interfaces.DSAPrivateKey;
@@@ -32,6 -32,6 +33,7 @@@ import java.security.interfaces.ECPubli
  import java.security.interfaces.RSAPrivateKey;
  import java.security.interfaces.RSAPublicKey;
  import java.util.ArrayList;
++import java.util.Base64;
  import java.util.Collection;
  import java.util.List;
  
@@@ -45,7 -45,8 +47,8 @@@ import org.apache.sshd.common.keyprovid
  import 
org.apache.sshd.common.keyprovider.ClassLoadableResourceKeyPairProvider;
  import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
  import org.apache.sshd.common.util.GenericUtils;
++import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
  import org.apache.sshd.common.util.io.resource.PathResource;
 -import org.junit.jupiter.api.Assumptions;
  import org.junit.jupiter.api.MethodOrderer.MethodName;
  import org.junit.jupiter.api.Tag;
  import org.junit.jupiter.api.Test;
@@@ -118,6 -125,6 +121,19 @@@ class SecurityUtilsTest extends Securit
          }
      }
  
++    @Test
++    void x509EncodingEc() throws Exception {
++        KeyPairGenerator generator = 
SecurityUtils.getKeyPairGenerator(KeyUtils.EC_ALGORITHM);
++        generator.initialize(521);
++        KeyPair kp = generator.generateKeyPair();
++        String enc = 
Base64.getEncoder().encodeToString(kp.getPublic().getEncoded());
++        ByteArrayBuffer buf = new ByteArrayBuffer();
++        buf.putPublicKey(kp.getPublic());
++        PublicKey readBack = buf.getPublicKey();
++        assertTrue(KeyUtils.compareKeys(kp.getPublic(), readBack), "Public 
keys should be equal");
++        assertEquals(enc, 
Base64.getEncoder().encodeToString(readBack.getEncoded()), 
readBack.getClass().getCanonicalName());
++    }
++
      private KeyPair testLoadECPrivateKey(String name) throws Exception {
          return testLoadPrivateKey(name, ECPublicKey.class, 
ECPrivateKey.class);
      }

Reply via email to