Кто-нибудь знает какие-либо существующие реализации для NIST SP 800-56A Функция выделения ключа конкатенации/CONCAT KDF (желательно на Java)?Существующие реализации для NIST SP 800-56A Функция определения ключа каскадирования?
Основная функция вывода описана в разделе 5.8.1 публикации NIST по: Рекомендации для парных ключевых схем Установления с использованием дискретного логарифмирования Cryptography
Ссылки здесь: http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf
CNG Microsoft имеет реализацию here, но если вы сравните функцию, реализованную Microsoft, по сравнению с параметрами, зарегистрированными в NIST SP 800-56A, они не совпадают, а внедрение Microsoft непригодно. Я также попытался реализовать пример программы на C++, но я не смог сопоставить параметры.
Может ли кто-нибудь попытаться реализовать его или знать о существующих реализациях?
Я ищу реализацию, которая способна обосновать, почему она соответствует спецификациям NIST. Я видел пару реализаций, и я чувствую, что они не соответствуют спецификациям NIST (отсутствующие параметры, неверный логический поток и т. Д.).
Если вы можете реализовать его самостоятельно, я всегда рад поделиться своим собственным исходным кодом для обсуждения. Благодаря! Это будет хорошим вкладом в сообщество с открытым исходным кодом!
EDIT:
Благодаря @Rasmus Faber, я могу, наконец, довести этот вопрос к концу, и надеюсь ответить на тот же вопрос, что все еще есть, как я.
Вот код, который я редактировал основанный на @Rasmus Faber и моих оригинальных кодов:
ConcatKeyDerivationFunction.java
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
*
* Implementation of Concatenation Key Derivation Function<br/>
* http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf
*
*/
public class ConcatKeyDerivationFunction {
private static final long MAX_HASH_INPUTLEN = Long.MAX_VALUE;
private static final long UNSIGNED_INT_MAX_VALUE = 4294967295L;
private static MessageDigest md;
public ConcatKeyDerivationFunction(String hashAlg) throws NoSuchAlgorithmException {
md = MessageDigest.getInstance(hashAlg);
}
public byte[] concatKDF(byte[] z, int keyDataLen, byte[] algorithmID, byte[] partyUInfo, byte[] partyVInfo, byte[] suppPubInfo, byte[] suppPrivInfo) {
int hashLen = md.getDigestLength() * 8;
if (keyDataLen % 8 != 0) {
throw new IllegalArgumentException("keydatalen should be a multiple of 8");
}
if (keyDataLen > (long) hashLen * UNSIGNED_INT_MAX_VALUE) {
throw new IllegalArgumentException("keydatalen is too large");
}
if (algorithmID == null || partyUInfo == null || partyVInfo == null) {
throw new NullPointerException("Required parameter is null");
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
baos.write(algorithmID);
baos.write(partyUInfo);
baos.write(partyVInfo);
if (suppPubInfo != null) {
baos.write(suppPubInfo);
}
if (suppPrivInfo != null) {
baos.write(suppPrivInfo);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
byte[] otherInfo = baos.toByteArray();
return concatKDF(z, keyDataLen, otherInfo);
}
private byte[] concatKDF(byte[] z, int keyDataLen, byte[] otherInfo) {
keyDataLen = keyDataLen/8;
byte[] key = new byte[keyDataLen];
int hashLen = md.getDigestLength();
int reps = keyDataLen/hashLen;
if (reps > UNSIGNED_INT_MAX_VALUE) {
throw new IllegalArgumentException("Key derivation failed");
}
int counter = 1;
byte[] counterInBytes = intToFourBytes(counter);
if ((counterInBytes.length + z.length + otherInfo.length) * 8 > MAX_HASH_INPUTLEN) {
throw new IllegalArgumentException("Key derivation failed");
}
for (int i = 0; i <= reps; i++) {
md.reset();
md.update(intToFourBytes(i + 1));
md.update(z);
md.update(otherInfo);
byte[] hash = md.digest();
if (i < reps) {
System.arraycopy(hash, 0, key, hashLen * i, hashLen);
} else {
System.arraycopy(hash, 0, key, hashLen * i, keyDataLen % hashLen);
}
}
return key;
}
private byte[] intToFourBytes(int i) {
byte[] res = new byte[4];
res[0] = (byte) (i >>> 24);
res[1] = (byte) ((i >>> 16) & 0xFF);
res[2] = (byte) ((i >>> 8) & 0xFF);
res[3] = (byte) (i & 0xFF);
return res;
}
}
@Rasmus Faber: Спасибо за ваши усилия. Я даю вам полный кредит за вышеуказанный код. То, что я сделал с приведенным выше кодом, заключалось в добавлении кода для выполнения проверки, как того требуют спецификации NIST.
Кроме того, я исправил ошибку, в которой переданный ключDataLen предназначался для указания длины в битах, но она рассматривалась как длина в байтах. Следовательно, сгенерированный ключ оказался в 8 раз больше.
Это было исправлено добавлением строки keyDataLen = keyDataLen/8;
в первую строку второго метода.
Я благодарю всех за поддержку и надеюсь, что этот фрагмент кода пройдет долгий путь к сообществу с открытым исходным кодом!
Почему вы не чувствуете, реализация CNG может использоваться? –
Мне не удалось сопоставить параметры между реализацией СПГ и параметрами, определенными в NIST SP 800-56A. Например, реализация CNG даже не предлагает использовать алгоритм хеширования. –
Реализация Microsoft имеет хеш-функцию, жестко закодированную, да (и я не вижу *, которая хэш-функция жестко закодирована). Это делает его непригодным для вас? Вы ищете другую реализацию, чтобы проверить свою собственную? –