Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

retrieve full extension value from certificate

I'm using: java.security.cert.X509Certificate package. and java.security.cert.X509CRL;

When I get extension value, for example when OID=2.5.29.14 (it is SubjectKeyIdentifier) cert.getExtensionValue("2.5.29.14"); I get this byte[] range:

[4,22,4,20,5,125,-118,106,-44,108,39,-74,-108,-20,-27,-32,-113,64,-69,125,-8,102,-52,-24]

When I see in certificate, SubjectKeyIdentifier starts from 5.

Question 1: what is at the start of this range? it is 4 byte.

When I see AuthorityKeyIdentifier in X509CRL (AuthorityKeyIdentifier of CRL == SubjectKeyIdentifier Of certificate if CRL is signed by this certificate) there was the same:

[4,24,48,22,-128,20,5,125,-118,106,-44,108,39,-74,-108,-20,-27,-32,-113,64,-69,125,-8,102,-52,-24] but there was another 6 byte at the beginning.

Question 2: what is at the start of this range? it is 6 byte.

and another question:

Question 3: how to parse ExtensionValue in order to get only Identifier value. is this 4 and 6 byte fixed? what is the best way for parsing?


1 Answers

Answer to question 1: These bytes are the binary representation of the ASN 1 data structure. ASN 1 (Abstract Syntaxt Notation One) is a standard defined by the ITU and commonly used in RFCs / message protocols to define higher level data structures (for example X.509 certificates).

ASN 1 has a basic syntax consisting of tripels (tag type, length, value). Some ASN 1 tags allow elements to be nested. In your case you have an

ASN 1 OCTET STRING (tag type 4) with a length of 22 which contains an 
  ASN 1 OCTET STRING (the second 4 in the byte array) of length 20.
    The key identifier

Answer to question 2: The definition of the AuthorityKeyIdentifier differs from SubjectKeyIdentifier (for details check RFC 5280). In your case it is an

ASN 1 OCTET STRING of length 24 which contains an 
  ASN 1 CONSTRUCTED SEQUENCE (tag type 16 for ASN 1 SEQUENCE and tag type 32 for ASN 1 CONSTRUCTED logically or'red -> 16 + 32 = 48) of length 22 which contains
    ASN 1 CONTEXT SPECIFIC DATA (tag type 128 which results in -128 cast to a byte) of length 20
      The key identifier

The data structure differs from a SubjectKeyIdentifier extension as an AuthorityKeyIdentifier extension alternatively may consist of the issuer and serial number of the certificate to use to verify the current certificate.

In your case both key identifiers (the last 20 bytes of the byte arrays) are equal. Hence you may use the certificate mentioned in the first to question to verify the signature of the CRL mentioned in the second question (verification prevents from a manipulated CRL).

Answer to question 3: I strongly recommend not to implement ASN 1 by yourself. Use a libary such as Bouncycastle. To parse data structures correctly you have to use the appropriate classes, especially with Bouncycastle there is no convenience class to determine the type of an ASN 1 structure by a best-effort-approach. However such approach would be nearly impossible to implement.

For example let's say we have the byte array [4,4,67,68,45,53] Does this data (an ASN 1 OCTET STRING) represent:

  • a LDAP message or
  • a JPEG or
  • a human readable string or
  • ...?

Due to the sheer number of protocols defined upon ASN 1 it can not be said which object the data should represent. Furthermore assume that all of the listed interpretations are possible (they are not) which one should be chosen by a general purpose library? Again assume that this data would be a valid JPEG image and a valid LDAP message. A JPEG would have something like transparency, rgb colors and so on. A LDAP message has an id for a protocol operation (BIND request, BIND response, SEARCH request, ...) and some more stuff. Would you like to do some tricky bit manipulations to convert from one into the other?

Furthermore the data maybe should represent something completely different than guessed by our marvellous library. Unfortunately the data got corrupted due to corruptd TCP packages, ... . Now our library can not give us a message similar to

"Bad LDAP message, syntax violated by ..."

as it accidentally parses the data as perfectly legal JPEG.

To parse the shown data for example use Bouncycastle (assuming version 1.51):

//retrieve the certificate from somewhere
X509Certificate c = ...;
String oid = Extension.authorityKeyIdentifier.getId();
byte[] extensionValue = c.getExtensionValue(oid);
ASN1OctetString akiOc = ASN1OctetString.getInstance(extensionValue);
AuthorityKeyIdentifier aki = AuthorityKeyIdentifier.getInstance(akiOc.getOctets());

Then you can invoke

aki.getKeyIdentifier();
aki.getAuthorityCertIssuer();
aki.getAuthorityCertSerialNumber();

for further processing.

like image 193
Sebastian Avatar answered Dec 06 '25 07:12

Sebastian