Вопрос или проблема
Мне нужно иметь возможность использовать алгоритм HKDF на моем входном ключе в библиотеке bouncy-castle FIPS. В обычной библиотеке bouncy-castle есть простой способ сделать это
HKDFBytesGenerator hkdfBytesGenerator = new HKDFBytesGenerator(new SHA256Digest());
HKDFParameters hkdfParameters = new HKDFParameters(inputKey, salt, info);
hkdfBytesGenerator.init(hkdfParameters);
byte[] hkdf = new byte[32];
hkdfBytesGenerator.generateBytes(hkdf, 0, 32);
Однако в bouncy-castle FIPS я пока не смог разобраться, как выполнить ту же операцию. Мне нужно иметь возможность предоставить как salt
, так и info
параметры. HKDFKeyBuilder#build
выполняет только часть “экстракции” без “расширения” и, следовательно, не имеет info
в качестве параметра. Аналогично именованный HKDFBytesGenerator
однако не выполняет “экстракцию” и, следовательно, не содержит salt
.
Ответ все это время был рядом. Как я уже упоминал, HKDFKeyBuilder
выполняет только “экстракцию”, а HKDFBytesGenerator
выполняет только “расширение”, поэтому вам нужно использовать оба. Сначала вам нужно извлечь ключ с помощью HKDFKeyBuilder
, а затем расширить его с помощью HKDFBytesGenerator
. Код должен выглядеть примерно так, в зависимости от ваших других параметров
HKDFKeyBuilder hkdfKeyBuilder = FipsKDF.HKDF_KEY_BUILDER.withSalt(salt).withPrf(AgreementKDFPRF.SHA256_HMAC);
byte[] extractedKey = hkdfKeyBuilder.build(inputKey).getKey();
AgreementOperatorFactory factory = new AgreementOperatorFactory();
KDFCalculator<AgreementKDFParameters> kdfCalculator = factory.createKDFCalculator(FipsKDF.HKDF.withPRF(AgreementKDFPRF.SHA256_HMAC).using(extractedKey).withIV(info));
byte[] hkdf = new byte[32];
kdfCalculator.generateBytes(hkdf);
return hkdf;
Ответ или решение
Для использования алгоритма HKDF в библиотеке Bouncy Castle FIPS, необходимо учесть, что библиотека разделяет этапы "извлечения" и "расширения". Естественно, это требует использования двух различных классов: HKDFKeyBuilder
для извлечения ключа и HKDFBytesGenerator
(или соответствующего механизма) для расширения.
Вот шаги, которые необходимо выполнить:
-
Извлечение ключа с помощью
HKDFKeyBuilder
. На этом этапе вы укажете соль и PRF (Pseudo-Random Function). - Расширение ключа с помощью выбранного механизма генерации для получения окончательного результата. В данном случае, вы можете использовать
KDFCalculator
, чтобы генерировать выходные байты на основе извлеченного ключа и параметраinfo
.
Ниже приведен полный пример кода, который выполняет указанные действия:
import org.bouncycastle.fips.jcajce.provider.asymmetric.util.FipsKDF;
import org.bouncycastle.fips.jcajce.provider.asymmetric.util.AgreementKDFParameters;
import org.bouncycastle.fips.jcajce.provider.asymmetric.util.KDFCalculator;
import org.bouncycastle.fips.jcajce.provider.asymmetric.util.AgreementOperatorFactory;
public byte[] generateHKDF(byte[] inputKey, byte[] salt, byte[] info) {
// Шаг 1: Извлечение ключа
HKDFKeyBuilder hkdfKeyBuilder = FipsKDF.HKDF_KEY_BUILDER
.withSalt(salt)
.withPrf(AgreementKDFPRF.SHA256_HMAC);
byte[] extractedKey = hkdfKeyBuilder.build(inputKey).getKey();
// Шаг 2: Расширение ключа
AgreementOperatorFactory factory = new AgreementOperatorFactory();
KDFCalculator<AgreementKDFParameters> kdfCalculator = factory.createKDFCalculator(
FipsKDF.HKDF.withPRF(AgreementKDFPRF.SHA256_HMAC)
.using(extractedKey)
.withIV(info)
);
byte[] hkdf = new byte[32]; // Размер выходного ключа
kdfCalculator.generateBytes(hkdf);
return hkdf;
}
Пояснение коду:
HKDFKeyBuilder
: Этот класс используется для извлечения ключа, в который передаются входной ключ, соль и PRF. Он построит промежуточный ключ на основе этих параметров.KDFCalculator
: Этот класс предназначен для расширения полученного ключа до желаемого размера, используя дополнительную информацию, переданную черезinfo
.
Такой подход позволяет полностью реализовать алгоритм HKDF в Bouncy Castle FIPS, сохраняя возможность настройки как соль, так и информацию.