2012-06-04 9 views
12

¿Alguien sabe de alguna implementación existente para NIST SP 800-56A Función de derivación de clave de concatenación/CONCAT KDF (preferiblemente en Java)?Implementaciones existentes para la función de derivación de clave de concatenación NIST SP 800-56A?

La función de derivación de claves se documenta en la sección 5.8.1 de la publicación del NIST: Recomendación de a pares clave Esquemas de establecimiento Uso de logaritmo discreto Criptografía

Enlace aquí: http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf

GNC de Microsoft tiene una implementación here pero si compara la función implementada por Microsoft, en comparación con los parámetros documentados en NIST SP 800-56A, no coinciden, y la implementación de Microsoft es inutilizable. También intenté implementar un programa de ejemplo en C++, pero no pude hacer coincidir los parámetros.

¿Alguien podría intentar implementarlo o conocer alguna implementación existente?

Estoy buscando una implementación que pueda justificar por qué es precisa para las especificaciones NIST. He visto un par de implementaciones y creo que no son precisas para las especificaciones NIST (parámetros faltantes, flujo lógico no válido, etc.).

Si puede implementarlo usted mismo, siempre estoy contento de compartir mi propio código fuente para debatir. ¡Gracias! ¡Esta sería una buena contribución a la comunidad de código abierto!

EDIT:

Gracias a @Rasmus Faber, que finalmente puede llevar esta cuestión a su fin, y la esperanza de responder a la misma pregunta que todo el mundo tiene que yo.

Aquí está el código que he editado basado en @Rasmus Faber y mis códigos originales:

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: Gracias por su esfuerzo. Le doy crédito completo por el código anterior. Lo que hice con el código anterior fue agregar código para realizar la validación según lo exigen las especificaciones del NIST.

Además, he reparado un error por el que el keyDataLen pasado se suponía que especificaba la longitud en bits, pero se trataba como la longitud en bytes. Por lo tanto, la clave generada terminó siendo 8 veces más grande.

Esto se solucionó al agregar una línea keyDataLen = keyDataLen/8; en la primera línea del segundo método.

¡Agradezco a todos por su apoyo y espero que este fragmento de código recorra un largo camino hasta la comunidad de código abierto!

+0

¿Por qué no se siente la aplicación de GNC es utilizable? –

+0

No pude hacer coincidir los parámetros entre la implementación de CNG y los parámetros definidos en NIST SP 800-56A. Por ejemplo, la implementación de CNG ni siquiera solicita que se use el algoritmo hash. –

+0

La implementación de Microsoft tiene la función hash codificada, sí (y no puedo ver * qué * función hash está codificada). ¿Eso lo hace inutilizable para ti? ¿Estás buscando otra implementación para verificar la tuya? –

Respuesta

6

Aquí es una aplicación rápida y sucia:

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

¡Hola, gracias por tu respuesta! Probé tu código a fondo, y logré hacer coincidir tu implementación con la mía, ¡hasta que obtuvimos el mismo resultado! Realmente aprecio que se tome el tiempo de implementar esto. He agregado la validación a su código y he corregido un error con keyDataLen como se describe arriba. Por favor, siéntase libre de volver a mirar el código y avíseme si detecta algo. –

+0

¡Gracias una vez más! Transmitiré estos códigos a la comunidad con la que estoy trabajando ya que actualmente necesitamos este ConcatKDF. –

+0

@LaiXinChu: tenga en cuenta que su implementación modificada no maneja correctamente longitudes de clave que no son un múltiplo de 8 bits. Creo que simplemente fallaría si 'keyDataLenInBits% 8! = 0'. –

3

No creo que pueda encontrarlos luego pruebe todo en la lista de Validated Component Implementations de http://csrc.nist.gov/groups/STM/cavp/documents/components/componentval.html.

Solo hay un proveedor que los escribe en Java: Entrust http://www.entrust.com.

Todos ellos están validados sin el KDF :). El resto del trabajo depende de ti.

+0

Lamentablemente, todos ellos están validados sin el KDF, ¡y el KDF es exactamente lo que necesito! Mmm, investigaré esto. ¡Gracias por el esfuerzo! –

Cuestiones relacionadas