PBE( Password based Encryption, 基于口密加密)。PBE是一种基于口令的加密算法, 采用随机数杂凑(盐)多重加密方法保证数据安全性。
PBE算法并没有真正构建新的算法, 而是对现有对称加密算法(比如DES)进行了包装。
因为密钥很长,一般 由算法产生, 比如DES密钥长度56; 口令一般比较短, 可以容易记住, 也就是我们平时所说的密码。口令很容易通过穷举攻击被破译, 所以就引入了“盐”。
盐本身是一个随机信息, 相同的随机信息不可能使用两次, 将盐加载口令上, 通过消息摘要算法迭代计算构建密钥, 破译就比较难了。
JDK本身提供了对PBE算法的实现,不需要导入其他的第三方库。 Java中的PBE算法是对各种消息摘要算法(比如MD5,SHA)和对称加密算法(比如DES,RC2)的组合。 比如 PBEWithMD5AndDES算法。
PBEWithMD5AndDES的密钥长度是56 , 是组合了MD5和DES算法。
本篇示例环境:
- JDK1.8
- Eclipse IDE
因为示例需要使用base64对字节数组和字符串进行转换,所以需要导入base64的包,这个包在本地JRE的lib 目录下, 导入方式如下图:
这里将加密和解密放在一起, 实际项目中可以分开来放, 完整代码如下:
import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import sun.misc.base64Decoder;
import sun.misc.base64Encoder;
public class PBEDemo {
public static final String ALGORITHM = "PBEWITHMD5andDES";
public static byte[] initSalt() throws Exception {
SecureRandom random = new SecureRandom();//实例化安全随机数
return random.generateSeed(8);//产出盐
}
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);
}
public static byte[] decryptbase64(String key) throws Exception {
return (new base64Decoder()).decodeBuffer(key);
}
public static String encryptbase64(byte[] key) throws Exception {
return (new base64Encoder()).encodeBuffer(key);
}
public static void main(String[] args) throws Exception {
String message = "你好";
String password = "oscar999";
//1. 加密
byte[] salt = initSalt();
byte[] encryBytes = encrypt(message.getBytes(),password,salt);
String encryStr = encryptbase64(encryBytes);
String saltStr = encryptbase64(salt);
System.out.println("原文="+message);
System.out.println("盐="+saltStr);
System.out.println("密文="+encryStr);
//2. 解密
encryBytes = decryptbase64(encryStr);
salt = decryptbase64(saltStr);
byte[] decryBytes = decrypt(encryBytes,password,salt);
System.out.println("解密后="+new String(decryBytes));
}
}
说明:
- 加密和解密返回的类型都是byte[], 通过base64编码转换为可显示字串。上面方法的decryptbase64() 和encryptbase64() 用于字符串和字符数组类型的转换。
- 盐必须为8个字节, 盐可以随机产生,也可以是双方按一定规律约定的消息(比如按时间), 也可以是一个固定的号码。
盐的值不对
相关知识参考- base64是一种基于64个可打印字符来表示二进制数据的表示方法, 相关参考:base64 编码介绍
-
- MD5 , 全称是Message-Digest Algorithm 5, 是一种消息摘要算法。关于消息摘要, 可以参考消息摘要(Message Digest)及其算法



