openjdk.ruOpenJDK на русском

JEP 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism

Механизм инкапсуляции ключей на основе модульных решёток, устойчивый к квантовым вычислениям

ОтветственныйWeijun Wang
ТипFeature
ОбластьSE
СтатусClosed / Delivered
Выпуск24
Компонентsecurity-libs / javax.crypto
Обсуждениеsecurity dash dev at openjdk dot org
ТрудоёмкостьM
ДлительностьS
РецензентыSean Mullan
ОдобренAlan Bateman, Sean Mullan
Создан2024/08/26 18:33
Обновлён2025/03/13 14:49
Задача8339009

Аннотация

Повысить безопасность Java-приложений за счёт реализации устойчивого к квантовым вычислениям механизма инкапсуляции ключей на основе модульных решёток (Module-Lattice-Based Key-Encapsulation Mechanism, ML-KEM). Механизмы инкапсуляции ключей (KEM) служат для защиты симметричных ключей при передаче по незащищённым каналам связи с помощью криптографии с открытым ключом. ML-KEM разработан так, чтобы оставаться стойким к будущим атакам с использованием квантовых вычислений. Он стандартизирован Национальным институтом стандартов и технологий США (NIST) в FIPS 203.

Цели

  • Предоставить реализации ML-KEM для API KeyPairGenerator, KEM и KeyFactory с поддержкой наборов параметров ML-KEM-512, ML-KEM-768 и ML-KEM-1024, стандартизированных в FIPS 203.

Что не является целью

  • Реализация алгоритма Kyber, на основе которого создан ML-KEM, не является целью. Эти два алгоритма несовместимы между собой.

  • Добавление поддержки ML-KEM в компоненты платформы Java, для которых ещё нет необходимых стандартов, не является целью. В частности, это относится к реализации протокола Transport Layer Security (TLS) в пакете javax.net.ssl. Мы добавим такую поддержку, когда соответствующие стандарты появятся.

Мотивация

Область квантовых вычислений уже много лет стабильно развивается. Будущий крупномасштабный квантовый компьютер сможет с помощью алгоритма Шора, который умеет раскладывать целые числа на множители и решать задачу дискретного логарифмирования, нарушить безопасность широко используемых алгоритмов с открытым ключом, включая Rivest-Shamir-Adleman (RSA) и Diffie-Hellman. Платформа Java использует такие алгоритмы, помимо прочего, для цифровой подписи JAR-файлов и для установления защищённых сетевых соединений по протоколу Transport Layer Security (TLS). Атаку, на которую обычному суперкомпьютеру могли бы потребоваться от тысяч до миллионов лет, квантовый компьютер с алгоритмом Шора мог бы выполнить всего за несколько часов.

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

Для обмена ключами способом, устойчивым к квантовым вычислениям, NIST стандартизировал механизм инкапсуляции ключей на основе модульных решёток (ML-KEM) в FIPS 203. В США государственные компьютерные системы, обрабатывающие конфиденциальную информацию, должны в течение следующего десятилетия перейти на ML-KEM. Поэтому платформе Java необходимо предоставить реализацию этого алгоритма.

Описание

Как описано в JEP 452, KEM состоит из трёх функций:

  • Функция генерации пары ключей возвращает пару ключей, состоящую из открытого и закрытого ключа.

  • Функция инкапсуляции ключа вызывается отправителем и принимает открытый ключ получателя и параметр шифрования; она возвращает секретный ключ K и сообщение инкапсуляции ключа. Отправитель пересылает сообщение инкапсуляции ключа получателю.

  • Функция декапсуляции ключа вызывается получателем и принимает закрытый ключ получателя и полученное сообщение инкапсуляции ключа; она возвращает секретный ключ K.

Для первой функции мы предоставим реализацию API KeyPairGenerator, которая генерирует пары ключей ML-KEM. Для второй и третьей функций мы предоставим реализацию API KEM, которая согласует общие секретные ключи на основе пары ключей ML-KEM. Мы также предоставим реализацию API KeyFactory, которая преобразует ключи ML-KEM в их кодированное представление и обратно.

В Java Security Standard Algorithm Names Specification мы определим новое стандартное имя семейства алгоритмов "ML-KEM" для API KeyPairGenerator, KEM и KeyFactory.

FIPS 203 определяет для ML-KEM три набора параметров. В порядке возрастания криптостойкости и снижения производительности они называются "ML-KEM-512", "ML-KEM-768" и "ML-KEM-1024". Эти имена наборов параметров также будут определены как стандартные имена алгоритмов для API KeyPairGenerator, KEM и KeyFactory, а кроме того, будут представлены новыми константами NamedParameterSpec: ML_KEM_512, ML_KEM_768 и ML_KEM_1024.

Генерация пар ключей ML-KEM

Сгенерировать пару ключей ML-KEM можно одним из трёх способов:

  • Создать KeyPairGenerator по имени семейства и инициализировать его именем набора параметров:

    KeyPairGenerator g = KeyPairGenerator.getInstance("ML-KEM");
    g.initialize(NamedParameterSpec.ML_KEM_512);
    KeyPair kp = g.generateKeyPair(); // an ML-KEM-512 key pair
  • Если не инициализировать KeyPairGenerator набором параметров, реализация по умолчанию использует ML-KEM-768:

    KeyPairGenerator g = KeyPairGenerator.getInstance("ML-KEM");
    KeyPair kp = g.generateKeyPair(); // an ML-KEM-768 key pair
  • Создать KeyPairGenerator непосредственно по имени набора параметров:

    KeyPairGenerator g = KeyPairGenerator.getInstance("ML-KEM-1024");
    KeyPair kp = g.generateKeyPair(); // an ML-KEM-1024 key pair

API KeyPairGenerator позволяет указать при инициализации целочисленный размер ключа, но для пар ключей ML-KEM это не поддерживается и приведёт к выбросу InvalidParameterException.

Команда keytool будет поддерживать генерацию пар ключей и сертификатов ML-KEM. Например, чтобы сгенерировать пару ключей ML-KEM и подписать сертификат ключом EC:

$ keytool -keystore ks -storepass changeit -genkeypair -alias ec \
          -keyalg ec -dname CN=ec -ext bc
$ keytool -keystore ks -storepass changeit -genkeypair -alias mlkem \
          -keyalg ML-KEM -groupname ML-KEM-768 -dname CN=ML-KEM -signer ec

Первая команда создаёт пару ключей EC; вторая создаёт пару ключей ML-KEM и сертификат, подписанный ключом EC. Мы подписываем сертификат ключом EC, потому что ML-KEM сам по себе не является алгоритмом подписи и поэтому не может использоваться для подписи сертификата, содержащего открытый ключ ML-KEM.

Имя набора параметров (ML-KEM-768) можно также указать непосредственно в параметре -keyalg:

$ keytool -keystore ks -storepass changeit -genkeypair -alias mlkem2 \
          -keyalg ML-KEM-768 -dname CN=ML-KEM2 -signer ec

Инкапсуляция и декапсуляция ключей ML-KEM

Для согласования общего секретного ключа можно использовать реализацию KEM для ML-KEM.

Например, отправитель может вызвать функцию инкапсуляции, чтобы получить секретный ключ и сообщение инкапсуляции ключа:

KEM ks = KEM.getInstance("ML-KEM");
KEM.Encapsulator enc = ks.newEncapsulator(publicKey);
KEM.Encapsulated encap = enc.encapsulate();
byte[] msg = encap.encapsulation();     // send this to receiver
SecretKey sks = encap.key();

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

byte[] msg = ...;                       // received from sender
KEM kr = KEM.getInstance("ML-KEM");
KEM.Decapsulator dec = kr.newDecapsulator(privateKey);
SecretKey skr = dec.decapsulate(msg);

sks и skr содержат одинаковый ключевой материал, известный только отправителю и получателю.

Если объект KEM создан по имени семейства, он принимает ключи ML-KEM этого семейства с любым набором параметров. Если он создан по имени набора параметров, он принимает только ключи ML-KEM, использующие этот набор параметров; в противном случае методы newEncapsulator и newDecapsulator выбрасывают InvalidKeyException.

Кодирование и декодирование ключей ML-KEM

С помощью реализации KeyFactory для ML-KEM можно преобразовать закрытый ключ ML-KEM в кодировку PKCS #8 и обратно или открытый ключ ML-KEM в кодировку X.509 и обратно.

Например, чтобы преобразовать закрытый ключ ML-KEM в кодировку PKCS #8 и обратно:

KeyFactory f = KeyFactory.getInstance("ML-KEM");
PKCS8EncodedKeySpec p8spec = f.getKeySpec(kp.getPrivate(),
                                          PKCS8EncodedKeySpec.class);
PrivateKey sk2 = f.generatePrivate(p8spec);

Аналогично, чтобы преобразовать открытый ключ ML-KEM в кодировку X.509 и обратно:

X509EncodedKeySpec x509spec = f.getKeySpec(kp.getPublic(),
                                           X509EncodedKeySpec.class);
PublicKey pk2 = f.generatePublic(x509spec);

Реализация KeyFactory может также преобразовать ключ другого провайдера безопасности с помощью метода translateKey, если формат его кодировки поддерживается.

Метод getAlgorithm объекта Key, созданного реализацией KeyPairGenerator или KeyFactory для ML-KEM, всегда возвращает имя семейства "ML-KEM", независимо от того, был ли KeyPairGenerator или KeyFactory создан по имени семейства "ML-KEM" или по одному из имён наборов параметров. Метод getParams ключа ML-KEM возвращает объект NamedParameterSpec, соответствующий имени набора параметров ключа.

Если объект KeyFactory создан по имени семейства, он кодирует и декодирует ключи ML-KEM этого семейства с любым набором параметров. Если он создан по имени набора параметров, он кодирует и декодирует только ключи ML-KEM, использующие этот набор параметров; в противном случае метод translateKey выбрасывает InvalidKeyException, а методы generatePrivate, generatePublic и getKeySpec выбрасывают InvalidKeySpecException.

Кодировка, используемая KeyFactory для ML-KEM, определена в черновике RFC IETF. Мы будем отслеживать изменения в этом черновике до его публикации.

Альтернативы

  • Проект Open Quantum Safe предоставляет обёртку JNI для своей библиотеки liboqs на C, в которой реализован набор устойчивых к квантовым вычислениям алгоритмов, включая Kyber и ML-KEM. Если Open Quantum Safe достигнет своей цели и станет основной реализацией устойчивой к квантовым вычислениям криптографии для крупных проектов, таких как OpenSSL, BoringSSL, OpenSSH и Mozilla, то благодаря широкому тестированию и использованию она заметно выиграет в производительности и надёжности.

    По сравнению с нативной реализацией главное преимущество реализации ML-KEM на Java в том, что она встроена непосредственно в JDK. Благодаря этому она сразу доступна на всех платформах, на которые JDK уже портирован.

Тестирование

  • Модульные тесты подтвердят, что реализации соответствуют спецификациям API KeyGenerator, KeyFactory и KEM, в том числе в граничных случаях, таких как недопустимые входные параметры, граничные значения и неподдерживаемые операции.

  • Тесты с известными ответами (Known Answer Tests, KAT) охватят как корректные криптографические операции (позитивные случаи), так и некорректные операции или известные уязвимости (негативные случаи), обеспечивая всестороннюю проверку. В их числе будут, помимо прочего:

  • Тесты совместимости с реализациями других поставщиков, включая, помимо прочего, liboqs, подтвердят, что наша реализация ML-KEM корректно работает с другими.