问题描述
此问题与此一个,但更具体一些.我怀疑我没有正确计算pdf的哈希值.
This question is related to this one, but a bit more specific. I am suspecting I am not computing the hash of my pdf properly.
我想计算签名PDF的SHA256哈希值.
I would like to compute the SHA256 hash of a signed PDF.
根据 PDF32000 我应该:
- 获取
\ByteRange
值 - 连接两个块
- 计算SHA256
这是我所做的:
$ grep -aPo 'ByteRange\[\s*(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s*\]' dummy-signed.pdf
ByteRange[ 0 59718 72772 5058]
$ dd if=dummy-signed.pdf of=head.bin bs=1 skip=0 count=59718
59718 bytes (60 kB, 58 KiB) copied, 0.630196 s, 94.8 kB/s
$ dd if=dummy-signed.pdf of=tail.bin bs=1 skip=72772 count=5058
5058 bytes (5.1 kB, 4.9 KiB) copied, 0.064317 s, 78.6 kB/s
$ cat head.bin tail.bin > whole.bin
$ sha256sum whole.bin
04b69f55f12fa5cc7923f4307154f2702efde43b32e4a8d9dbb0507a56fcecd3 whole.bin
我检查了是否不包含<
和>
字符:
I checked that I am not including the <
and >
chars:
$ hexdump -C head.bin | tail -n3
0000e930 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 43 6f | /Co|
0000e940 6e 74 65 6e 74 73 |ntents|
0000e946
$ hexdump -C tail.bin | head -n3
00000000 2f 46 69 6c 74 65 72 2f 41 64 6f 62 65 2e 50 50 |/Filter/Adobe.PP|
00000010 4b 4c 69 74 65 2f 4d 28 44 3a 32 30 31 39 30 31 |KLite/M(D:201901|
00000020 32 38 31 33 34 30 35 38 2b 30 31 27 30 30 27 29 |28134058+01'00')|
不幸的是,似乎我的签名是错误的,但是在解码PKCS7
签名后,我再次检查了哈希是sha256WithRSAEncryption
,所以在验证了摘要之后,我得到的是另一个哈希,而不是我计算的哈希.
Unfortunately it seems my signature is wrong, but after decoding the PKCS7
signature I double checked the hash is sha256WithRSAEncryption
, so after verifying this digest I get another hash than the one I computed.
我的/SubFilter
是:
$ grep -aPo '/SubFilter.*?(?=>)' dummy-signed.pdf
/SubFilter/adbe.pkcs7.detached/Type/Sig
我的PDF版本是:
$ grep -aPo '%PDF-\d.\d' dummy-signed.pdf
%PDF-1.6
因此,从带有adbe.pkcs7.detached
和PDF 1.6
的PDF32000中,哈希值应为SHA256,它与PKCS7中的值兼容.
So from PDF32000 with adbe.pkcs7.detached
and PDF 1.6
the HASH should be SHA256 which is compatible with what I found in the PKCS7.
仅作记录,我从签名中得到的哈希值是:
Just for the record, the hash I get from the signature is:
#!/bin/bash
PKCS7='out.pkcs7'
# Extract Digest (SHA256)
OFFSET=$(openssl asn1parse -inform der -in $PKCS7 | \
perl -ne 'print $1 + $2 if /(\d+):d=\d\s+hl=(\d).*?256 prim.*HEX DUMP/m')
dd if=$PKCS7 of=signed-sha256.bin bs=1 skip=$OFFSET count=256
# Extract Public key
openssl pkcs7 -print_certs -inform der -in $PKCS7 | \
tac | sed '/-----BEGIN/q' | tac > client.pem
openssl x509 -in client.pem -pubkey -noout > client.pub.pem
# Verify the signature
openssl rsautl -verify -pubin -inkey client.pub.pem < signed-sha256.bin > verified.bin
# Get Hash and compare with the computed hash from the PDF
openssl asn1parse -inform der -in verified.bin | grep -Po '\[HEX DUMP\]:\K\w+$' | tr A-F a-f
$ ./verify-signature.sh
256+0 records in
256+0 records out
256 bytes copied, 0.029548 s, 8.7 kB/s
2a3f629f7bdce750321da7f219ec5759dc9ed14818acbd3cd0b6092d5371c03a
您可以从我的
curl https://gist.githubusercontent.com/nowox/94dd54e484df877e1232c18bd7b91c97/raw/d249f3757137e9b665e895c900f08b1156f1bc4f/dummy-signed.pdf.base64 | base64 --decode > dummy-signed.pdf
推荐答案
简而言之
您尝试从签名容器中提取错误的哈希值.
我之前并不了解这一点,因为我实际上不是opensl专家.通过分析示例PDF,混乱的原因变得很清楚.
在PKCS#7/CMS签名容器中,通常(至少)有两个感兴趣的哈希值:
In a PKCS#7 / CMS signature container there usually are (at least) two hash values of interest:
-
messageDigest
signed属性和 中已签名文档数据的哈希值 - 加密的签名字节中已签名属性的散列值(如果使用旧的RSA签名方案,则为散列值).
- the hash value of the signed document data in the
messageDigest
signed attribute and - the hash value of the signed attributes (in case of the old RSA signing scheme) in the encrypted signature bytes.
示例文档中签名容器中的messageDigest
签名属性看起来像这样(如果您在openssl中将asn1-dump转储,外观可能会有所不同,但该值仍应可识别):
The messageDigest
signed attribute in the signature container in your example document looks like this (appearances might differ if you asn1-dump in openssl but the value should be recognizable nonetheless):
5306 47: . . . . . . SEQUENCE {
<06 09>
5308 9: . . . . . . . OBJECT IDENTIFIER messageDigest (1 2 840 113549 1 9 4)
: . . . . . . . . (PKCS #9)
<31 22>
5319 34: . . . . . . . SET {
<04 20>
5321 32: . . . . . . . . OCTET STRING
: . . . . . . . . . 04 B6 9F 55 F1 2F A5 CC ...U./..
: . . . . . . . . . 79 23 F4 30 71 54 F2 70 y#.0qT.p
: . . . . . . . . . 2E FD E4 3B 32 E4 A8 D9 ...;2...
: . . . . . . . . . DB B0 50 7A 56 FC EC D3
: . . . . . . . . }
: . . . . . . . }
: . . . . . . }
您可以识别,该属性包含您计算出的哈希值.
As you can recognize, this attribute contains the hash value you calculated.
另一方面,您尝试从解密的签名字节中提取签名的哈希值,这不是文档的哈希,而是文档属性的哈希!
You on the other hand try to extract the signed hash value from the decrypted signature bytes which is not the hash of the document but instead the hash of the signed attributes!
另外,在该提取步骤中似乎出现了问题,您应该获取的值是
Additionally something appears to go wrong in that extraction step, the value you should retrieve is
AB86B27177E388A1EE69A5C7479D74621E84473E0CAB5C647471B724FEFCE826
而不是
2a3f629f7bdce750321da7f219ec5759dc9ed14818acbd3cd0b6092d5371c03a
你得到了.
这篇关于如何计算PDF签名哈希?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!