1 package club.wpia.gigi.crypto;
3 import java.io.IOException;
4 import java.security.cert.Extension;
5 import java.util.Collections;
6 import java.util.LinkedList;
9 import sun.security.provider.certpath.CertId;
10 import sun.security.util.DerInputStream;
11 import sun.security.util.DerOutputStream;
12 import sun.security.util.DerValue;
13 import sun.security.util.ObjectIdentifier;
16 * Adapted from {@link sun.security.provider.certpath.OCSPRequest}
18 public class OCSPRequest {
20 static final ObjectIdentifier NONCE_EXTENSION_OID = ObjectIdentifier.newInternal(new int[] {
21 1, 3, 6, 1, 5, 5, 7, 48, 1, 2
24 // List of request CertIds
25 private final List<CertId> certIds;
27 private final List<Extension> extensions;
31 private Extension nonceExt;
34 * Constructs an OCSPRequest. This constructor is used to construct an
35 * unsigned OCSP Request for a single user cert.
37 OCSPRequest(CertId certId) {
38 this(Collections.singletonList(certId));
41 OCSPRequest(List<CertId> certIds) {
42 this.certIds = certIds;
43 this.extensions = Collections.<Extension>emptyList();
46 OCSPRequest(List<CertId> certIds, List<Extension> extensions) {
47 this.certIds = certIds;
48 this.extensions = extensions;
52 * Creates a new OCSPRequest from its binary data.
55 * the binary form of the OCSP request.
57 * if the input is malformed
59 public OCSPRequest(byte[] in) throws IOException {
60 DerInputStream dis = new DerInputStream(in);
61 DerInputStream req = dis.getDerValue().getData();
62 DerInputStream tbsreq = req.getDerValue().getData();
63 // req.getDerValue()optional signature
65 LinkedList<Extension> exts = new LinkedList<>();
66 LinkedList<CertId> cis = new LinkedList<>();
67 // handles the content of structure
69 //TBSRequest ::= SEQUENCE {
70 // version [0] EXPLICIT Version DEFAULT v1,
71 // requestorName [1] EXPLICIT GeneralName OPTIONAL,
72 // requestList SEQUENCE OF Request,
73 // requestExtensions [2] EXPLICIT Extensions OPTIONAL }
75 while (tbsreq.available() > 0) {
77 if (tbsreq.peekByte() == DerValue.tag_Sequence) {
78 for (DerValue certId : tbsreq.getSequence(1)) {
79 CertId ci = new CertId(certId.getData().getDerValue().getData());
83 } else if (tbsreq.peekByte() == DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 2)) {
84 DerValue[] seq = tbsreq.getDerValue().getData().getSequence(5);
85 for (DerValue derValue : seq) {
86 sun.security.x509.Extension e = new sun.security.x509.Extension(derValue);
87 if (e.getExtensionId().equals((Object) NONCE_EXTENSION_OID)) {
90 } else if (e.isCritical()) {
91 throw new IOException("Unknown critical extension");
96 // Skip any other element
102 if (exts.isEmpty()) {
105 extensions = Collections.unmodifiableList(exts);
107 certIds = Collections.unmodifiableList(cis);
110 byte[] encodeBytes() throws IOException {
112 try (DerOutputStream ocspRequest = new DerOutputStream()) {
113 try (DerOutputStream tbsRequest = new DerOutputStream()) {
114 try (DerOutputStream tmp = new DerOutputStream()) {
117 try (DerOutputStream requestsOut = new DerOutputStream()) {
118 for (CertId certId : certIds) {
119 try (DerOutputStream certIdOut = new DerOutputStream()) {
120 certId.encode(certIdOut);
121 requestsOut.write(DerValue.tag_Sequence, certIdOut);
125 tmp.write(DerValue.tag_Sequence, requestsOut);
128 if ( !extensions.isEmpty()) {
129 try (DerOutputStream extsOut = new DerOutputStream()) {
130 try (DerOutputStream extOut = new DerOutputStream()) {
131 for (Extension ext : extensions) {
134 if (ext.getId().equals(NONCE_EXTENSION_OID.toString())) {
135 nonce = ext.getValue();
140 extsOut.write(DerValue.tag_Sequence, extOut);
143 tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 2), extsOut);
147 tbsRequest.write(DerValue.tag_Sequence, tmp);
150 // OCSPRequest without the signature
151 ocspRequest.write(DerValue.tag_Sequence, tbsRequest);
154 byte[] bytes = ocspRequest.toByteArray();
160 public List<CertId> getCertIds() {
168 public Extension getNonceExt() {