如何手动计算和验证证书签名请求的签名 [英] 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
验证该证书-
它包含我生成的密钥对的公钥
- 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
以下是我的疑问:
- 计算签名需要考虑哪些数据字段?
- 我们可以手动创建签名并使用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
中描述的算法和私钥对DER编码的ASN.1格式的certificationRequestInfo
(有关结构详细信息,请参阅RFC)进行签名,以产生签名
.The
certificationRequestInfo
(see RFC for structure details) in DER-encoded ASN.1 format is signed using the algorithm described insignatureAlgorithm
and the private key to yieldsignature
.让我们从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 signedpub.pem
: the CSR requester's public keysig.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 thecertificationRequestInfo
:$ 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屋!
-