11/*
2- * Copyright (c) 2001, 2019 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2001, 2025 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
3131 * @bug 4328195
3232 * @summary Need to include the alternate subject DN for certs,
3333 * https should check for this
34+ * @modules java.base/sun.security.x509
35+ * java.base/sun.security.util
3436 * @library /javax/net/ssl/templates
35- * @run main/othervm ServerIdentityTest dnsstore localhost
36- * @run main/othervm ServerIdentityTest ipstore 127.0.0.1
37+ * /test/lib
38+ * @run main/othervm ServerIdentityTest dns localhost
39+ * @run main/othervm ServerIdentityTest ip 127.0.0.1
3740 *
3841 * @author Yingxian Wang
3942 */
4043
41- import java .io .InputStream ;
44+ import static jdk .test .lib .Asserts .fail ;
45+
4246import java .io .BufferedWriter ;
47+ import java .io .IOException ;
48+ import java .io .InputStream ;
4349import java .io .OutputStreamWriter ;
50+ import java .math .BigInteger ;
4451import java .net .HttpURLConnection ;
4552import java .net .InetAddress ;
4653import java .net .Proxy ;
4754import java .net .URL ;
4855import java .net .UnknownHostException ;
49-
56+ import java .security .KeyPair ;
57+ import java .security .KeyPairGenerator ;
58+ import java .security .KeyStore ;
59+ import java .security .PrivateKey ;
60+ import java .security .PublicKey ;
61+ import java .security .SecureRandom ;
62+ import java .security .cert .Certificate ;
63+ import java .security .cert .CertificateException ;
64+ import java .security .cert .X509Certificate ;
65+ import java .time .Instant ;
66+ import java .time .temporal .ChronoUnit ;
67+ import java .util .Date ;
68+ import java .util .List ;
5069import javax .net .ssl .HttpsURLConnection ;
70+ import javax .net .ssl .KeyManagerFactory ;
5171import javax .net .ssl .SSLContext ;
5272import javax .net .ssl .SSLSocket ;
73+ import javax .net .ssl .TrustManagerFactory ;
74+ import jdk .test .lib .security .CertificateBuilder ;
75+ import sun .security .x509 .AuthorityKeyIdentifierExtension ;
76+ import sun .security .x509 .GeneralName ;
77+ import sun .security .x509 .GeneralNames ;
78+ import sun .security .x509 .KeyIdentifier ;
79+ import sun .security .x509 .SerialNumber ;
80+ import sun .security .x509 .X500Name ;
5381
5482public final class ServerIdentityTest extends SSLSocketTemplate {
5583
56- private static String keystore ;
5784 private static String hostname ;
58- private static SSLContext context ;
85+ private static SSLContext serverContext ;
5986
6087 /*
6188 * Run the test case.
@@ -64,7 +91,7 @@ public static void main(String[] args) throws Exception {
6491 // Get the customized arguments.
6592 initialize (args );
6693
67- ( new ServerIdentityTest () ).run ();
94+ new ServerIdentityTest ().run ();
6895 }
6996
7097 ServerIdentityTest () throws UnknownHostException {
@@ -95,7 +122,7 @@ protected void runClientApplication(int serverPort) throws Exception {
95122 HttpURLConnection urlc = null ;
96123 InputStream is = null ;
97124 try {
98- urlc = (HttpURLConnection )url .openConnection (Proxy .NO_PROXY );
125+ urlc = (HttpURLConnection ) url .openConnection (Proxy .NO_PROXY );
99126 is = urlc .getInputStream ();
100127 } finally {
101128 if (is != null ) {
@@ -109,31 +136,127 @@ protected void runClientApplication(int serverPort) throws Exception {
109136
110137 @ Override
111138 protected SSLContext createServerSSLContext () throws Exception {
112- return context ;
113- }
114-
115- @ Override
116- protected SSLContext createClientSSLContext () throws Exception {
117- return context ;
139+ return serverContext ;
118140 }
119141
120142 private static void initialize (String [] args ) throws Exception {
121- keystore = args [0 ];
143+ String mode = args [0 ];
122144 hostname = args [1 ];
123145
124- String password = "changeit" ;
125- String keyFilename =
126- System .getProperty ("test.src" , "." ) + "/" + keystore ;
127- String trustFilename =
128- System .getProperty ("test.src" , "." ) + "/" + keystore ;
146+ KeyPairGenerator kpg = KeyPairGenerator .getInstance ("RSA" );
147+ KeyPair caKeys = kpg .generateKeyPair ();
148+ KeyPair serverKeys = kpg .generateKeyPair ();
149+ KeyPair clientKeys = kpg .generateKeyPair ();
150+
151+ CertificateBuilder serverCertificateBuilder = customCertificateBuilder (
152+ "CN=server, O=Some-Org, L=Some-City, ST=Some-State, C=US" ,
153+ serverKeys .getPublic (), caKeys .getPublic ())
154+ .addBasicConstraintsExt (false , false , -1 );
129155
130- System .setProperty ("javax.net.ssl.keyStore" , keyFilename );
131- System .setProperty ("javax.net.ssl.keyStorePassword" , password );
132- System .setProperty ("javax.net.ssl.trustStore" , trustFilename );
133- System .setProperty ("javax.net.ssl.trustStorePassword" , password );
156+ if (mode .equalsIgnoreCase ("dns" )) {
157+ serverCertificateBuilder .addSubjectAltNameDNSExt (List .of (hostname ));
158+ } else if (mode .equalsIgnoreCase ("ip" )) {
159+ serverCertificateBuilder .addSubjectAltNameIPExt (List .of (hostname ));
160+ } else {
161+ fail ("Unknown mode: " + mode );
162+ }
163+
164+ X509Certificate trustedCert = createTrustedCert (caKeys );
165+
166+ X509Certificate serverCert = serverCertificateBuilder .build (
167+ trustedCert , caKeys .getPrivate (), "SHA256WithRSA" );
168+
169+ X509Certificate clientCert = customCertificateBuilder (
170+ "CN=localhost, OU=SSL-Client, O=Some-Org, L=Some-City, ST=Some-State, C=US" ,
171+ clientKeys .getPublic (), caKeys .getPublic ())
172+ .addBasicConstraintsExt (false , false , -1 )
173+ .build (trustedCert , caKeys .getPrivate (), "SHA256WithRSA" );
174+
175+ serverContext = getSSLContext (
176+ trustedCert , serverCert , serverKeys .getPrivate ());
177+
178+ SSLContext clientContext = getSSLContext (
179+ trustedCert , clientCert , clientKeys .getPrivate ());
134180
135- context = SSLContext .getDefault ();
136181 HttpsURLConnection .setDefaultSSLSocketFactory (
137- context .getSocketFactory ());
182+ clientContext .getSocketFactory ());
138183 }
184+
185+ private static SSLContext getSSLContext (
186+ X509Certificate trustedCertificate , X509Certificate keyCertificate ,
187+ PrivateKey privateKey )
188+ throws Exception {
189+
190+ // create a key store
191+ KeyStore ks = KeyStore .getInstance ("PKCS12" );
192+ ks .load (null , null );
193+
194+ // import the trusted cert
195+ ks .setCertificateEntry ("TLS Signer" , trustedCertificate );
196+
197+ // generate certificate chain
198+ Certificate [] chain = new Certificate [2 ];
199+ chain [0 ] = keyCertificate ;
200+ chain [1 ] = trustedCertificate ;
201+
202+ // import the key entry.
203+ final char [] passphrase = "passphrase" .toCharArray ();
204+ ks .setKeyEntry ("Whatever" , privateKey , passphrase , chain );
205+
206+ // Using PKIX TrustManager
207+ TrustManagerFactory tmf = TrustManagerFactory .getInstance ("PKIX" );
208+ tmf .init (ks );
209+
210+ // Using PKIX KeyManager
211+ KeyManagerFactory kmf = KeyManagerFactory .getInstance ("PKIX" );
212+
213+ // create SSL context
214+ SSLContext ctx = SSLContext .getInstance ("TLS" );
215+ kmf .init (ks , passphrase );
216+ ctx .init (kmf .getKeyManagers (), tmf .getTrustManagers (), null );
217+ return ctx ;
218+ }
219+
220+ private static X509Certificate createTrustedCert (KeyPair caKeys )
221+ throws Exception {
222+ SecureRandom random = new SecureRandom ();
223+
224+ KeyIdentifier kid = new KeyIdentifier (caKeys .getPublic ());
225+ GeneralNames gns = new GeneralNames ();
226+ GeneralName name = new GeneralName (new X500Name (
227+ "O=Some-Org, L=Some-City, ST=Some-State, C=US" ));
228+ gns .add (name );
229+ BigInteger serialNumber = BigInteger .valueOf (
230+ random .nextLong (1000000 ) + 1 );
231+ return customCertificateBuilder (
232+ "O=Some-Org, L=Some-City, ST=Some-State, C=US" ,
233+ caKeys .getPublic (), caKeys .getPublic ())
234+ .setSerialNumber (serialNumber )
235+ .addExtension (new AuthorityKeyIdentifierExtension (kid , gns ,
236+ new SerialNumber (serialNumber )))
237+ .addBasicConstraintsExt (true , true , -1 )
238+ .build (null , caKeys .getPrivate (), "SHA256WithRSA" );
239+ }
240+
241+ private static CertificateBuilder customCertificateBuilder (
242+ String subjectName , PublicKey publicKey , PublicKey caKey )
243+ throws CertificateException , IOException {
244+ SecureRandom random = new SecureRandom ();
245+
246+ CertificateBuilder builder = new CertificateBuilder ()
247+ .setSubjectName (subjectName )
248+ .setPublicKey (publicKey )
249+ .setNotBefore (
250+ Date .from (Instant .now ().minus (1 , ChronoUnit .HOURS )))
251+ .setNotAfter (Date .from (Instant .now ().plus (1 , ChronoUnit .HOURS )))
252+ .setSerialNumber (
253+ BigInteger .valueOf (random .nextLong (1000000 ) + 1 ))
254+ .addSubjectKeyIdExt (publicKey )
255+ .addAuthorityKeyIdExt (caKey );
256+ builder .addKeyUsageExt (
257+ new boolean []{true , true , true , true , true , true });
258+
259+ return builder ;
260+ }
261+
139262}
0 commit comments