Тема 16

Постквантовая криптография и практика безопасного применения

Постквантовая криптография и практика безопасного применения

Вся криптография с открытым ключом, разобранная в этом курсе, стоит на двух задачах: факторизации и дискретном логарифме. RSA держится на первой, Диффи — Хеллман и эллиптические кривые — на второй. В 1994 году Питер Шор показал, что квантовый компьютер решает обе за полиномиальное время 1. Это не ослабило схемы — это поставило под вопрос само их существование.

Симметричная криптография пострадала меньше. Алгоритм Гровера даёт лишь квадратичное ускорение перебора 2, поэтому AES-128 превращается в «AES-64», а AES-256 остаётся стойким. Но асимметричная часть — обмен ключами, подписи, сертификаты — ломается целиком, а вместе с ней и вся инфраструктура, которую мы строили пятнадцать тем.

Терминология здесь немного путает. «Постквантовая криптография» — это не криптография на квантовых компьютерах, а схемы, которые работают на обычных машинах и при этом стойки к квантовому противнику. «Квантовая криптография» — другое: распределение ключей по квантовому каналу (QKD), где подслушивание физически обнаруживается. QKD требует специального оборудования и не решает задачу подписи; постквантовые схемы решают обе задачи и работают на существующем железе. Именно поэтому стандартизация пошла по второму пути.

Отсюда и название: постквантовая криптография — это схемы, стойкие против квантового противника, но работающие на обычных компьютерах. После восьми лет конкурса NIST в 2024 году опубликовал три стандарта: ML-KEM для обмена ключами, ML-DSA и SLH-DSA для подписей. На них уже переходят браузеры, а гибридный обмен X25519MLKEM768 стал обычным делом в TLS.

Тема устроена так: сначала квантовая угроза и её реальные масштабы, затем стандарты 2024 года и семейства схем, потом учебная криптография на решётках — LWE и схема Регева с числовым примером, — потом хеш-подписи от Лэмпорта до SLH-DSA. Завершают тему внедрение (гибриды, криптографическая гибкость) и практика: что использовать в 2026 году, какие ошибки встречаются чаще всего и что говорит регуляторика.

Паспорт темы. Нужно знать: темы 15. Освоите: оценивать угрозу Шора и Гровера; описывать ML-KEM, ML-DSA и SLH-DSA; объяснять LWE на учебном примере; строить гибридный обмен и планировать crypto-agility; аудировать криптографический код. Проверяет: ЛР 16. Минимум: разделы 1–4. Углубление: разделы 5–6.

Квантовая угроза

Алгоритм Шора

Задача факторизации и задача дискретного логарифмирования считаются трудными, потому что лучшие известные классические алгоритмы субэкспоненциальны (решето числового поля) или экспоненциальны (ро-метод Полларда для дискретного логарифма). Шор свёл обе к нахождению периода функции — а период квантовый компьютер находит преобразованием Фурье за полиномиальное время 1.

Конкретно: RSA ломается, потому что из n можно найти p и q; Диффи — Хеллман и ECDH ломаются, потому что из g^a можно найти a; ECDSA и EdDSA ломаются, потому что из открытого ключа восстанавливается закрытый. Устоять не может ни одна схема, чья стойкость сводится к этим задачам.

Важно понимать, чего алгоритм Шора не делает. Он не ломает симметричные шифры, хеш-функции и коды аутентификации. Он не даёт «универсального взлома». Он решает конкретный класс задач, и именно на нём стоит вся асимметричная криптография.

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

Гровер даёт квадратичное ускорение поиска в неструктурированном пространстве 2: перебор 2^k вариантов превращается в 2^(k/2). Для симметричных схем это означает, что стойкость в битах делится пополам.

ПримитивКлассическая стойкостьСтойкость против ГровераВывод
AES-128128 бит~64 битанедостаточно для долгосрочной защиты
AES-256256 бит~128 битнормальный выбор
SHA-256 (коллизии)128 бит~85 битприемлемо, но SHA-384 лучше
SHA-3-256128 бит~85 битто же

У Гровера есть важное ограничение. Ускорение квадратичное, а параллелизация даёт мало: k параллельных машин сокращают время лишь в √k раз, потому что суммарное число операций не уменьшается. То есть защита от Гровера — это просто удвоение ключа, а не «ещё один алгоритм».

Есть и второе ограничение — квантовые вычисления с коррекцией ошибок. Физические кубиты шумят, и для устойчивой работы нужно много физических кубитов на один логический (обычно сотни или тысячи, в зависимости от кода коррекции). Именно поэтому оценки вроде «20 миллионов физических кубитов» выглядят так внушительно: логических там будет всего несколько тысяч.

Практический вывод прост: удвойте длину симметричного ключа и не беспокойтесь. Никакой «постквантовый AES» не нужен — нужен AES-256 и SHA-384 вместо AES-128 и SHA-256.

Оценки ресурсов и «сохрани сейчас — расшифруй потом»

Квантовый компьютер, способный факторизовать RSA-2048, — это не настольная машина. Оценка Гидни и Экера: около 20 миллионов физических кубитов с шумом и примерно 8 часов работы 7. Для RSA-4096 — примерно вдвое больше кубитов. Современные устройства имеют порядка сотен — тысяч физических кубитов и не умеют удерживать когерентность достаточно долго для коррекции ошибок.

Из этого часто делают вывод «ещё не скоро, можно не спешить». Это ошибка, и вот почему.

Во-первых, сроки неизвестны. Оценки «через 15–30 лет» — это оценки, а не гарантии, и они менялись в обе стороны.

Во-вторых, работает атака «сохрани сейчас — расшифруй потом» (harvest now, decrypt later): противник записывает зашифрованный трафик сегодня, а расшифровывает, когда появится компьютер. Если данные должны оставаться секретными 10–20 лет, их уже нельзя защищать схемой, которая завтра сломается.

В-третьих, миграция инфраструктуры занимает годы. Сертификаты, прошивки, библиотеки, стандарты, аудит — всё это не обновляется по команде. Отсюда «теорема Москы»: если данные должны быть защищены X лет, а миграция занимает Y лет, начинать нужно за X − Y лет до появления компьютера.

Квантовая угроза и окно миграции
Слева — что ломает Шор, справа — окно миграции: начинать нужно раньше, чем появится компьютер, иначе данные уже перехвачены

Стандарты 2024 года

Хронология конкурса

NIST начал процесс в 2016 году, объявив конкурс на постквантовые схемы. На первый раунд пришло 82 заявки; после нескольких лет публичного криптоанализа осталось несколько семейств. В июле 2022 года были выбраны Kyber (обмен ключами), Dilithium и Falcon (подписи), SPHINCS+ (подписи на хешах). В августе 2024 года вышли стандарты:

  • FIPS 203 — ML-KEM (на основе Kyber) 3;
  • FIPS 204 — ML-DSA (на основе Dilithium) 4;
  • FIPS 205 — SLH-DSA (на основе SPHINCS+) 5.

Falcon остался в резерве: он компактнее по подписям, но сложнее в реализации и хуже поддаётся защите от побочных каналов. Обзор всего поля с объяснением, почему именно решётки оказались практичным выбором, дан в статье Бернстайна и Ланге 11.

Отдельно стоит сказать про то, как читать эти стандарты. FIPS 203–205 — не «описания идей», а точные спецификации: в них зафиксированы распределения, порядок операций, правила кодирования и проверки, от которых зависит стойкость. Реализация «по мотивам статьи» почти наверняка будет содержать уязвимость, потому что все тонкости — в деталях, а не в формуле.

ML-KEM

ML-KEM — схема инкапсуляции ключа (KEM): одна сторона генерирует пару ключей, другая инкапсулирует в открытый ключ случайный секрет и отправляет шифртекст, первая декапсулирует. Это замена ECDH: результат — общий секрет 32 байта, из которого выводятся ключи.

Основа — Module-LWE: задача о поиске секрета в системе линейных уравнений над кольцом с малым шумом. Параметры трёх уровней:

ПараметрML-KEM-512ML-KEM-768ML-KEM-1024
Уровень стойкости (NIST)135
Открытый ключ800 байт1184 байта1568 байт
Шифртекст768 байт1088 байт1568 байт
Секрет32 байта32 байта32 байта

Открытый ключ в 1184 байта — это в 37 раз больше, чем 32 байта X25519, и в 2,8 раза больше, чем весь открытый ключ RSA-3072. Отсюда и главная проблема внедрения: трафик рукопожатия растёт.

ML-DSA и SLH-DSA

ML-DSA — подпись на Module-LWE (точнее, на задаче SIS — коротких векторов в решётке). Она даёт подписи в тысячи байт:

ПараметрML-DSA-44ML-DSA-65ML-DSA-87
Уровень235
Открытый ключ1312 байт1952 байта2592 байта
Подпись2420 байт3309 байт4627 байт

SLH-DSA — подпись на хеш-функциях, без всякой алгебры. Она медленнее и даёт огромные подписи (около 7,9 КБ для 128-битного уровня), но её стойкость опирается только на свойства хеша. Это страховка: если решёточные схемы когда-нибудь сломают, останется вариант, не зависящий от их математики.

Сравним с привычным:

СхемаОткрытый ключПодписьСтойкость
RSA-3072422 байта384 байта128 бит
ECDSA P-25691 байт72 байта128 бит
Ed2551944 байта64 байта~128 бит
ML-DSA-651952 байта3309 байт192 бита
SLH-DSA-SHA2-128s32 байта7856 байт128 бит
Размеры ключей и подписей
Постквантовые схемы дают ключи и подписи в десятки раз больше: это плата за стойкость к алгоритму Шора

Семейства схем и взлом SIKE

Постквантовая криптография — не одна схема, а несколько семейств с разной математикой.

  • Решётки. ML-KEM, ML-DSA, Falcon. Быстрые, компактные ключи, но требуют аккуратной реализации (постоянное время, защита от утечек).
  • Коды. Classic McEliece — схема 1978 года, стойкая до сих пор, с открытым ключом в сотни килобайт и шифртекстом в сотню байт. Ключ огромен, зато передаётся один раз и дальше не мешает; в сценариях «ключ в прошивке» это приемлемо, с огромным открытым ключом (сотни килобайт) и крошечным шифртекстом. Хороша для случаев, когда ключ передаётся один раз.
  • Хеш-подписи. Лэмпорт, Меркл, XMSS, LMS, SLH-DSA. Стойкость опирается только на хеш; цена — размер и скорость.
  • Изогении. SIKE — красивая схема на изогениях эллиптических кривых, дошедшая до финала конкурса. В 2022 году Кастрик и Декрю нашли атаку, восстанавливающую ключ за минуты на одном ядре 8. Схему исключили.

У каждого семейства своя ниша. Решётки удобны везде, где важны размеры и скорость. Коды — там, где ключ статичен, а канал узкий. Хеш-подписи — там, где нужна максимальная уверенность в предположениях и можно пожертвовать размером: прошивки, обновления, долгоживущие документы.

История SIKE — важный урок. Схема прошла несколько лет публичного анализа, была финалистом и всё равно оказалась сломана. Это не значит, что решётки тоже сломают; это значит, что «прошло пять лет аудита» не равно «безопасно». Отсюда и стратегия NIST: несколько семейств параллельно плюс гибриды.

Учебная криптография на решётках

LWE своими словами

Задача Learning With Errors (LWE), предложенная Регевом в 2005 году 6, формулируется так. Есть секретный вектор s из n малых чисел. Противнику даны m уравнений вида

b_i = a_i · s + e_i  (mod q)

где a_i — случайные векторы, а e_i — маленькие ошибки. Нужно найти s.

Без ошибок это обычная система линейных уравнений: гауссово исключение, и всё. Именно ошибки делают задачу трудной: каждое уравнение «почти верно», но неизвестно, насколько именно. Интуиция такая: вы знаете, что точки лежат почти на гиперплоскости, но не знаете, в какую сторону и насколько они сдвинуты, — и при большой размерности это неразрешимо.

У задачи есть важное свойство: она «худший случай — средний случай». Регев доказал, что если LWE трудна в среднем, то она трудна и в худшем случае (для решёточных задач), — а это означает, что криптографу не нужно искать «удачные» экземпляры: подойдёт любой. Классические схемы такого свойства не имеют, и именно оно делает LWE удобной основой стандартов.

Стойкость LWE связана с трудными задачами в решётках (приближённое кратчайшее независимое семейство векторов), и лучшие известные алгоритмы работают экспоненциально по n. Это и есть причина, по которой на LWE строят постквантовые схемы: алгоритм Шора здесь не помогает, потому что задача не сводится к поиску периода.

Схема Регева

Простейшее шифрование на LWE — схема Регева для одного бита.

ключи:   s ← {−1,0,1}^n ;  A ← случайная m×n ;  e ← {−1,0,1}^m
         b = A·s + e (mod q) ;  открытый ключ (A, b), секрет s
шифр:    выбрать случайное подмножество S из m уравнений
         u = Σ_{i∈S} A_i ,  v = Σ_{i∈S} b_i + bit·(q/2)  (mod q)
расшифр: d = v − s·u (mod q)
         d ближе к 0 → бит 0 ;  d ближе к q/2 → бит 1

Почему это работает: v − s·u = Σ e_i + bit·(q/2). Сумма ошибок мала по сравнению с q/2, поэтому результат остаётся рядом с нулём или рядом с q/2, и бит восстанавливается. Стойкость держится на том, что по (A, b) найти s трудно.

Совсем маленький пример, который можно проверить вручную. Возьмём n = 3, q = 97, m = 4, секрет s = (1, −1, 0), ошибки e = (−1, −1, 0, 0). Тогда

A = [[57, 71, 59],        b = A·s + e = (82, 88, 1, 77)
     [57, 65, 75],
     [24, 23, 65],
     [60, 80, 78]]

Шифруем бит 1, выбирая подмножество уравнений {1, 3, 4} (нумерация с единицы): u = (44, 77, 8), v = b₁ + b₃ + b₄ + 48 = 14 (mod 97). Расшифрование: d = v − s·u = 14 − (44 − 77) = 47. Это ближе к q/2 = 48, чем к нулю, значит бит — 1. Всё сошлось, и видно, откуда взялось 47: это сумма ошибок (−1 + 0 + 0) плюс сдвиг 48.

Числовой пример с параметрами из лабораторной работы (n = 8, q = 97, m = 16):

  • секрет s — восемь чисел из {−1, 0, 1};
  • каждое уравнение добавляет ошибку ±1 или 0;
  • сумма шестнадцати ошибок не превышает 16, а порог — q/4 = 24;
  • значит, расшифрование ошибается только если сумма ошибок превысит 24, что при таких параметрах случается редко.

Код шифрования и расшифрования занимает десяток строк:

def encrypt(pk, bit, params, rng):
    A, b = pk
    q, n, m = params["q"], params["n"], params["m"]
    mask = [rng.randrange(2) for _ in range(m)]
    u = [sum(mask[i] * A[i][j] for i in range(m)) % q for j in range(n)]
    v = (sum(mask[i] * b[i] for i in range(m)) + bit * (q // 2)) % q
    return u, v

def decrypt(secret, ciphertext, params):
    q, n = params["q"], params["n"]
    u, v = ciphertext
    d = (v - sum(secret[j] * u[j] for j in range(n))) % q
    return 0 if min(d, q - d) <= q // 4 else 1

Сравните с тем, что делает ML-KEM: те же u и v, только над кольцом многочленов, с хешами и отбраковкой. Принцип один.

LWE: шум и порог расшифрования
Сумма ошибок удерживает результат около 0 или q/2; пока шум меньше q/4, бит восстанавливается правильно

Почему без шума всё ломается

Если убрать ошибки, шифрование Регева становится прозрачным: b = A·s — обычная линейная система, и s находится методом Гаусса за O(n³). Лабораторная работа показывает это буквально: функция recover_secret_noiseless решает систему над GF(97) и восстанавливает секрет, а при добавлении шума система становится несовместной, и метод Гаусса даёт либо ошибку, либо неверный ответ.

Это не курьёз, а суть конструкции: шум — единственное, что защищает схему. Отсюда и требования к реализации ML-KEM: распределение шума должно быть ровно таким, как в стандарте, а отбраковка (проверка, что шифртекст не деградировал) — обязательной. Ошибка в генерации шума или в проверке приводит к атакам, которых в спецификации нет.

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

Параметры ML-KEM — не предмет вкуса. От них зависит и стойкость, и вероятность ошибки расшифрования, и эти две величины тянут в разные стороны: больше шум — выше стойкость и выше вероятность сбоя; меньше шум — наоборот. Стандарт фиксирует компромисс, при котором вероятность ошибки меньше 2^-128, а стойкость соответствует уровню NIST.

Если уменьшить шум «чтобы не было ошибок», схема ослабнет. Если увеличить размерность «чтобы надёжнее», вырастут ключи и упадёт скорость. Если поменять распределение на более удобное — изменится доказательство стойкости, и схема перестанет быть ML-KEM. Это ровно тот случай, когда «самодельные параметры» — не оптимизация, а уязвимость.

От LWE к ML-KEM

ML-KEM устроен сложнее учебной схемы, но идея та же.

  • Вместо произвольной матрицы — кольцо многочленов Z_q[X]/(X^256 + 1), и умножение делается через NTT. Это даёт скорость и компактность.
  • Вместо одного вектора — модуль ранга k (отсюда «Module-LWE»): k = 2, 3, 4 для трёх уровней.
  • Добавлены хеши и «отбраковка» (FO-преобразование), чтобы схема была стойкой в модели с выбором шифртекста, а не только в пассивной модели.
  • Секрет и шум — из центрированного биномиального распределения, а не из {−1,0,1}.

Стоит сразу ответить на частый вопрос: зачем гибрид, если ML-KEM уже стандартизован? Причин две. Первая — доверие: решёточные схемы моложе, чем RSA и ECC, и публичный анализ продолжается. Вторая — совместимость: гибрид позволяет включить постквантовую защиту, не отказываясь от привычной, и не требует менять сертификаты. Если завтра найдётся атака на ML-KEM, гибрид останется стойким на X25519; если появится квантовый компьютер, гибрид останется стойким на ML-KEM. Такая «страховка с двух сторон» и есть смысл конструкции.

Именно эти детали — предмет стандарта. Учебная схема показывает принцип, но не заменяет FIPS 203: реализовывать ML-KEM самостоятельно нельзя ни при каких обстоятельствах.

Хеш-подписи

Лэмпорт

Одноразовая подпись Лэмпорта предложена в 1979 году 9 и устроена настолько просто, что её можно объяснить за минуту.

ключи:  для каждого из 256 бит — пара секретов sk[i][0], sk[i][1]
        открытый ключ: pk[i][b] = H(sk[i][b])
подпись: для каждого бита дайджеста d[i] раскрыть sk[i][d[i]]
проверка: для каждого i проверить H(sig[i]) == pk[i][d[i]]

Стойкость следует из односторонности хеша: зная H(x), нельзя найти x. Подделка подписи требует найти прообраз — то есть сломать хеш.

Цена — размер. Для 256-битного дайджеста открытый ключ и секрет занимают по 16 КБ (256 пар по 32 байта), а подпись — 8 КБ. И главное: подпись одноразовая. Две подписи разными сообщениями раскрывают секреты для всех битов, где дайджесты различаются, — а в среднем это половина битов. После этого подделать подпись любого сообщения несложно.

Лэмпорт и дерево Меркла
Каждая подпись раскрывает по одному секрету на бит; дерево Меркла позволяет использовать много одноразовых ключей с одним открытым ключом

Меркл и XMSS/LMS

Меркл в 1989 году предложил решение 10: сгенерировать много одноразовых ключей, построить над ними дерево Меркла и опубликовать только корень. Подпись тогда состоит из одноразовой подписи и пути в дереве.

Для восьми ключей путь — три хеша по 32 байта, то есть 96 байт дополнительно. Для 2^20 ключей — уже 20 хешей, 640 байт, зато одноразовых подписей хватает надолго. Схемы XMSS и LMS стандартизованы и используются там, где нужна стойкость без алгебраических предположений: в прошивках, в подписи обновлений, в долгоживущих системах.

Главная практическая опасность XMSS и LMS — состояние. Каждая подпись использует одноразовый лист, и номер использованного листа нужно хранить. Если восстановить подписывающую машину из резервной копии и подписать ещё раз тем же листом, получится ровно та же катастрофа, что и при повторе nonce в ECDSA (тема 13): два разных сообщения с одним одноразовым ключом раскрывают ключ.

Полезно посчитать. Для 2^20 подписей дерево Меркла требует хранить 2^21 узлов, то есть около 64 МБ хешей, и время генерации ключа — минуты. Для 2^10 подписей это уже 64 КБ и секунды. Отсюда практика: либо дерево на миллион подписей с офлайн-генерацией, либо иерархия из деревьев поменьше.

Ограничение остаётся: число подписей фиксировано заранее. Исчерпали дерево — нужен новый открытый ключ. Отсюда практика: либо дерево на миллионы подписей, либо иерархия деревьев.

SLH-DSA

SLH-DSA (FIPS 205 5) — стандартизованный вариант SPHINCS+, то есть хеш-подпись с деревом и «немного Stateless»: подписывающий не хранит состояние между подписями. Это важно: XMSS и LMS требуют хранить счётчик использованных листьев, и его потеря (восстановление из резервной копии) означает повторное использование одноразового ключа — катастрофу.

Проверка хеш-подписи дешевле подписания: нужно пересчитать хеши по пути и сравнить с корнем. Подписание дороже, потому что требует построить путь и, в случае stateless-схемы, пройти несколько уровней дерева. Для сервера, который подписывает редко, а проверяет часто, это удобно; для устройства, которое подписывает постоянно, — не очень.

SLH-DSA решает проблему состояния ценой размера и скорости: подпись 7856 байт, подписание — миллисекунды-секунды. Зато стойкость опирается только на хеш-функцию, а состояние не нужно вовсе.

Внедрение: гибриды и гибкость

X25519MLKEM768

Гибридный обмен — компромисс между «уже можно» и «ещё страшно». Идея: выполнить два обмена одновременно, классический и постквантовый, и скомбинировать секреты через KDF. Стойкость сохраняется, если не сломан хотя бы один из компонентов.

Как именно комбинируются секреты? Не сложением и не «взять первый». Стандартный приём — конкатенация и KDF: secret = HKDF(X25519-секрет ‖ ML-KEM-секрет, context). Такая конструкция сохраняет стойкость, если хотя бы один из входов случаен и неизвестен противнику, — а второй при этом может быть полностью скомпрометирован. Если бы секреты складывали побитово, компрометация одного давала бы знание разности и ослабляла другой.

Отдельный вопрос — аутентификация. Гибридный обмен защищает от пассивного противника с квантовым компьютером, но подпись сервера всё ещё классическая. Значит, активный противник с квантовым компьютером теоретически может подделать подпись и встать посередине. Именно поэтому стандарты предусматривают и гибридные подписи: ML-DSA вместе с Ed25519.

В TLS 1.3 это просто ещё одна группа: X25519MLKEM768. Клиент присылает key_share, содержащий и X25519-ключ, и ML-KEM-768-ключ; сервер отвечает тем же; общий секрет — результат комбинирования.

Поддержка зависит от версии: ML-KEM появился в OpenSSL 3.5, а гибридные группы — там же. Проверим, что есть в системе, и посмотрим на размеры ключей.

openssl list -kem-algorithms | grep -i ml-kem
openssl genpkey -algorithm ML-KEM-768 -out mlkem.pem
openssl pkey -in mlkem.pem -pubout -outform DER | wc -c

В OpenSSL 3.6 вывод первой команды содержит ML-KEM-512, ML-KEM-768, ML-KEM-1024 и гибриды X25519MLKEM768, X448MLKEM1024, SecP256r1MLKEM768. Вторая и третья команды дают открытый ключ ML-KEM-768 размером 1206 байт в DER (1184 байта чистого ключа плюс заголовок).

Цена видна в размерах.

openssl s_client -connect 127.0.0.1:8443 -tls1_3 -groups X25519 -msg
openssl s_client -connect 127.0.0.1:8443 -tls1_3 -groups X25519MLKEM768 -msg

Обе команды требуют OpenSSL 3.5 или новее; на 3.0 вторая завершится ошибкой «неизвестная группа», и это ожидаемо. Разница в размере ClientHello — 221 байт против 1399 байт для гибрида. Эти 1178 байт почти ровно равны открытому ключу ML-KEM-768 (1184 байта), и именно они определяют цену гибрида для сети.

Что зависит от версии, а что нет

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

СведениеСтатусКак формулировать
FIPS 203, 204, 205 опубликованы в августе 2024 годастабильное«стандарты 2024 года»
Размеры ключей и подписей ML-KEM/ML-DSAстабильное«открытый ключ ML-KEM-768 — 1184 байта»
Конструкция гибрида через конкатенацию и KDFстабильное«HKDF(X25519 ‖ ML-KEM)»
Наличие ML-KEM в OpenSSLверсионное«в OpenSSL 3.5 и новее»
Список гибридных групп в OpenSSLверсионное«на 3.5: X25519MLKEM768; состав списка уточняется по openssl list»
Группа по умолчанию в браузерахверсионное и подвижное«на момент проверки, <дата>, Chrome предлагал …»
ML-KEM в cryptographyверсионное«в 45.0 и новее»
Рекомендации NIST/OWASP по параметрамредакционное«в редакции <год>»

Правило простое: если утверждение содержит номер версии или слово «по умолчанию», оно проверяется командой openssl version или python3 -c "import cryptography; print(cryptography.__version__)" перед тем, как попасть в отчёт. Если версия не совпадает с ожидаемой, это фиксируется одной строкой, а не подгоняется под текст.

Гибридный обмен в TLS 1.3
Секрет = KDF(X25519-секрет ‖ ML-KEM-секрет): стойкость держится, пока не сломан хотя бы один компонент

С подписями ситуация сложнее. Сертификат с ML-DSA-65 добавляет к цепочке около двух килобайт вместо 91 байта у P-256, а подпись в CertificateVerify — ещё 3,3 КБ. Для одной цепочки из трёх сертификатов это уже десяток килобайт, и часть старых клиентов просто не примет такой ClientHello/Certificate. Поэтому внедрение подписей идёт медленнее, чем обмена ключами: обмен можно сделать гибридным незаметно, а подпись видна всем.

На практике это означает, что рукопожатие вырастает на один-два пакета и что часть старых устройств может упереться в MTU. Браузеры и крупные CDN включают гибрид по умолчанию, а серверы постепенно догоняют.

Криптографическая гибкость и инвентаризация

Crypto-agility — способность системы менять алгоритмы без переделки архитектуры. Звучит просто, но на практике всё упирается в инвентаризацию: нужно знать, где и какие алгоритмы используются.

Минимальный план перехода выглядит так.

  1. Инвентаризация. Собрать все места, где есть криптография: TLS, подписи кода, сертификаты, шифрование данных, токены, прошивки. Для каждого — алгоритм, длина ключа, срок жизни данных.
  2. Приоритизация. Сначала — долгоживущие данные и долгоживущие ключи: то, что переживёт появление компьютера.
  3. Гибриды. Включить гибридный обмен там, где поддержка уже есть, — это дешёвый шаг без изменения архитектуры.
  4. Готовность к смене подписи. Проверить, что формат сертификатов и подписей допускает новые алгоритмы (это не всегда так: старые форматы фиксируют OID).
  5. Мониторинг. Отслеживать, какие алгоритмы реально используются, а не какие заявлены в конфигурации.

Моска сформулировал это как правило: срок защиты данных плюс срок миграции должны укладываться в срок до появления компьютера 14. NIST в IR 8547 уточняет план: устаревшие алгоритмы объявляются deprecated, затем disallowed, и переход растянут на годы 12.

Практика безопасного применения

Что использовать в 2026 году

Сводная таблица по всему курсу — то, что стоит помнить, если из головы выветрится всё остальное.

ЗадачаРекомендацияНе использовать
Симметричное шифрованиеAES-256-GCM, ChaCha20-Poly1305AES-ECB, CBC без MAC, RC4, 3DES
ХешированиеSHA-256/SHA-384, SHA-3MD5, SHA-1
ПаролиArgon2id, scryptMD5, SHA-1, «SHA-256 с солью» без растяжения
MACHMAC-SHA-256, Poly1305 в AEADсамодельные «хеш с ключом», сравнение через ==
Обмен ключамиX25519, гибрид X25519MLKEM768статический RSA, экспортные DH-группы
ПодписьEd25519, ECDSA P-256, ML-DSA (гибрид)RSA-1024, ECDSA с плохим nonce
СертификатыX.509 с SAN, CT, OCSP staplingCN вместо SAN, самоподписанные в продакшене
Генерация случайностиsecrets, os.urandom, getrandomrandom, время, PID, счётчики
Хранение секретовKMS, HSM, переменные окружения вне кодаконстанты в исходниках, git

Хорошая библиотека экономит не строки, а решения. Сравните два подхода к одной задаче — зашифровать сообщение с аутентификацией.

# высокоуровневый вариант: всё уже собрано правильно
from cryptography.fernet import Fernet

key = Fernet.generate_key()
token = Fernet(key).encrypt(b"secret")
assert Fernet(key).decrypt(token) == b"secret"

# низкоуровневый вариант: AES-GCM, IV и тег — на вашей совести
import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

key = AESGCM.generate_key(bit_length=256)
iv = os.urandom(12)
ct = AESGCM(key).encrypt(iv, b"secret", b"aad")
assert AESGCM(key).decrypt(iv, ct, b"aad") == b"secret"

Fernet — это AES-CBC с HMAC, версией формата и меткой времени, собранный так, чтобы неправильно использовать его было трудно. AES-GCM даёт больше свободы и больше способов ошибиться: забыть AAD, переиспользовать IV, не проверить тег. Правило простое: если высокоуровневый API решает задачу — берите его.

Таблица — ориентир, а не догма: в регулируемой среде могут требоваться ГОСТ-алгоритмы, а в унаследованной системе — поддерживать то, что уже есть. Но отклонение должно быть осознанным и задокументированным.

Типичные ошибки и CWE

Классификация помогает не повторять чужие ошибки. Ниже — то, что встречается в учебном коде чаще всего 13.

CWEЧто этоКак выглядит
CWE-327использование сломанного или рискованного алгоритмаMD5 для паролей, ECB для файлов, DES
CWE-328слабая хеш-функцияSHA-1 для подписи, «хеш вместо KDF»
CWE-330недостаточно случайные значенияrandom для nonce, счётчик вместо случайности
CWE-331недостаточная энтропиявремя, PID, rand() без seed
CWE-338предсказуемый генераторrandom.seed(42) для ключей
CWE-798зашитые учётные данныеключ в исходнике, пароль в репозитории
CWE-329статический IVодин и тот же IV для всех сообщений
CWE-353отсутствие проверки целостностишифрование без MAC
CWE-347неверная проверка подписипроверка «подпись непустая» вместо криптопроверки
CWE-208утечка через времясравнение MAC через ==
CWE-916недостаточная стоимость хешированияодин SHA-256 вместо Argon2id

Лабораторная работа даёт модуль с десятью такими ошибками — их нужно найти, классифицировать и исправить. Это самое полезное упражнение курса: узнать ошибку в чужом коде проще, чем не допустить её в своём.

Управление секретами

Секреты в коде — отдельная категория, потому что они не «ошибка алгоритма», а ошибка процесса. Правила простые.

  • Секрет живёт в хранилище секретов (KMS, Vault, переменные окружения), а не в исходниках и не в git.
  • У каждого секрета есть владелец, срок жизни и процедура ротации.
  • Секрет, попавший в репозиторий, считается скомпрометированным, даже если коммит удалён: история есть у всех.
  • Логи не содержат секретов и ключей; отладочные дампы — тоже.
  • Резервные копии ключей защищены так же, как сами ключи.

Отдельная тема — зависимости. Криптографическая ошибка часто приходит не из своего кода, а из библиотеки: устаревший OpenSSL, самодельная обёртка над cryptography, «свой» парсер сертификатов. Инвентаризация зависимостей и отслеживание CVE — часть гигиены, а не бюрократия. Хорошая практика: минимум зависимостей, фиксация версий, автоматическое обновление с тестами.

И ещё одна тонкость: постоянное время. Сравнение MAC, проверка дополнения, разбор токена — всё это не должно зависеть от секретных данных по времени выполнения. В Python для этого есть hmac.compare_digest, в C — свои приёмы, но главное — не писать if token == expected.

Регуляторика

В России применение криптографии регулируется: для защиты информации в государственных системах и для квалифицированных подписей используются сертифицированные средства криптографической защиты информации (СКЗИ), чаще всего на алгоритмах ГОСТ. ГОСТ Р 34.10-2012 и ГОСТ Р 34.11-2012 — это подпись и хеш; ГОСТ Р 34.12-2015 — блочный шифр («Кузнечик», «Магма»).

Есть и более общий принцип: регуляторика отвечает на вопрос «можно ли применять», а не «безопасно ли это». Сертификат соответствия не заменяет анализ угроз, а анализ угроз не заменяет сертификат. В проекте нужны оба, и лучше, если они не противоречат друг другу.

Практические следствия:

  • для квалифицированной электронной подписи нужен аккредитованный УЦ и сертифицированное СКЗИ (тема 14);
  • для государственных информационных систем — требования ФСТЭК и ФСБ, включая классы защиты;
  • для TLS с ГОСТ-алгоритмами нужны сертифицированные реализации; в общем случае это отдельный стек, а не «OpenSSL с другой кривой»;
  • для коммерческих систем вне регулируемой сферы ограничений на алгоритмы нет, но контрагент может требовать ГОСТ по договору.

Отдельно стоит помнить: сертификация — это про соответствие требованиям, а не про отсутствие уязвимостей. Сертифицированное СКЗИ может иметь ошибку в парсинге; несертифицированная библиотека может быть безупречна. Это разные оси.

Итоги темы

Квантовый компьютер ломает асимметричную криптографию алгоритмом Шора и вдвое ослабляет симметричную алгоритмом Гровера. Оценки ресурсов велики (миллионы кубитов и часы работы для RSA-2048), но угроза «сохрани сейчас — расшифруй потом» делает ожидание опасным: данные, перехваченные сегодня, могут быть расшифрованы позже.

Стандарты 2024 года дают готовые замены: ML-KEM для обмена ключами, ML-DSA и SLH-DSA для подписей. Решёточные схемы компактнее и быстрее, хеш-подписи надёжнее по предположениям, коды дают крошечные шифртексты при огромных ключах. Взлом SIKE напоминает, что публичный анализ не гарантирует стойкости, и потому стандартов несколько.

Учебная криптография на решётках показывает суть: LWE — это система линейных уравнений с малым шумом, и весь секрет в шуме. Без шума она решается методом Гаусса; с шумом — нет. Хеш-подписи идут другим путём: Лэмпорт даёт одноразовую подпись из односторонней функции, дерево Меркла превращает её в многократную, SLH-DSA убирает состояние ценой размера.

Внедрение идёт через гибриды: X25519MLKEM768 в TLS добавляет около килобайта к рукопожатию и сохраняет стойкость, пока не сломан хотя бы один компонент. Криптографическая гибкость и инвентаризация — не бюрократия, а условие перехода.

И последнее, что важнее всех алгоритмов: безопасность определяется не выбором «самой стойкой схемы», а дисциплиной. Постоянное время, случайность из правильного источника, секреты вне кода, проверка целостности, аккуратная обработка ошибок. Список CWE в этой теме — по сути, чек-лист того, что ломается в реальных системах чаще, чем любая математика.

Литература

  1. Shor P. W. Polynomial-Time Algorithms for Prime Factorization and Discrete Logarithms on a Quantum Computer. — SIAM Journal on Computing, 1997, Т. 26, № 5, С. 1484–1509. DOI: 10.1137/S0097539795293172
  2. Grover L. K. A Fast Quantum Mechanical Algorithm for Database Search. — Proceedings of the 28th Annual ACM Symposium on Theory of Computing (STOC), 1996, С. 212–219. DOI: 10.1145/237814.237866
  3. NIST. Module-Lattice-Based Key-Encapsulation Mechanism Standard. — FIPS 203, 2024. DOI: 10.6028/NIST.FIPS.203
  4. NIST. Module-Lattice-Based Digital Signature Standard. — FIPS 204, 2024. DOI: 10.6028/NIST.FIPS.204
  5. NIST. Stateless Hash-Based Digital Signature Standard. — FIPS 205, 2024. DOI: 10.6028/NIST.FIPS.205
  6. Regev O. On Lattices, Learning with Errors, Random Linear Codes, and Cryptography. — Journal of the ACM, 2009, Т. 56, № 6, С. 1–40. DOI: 10.1145/1568318.1568324
  7. Gidney C., Ekerå M. How to Factor 2048 Bit RSA Integers in 8 Hours Using 20 Million Noisy Qubits. — Quantum, 2021, Т. 5, С. 433. DOI: 10.22331/q-2021-04-15-433
  8. Castryck W., Decru T. An Efficient Key Recovery Attack on SIDH. — Advances in Cryptology — EUROCRYPT 2023, Springer, 2023, С. 423–447. DOI: 10.1007/978-3-031-30589-4_15
  9. Lamport L. Constructing Digital Signatures from a One-Way Function. — Technical Report CSL-98, SRI International, 1979.
  10. Merkle R. C. A Certified Digital Signature. — Advances in Cryptology — CRYPTO '89, Springer, 1990, С. 218–238. DOI: 10.1007/0-387-34805-0_21
  11. Bernstein D. J., Lange T. Post-Quantum Cryptography. — Nature, 2017, Т. 549, С. 188–194. DOI: 10.1038/nature23461
  12. NIST. Transition to Post-Quantum Cryptography Standards. — NIST IR 8547 (initial public draft), 2024. DOI: 10.6028/NIST.IR.8547.ipd
  13. MITRE. Common Weakness Enumeration (CWE). — https://cwe.mitre.org
  14. Mosca M. Cybersecurity in an Era with Quantum Computers: Will We Be Ready? — IEEE Security & Privacy, 2018, Т. 16, № 5, С. 38–41. DOI: 10.1109/MSP.2018.3761723