I want to retrieve the OCSP information from a given X509Certificate object. Since I don't know how to parse this information I am asking this question here.
Here is what I got so far:
X509Certificate x509cert = ... //The Certificate
ASN1Primitive obj = ASN1Primitive.fromByteArray(x509cert
.getExtensionValue(Extension.authorityInfoAccess
.getId()));
AuthorityInformationAccess aia = AuthorityInformationAccess.getInstance(obj);
an exception is thrown:
java.security.cert.CertificateParsingException: java.lang.IllegalArgumentException: unknown object in getInstance: org.bouncycastle.asn1.DEROctetString
How do I parse a ASN1Primitive into a valid DEROctetString to progress?
The value of the ASN1Primitive in the example is:
3032303006082b060105050730018624687474703a2f2f6f6373702e616368656c6f732e64653a383038302f6f6373702f65676b
and seems to me to be a valid value.
You can build a DEROctetString using ASN1InputStream
byte[] authInfoAccessExtensionValue = x509cert.getExtensionValue(X509Extension.authorityInfoAccess.getId());
ASN1InputStream ais1 = new ASN1InputStream(new ByteArrayInputStream(authInfoAccessExtensionValue ));
DEROctetString oct = (DEROctetString) (ais1.readObject());
ASN1InputStream ais2 = new ASN1InputStream(oct.getOctets());
AuthorityInformationAccess authorityInformationAccess = AuthorityInformationAccess.getInstance(ais2.readObject());
Try this code to get the OCSP URI meta-data within a X509Certificate. The code is extracted from class OnlineOCSPSource of SD-DSS project (and slightly modified)
public String getAccessLocation(X509Certificate certificate) throws IOException {
final ASN1ObjectIdentifier ocspAccessMethod = X509ObjectIdentifiers.ocspAccessMethod;
final byte[] authInfoAccessExtensionValue = certificate.getExtensionValue(X509Extension.authorityInfoAccess.getId());
if (null == authInfoAccessExtensionValue) {
return null;
}
ASN1InputStream ais1 = null;
ASN1InputStream ais2 = null;
try {
final ByteArrayInputStream bais = new ByteArrayInputStream(authInfoAccessExtensionValue);
ais1 = new ASN1InputStream(bais);
final DEROctetString oct = (DEROctetString) (ais1.readObject());
ais2 = new ASN1InputStream(oct.getOctets());
final AuthorityInformationAccess authorityInformationAccess = AuthorityInformationAccess.getInstance(ais2.readObject());
final AccessDescription[] accessDescriptions = authorityInformationAccess.getAccessDescriptions();
for (AccessDescription accessDescription : accessDescriptions) {
final boolean correctAccessMethod = accessDescription.getAccessMethod().equals(ocspAccessMethod);
if (!correctAccessMethod) {
continue;
}
final GeneralName gn = accessDescription.getAccessLocation();
if (gn.getTagNo() != GeneralName.uniformResourceIdentifier) {
//Not a uniform resource identifier
continue;
}
final DERIA5String str = (DERIA5String) ((DERTaggedObject) gn.toASN1Primitive()).getObject();
final String accessLocation = str.getString();
return accessLocation;
}
return null;
} finally {
ais1.close();
ais2.close();
}
}
In Bouncy Castle 1.57, there's no need to create the intermediary ASN1Primitive. You can get the extension just by using the org.bouncycastle.asn1.x509.Extension and org.bouncycastle.x509.extension.X509ExtensionUtil classes:
X509Certificate cert = // the certificate
// get Authority Information Access extension
byte[] extVal = cert.getExtensionValue(Extension.authorityInfoAccess.getId());
AuthorityInformationAccess aia = AuthorityInformationAccess.getInstance(X509ExtensionUtil.fromExtensionValue(extVal));
Then you can use the aia object:
AccessDescription[] descriptions = aia.getAccessDescriptions();
for (AccessDescription ad : descriptions) {
// ...
}
You can do it in previous versions as well, but for version <= 1.47 I believe that Extension class doesn't exist and you should use org.bouncycastle.asn1.x509.X509Extension instead (I think that org.bouncycastle.x509.extension.X509ExtensionUtil is the same).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With