###服务端 服务端采用AES对称加密算法。
AES是基于数据块的加密方式,每次处理的数据是一块(16字节),当数据不是16字节的倍数时自动填充OR手动填充(填充方式取决于使用哪种填充方式)。
支持的模式包括:
- ECB:是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文。
- CBC:是一种循环模式,前一个分组的密文和当前分组的明文异或操作后再加密,这样做的目的是增强破解难度。
- CFB/OFB实际上是一种反馈模式,目的也是增强破解的难度。
- ECB和CBC的加密结果是不一样的,两者的模式不同,而且CBC会在第一个密码块运算时加入一个初始化向量。
补码方式包括:NoPadding,PKCS5Padding,ISO10126Padding;
个人观点:补码方式的选择依据解码端,例如OC解码需要使用noPadding,crypto-js解码需要使用PKCS5Padding
加密代码:
/**
* encryptToAESPKCS5:加密AES
*
* @param content : 加密内容
* @param password : 加密密钥
* @return
*/
public static String encryptToAESPKCS5(String content, String password) {
byte[] encryptResult = null;
try {
// 密钥
SecretKeySpec secretKey = new SecretKeySpec(password.getBytes(), "AES");
// 算法/模式/填充
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] byteContent = content.getBytes("utf-8");
// 初始化向量,在密钥相同的前提下,加上初始化向量,相同内容加密后相同
IvParameterSpec zeroIv = new IvParameterSpec(password.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, secretKey, zeroIv);
encryptResult = cipher.doFinal(byteContent);
}
catch(Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return Base64.getEncoder().encodeToString(encryptResult);
}
解密代码:
/**
* decryptToAESPKCS5:解密AES
*
* @param content : 解密内容
* @param password : 解密密钥
* @return
*/
public static String decryptToAESPKCS5(String content, String password) {
byte[] decryptResult = null;
try {
// 密钥
SecretKeySpec secretKey = new SecretKeySpec(password.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// base64转换
byte[] byteContent = Base64.getDecoder().decode(content);
IvParameterSpec zeroIv = new IvParameterSpec(password.getBytes());
cipher.init(Cipher.DECRYPT_MODE, secretKey, zeroIv);
decryptResult = cipher.doFinal(byteContent);
String originalString = new String(decryptResult, "utf-8");
return originalString;
}
catch(Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return null;
}
注意:
1.密钥(代码中的password)必须是16位;
2.加密内容必须为16的倍数,在PKCS5Padding、ISO10126Padding填充模式下会自动补位,在noPadding填充模式下需要自己进行补位;
###前端 前端采用开源crypto-js工具。https://www.npmjs.com/package/crypto-js
/**
* [encrypt 加密]
* @return {[type]} [description]
*/
function encrypt() {
var content = $("#encryptContent").val();
var encryptResult = CryptoJS.AES.encrypt(content, key, {
iv: key,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
$("#encryptResult").val(encryptResult);
}
/**
* [decrypt 解密]
* @return {[type]} [description]
*/
function decrypt() {
var content = $("#decryptContent").val();
var bytes = CryptoJS.AES.decrypt(content.toString(), key, {
iv: key,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
var decryptResult = bytes.toString(CryptoJS.enc.Utf8);
$("#decryptResult").val(decryptResult);
}
注意:如果结合服务端加密内容使用crypto-js进行解密,无需进行BASE64解码
服务端源码github:https://github.com/kris-J/java-aes-encrypt
前端源码github:https://github.com/kris-J/aesEncrypt-use-Crypto-js