Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое подпись в криптографии?
Цифровая подпись (digital signature) — это криптографический механизм, который гарантирует подлинность и неизменяемость данных, а также неотрекаемость автора. Подпись подтверждает, что сообщение было отправлено конкретным лицом и не было изменено в пути.
Как это работает
Цифровая подпись основана на асимметричной криптографии (public-key cryptography) с использованием пары ключей:
- Приватный ключ (Private Key) — секретный ключ, известный только владельцу
- Открытый ключ (Public Key) — доступный всем, используется для проверки подписи
Процесс подписания
1. Отправитель берёт сообщение
2. Создаёт хеш сообщения
3. Шифрует хеш своим приватным ключом → получает подпись
4. Отправляет сообщение + подпись
Процесс проверки
1. Получатель берёт подпись и расшифровывает её открытым ключом отправителя
2. Получает хеш из подписи
3. Вычисляет хеш от полученного сообщения
4. Сравнивает оба хеша
5. Если совпадают → подпись валидна, сообщение не изменено
Алгоритмы цифровой подписи
RSA (Rivest-Shamir-Adleman)
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.backends import default_backend
# Генерируем пару ключей
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()
# Подписываем сообщение
message = b"Hello, World!"
signature = private_key.sign(
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
# Проверяем подпись
try:
public_key.verify(
signature,
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print("Подпись валидна!")
except Exception as e:
print(f"Ошибка проверки: {e}")
ECDSA (Elliptic Curve Digital Signature Algorithm)
Большинство современных приложений используют ECDSA — более эффективный алгоритм:
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import hashes
# Генерируем пару ключей
private_key = ec.generate_private_key(
ec.SECP256R1() # Стандартная кривая (используется в Bitcoin, TLS)
)
public_key = private_key.public_key()
# Подписываем
message = b"Secret message"
signature = private_key.sign(
message,
ec.ECDSA(hashes.SHA256())
)
# Проверяем
try:
public_key.verify(signature, message, ec.ECDSA(hashes.SHA256()))
print("ECDSA подпись валидна!")
except Exception:
print("Неверная подпись")
Практический пример: подписание файла
import os
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding
class FileSigner:
def __init__(self, key_size=2048):
self.private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=key_size,
backend=default_backend()
)
self.public_key = self.private_key.public_key()
def sign_file(self, filepath: str) -> bytes:
"""Подписать файл"""
with open(filepath, 'rb') as f:
data = f.read()
signature = self.private_key.sign(
data,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
return signature
def verify_file(self, filepath: str, signature: bytes) -> bool:
"""Проверить подпись файла"""
with open(filepath, 'rb') as f:
data = f.read()
try:
self.public_key.verify(
signature,
data,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
return True
except Exception:
return False
def export_public_key(self) -> bytes:
"""Экспортировать открытый ключ"""
return self.public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
# Использование
signer = FileSigner()
# Подписываем файл
signature = signer.sign_file('document.txt')
# Проверяем подпись
if signer.verify_file('document.txt', signature):
print("Документ не изменён")
else:
print("Документ подделан!")
# Экспортируем открытый ключ для отправки
public_key_pem = signer.export_public_key()
Отличие от хеширования
| Операция | Хеш | Подпись |
|---|---|---|
| Ключи | Не требуются | Приватный и открытый ключ |
| Направление | Однонаправленное | Двусторонняя проверка |
| Аутентификация | Нет | Да (доказывает автора) |
| Неотрекаемость | Нет | Да (автор не может отрицать) |
| Пример | SHA256(message) | RSA_sign(message, private_key) |
Реальные примеры использования
- Email подписи (PGP, S/MIME) — подтверждение автора письма
- Цифровые сертификаты (SSL/TLS) — безопасность веб-сайтов
- Блокчейн (Bitcoin, Ethereum) — подпись транзакций
- Обновления ПО — проверка подлинности обновлений
- Юридические документы — электронная подпись
- API аутентификация — подпись запросов к API
Безопасность приватного ключа
from cryptography.hazmat.primitives import serialization
# Сохранить приватный ключ с паролем
encrypted_pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.BestAvailableEncryption(b"password123")
)
# Загрузить приватный ключ
loaded_private_key = serialization.load_pem_private_key(
encrypted_pem,
password=b"password123",
backend=default_backend()
)
Важные принципы
- Приватный ключ остаётся в секрете — если украден, подпись недействительна
- Открытый ключ распространяется свободно — используется для проверки
- Подпись привязана к сообщению — изменение символа → неверная подпись
- Невозможно подделать без приватного ключа — это математический факт
- Не зависит от секретного канала — подпись валидна по открытым каналам
Вывод: Цифровая подпись — это фундаментальный инструмент криптографии, обеспечивающий аутентификацию, целостность и неотрекаемость в цифровом мире. Без подписей невозможны безопасные транзакции, блокчейн и доверие в интернете.