Cryptography – работа с шифрованием

онлайн тренажер по питону
Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Cryptography в Python: Полное руководство по безопасному шифрованию и криптографии

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

Библиотека Cryptography для Python представляет собой мощный и универсальный инструмент, который объединяет в себе простоту использования и профессиональный уровень безопасности. Она обеспечивает как высокоуровневые решения для повседневных задач, так и низкоуровневый доступ к криптографическим примитивам для специализированных случаев.

Что такое библиотека Cryptography

Cryptography — это современная криптографическая библиотека для Python, которая предоставляет рецепты и примитивы для разработчиков Python. Она была создана командой PyCA (Python Cryptographic Authority) и быстро стала стандартом де-факто для криптографических операций в экосистеме Python.

Основные принципы библиотеки:

  • Безопасность по умолчанию
  • Простота использования
  • Производительность благодаря C-биндингам
  • Совместимость со стандартами
  • Активная поддержка сообщества

Установка и настройка

Установка библиотеки осуществляется через менеджер пакетов pip:

pip install cryptography

Для работы с дополнительными функциями может потребоваться установка зависимостей:

# Для работы с SSH
pip install cryptography[ssh]

# Полная установка со всеми зависимостями
pip install cryptography[all]

Архитектура библиотеки Cryptography

Двухуровневая архитектура

Библиотека построена по принципу двухуровневой архитектуры:

High-Level Recipes (Высокоуровневые рецепты)

  • Готовые решения для типичных задач
  • Безопасные настройки по умолчанию
  • Минимум кода для максимального результата
  • Примеры: Fernet, X.509 certificate builder

Low-Level Primitives (Низкоуровневые примитивы)

  • Полный контроль над криптографическими операциями
  • Гибкость в настройке параметров
  • Доступ к специализированным алгоритмам
  • Примеры: AES в различных режимах, эллиптические кривые

Преимущества архитектуры

  • Безопасность: высокоуровневый API предотвращает типичные ошибки
  • Гибкость: низкоуровневый доступ для специальных случаев
  • Производительность: использование OpenSSL и собственных C-биндингов
  • Совместимость: поддержка стандартных форматов и протоколов

Симметричное шифрование с Fernet

Что такое Fernet

Fernet — это высокоуровневый симметричный алгоритм шифрования, который обеспечивает:

  • AES-128 шифрование в режиме CBC
  • HMAC-SHA256 для проверки подлинности
  • Временные метки для контроля TTL
  • Base64URL кодирование результата

Основные операции с Fernet

Генерация ключа:

from cryptography.fernet import Fernet

# Генерация нового ключа
key = Fernet.generate_key()
print(f"Ключ: {key}")

Сохранение ключа в файл:

# Безопасное сохранение ключа
with open("secret.key", "wb") as key_file:
    key_file.write(key)

# Загрузка ключа из файла
with open("secret.key", "rb") as key_file:
    loaded_key = key_file.read()

Шифрование данных:

# Создание объекта шифрования
cipher_suite = Fernet(key)

# Шифрование строки
message = "Это конфиденциальная информация"
encrypted_message = cipher_suite.encrypt(message.encode())

print(f"Зашифрованное сообщение: {encrypted_message}")

Расшифровка данных:

# Расшифровка
decrypted_message = cipher_suite.decrypt(encrypted_message)
print(f"Расшифрованное сообщение: {decrypted_message.decode()}")

Работа с TTL (Time To Live)

import time

# Шифрование с временной меткой
encrypted_with_time = cipher_suite.encrypt(b"Временное сообщение")

# Расшифровка с проверкой TTL (30 секунд)
try:
    decrypted = cipher_suite.decrypt(encrypted_with_time, ttl=30)
    print("Сообщение действительно")
except:
    print("Сообщение устарело")

Асимметричное шифрование

RSA шифрование

RSA остается одним из самых популярных алгоритмов асимметричного шифрования.

Генерация ключевой пары:

from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization

# Генерация приватного ключа
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
)

# Получение публичного ключа
public_key = private_key.public_key()

Сериализация ключей:

# Сериализация приватного ключа
private_pem = private_key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.PKCS8,
    encryption_algorithm=serialization.NoEncryption()
)

# Сериализация публичного ключа
public_pem = public_key.public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
)

Шифрование и расшифровка:

from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes

# Шифрование
message = b"Секретное сообщение"
ciphertext = public_key.encrypt(
    message,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

# Расшифровка
plaintext = private_key.decrypt(
    ciphertext,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

Эллиптические кривые (ECC)

ECC обеспечивает такой же уровень безопасности, как RSA, но с меньшим размером ключей.

from cryptography.hazmat.primitives.asymmetric import ec

# Генерация ключа на кривой SECP256R1
private_key = ec.generate_private_key(ec.SECP256R1())
public_key = private_key.public_key()

# Подпись
signature = private_key.sign(
    b"Сообщение для подписи",
    ec.ECDSA(hashes.SHA256())
)

# Проверка подписи
try:
    public_key.verify(signature, b"Сообщение для подписи", ec.ECDSA(hashes.SHA256()))
    print("Подпись верна")
except:
    print("Подпись неверна")

Хэширование и MAC

Простое хэширование

from cryptography.hazmat.primitives import hashes

# Создание объекта хеша
digest = hashes.Hash(hashes.SHA256())

# Добавление данных
digest.update(b"Первая часть данных")
digest.update(b"Вторая часть данных")

# Получение результата
hash_value = digest.finalize()
print(f"SHA-256 хеш: {hash_value.hex()}")

HMAC (Hash-based Message Authentication Code)

from cryptography.hazmat.primitives import hmac

# Создание HMAC
secret_key = b"secret_key"
h = hmac.HMAC(secret_key, hashes.SHA256())
h.update(b"Сообщение для аутентификации")

# Получение MAC
mac = h.finalize()
print(f"HMAC: {mac.hex()}")

# Проверка MAC
h2 = hmac.HMAC(secret_key, hashes.SHA256())
h2.update(b"Сообщение для аутентификации")
h2.verify(mac)  # Не вызывает исключение, если MAC верен

Цифровые подписи

RSA подписи

# Создание подписи
signature = private_key.sign(
    b"Документ для подписи",
    padding.PSS(
        mgf=padding.MGF1(hashes.SHA256()),
        salt_length=padding.PSS.MAX_LENGTH
    ),
    hashes.SHA256()
)

# Проверка подписи
try:
    public_key.verify(
        signature,
        b"Документ для подписи",
        padding.PSS(
            mgf=padding.MGF1(hashes.SHA256()),
            salt_length=padding.PSS.MAX_LENGTH
        ),
        hashes.SHA256()
    )
    print("Подпись действительна")
except:
    print("Подпись недействительна")

Ed25519 подписи

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

from cryptography.hazmat.primitives.asymmetric import ed25519

# Генерация ключа
private_key = ed25519.Ed25519PrivateKey.generate()
public_key = private_key.public_key()

# Подпись
signature = private_key.sign(b"Сообщение")

# Проверка
try:
    public_key.verify(signature, b"Сообщение")
    print("Ed25519 подпись верна")
except:
    print("Ed25519 подпись неверна")

Производные функции ключей (KDF)

PBKDF2

PBKDF2 используется для преобразования паролей в криптографические ключи.

from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import os

# Генерация соли
salt = os.urandom(16)

# Настройка KDF
kdf = PBKDF2HMAC(
    algorithm=hashes.SHA256(),
    length=32,
    salt=salt,
    iterations=100_000,
)

# Генерация ключа из пароля
password = b"мой_супер_пароль"
key = kdf.derive(password)

# Проверка пароля
kdf2 = PBKDF2HMAC(
    algorithm=hashes.SHA256(),
    length=32,
    salt=salt,
    iterations=100_000,
)

try:
    kdf2.verify(password, key)
    print("Пароль верен")
except:
    print("Пароль неверен")

Scrypt

Scrypt обеспечивает защиту от атак с использованием специализированного оборудования.

from cryptography.hazmat.primitives.kdf.scrypt import Scrypt

salt = os.urandom(16)
kdf = Scrypt(
    algorithm=hashes.SHA256(),
    length=32,
    salt=salt,
    n=2**14,
    r=8,
    p=1,
)

key = kdf.derive(b"пароль")

Низкоуровневое симметричное шифрование

AES в различных режимах

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
import os

# AES в режиме CBC
key = os.urandom(32)  # 256-битный ключ
iv = os.urandom(16)   # 128-битный вектор инициализации

cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
encryptor = cipher.encryptor()
decryptor = cipher.decryptor()

# Добавление padding
padder = padding.PKCS7(128).padder()
padded_data = padder.update(b"Длинное сообщение для шифрования")
padded_data += padder.finalize()

# Шифрование
ciphertext = encryptor.update(padded_data) + encryptor.finalize()

# Расшифровка
plaintext_padded = decryptor.update(ciphertext) + decryptor.finalize()

# Удаление padding
unpadder = padding.PKCS7(128).unpadder()
plaintext = unpadder.update(plaintext_padded) + unpadder.finalize()

ChaCha20

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms

key = os.urandom(32)
nonce = os.urandom(16)

cipher = Cipher(algorithms.ChaCha20(key, nonce), mode=None)
encryptor = cipher.encryptor()

ciphertext = encryptor.update(b"Сообщение для ChaCha20") + encryptor.finalize()

Работа с X.509 сертификатами

Создание самоподписанного сертификата

from cryptography import x509
from cryptography.x509.oid import NameOID
import datetime

# Создание сертификата
subject = issuer = x509.Name([
    x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU"),
    x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Moscow"),
    x509.NameAttribute(NameOID.LOCALITY_NAME, u"Moscow"),
    x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"My Company"),
    x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
])

cert = x509.CertificateBuilder().subject_name(
    subject
).issuer_name(
    issuer
).public_key(
    public_key
).serial_number(
    x509.random_serial_number()
).not_valid_before(
    datetime.datetime.utcnow()
).not_valid_after(
    datetime.datetime.utcnow() + datetime.timedelta(days=365)
).sign(private_key, hashes.SHA256())

# Сохранение сертификата
with open("certificate.pem", "wb") as f:
    f.write(cert.public_bytes(serialization.Encoding.PEM))

Полная таблица методов и функций библиотеки Cryptography

Высокоуровневые рецепты

Модуль/Класс Метод/Функция Описание
Fernet generate_key() Генерация симметричного ключа для Fernet
  encrypt(data) Шифрование данных с проверкой подлинности
  decrypt(token, ttl=None) Расшифровка с опциональной проверкой TTL
MultiFernet encrypt(data) Шифрование с ротацией ключей
  decrypt(token, ttl=None) Расшифровка с поддержкой нескольких ключей
  rotate(data) Перешифровка данных новым ключом

Асимметричная криптография

Модуль Функция/Метод Описание
rsa generate_private_key(public_exponent, key_size) Генерация RSA ключевой пары
  encrypt(message, padding) RSA шифрование
  decrypt(ciphertext, padding) RSA расшифровка
  sign(message, padding, algorithm) RSA подпись
  verify(signature, message, padding, algorithm) Проверка RSA подписи
ec generate_private_key(curve) Генерация ключа эллиптической кривой
  sign(data, signature_algorithm) ECDSA подпись
  verify(signature, data, signature_algorithm) Проверка ECDSA подписи
ed25519 Ed25519PrivateKey.generate() Генерация Ed25519 ключа
  sign(data) Ed25519 подпись
  verify(signature, data) Проверка Ed25519 подписи
x25519 X25519PrivateKey.generate() Генерация ключа для обмена ключами
  exchange(peer_public_key) Выполнение обмена ключами

Хэширование и MAC

Модуль Функция/Метод Описание
hashes Hash(algorithm) Создание объекта хеша
  update(data) Добавление данных к хешу
  finalize() Получение финального хеша
hmac HMAC(key, algorithm) Создание HMAC объекта
  update(data) Добавление данных к HMAC
  finalize() Получение MAC
  verify(signature) Проверка MAC

Производные функции ключей

Класс Метод Описание
PBKDF2HMAC derive(key_material) Получение ключа из пароля
  verify(key_material, expected_key) Проверка соответствия пароля ключу
Scrypt derive(key_material) Scrypt деривация ключа
  verify(key_material, expected_key) Проверка Scrypt ключа
HKDF derive(key_material) HKDF расширение ключа
  expand(key_material, length, info) HKDF расширение с дополнительной информацией

Симметричные шифры

Класс Параметры Описание
AES key (128/192/256 бит) Алгоритм AES
ChaCha20 key (256 бит), nonce (128 бит) Потоковый шифр ChaCha20
TripleDES key (192 бит) Устаревший 3DES

Режимы шифрования

Режим Параметры Описание
CBC initialization_vector Cipher Block Chaining
GCM initialization_vector, tag Galois/Counter Mode с аутентификацией
CTR nonce Counter mode
ECB - Electronic Codebook (не рекомендуется)
OFB initialization_vector Output Feedback
CFB initialization_vector Cipher Feedback

Сериализация

Модуль Функция Описание
serialization load_pem_private_key(data, password) Загрузка приватного ключа из PEM
  load_pem_public_key(data) Загрузка публичного ключа из PEM
  load_der_private_key(data, password) Загрузка приватного ключа из DER
  load_der_public_key(data) Загрузка публичного ключа из DER

X.509 сертификаты

Класс Метод Описание
CertificateBuilder subject_name(name) Установка субъекта сертификата
  issuer_name(name) Установка издателя сертификата
  public_key(key) Установка публичного ключа
  serial_number(number) Установка серийного номера
  not_valid_before(time) Установка даты начала действия
  not_valid_after(time) Установка даты окончания действия
  sign(private_key, algorithm) Подписание сертификата

Практические примеры использования

Создание безопасного хранилища паролей

import json
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import base64
import os

class PasswordManager:
    def __init__(self, master_password: str):
        self.salt = os.urandom(16)
        self.key = self._derive_key(master_password, self.salt)
        self.cipher = Fernet(self.key)
        self.passwords = {}
    
    def _derive_key(self, password: str, salt: bytes) -> bytes:
        kdf = PBKDF2HMAC(
            algorithm=hashes.SHA256(),
            length=32,
            salt=salt,
            iterations=100_000,
        )
        key = base64.urlsafe_b64encode(kdf.derive(password.encode()))
        return key
    
    def add_password(self, service: str, password: str):
        encrypted_password = self.cipher.encrypt(password.encode())
        self.passwords[service] = base64.urlsafe_b64encode(encrypted_password).decode()
    
    def get_password(self, service: str) -> str:
        if service not in self.passwords:
            raise ValueError("Сервис не найден")
        
        encrypted_password = base64.urlsafe_b64decode(self.passwords[service])
        decrypted_password = self.cipher.decrypt(encrypted_password)
        return decrypted_password.decode()

# Использование
pm = PasswordManager("мой_мастер_пароль")
pm.add_password("gmail", "супер_секретный_пароль")
print(pm.get_password("gmail"))

Безопасная передача файлов

from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.fernet import Fernet

def secure_file_transfer():
    # Генерация ключей получателя
    recipient_private_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
    )
    recipient_public_key = recipient_private_key.public_key()
    
    # Отправитель
    # 1. Генерация симметричного ключа для файла
    file_key = Fernet.generate_key()
    file_cipher = Fernet(file_key)
    
    # 2. Шифрование файла
    file_content = b"Содержимое конфиденциального файла"
    encrypted_file = file_cipher.encrypt(file_content)
    
    # 3. Шифрование ключа файла публичным ключом получателя
    encrypted_key = recipient_public_key.encrypt(
        file_key,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    
    # Получатель
    # 1. Расшифровка ключа файла
    decrypted_file_key = recipient_private_key.decrypt(
        encrypted_key,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    
    # 2. Расшифровка файла
    file_cipher_recipient = Fernet(decrypted_file_key)
    decrypted_file = file_cipher_recipient.decrypt(encrypted_file)
    
    print(f"Исходный файл: {file_content}")
    print(f"Расшифрованный файл: {decrypted_file}")

secure_file_transfer()

Безопасность и лучшие практики

Основные принципы безопасности

  1. Никогда не используйте константные ключи — всегда генерируйте случайные ключи
  2. Используйте соль для хэширования паролей — предотвращает rainbow table атаки
  3. Проверяйте подлинность данных — используйте HMAC или аутентифицированное шифрование
  4. Ограничивайте время жизни токенов — используйте TTL в Fernet
  5. Никогда не логируйте секретные данные — ключи и пароли не должны попадать в логи

Распространенные ошибки

Использование eval() с расшифрованными данными

# НЕПРАВИЛЬНО!
decrypted_data = cipher.decrypt(token)
result = eval(decrypted_data)  # Опасно!

# ПРАВИЛЬНО!
import json
decrypted_data = cipher.decrypt(token)
result = json.loads(decrypted_data)  # Безопасно

Хранение ключей вместе с данными

# НЕПРАВИЛЬНО!
key = Fernet.generate_key()
encrypted_data = cipher.encrypt(data)
# Сохранение ключа и данных в одном месте

# ПРАВИЛЬНО!
# Ключи должны храниться отдельно от данных
# Используйте переменные окружения, Key Management Services

Рекомендации по производительности

  1. Переиспользуйте объекты Cipher — создание шифра дорого
  2. Используйте потоковое шифрование для больших данных
  3. Рассмотрите использование ChaCha20 для мобильных устройств

Сравнение с другими библиотеками

Библиотека Уровень API Симметричное шифрование Асимметричное шифрование Активная разработка Рекомендация
cryptography Высокий + Низкий ✅ Полная поддержка ✅ RSA, ECC, Ed25519 ✅ Активная Рекомендуется
pycryptodome Средний ✅ Хорошая поддержка ✅ RSA, ECC ✅ Активная Альтернатива
pycrypto Низкий ⚠️ Базовая ⚠️ Только RSA ❌ Заброшена Не рекомендуется
hashlib Высокий ❌ Только хеширование ❌ Нет ✅ Стандартная Только для хэширования
ssl Высокий ⚠️ TLS-ориентированная ⚠️ Ограниченная ✅ Стандартная Для TLS/SSL

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

Безопасность веб-приложений

Хранение сессий:

from cryptography.fernet import Fernet
import json
import datetime

class SessionManager:
    def __init__(self, secret_key):
        self.cipher = Fernet(secret_key)
    
    def create_session(self, user_id, expires_in_hours=24):
        session_data = {
            'user_id': user_id,
            'created_at': datetime.datetime.utcnow().isoformat(),
            'expires_at': (datetime.datetime.utcnow() + 
                         datetime.timedelta(hours=expires_in_hours)).isoformat()
        }
        
        token = self.cipher.encrypt(json.dumps(session_data).encode())
        return token
    
    def validate_session(self, token):
        try:
            decrypted_data = self.cipher.decrypt(token)
            session_data = json.loads(decrypted_data.decode())
            
            expires_at = datetime.datetime.fromisoformat(session_data['expires_at'])
            if datetime.datetime.utcnow() > expires_at:
                return None
                
            return session_data
        except:
            return None

Микросервисная архитектура

JWT-подобные токены с дополнительной безопасностью:

import json
import base64
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding

class SecureTokenService:
    def __init__(self):
        self.private_key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=2048,
        )
        self.public_key = self.private_key.public_key()
    
    def create_token(self, payload):
        # Создание заголовка
        header = {"alg": "RS256", "typ": "JWT"}
        
        # Кодирование заголовка и payload
        encoded_header = base64.urlsafe_b64encode(json.dumps(header).encode()).decode().rstrip('=')
        encoded_payload = base64.urlsafe_b64encode(json.dumps(payload).encode()).decode().rstrip('=')
        
        # Создание подписи
        message = f"{encoded_header}.{encoded_payload}".encode()
        signature = self.private_key.sign(
            message,
            padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH
            ),
            hashes.SHA256()
        )
        
        encoded_signature = base64.urlsafe_b64encode(signature).decode().rstrip('=')
        
        return f"{encoded_header}.{encoded_payload}.{encoded_signature}"
    
    def verify_token(self, token):
        try:
            parts = token.split('.')
            if len(parts) != 3:
                return None
            
            header, payload, signature = parts
            
            # Восстановление подписи
            signature_bytes = base64.urlsafe_b64decode(signature + '==')
            message = f"{header}.{payload}".encode()
            
            # Проверка подписи
            self.public_key.verify(
                signature_bytes,
                message,
                padding.PSS(
                    mgf=padding.MGF1(hashes.SHA256()),
                    salt_length=padding.PSS.MAX_LENGTH
                ),
                hashes.SHA256()
            )
            
            # Декодирование payload
            payload_data = json.loads(base64.urlsafe_b64decode(payload + '==').decode())
            return payload_data
            
        except Exception as e:
            return None

Часто задаваемые вопросы

Какой размер ключа RSA следует использовать?

Рекомендуется использовать минимум 2048 бит для RSA ключей. Для высокобезопасных систем рассмотрите 4096 бит, но учитывайте влияние на производительность.

Когда использовать Fernet, а когда низкоуровневые примитивы?

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

Как правильно хранить криптографические ключи?

  • В производственных системах используйте Key Management Services (AWS KMS, Azure Key Vault)
  • Для разработки — переменные окружения
  • Никогда не храните ключи в коде или системах контроля версий

Что делать при компрометации ключа?

  1. Немедленно отозвать скомпрометированный ключ
  2. Сгенерировать новую ключевую пару
  3. Перешифровать все данные новым ключом
  4. Уведомить пользователей о необходимости обновления

Как обеспечить совместимость между разными версиями библиотеки?

Используйте стабильные форматы сериализации (PEM, DER) и избегайте экспериментальных функций в продакшене.

Производительность и оптимизация

Бенчмарки операций

Операция Время (мс/операция) Рекомендации
Fernet encrypt (1KB) ~0.1 Оптимально для большинства задач
RSA encrypt (2048-bit) ~1.5 Используйте для небольших данных
AES-GCM (1KB) ~0.05 Быстрее Fernet, но требует больше кода
Ed25519 sign ~0.3 Быстрее RSA подписей
PBKDF2 (100k iterations) ~50 Баланс между безопасностью и скоростью

Оптимизация для больших объемов данных

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import os

def encrypt_large_file(input_file, output_file, key):
    """Потоковое шифрование больших файлов"""
    iv = os.urandom(16)
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
    encryptor = cipher.encryptor()
    
    with open(input_file, 'rb') as infile, open(output_file, 'wb') as outfile:
        # Записываем IV в начало файла
        outfile.write(iv)
        
        # Шифруем блоками по 64KB
        while True:
            chunk = infile.read(64 * 1024)
            if not chunk:
                break
            
            # Добавляем padding только к последнему блоку
            if len(chunk) < 64 * 1024:  # Последний блок
                from cryptography.hazmat.primitives import padding
                padder = padding.PKCS7(128).padder()
                chunk = padder.update(chunk) + padder.finalize()
            
            encrypted_chunk = encryptor.update(chunk)
            outfile.write(encrypted_chunk)
        
        # Финализация
        final_chunk = encryptor.finalize()
        if final_chunk:
            outfile.write(final_chunk)

Интеграция с популярными фреймворками

Django

from cryptography.fernet import Fernet
from django.conf import settings

class EncryptedModelField:
    def __init__(self):
        self.cipher = Fernet(settings.ENCRYPTION_KEY.encode())
    
    def encrypt_field(self, value):
        if value:
            return self.cipher.encrypt(str(value).encode()).decode()
        return value
    
    def decrypt_field(self, value):
        if value:
            return self.cipher.decrypt(value.encode()).decode()
        return value

FastAPI

from fastapi import HTTPException, Depends
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding

async def verify_signature(request_data: dict, signature: str):
    """Middleware для проверки подписи API запросов"""
    try:
        public_key = get_api_public_key()  # Получение ключа из конфига
        message = json.dumps(request_data, sort_keys=True).encode()
        signature_bytes = base64.b64decode(signature)
        
        public_key.verify(
            signature_bytes,
            message,
            padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH
            ),
            hashes.SHA256()
        )
        return True
    except Exception:
        raise HTTPException(status_code=401, detail="Invalid signature")

Заключение

Библиотека Cryptography представляет собой мощный и надежный инструмент для решения криптографических задач в Python. Она успешно сочетает простоту использования высокоуровневого API с гибкостью низкоуровневых примитивов, что делает её подходящей как для быстрого прототипирования, так и для промышленных решений.

Основные преимущества библиотеки:

  • Безопасность по умолчанию: современные алгоритмы и защита от типичных ошибок
  • Производительность: оптимизированные C-биндинги для критически важных операций
  • Стандартизация: поддержка индустриальных стандартов и форматов
  • Активное развитие: регулярные обновления и исправления безопасности

Cryptography активно используется в крупнейших проектах: от банковских систем и государственных сервисов до стартапов и научных исследований. Её надежность подтверждена временем и доверием сообщества разработчиков.

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

Новости