2012-06-04 7 views
12

Qualcuno sa di eventuali implementazioni esistenti per NIST SP 800-56A Funzione di derivazione chiave di concatenazione/CONCAT KDF (preferibilmente in Java)?Implementazioni esistenti per NIST SP 800-56A Funzione di derivazione chiave di concatenazione?

La funzione chiave di derivazione è documentata nella sezione 5.8.1 della pubblicazione del NIST: Raccomandazione per Pair-Wise chiave Schemi stabilimenti che utilizzino logaritmo discreto Cryptography

link qui: http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf

CNG di Microsoft ha un'implementazione here ma se si confronta la funzione implementata da Microsoft, rispetto ai parametri documentati in NIST SP 800-56A, questi non vengono calcolati e l'implementazione di Microsoft non è utilizzabile. Ho tentato di implementare un programma di esempio in C++, ma non ho potuto abbinare i parametri.

Qualcuno potrebbe tentare di implementarlo o conoscere eventuali implementazioni esistenti?

Sto cercando un'implementazione che sia in grado di giustificare il motivo della precisione con le specifiche NIST. Ho visto un paio di implementazioni là fuori e ritengo che non siano accurate rispetto alle specifiche NIST (parametri mancanti, flusso logico non valido ecc.).

Se è possibile implementarlo da soli, sono sempre lieto di condividere il mio codice sorgente per il dibattito. Grazie! Questo sarebbe un buon contributo per la comunità open source!

EDIT:

Grazie a @Rasmus Faber, posso finalmente portare la questione al termine, e la speranza di rispondere alla stessa domanda che tutti gli altri hanno di me.

Ecco il codice che ho modificato sulla base di @Rasmus Faber e i miei codici originali:

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: Grazie per il vostro sforzo. Ti do pieno credito per il codice di cui sopra. Quello che ho fatto con il codice sopra è stato quello di aggiungere codice per eseguire la convalida come richiesto dalle specifiche NIST.

Inoltre, ho corretto un bug in cui il keyDataLen è passato per specificare la lunghezza in bit, ma è stato trattato come la lunghezza in byte. Quindi, la chiave generata è risultata 8 volte più grande.

Ciò è stato risolto aggiungendo una riga keyDataLen = keyDataLen/8; nella prima riga del secondo metodo.

Ringrazio tutti per il loro supporto e spero che questo pezzo di codice possa fare molto per la comunità open source!

+0

Perché non si sente l'implementazione CNG è utilizzabile? –

+0

Non è stato possibile associare i parametri tra l'implementazione CNG e i parametri definiti in NIST SP 800-56A. Ad esempio, l'implementazione CNG non richiede nemmeno l'utilizzo dell'algoritmo hash. –

+0

L'implementazione Microsoft ha la funzione hash hardcoded, sì (e non riesco a vedere * quale * hash-function è hard-coded a). Questo lo rende inutilizzabile? Stai cercando un'altra implementazione per verificarne la tua? –

risposta

6

Ecco un'implementazione veloce e sporco:

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

Ciao grazie per la tua risposta !! Ho testato a fondo il tuo codice e sono riuscito a far coincidere la tua implementazione con la mia, finché non abbiamo ottenuto lo stesso risultato! Apprezzo molto che tu abbia dedicato del tempo per implementarlo. Ho aggiunto la convalida al tuo codice e corretto un bug con keyDataLen come descritto sopra. Sentiti libero di riconnettere il codice e fammi sapere se noti qualcosa! –

+0

Grazie ancora! Trasmetterò questi codici alla comunità con cui lavoro, poiché attualmente abbiamo bisogno di questo ConcatKDF. –

+0

@LaiXinChu: si noti che l'implementazione modificata non gestisce correttamente le lunghezze chiave che non sono un multiplo di 8 bit. Penso che mi mancherebbe solo se 'keyDataLenInBits% 8! = 0'. –

Problemi correlati