![数字签名手动哈希验证](https://linux22.com/image/227799/%E6%95%B0%E5%AD%97%E7%AD%BE%E5%90%8D%E6%89%8B%E5%8A%A8%E5%93%88%E5%B8%8C%E9%AA%8C%E8%AF%81.png)
我正在尝试学习 PKI,我想做一个测试,通过比较哈希值来验证我对数字证书的理解......让我解释一下。
据我通俗地理解,如果我有一个服务器的公共签名数字证书,那么该服务器证书将具有由 CA 创建的数字签名。例如,当我通过 https 浏览该服务器时,我的计算机将通过检查信任链来验证证书。因此,它获取数字证书,对其进行解密(使用 CA 的公钥)并显示哈希值。将此值与已签名数据的哈希值进行比较,如果它们匹配,则证书是由受信任的源签名的。
所以现在我想尝试和模拟的是手动验证我使用 openssl 在计算机上创建的数字签名。因此我做了以下事情:
## Create a key pair
$ openssl genrsa -aes128 -passout pass:Test123 -out private.pem 4096
$ openssl rsa -in private.pem -passin pass:Test123 -pubout -out public.pem
## Create a file as something to sign
$ touch filex
$ echo "some data" > filex
## Sign the file
$ openssl dgst -sha256 -sign private.pem -out data.txt.signature filex
## Verify the signature
$ openssl dgst -sha256 -verify public.pem -signature data.txt.signature filex
Verified OK
所以这证实了我想要的(尽管这里没有 CA)。我想要做的是查看它在解密数字签名时计算出的实际哈希值,这样我就可以在我的“filex”上运行 sha256sum 并比较两者。但我似乎找不到办法做到这一点。谁能帮助我找到实现这一目标的方法?
更新:由于有人发布了之前类似问题的链接,我尝试了该方法,但无法使其工作。因此,我将复制我在下面完成的步骤:
首先,我从我的浏览器中获取了 stackexchange.pem 和 CA 的 E1.pem 文件并下载了它。
$ openssl asn1parse -i -in stackexchange.pem
0:d=0 hl=4 l= 947 cons: SEQUENCE
4:d=1 hl=4 l= 824 cons: SEQUENCE
8:d=2 hl=2 l= 3 cons: cont [ 0 ]
10:d=3 hl=2 l= 1 prim: INTEGER :02
13:d=2 hl=2 l= 18 prim: INTEGER :035FE125AEA1239BD263714150F2D8EE3C0F
33:d=2 hl=2 l= 10 cons: SEQUENCE
35:d=3 hl=2 l= 8 prim: OBJECT :ecdsa-with-SHA384
45:d=2 hl=2 l= 50 cons: SEQUENCE
47:d=3 hl=2 l= 11 cons: SET
49:d=4 hl=2 l= 9 cons: SEQUENCE
51:d=5 hl=2 l= 3 prim: OBJECT :countryName
56:d=5 hl=2 l= 2 prim: PRINTABLESTRING :US
60:d=3 hl=2 l= 22 cons: SET
62:d=4 hl=2 l= 20 cons: SEQUENCE
64:d=5 hl=2 l= 3 prim: OBJECT :organizationName
69:d=5 hl=2 l= 13 prim: PRINTABLESTRING :Let's Encrypt
84:d=3 hl=2 l= 11 cons: SET
86:d=4 hl=2 l= 9 cons: SEQUENCE
88:d=5 hl=2 l= 3 prim: OBJECT :commonName
93:d=5 hl=2 l= 2 prim: PRINTABLESTRING :E1
97:d=2 hl=2 l= 30 cons: SEQUENCE
99:d=3 hl=2 l= 13 prim: UTCTIME :231117014719Z
114:d=3 hl=2 l= 13 prim: UTCTIME :240215014718Z
129:d=2 hl=2 l= 28 cons: SEQUENCE
131:d=3 hl=2 l= 26 cons: SET
133:d=4 hl=2 l= 24 cons: SEQUENCE
135:d=5 hl=2 l= 3 prim: OBJECT :commonName
140:d=5 hl=2 l= 17 prim: PRINTABLESTRING :stackexchange.com
159:d=2 hl=2 l= 89 cons: SEQUENCE
161:d=3 hl=2 l= 19 cons: SEQUENCE
163:d=4 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
172:d=4 hl=2 l= 8 prim: OBJECT :prime256v1
182:d=3 hl=2 l= 66 prim: BIT STRING
250:d=2 hl=4 l= 578 cons: cont [ 3 ]
254:d=3 hl=4 l= 574 cons: SEQUENCE
258:d=4 hl=2 l= 14 cons: SEQUENCE
260:d=5 hl=2 l= 3 prim: OBJECT :X509v3 Key Usage
265:d=5 hl=2 l= 1 prim: BOOLEAN :255
268:d=5 hl=2 l= 4 prim: OCTET STRING [HEX DUMP]:03020780
274:d=4 hl=2 l= 29 cons: SEQUENCE
276:d=5 hl=2 l= 3 prim: OBJECT :X509v3 Extended Key Usage
281:d=5 hl=2 l= 22 prim: OCTET STRING [HEX DUMP]:301406082B0601050507030106082B06010505070302
305:d=4 hl=2 l= 12 cons: SEQUENCE
307:d=5 hl=2 l= 3 prim: OBJECT :X509v3 Basic Constraints
312:d=5 hl=2 l= 1 prim: BOOLEAN :255
315:d=5 hl=2 l= 2 prim: OCTET STRING [HEX DUMP]:3000
319:d=4 hl=2 l= 29 cons: SEQUENCE
321:d=5 hl=2 l= 3 prim: OBJECT :X509v3 Subject Key Identifier
326:d=5 hl=2 l= 22 prim: OCTET STRING [HEX DUMP]:0414ABB9D50E8357BF0921BC299E1B83B6ED2A1BB326
350:d=4 hl=2 l= 31 cons: SEQUENCE
352:d=5 hl=2 l= 3 prim: OBJECT :X509v3 Authority Key Identifier
357:d=5 hl=2 l= 24 prim: OCTET STRING [HEX DUMP]:301680145AF3ED2BFC36C23779B95230EA546FCF55CB2EAC
383:d=4 hl=2 l= 85 cons: SEQUENCE
385:d=5 hl=2 l= 8 prim: OBJECT :Authority Information Access
395:d=5 hl=2 l= 73 prim: OCTET STRING [HEX DUMP]:3047302106082B060105050730018615687474703A2F2F65312E6F2E6C656E63722E6F7267302206082B060105050730028616687474703A2F2F65312E692E6C656E63722E6F72672F
470:d=4 hl=2 l= 75 cons: SEQUENCE
472:d=5 hl=2 l= 3 prim: OBJECT :X509v3 Subject Alternative Name
477:d=5 hl=2 l= 68 prim: OCTET STRING [HEX DUMP]:304282182A2E6D6574612E737461636B65786368616E67652E636F6D82132A2E737461636B65786368616E67652E636F6D8211737461636B65786368616E67652E636F6D
547:d=4 hl=2 l= 19 cons: SEQUENCE
549:d=5 hl=2 l= 3 prim: OBJECT :X509v3 Certificate Policies
554:d=5 hl=2 l= 12 prim: OCTET STRING [HEX DUMP]:300A3008060667810C010201
568:d=4 hl=4 l= 260 cons: SEQUENCE
572:d=5 hl=2 l= 10 prim: OBJECT :CT Precertificate SCTs
584:d=5 hl=3 l= 245 prim: OCTET STRING [HEX DUMP]:0481F200F000770048B0E36BDAA647340FE56A02FA9D30EB1C5201CB56DD2C81D9BBBFAB39D884730000018BDB2CF9BB0000040300483046022100D3057AB69D47FA324E26A59D5210029843F17CA8034FD70045A2F6514098434B022100A693797A5A0EE660AC1C4D904079FC367F921826980340F6ED9C5D580C63CFC7007500EECDD064D5DB1ACEC55CB79DB4CD13A23287467CBCECDEC351485946711FB59B0000018BDB2CF9D1000004030046304402206044A6FAE9C47837ABA50300BFC5C2EBBD33705697EB5C7DB40BDAAC4638E16D02205EB94A42B09FFDE5277C7A2B02BCA288EA859E114B71B4C41D022CC3FFB6D427
832:d=1 hl=2 l= 10 cons: SEQUENCE
834:d=2 hl=2 l= 8 prim: OBJECT :ecdsa-with-SHA384
844:d=1 hl=2 l= 105 prim: BIT STRING
我的标记是 4 和 844(844 之后 = sig)
抓取要签名的数据,并以二进制形式留下
$ openssl asn1parse -in stackexchange.pem -strparse 4 -out stackexchange.tbs
获取数字签名
$ openssl asn1parse -in stackexchange.pem -strparse 844 -out stackexchange.sig
从 CA 的 pem 文件中获取公钥
$openssl x509 -in E1.pem -noout -pubkey > e1.pub
检查输出
$ openssl pkey -in e1.pub -pubin -text
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEJFwtoir9HEumXZdzJzGssqBpYu9l6Kaw
8KxLn/8cC3AP05gvTfwPAJs38HQFVzKXLgXvKkMlo/tuNCcT9k9+adMCmV7rJEeS
wSSb5rEhj8EkgfxozB9pulj1GSL3dMYW
-----END PUBLIC KEY-----
Public-Key: (384 bit)
pub:
04:24:5c:2d:a2:2a:fd:1c:4b:a6:5d:97:73:27:31:
ac:b2:a0:69:62:ef:65:e8:a6:b0:f0:ac:4b:9f:ff:
1c:0b:70:0f:d3:98:2f:4d:fc:0f:00:9b:37:f0:74:
05:57:32:97:2e:05:ef:2a:43:25:a3:fb:6e:34:27:
13:f6:4f:7e:69:d3:02:99:5e:eb:24:47:92:c1:24:
9b:e6:b1:21:8f:c1:24:81:fc:68:cc:1f:69:ba:58:
f5:19:22:f7:74:c6:16
ASN1 OID: secp384r1
NIST CURVE: P-384
将要签名的字段哈希为二进制文件
$ openssl sha384 <stackexchange.tbs -binary >hash
现在执行手动验证
$ openssl pkeyutl -verify -in hash -sigfile stackexchange.sig -inkey e1.pub -pubin -pkeyopt digest:sha384
Signature Verified Successfully
啊糟糕,当我尝试编辑这篇文章并更新有关戴夫链接的方法不起作用时,我意识到我在实现它时犯了一个错误。因此,在编辑这篇文章时,我实际上已经给出了我想要的确切答案,而不是此更新的问题,因为我现在看到它验证成功。
我仍然想了解为什么@u1686_grawity 认为解密不参与验证,因为我愿意接受建议。然而,我的更新显示我手动对证书的所有待签名字段进行哈希处理,并将其哈希到名为“hash”的文件中,然后获取 E1.pem 的公共证书(原始证书的 CA) pem 文件)使用它作为解密密钥作为输入,并针对 .sig 文件运行它。由于我的哈希结果和解密的哈希值匹配,这意味着我从原始 pem 文件中提取的签名绝对经过 CA 验证并且是真实的。所以我很困惑为什么 u1686_grawity 和互联网上的许多其他人相信没有解密发生......