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

1 Создание цифровой подписи с помощью RSA
Цифровая подпись позволяет гарантировать две вещи: авторство (сообщение пришло именно от владельца ключа) и целостность (сообщение не было изменено по пути).
Создадим подпись, проверим ее валидность
Замечание: При шифровании использвется открытый ключ, чтобы данные мог прочитать только владелец закрытого. А при создании подписи всё наоборот: используется закрытый ключ, чтобы любой мог проверить подлинность с помощью открытого ключа.
2 Создание цифровой подписи
Вычислим 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
3 Анализ файла подписи
Смотрим содержимое файла с подписью:
❯ 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 представлении без какой-либо обёртки.
4 Проверка подлинности
Для проверки подписи получателю нужны: сам файл, файл подписи и открытый ключ:
❯ openssl dgst -sha256 -verify publickey.pem -signature signature.bin message.txt
Verified OK
Если подпись не соответствует файлу, то OpenSSL выдаст ошибку Verification failure.
5 Подпись “изнутри”
С помощью открытого ключа “расшифровываем” подпись, чтобы увидеть, что именно было подписано:
❯ 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.
Значит подпись была выполнена правильно.







