2012-06-04 2 views
12

Кто-нибудь знает какие-либо существующие реализации для 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; в первую строку второго метода.

Я благодарю всех за поддержку и надеюсь, что этот фрагмент кода пройдет долгий путь к сообществу с открытым исходным кодом!

+0

Почему вы не чувствуете, реализация CNG может использоваться? –

+0

Мне не удалось сопоставить параметры между реализацией СПГ и параметрами, определенными в NIST SP 800-56A. Например, реализация CNG даже не предлагает использовать алгоритм хеширования. –

+0

Реализация Microsoft имеет хеш-функцию, жестко закодированную, да (и я не вижу *, которая хэш-функция жестко закодирована). Это делает его непригодным для вас? Вы ищете другую реализацию, чтобы проверить свою собственную? –

ответ

6

Вот быстрая и грязная реализация:

public byte[] concatKDF(String hashAlg, byte[] z, int keyDataLen, byte[] algorithmID, byte[] partyUInfo, byte[] partyVInfo, byte[] suppPubInfo, byte[] suppPrivInfo) throws NoSuchAlgorithmException 
{ 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    try { 
     baos.write(algorithmID); 
     baos.write(partyUInfo); 
     baos.write(partyVInfo); 
     baos.write(suppPubInfo); 
     baos.write(suppPrivInfo); 
    } catch (IOException e) { 
     throw new RuntimeException(e); 
    } 

    byte[] otherInfo = baos.toByteArray(); 
    return concatKDF(hashAlg, z, keyDataLen, otherInfo); 
} 

public byte[] concatKDF(String hashAlg, byte[] z, int keyDataLen, byte[] otherInfo) throws NoSuchAlgorithmException 
{ 
    byte[] key = new byte[keyDataLen]; 
    MessageDigest md = MessageDigest.getInstance(hashAlg); 
    int hashLen = md.getDigestLength(); 
    int reps = keyDataLen/hashLen; 
    for(int i=1;i<=reps;i++){ 
     md.reset(); 
     md.update(intToFourBytes(i)); 
     md.update(z); 
     md.update(otherInfo); 
     byte[] hash = md.digest(); 
     if(i<reps){ 
      System.arraycopy(hash, 0, key, hashLen*(i-1), hashLen); 
     }else{ 
      if(keyDataLen % hashLen == 0){ 
       System.arraycopy(hash, 0, key, hashLen*(i-1), hashLen); 
      }else{ 
       System.arraycopy(hash, 0, key, hashLen*(i-1), keyDataLen % hashLen); 
      } 
     } 
    } 
    return key; 
} 

public 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; 
} 
+0

Привет, спасибо за ваш ответ! Я тщательно проверил ваш код и сумел сопоставить свою реализацию с моей, пока мы не получили тот же результат! Я очень ценю, что вы тратите время на это. Я добавил подтверждение вашего кода и исправил ошибку с keyDataLen, как описано выше. Пожалуйста, не стесняйтесь повторно использовать код и дайте мне знать, если вы заметили что-нибудь! –

+0

Еще раз спасибо! Я передам эти коды сообществу, с которым я работаю, поскольку мы в настоящее время нуждаемся в этом ConcatKDF. –

+0

@LaiXinChu: Обратите внимание, что ваша модифицированная реализация неправильно обрабатывает длины ключа, которые не являются кратными 8 бит. Я думаю, что просто сработаю, если 'keyDataLenInBits% 8! = 0'. –

3

Не думаю, что вы можете найти их другие, чем проверить все в списке Validated Component Implementations от http://csrc.nist.gov/groups/STM/cavp/documents/components/componentval.html.

Существует только один поставщик, записывающий их в Java - Entrust http://www.entrust.com.

Все они проверяются без KDF :). Остальная работа зависит от вас.

+0

К сожалению, все они проверяются без KDF, а KDF - именно то, что мне нужно! Хм, я посмотрю на это. Спасибо за попытку! –

 Смежные вопросы

  • Нет связанных вопросов^_^