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

JEP 478: Key Derivation Function API (Preview)

Key Derivation Function API, версия Preview (предварительная версия)

ОтветственныйKevin Driver
ТипFeature
ОбластьSE
СтатусClosed / Delivered
Выпуск24
Компонентsecurity-libs / javax.crypto
Обсуждениеsecurity dash dev at openjdk dot org
ТрудоёмкостьM
ДлительностьM
Связан сJEP 510: Key Derivation Function API
РецензентыSean Mullan
ОдобренSean Mullan
Создан2017/10/23 16:56
Обновлён2026/02/27 18:34
Задача8189808

Аннотация

Мы вводим API для функций формирования ключей (Key Derivation Functions, KDF). Это криптографические алгоритмы, которые формируют дополнительные ключи из секретного ключа и других данных. Это API в статусе Preview.

Цели

  • Дать приложениям возможность использовать такие алгоритмы KDF, как HMAC-based Extract-and-Expand Key Derivation Function (HKDF, RFC 5869) и Argon2 (RFC 9106).

  • Дать возможность использовать KDF в реализациях механизма инкапсуляции ключей (Key Encapsulation Mechanism, KEM, JEP 452), например в ML-KEM, в протоколах более высокого уровня, например в Hybrid Key Exchange in TLS 1.3, и в криптографических схемах, например в гибридном шифровании с открытым ключом (Hybrid Public Key Encryption, HPKE, RFC 9180).

  • Позволить провайдерам безопасности реализовывать алгоритмы KDF как на Java, так и в нативном коде.

  • Включить реализацию HKDF и добавить дополнительные API, специфичные для HKDF.

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

  • Сделать существующие реализации функций формирования ключей на основе пароля PBKDF1 и PBKDF2 доступными через новый KDF API не является целью. Эти реализации останутся доступны через существующий API SecretKeyFactory.

  • Предоставить реализацию HKDF для PKCS#11 не является целью. Мы намерены сделать это в рамках отдельного улучшения.

  • Переработать функции формирования ключей, используемые в реализации TLS в JDK, так, чтобы они использовали новый KDF API, не является целью. Однако мы можем сделать это в последующей работе.

Мотивация

Функции формирования ключей (KDF) используют криптографические входные данные, такие как исходный ключевой материал, значение соли и псевдослучайная функция, чтобы создать новый криптографически стойкий ключевой материал. KDF часто используют для создания криптографических данных, из которых можно получить несколько ключей. KDF позволяет создавать ключи так, что это одновременно безопасно и воспроизводимо двумя сторонами, которым известны входные данные.

Формирование ключей похоже на хэширование паролей. KDF использует хэш с ключом вместе с дополнительной энтропией из других своих входных данных, чтобы либо извлечь новый ключевой материал, либо безопасно расширить значения в более длинный поток ключевого материала.

С появлением квантовых вычислений классические криптографические алгоритмы будут всё более уязвимы для практических атак. Поэтому для платформы Java крайне важно поддерживать постквантовую криптографию (Post-Quantum Cryptography, PQC), устойчивую к этим атакам. Со временем мы намерены добиться этого за счёт поддержки гибридного шифрования с открытым ключом (HPKE), которое обеспечивает плавный переход на алгоритмы шифрования, устойчивые к квантовым атакам. KEM API (JEP 452), интегрированный в JDK 21, — один из строительных блоков HPKE и наш первый шаг к HPKE и готовности к постквантовой эпохе. Предлагаемый здесь KDF API — ещё один строительный блок HPKE, и он станет вторым шагом.

Расширяемость, которую даёт добавление KDF API, принесёт и дополнительные преимущества. Стандарт PKCS#11 для криптографических аппаратных устройств уже много лет описывает поддержку KDF. Если сделать эту технологию доступной через API javax.crypto, это пойдёт на пользу приложениям и библиотекам, которые работают с такими устройствами. Кроме того, разработчики сторонних криптопровайдеров смогут предлагать собственные реализации KDF, в частности прошедшие проверку при тестировании и затем сертифицированные National Institute of Standards and Technology.

Наконец, крайне важно, чтобы платформа Java предлагала лучшую поддержку API для KDF хэширования паролей, более совершенных, чем PBKDF1 и PBKDF2, таких как Argon2. Ни один из существующих криптографических API платформы Java сейчас не способен естественным образом представить KDF (см. ниже). Разработчики сторонних провайдеров безопасности уже заявляли о потребности в стандартном KDF API.

Описание

У функции формирования ключей есть две основные операции:

  • Создание экземпляра и инициализация: создаёт KDF и инициализирует её подходящими параметрами, и

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

Мы определяем новый класс javax.crypto.KDF для представления функций формирования ключей.

Это API в статусе Preview, по умолчанию отключённый

Чтобы использовать этот новый API в JDK 24, нужно включить Preview-возможности:

  • Скомпилируйте программу с javac --release 24 --enable-preview Main.java и запускайте её с java --enable-preview Main; или

  • При использовании средства запуска исходного кода запускайте программу с java --enable-preview Main.java; или

  • При использовании jshell запускайте его с jshell --enable-preview.

Создание экземпляра и инициализация

Класс KDF предоставляет обычный набор методов getInstance с обычными комбинациями параметров, включая необязательные KDFParameters и имена криптопровайдеров. Методы getInstance одновременно создают экземпляр KDF и инициализируют его алгоритм.

Алгоритму HKDF — единственной KDF, которую мы намерены включить на данный момент, — объект KDFParameters не нужен. Однако другим алгоритмам, например SHAKE, он может понадобиться.

Формирование

Класс KDF определяет два метода для формирования ключей:

  • deriveKey(String alg, AlgorithmParameterSpec spec) создаёт объект SecretKey, используя указанный алгоритм и в соответствии с указанными параметрами.

  • deriveData(AlgorithmParameterSpec spec) возвращает массив байтов, который можно использовать как источник энтропии или если ключевой материал нужен именно в таком виде.

Мы используем пустой интерфейс AlgorithmParameterSpec, поскольку разные алгоритмы KDF принимают разные параметры. Реализация KDF должна определять один или несколько подклассов AlgorithmParameterSpec для описания своих параметров.

Для включённой реализации HKDF мы предоставляем три таких подкласса, каждый из которых представляет входные данные для отдельного режима работы:

Объемлющий интерфейс HKDFParameterSpec определяет статические фабричные методы для создания экземпляров этих трёх классов. Он также определяет класс-построитель HKDFParameterSpec.Builder для сборки ключевого материала для операций извлечения.

Пример

// Create a KDF object for the specified algorithm
KDF hkdf = KDF.getInstance("HKDF-SHA256"); 

// Create an ExtractExpand parameter specification
AlgorithmParameterSpec params =
    HKDFParameterSpec.ofExtract()
                     .addIKM(initialKeyMaterial)
                     .addSalt(salt).thenExpand(info, 32);

// Derive a 32-byte AES key
SecretKey key = hkdf.deriveKey("AES", params);

// Additional deriveKey calls can be made with the same KDF object

Реализация провайдеров KDF

Реализация KDF должна расширять абстрактный класс javax.crypto.KDFSpi.

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

Дальнейшая работа

  • Переработка TLS 1.3 — мы намерены улучшить реализацию TLS 1.3 в JDK, чтобы она использовала KDF API для формирования ключей через HKDF. Тогда же мы добавим новые функциональные тесты, демонстрирующие эффективность получения реализации KDF через новый API.

    Поначалу мы не планируем делать это для версий TLS до 1.3.

  • Реализация Argon2 — со временем мы намерены реализовать KDF хэширования паролей Argon2.

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

  • Использовать существующие API — мы рассматривали возможность представить KDF с помощью существующих API KeyGenerator и SecretKeyFactory. Более ранние алгоритмы формирования ключей, такие как TLS-PRF, PBKDF1 и PBKDF2, удалось вписать в эти API, но в целом эти API плохо подходят для KDF.

    • KeyGenerator спроектирован вокруг добавления энтропии через объект SecureRandom, чтобы создать недетерминированный ключ из набора входных данных. KDF, напротив, поддерживают независимое формирование одного и того же ключевого материала двумя отдельными сторонами.

    • SecretKeyFactory спроектирован для создания одного ключа. Хотя есть сценарии, в которых KDF может использоваться таким образом, KDF также должны поддерживать последовательные детерминированные формирования из потока ключей.

  • Сделать PBKDF2 доступной через новый API KDF — PBKDF2 быстро вытесняется более стойкими алгоритмами, такими как Argon2. Разработчики, которые уже используют PBKDF2, скорее всего, продолжат использовать её через API SecretKeyFactory, а не станут переделывать существующий код под API KDF. Поэтому делать PBKDF2 доступной через новый API сейчас нецелесообразно, но мы можем сделать это позже, если возникнет веская необходимость.

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

Мы добавим тесты с известными ответами (known-answer, KAT) из RFC 5869, если они доступны, а также тесты обработки исключений и регрессионное тестирование SSL/TLS.