1. 简介
DES是一种对称加密 (Data Encryption Standard) 算法。于1977年得到美国政府的正式许可,是一种用56位密钥来加密64位数据的方法。一般密码长度为8个字节,其中56位加密密钥,每个第8位都用作奇偶校验。
DES算法一般有两个关键点,第一个是加密算法,第二个是数据补位。加密算法常见的有 ECB 模式和 CBC 模式。
ECB 模式: ECB(电子密本方式)其实非常简单,就是将数据按照8个字节一段进行DES加密或解密得到一段段的8个字节的密文或者明文,最后一段不足8个字节(一般补0或者F),按照需求补足8个字节进行计算(并行计算),之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。
优点:简单、有利于并行计算、误差不会被传递;
缺点:不能隐藏明文的模式、可能对明文进行主动攻击;
CBC 模式: 密文分组链接方式,它比较麻烦,加密步骤如下:
第一组数据 D1 与向量I异或后的结果进行 DES 加密得到第一组密文C1(注意:这里有向量I的说法,ECB模式下没有使用向量I);
第二组数据 D2 与第一组的加密结果 C1 异或以后的结果进行 DES 加密,得到第二组密文 C2;
之后的数据以此类推,得到 Cn
按顺序连为 C1C2C3…Cn 即为加密结果;
优点:不容易主动攻击,安全性好于 ECB,是 SSL、IPSec 的标准;
缺点:不利于并行计算、误差传递、需要初始化向量 IV;
2. Vue中 实现 DES 加密和解密
安装 crypto-js
npm install crypto-js
2.1 ECB 模式
2.1.1 封装方法
// utils/des.js import cryptoJs from 'crypto-js'; // 随机生成指定数量的16进制key(该方法非必须,也可自己指定key) const generatekey = (num) => { let library = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; let key = ""; for (var i = 0; i < num; i++) { let randomPoz = Math.floor(Math.random() * library.length); key += library.substring(randomPoz, randomPoz + 1); } return key; } /* * message:需要解密的字符串, * key: 密钥(加密解密密钥同一个) */ //DES加密 const encryptDes = (message, key = 'abcd@1234') => { var keyHex = cryptoJs.enc.Utf8.parse(key) var option = { mode: cryptoJs.mode.ECB, padding: cryptoJs.pad.Pkcs7 } var encrypted = cryptoJs.DES.encrypt(message, keyHex, option) return encrypted.ciphertext.toString(); // 返回hex格式密文,如需返回base64格式:encrypted.toString() } //DES解密 const decryptDes = (message, key = 'abcd@1234') => { var keyHex = cryptoJs.enc.Utf8.parse(key) var decrypted = cryptoJs.DES.decrypt( { ciphertext: cryptoJs.enc.Hex.parse(message) }, // 若 message 是 base64 格式,则无需转16进制hex,直接传入 message 即可 keyHex, { mode: cryptoJs.mode.ECB, padding: cryptoJs.pad.Pkcs7 } ) return decrypted.toString(cryptoJs.enc.Utf8) } export { generatekey, encryptDes, decryptDes, }
2.1.2 引入使用
<script> import { encryptDes, decryptDes,generatekey } from '@/utils/des.js' export default { data() { return { info:{ userName:'test', passWord:'Hi@123' } }; }, methods: { test(){ const key = generatekey(8); // 也可直接指定key let key = 'des'; //如果是对象/数组的话,需要先JSON.stringify转换成字符串 const encrypts = encryptDes(JSON.stringify(this.info), key); const dess = JSON.parse(decryptDes(encrypts, key)); console.log(encrypts, dess) } }, mounted() { this.test(); }, }; </script>
2.2 CBC 模式
2.2.1 封装方法
// utils/des.js import cryptoJs from 'crypto-js'; // 随机生成指定数量的16进制key(该方法非必须,也可直接指定固定key值) const generatekey = (num) => { let library = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; let key = ""; for (var i = 0; i < num; i++) { let randomPoz = Math.floor(Math.random() * library.length); key += library.substring(randomPoz, randomPoz + 1); } return key; } /* * message: 需要加解密的文本 key: 加解密的秘钥 iv: 偏移量,最短8位数,ecb模式不需要此参数 */ // 加密 const encrypt = (message, key = 'abcd@1234', iv = 'hello world') => { const keyHex = cryptoJs.enc.Utf8.parse(key); // 秘钥 const ivHex = cryptoJs.enc.Utf8.parse(iv); // 偏移量 const option = { iv: ivHex, mode: cryptoJs.mode.CBC, padding: cryptoJs.pad.Pkcs7 }; // Pkcs7填充方式 const encrypted = cryptoJs.DES.encrypt(message, keyHex, option); return encrypted.ciphertext.toString() // 加密出来为 hex格式密文 } // 解密 const decrypt = (message, key = 'abcd@1234', iv = 'hello world') => { const keyHex = cryptoJs.enc.Utf8.parse(key) const ivHex = cryptoJs.enc.Utf8.parse(iv) const decrypted = cryptoJs.DES.decrypt({ ciphertext: cryptoJs.enc.Hex.parse(message) }, keyHex, { iv: ivHex, mode: cryptoJs.mode.CBC, padding: cryptoJs.pad.Pkcs7 }) return decrypted.toString(cryptoJs.enc.Utf8) } export { generatekey, encrypt, decrypt, }
2.2.2 引入使用
<script> import { encrypt, decrypt, generatekey } from '@/utils/des.js' export default { data() { return { info:{ userName:'test', passWord:'Hi@123' } }; }, methods: { test(){ const key = generatekey(8); // 也可直接指定固定key值 let key = 'des'; //如果是对象/数组的话,需要先JSON.stringify转换成字符串 const encrypts = encrypt(JSON.stringify(this.info), key, '12345678'); const dess = JSON.parse(decrypt(encrypts, key, '12345678')); console.log(encrypts, dess) } }, mounted() { this.test(); }, }; </script>