首先需要在项目加下载cryptoJS插件
npm i crypto-js -s
引入
import CryptoJS from 'crypto-js'
封装一个加密函数.AES加密需要这三个参数需要加密的原文,秘钥,偏移量,并且模式和填充需要保持和后台一致,本人使用的是EBC模式和Pkcs5的填充方式,有为Pkcs5和Pkcs7的填充方式一下,所以下面代码的填充方式我会写Pkcs7(插件中没有直接提供Pkcs5的填充),因为是EBC模式,可不加偏移量
export function encrypt(data,key,iv){
var encrypted =CryptoJS.AES.encrypt(data,key,{
//iv:iv
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString().replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,""); //返回base64格式字符串 根据需要做字符串操作
}
但是这样通过接口上传后,后台报了这么一个错
Given final block not properly padded
仔细分析一下,不难发现,该异常是在解密的时候抛出的.
由于Java就是按照128bit给的,但是由于是一个字符串,需要先在前端将其转为128bit的才行。需要使用CryptoJS.enc.Utf8.parse方法才可以将key转为128bit的。
key =Crypto.enc.Utf8.parse(key)
但是,把key转128bit之后 后台还是报刚才的错.于是想到是不是填充方式的问题.然后我用线上的AES加密网站,发现如果秘钥是16位的话返回的加密后字符串和我本地生成的一样,如果秘钥小于16位则不同,接下来确定肯定是填充方式有问题,于是问了我们后台,后台是通过\x00填充的(我估计 猜测 也许 有可能插件是通过\xff填充,毕竟这方面我不太懂),封装了一个fillkey函数
function fillKey(key, keySize) {
keySize = keySize || 128;
var filledKey = Buffer.alloc(keySize / 8);
var keys = Buffer.from(key);
if (keys.length < filledKey.length) {
for (var i = 0; i < filledKey.length; i++) {
if (i<keys.length){
filledKey[i] = keys[i];
}
}
}
return filledKey;
接着提交成功
完整代码
import CryptoJS from 'crypto-js'
function fillKey(key, keySize) {
keySize = keySize || 128;
var filledKey = Buffer.alloc(keySize / 8);
var keys = Buffer.from(key);
if (keys.length < filledKey.length) {
for (var i = 0; i < filledKey.length; i++) {
if (i<keys.length){
filledKey[i] = keys[i];
}
}
}
console.log(filledKey)
return filledKey;
}
export function encrypt(data,key){
console.log("oldvalue="+key)
console.log("newValue="+data)
key=fillKey(key)
key = CryptoJS.enc.Utf8.parse(key);
var encrypted =CryptoJS.AES.encrypt(data,key,{
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString().replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,""); //
}
留有部分打印值 用于观察效果