Ответ
В Python криптографическая подпись реализуется по-разному в зависимости от задачи: для симметричной аутентификации (проверка целостности и автора с общим ключом) используется HMAC, а для асимметричной (цифровая подпись с парой ключей) — алгоритмы вроде RSA или ECDSA.
1. HMAC (Hash-based Message Authentication Code)
Используется, когда обе стороны имеют общий секретный ключ. Гарантирует, что сообщение не было изменено и было отправлено владельцем ключа. Реализуется через модуль hmac.
Пример с hmac и hashlib:
import hmac
import hashlib
# Общий секретный ключ (должен быть известен только отправителю и получателю)
secret_key = b'my-super-secret-key'
message = b'This is the message to sign.'
# Создание подписи
signature = hmac.new(secret_key, message, hashlib.sha256).hexdigest()
print(f"Сообщение: {message.decode()}")
print(f"HMAC-SHA256 подпись: {signature}")
# Проверка подписи на стороне получателя
# Получатель генерирует подпись с тем же ключом и сравнивает
# hmac.compare_digest используется для безопасного сравнения строк
# во избежание атак по времени
received_signature = signature
is_valid = hmac.compare_digest(
hmac.new(secret_key, message, hashlib.sha256).hexdigest(),
received_signature
)
print(f"Подпись верна: {is_valid}")
2. Цифровая подпись (RSA)
Используется асимметричное шифрование (приватный и публичный ключи). Отправитель подписывает данные своим приватным ключом, а любой получатель может проверить подпись с помощью публичного ключа отправителя. Это доказывает авторство и целостность.
Для этого используется библиотека cryptography.
Пример с cryptography:
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from cryptography.exceptions import InvalidSignature
# 1. Генерация пары ключей (в реальном приложении ключи хранятся, а не генерируются каждый раз)
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048
)
public_key = private_key.public_key()
message = b"This is a message for digital signature."
# 2. Подпись сообщения приватным ключом
signature = private_key.sign(
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
# 3. Проверка подписи публичным ключом
try:
public_key.verify(
signature,
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print("Цифровая подпись верна.")
except InvalidSignature:
print("Ошибка: цифровая подпись недействительна!")
Ключевые различия:
- HMAC: Нужен общий секрет. Быстрее. Цель — аутентификация и целостность.
- RSA/ECDSA: Используется пара ключей. Медленнее. Цель — авторство, целостность и неотказуемость (non-repudiation).