Реализуется ли HKDF в архитектуре криптографии Java?

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

В обоих случаях HKDF реализован поверх HMAC, предоставленного JCA. Я еще не читал эти реализации подробно, но мне было интересно, разве это не реализовано нигде в JCA или само по себе? Должен ли я реализовать свой собственный HKDF?

Больше всего меня беспокоит ошибка в применении аргумента информации. Это выглядит нетривиально и критично.

1 ответ

Реализации HKDF на Java

Нет, функция выведения ключа (HKDF) на основе хешированного сообщения аутентификации (HMAC), как и большинство KDF, не имеет стандартной реализации в JCA.

Есть некоторые реализации, встроенные в другие проекты (как вы уже сказали):

Также есть, конечно, Bouncy Castle, который использует свои собственные реализации Hmac/Mac и API. BC, однако, является большой зависимостью и может быть непрактичным, например, для встроенного или мобильного варианта использования. Для этого я реализовал отдельную легковесную библиотеку Java (проходящую через все тестовые векторы RFC 5869), которая работает с любым javax.crypto.Mac пример:

Если вы предпочитаете, вы можете, конечно, реализовать его самостоятельно, это довольно прямолинейная спецификация при использовании встроенной реализации JCA Hmac.

Информационный параметр в HKDF

Из RFC 5869:

Хотя значение 'info' является необязательным в определении HKDF, оно
часто имеет большое значение в приложениях. Его основная цель заключается в
привязать полученный ключевой материал к конкретному приложению и контексту
Информация. (...) В частности, это может предотвратить создание одного и того же ключевого материала для разных контекстов.

Так, например, если вы хотите получить секретный ключ и IV из одного и того же исходного материала, вы должны использовать параметр info ( используя эту библиотеку):

//example input
String userInput = "this is a user input with bad entropy";

HKDF hkdf = HKDF.fromHmacSha256();

//extract the "raw" data to create output with concentrated entropy
byte[] pseudoRandomKey = hkdf.extract(staticSalt32Byte, userInput.getBytes(StandardCharsets.UTF_8));

//create expanded bytes for e.g. AES secret key and IV
byte[] expandedAesKey = hkdf.expand(pseudoRandomKey, "aes-key".getBytes(StandardCharsets.UTF_8), 16);
byte[] expandedIv = hkdf.expand(pseudoRandomKey, "aes-iv".getBytes(StandardCharsets.UTF_8), 16);

//Example boilerplate encrypting a simple string with created key/iv
SecretKey key = new SecretKeySpec(expandedAesKey, "AES"); //AES-128 key
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(expandedIv));
byte[] encrypted = cipher.doFinal("my secret message".getBytes(StandardCharsets.UTF_8));
Другие вопросы по тегам