1
1
/*
2
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
21
21
* questions.
22
22
*/
23
23
24
- /*
25
- * This test is called by certreplace.sh
26
- */
27
-
28
24
import java .io .FileInputStream ;
25
+ import java .io .FileOutputStream ;
26
+ import java .nio .file .Files ;
27
+ import java .nio .file .Path ;
28
+ import java .nio .file .Paths ;
29
+ import java .nio .file .StandardOpenOption ;
29
30
import java .security .KeyStore ;
31
+ import java .security .PrivateKey ;
30
32
import java .security .cert .Certificate ;
31
33
import java .security .cert .CertificateFactory ;
32
34
import java .security .cert .X509Certificate ;
33
- import java .util .Arrays ;
34
35
import java .util .ArrayList ;
35
36
import java .util .List ;
37
+
38
+ import jdk .test .lib .SecurityTools ;
39
+ import jdk .test .lib .security .CertUtils ;
40
+ import jdk .test .lib .security .KeyStoreUtils ;
36
41
import sun .security .validator .Validator ;
37
42
43
+ /*
44
+ * @test id=certreplace
45
+ * @bug 6948803
46
+ * @summary CertPath validation regression caused by SHA1 replacement root and MD2 disable feature
47
+ * @library /test/lib
48
+ * @modules java.base/sun.security.validator
49
+ *
50
+ * @run main CertReplace certreplace.jks certreplace.certs
51
+ */
52
+
53
+ /*
54
+ * @test id=samedn
55
+ * @bug 6958869
56
+ * @summary Regression: PKIXValidator fails when multiple trust anchors have same dn
57
+ * @library /test/lib
58
+ * @modules java.base/sun.security.validator
59
+ *
60
+ * @run main CertReplace samedn.jks samedn1.certs
61
+ * @run main CertReplace samedn.jks samedn2.certs
62
+ */
63
+
38
64
public class CertReplace {
39
65
66
+ private static final String SAMEDN_JKS = "samedn.jks" ;
67
+ private static final String CERTREPLACE_JKS = "certreplace.jks" ;
68
+ private static final String PASSWORD = "changeit" ;
69
+ private static final char [] PASSWORD_CHAR_ARR = PASSWORD .toCharArray ();
70
+
71
+ /**
72
+ * This method creates certs for the Cert Replace test
73
+ *
74
+ * @throws Exception
75
+ */
76
+ private static void certReplace () throws Exception {
77
+
78
+ final String ktBaseParameters = "-storepass " + PASSWORD + " " +
79
+ "-keypass " + PASSWORD + " " +
80
+ "-keystore " + CERTREPLACE_JKS + " " +
81
+ "-keyalg rsa " ;
82
+
83
+ final Path keystoreFilePath = Paths .get (CERTREPLACE_JKS );
84
+ Files .deleteIfExists (keystoreFilePath );
85
+
86
+ // 1. Generate 3 aliases in a keystore: ca, int, user
87
+ SecurityTools .keytool (ktBaseParameters +
88
+ "-genkeypair -alias ca -dname CN=CA -keyalg rsa -sigalg md2withrsa -ext bc" );
89
+ SecurityTools .keytool (ktBaseParameters +
90
+ "-genkeypair -alias int -dname CN=Int -keyalg rsa" );
91
+ SecurityTools .keytool (ktBaseParameters +
92
+ "-genkeypair -alias user -dname CN=User -keyalg rsa" );
93
+
94
+ final KeyStore keyStore = KeyStoreUtils .loadKeyStore (CERTREPLACE_JKS , PASSWORD );
95
+
96
+ // 2. Signing: ca -> int -> user
97
+
98
+ SecurityTools .keytool (ktBaseParameters +
99
+ "-certreq -alias int -file int.req" );
100
+ SecurityTools .keytool (ktBaseParameters +
101
+ "-gencert -rfc -alias ca -ext bc -infile int.req " +
102
+ "-outfile int.cert" );
103
+
104
+ //putting the certificate in the keystore
105
+ try (final FileInputStream certInputStream = new FileInputStream ("int.cert" )) {
106
+ final Certificate [] certs = new Certificate []{
107
+ CertUtils .getCertFromStream (
108
+ certInputStream
109
+ )
110
+ };
111
+
112
+ final PrivateKey privateKey = (PrivateKey ) keyStore .getKey ("int" , PASSWORD_CHAR_ARR );
113
+ keyStore .setKeyEntry ("int" , privateKey , PASSWORD_CHAR_ARR , certs );
114
+ keyStore .store (new FileOutputStream (CERTREPLACE_JKS ), PASSWORD_CHAR_ARR );
115
+ }
116
+
117
+ SecurityTools .keytool (ktBaseParameters +
118
+ "-certreq -alias user -file user.req" );
119
+ SecurityTools .keytool (ktBaseParameters +
120
+ "-gencert -rfc -alias int " +
121
+ "-infile user.req " +
122
+ "-outfile certreplace.certs" ); // this will create certreplace.certs which is later appended
123
+
124
+ // 3. Create the certchain file
125
+ final Path certPath = Paths .get ("certreplace.certs" );
126
+
127
+ Files .write (certPath , Files .readAllBytes (Path .of ("int.cert" )), StandardOpenOption .APPEND );
128
+
129
+ final String outputCa = SecurityTools .keytool (ktBaseParameters +
130
+ "-export -rfc -alias ca" ).getOutput ();
131
+ Files .write (certPath , outputCa .getBytes (), StandardOpenOption .APPEND );
132
+
133
+ // 4. Upgrade ca from MD2withRSA to SHA256withRSA, remove other aliases and make this keystore the cacerts file
134
+ keyStore .deleteEntry ("int" );
135
+ keyStore .deleteEntry ("user" );
136
+ keyStore .store (new FileOutputStream (CERTREPLACE_JKS ), PASSWORD_CHAR_ARR );
137
+
138
+ SecurityTools .keytool (ktBaseParameters +
139
+ "-selfcert -alias ca" );
140
+ }
141
+
142
+ /**
143
+ * This method creates certs for the Same DN test
144
+ *
145
+ * @throws Exception
146
+ */
147
+ private static void sameDn () throws Exception {
148
+
149
+ final String ktBaseParameters = "-storepass " + PASSWORD + " " +
150
+ "-keypass " + PASSWORD + " " +
151
+ "-keystore " + SAMEDN_JKS + " " +
152
+ "-keyalg rsa " ;
153
+
154
+ final Path keystoreFilePath = Paths .get (SAMEDN_JKS );
155
+ Files .deleteIfExists (keystoreFilePath );
156
+
157
+ // 1. Generate 3 aliases in a keystore: ca1, ca2, user. The CAs' startdate
158
+ // is set to one year ago so that they are expired now
159
+ SecurityTools .keytool (ktBaseParameters +
160
+ "-genkeypair -alias ca1 -dname CN=CA -keyalg rsa " +
161
+ "-sigalg md5withrsa -ext bc -startdate -1y" );
162
+ SecurityTools .keytool (ktBaseParameters +
163
+ "-genkeypair -alias ca2 -dname CN=CA -keyalg rsa " +
164
+ "-sigalg sha1withrsa -ext bc -startdate -1y" );
165
+ SecurityTools .keytool (ktBaseParameters +
166
+ "-genkeypair -alias user -dname CN=User -keyalg rsa" );
167
+
168
+ // 2. Signing: ca -> user. The startdate is set to 1 minute in the past to ensure the certificate
169
+ // is valid at the time of validation and to prevent any issues with timing discrepancies
170
+ // Automatically saves the certs to the certs files
171
+
172
+ SecurityTools .keytool (ktBaseParameters +
173
+ "-certreq -alias user -file user.req" );
174
+ SecurityTools .keytool (ktBaseParameters +
175
+ "-gencert -rfc -alias ca1 " +
176
+ "-startdate -1M -infile user.req -outfile samedn1.certs" );
177
+ SecurityTools .keytool (ktBaseParameters +
178
+ "-gencert -rfc -alias ca2 " +
179
+ "-startdate -1M -infile user.req -outfile samedn2.certs" );
180
+
181
+ // 3. Remove user for cacerts
182
+ final KeyStore keyStore = KeyStoreUtils .loadKeyStore (SAMEDN_JKS , PASSWORD );
183
+ keyStore .deleteEntry ("user" );
184
+ keyStore .store (new FileOutputStream (CERTREPLACE_JKS ), PASSWORD_CHAR_ARR );
185
+ }
186
+
40
187
/**
41
188
* @param args {cacerts keystore, cert chain}
42
189
*/
43
190
public static void main (String [] args ) throws Exception {
44
191
192
+ if (args [0 ].equals (CERTREPLACE_JKS )) {
193
+ certReplace ();
194
+ } else if (args [0 ].equals (SAMEDN_JKS )) {
195
+ sameDn ();
196
+ } else {
197
+ throw new RuntimeException ("Not recognised test " + args [0 ]);
198
+ }
199
+
45
200
KeyStore ks = KeyStore .getInstance ("JKS" );
46
- ks .load (new FileInputStream (args [0 ]), "changeit" .toCharArray ());
201
+ try (final FileInputStream certInputStream = new FileInputStream (args [0 ])) {
202
+ ks .load (certInputStream , PASSWORD_CHAR_ARR );
203
+ }
47
204
Validator v = Validator .getInstance
48
205
(Validator .TYPE_PKIX , Validator .VAR_GENERIC , ks );
49
206
X509Certificate [] chain = createPath (args [1 ]);
@@ -57,9 +214,10 @@ public static void main(String[] args) throws Exception {
57
214
public static X509Certificate [] createPath (String chain ) throws Exception {
58
215
CertificateFactory cf = CertificateFactory .getInstance ("X.509" );
59
216
List list = new ArrayList ();
60
- for (Certificate c : cf .generateCertificates (
61
- new FileInputStream (chain ))) {
62
- list .add ((X509Certificate )c );
217
+ try (final FileInputStream certInputStream = new FileInputStream (chain )) {
218
+ for (Certificate c : cf .generateCertificates (certInputStream )) {
219
+ list .add ((X509Certificate ) c );
220
+ }
63
221
}
64
222
return (X509Certificate []) list .toArray (new X509Certificate [0 ]);
65
223
}
0 commit comments