使用RFC2898從密碼生成密鑰。據我所知,這不包含在JRE或JCE中,但它包含在諸如JBoss,Oracle和WebSphere之類的J2EE服務器中。它也包含在.NET Base Class Library(Rfc2898DeriveBytes)中。
Java中有一些LGPL實現,但快速查看this one看起來有點過於複雜。還有一個很好的javascript version。 (我製作了a modified version of that one並將它打包爲Windows腳本組件)
由於缺少一個合適的許可證很好的實現,我打包了一些來自Mattias Gartner的代碼。這是整個代碼。簡短,簡單,易於理解。它的許可證號爲MS Public License。
// PBKDF2.java
// ------------------------------------------------------------------
//
// RFC2898 PBKDF2 in Java. The RFC2898 defines a standard algorithm for
// deriving key bytes from a text password. This is sometimes
// abbreviated "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.
//
// Created Sun Aug 09 01:06:57 2009
//
// last saved:
// Time-stamp: <2009-August-09 02:19:50>
// ------------------------------------------------------------------
//
// code thanks to 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.
//
// dklen is expressed in bytes. (16 for a 128-bit key)
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() {}
}
你想在這裏做密碼/短語哈希或數據加密(如PGP或SSL與密碼短語)嗎?標題對前者有點誤導,但我認爲你想要做後者... – JeeBee 2008-12-16 19:01:59
我想要做前者,但我不知道你爲什麼稱它爲哈希。我希望它是可逆的。用密碼思考DES或AES加密。正如你所描述的那樣,對稱加密不是非對稱的。 – skiphoppy 2008-12-16 19:07:11