参考:
AES加密解密:http://tool.chacuo.net/cryptaes
在数字加密算法中,通过可划分为对称加密和非对称加密
对称加密:如AES,DES,3DES
含义:加密和解密使用的是同一把钥匙。密钥不能在网络中传输,避免被拦截。如果要传输,必须要对密钥进行非对称加密再加密一次。
优点:算法简单,加密解密容易,效率高,执行快。
缺点:相对来说不算特别安全,只有一把钥匙,密文如果被拦截,且密钥也被劫持,那么,信息很容易被破译。
非对称加密:如RSA DSA RCC
含义:有两个钥匙,及公钥(Public Key)和私钥(Private Key)。公钥和私钥是成对的存在,如果对原文使用公钥加密,则只能使用对应的私钥才能解密。通过私钥经过一系列算法是可以推导出公钥的,但是无法通过公钥反向推倒出私钥,这个过程的单向的。
优点:安全,即使密文被拦截、公钥被获取,但是无法获取到私钥,也就无法破译密文。作为接收方,务必要保管好自己的密钥。
缺点:加密算法及其复杂,安全性依赖算法与密钥,而且加密和解密效率很低。
下载crypto-js
cnpm i -S crypto-js
局部引用
import CryptoJS from "crypto-js";
加密解密数据
前端CBC模式或者ECB模式下的填充方式 Pkcs7,对应后端AES算法模式中的 PKCS5Padding 填充方式
AES算法的ECB模式加密-设置秘钥
ECB(Electronic Code Book电子密码本)模式
优点:
- 简单;
- 有利于并行计算;
- 误差不会被扩散;
缺点:
- 不能隐藏明文的模式
- 可能对明文进行主动攻击
因此,此模式适于加密小消息。
随机生成aes密钥:
密钥字符串的length最好为16。当然也可以为32,但是在工作中发现用32的话,后端可能会因为密钥长度相对较长而导致密钥被截断一部分,因此选择用16
//生成指定长度随机字符串
generateRandomStr(strLength = 16) {
let code = '';
const chars = 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
const charsArr = chars.split('');
for (let i = 0; i < strLength; i++) {
const num = Math.floor(Math.random() * charsArr.length);
code += charsArr[num];
}
return code;
}
测试:
encryptData() {
// 此处key为16进制
let key = '385f33cb91484b04a177828829081ab7';
console.log('密钥:', key);
// key格式化处理
key = CryptoJS.enc.Utf8.parse(key);
// 加密内容
const polygonGeojson = {
type: 'Feature',
properties: {},
geometry: {
type: 'Polygon',
coordinates: [
[
[106, 33],
[108.03955078125, 32.2313896627376],
[108.25927734375, 33.15594830078649],
[106, 33]
]
]
}
};
const content = JSON.stringify(polygonGeojson);
console.log('加密前:', polygonGeojson);
// 加密方法
const encryptedContent = CryptoJS.AES.encrypt(content, key, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
const encStr = encryptedContent.ciphertext.toString();
console.log('加密后:', encStr);
// 解密方法
const decryptedContent = CryptoJS.AES.decrypt(
CryptoJS.format.Hex.parse(encStr),
key,//注意:后面这里最好使用 CryptoJS.format.Utf8.parse(key)
{
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
}
);
console.log(
'解密:',
JSON.parse(CryptoJS.enc.Utf8.stringify(decryptedContent))
);
}
AES算法的CBC模式加密-设置秘钥和偏移量
CBC(Cipher Block Chaining,加密块链)模式
优点:
- 不容易主动攻击
- 安全性好于ECB
- 适合传输长度长的报文,是SSL、IPSec的标准。
缺点:
- 不利于并行计算
- 误差传递
- 需要初始化向量IV
CBC模式前、后端需要确定偏移量的值,并且保持一致,这样才能确保后端解密成功。
encryptData() {
// 此处key为16进制
let key = '385f33cb91484b04a177828829081ab7';
console.log('密钥:', key);
// key格式化处理
key = CryptoJS.enc.Utf8.parse(key);
// 偏移量长度为16位, 注:偏移量需要与后端定义好,保证一致
let iv_key = '37fa77f6a3b0462d';
let iv = CryptoJS.enc.Utf8.parse(iv_key);
// 加密内容
const polygonGeojson = {
type: 'Feature',
properties: {},
geometry: {
type: 'Polygon',
coordinates: [
[
[106, 33],
[108.03955078125, 32.2313896627376],
[108.25927734375, 33.15594830078649],
[106, 33]
]
]
}
};
const content = JSON.stringify(polygonGeojson);
console.log('加密前:', polygonGeojson);
// 加密方法
const encryptedContent = CryptoJS.AES.encrypt(content, key, {
iv: iv,
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
const encStr = encryptedContent.ciphertext.toString();
console.log('加密后:', encStr);
// 解密方法
const decryptedContent = CryptoJS.AES.decrypt(
CryptoJS.format.Hex.parse(encStr),
key,//注意:后面这里最好使用 CryptoJS.format.Utf8.parse(key)
{
iv: iv,
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
}
);
console.log(
'解密:',
JSON.parse(CryptoJS.enc.Utf8.stringify(decryptedContent))
);
}
封装 :crypto-util.js
import CryptoJS from 'crypto-js';
// 加密数据
export function encryptData(data, str = "385f33cb91484b04a177828829081ab7") {
let key = CryptoJS.enc.Utf8.parse(str);
// 加密内容
const content = JSON.stringify(data);
// 加密方法
const encryptedContent = CryptoJS.AES.encrypt(content, key, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.ZeroPadding,
});
const encStr = encryptedContent.ciphertext.toString();
return encStr
}
//解密数据
export function decryptData(encStr, str = "385f33cb91484b04a177828829081ab7") {
if (!encStr) return
let key = CryptoJS.enc.Utf8.parse(str);
// 解密方法
const decryptedContent = CryptoJS.AES.decrypt(
CryptoJS.format.Hex.parse(encStr),
key, //注意:后面这里最好使用 CryptoJS.format.Utf8.parse(key)
{
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.ZeroPadding,
}
);
return JSON.parse(CryptoJS.enc.Utf8.stringify(decryptedContent))
}