← Назад к вопросам

Что такое подпись в криптографии?

1.0 Junior🔥 71 комментариев
#Другое

Комментарии (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)

Реальные примеры использования

  1. Email подписи (PGP, S/MIME) — подтверждение автора письма
  2. Цифровые сертификаты (SSL/TLS) — безопасность веб-сайтов
  3. Блокчейн (Bitcoin, Ethereum) — подпись транзакций
  4. Обновления ПО — проверка подлинности обновлений
  5. Юридические документы — электронная подпись
  6. 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()
)

Важные принципы

  1. Приватный ключ остаётся в секрете — если украден, подпись недействительна
  2. Открытый ключ распространяется свободно — используется для проверки
  3. Подпись привязана к сообщению — изменение символа → неверная подпись
  4. Невозможно подделать без приватного ключа — это математический факт
  5. Не зависит от секретного канала — подпись валидна по открытым каналам

Вывод: Цифровая подпись — это фундаментальный инструмент криптографии, обеспечивающий аутентификацию, целостность и неотрекаемость в цифровом мире. Без подписей невозможны безопасные транзакции, блокчейн и доверие в интернете.