2009-06-18 19 views
6

mi chiedevo se qualcuno ha provato a fare un equivalente diJava equivalente di Rfc2898DerivedBytes C# s '

Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(secret, saltValueBytes); 
byte[] secretKey = key.GetBytes(16); 

in Java. Dove segreto è una stringa (password), e saltValueBytes è, beh, un salt in array di byte.

Ho provato roba, ma non riesco a spiegarmelo.

+0

Puoi dire come hai risolto con la libreria nella risposta scelta? –

risposta

4

Ho trovato this implementation tramite una ricerca su Google ma non l'ho mai usato.

Un'implementazione Java gratuitamente RFC 2898 /PKCS # 5 PBKDF2

Non sembra esserci nessuna piccola e liberamente implementazione disponibile Java di RFC 2898/PKCS # 5 disponibili. Piccolo come in solo pochi file sorgente, con banale compilato e senza dipendenze, gratuito come in LGPL.

data la disponibilità di HMacSHA1 in SUN ICC crittografico erogatori standard tale attuazione è abbastanza semplice e può essere derivata dalla descrizione RFC letteralmente. Il mio codice è un'implementazione di camera bianca con la sola base RFC.

+0

Grazie, Andrew. Non proprio quello che stavo cercando dato che mi piacerebbe una normale implementazione Java usando le normali librerie –

+0

Lo so - è davvero un peccato che non ci sia un equivalente diretto. –

+0

@ElChe So che questo è vecchio, ma dal momento che hai scelto questo come risposta, puoi dire come hai finito per scrivere l'equivalente di quelle 2 righe che hai chiesto (usando l'implementazione collegata)? –

4

Questo funziona per me. Continuo a non credere che un'implementazione standard di un PBKDF2 conforme a RFC2898 non sia presente nel JRE. Penso di dover guardare nei posti sbagliati. La confusione del nome (RFC2898 PKCS5 PBKDF2) non aiuta.

// PBKDF2.java 
// ------------------------------------------------------------------ 
// 
// RFC2898 PBKDF2 in Java. The RFC2898 defines a standard algorithm for 
// deriving key bytes from a text password. This is also called 
// "PBKDF2", for Password-based key derivation function #2. 
// 
// There's no RFC2898-compliant PBKDF2 function in the JRE, as far as I 
// know, but it is available in many J2EE runtimes, including those from 
// JBoss, IBM, and Oracle. 
// 
// It's fairly simple to implement, so here it is. 
// 
// Author: Admin 
// built on host: DINOCH-2 
// Created Sun Aug 09 01:06:57 2009 
// 
// last saved: 
// Time-stamp: <2009-August-09 11:11:47> 
// ------------------------------------------------------------------ 
// 
// code from Matthias Gartner 
// 
// ------------------------------------------------------------------ 

package cheeso.examples; 


import java.security.NoSuchAlgorithmException; 
import java.security.InvalidKeyException; 
import javax.crypto.Mac; 
import javax.crypto.spec.SecretKeySpec; 


public class PBKDF2 
{ 
    public static byte[] deriveKey(byte[] password, 
            byte[] salt, 
            int iterationCount, 
            int dkLen) 
     throws java.security.NoSuchAlgorithmException, 
       java.security.InvalidKeyException 
    { 
     SecretKeySpec keyspec = new SecretKeySpec(password, "HmacSHA1"); 
     Mac prf = Mac.getInstance("HmacSHA1"); 
     prf.init(keyspec); 

     // Note: hLen, dkLen, l, r, T, F, etc. are horrible names for 
     //  variables and functions in this day and age, but they 
     //  reflect the terse symbols used in RFC 2898 to describe 
     //  the PBKDF2 algorithm, which improves validation of the 
     //  code vs. the RFC. 
     // 
     // hLen denotes the length in octets of the pseudorandom function output 
     // dklen the length in octets (bytes) of the derived key. 

     int hLen = prf.getMacLength(); // 20 for SHA1 
     int l = Math.ceil(dkLen/hLen); // 1 for 128bit (16-byte) keys 
     int r = dkLen - (l-1)*hLen;  // 16 for 128bit (16-byte) keys 
     byte T[] = new byte[l * hLen]; 
     int ti_offset = 0; 
     for (int i = 1; i <= l; i++) { 
      F(T, ti_offset, prf, salt, iterationCount, i); 
      ti_offset += hLen; 
     } 

     if (r < hLen) { 
      // Incomplete last block 
      byte DK[] = new byte[dkLen]; 
      System.arraycopy(T, 0, DK, 0, dkLen); 
      return DK; 
     } 
     return T; 
    } 


    private static void F(byte[] dest, int offset, Mac prf, byte[] S, int c, int blockIndex) { 
     final int hLen = prf.getMacLength(); 
     byte U_r[] = new byte[ hLen ]; 
     // U0 = S || INT (i); 
     byte U_i[] = new byte[S.length + 4]; 
     System.arraycopy(S, 0, U_i, 0, S.length); 
     INT(U_i, S.length, blockIndex); 
     for(int i = 0; i < c; i++) { 
      U_i = prf.doFinal(U_i); 
      xor(U_r, U_i); 
     } 

     System.arraycopy(U_r, 0, dest, offset, hLen); 
    } 

    private static void xor(byte[] dest, byte[] src) { 
     for(int i = 0; i < dest.length; i++) { 
      dest[i] ^= src[i]; 
     } 
    } 

    private static void INT(byte[] dest, int offset, int i) { 
     dest[offset + 0] = (byte) (i/(256 * 256 * 256)); 
     dest[offset + 1] = (byte) (i/(256 * 256)); 
     dest[offset + 2] = (byte) (i/(256)); 
     dest[offset + 3] = (byte) (i); 
    } 

    // ctor 
    private PBKDF2() {} 
} 
+0

Ciao, come si usa e supporta 256 tasti? evviva –

+0

Per usarlo: 'byte [] myKey = PBKDF2.deriveKey (...);' – Cheeso

+0

** Nota **, questa implementazione non è corretta! Secondo RFC, 'l' è definito come' ceil (dkLen/hLen) 'e non come il massimo dei due. –

1

leggermente migliorata codice di Cheeso per lavorare con HMACSHA256 o HMacSHA512 aggiungendo deriveKey sovraccarico(). Con questo cambiamento, il codice è stato eseguito con i vettori di test PKDF2-HMAC-SHA512 da
PHP Crypt lib che hanno provocato 6 guasti su 100 casi di test.

// PBKDF2.java 
// ------------------------------------------------------------------ 
// 
// RFC2898 PBKDF2 in Java. The RFC2898 defines a standard algorithm for 
// deriving key bytes from a text password. This is also called 
// "PBKDF2", for Password-based key derivation function #2. 
// 
// There's no RFC2898-compliant PBKDF2 function in the JRE, as far as I 
// know, but it is available in many J2EE runtimes, including those from 
// JBoss, IBM, and Oracle. 
// 
// It's fairly simple to implement, so here it is. 
// 
// Author: Admin 
// built on host: DINOCH-2 
// Created Sun Aug 09 01:06:57 2009 
// 
// last saved: 
// Time-stamp: <2009-August-09 11:11:47> 
// ------------------------------------------------------------------ 
// 
// code from Matthias Gartner 
// 
// ------------------------------------------------------------------ 

package cheeso.examples; 


import java.security.NoSuchAlgorithmException; 
import java.security.InvalidKeyException; 
import javax.crypto.Mac; 
import javax.crypto.spec.SecretKeySpec; 


public class PBKDF2 
{ 
    public static byte[] deriveKey(byte[] password, 
            byte[] salt, 
            int iterationCount, 
            int dkLen) 
      throws NoSuchAlgorithmException, 
      InvalidKeyException 
    { 
     return deriveKey("HmacSHA1", password, salt, iterationCount, dkLen); 
    } 

    public static byte[] deriveKey(String hmacAlgo, 
            byte[] password, 
            byte[] salt, 
            int iterationCount, 
            int dkLen) 
      throws NoSuchAlgorithmException, 
      InvalidKeyException 
    { 
     SecretKeySpec keyspec = new SecretKeySpec(password, hmacAlgo); 
     Mac prf = Mac.getInstance(hmacAlgo); 
     prf.init(keyspec); 

     // Note: hLen, dkLen, l, r, T, F, etc. are horrible names for 
     //  variables and functions in this day and age, but they 
     //  reflect the terse symbols used in RFC 2898 to describe 
     //  the PBKDF2 algorithm, which improves validation of the 
     //  code vs. the RFC. 
     // 
     // dklen is expressed in bytes. (16 for a 128-bit key, 32 for 256) 

     int hLen = prf.getMacLength(); // 20 for SHA1 
     int l = Math.max(dkLen, hLen); // 1 for 128bit (16-byte) keys 
     int r = dkLen - (l-1)*hLen;  // 16 for 128bit (16-byte) keys 
     byte T[] = new byte[l * hLen]; 
     int ti_offset = 0; 
     for (int i = 1; i <= l; i++) { 
      F(T, ti_offset, prf, salt, iterationCount, i); 
      ti_offset += hLen; 
     } 

     if (r < hLen) { 
      // Incomplete last block 
      byte DK[] = new byte[dkLen]; 
      System.arraycopy(T, 0, DK, 0, dkLen); 
      return DK; 
     } 
     return T; 
    } 


    private static void F(byte[] dest, int offset, Mac prf, byte[] S, int c, int blockIndex) { 
     final int hLen = prf.getMacLength(); 
     byte U_r[] = new byte[ hLen ]; 
     // U0 = S || INT (i); 
     byte U_i[] = new byte[S.length + 4]; 
     System.arraycopy(S, 0, U_i, 0, S.length); 
     INT(U_i, S.length, blockIndex); 
     for(int i = 0; i < c; i++) { 
      U_i = prf.doFinal(U_i); 
      xor(U_r, U_i); 
     } 

     System.arraycopy(U_r, 0, dest, offset, hLen); 
    } 

    private static void xor(byte[] dest, byte[] src) { 
     for(int i = 0; i < dest.length; i++) { 
      dest[i] ^= src[i]; 
     } 
    } 

    private static void INT(byte[] dest, int offset, int i) { 
     dest[offset + 0] = (byte) (i/(256 * 256 * 256)); 
     dest[offset + 1] = (byte) (i/(256 * 256)); 
     dest[offset + 2] = (byte) (i/(256)); 
     dest[offset + 3] = (byte) (i); 
    } 

    // ctor 
    private PBKDF2() {} 
} 
+1

che cosa significa se 6 su 100 test falliscono? Il codice è in qualche modo buggato o i vettori di test sono sbagliati? – pjklauser

4

So che questo è in ritardo al gioco, ma Java 6 e fino fa hanno un'implementazione integrata PBKDF2.

int dkLen = 64; 
int rounds = 1000; 
PBEKeySpec keySpec = new PBEKeySpec("Some password".toCharArray(), "SomeSalt".getBytes(), rounds, dkLen * 8); 
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
byte[] out = factory.generateSecret(keySpec).getEncoded(); 

L'elenco delle richieste Java 6 Security Enhancements comparabilità con PKCS # 5, e attraverso la mia (superficiale) test in quanto sembra per la produzione di chiavi PBKDF2 corretti.

+0

Il problema con questo è che hai solo SHA1. Non puoi cambiarlo per usare qualcosa di più recente. Anche se lo accetti, non riesco ancora a fare in modo che questa libreria produca hash che corrispondono ad altre librerie di riferimento (non Java). – staticsan

+0

Questo utilizza solo HMAC-SHA1 perché è tutto ciò che menziona RFC2898 e Op stava richiedendo un equivalente Java di Rfc2898DeriveBytes. Inoltre, non si è sicuri di cosa si stia testando, ma questo assolutamente produce chiavi PBKDF2 corrette. Verificato in base a Rfc2898DeriveBytes e ai [vettori di test PBKDF2] (https://www.ietf.org/rfc/rfc6070.txt). – Syon