為什麼 X.509 中的簽名欄位是 BIT STRING,儘管裡面有 ASN.1 (DER) 數據?
從以下 X.509 證書的 ASN.1 定義可以看出,簽名欄位是一個 BIT STRING。
Certificate ::= SEQUENCE { tbsCertificate TBSCertificate ({ x509_note_tbs_certificate }), signatureAlgorithm AlgorithmIdentifier, signature BIT STRING ({ x509_note_signature }) }
但是,至少對於 rsaEncryption 算法,裡面有 ASN.1 DER 數據(代表簽名)。
那麼,為什麼它是一個 BIT STRING?像 SEQUENCE 或只是 OCTET STRING 這樣的東西不會更好嗎?
簽名欄位的內容取決於
signatureAlgorithm
所使用的內容。所以它可以保存任何東西(包括 DER 序列化),只要它最終編碼為BIT STRING
.因此簽名的長度可以不同。Using
BIT STRING
允許您知道簽名中使用的確切位數。您可能會在OCTET STRING
八位字節流的兩端獲得一些額外的位,這可能需要一些特殊處理才能將它們排除在接收端的進一步處理之外。該
SEQUENCE
類型就像一個記錄,我不確定它為什麼在這裡有用。
但是,至少對於 rsaEncryption 算法,裡面有 ASN.1 DER 數據(代表簽名)。
實際上並非如此。例如,DSA 和 ECDSA 就是這種情況,其中籤名由兩部分組成: $ r $ 和 $ s $ 價值。但是,RSA 並非如此。
我們來看看這個站點的簽名,它可以使用 *.stackexchange.com 證書使用 RSA:
openssl asn1parse -inform DER -in "*.stackexchange.com.cer" -dump
生成 1565 字節的證書,並且:
... 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 .
所以這是一個 256 字節/2048 位簽名的原始位串編碼。第一個有值字節簡單地編碼不使用以下字節表示
00
的位數。它當然為零,因為 RSA PKCS#1 簽名始終將簽名輸出為靜態大小的八位字節字元串,其大小與模的最小字節大小相同(使用稱為 I2OSP 的函式)。正如Ilya所指出的,簽名格式取決於所使用的算法。使用 SEQUENCE 並不是原始值的真正選擇。使用 OCTET STRING ……好吧,我想他們玩得很安全,但是 OCTET STRING 在 99.9% 的情況下也能正常工作,並且在開始時不需要
00
值字節。另一種選擇是打開算法標識符的 OID,然後使用正確的簽名類型。然而,這會使 X.509 證書的解析變得複雜。X.509 證書似乎選擇了不太複雜的選項,即使這可能導致在原始類型中嵌套 ASN.1 結構。
幸運的是,在解析 X.509 證書時還存在足夠多的問題。