As can be seen from the following ASN.1 definition of an X.509 certificate, the Signature field is a BIT STRING.

Certificate ::= SEQUENCE {
    tbsCertificate      TBSCertificate ({ x509_note_tbs_certificate }),
    signatureAlgorithm  AlgorithmIdentifier,
    signature       BIT STRING ({ x509_note_signature })

However, at least for the rsaEncryption algorithm, there's ASN.1 DER data inside (representing the signature).

So, why is it a BIT STRING? Wouldn't something like SEQUENCE or just OCTET STRING work better?

  • $\begingroup$ As Maarten answers, RSA signature is not DER. For contrast, the content of the BITSTRING in SubjectPublicKeyInfo is: for RSA a DER SEQUENCE; for DSA (or DH) a DER INTEGER; and for EC not DER at all but raw X9.62/SECG.SEC1 point encoding -- all of which are octet-aligned and don't need the bit-padding supported by ASN.1 BITSTRING. $\endgroup$ – dave_thompson_085 Feb 12 '18 at 23:27

The contents of the signature field is dependent on the signatureAlgorithm being used. So it can hold anything (including DER serialisation) for as long as it's eventually encoded as a BIT STRING.

Therefore the length of the signature can be different. Using BIT STRING allows you to know the exact number of bits being used in the signature. With OCTET STRING you may get some extra bits at either ends of the octet-stream which would probably need some special handling to exclude them from further processing at the receiving end.

The SEQUENCE type is like a record, I am not sure why it could be useful here.

  • $\begingroup$ The problem is, the signature field normally contains an ASN.1-encoded signature (with some auxiliary data), and that's guaranteed to be byte-aligned, thus eliminating the need for a BIT STRING. Are there any exceptions? $\endgroup$ – Mark Feb 12 '18 at 16:47
  • $\begingroup$ Well, "normally" you say. ;-) Is it that the X.509 framework has been designed for a more opaque use-case? Also, signature field is not required to contain ASN.1/DER serialisation. It can be any blob. $\endgroup$ – Ilya Etingof Feb 12 '18 at 16:48
  • $\begingroup$ Is there any signature algorithm that actually uses the possibility of placing a binary blob there, or is this just a left-over from the times when X.509 was designed? $\endgroup$ – Mark Feb 12 '18 at 19:11
  • $\begingroup$ Um, yes, RSA. You're mistaken in thinking that signature value is DER encoded. $\endgroup$ – Maarten Bodewes Feb 12 '18 at 22:54

However, at least for the rsaEncryption algorithm, there's ASN.1 DER data inside (representing the signature).

This is not actually the case. It is the case for - for instance - DSA and ECDSA, where the signature consists of two parts: the $r$ and $s$ value. However, it is not the case for RSA.

Let's take a look the the signature of this site, which can use *.stackexchange.com certificate using RSA:

openssl asn1parse -inform DER -in "*.stackexchange.com.cer" -dump

generates 1565 bytes of certificate, and:

 1565:d=1  hl=4 l= 257 prim: BIT STRING        
      0000 - 00 0c c9 00 c1 92 74 aa-17 d5 fa dd a8 d9 4d 89   ......t.......M.
      0010 - 7b bc 19 c6 ec 9b f0 f1-58 c5 e9 71 35 e5 66 7f   {.......X..q5.f.
      0020 - 2c fb fa 90 42 87 3e ff-7a 34 08 ad c2 f3 f8 fd   ,...B.>.z4......
      0030 - 9f 90 e6 b1 86 bc f0 fe-8d b6 de 72 b0 3b 3e 6f   ...........r.;>o
      0040 - 4c a7 5c 5b da e0 20 04-c8 a6 a8 3c ce 12 22 93   L.\[.. ....<..".
      0050 - a3 c1 f5 81 45 25 0e a8-02 24 40 ed bf 2e 12 81   ....E%...$@.....
      0060 - c1 3f c4 9e 96 88 1c 82-86 9c 8d 14 75 72 d0 a0   .?..........ur..
      0070 - 37 e4 30 38 3a 9a 02 6c-10 1b 0a 74 a1 79 11 f1   7.08:..l...t.y..
      0080 - 17 ee 25 37 34 ee 71 54-93 c9 13 cf d1 d1 bb 4b   ..%74.qT.......K
      0090 - 01 d6 30 c4 1f 52 e9 f4-a9 09 71 9e d8 7a 90 0f   ..0..R....q..z..
      00a0 - 5d 35 3b fe ff e0 c5 8d-74 54 9b 7d d0 d2 15 c9   ]5;.....tT.}....
      00b0 - f9 a0 49 be 89 d8 a6 ae-a8 8d ac 5e 64 9e 6b 89   ..I........^d.k.
      00c0 - cb 8a 8f 06 42 fb b6 13-6e 18 ae ab bd 80 85 64   ....B...n......d
      00d0 - 93 34 dd 91 19 86 44 26-9f 68 c6 ff b2 e0 8d fc   .4....D&.h......
      00e0 - 19 9a f7 dc 21 37 80 0c-2a 72 95 ff 3c 6c bf a5   ....!7..*r..<l..
      00f0 - 7f eb f1 7b a7 02 97 d0-b2 a9 68 01 0e 9b 08 c6   ...{......h.....
      0100 - 91                                                .

So that's a raw bit string encoding of a 256 byte / 2048 bit signature. The first 00 valued byte simply encodes the number of bits not to use of the following byte representation. It is of course zero as RSA PKCS#1 signatures always output the signature as a statically sized octet string with the same size as the minimal byte size of the modulus (using a function called I2OSP).

As indicated by Ilya, the signature format depends on the algorithm used. Using a SEQUENCE is not really an option for primitive values. Using an OCTET STRING... well, I suppose they played it safe, but an OCTET STRING would have worked as well in 99.9% of the cases and would not required the 00 valued byte at the beginning.

Another option would have been to switch on the OID of the algorithm identifier and then use the correct type for the signature. That would however have complicated the parsing of X.509 certificates. It seems that X.509 certificates went for the less complicated option, even if that could result in nesting ASN.1 structures in primitive types.

Fortunately there are enough issues left when parsing X.509 certificates.

  • $\begingroup$ DSA is also SEQUENCE of two INTEGERs, like ECDSA. +2 for 'enough issues left' :) $\endgroup$ – dave_thompson_085 Feb 12 '18 at 23:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.