openSSL 創建了 73 字節的 CSR 簽名大小,但不應該是 70 字節
secp256r1
在使用帶有曲線檢查文件的openSSL創建CSR之後,使用
openssl asn1parse -i -in ecTest.csr
簽名的大小為73字節,為什麼?
我認為簽名的 ASN.1 是
ECDSA-Sig-Value ::= SEQUENCE { r INTEGER, s INTEGER }
為此
secp256r1
,每個都是 32 個字節,這r
意味著s
1+1 + 1+1+32 + 1+1+32 = 70bytes SEQUENCE INTEGER INTEGER
需要“額外”八位字節,因為 ASN.1 根據X.690的第 8.3.3 節對整數使用二進制補碼表示法:
內容八位位組應為等於整數值的二進制補碼
在二進制補碼中,最高位表示負數。由於我們的數字實際上都不是負數,因此正確的符號需要有前導零。
我們可以在以下簽名上看到這一點:
$ openssl asn1parse -i -in foo.csr -strparse 126 -out raw 0:d=0 hl=2 l= 69 cons: SEQUENCE 2:d=1 hl=2 l= 32 prim: INTEGER :1937197C689C3E511CCB830E5F3677D3FA18F045EBA969739B622B95FEB619C1 36:d=1 hl=2 l= 33 prim: INTEGER :BA1B75CEE9714860639A20B50125C20224CBBEBE01F4CCBFA46731706F55D171
您會注意到我的第一個整數的長度為 32,而第二個整數的長度為 33。
轉儲原始內容,我們得到:
$ hd raw 00000000 30 45 02 20 19 37 19 7c 68 9c 3e 51 1c cb 83 0e |0E. .7.|h.>Q....| 00000010 5f 36 77 d3 fa 18 f0 45 eb a9 69 73 9b 62 2b 95 |_6w....E..is.b+.| 00000020 fe b6 19 c1 02 21 00 ba 1b 75 ce e9 71 48 60 63 |.....!...u..qH`c| 00000030 9a 20 b5 01 25 c2 02 24 cb be be 01 f4 cc bf a4 |. ..%..$........| 00000040 67 31 70 6f 55 d1 71 |g1poU.q|
讓我們將其分解為各種組件:
30 45
:SEQUENCE
長度 6902 20
:INTEGER
長度 3219 37 19 7c ... 19 c1
:INTEGER
內容(32字節)02 21
:INTEGER
長度 3300 ba 1b 75 ... d1 71
:INTEGER
內容(33字節)這與
asn1parse
告訴我們的完全相符。注意第一個整數(編碼為 32 字節長度)和第二個整數(編碼為 33 字節長度)之間的差異。第一個以
19
二進制00011001
開頭。因為它沒有設置高位,所以這確實是一個正數。
BA
但是第二個以10111010
二進制開頭。高位被設置,如果我們按原樣解碼它將是負數。由於它不是負數,因此正確的二進制補碼符號具有前導零。在您的情況下,兩個數字都設置了高位,因此它們都被
00
預先設置。您最終的總大小為: $ 2 + 2 + 32+1 + 2 + 32+1 = 72 $ .
糟糕,我們還差一個 73。這是規範
BITSTRING
中定義的編碼的一部分,第 8.6.2.2 節為:初始八位字節應編碼為無符號二進制整數,位 1 作為最低有效位,最後後續八位字節中未使用的位數。該數字應在零到七的範圍內。
這是因為 a
BITSTRING
可以表示不是 8 的倍數的位數。在我們的例子中,我們正在使用所有位,因此位串的初始八位字節是00
.我們現在有了正確的長度: $ 72 + 1 = 73 $ .