JEP 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm
Квантово-устойчивый алгоритм цифровой подписи на основе модульных решёток
| Ответственный | Weijun Wang |
| Тип | Feature |
| Область | SE |
| Статус | Closed / Delivered |
| Выпуск | 24 |
| Компонент | security-libs / java.security |
| Обсуждение | security dash dev at openjdk dot org |
| Трудоёмкость | M |
| Длительность | M |
| Рецензенты | Sean Mullan |
| Одобрен | Alan Bateman, Sean Mullan |
| Создан | 2024/08/26 18:34 |
| Обновлён | 2025/11/03 22:24 |
| Задача | 8339010 |
Аннотация
Повысить безопасность Java-приложений за счёт реализации квантово-устойчивого алгоритма цифровой подписи на основе модульных решёток (Module-Lattice-Based Digital Signature Algorithm, ML-DSA). Цифровые подписи используются для обнаружения несанкционированных изменений данных и для подтверждения подлинности подписавших. ML-DSA спроектирован так, чтобы оставаться стойким к будущим атакам с использованием квантовых вычислений. Он стандартизован Национальным институтом стандартов и технологий США (NIST) в FIPS 204.
Цели
- Предоставить реализации ML-DSA для API
KeyPairGenerator,SignatureиKeyFactoryс поддержкой наборов параметров ML-DSA-44, ML-DSA-65 и ML-DSA-87, стандартизованных в FIPS 204.
Что не является целью
-
Реализация алгоритма Dilithium, на основе которого создан ML-DSA, не является целью. Эти два алгоритма несовместимы между собой.
-
Добавление поддержки ML-DSA в те компоненты платформы Java, для которых ещё нет необходимых стандартов, не является целью. В частности, это относится к подписи JAR-файлов, а также к реализации протокола Transport Layer Security (TLS) в пакете
javax.net.ssl. Мы добавим такую поддержку, когда стандарты появятся. -
Поддержка Pre-Hash ML-DSA (FIPS 204 §5.4) и возможность задавать строки контекста, специфичные для приложения (FIPS 204 §5.2), не являются целью. Мы можем реализовать эти возможности в одном из будущих выпусков.
Мотивация
Область квантовых вычислений уже много лет стабильно развивается. Будущий крупномасштабный квантовый компьютер сможет с помощью алгоритма Шора, который способен раскладывать целые числа на множители и решать задачу дискретного логарифмирования, нарушить безопасность широко используемых алгоритмов с открытым ключом, включая Rivest-Shamir-Adleman (RSA) и Diffie-Hellman. Платформа Java использует такие алгоритмы, в частности, для цифровой подписи JAR-файлов и для установки защищённых сетевых соединений по протоколу Transport Layer Security (TLS). Атаку, на которую обычному суперкомпьютеру могли бы потребоваться от тысяч до миллионов лет, квантовый компьютер с алгоритмом Шора мог бы выполнить всего за несколько часов. В ответ на эту угрозу криптографы разработали квантово-устойчивые криптографические алгоритмы, которые невозможно взломать алгоритмом Шора.
Для квантово-устойчивой подписи данных и подтверждения подлинности NIST стандартизовал алгоритм цифровой подписи на основе модульных решёток (ML-DSA) в FIPS 204. В США государственные компьютерные системы, обрабатывающие конфиденциальную информацию, должны в течение следующего десятилетия перейти на использование ML-DSA. Поэтому платформе Java крайне важно предоставить реализацию этого алгоритма.
Описание
Мы предоставим реализации ML-DSA для API KeyPairGenerator — для генерации пар ключей ML-DSA, для API Signature — для создания и проверки подписей ML-DSA и для API KeyFactory — для преобразования ключей ML-DSA в их кодированное представление и обратно.
В Java Security Standard Algorithm Names Specification мы определим новое стандартное имя семейства алгоритмов "ML-DSA" для API KeyPairGenerator, Signature и KeyFactory.
FIPS 204 определяет три набора параметров для ML-DSA. В порядке возрастания криптостойкости и снижения производительности они называются "ML-DSA-44", "ML-DSA-65" и "ML-DSA-87". Эти имена наборов параметров также будут определены как стандартные имена алгоритмов для API KeyPairGenerator, Signature и KeyFactory, а кроме того, будут представлены новыми константами NamedParameterSpec: ML_DSA_44, ML_DSA_65 и ML_DSA_87.
Генерация пар ключей ML-DSA
Сгенерировать пару ключей ML-DSA можно одним из трёх способов:
-
Создать экземпляр
KeyPairGeneratorс именем семейства и инициализировать его именем набора параметров:KeyPairGenerator g = KeyPairGenerator.getInstance("ML-DSA"); g.initialize(NamedParameterSpec.ML_DSA_44); KeyPair kp = g.generateKeyPair(); // an ML-DSA-44 key pair -
Если не инициализировать
KeyPairGeneratorнабором параметров, реализация по умолчанию использует ML-DSA-65:KeyPairGenerator g = KeyPairGenerator.getInstance("ML-DSA"); KeyPair kp = g.generateKeyPair(); // an ML-DSA-65 key pair -
Напрямую создать экземпляр
KeyPairGeneratorс именем набора параметров:KeyPairGenerator g = KeyPairGenerator.getInstance("ML-DSA-87"); KeyPair kp = g.generateKeyPair(); // an ML-DSA-87 key pair
API KeyPairGenerator позволяет указать при инициализации целочисленный размер ключа, но для пар ключей ML-DSA это не поддерживается и приведёт к выбросу InvalidParameterException.
Команда keytool будет поддерживать генерацию пар ключей и сертификатов ML-DSA. Например:
$ keytool -keystore ks -storepass changeit -genkeypair -alias mldsa \
-keyalg ML-DSA -groupname ML-DSA-65 -dname CN=ML-DSA
Можно также указать имя набора параметров, ML-DSA-65, напрямую через параметр -keyalg:
$ keytool -keystore ks -storepass changeit -genkeypair -alias mldsa \
-keyalg ML-DSA-65 -dname CN=ML-DSA2
Подпись ключами ML-DSA
Для создания и проверки подписей ML-DSA можно использовать реализацию Signature для ML-DSA.
Например, чтобы подписать сообщение закрытым ключом:
byte[] msg = ...;
Signature ss = Signature.getInstance("ML-DSA");
ss.initSign(privateKey);
ss.update(msg);
byte[] sig = ss.sign();
Чтобы проверить подпись открытым ключом:
byte[] msg = ...;
byte[] sig = ...;
Signature sv = Signature.getInstance("ML-DSA");
sv.initVerify(publicKey);
sv.update(msg);
boolean verified = sv.verify(sig);
Если объект Signature создан с именем семейства, он принимает ключи ML-DSA этого семейства с любым набором параметров. Если он создан с именем набора параметров, он принимает только ключи ML-DSA с этим набором параметров; в противном случае методы initSign и initVerify выбрасывают InvalidKeyException.
Кодирование и декодирование ключей ML-DSA
С помощью реализации KeyFactory для ML-DSA можно преобразовать закрытый ключ ML-DSA в кодировку PKCS #8 и обратно, а открытый ключ ML-DSA — в кодировку X.509 и обратно.
Например, чтобы преобразовать закрытый ключ ML-DSA в кодировку PKCS #8 и обратно:
KeyFactory f = KeyFactory.getInstance("ML-DSA");
PKCS8EncodedKeySpec p8spec = f.getKeySpec(kp.getPrivate(),
PKCS8EncodedKeySpec.class);
PrivateKey sk2 = f.generatePrivate(p8spec);
Аналогично, чтобы преобразовать открытый ключ ML-DSA в кодировку X.509 и обратно:
X509EncodedKeySpec x509spec = f.getKeySpec(kp.getPublic(),
X509EncodedKeySpec.class);
PublicKey pk2 = f.generatePublic(x509spec);
Реализация KeyFactory также может преобразовать ключ другого провайдера безопасности с помощью метода translateKey, если формат его кодировки поддерживается.
Метод getAlgorithm объекта Key, созданного реализацией KeyPairGenerator или KeyFactory для ML-DSA, всегда возвращает имя семейства "ML-DSA", независимо от того, был ли KeyPairGenerator или KeyFactory создан с именем семейства "ML-DSA" или с одним из имён наборов параметров. Метод getParams ключа ML-DSA возвращает объект NamedParameterSpec, соответствующий имени набора параметров ключа.
Если объект KeyFactory создан с именем семейства, он кодирует и декодирует ключи ML-DSA этого семейства с любым набором параметров. Если он создан с именем набора параметров, он кодирует и декодирует только ключи ML-DSA с этим набором параметров; в противном случае метод translateKey выбрасывает InvalidKeyException, а методы generatePrivate, generatePublic и getKeySpec выбрасывают InvalidKeySpecException.
Кодировка, которую использует KeyFactory для ML-DSA, определена в черновике IETF RFC. Мы будем отслеживать изменения этого черновика до его публикации.
Альтернативы
-
Проект Open Quantum Safe предоставляет JNI-обёртку для своей библиотеки
liboqsна C, в которой реализован набор квантово-устойчивых алгоритмов, включая Dilithium и ML-DSA. Если Open Quantum Safe достигнет своей цели и станет основной реализацией квантово-устойчивой криптографии для крупных проектов, таких как OpenSSL, BoringSSL, OpenSSH и Mozilla, то благодаря широкому тестированию и использованию она значительно выиграет в производительности и надёжности.По сравнению с нативной реализацией, реализация ML-DSA на Java даёт ключевое преимущество: она встроена непосредственно в JDK. Поэтому она сразу доступна на всех платформах, на которые JDK уже портирован.
Тестирование
-
Модульные тесты подтвердят, что реализации соответствуют спецификациям API
KeyGenerator,SignatureиKeyFactory, в том числе в граничных случаях, таких как недопустимые входные параметры, граничные значения и неподдерживаемые операции. -
Тесты с известными ответами (Known Answer Tests, KAT) охватят как корректные криптографические операции (позитивные случаи), так и некорректные операции или известные уязвимости (негативные случаи), что обеспечит всестороннюю проверку. В их число войдут, в частности:
-
KAT (здесь, здесь и здесь), сгенерированные сервисом NIST Cryptographic Algorithm Validation Program, и
-
тесты ML-DSA из Project Wycheproof, которые находятся в разработке.
-
-
Тесты совместимости с реализациями других поставщиков, включая, помимо прочего,
liboqs, подтвердят, что наша реализация ML-DSA корректно работает с другими.