Java相当于C#的Rfc2898DerivedBytes

我想知道是否有人试图做相同的

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

在Java中。 其中secret是字符串(密码),而saltValueBytes是字节数组中的salt。

我尝试了一些东西,但似乎无法绕过它。

我通过谷歌搜索找到了这个实现 ,但我从未使用它。

RFC 2898 / PKCS#5 PBKDF2的免费Java实现

似乎没有可用的小型且免费提供的RFC 2898 / PKCS#5 Java实现。 像少数几个源文件一样小,具有简单的编译和无依赖性,在LGPL中是免费的。

鉴于HMacSHA1在标准SUN JCE加密提供程序中的可用性,这种实现非常简单,并且可以从字面上完全从RFC描述中获得。 我的代码是一个洁净室实现,只有RFC作为其基础。

我知道这是游戏的后期,但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(); 

Java 6安全增强function列表声称与PKCS#5具有可比性,并且通过我自己的(粗略)测试,它确实产生了正确的PBKDF2密钥。

这个对我有用。 我仍然不相信JRE中不存在符合RFC2898的PBKDF2的标准实现。 我想我一定是在找错地方。 名称混淆(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 () {} } 

通过添加重载的deriveKey(),稍微改进了Cheeso使用HMacSHA256或HMacSHA512的代码。 通过此更改,代码使用PKDF2-HMAC-SHA512测试向量运行
PHP Crypt lib导致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 () {} }