From 9e408f715266cc2556193770c06808d9b7aade1f Mon Sep 17 00:00:00 2001 From: Jian Date: Sun, 23 Nov 2025 08:34:54 +0800 Subject: [PATCH 1/3] MINOR: Skip testDsaKeyPair when DSA algorithm is not supported Signed-off-by: Jian --- .../common/network/SslTransportLayerTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java b/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java index 9525ccfbc82be..cad802cbcabcf 100644 --- a/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java +++ b/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java @@ -78,6 +78,7 @@ import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; @@ -476,6 +477,8 @@ public void testClientAuthenticationRequestedNotProvided(Args args) throws Excep @ArgumentsSource(SslTransportLayerArgumentsForTLS2Provider.class) public void testDsaKeyPair(Args args) throws Exception { // DSA algorithms are not supported for TLSv1.3. + // Skip test if DSA is not supported by the JVM + assumeTrue(isDsaSupported(), "DSA algorithm is not supported by this JVM"); args.serverCertStores = certBuilder(true, "server", args.useInlinePem).keyAlgorithm("DSA").build(); args.clientCertStores = certBuilder(false, "client", args.useInlinePem).keyAlgorithm("DSA").build(); args.sslServerConfigs = args.getTrustingConfig(args.serverCertStores, args.clientCertStores); @@ -1345,6 +1348,19 @@ private static CertStores.Builder certBuilder(boolean isServer, String cn, boole .usePem(useInlinePem); } + /** + * Check if DSA algorithm is supported by the JVM. + * @return true if DSA KeyPairGenerator is available, false otherwise + */ + private static boolean isDsaSupported() { + try { + java.security.KeyPairGenerator.getInstance("DSA"); + return true; + } catch (java.security.NoSuchAlgorithmException e) { + return false; + } + } + @FunctionalInterface private interface FailureAction { FailureAction NO_OP = () -> { }; From bc64aa6fe7afe04eb4fb223ee5647bdf184f882c Mon Sep 17 00:00:00 2001 From: Jian Date: Sun, 23 Nov 2025 10:54:07 +0800 Subject: [PATCH 2/3] check if DSA-compatible cipher suites existed Signed-off-by: Jian --- .../common/network/SslTransportLayerTest.java | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java b/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java index cad802cbcabcf..8672e1c8581c5 100644 --- a/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java +++ b/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java @@ -1349,16 +1349,45 @@ private static CertStores.Builder certBuilder(boolean isServer, String cn, boole } /** - * Check if DSA algorithm is supported by the JVM. - * @return true if DSA KeyPairGenerator is available, false otherwise + * Check if DSA algorithm is supported by the JVM and if there are compatible cipher suites + * available for TLSv1.2. This is important because even if DSA KeyPairGenerator is available, + * the SSL handshake may fail if no DSA-compatible cipher suites are available. + * @return true if DSA KeyPairGenerator is available and DSA-compatible cipher suites exist, false otherwise */ private static boolean isDsaSupported() { + // First check if DSA KeyPairGenerator is available try { java.security.KeyPairGenerator.getInstance("DSA"); - return true; } catch (java.security.NoSuchAlgorithmException e) { return false; } + + // Check if there are DSA-compatible cipher suites available for TLSv1.2 + // DSA algorithms are not supported for TLSv1.3, so we only check TLSv1.2 + try { + SSLContext context = SSLContext.getInstance("TLSv1.2"); + context.init(null, null, null); + SSLParameters params = context.getDefaultSSLParameters(); + String[] cipherSuites = params.getCipherSuites(); + + // Check if any cipher suite supports DSA/DSS + // DSA-related cipher suites typically contain "DSS" or "DSA" in their names + for (String cipherSuite : cipherSuites) { + // Common DSA cipher suite patterns: + // - TLS_DHE_DSS_* (Diffie-Hellman Ephemeral with DSS) + // - TLS_DH_DSS_* (Diffie-Hellman with DSS) + // - SSL_DHE_DSS_* (legacy SSL with DSS) + // - SSL_DH_DSS_* (legacy SSL with DSS) + if (cipherSuite.contains("_DSS_") || cipherSuite.contains("_DSA_")) { + return true; + } + } + // No DSA-compatible cipher suites found + return false; + } catch (Exception e) { + // If we can't check cipher suites, assume DSA is not fully supported + return false; + } } @FunctionalInterface From 96108edee4098cb22f9c21b78141465031ea9fec Mon Sep 17 00:00:00 2001 From: Jian Date: Sun, 23 Nov 2025 11:18:34 +0800 Subject: [PATCH 3/3] remove the 'DSA' match Signed-off-by: Jian --- .../common/network/SslTransportLayerTest.java | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java b/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java index 8672e1c8581c5..e4b4c174a679e 100644 --- a/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java +++ b/clients/src/test/java/org/apache/kafka/common/network/SslTransportLayerTest.java @@ -55,6 +55,7 @@ import java.nio.channels.SocketChannel; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -1370,20 +1371,11 @@ private static boolean isDsaSupported() { SSLParameters params = context.getDefaultSSLParameters(); String[] cipherSuites = params.getCipherSuites(); - // Check if any cipher suite supports DSA/DSS - // DSA-related cipher suites typically contain "DSS" or "DSA" in their names - for (String cipherSuite : cipherSuites) { - // Common DSA cipher suite patterns: - // - TLS_DHE_DSS_* (Diffie-Hellman Ephemeral with DSS) - // - TLS_DH_DSS_* (Diffie-Hellman with DSS) - // - SSL_DHE_DSS_* (legacy SSL with DSS) - // - SSL_DH_DSS_* (legacy SSL with DSS) - if (cipherSuite.contains("_DSS_") || cipherSuite.contains("_DSA_")) { - return true; - } - } - // No DSA-compatible cipher suites found - return false; + // Check if any cipher suite supports DSA + // In TLS standards and JVM implementations, DSA signature cipher suites use "_DSS_" naming + // Common patterns: TLS_DHE_DSS_*, TLS_DH_DSS_*, SSL_DHE_DSS_*, SSL_DH_DSS_* + return Arrays.stream(cipherSuites) + .anyMatch(suite -> suite.contains("_DSS_")); } catch (Exception e) { // If we can't check cipher suites, assume DSA is not fully supported return false;