如何手动计算和验证证书签名请求的签名 [英] How to manually calculate and verify the signature of a certificate signing request

查看:65
本文介绍了如何手动计算和验证证书签名请求的签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  • 我已经创建了密钥对

openssl genrsa -out test1 2048

  • 然后使用该密钥创建证书签名请求

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

  • 使用 openssl req -in foo.csr -text 验证该证书
    • 它包含我生成的密钥对的公钥

    • verifying that certificate using openssl req -in foo.csr -text
      • It Contains the public key of the keypair i have generated

            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 attributes i have provided while creating the CSR

              Subject: CN=foo
      

    • 数字签名信息

    • Digital Signature Information

      签名算法:sha256WithRSAEncryption92: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

      Signature Algorithm: 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 .

      The data over which the signature is calculated is pretty much everything in the CSR except for the signature algorithm and signature. This is called the certificationRequestInfo in RFC 2986.

      第二个问题:我们如何验证签名?

      The second question: how do we verify the signature?

      简短答案:让 openssl 为您完成.

      到目前为止,最简单的方法是要求 openssl 本身进行验证:

      The easiest way by far is to ask openssl itself to verify it:

      $ 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
      

      完成!

      冗长而乏味的答案:手动完成

      好,所以您真的想手动进行.让我们试一试.

      Ok, so you really want to do it manually. Let's give it a shot.

      鉴于上述,我们首先需要从CSR中提取所需的信息.倾销ASN.1结构,我们得到:

      Given the above, we first need to extract the desired information from the CSR. Dumping the ASN.1 structure, we get:

      $ 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 ::= SEQUENCE {
          certificationRequestInfo CertificationRequestInfo,
          signatureAlgorithm       AlgorithmIdentifier{{ SignatureAlgorithms }},
          signature                BIT STRING
      }
      

      使用 signatureAlgorithm 中描述的算法和私钥对D​​ER编码的ASN.1格式的 certificationRequestInfo (有关结构详细信息,请参阅RFC)进行签名,以产生签名.

      The certificationRequestInfo (see RFC for structure details) in DER-encoded ASN.1 format is signed using the algorithm described in signatureAlgorithm and the private key to yield signature.

      让我们从CSR中提取我们需要的所有部分. strparse 值是您要导出的偏移量,这是上面输出中每行的第一个数字.

      Let's extract all the parts we need from the CSR. The strparse value is the offset you want to export, this is the first number on each line in the output above.

      # 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 仍然很高兴将其写到文件中.

      Ignore the error on the last one, this is because the extracted data is the raw signature bytes, it's not ASN.1 encoded. openssl still happily wrote it out to the file.

      我们现在有以下文件:

      • info.der :已签名的DER编码数据
      • pub.pem :CSR请求者的公钥
      • sig.raw :CSR中包含的签名
      • info.der: the DER-encoded data that was signed
      • pub.pem: the CSR requester's public key
      • sig.raw: the signature included in the CSR

      让我们使用公钥验证RSA签名(因为这就是签名算法所说的内容)并提取原始哈希:

      Let's verify the RSA signature (because that's what the signature algorithm says) using the public key and extract the original hash:

      $ 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
      

      它没有失败,因此我们已经知道公钥是与用于签名数据的私钥匹配的公钥.

      It didn't fail, so we already know the public key is the one that matches the private key used to sign the data.

      最后一部分,长的 OCTET STRING 是由CSR请求者计算出的消息的原始哈希值:

      The last section, the long OCTET STRING is the raw hash of the message as computed by the CSR requester:

      192e0909dabc7454006628aa3f7fb009afa62a17a44908cae5e166e528dcdd11
      


      让我们计算 certificationRequestInfo sha256 哈希(再次:因为签名算法告诉我们):


      Let's compute the sha256 hash (once again: because the signature algorithm tells us to) of the certificationRequestInfo:

      $ sha256sum info.der 
      192e0909dabc7454006628aa3f7fb009afa62a17a44908cae5e166e528dcdd11  info.der
      

      是的!哈希值等于从签名中提取的哈希值.

      Yay! The hash is equal to the one extracted from the signature.

      哈希匹配和签名是由与CSR中列出的公钥相对应的私钥签名的.这是有效的CSR .

      The hashes match and the signature was signed by the private key corresponding to the public key listed in the CSR. This is a valid CSR.

      完成!看,我说那会很乏味.

      Done! See, I said it would be tedious.

      这篇关于如何手动计算和验证证书签名请求的签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆