在 Java 加密技術系列的前兩篇中,我們已經探討了 DES、3DES、AES 等對稱加密算法。本文將深入介紹另一種重要的對稱加密方式——PBE(Password-Based Encryption,基於密碼的加密)。PBE 的獨特之處在於它允許用戶直接掌管口令,無需依賴任何物理媒體,並通過隨機數(鹽值)和多重雜湊機制來保障數據安全性,是一種既簡便又有效的加密方案。
PBE 將用戶提供的密碼作為核心輸入,結合隨機生成的鹽值,經過多次雜湊運算衍生出加密金鑰。這種機制有效防禦了彩虹表攻擊,因為相同的密碼配合不同的鹽值會產生完全不同的加密結果。Java 提供了豐富的 PBE 算法支持,包括 PBEWithMD5AndDES、PBEWithMD5AndTripleDES、PBEWithSHA1AndDESede 等多種組合。
以下是完整的 PBECoder 實現,展示了鹽值生成、密鑰轉換、加密解密的完整流程:
import java.security.Key;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
public abstract class PBECoder extends Coder {
public static final String ALGORITHM = "PBEWITHMD5andDES";
public static byte[] initSalt() throws Exception {
byte[] salt = new byte[8];
Random random = new Random();
random.nextBytes(salt);
return salt;
}
private static Key toKey(String password) throws Exception {
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey secretKey = keyFactory.generateSecret(keySpec);
return secretKey;
}
public static byte[] encrypt(byte[] data, String password, byte[] salt) throws Exception {
Key key = toKey(password);
PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
return cipher.doFinal(data);
}
public static byte[] decrypt(byte[] data, String password, byte[] salt) throws Exception {
Key key = toKey(password);
PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
return cipher.doFinal(data);
}
}
通過 JUnit 測試類驗證加密解密流程的正確性:
public class PBECoderTest {
@Test
public void test() throws Exception {
String inputStr = "abc";
String pwd = "efg";
byte[] salt = PBECoder.initSalt();
byte[] data = PBECoder.encrypt(inputStr.getBytes(), pwd, salt);
System.err.println("加密後: " + PBECoder.encryptBASE64(data));
byte[] output = PBECoder.decrypt(data, pwd, salt);
String outputStr = new String(output);
System.err.println("解密後: " + outputStr);
assertEquals(inputStr, outputStr);
}
}
控制台輸出確認加密解密過程完全可逆:
原文: abc
密碼: efg
加密後: iCZ0uRtaAhE=
解密後: abc
下一篇我們將進入非對稱加密領域,探討 RSA、DSA、DH、ECC 等算法的 Java 實現。