Sử dụng RFC2898 để tạo khóa từ mật khẩu. Điều này không được bao gồm trong JRE hoặc JCE, theo như tôi biết, nhưng nó được bao gồm trong các Máy chủ J2EE như JBoss, Oracle và WebSphere. Nó cũng được bao gồm trong thư viện lớp cơ sở .NET (Rfc2898DeriveBytes).
Có một số triển khai LGPL trong Java ngoài kia, nhưng trên giao diện nhanh, this one trông hơi phức tạp một chút. Ngoài ra còn có một số javascript version tốt. (Tôi đã sản xuất a modified version of that one và đóng gói nó như là một thành phần Windows Script)
Thiếu một thực hiện tốt với giấy phép thích hợp, tôi đóng gói một số mã từ Mattias Gartner. Đây là mã toàn bộ. Ngắn gọn, đơn giản, dễ hiểu. Nó được cấp phép theo số 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() {}
}
Bạn có muốn thực hiện băm mật khẩu/cụm từ hoặc mã hóa dữ liệu (như PGP hoặc SSL bằng cụm mật khẩu) tại đây không? Tiêu đề là một chút gây hiểu nhầm cho các cựu, nhưng tôi nghĩ rằng bạn muốn làm thứ hai ... – JeeBee
Tôi muốn làm điều cũ, nhưng tôi không biết tại sao bạn đang gọi nó băm. Tôi muốn nó có thể đảo ngược. Hãy suy nghĩ mã hóa DES hoặc AES bằng cụm mật khẩu. Mã hóa đối xứng, không đối xứng như bạn mô tả. – skiphoppy
Tại sao bạn cần mã hóa cụm từ mật khẩu có thể đảo ngược? Đó không phải là điều mong muốn. – JeeBee