Search code examples
pkix509asn.1csrder

Creating CSR programmatically


I am trying to create a CSR programmatically. I've read about ASN.1, RFC 2986, X.509.
I have also parsed several DER-encoded CSR files manually which were created using OpenSSL.
Everything looks clear except for a couple of things:

  1. Public key part contains next bytes 8D 00 30 81 89 02 81 81 before the BIT STRING content (and after 03 81). What is this? I noticed that all CSR files encoded with DER contain them. I didn't find anything about them in the RFC.

  2. Signature part contains next unclear bytes before the signature content but after 03 81. As I understand this part contains information about the last octet in BIT STRING (how much bites in last byte actually should be taken). But I don't understand how to decode these bytes. For example the signature could look like the following:
    03 81 81 00 64 12 ... 24 B1 28
    where 03h is a BIT STRING format, 81h length of the bit string, 64 12 ... 24 B1 28 is a signature (but it has length 80h). I don't understand the part 81 00.

Thanks in advance.


Solution

    1. The BIT STRING in the SubjectPublicKeyInfo depends on your public key algorithm. The contents are again DER-encoded, see RFC 3370 for possibilities.

    2. If your signature looks like

      03 81 81 00 64 12 ... 24 B1 28

    this is to be interpreted as follows. DER is a TLV (Tag - Length - Value) encoding. So the first byte (octet in their parlance) represents the tag - 03 for BIT STRING as you noticed correctly.

    The second byte determines the length:

    In the long form, the length octets shall consist of an initial octet and one or more subsequent octets. The initial octet shall be encoded as follows:

    a) bit 8 shall be one;

    b) bits 7 to 1 shall encode the number of subsequent octets in the length octets, as an unsigned binary integer with bit 7 as the most significant bit;

    81has bit 8 set to one, so the remaining bits indicate the number of bytes that determine the overall length. In your case it's simply 1 byte. So the next byte is your lenght - 81 being equal to signature length of 129 bytes. So the following 129 bytes represent your value, starting with the 00.