Цифровая подпись

Асимметрию можно использовать наоборот: подписать сообщение закрытым ключом, чтобы все убедились в авторстве.

Шифрование наоборот

При шифровании Алиса берёт открытый ключ Боба. А что если применить закрытый ключ? Тогда расшифровать сможет любой — ведь открытый ключ известен всем. Скрыть содержимое так нельзя, но появляется кое-что другое: доказательство, что сообщение создал именно владелец закрытого ключа. Это и есть цифровая подпись.

Что подтверждает подпись

  • Подлинность: сообщение действительно от заявленного автора.
  • Целостность: сообщение не изменили после подписи.
  • Неотказуемость: автор не сможет отрицать, что подписал.

Как это работает на практике

Подписывают не само сообщение целиком, а его хеш — так быстрее и удобнее. Схема такая:

  1. Алиса считает хеш сообщения.
  2. Шифрует хеш своим закрытым ключом — это и есть подпись.
  3. Боб берёт открытый ключ Алисы, проверяет подпись и сравнивает с хешем полученного сообщения.

Игрушечная подпись на Python

Сделаем мини-подпись на маленьком RSA. «Подпишем» хеш сообщения закрытым ключом и проверим открытым:

import hashlib

# мини-ключи RSA
n, e, d = 3233, 17, 2753

message = "Я согласен на сделку"
# короткий числовой хеш сообщения (для демонстрации)
h = int(hashlib.sha256(message.encode()).hexdigest(), 16) % n

signature = pow(h, d, n)          # подпись = хеш в степени d (закрытый ключ)
check = pow(signature, e, n)      # проверка степенью e (открытый ключ)

print("Хеш сообщения:", h)
print("Подпись:", signature)
print("Подпись верна:", check == h)

Вывод:

Хеш сообщения: 1990
Подпись: 2784
Подпись верна: True

Что будет при подделке

Если кто-то изменит сообщение, его хеш поменяется, и проверка подписи провалится:

import hashlib
n, e, d = 3233, 17, 2753

msg = "Я согласен на сделку"
h = int(hashlib.sha256(msg.encode()).hexdigest(), 16) % n
signature = pow(h, d, n)

# враг подменил сообщение
fake = "Я согласен на ДВЕ сделки"
h_fake = int(hashlib.sha256(fake.encode()).hexdigest(), 16) % n

print("Проверка против подделки:", pow(signature, e, n) == h_fake)

Вывод:

Проверка против подделки: False

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

Проверьте себя
1. Каким ключом создаётся цифровая подпись?
AОткрытым ключом получателя
BЗакрытым ключом автора
CОбщим симметричным ключом
DСлучайным ключом без пары
2. Что произойдёт с цифровой подписью, если изменить сообщение после подписания?
AНичего, подпись останется верной
BХеш изменится и проверка подписи провалится
CПодпись автоматически обновится
DСообщение нельзя будет открыть
Поддержать проект