Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -78,6 +79,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;
Expand Down Expand Up @@ -476,6 +478,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);
Expand Down Expand Up @@ -1345,6 +1349,39 @@ private static CertStores.Builder certBuilder(boolean isServer, String cn, boole
.usePem(useInlinePem);
}

/**
* 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");
} 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
// 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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure why we get this branch? SSLContext.getInstance gets error if tlsv1.2 is not supported?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chia7712 yes. I change the 1.2 to 1.8 and take a snapshot for it:
image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

understand, it will certainly be an issue if tlsv1.2 is dropped. I'm confident Apache Kafka' lifespan will exceed that necessity

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree

// If we can't check cipher suites, assume DSA is not fully supported
return false;
}
}

@FunctionalInterface
private interface FailureAction {
FailureAction NO_OP = () -> { };
Expand Down