@@ -128,6 +128,23 @@ public static CRL getCRL(String url) throws IOException, CertificateException, C
128128 return SignUtils .parseCrlFromStream (new URL (url ).openStream ());
129129 }
130130
131+ /**
132+ * Retrieves the URL for the issuer certificate for the given CRL.
133+ *
134+ * @param crl the CRL response
135+ *
136+ * @return the URL or null.
137+ */
138+ public static String getIssuerCertURL (CRL crl ) {
139+ IASN1Primitive obj ;
140+ try {
141+ obj = getExtensionValue (crl , FACTORY .createExtension ().getAuthorityInfoAccess ().getId ());
142+ return getValueFromAIAExtension (obj , SecurityIDs .ID_CA_ISSUERS );
143+ } catch (IOException e ) {
144+ return null ;
145+ }
146+ }
147+
131148 // Online Certificate Status Protocol
132149
133150 /**
@@ -141,22 +158,10 @@ public static String getOCSPURL(X509Certificate certificate) {
141158 IASN1Primitive obj ;
142159 try {
143160 obj = getExtensionValue (certificate , FACTORY .createExtension ().getAuthorityInfoAccess ().getId ());
144- if (obj == null ) {
145- return null ;
146- }
147- IASN1Sequence accessDescriptions = FACTORY .createASN1Sequence (obj );
148- for (int i = 0 ; i < accessDescriptions .size (); i ++) {
149- IASN1Sequence accessDescription = FACTORY .createASN1Sequence (accessDescriptions .getObjectAt (i ));
150- IASN1ObjectIdentifier id = FACTORY .createASN1ObjectIdentifier (accessDescription .getObjectAt (0 ));
151- if (accessDescription .size () == 2 && id != null && SecurityIDs .ID_OCSP .equals (id .getId ())) {
152- IASN1Primitive description = FACTORY .createASN1Primitive (accessDescription .getObjectAt (1 ));
153- return getStringFromGeneralName (description );
154- }
155- }
161+ return getValueFromAIAExtension (obj , SecurityIDs .ID_OCSP );
156162 } catch (IOException e ) {
157163 return null ;
158164 }
159- return null ;
160165 }
161166
162167 // Missing certificates in chain
@@ -172,22 +177,10 @@ public static String getIssuerCertURL(X509Certificate certificate) {
172177 IASN1Primitive obj ;
173178 try {
174179 obj = getExtensionValue (certificate , FACTORY .createExtension ().getAuthorityInfoAccess ().getId ());
175- if (obj == null ) {
176- return null ;
177- }
178- IASN1Sequence accessDescriptions = FACTORY .createASN1Sequence (obj );
179- for (int i = 0 ; i < accessDescriptions .size (); i ++) {
180- IASN1Sequence accessDescription = FACTORY .createASN1Sequence (accessDescriptions .getObjectAt (i ));
181- IASN1ObjectIdentifier id = FACTORY .createASN1ObjectIdentifier (accessDescription .getObjectAt (0 ));
182- if (accessDescription .size () == 2 && id != null && SecurityIDs .ID_CA_ISSUERS .equals (id .getId ())) {
183- IASN1Primitive description = FACTORY .createASN1Primitive (accessDescription .getObjectAt (1 ));
184- return getStringFromGeneralName (description );
185- }
186- }
180+ return getValueFromAIAExtension (obj , SecurityIDs .ID_CA_ISSUERS );
187181 } catch (IOException e ) {
188182 return null ;
189183 }
190- return null ;
191184 }
192185
193186 // Time Stamp Authority
@@ -245,17 +238,41 @@ static boolean isSelfSigned(X509Certificate certificate) {
245238 * @param certificate the certificate from which we need the ExtensionValue
246239 * @param oid the Object Identifier value for the extension.
247240 *
248- * @return the extension value as an {@link IASN1Primitive} object
241+ * @return the extension value as an {@link IASN1Primitive} object.
249242 *
250243 * @throws IOException
251244 */
252245 private static IASN1Primitive getExtensionValue (X509Certificate certificate , String oid ) throws IOException {
253- byte [] bytes = SignUtils .getExtensionValueByOid (certificate , oid );
254- if (bytes == null ) {
246+ return getExtensionValueFromByteArray (SignUtils .getExtensionValueByOid (certificate , oid ));
247+ }
248+
249+ /**
250+ * @param crl the CRL from which we need the ExtensionValue
251+ * @param oid the Object Identifier value for the extension.
252+ *
253+ * @return the extension value as an {@link IASN1Primitive} object.
254+ *
255+ * @throws IOException
256+ */
257+ private static IASN1Primitive getExtensionValue (CRL crl , String oid ) throws IOException {
258+ return getExtensionValueFromByteArray (SignUtils .getExtensionValueByOid (crl , oid ));
259+ }
260+
261+ /**
262+ * Converts extension value represented as byte array to {@link IASN1Primitive} object.
263+ *
264+ * @param extensionValue the extension value as byte array
265+ *
266+ * @return the extension value as an {@link IASN1Primitive} object.
267+ *
268+ * @throws IOException
269+ */
270+ private static IASN1Primitive getExtensionValueFromByteArray (byte [] extensionValue ) throws IOException {
271+ if (extensionValue == null ) {
255272 return null ;
256273 }
257274 IASN1OctetString octs ;
258- try (IASN1InputStream aIn = FACTORY .createASN1InputStream (new ByteArrayInputStream (bytes ))) {
275+ try (IASN1InputStream aIn = FACTORY .createASN1InputStream (new ByteArrayInputStream (extensionValue ))) {
259276 octs = FACTORY .createASN1OctetString (aIn .readObject ());
260277 }
261278 try (IASN1InputStream aIn = FACTORY .createASN1InputStream (new ByteArrayInputStream (octs .getOctets ()))) {
@@ -274,4 +291,28 @@ private static String getStringFromGeneralName(IASN1Primitive names) {
274291 IASN1TaggedObject taggedObject = FACTORY .createASN1TaggedObject (names );
275292 return new String (FACTORY .createASN1OctetString (taggedObject , false ).getOctets (), StandardCharsets .ISO_8859_1 );
276293 }
294+
295+ /**
296+ * Retrieves accessLocation value for specified accessMethod from the Authority Information Access extension.
297+ *
298+ * @param extensionValue Authority Information Access extension value
299+ * @param accessMethod accessMethod OID; usually id-ad-caIssuers or id-ad-ocsp
300+ *
301+ * @return the location (URI) of the information.
302+ */
303+ private static String getValueFromAIAExtension (IASN1Primitive extensionValue , String accessMethod ) {
304+ if (extensionValue == null ) {
305+ return null ;
306+ }
307+ IASN1Sequence accessDescriptions = FACTORY .createASN1Sequence (extensionValue );
308+ for (int i = 0 ; i < accessDescriptions .size (); i ++) {
309+ IASN1Sequence accessDescription = FACTORY .createASN1Sequence (accessDescriptions .getObjectAt (i ));
310+ IASN1ObjectIdentifier id = FACTORY .createASN1ObjectIdentifier (accessDescription .getObjectAt (0 ));
311+ if (accessDescription .size () == 2 && id != null && accessMethod .equals (id .getId ())) {
312+ IASN1Primitive description = FACTORY .createASN1Primitive (accessDescription .getObjectAt (1 ));
313+ return getStringFromGeneralName (description );
314+ }
315+ }
316+ return null ;
317+ }
277318}
0 commit comments