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 f9863a121ec1d74f5a2f738fbf2bd7f7d8b2a268 Author: Thomas Wolf <[email protected]> AuthorDate: Thu Sep 18 21:54:01 2025 +0200 Force SunEC for ed25519 public key recovery on Java15+ The hack feeding the private key bytes into KeyPairGenerator works only with SunEC. It may not work with other security providers. If SunEC should not be available, ed25519 public key recovery will not be supported. This should have an effect at most on reading PEM files that do not contain the public key. (Which they should, though, according to RFC 5915: "Though the ASN.1 indicates publicKey is OPTIONAL, implementations that conform to this document SHOULD always include the publicKey field.") [1] https://datatracker.ietf.org/doc/html/rfc5915#section-3 --- .../util/security/eddsa/jce/JcePublicKeyFactory.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/sshd-common/src/main/java15/org/apache/sshd/common/util/security/eddsa/jce/JcePublicKeyFactory.java b/sshd-common/src/main/java15/org/apache/sshd/common/util/security/eddsa/jce/JcePublicKeyFactory.java index a91c1479b..214a2d122 100644 --- a/sshd-common/src/main/java15/org/apache/sshd/common/util/security/eddsa/jce/JcePublicKeyFactory.java +++ b/sshd-common/src/main/java15/org/apache/sshd/common/util/security/eddsa/jce/JcePublicKeyFactory.java @@ -18,9 +18,8 @@ */ package org.apache.sshd.common.util.security.eddsa.jce; -import java.security.InvalidAlgorithmParameterException; +import java.security.GeneralSecurityException; import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; @@ -40,7 +39,8 @@ public class JcePublicKeyFactory implements PublicKeyFactory { @Override public PublicKey getPublicKey(PrivateKey key) { - if (SecurityUtils.EDDSA.equalsIgnoreCase(key.getAlgorithm()) && (key instanceof EdECKey)) { + if (SecurityUtils.EDDSA.equalsIgnoreCase(key.getAlgorithm()) && (key instanceof EdECKey) + && (key.getClass().getCanonicalName().startsWith("sun."))) { NamedParameterSpec params = ((EdECKey) key).getParams(); return recoverEd25519PublicKey(key, params); } @@ -55,16 +55,17 @@ public class JcePublicKeyFactory implements PublicKeyFactory { // // This relies on the library using the returned "random" value as-is for the private key. Theoretically a // library would be free to process these random bytes in any way it wants before setting it as private key. - // Since any such post-processing of the random value runs the risk of introducing weaknesses through - // inadvertently loosing some randomness properties of the originally cryptographically secure random data, it - // is unlikely that an EdDSA implementation would do so, and in any case the JDK implementation doesn't. + // Luckily the OpenJDK implementation of SunEC doesn't do so. + // + // Other providers do that, though. For instance IBM's OpenJCEPlus even ignores the passed SecureRandom + // completely and generates keys and random data via native code in some unknown way. // // All this is just a hack to work around sun.security.ec.ed.EdDSAOperations.computePublic() not being // accessible. // // Note that NamedParameterSpec was introduced in Java 11, and the ED25519 constant in Java 15. try { - KeyPairGenerator gen = KeyPairGenerator.getInstance(params.getName()); + KeyPairGenerator gen = KeyPairGenerator.getInstance(params.getName(), "SunEC"); gen.initialize(params, new SecureRandom() { private static final long serialVersionUID = 1L; @@ -79,7 +80,7 @@ public class JcePublicKeyFactory implements PublicKeyFactory { } }); return gen.generateKeyPair().getPublic(); - } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) { + } catch (GeneralSecurityException e) { return null; } finally { Arrays.fill(rawPrivateKey, (byte) 0);
