Admin
Администратор
Быстрый и защищенный стриминг данных: ECDH + AES-GCM
Привет. Недавно ковырял тему передачи тяжелых файлов и решил проверить, как современные методы на базе эллиптических кривых живут в паре с быстрым шифрованием. Задача была простая: передать данные быстро, безопасно и не убить производительность.I. Выбор инструментов
Когда пилишь архитектуру, первое, во что упираешься - как безопасно передать ключ шифрования собеседнику. Я выбрал связку ECDH на кривой Curve25519.Логика реализации:ECDH (Elliptic Curve Diffie-Hellman) - это протокол, который позволяет двум сторонам создать общий секретный пароль, перекидываясь по сети только открытыми (публичными) данными. Даже если переписку перехватят, ключ из неё не достать.
- Генерирую временные (эфемеральные) ключи на клиенте и сервере.
- Обмениваюсь публичными точками.
- Вычисляю Shared Secret (тот самый общий секрет).
Дальше само шифрование. В качестве основного алгоритма взял AES-256-GCM.HKDF (Hash-based Key Derivation Function) - алгоритм, который берет сырой секрет и превращает его в криптографически стойкий, надежный ключ фиксированной длины.
AES (Advanced Encryption Standard) - стандарт симметричного шифрования.
GCM (Galois/Counter Mode) - режим работы шифра, который дает нам свойство AEAD.
AEAD (Authenticated Encryption with Associated Data) - это "шифрование с аутентификацией". Простыми словами: алгоритм не только прячет данные, но и вешает на них "цифровую пломбу" (тег). Если хакер поменяет хоть один бит в пути, проверка пломбы не сойдется, и мы сразу поймем, что данные битые, и просто разорвем соединение.
II. Бинарный стриминг в коде
Самое интересное началось при попытке передать файл на 500 МБ через сокеты. Если пытаться зашифровать его целиком одним куском — оперативная память улетает в потолок, а задержки (лаги) становятся дикими.Решение классическое - чанковое шифрование. Режем поток на небольшие куски (блоки) по 16 КБ.
Критичный момент: для каждого чанка нужно менять Nonce.
Я сделал просто: для каждого нового куска увеличиваю счетчик на 1.Nonce (Number used once) - "число, используемое один раз". Это уникальная добавка к ключу. Если зашифровать два разных куска данных одним ключом и одним и тем же Nonce — злоумышленники смогут взломать шифр.
Вот упрощенный пример на Python:
Python:
import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
def encrypt_stream(key, data_stream):
aesgcm = AESGCM(key)
nonce_counter = 0
for chunk in data_stream:
# Формируем уникальный 12-байтовый nonce для каждого чанка
# big='big' важен для совместимости с сетевым порядком байт
nonce = nonce_counter.to_bytes(12, byteorder='big')
# Шифруем блок. AEAD сам добавит проверочный тег к шифротексту.
ciphertext = aesgcm.encrypt(nonce, chunk, None)
# В сокет улетает: [размер чанка (4б)] + [nonce (12б)] + [шифротекст + тег]
yield ciphertext
nonce_counter += 1
III. Итоги
Главный вывод: не бойтесь внедрять современные алгоритмы. Использовать старый добрый RSA или вшитые статические ключи в 2024 году - это уже просто безответственно.Библиотек под Curve25519 и AEAD сейчас хватает под любой язык программирования.RSA - алгоритм асимметричного шифрования. Он медленный и требует очень длинных ключей для надежности, в отличие от шустрых эллиптических кривых.