diff --git a/src/java.base/share/classes/javax/net/ssl/KeyManagerFactory.java b/src/java.base/share/classes/javax/net/ssl/KeyManagerFactory.java index 652a20c837705..6c38e9577daf1 100644 --- a/src/java.base/share/classes/javax/net/ssl/KeyManagerFactory.java +++ b/src/java.base/share/classes/javax/net/ssl/KeyManagerFactory.java @@ -64,7 +64,7 @@ public class KeyManagerFactory { public static final String getDefaultAlgorithm() { String type = Security.getProperty("ssl.KeyManagerFactory.algorithm"); if (type == null) { - type = "SunX509"; + type = "PKIX"; } return type; } diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index b115d47983848..826e3b4a21d1d 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -320,7 +320,7 @@ security.overridePropertiesFile=true # Determines the default key and trust manager factory algorithms for # the javax.net.ssl package. # -ssl.KeyManagerFactory.algorithm=SunX509 +ssl.KeyManagerFactory.algorithm=PKIX ssl.TrustManagerFactory.algorithm=PKIX # diff --git a/test/jdk/javax/rmi/ssl/SSLSocketParametersTest.java b/test/jdk/javax/rmi/ssl/SSLSocketParametersTest.java index 6da3289458751..3aa7a98c39403 100644 --- a/test/jdk/javax/rmi/ssl/SSLSocketParametersTest.java +++ b/test/jdk/javax/rmi/ssl/SSLSocketParametersTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,8 @@ /* * @test * @bug 5016500 - * @library /test/lib/ + * @library /javax/net/ssl/templates + * /test/lib/ * @summary Test SslRmi[Client|Server]SocketFactory SSL socket parameters. * @run main/othervm SSLSocketParametersTest 1 * @run main/othervm SSLSocketParametersTest 2 @@ -36,8 +37,6 @@ */ import jdk.test.lib.Asserts; -import java.io.IOException; -import java.io.File; import java.io.Serializable; import java.lang.ref.Reference; import java.rmi.ConnectIOException; @@ -49,13 +48,17 @@ import javax.rmi.ssl.SslRMIClientSocketFactory; import javax.rmi.ssl.SslRMIServerSocketFactory; -public class SSLSocketParametersTest implements Serializable { +public class SSLSocketParametersTest extends SSLContextTemplate { + + public SSLSocketParametersTest() throws Exception { + SSLContext.setDefault(createServerSSLContext()); + } public interface Hello extends Remote { String sayHello() throws RemoteException; } - public class HelloImpl implements Hello { + public static class HelloImpl implements Hello { public String sayHello() { return "Hello World!"; } @@ -134,23 +137,7 @@ public void runTest(int testNumber) throws Exception { } public static void main(String[] args) throws Exception { - // Set keystore properties (server-side) - // - final String keystore = System.getProperty("test.src") + - File.separator + "keystore"; - System.out.println("KeyStore = " + keystore); - System.setProperty("javax.net.ssl.keyStore", keystore); - System.setProperty("javax.net.ssl.keyStorePassword", "password"); - - // Set truststore properties (client-side) - // - final String truststore = System.getProperty("test.src") + - File.separator + "truststore"; - System.out.println("TrustStore = " + truststore); - System.setProperty("javax.net.ssl.trustStore", truststore); - System.setProperty("javax.net.ssl.trustStorePassword", "trustword"); - SSLSocketParametersTest test = new SSLSocketParametersTest(); test.runTest(Integer.parseInt(args[0])); } -} \ No newline at end of file +} diff --git a/test/jdk/javax/rmi/ssl/keystore b/test/jdk/javax/rmi/ssl/keystore deleted file mode 100644 index 05f535645827b..0000000000000 Binary files a/test/jdk/javax/rmi/ssl/keystore and /dev/null differ diff --git a/test/jdk/javax/rmi/ssl/truststore b/test/jdk/javax/rmi/ssl/truststore deleted file mode 100644 index 2f5ba3433dc61..0000000000000 Binary files a/test/jdk/javax/rmi/ssl/truststore and /dev/null differ diff --git a/test/jdk/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java b/test/jdk/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java index 15224e22e6eea..5803da2510a6d 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java +++ b/test/jdk/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,31 +31,58 @@ * @bug 4328195 * @summary Need to include the alternate subject DN for certs, * https should check for this + * @modules java.base/sun.security.x509 + * java.base/sun.security.util * @library /javax/net/ssl/templates - * @run main/othervm ServerIdentityTest dnsstore localhost - * @run main/othervm ServerIdentityTest ipstore 127.0.0.1 + * /test/lib + * @run main/othervm ServerIdentityTest dns localhost + * @run main/othervm ServerIdentityTest ip 127.0.0.1 * * @author Yingxian Wang */ -import java.io.InputStream; +import static jdk.test.lib.Asserts.fail; + import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStream; import java.io.OutputStreamWriter; +import java.math.BigInteger; import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.Proxy; import java.net.URL; import java.net.UnknownHostException; - +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Date; +import java.util.List; import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManagerFactory; +import jdk.test.lib.security.CertificateBuilder; +import sun.security.x509.AuthorityKeyIdentifierExtension; +import sun.security.x509.GeneralName; +import sun.security.x509.GeneralNames; +import sun.security.x509.KeyIdentifier; +import sun.security.x509.SerialNumber; +import sun.security.x509.X500Name; public final class ServerIdentityTest extends SSLSocketTemplate { - private static String keystore; private static String hostname; - private static SSLContext context; + private static SSLContext serverContext; /* * Run the test case. @@ -64,7 +91,7 @@ public static void main(String[] args) throws Exception { // Get the customized arguments. initialize(args); - (new ServerIdentityTest()).run(); + new ServerIdentityTest().run(); } ServerIdentityTest() throws UnknownHostException { @@ -95,7 +122,7 @@ protected void runClientApplication(int serverPort) throws Exception { HttpURLConnection urlc = null; InputStream is = null; try { - urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY); + urlc = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY); is = urlc.getInputStream(); } finally { if (is != null) { @@ -109,31 +136,127 @@ protected void runClientApplication(int serverPort) throws Exception { @Override protected SSLContext createServerSSLContext() throws Exception { - return context; - } - - @Override - protected SSLContext createClientSSLContext() throws Exception { - return context; + return serverContext; } private static void initialize(String[] args) throws Exception { - keystore = args[0]; + String mode = args[0]; hostname = args[1]; - String password = "changeit"; - String keyFilename = - System.getProperty("test.src", ".") + "/" + keystore; - String trustFilename = - System.getProperty("test.src", ".") + "/" + keystore; + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + KeyPair caKeys = kpg.generateKeyPair(); + KeyPair serverKeys = kpg.generateKeyPair(); + KeyPair clientKeys = kpg.generateKeyPair(); + + CertificateBuilder serverCertificateBuilder = customCertificateBuilder( + "CN=server, O=Some-Org, L=Some-City, ST=Some-State, C=US", + serverKeys.getPublic(), caKeys.getPublic()) + .addBasicConstraintsExt(false, false, -1); - System.setProperty("javax.net.ssl.keyStore", keyFilename); - System.setProperty("javax.net.ssl.keyStorePassword", password); - System.setProperty("javax.net.ssl.trustStore", trustFilename); - System.setProperty("javax.net.ssl.trustStorePassword", password); + if (mode.equalsIgnoreCase("dns")) { + serverCertificateBuilder.addSubjectAltNameDNSExt(List.of(hostname)); + } else if (mode.equalsIgnoreCase("ip")) { + serverCertificateBuilder.addSubjectAltNameIPExt(List.of(hostname)); + } else { + fail("Unknown mode: " + mode); + } + + X509Certificate trustedCert = createTrustedCert(caKeys); + + X509Certificate serverCert = serverCertificateBuilder.build( + trustedCert, caKeys.getPrivate(), "SHA256WithRSA"); + + X509Certificate clientCert = customCertificateBuilder( + "CN=localhost, OU=SSL-Client, O=Some-Org, L=Some-City, ST=Some-State, C=US", + clientKeys.getPublic(), caKeys.getPublic()) + .addBasicConstraintsExt(false, false, -1) + .build(trustedCert, caKeys.getPrivate(), "SHA256WithRSA"); + + serverContext = getSSLContext( + trustedCert, serverCert, serverKeys.getPrivate()); + + SSLContext clientContext = getSSLContext( + trustedCert, clientCert, clientKeys.getPrivate()); - context = SSLContext.getDefault(); HttpsURLConnection.setDefaultSSLSocketFactory( - context.getSocketFactory()); + clientContext.getSocketFactory()); } + + private static SSLContext getSSLContext( + X509Certificate trustedCertificate, X509Certificate keyCertificate, + PrivateKey privateKey) + throws Exception { + + // create a key store + KeyStore ks = KeyStore.getInstance("PKCS12"); + ks.load(null, null); + + // import the trusted cert + ks.setCertificateEntry("TLS Signer", trustedCertificate); + + // generate certificate chain + Certificate[] chain = new Certificate[2]; + chain[0] = keyCertificate; + chain[1] = trustedCertificate; + + // import the key entry. + final char[] passphrase = "passphrase".toCharArray(); + ks.setKeyEntry("Whatever", privateKey, passphrase, chain); + + // Using PKIX TrustManager + TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); + tmf.init(ks); + + // Using PKIX KeyManager + KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX"); + + // create SSL context + SSLContext ctx = SSLContext.getInstance("TLS"); + kmf.init(ks, passphrase); + ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + return ctx; + } + + private static X509Certificate createTrustedCert(KeyPair caKeys) + throws Exception { + SecureRandom random = new SecureRandom(); + + KeyIdentifier kid = new KeyIdentifier(caKeys.getPublic()); + GeneralNames gns = new GeneralNames(); + GeneralName name = new GeneralName(new X500Name( + "O=Some-Org, L=Some-City, ST=Some-State, C=US")); + gns.add(name); + BigInteger serialNumber = BigInteger.valueOf( + random.nextLong(1000000) + 1); + return customCertificateBuilder( + "O=Some-Org, L=Some-City, ST=Some-State, C=US", + caKeys.getPublic(), caKeys.getPublic()) + .setSerialNumber(serialNumber) + .addExtension(new AuthorityKeyIdentifierExtension(kid, gns, + new SerialNumber(serialNumber))) + .addBasicConstraintsExt(true, true, -1) + .build(null, caKeys.getPrivate(), "SHA256WithRSA"); + } + + private static CertificateBuilder customCertificateBuilder( + String subjectName, PublicKey publicKey, PublicKey caKey) + throws CertificateException, IOException { + SecureRandom random = new SecureRandom(); + + CertificateBuilder builder = new CertificateBuilder() + .setSubjectName(subjectName) + .setPublicKey(publicKey) + .setNotAfter( + Date.from(Instant.now().minus(1, ChronoUnit.HOURS))) + .setNotAfter(Date.from(Instant.now().plus(1, ChronoUnit.HOURS))) + .setSerialNumber( + BigInteger.valueOf(random.nextLong(1000000) + 1)) + .addSubjectKeyIdExt(publicKey) + .addAuthorityKeyIdExt(caKey); + builder.addKeyUsageExt( + new boolean[]{true, true, true, true, true, true}); + + return builder; + } + } diff --git a/test/jdk/sun/net/www/protocol/https/HttpsClient/dnsstore b/test/jdk/sun/net/www/protocol/https/HttpsClient/dnsstore deleted file mode 100644 index 5f4fc81c9b7ce..0000000000000 Binary files a/test/jdk/sun/net/www/protocol/https/HttpsClient/dnsstore and /dev/null differ diff --git a/test/jdk/sun/net/www/protocol/https/HttpsClient/ipstore b/test/jdk/sun/net/www/protocol/https/HttpsClient/ipstore deleted file mode 100644 index 04a9508e0a1c4..0000000000000 Binary files a/test/jdk/sun/net/www/protocol/https/HttpsClient/ipstore and /dev/null differ diff --git a/test/jdk/sun/security/tools/keytool/PrintSSL.java b/test/jdk/sun/security/tools/keytool/PrintSSL.java index 7cdc0a4577104..0a29b83159cc3 100644 --- a/test/jdk/sun/security/tools/keytool/PrintSSL.java +++ b/test/jdk/sun/security/tools/keytool/PrintSSL.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ import java.net.ServerSocket; import java.nio.file.Files; import java.nio.file.Paths; +import java.security.Security; import java.util.concurrent.CountDownLatch; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLSocket; @@ -48,6 +49,11 @@ public class PrintSSL { public static void main(String[] args) throws Throwable { + // Using "SunX509" KeyManager which doesn't check peer supported + // signature algorithms, so we can make keytool print certificate + // with weak MD5withRSA signature algorithm. + Security.setProperty("ssl.KeyManagerFactory.algorithm", "SunX509"); + Files.deleteIfExists(Paths.get("keystore")); // make sure that "-printcert" works with weak algorithms diff --git a/test/lib/jdk/test/lib/security/CertificateBuilder.java b/test/lib/jdk/test/lib/security/CertificateBuilder.java index 60358c9a4eabf..c86fe1049200c 100644 --- a/test/lib/jdk/test/lib/security/CertificateBuilder.java +++ b/test/lib/jdk/test/lib/security/CertificateBuilder.java @@ -43,6 +43,7 @@ import sun.security.x509.AlgorithmId; import sun.security.x509.AuthorityInfoAccessExtension; import sun.security.x509.AuthorityKeyIdentifierExtension; +import sun.security.x509.IPAddressName; import sun.security.x509.SubjectKeyIdentifierExtension; import sun.security.x509.BasicConstraintsExtension; import sun.security.x509.CertificateSerialNumber; @@ -233,6 +234,26 @@ public CertificateBuilder addSubjectAltNameDNSExt(List dnsNames) return this; } + /** + * Helper method to add IPAddress types for the SAN extension + * + * @param IPAddresses A {@code List} of names to add as IPAddress + * types + * @throws IOException if an encoding error occurs. + */ + public CertificateBuilder addSubjectAltNameIPExt(List IPAddresses) + throws IOException { + if (!IPAddresses.isEmpty()) { + GeneralNames gNames = new GeneralNames(); + for (String name : IPAddresses) { + gNames.add(new GeneralName(new IPAddressName(name))); + } + addExtension(new SubjectAlternativeNameExtension(false, + gNames)); + } + return this; + } + /** * Helper method to add one or more OCSP URIs to the Authority Info Access * certificate extension. Location strings can be in two forms: