Содержание

Создание цифровой подписи с помощью RSA в OpenSSL

Цифровая подпись позволяет гарантировать две вещи: авторство (сообщение пришло именно от владельца ключа) и целостность (сообщение не было изменено по пути).

Создадим подпись, проверим ее валидность

Замечание: При шифровании использвется открытый ключ, чтобы данные мог прочитать только владелец закрытого. А при создании подписи всё наоборот: используется закрытый ключ, чтобы любой мог проверить подлинность с помощью открытого ключа.

Вычислим SHA-256 хеш файла message.txt:

❯ openssl dgst -sha256 message.txt

SHA2-256(message.txt)= eb96d1f89812bf4967d9fb4ead128c3b787272b7be21dd2529278db1128d559c

Создадим файл подписи signature.bin, используя закрытый ключ:

openssl dgst -sha256 -sign privatekey.pem -out signature.bin message.txt

Что происходит внутри:

  • Вычисляется хеш файла: h = SHA256(message.txt)
  • Формируется структура DigestInfo в формате asn.1, которая содержит идентификатор алгоритма хеширования и само хеш значение
  • Добавляется паддинг: padded = PKCS#1(digestInfo)
  • Вычисляется подпись: signature = padded^d mod n, где d - закрытая экспонента, n - модуль RSA

Смотрим содержимое файла с подписью:

❯ cat signature.bin | xxd

00000000: 9a1a 483b 2317 d46e 7221 53d5 d9cd 0c52  ..H;#..nr!S....R
00000010: 8b51 1492 df8c 1840 116e 162a 5bcc f8a6  .Q.....@.n.*[...
00000020: d834 64cf 8453 4a70 bad1 164b ddb6 eb42  .4d..SJp...K...B
00000030: 7029 99a3 54f1 70f6 240a d201 c78d 224e  p)..T.p.$....."N
00000040: 7aaa 3a5f 7feb 18c4 0496 9cf7 3028 b60c  z.:_........0(..
00000050: e1af 1600 2444 d960 53e5 1628 0c3b 6b1f  ....$D.`S..(.;k.
00000060: e5d4 00c6 da20 9bed 2924 5ce3 8ce3 d529  ..... ..)$\....)
00000070: 3483 8cf1 9032 c535 cd0a 6d45 ca8b 79ff  4....2.5..mE..y.

Файл signature.bin имеет размер 128 байт, что соответствует 1024-битному RSA-ключу.
По сути, это просто число s = padded^d mod n в big-endian представлении без какой-либо обёртки.

Для проверки подписи получателю нужны: сам файл, файл подписи и открытый ключ:

❯ openssl dgst -sha256 -verify publickey.pem -signature signature.bin message.txt

Verified OK

Если подпись не соответствует файлу, то OpenSSL выдаст ошибку Verification failure.

С помощью открытого ключа “расшифровываем” подпись, чтобы увидеть, что именно было подписано:

❯ openssl pkeyutl -verifyrecover -pubin -inkey publickey.pem -in signature.bin -out recovered.bin

Файл recovered.bin вычисляется как signature.bin^e mod n с учетом паддинга.

Разберем полученный файл как asn.1 структуру:

❯ openssl asn1parse -in recovered.bin -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]:EB96D1F89812BF4967D9FB4EAD128C3B787272B7BE21DD2529278DB1128D559C

Видим, что для подписи использовался алгоритм sha256.
Значение 0xEB96..559C в точности совпадает с хешом файла message.txt.
Значит подпись была выполнена правильно.

Похожее