2009-06-18 18 views
6

誰もがJavaでのJava同等

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

の同等の操作を行うことを試みた場合、私は思っていました。 secretは文字列(パスワード)で、saltValueBytesはバイト配列のsaltです。

私はものを試しましたが、その周りに私の頭を包むように見えることはできません。

+0

あなたは、選択した回答のライブラリでそれをどのように解決したか教えてください。 –

答えて

4

Google検索でthis implementationが見つかりましたが、一度も使ったことがありません。 RFC 2898 /PKCS#5の

無料のJava実装PBKDF2

RFC 利用できる2898/PKCS#5の少なからと自由に 可能なJavaの実装はないように思えます。 のような小規模なソースファイルは、 のコンパイルと依存関係なしで、LGPLには という名前で無料です。

標準SUN JCE暗号 プロバイダ内HMacSHA1の利用可能性を考えると、そのような実装は 非常に簡単であり、文字通り RFCの説明から導き出すことができます。 私のコードはクリーンルームの実装 であり、RFCのみをベースにしています。

+0

ありがとう、アンドリュー。普通のライブラリを使った通常のJava実装が本当に好きなので、私が探していたものではありません。 –

+0

私はそれを知っています。 –

+0

@ElCheこれは古かったのですが、これを答えとして選択したので、リンクされた実装を使用して質問したそれらの2行に相当するものをどのように書くのかを教えてください。 –

4

これは私のために働く。 私は依然としてRFC2898準拠のPBKDF2の標準実装がJREに存在しないことを不信感として抱いています。私は間違った場所で探しているに違いないと思う。名前の混乱(RFC2898 PKCS5 PBKDF2)は役に立ちません。

// 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

こんにちは、それを使用する方法とそれは256キーをサポートしていますか?歓声 –

+0

それを使うには: 'byte [] myKey = PBKDF2.deriveKey(...);' – Cheeso

+0

**注意**、この実装は間違っています! RFCによれば、 'l'は' ceil(dkLen/hLen) 'と定義され、2つの最大値ではありません。 –

1

はややオーバーロードderiveKey()を追加することによって、HMACSHA256またはHMacSHA512を扱うためCheesoのコードを改善しました。この変更により、コードは
PHP Crypt libからのPKDF2-HMAC-SHA512テストベクトルで実行され、100のテストケースのうち6つが失敗に終わった。

// 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

100のテストケースのうち6つが「失敗する」とはどういう意味ですか?コードが何らかの形でバグがありますか?あるいはテストベクトルが間違っていますか? – pjklauser

4

私は、これはゲーム後半にある知っているが、Java 6とアップが内蔵されていない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(); 

正しいPBKDF2鍵を生成するように見えるんテストPKCS#5、そして私自身から(ぞんざい)とJava 6 Security Enhancements請求の比較のリスト。

+0

この問題は、SHA1しか持たないことです。新しいものを使用するように変更することはできません。もしあなたがそれを受け入れるとしても、私はまだこのライブラリが他の(Java以外の)リファレンスライブラリにマッチしたハッシュを生成することはできませんでした。 – staticsan

+0

これはHMAC-SHA1のみを使用しています。これはRFC2898に言及しており、OpはJava相当のRfc2898DeriveBytesを要求していたからです。また、あなたがテストしているものは確かではありませんが、これは正しいPBKDF2キーを生成します。これをRfc2898DeriveBytesと[PBKDF2テストベクタ](https://www.ietf.org/rfc/rfc6070.txt)に対して検証しました。 – Syon