Skip to content

Commit 9d9d7a1

Browse files
author
Jamil Nimeh
committedFeb 21, 2025
8349759: Add unit test for CertificateBuilder and SimpleOCSPServer test utilities
Reviewed-by: mullan
1 parent b45c32c commit 9d9d7a1

File tree

3 files changed

+308
-59
lines changed

3 files changed

+308
-59
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/**
25+
* @test
26+
* @bug 8349759
27+
* @summary Test the CertificateBuilder and SimpleOCSPServer test utility
28+
* classes using a range of signature algorithms and parameters.
29+
* The goal is to test with both no-parameter and parameterized
30+
* signature algorithms and use the CertPathValidator to validate
31+
* the correctness of the certificate and OCSP server-side structures.
32+
* @modules java.base/sun.security.x509
33+
* java.base/sun.security.provider.certpath
34+
* java.base/sun.security.util
35+
* @library /test/lib
36+
* @run main/othervm CPVAlgTestWithOCSP RSA
37+
* @run main/othervm CPVAlgTestWithOCSP RSA:3072
38+
* @run main/othervm CPVAlgTestWithOCSP DSA
39+
* @run main/othervm CPVAlgTestWithOCSP DSA:3072
40+
* @run main/othervm CPVAlgTestWithOCSP RSASSA-PSS
41+
* @run main/othervm CPVAlgTestWithOCSP RSASSA-PSS:3072
42+
* @run main/othervm CPVAlgTestWithOCSP RSASSA-PSS:4096:SHA-512:SHA3-384:128:1
43+
* @run main/othervm CPVAlgTestWithOCSP EC
44+
* @run main/othervm CPVAlgTestWithOCSP EC:secp521r1
45+
* @run main/othervm CPVAlgTestWithOCSP Ed25519
46+
* @run main/othervm CPVAlgTestWithOCSP ML-DSA-65
47+
*/
48+
49+
import java.math.BigInteger;
50+
import java.security.*;
51+
import java.security.cert.*;
52+
import java.security.cert.Certificate;
53+
import java.security.spec.*;
54+
import java.util.*;
55+
import java.util.concurrent.TimeUnit;
56+
57+
import jdk.test.lib.security.SimpleOCSPServer;
58+
import jdk.test.lib.security.CertificateBuilder;
59+
60+
import static java.security.cert.PKIXRevocationChecker.Option.NO_FALLBACK;
61+
62+
public class CPVAlgTestWithOCSP {
63+
64+
static final String passwd = "passphrase";
65+
static final String ROOT_ALIAS = "root";
66+
static final boolean[] CA_KU_FLAGS = {true, false, false, false, false,
67+
true, true, false, false};
68+
static final boolean[] EE_KU_FLAGS = {true, false, false, false, false,
69+
false, false, false, false};
70+
static final List<String> EE_EKU_OIDS = List.of("1.3.6.1.5.5.7.3.1",
71+
"1.3.6.1.5.5.7.3.2");
72+
73+
public static void main(String[] args) throws Exception {
74+
if (args == null || args.length < 1) {
75+
throw new RuntimeException(
76+
"Usage: CPVAlgTestWithOCSP <IssKeyAlg>");
77+
}
78+
String keyGenAlg = args[0];
79+
80+
// Generate Root and EE keys
81+
KeyPairGenerator keyGen = getKpGen(keyGenAlg);
82+
KeyPair rootCaKP = keyGen.genKeyPair();
83+
KeyPair eeKp = keyGen.genKeyPair();
84+
85+
// Set up the Root CA Cert
86+
// Make a 3 year validity starting from 60 days ago
87+
long start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(60);
88+
long end = start + TimeUnit.DAYS.toMillis(1085);
89+
CertificateBuilder cbld = new CertificateBuilder();
90+
cbld.setSubjectName("CN=Root CA Cert, O=SomeCompany").
91+
setPublicKey(rootCaKP.getPublic()).
92+
setSerialNumber(new BigInteger("1")).
93+
setValidity(new Date(start), new Date(end)).
94+
addSubjectKeyIdExt(rootCaKP.getPublic()).
95+
addAuthorityKeyIdExt(rootCaKP.getPublic()).
96+
addBasicConstraintsExt(true, true, -1).
97+
addKeyUsageExt(CA_KU_FLAGS);
98+
99+
// Make our Root CA Cert!
100+
X509Certificate rootCert = cbld.build(null, rootCaKP.getPrivate());
101+
log("Root CA Created:\n%s", rootCert);
102+
103+
// Now build a keystore and add the keys and cert
104+
KeyStore.Builder keyStoreBuilder =
105+
KeyStore.Builder.newInstance("PKCS12", null,
106+
new KeyStore.PasswordProtection("adminadmin0".toCharArray()));
107+
KeyStore rootKeystore = keyStoreBuilder.getKeyStore();
108+
Certificate[] rootChain = {rootCert};
109+
rootKeystore.setKeyEntry(ROOT_ALIAS, rootCaKP.getPrivate(),
110+
passwd.toCharArray(), rootChain);
111+
112+
// Now fire up the OCSP responder
113+
SimpleOCSPServer rootOcsp = new SimpleOCSPServer(rootKeystore,
114+
passwd, ROOT_ALIAS, null);
115+
rootOcsp.enableLog(true);
116+
rootOcsp.setNextUpdateInterval(3600);
117+
rootOcsp.start();
118+
119+
// Wait 60 seconds for server ready
120+
boolean readyStatus = rootOcsp.awaitServerReady(60, TimeUnit.SECONDS);
121+
if (!readyStatus) {
122+
throw new RuntimeException("Server not ready");
123+
}
124+
int rootOcspPort = rootOcsp.getPort();
125+
String rootRespURI = "http://localhost:" + rootOcspPort;
126+
log("Root OCSP Responder URI is %s", rootRespURI);
127+
128+
// Let's make an EE cert
129+
// Make a 1 year validity starting from 60 days ago
130+
start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(60);
131+
end = start + TimeUnit.DAYS.toMillis(365);
132+
cbld.reset().setSubjectName("CN=Brave Sir Robin, O=SomeCompany").
133+
setPublicKey(eeKp.getPublic()).
134+
setValidity(new Date(start), new Date(end)).
135+
addSubjectKeyIdExt(eeKp.getPublic()).
136+
addAuthorityKeyIdExt(rootCaKP.getPublic()).
137+
addKeyUsageExt(EE_KU_FLAGS).
138+
addExtendedKeyUsageExt(EE_EKU_OIDS).
139+
addSubjectAltNameDNSExt(Collections.singletonList("localhost")).
140+
addAIAExt(Collections.singletonList(rootRespURI));
141+
X509Certificate eeCert = cbld.build(rootCert, rootCaKP.getPrivate());
142+
log("EE CA Created:\n%s", eeCert);
143+
144+
// Provide end entity cert revocation info to the Root CA
145+
// OCSP responder.
146+
Map<BigInteger, SimpleOCSPServer.CertStatusInfo> revInfo =
147+
new HashMap<>();
148+
revInfo.put(eeCert.getSerialNumber(),
149+
new SimpleOCSPServer.CertStatusInfo(
150+
SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD));
151+
rootOcsp.updateStatusDb(revInfo);
152+
153+
// validate chain
154+
CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
155+
PKIXRevocationChecker prc =
156+
(PKIXRevocationChecker) cpv.getRevocationChecker();
157+
prc.setOptions(EnumSet.of(NO_FALLBACK));
158+
PKIXParameters params =
159+
new PKIXParameters(Set.of(new TrustAnchor(rootCert, null)));
160+
params.addCertPathChecker(prc);
161+
CertificateFactory cf = CertificateFactory.getInstance("X.509");
162+
CertPath cp = cf.generateCertPath(List.of(eeCert));
163+
cpv.validate(cp, params);
164+
}
165+
166+
private static KeyPairGenerator getKpGen(String keyGenAlg)
167+
throws GeneralSecurityException {
168+
String[] algComps = keyGenAlg.split(":");
169+
KeyPairGenerator kpg = KeyPairGenerator.getInstance(algComps[0]);
170+
int bitLen;
171+
172+
// Handle any parameters in additional tokenized fields
173+
switch (algComps[0].toUpperCase()) {
174+
case "EC":
175+
// The curve name will be the second token, or secp256r1
176+
// if not provided.
177+
String curveName = (algComps.length >= 2) ? algComps[1] :
178+
"secp256r1";
179+
kpg.initialize(new ECGenParameterSpec(curveName));
180+
break;
181+
case "RSA":
182+
case "DSA":
183+
// Form is RSA|DSA[:<KeyBitLen>]
184+
bitLen = (algComps.length >= 2) ?
185+
Integer.parseInt(algComps[1]) : 2048;
186+
kpg.initialize(bitLen);
187+
break;
188+
case "RSASSA-PSS":
189+
// Form is RSASSA-PSS[:<KeyBitLen>[:HASH:MGFHASH:SALTLEN:TR]]
190+
switch (algComps.length) {
191+
case 1: // Default key length and parameters
192+
kpg.initialize(2048);
193+
break;
194+
case 2: // Specified key length, default params
195+
kpg.initialize(Integer.parseInt(algComps[1]));
196+
break;
197+
default: // len > 2, key length and specified parameters
198+
bitLen = Integer.parseInt(algComps[1]);
199+
String hashAlg = algComps[2];
200+
MGF1ParameterSpec mSpec = (algComps.length >= 4) ?
201+
new MGF1ParameterSpec(algComps[3]) :
202+
MGF1ParameterSpec.SHA256;
203+
int saltLen = (algComps.length >= 5) ?
204+
Integer.parseInt(algComps[4]) : 32;
205+
int trail = (algComps.length >= 6) ?
206+
Integer.parseInt(algComps[5]) :
207+
PSSParameterSpec.TRAILER_FIELD_BC;
208+
PSSParameterSpec pSpec = new PSSParameterSpec(hashAlg,
209+
"MGF1", mSpec, saltLen, trail);
210+
kpg.initialize(new RSAKeyGenParameterSpec(bitLen,
211+
RSAKeyGenParameterSpec.F4, pSpec));
212+
break;
213+
}
214+
215+
// Default: just use the KPG as-is, no additional init needed.
216+
}
217+
218+
return kpg;
219+
}
220+
221+
/**
222+
* Log a message on stdout
223+
*
224+
* @param format the format string for the log entry
225+
* @param args zero or more arguments corresponding to the format string
226+
*/
227+
private static void log(String format, Object ... args) {
228+
System.out.format(format + "\n", args);
229+
}
230+
}

‎test/lib/jdk/test/lib/security/CertificateBuilder.java

+27-19
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
import sun.security.x509.GeneralName;
5252
import sun.security.x509.GeneralNames;
5353
import sun.security.x509.KeyUsageExtension;
54-
import sun.security.x509.SerialNumber;
5554
import sun.security.x509.SubjectAlternativeNameExtension;
5655
import sun.security.x509.URIName;
5756
import sun.security.x509.KeyIdentifier;
@@ -288,11 +287,8 @@ public CertificateBuilder addAIAExt(List<String> locations)
288287
*
289288
* @param bitSettings Boolean array for all nine bit settings in the order
290289
* documented in RFC 5280 section 4.2.1.3.
291-
*
292-
* @throws IOException if an encoding error occurs.
293290
*/
294-
public CertificateBuilder addKeyUsageExt(boolean[] bitSettings)
295-
throws IOException {
291+
public CertificateBuilder addKeyUsageExt(boolean[] bitSettings) {
296292
return addExtension(new KeyUsageExtension(bitSettings));
297293
}
298294

@@ -305,11 +301,9 @@ public CertificateBuilder addKeyUsageExt(boolean[] bitSettings)
305301
* @param maxPathLen The maximum path length issued by this CA. Values
306302
* less than zero will omit this field from the resulting extension and
307303
* no path length constraint will be asserted.
308-
*
309-
* @throws IOException if an encoding error occurs.
310304
*/
311305
public CertificateBuilder addBasicConstraintsExt(boolean crit, boolean isCA,
312-
int maxPathLen) throws IOException {
306+
int maxPathLen) {
313307
return addExtension(new BasicConstraintsExtension(crit, isCA,
314308
maxPathLen));
315309
}
@@ -389,7 +383,27 @@ public CertificateBuilder reset() {
389383
}
390384

391385
/**
392-
* Build the certificate.
386+
* Build the certificate using the default algorithm for the provided
387+
* signing key.
388+
*
389+
* @param issuerCert The certificate of the issuing authority, or
390+
* {@code null} if the resulting certificate is self-signed.
391+
* @param issuerKey The private key of the issuing authority
392+
*
393+
* @return The resulting {@link X509Certificate}
394+
*
395+
* @throws IOException if an encoding error occurs.
396+
* @throws CertificateException If the certificate cannot be generated
397+
* by the underlying {@link CertificateFactory}
398+
*/
399+
public X509Certificate build(X509Certificate issuerCert,
400+
PrivateKey issuerKey) throws IOException, CertificateException {
401+
return build(issuerCert, issuerKey,
402+
SignatureUtil.getDefaultSigAlgForKey(issuerKey));
403+
}
404+
405+
/**
406+
* Build the certificate using the key and specified signing algorithm.
393407
*
394408
* @param issuerCert The certificate of the issuing authority, or
395409
* {@code null} if the resulting certificate is self-signed.
@@ -401,14 +415,10 @@ public CertificateBuilder reset() {
401415
* @throws IOException if an encoding error occurs.
402416
* @throws CertificateException If the certificate cannot be generated
403417
* by the underlying {@link CertificateFactory}
404-
* @throws NoSuchAlgorithmException If an invalid signature algorithm
405-
* is provided.
406418
*/
407419
public X509Certificate build(X509Certificate issuerCert,
408420
PrivateKey issuerKey, String algName)
409-
throws IOException, CertificateException, NoSuchAlgorithmException {
410-
// TODO: add some basic checks (key usage, basic constraints maybe)
411-
421+
throws IOException, CertificateException {
412422
byte[] encodedCert = encodeTopLevel(issuerCert, issuerKey, algName);
413423
ByteArrayInputStream bais = new ByteArrayInputStream(encodedCert);
414424
return (X509Certificate)factory.generateCertificate(bais);
@@ -437,15 +447,14 @@ public X509Certificate build(X509Certificate issuerCert,
437447
*/
438448
private byte[] encodeTopLevel(X509Certificate issuerCert,
439449
PrivateKey issuerKey, String algName)
440-
throws CertificateException, IOException, NoSuchAlgorithmException {
450+
throws CertificateException, IOException {
441451

442-
AlgorithmId signAlg = AlgorithmId.get(algName);
452+
AlgorithmId signAlg;
443453
DerOutputStream outerSeq = new DerOutputStream();
444454
DerOutputStream topLevelItems = new DerOutputStream();
445455

446456
try {
447-
Signature sig = SignatureUtil.fromKey(signAlg.getName(), issuerKey, (Provider)null);
448-
// Rewrite signAlg, RSASSA-PSS needs some parameters.
457+
Signature sig = SignatureUtil.fromKey(algName, issuerKey, "");
449458
signAlg = SignatureUtil.fromSignature(sig, issuerKey);
450459
tbsCertBytes = encodeTbsCert(issuerCert, signAlg);
451460
sig.update(tbsCertBytes);
@@ -566,7 +575,6 @@ private byte[] encodeTbsCert(X509Certificate issuerCert,
566575
*/
567576
private void encodeExtensions(DerOutputStream tbsStream)
568577
throws IOException {
569-
570578
if (extensions.isEmpty()) {
571579
return;
572580
}

‎test/lib/jdk/test/lib/security/SimpleOCSPServer.java

+51-40
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import java.io.*;
2727
import java.net.*;
28+
import java.nio.charset.StandardCharsets;
2829
import java.security.*;
2930
import java.security.cert.CRLReason;
3031
import java.security.cert.X509Certificate;
@@ -61,22 +62,22 @@ public class SimpleOCSPServer {
6162
static final int FREE_PORT = 0;
6263

6364
// CertStatus values
64-
public static enum CertStatus {
65+
public enum CertStatus {
6566
CERT_STATUS_GOOD,
6667
CERT_STATUS_REVOKED,
6768
CERT_STATUS_UNKNOWN,
6869
}
6970

7071
// Fields used for the networking portion of the responder
7172
private ServerSocket servSocket;
72-
private InetAddress listenAddress;
73+
private final InetAddress listenAddress;
7374
private int listenPort;
7475

7576
// Keystore information (certs, keys, etc.)
76-
private KeyStore keystore;
77-
private X509Certificate issuerCert;
78-
private X509Certificate signerCert;
79-
private PrivateKey signerKey;
77+
private final KeyStore keystore;
78+
private final X509Certificate issuerCert;
79+
private final X509Certificate signerCert;
80+
private final PrivateKey signerKey;
8081

8182
// Fields used for the operational portions of the server
8283
private boolean logEnabled = false;
@@ -91,9 +92,9 @@ public static enum CertStatus {
9192
// Fields used in the generation of responses
9293
private long nextUpdateInterval = -1;
9394
private Date nextUpdate = null;
94-
private ResponderId respId;
95-
private AlgorithmId sigAlgId;
96-
private Map<CertId, CertStatusInfo> statusDb =
95+
private final ResponderId respId;
96+
private String sigAlgName;
97+
private final Map<CertId, CertStatusInfo> statusDb =
9798
Collections.synchronizedMap(new HashMap<>());
9899

99100
/**
@@ -140,40 +141,39 @@ public SimpleOCSPServer(KeyStore ks, String password, String issuerAlias,
140141
public SimpleOCSPServer(InetAddress addr, int port, KeyStore ks,
141142
String password, String issuerAlias, String signerAlias)
142143
throws GeneralSecurityException, IOException {
143-
Objects.requireNonNull(ks, "Null keystore provided");
144+
keystore = Objects.requireNonNull(ks, "Null keystore provided");
144145
Objects.requireNonNull(issuerAlias, "Null issuerName provided");
145146

146147
utcDateFmt.setTimeZone(TimeZone.getTimeZone("GMT"));
147148

148-
keystore = ks;
149-
issuerCert = (X509Certificate)ks.getCertificate(issuerAlias);
149+
issuerCert = (X509Certificate)keystore.getCertificate(issuerAlias);
150150
if (issuerCert == null) {
151151
throw new IllegalArgumentException("Certificate for alias " +
152152
issuerAlias + " not found");
153153
}
154154

155155
if (signerAlias != null) {
156-
signerCert = (X509Certificate)ks.getCertificate(signerAlias);
156+
signerCert = (X509Certificate)keystore.getCertificate(signerAlias);
157157
if (signerCert == null) {
158158
throw new IllegalArgumentException("Certificate for alias " +
159159
signerAlias + " not found");
160160
}
161-
signerKey = (PrivateKey)ks.getKey(signerAlias,
161+
signerKey = (PrivateKey)keystore.getKey(signerAlias,
162162
password.toCharArray());
163163
if (signerKey == null) {
164164
throw new IllegalArgumentException("PrivateKey for alias " +
165165
signerAlias + " not found");
166166
}
167167
} else {
168168
signerCert = issuerCert;
169-
signerKey = (PrivateKey)ks.getKey(issuerAlias,
169+
signerKey = (PrivateKey)keystore.getKey(issuerAlias,
170170
password.toCharArray());
171171
if (signerKey == null) {
172172
throw new IllegalArgumentException("PrivateKey for alias " +
173173
issuerAlias + " not found");
174174
}
175175
}
176-
sigAlgId = AlgorithmId.get(SignatureUtil.getDefaultSigAlgForKey(signerKey));
176+
sigAlgName = SignatureUtil.getDefaultSigAlgForKey(signerKey);
177177
respId = new ResponderId(signerCert.getSubjectX500Principal());
178178
listenAddress = addr;
179179
listenPort = port;
@@ -495,8 +495,14 @@ private Map<CertId, CertStatusInfo> checkStatusDb(
495495
public void setSignatureAlgorithm(String algName)
496496
throws NoSuchAlgorithmException {
497497
if (!started) {
498-
sigAlgId = AlgorithmId.get(algName);
499-
log("Signature algorithm set to " + sigAlgId.getName());
498+
// We don't care about the AlgorithmId object, we're just
499+
// using it to validate the algName parameter.
500+
AlgorithmId.get(algName);
501+
sigAlgName = algName;
502+
log("Signature algorithm set to " + algName);
503+
} else {
504+
log("Signature algorithm cannot be set on a running server, " +
505+
"stop the server first");
500506
}
501507
}
502508

@@ -604,9 +610,9 @@ private static synchronized void err(Throwable exc) {
604610
* object may be used to construct OCSP responses.
605611
*/
606612
public static class CertStatusInfo {
607-
private CertStatus certStatusType;
613+
private final CertStatus certStatusType;
608614
private CRLReason reason;
609-
private Date revocationTime;
615+
private final Date revocationTime;
610616

611617
/**
612618
* Create a Certificate status object by providing the status only.
@@ -745,7 +751,7 @@ public void run() {
745751
// This will be tokenized so we know if we are dealing with
746752
// a GET or POST.
747753
String[] headerTokens = readLine(in).split(" ");
748-
LocalOcspRequest ocspReq = null;
754+
LocalOcspRequest ocspReq;
749755
LocalOcspResponse ocspResp = null;
750756
ResponseStatus respStat = ResponseStatus.INTERNAL_ERROR;
751757
try {
@@ -794,7 +800,7 @@ public void run() {
794800
out.flush();
795801

796802
log("Closing " + ocspSocket);
797-
} catch (IOException | CertificateException exc) {
803+
} catch (IOException | GeneralSecurityException exc) {
798804
err(exc);
799805
}
800806
}
@@ -826,10 +832,10 @@ public void sendResponse(OutputStream out, LocalOcspResponse resp)
826832
append("\r\n");
827833
}
828834
sb.append("\r\n");
835+
log(resp.toString());
829836

830-
out.write(sb.toString().getBytes("UTF-8"));
837+
out.write(sb.toString().getBytes(StandardCharsets.UTF_8));
831838
out.write(respBytes);
832-
log(resp.toString());
833839
}
834840

835841
/**
@@ -940,7 +946,7 @@ private LocalOcspRequest parseHttpOcspGet(String[] headerTokens,
940946
// "/" off before decoding.
941947
return new LocalOcspRequest(Base64.getMimeDecoder().decode(
942948
URLDecoder.decode(headerTokens[1].replaceAll("/", ""),
943-
"UTF-8")));
949+
StandardCharsets.UTF_8)));
944950
}
945951

946952
/**
@@ -974,8 +980,7 @@ private String readLine(InputStream is) throws IOException {
974980
bos.write(b);
975981
}
976982
}
977-
978-
return new String(bos.toByteArray(), "UTF-8");
983+
return bos.toString(StandardCharsets.UTF_8);
979984
}
980985
}
981986

@@ -1052,7 +1057,6 @@ private void parseSignature(DerValue sigSequence)
10521057

10531058
if (sigItems[2].isContextSpecific((byte)0)) {
10541059
DerValue[] certDerItems = sigItems[2].data.getSequence(4);
1055-
int i = 0;
10561060
for (DerValue dv : certDerItems) {
10571061
X509Certificate xc = new X509CertImpl(dv);
10581062
certificates.add(xc);
@@ -1131,7 +1135,7 @@ private List<LocalSingleRequest> getRequests() {
11311135
* Return the list of X.509 Certificates in this OCSP request.
11321136
*
11331137
* @return an unmodifiable {@code List} of zero or more
1134-
* {@cpde X509Certificate} objects.
1138+
* {@code X509Certificate} objects.
11351139
*/
11361140
private List<X509Certificate> getCertificates() {
11371141
return Collections.unmodifiableList(certificates);
@@ -1295,7 +1299,8 @@ public class LocalOcspResponse {
12951299
private final Map<String, Extension> responseExtensions;
12961300
private byte[] signature;
12971301
private final List<X509Certificate> certificates;
1298-
private final byte[] encodedResponse;
1302+
private final Signature signEngine;
1303+
private final AlgorithmId sigAlgId;
12991304

13001305
/**
13011306
* Constructor for the generation of non-successful responses
@@ -1305,9 +1310,11 @@ public class LocalOcspResponse {
13051310
* @throws IOException if an error happens during encoding
13061311
* @throws NullPointerException if {@code respStat} is {@code null}
13071312
* or {@code respStat} is successful.
1313+
* @throws GeneralSecurityException if errors occur while obtaining
1314+
* the signature object or any algorithm identifier parameters.
13081315
*/
13091316
public LocalOcspResponse(OCSPResponse.ResponseStatus respStat)
1310-
throws IOException {
1317+
throws IOException, GeneralSecurityException {
13111318
this(respStat, null, null);
13121319
}
13131320

@@ -1324,10 +1331,13 @@ public LocalOcspResponse(OCSPResponse.ResponseStatus respStat)
13241331
* @throws NullPointerException if {@code respStat} is {@code null}
13251332
* or {@code respStat} is successful, and a {@code null} {@code itemMap}
13261333
* has been provided.
1334+
* @throws GeneralSecurityException if errors occur while obtaining
1335+
* the signature object or any algorithm identifier parameters.
13271336
*/
13281337
public LocalOcspResponse(OCSPResponse.ResponseStatus respStat,
13291338
Map<CertId, CertStatusInfo> itemMap,
1330-
Map<String, Extension> reqExtensions) throws IOException {
1339+
Map<String, Extension> reqExtensions)
1340+
throws IOException, GeneralSecurityException {
13311341
responseStatus = Objects.requireNonNull(respStat,
13321342
"Illegal null response status");
13331343
if (responseStatus == ResponseStatus.SUCCESSFUL) {
@@ -1348,13 +1358,18 @@ public LocalOcspResponse(OCSPResponse.ResponseStatus respStat,
13481358
certificates.add(signerCert);
13491359
}
13501360
certificates.add(issuerCert);
1361+
// Create the signature object and AlgorithmId that we'll use
1362+
// later to create the signature on this response.
1363+
signEngine = SignatureUtil.fromKey(sigAlgName, signerKey, "");
1364+
sigAlgId = SignatureUtil.fromSignature(signEngine, signerKey);
13511365
} else {
13521366
respItemMap = null;
13531367
producedAtDate = null;
13541368
responseExtensions = null;
13551369
certificates = null;
1370+
signEngine = null;
1371+
sigAlgId = null;
13561372
}
1357-
encodedResponse = this.getBytes();
13581373
}
13591374

13601375
/**
@@ -1436,13 +1451,9 @@ private byte[] encodeBasicOcspResponse() throws IOException {
14361451
basicORItemStream.write(tbsResponseBytes);
14371452

14381453
try {
1439-
// Create the signature
1440-
Signature sig = SignatureUtil.fromKey(
1441-
sigAlgId.getName(), signerKey, (Provider)null);
1442-
sig.update(tbsResponseBytes);
1443-
signature = sig.sign();
1444-
// Rewrite signAlg, RSASSA-PSS needs some parameters.
1445-
sigAlgId = SignatureUtil.fromSignature(sig, signerKey);
1454+
// Create the signature with the initialized Signature object
1455+
signEngine.update(tbsResponseBytes);
1456+
signature = signEngine.sign();
14461457
sigAlgId.encode(basicORItemStream);
14471458
basicORItemStream.putBitString(signature);
14481459
} catch (GeneralSecurityException exc) {

1 commit comments

Comments
 (1)

openjdk-notifier[bot] commented on Feb 21, 2025

@openjdk-notifier[bot]
Please sign in to comment.