Как вычислить хэш подписи PDF? - PullRequest
0 голосов
/ 25 января 2019

Этот вопрос относится к этому одному, но немного более конкретно. Я подозреваю, что неправильно вычисляю хеш моего pdf.

Я бы хотел вычислить хеш SHA256 для подписанного PDF.

Согласно PDF32000 Я должен:

  1. Получить \ByteRange значения
  2. Объединить два куска
  3. Вычислить 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

Я проверил, что я не включаю символы < и >:

$ 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, поэтому после проверки этого дайджеста я получаю другой хэш, чем тот, который я вычислил.

Мой /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

Таким образом, из PDF32000 с adbe.pkcs7.detached и PDF 1.6 HASH должен быть SHA256, который совместим с тем, что я нашел в PKCS7.

Просто для справки, хэш, который я получаю из подписи:

#!/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

Вы можете получить доступ к тестовому файлу PDF dummy-signed.pdf из моего списка

curl https://gist.githubusercontent.com/nowox/94dd54e484df877e1232c18bd7b91c97/raw/d249f3757137e9b665e895c900f08b1156f1bc4f/dummy-signed.pdf.base64 | base64 --decode > dummy-signed.pdf

1 Ответ

0 голосов
/ 28 января 2019

Короче

Вы пытаетесь извлечь неправильное хеш-значение из контейнера подписи.

Подробно

Я не сделал 'Я не могу понять это раньше, потому что я не эксперт по openssl.Однако, проанализировав пример PDF, причина путаницы стала ясна.

В контейнере сигнатур PKCS # 7 / CMS обычно есть (как минимум) два значения хеш-функциипроценты:

  • значение хеша данных подписанного документа в messageDigest подписанном атрибуте и
  • значение хеша подписанных атрибутов (в случае старой схемы подписи RSA)в зашифрованных байтах подписи.

Атрибут со знаком messageDigest в контейнере подписи в вашем примере документа выглядит следующим образом (внешний вид может отличаться, если вы используете asn1-dump в openssl, но, тем не менее, значение должно быть распознаваемым):

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                            
         : . . . . . . . . }
         : . . . . . . . }
         : . . . . . . }

Как вы можете распознать, этот атрибут содержит вычисленное вами значение хеш-функции.

С другой стороны, вы пытаетесь извлечь подписанное значение хеш-функции из расшифрованных байтов подписи, не хэш документа, но вместо этого хэш подписанных атрибутов!

Кроме того, что-то идет не так, как надоНа этом этапе извлечения вы должны получить значение

AB86B27177E388A1EE69A5C7479D74621E84473E0CAB5C647471B724FEFCE826

, а не

2a3f629f7bdce750321da7f219ec5759dc9ed14818acbd3cd0b6092d5371c03a

, которое вы получили.

...