Openssl

openSSL 創建了 73 字節的 CSR 簽名大小,但不應該是 70 字節

  • September 16, 2020

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長度 69
  • 02 20:INTEGER長度 32
  • 19 37 19 7c ... 19 c1INTEGER內容(32字節)
  • 02 21:INTEGER長度 33
  • 00 ba 1b 75 ... d1 71INTEGER內容(33字節)

這與asn1parse告訴我們的完全相符。注意第一個整數(編碼為 32 字節長度)和第二個整數(編碼為 33 字節長度)之間的差異。

第一個以19二進制00011001開頭。因為它沒有設置高位,所以這確實是一個正數。

BA但是第二個以10111010二進制開頭。高位被設置,如果我們按原樣解碼它將是負數。由於它不是負數,因此正確的二進制補碼符號具有前導零。

在您的情況下,兩個數字都設置了高位,因此它們都被00預先設置。

您最終的總大小為: $ 2 + 2 + 32+1 + 2 + 32+1 = 72 $ .

糟糕,我們還差一個 73。這是規範BITSTRING中定義的編碼的一部分,第 8.6.2.2 節為:

初始八位字節應編碼為無符號二進制整數,位 1 作為最低有效位,最後後續八位字節中未使用的位數。該數字應在零到七的範圍內。

這是因為 aBITSTRING可以表示不是 8 的倍數的位數。在我們的例子中,我們正在使用所有位,因此位串的初始八位字節是00.

我們現在有了正確的長度: $ 72 + 1 = 73 $ .

引用自:https://crypto.stackexchange.com/questions/83976