簡體   English   中英

如何手動計算和驗證證書簽名請求的簽名

[英]How to manually calculate and verify the signature of a certificate signing request

  • 我創建了一個密鑰對

openssl genrsa -out test1 2048

  • 然后使用該密鑰創建證書簽名請求

openssl req -new -key test1 -subj "/CN=foo" -out foo.csr

  • 使用openssl req -in foo.csr -text驗證該證書
    • 它包含我生成的密鑰對的公鑰

       Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:ca:c5:29:98:08:05:30:30:03:08:eb:23:c2:af: 3e:2e:2d:dc:11:96:cb:2f:d1:1f:7f:41:a4:00:13: 8a:ee:4b:36:5b:f2:c1:d1:0f:8b:27:11:34:08:bd: 4d:df:7e:6d:7a:d7:f9:dd:ea:62:ad:fa:8f:8c:eb: 47:5f:55:82:2c:13:c2:11:41:12:b9:87:0b:3d:08: 86:1b:ad:71:16:89:1c:fa:07:4a:86:8f:80:a9:99: 37:f7:e2:d4:d3:d8:b2:5f:7f:c9:05:51:73:f0:c8: 59:ec:c3:09:a2:03:a5:6e:ec:8b:d9:9c:11:de:d3: df:55:a5:3f:0c:36:d6:93:8a:70:a0:b9:61:cd:c9: 4a:09:ad:f7:3e:fd:ce:6f:5c:bb:00:69:e9:3b:3d: 85:3b:01:1d:8f:6a:a7:d4:61:f9:b5:07:1e:90:ed: ab:3b:41:cc:db:e8:a0:e7:88:b7:77:35:66:30:b7: a6:cd:ea:d6:12:f5:ef:82:63:e9:46:29:2e:7c:10: 0e:32:fd:04:2d:cd:62:0e:4b:74:46:f7:fd:f6:4a: 8d:fb:82:9d:37:11:50:ea:9f:f0:d6:64:2b:50:a4: f0:18:6e:81:28:11:04:db:2a:0a:f7:b1:70:c5:78: fe:ed:e3:55:2c:64:f4:a5:a0:96:f5:11:3a:27:2c: 5a:51 Exponent: 65537 (0x10001)
    • 我在創建 CSR 時提供的主題屬性

       Subject: CN=foo
    • 數字簽名信息

      簽名算法:sha256WithRSAEncryption 92:b0:82:a5:aa:98:4a:62:5a:84:8a:15:5c:6f:48:dc:e3:ec: 7f:d5:04:e8:c1: 47:55:3c:b3:57:84:16:ff:5a:0d:29:2c:16: f2:cc:0c:18:c3:1f:d5:e1:57:3a:dd:8b: b1:c6:92:c3:fe:cb: 2b:9d:7d:79:d5:64:eb:31:00:8b:5e:77:48:ce:66:6f:dd:7b: 71: 41:f9:aa:6e:ea:ea:59:e0:cd:f8:db:a9:13:18:d2:2a:fc: 12:25:b3:01:44:0c:b1:02: f7:1a:0f:d0:07:04:1d:9f:6f:a1: 58:91:87:25:4a:d6:47:a6:b5:4e:3c:a1:fd:b6:6c: c3:96:16: c1:ab:00:d2:4c:95:ee:2c:01:2d:cf:0e:d0:62:1b:4f:0e:34: e3:e8:85:50: 63:74:eb:1f:ac:95:30:d4:df:43:7f:58:11:90: 35:29:9d:85:94:dc:c8:c2:29:81:46: 71:20:62:9c:9c:f8:ef: ed:bc:8b:e3:d5:41:b3:14:f7:43:c6:b2:74:c2:22:06:a2:af: 88:68:2e:67:c4:de:ed:61:37:41:d6:df:8a:76:7d:42:5d:98:d3:c9:19:8b:1d:26:73: 92:95:0f:ba:c1:78:3a:55:87:e0:3e: 16:13:34:6e:21:13:b9:da:b8:66:f3:0a:ec:79: ae:1a:95:6c: 04:cf:b8:b5

以下是我的疑惑:

  1. 它考慮了計算簽名的所有數據字段是什么?
  2. 我們可以手動創建簽名並使用 CSR 中提到的簽名進行驗證嗎?

用於計算簽名的數據幾乎是 CSR 中除簽名算法和簽名之外的所有內容。 這在RFC 2986 中稱為certificationRequestInfo

第二個問題:我們如何驗證簽名?

簡短的回答:讓openssl為你做這件事。

到目前為止,最簡單的方法是要求openssl本身來驗證它:

$ openssl genrsa -out test.key 2048
$ openssl req -new -key test.key -subj "/CN=foo" -out foo.csr
$ openssl req -in foo.csr -verify -noout
verify OK

完畢!


冗長(且乏味)的答案:手動完成

好的,所以你真的想手動完成。 讓我們試一試。

鑒於上述情況,我們首先需要從 CSR 中提取所需的信息。 轉儲 ASN.1 結構,我們得到:

$ openssl asn1parse -i -in foo.csr 
    0:d=0  hl=4 l= 595 cons: SEQUENCE          
    4:d=1  hl=4 l= 315 cons:  SEQUENCE          
    8:d=2  hl=2 l=   1 prim:   INTEGER           :00
   11:d=2  hl=2 l=  14 cons:   SEQUENCE          
   13:d=3  hl=2 l=  12 cons:    SET               
   15:d=4  hl=2 l=  10 cons:     SEQUENCE          
   17:d=5  hl=2 l=   3 prim:      OBJECT            :commonName
   22:d=5  hl=2 l=   3 prim:      UTF8STRING        :foo
   27:d=2  hl=4 l= 290 cons:   SEQUENCE          
   31:d=3  hl=2 l=  13 cons:    SEQUENCE          
   33:d=4  hl=2 l=   9 prim:     OBJECT            :rsaEncryption
   44:d=4  hl=2 l=   0 prim:     NULL              
   46:d=3  hl=4 l= 271 prim:    BIT STRING        
  321:d=2  hl=2 l=   0 cons:   cont [ 0 ]        
  323:d=1  hl=2 l=  13 cons:  SEQUENCE          
  325:d=2  hl=2 l=   9 prim:   OBJECT            :sha256WithRSAEncryption
  336:d=2  hl=2 l=   0 prim:   NULL              
  338:d=1  hl=4 l= 257 prim:  BIT STRING        

這是RFC 2986定義的結構化 CertificationRequest 為:

CertificationRequest ::= SEQUENCE {
    certificationRequestInfo CertificationRequestInfo,
    signatureAlgorithm       AlgorithmIdentifier{{ SignatureAlgorithms }},
    signature                BIT STRING
}

DER 編碼的 ASN.1 格式的certificationRequestInfo (結構細節參見RFC)使用signatureAlgorithm描述的算法和產生signature的私鑰進行signature


讓我們從 CSR 中提取我們需要的所有部分。 strparse值是您要導出的偏移量,這是上面輸出中每行的第一個數字。

# Extract the certificationRequestInfo (data to be signed)
$ openssl asn1parse -in foo.csr -strparse 4 -out info.der

# Extract the public key.
$ openssl req -pubkey -in foo.csr -noout -out pub.pem

# Alternatively, you can use:
$ openssl asn1parse -in foo.csr -strparse 27 -out tmp.der
$ openssl rsa -pubin -inform DER -in tmp.der -out pub.pem

# Extract the raw signature bytes:
$ openssl asn1parse -in foo.csr -strparse 338 -out sig.raw
    0:d=0  hl=2 l=  70 cons: cont [ 3 ]        
Error in encoding
139935063934272:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:../crypto/asn1/asn1_lib.c:91:

忽略最后一個的錯誤,這是因為提取的數據是原始簽名字節,不是 ASN.1 編碼的。 openssl仍然很高興地將它寫到文件中。

我們現在有以下文件:

  • info.der :已簽名的 DER 編碼數據
  • pub.pem : CSR 請求者的公鑰
  • sig.raw : CSR 中包含的簽名

讓我們使用公鑰驗證 RSA 簽名(因為這就是簽名算法所說的)並提取原始哈希:

$ openssl rsautl -verify -pubin -inkey pub.pem -in sig.raw -out hash.der
$ openssl asn1parse -i -in hash.der -inform DER
    0:d=0  hl=2 l=  49 cons: SEQUENCE          
    2:d=1  hl=2 l=  13 cons:  SEQUENCE          
    4:d=2  hl=2 l=   9 prim:   OBJECT            :sha256
   15:d=2  hl=2 l=   0 prim:   NULL              
   17:d=1  hl=2 l=  32 prim:  OCTET STRING      [HEX DUMP]:192E0909DABC7454006628AA3F7FB009AFA62A17A44908CAE5E166E528DCDD11

它沒有失敗,所以我們已經知道公鑰是與用於簽署數據的私鑰相匹配的公鑰。

最后一部分,長OCTET STRING是 CSR 請求者計算的消息的原始散列:

192e0909dabc7454006628aa3f7fb009afa62a17a44908cae5e166e528dcdd11

讓我們計算certificationRequestInfosha256哈希(再一次:因為簽名算法告訴我們):

$ sha256sum info.der 
192e0909dabc7454006628aa3f7fb009afa62a17a44908cae5e166e528dcdd11  info.der

好極了! 哈希值等於從簽名中提取的哈希值。


散列匹配並且簽名由與 CSR 中列出的公鑰對應的私鑰簽名。 這是一個有效的 CSR

完畢! 看,我說那會很乏味。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM