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 0598b834a78d3f800e8227548a0e001dfb883d49
Author: Thomas Wolf <[email protected]>
AuthorDate: Fri Sep 19 21:37:34 2025 +0200

    Also enable X25519 and X448 in SunECSecurityProviderRegistrar
    
    These algorithms are available since Java 11. If present, use them from
    SunEC even if Bouncy Castle is also present.
    
    Also enable it by default.
    
    Fix the two ed25519 PublicKeyEntryDecoders to not call
    KeyPairGenerator.initialize(int): the SunEC edDSA key pair generator
    throws an exception if called with value 256; it accepts 255 and 448.[1]
    
    [1] 
https://github.com/openjdk/jdk/blob/b03b6f54c5/src/java.base/share/classes/sun/security/ec/ed/EdDSAParameters.java#L275
---
 sshd-common/pom.xml                                |  9 ++-
 .../security/SunECSecurityProviderRegistrar.java   | 79 +++++++++++++++++-----
 .../eddsa/generic/Ed25519PublicKeyDecoder.java     |  6 ++
 .../OpenSSHEd25519PrivateKeyEntryDecoder.java      |  6 ++
 sshd-core/pom.xml                                  | 46 ++++++++-----
 sshd-test/pom.xml                                  | 57 +++++++++-------
 6 files changed, 146 insertions(+), 57 deletions(-)

diff --git a/sshd-common/pom.xml b/sshd-common/pom.xml
index 5d0fef547..b16433e1b 100644
--- a/sshd-common/pom.xml
+++ b/sshd-common/pom.xml
@@ -124,17 +124,21 @@
                         <configuration>
                             
<redirectTestOutputToFile>true</redirectTestOutputToFile>
                             
<reportsDirectory>${project.build.directory}/surefire-reports-common</reportsDirectory>
+                            <systemPropertyVariables>
+                                
<org.apache.sshd.security.provider.SunECWrapper.enabled>false</org.apache.sshd.security.provider.SunECWrapper.enabled>
+                            </systemPropertyVariables>
                         </configuration>
                     </execution>
                     <execution>
-                        <id>no-net-i2p</id>
+                        <id>bc</id>
                         <goals>
                             <goal>test</goal>
                         </goals>
                         <configuration>
                             
<redirectTestOutputToFile>true</redirectTestOutputToFile>
-                            
<reportsDirectory>${project.build.directory}/surefire-reports-no-net-i2p</reportsDirectory>
+                            
<reportsDirectory>${project.build.directory}/surefire-reports-bc</reportsDirectory>
                             <systemPropertyVariables>
+                                
<org.apache.sshd.security.provider.SunECWrapper.enabled>false</org.apache.sshd.security.provider.SunECWrapper.enabled>
                                 
<org.apache.sshd.security.provider.EdDSA.enabled>false</org.apache.sshd.security.provider.EdDSA.enabled>
                             </systemPropertyVariables>
                         </configuration>
@@ -200,4 +204,5 @@
             </plugin>
         </plugins>
     </build>
+
 </project>
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SunECSecurityProviderRegistrar.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SunECSecurityProviderRegistrar.java
index f0fea7c32..702c29db7 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SunECSecurityProviderRegistrar.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SunECSecurityProviderRegistrar.java
@@ -37,37 +37,84 @@ import org.apache.sshd.common.util.GenericUtils;
  * be set correctly. Mixing SunEC keys with Bouncy Castle signatures won't 
work.
  * </p>
  * <p>
- * This registrar is <em>disabled</em> by default. It can be enabled via a 
system property
- * {@code org.apache.sshd.security.provider.SunECWrapper.enabled=true}.
+ * This registrar is <em>enabled</em> by default. It can be disabled via a 
system property
+ * {@code org.apache.sshd.security.provider.SunECWrapper.enabled=false}.
  * </p>
  * <p>
- * The registrar can be configured as usual. By default it has only the 
"Ed25519" {@code KeyFactory},
- * {@code KeyPairGenerator}, and {@code Signature} enabled; everything else is 
disabled.
+ * The registrar can be configured as usual. By default are enabled:
+ * </p>
+ * <dl>
+ * <dt>"Ed25519"</dt>
+ * <dd>{@code KeyFactory}, {@code KeyPairGenerator}, and {@code Signature}, if 
"Ed25519" is supported by SunEC</dd>
+ * <dt>"X25519"</dt>
+ * <dd>{@code KeyAgreement}, {@code KeyFactory}, and {@code KeyPairGenerator}, 
if "X25519" is supported by SunEC</dd>
+ * <dt>"X448"</dt>
+ * <dd>{@code KeyAgreement}, {@code KeyFactory}, and {@code KeyPairGenerator}, 
if "X448" is supported by SunEC</dd>
+ * </dl>
+ * <p>
+ * Everything else is disabled.
  * </p>
  *
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  */
 public class SunECSecurityProviderRegistrar extends 
AbstractSecurityProviderRegistrar {
 
+    private static final String X25519 = "X25519";
+
+    private static final String X448 = "X448";
+
     private final Map<String, String> defaultProperties = new HashMap<>();
 
     public SunECSecurityProviderRegistrar() {
         super("SunECWrapper");
-        String baseName = getBasePropertyName();
-        defaultProperties.put(baseName + ".enabled", "false");
         if (isSupported()) {
-            boolean haveEd25519;
-            try {
-                KeyFactory factory = 
KeyFactory.getInstance(SecurityUtils.ED25519, getSecurityProvider());
-                haveEd25519 = factory != null;
-            } catch (NoSuchAlgorithmException e) {
-                haveEd25519 = false;
-            }
+            Provider provider = getSecurityProvider();
+
+            boolean haveEd25519 = have(SecurityUtils.ED25519, provider);
+            boolean haveX25519 = have("X25519", provider);
+            boolean haveX448 = have("X448", provider);
+
+            String keyAgreement = null;
+            String generator = null;
+            String factory = null;
+            String signature = null;
             if (haveEd25519) {
-                defaultProperties.put(baseName + ".KeyPairGenerator", 
"Ed25519");
-                defaultProperties.put(baseName + ".KeyFactory", "Ed25519");
-                defaultProperties.put(baseName + ".Signature", "Ed25519");
+                generator = SecurityUtils.ED25519;
+                factory = SecurityUtils.ED25519;
+                signature = SecurityUtils.ED25519;
+            }
+            if (haveX25519) {
+                keyAgreement = X25519;
+                generator = generator == null ? X25519 : (generator + ',' + 
X25519);
+                factory = factory == null ? X25519 : (factory + ',' + X25519);
+            }
+            if (haveX448) {
+                keyAgreement = keyAgreement == null ? X448 : (keyAgreement + 
',' + X448);
+                generator = generator == null ? X448 : (generator + ',' + 
X448);
+                factory = factory == null ? X448 : (factory + ',' + X448);
             }
+            String baseName = getBasePropertyName();
+            if (keyAgreement != null) {
+                defaultProperties.put(baseName + ".KeyAgreement", 
keyAgreement);
+            }
+            if (generator != null) {
+                defaultProperties.put(baseName + ".KeyPairGenerator", 
generator);
+            }
+            if (factory != null) {
+                defaultProperties.put(baseName + ".KeyFactory", factory);
+            }
+            if (signature != null) {
+                defaultProperties.put(baseName + ".Signature", signature);
+            }
+        }
+    }
+
+    private static boolean have(String algorithm, Provider provider) {
+        try {
+            KeyFactory factory = KeyFactory.getInstance(algorithm, provider);
+            return factory != null;
+        } catch (NoSuchAlgorithmException e) {
+            return false;
         }
     }
 
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/Ed25519PublicKeyDecoder.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/Ed25519PublicKeyDecoder.java
index 712defeac..e5f1941a8 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/Ed25519PublicKeyDecoder.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/Ed25519PublicKeyDecoder.java
@@ -23,6 +23,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.security.GeneralSecurityException;
 import java.security.KeyFactory;
+import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.security.PublicKey;
 import java.util.Collections;
@@ -55,6 +56,11 @@ public final class Ed25519PublicKeyDecoder extends 
AbstractPublicKeyEntryDecoder
         return SecurityUtils.getKeyPairGenerator(SecurityUtils.ED25519);
     }
 
+    @Override
+    public KeyPair generateKeyPair(int keySize) throws 
GeneralSecurityException {
+        return getKeyPairGenerator().generateKeyPair();
+    }
+
     @Override
     public String encodePublicKey(OutputStream s, PublicKey key) throws 
IOException {
         Objects.requireNonNull(key, "No public key provided");
diff --git 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/OpenSSHEd25519PrivateKeyEntryDecoder.java
 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/OpenSSHEd25519PrivateKeyEntryDecoder.java
index aafd8a717..3634ab053 100644
--- 
a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/OpenSSHEd25519PrivateKeyEntryDecoder.java
+++ 
b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/OpenSSHEd25519PrivateKeyEntryDecoder.java
@@ -24,6 +24,7 @@ import java.io.InputStream;
 import java.security.GeneralSecurityException;
 import java.security.InvalidKeyException;
 import java.security.KeyFactory;
+import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
@@ -157,6 +158,11 @@ public class OpenSSHEd25519PrivateKeyEntryDecoder extends 
AbstractPrivateKeyEntr
         return SecurityUtils.getKeyPairGenerator(SecurityUtils.ED25519);
     }
 
+    @Override
+    public KeyPair generateKeyPair(int keySize) throws 
GeneralSecurityException {
+        return getKeyPairGenerator().generateKeyPair();
+    }
+
     @Override
     public KeyFactory getKeyFactoryInstance() throws GeneralSecurityException {
         return SecurityUtils.getKeyFactory(SecurityUtils.ED25519);
diff --git a/sshd-core/pom.xml b/sshd-core/pom.xml
index c315235cf..3f3dfa97f 100644
--- a/sshd-core/pom.xml
+++ b/sshd-core/pom.xml
@@ -189,28 +189,42 @@
                         <configuration>
                             
<redirectTestOutputToFile>true</redirectTestOutputToFile>
                             
<reportsDirectory>${project.build.directory}/surefire-reports-nio2</reportsDirectory>
+                            <systemPropertyVariables>
+                                
<org.apache.sshd.security.provider.SunECWrapper.enabled>false</org.apache.sshd.security.provider.SunECWrapper.enabled>
+                            </systemPropertyVariables>
                         </configuration>
                     </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <configuration>
+                    <redirectTestOutputToFile>true</redirectTestOutputToFile>
+                    
<reportsDirectory>${project.build.directory}/surefire-reports-jce</reportsDirectory>
+                    <systemPropertyVariables>
+                        <!-- Enable using deprecated ssh-rsa signature keys 
with JSch 0.2.x -->
+                        
<jsch.server_host_key>ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,rsa-sha2-512,rsa-sha2-256,ssh-rsa</jsch.server_host_key>
+                        
<org.apache.sshd.security.provider.EdDSA.enabled>false</org.apache.sshd.security.provider.EdDSA.enabled>
+                        
<org.apache.sshd.security.provider.BC.enabled>false</org.apache.sshd.security.provider.BC.enabled>
+                    </systemPropertyVariables>
+                    <includes>
+                        <include>**/*Test.java</include>
+                    </includes>
+                    <excludes>
+                        <!-- These tests fail inexplicably without 
Bouncycastle -->
+                        <exclude>**/*LoadTest.java</exclude>
+                        <exclude>**/SinglePublicKeyAuthTest.java</exclude>
+                        <exclude>**/ClientTest.java</exclude>
+                    </excludes>
+                </configuration>
+                <executions>
                     <execution>
                         <id>jce</id>
                         <goals>
-                            <goal>test</goal>
+                            <goal>integration-test</goal>
+                            <goal>verify</goal>
                         </goals>
-                        <configuration>
-                            
<redirectTestOutputToFile>true</redirectTestOutputToFile>
-                            
<reportsDirectory>${project.build.directory}/surefire-reports-jce</reportsDirectory>
-                            <systemPropertyVariables>
-                                <!-- Enable using deprecated ssh-rsa signature 
keys with JSch 0.2.x -->
-                                
<jsch.server_host_key>ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,rsa-sha2-512,rsa-sha2-256,ssh-rsa</jsch.server_host_key>
-                                
<org.apache.sshd.security.provider.BC.enabled>false</org.apache.sshd.security.provider.BC.enabled>
-                            </systemPropertyVariables>
-                            <excludes>
-                                <!-- These tests fail inexplicably without 
Bouncycastle -->
-                                <exclude>**/*LoadTest.java</exclude>
-                                
<exclude>**/SinglePublicKeyAuthTest.java</exclude>
-                                <exclude>**/ClientTest.java</exclude>
-                            </excludes>
-                        </configuration>
                     </execution>
                 </executions>
             </plugin>
diff --git a/sshd-test/pom.xml b/sshd-test/pom.xml
index 24ae7e6fb..3ac83a5e1 100644
--- a/sshd-test/pom.xml
+++ b/sshd-test/pom.xml
@@ -132,33 +132,44 @@
                     </systemPropertyVariables>
                 </configuration>
             </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-failsafe-plugin</artifactId>
-                <configuration>
-                    <redirectTestOutputToFile>true</redirectTestOutputToFile>
-                    
<reportsDirectory>${project.build.directory}/surefire-reports-nio2</reportsDirectory>
-                    <systemPropertyVariables>
-                        
<org.apache.sshd.security.provider.SunECWrapper.enabled>true</org.apache.sshd.security.provider.SunECWrapper.enabled>
-                        
<org.apache.sshd.common.io.IoServiceFactoryFactory>org.apache.sshd.common.io.nio2.Nio2ServiceFactoryFactory</org.apache.sshd.common.io.IoServiceFactoryFactory>
-                    </systemPropertyVariables>
-                    <includes>
-                        <include>**/*Test.java</include>
-                    </includes>
-                </configuration>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>integration-test</goal>
-                            <goal>verify</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
         </plugins>
     </build>
 
     <profiles>
+        <profile>
+            <id>multirelease</id>
+            <activation>
+                <jdk>[11,)</jdk>
+            </activation>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-failsafe-plugin</artifactId>
+                        <configuration>
+                            
<redirectTestOutputToFile>true</redirectTestOutputToFile>
+                            
<reportsDirectory>${project.build.directory}/surefire-reports-mr</reportsDirectory>
+                            <systemPropertyVariables>
+                                
<org.apache.sshd.common.io.IoServiceFactoryFactory>org.apache.sshd.common.io.nio2.Nio2ServiceFactoryFactory</org.apache.sshd.common.io.IoServiceFactoryFactory>
+                            </systemPropertyVariables>
+                            <includes>
+                                <include>**/*Test.java</include>
+                            </includes>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <goals>
+                                    <goal>integration-test</goal>
+                                    <goal>verify</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
         <profile>
             <id>test-mina</id>
             <activation>

Reply via email to