最近在项目中遇到aes加解密128位ecb模式(在内容和key确定的情况下加密出来的内容是固定不变的),开始java后端的aes加解密是把内容加密后的字节数组encode_content直接发送给Java后端,这样导致前端vue中的aes加解密不能和Java后台互通,原因是前端vue加解密传输的内容是字符串,不能直接传输byte数组,所以无法互通。如果要实现跨平台通用最好不要直接传输字节数组。
aes加密后的内容输出格式可以是十六进制的字符串也可以是base64加密的字符串。
通用的后端算法如下,
public static String enCode(String content, String key) {
if (key == null || "".equals(key)) {
logger.info("key为空!");
return null;
}
if (key.length() != 16) {
logger.info("key长度不是16位!");
return null;
}
try {
byte[] raw = key.getBytes(); //获得密码的字节数组
SecretKeySpec skey = new SecretKeySpec(raw, "AES"); //根据密码生成AES密钥
Cipher cipher = Cipher.getInstance(ALGORITHM); //根据指定算法ALGORITHM自成密码器
cipher.init(Cipher.ENCRYPT_MODE, skey); //初始化密码器,第一个参数为加密(ENCRYPT_MODE)或者解密(DECRYPT_MODE)操作,第二个参数为生成的AES密钥
byte [] byte_content = content.getBytes("utf-8"); //获取加密内容的字节数组(设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
byte [] encode_content = cipher.doFinal(byte_content); //密码器加密数据
return Base64.encodeBase64String(encode_content); //将加密后的数据转换为字符串返回
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
后端的解密方法:
public static String deCode(String content, String key) {
if (key == null || "".equals(key)) {
logger.info("key为空!");
return null;
}
if (key.length() != 16) {
logger.info("key长度不是16位!");
return null;
}
try {
byte[] raw = key.getBytes(); //获得密码的字节数组
SecretKeySpec skey = new SecretKeySpec(raw, "AES"); //根据密码生成AES密钥
Cipher cipher = Cipher.getInstance(ALGORITHM); //根据指定算法ALGORITHM自成密码器
cipher.init(Cipher.DECRYPT_MODE, skey); //初始化密码器,第一个参数为加密(ENCRYPT_MODE)或者解密(DECRYPT_MODE)操作,第二个参数为生成的AES密钥
byte [] encode_content = Base64.decodeBase64(content); //把密文字符串转回密文字节数组
byte [] byte_content = cipher.doFinal(encode_content); //密码器解密数据
return new String(byte_content,"utf-8"); //将解密后的数据转换为字符串返回
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
这样的话在vue等js前端也可以和java平台的aes加解密互通;
前端加密解密实现:引入crypto.js
/*****************************************************
* AES加密
* @param content 加密内容
* @param key 加密密码,由字母或数字组成
此方法使用AES-128-ECB加密模式,key需要为16位
加密解密key必须相同,如:abcd1234abcd1234
* @return 加密密文
****************************************************/
function encrypt(content, key){
var sKey = CryptoJS.enc.Utf8.parse(key);
var sContent = CryptoJS.enc.Utf8.parse(content);
var encrypted = CryptoJS.AES.encrypt(sContent, sKey, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
return encrypted.toString();
}
/*****************************************************
* AES解密
* @param content 加密密文
* @param key 加密密码,由字母或数字组成
此方法使用AES-128-ECB加密模式,key需要为16位
加密解密key必须相同,如:abcd1234abcd1234
* @return 解密明文
****************************************************/
function decrypt(content, key){
var sKey = CryptoJS.enc.Utf8.parse(key);
var decrypt = CryptoJS.AES.decrypt(content, sKey, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
return CryptoJS.enc.Utf8.stringify(decrypt).toString();
}
注:此方法为AES,128位,ECB模式加密解密。
前后端只要保持key相同,可以相互加密解密。