概述
最近在项目开发中使用了对称加密对接,过程中遇到了些困惑踩了些坑总结了些经验,记录下来以供学习与探讨。
首先对称加密是什么?
对称加密又叫做私钥加密,即信息的加密和解密使用相同密钥的加密算法。对称加密的特点是算法公开、加密和解密速度快,适合于对大数据量进行加密。常见的对称加密有:DES、3DES、AES等。
前端如何实现?
前端可以使用crypto-js实现对称加密。crypto-js是谷歌开发的一个前端加密算法类库,可以非常方便的在前端进行其所支持的加解密操作。目前crypto-js已支持的算法有:MD5、SHA-1、SHA-256、AES、RSA、Rabbit、MARC4、HMAC、HMAC-MD5、HMAC-SHA1、HMAC-SHA256、PBKDF2等。
代码尝试:
- 前提:
- 加密算法【3DES】
- 加密模式【ECB】
- 加密填充模式【pkcs7padding】
- 秘钥为【abcdefg】
- 加密信息为【123456】
- 正确结果:8Q8GmNszg/Q=
3. api调用方式:
// message 加密的明文
// key 加密的密钥
var encrypted = CryptoJS.TripleDES.encrypt("Message", "key", {
mode, // 加密模式(CryptoJS.mode)中选择.
padding, // 加密填充模式(CryptoJS.pad)中选择。在分组密码中,当数据长度不符合分组长度时,需要按一定的方式,将尾部明文分组进行填充,这种将尾部分组数据填满的方法称为填充
});
- 初次尝试:
const key = 'abcdefg' // 秘钥
const message = '123456' // 明文
const encrypted = CryptoJS.TripleDES.encrypt(message, key, {
mode: CryptoJS.mode.ECB, // 加密模式
padding: CryptoJS.pad.Pkcs7, // 加密填充模式
})
console.log('输出结果')
console.log(encrypted.ciphertext.toString(CryptoJS.enc.Base64))
输出结果如上,与正确结果相差甚远,我们接下来深入api了解下。
- 深入了解:
// 根据api的接口,我们发现message和key传入的类型有WordArray
// 那么这个WordArray是什么?
CryptoJS.TripleDES.encrypt(message: WordArray | string, key: WordArray | string, cfg?: CipherOption): CipherParams;
// 我们根据源码找到
type WordArray = CryptoJS.lib.WordArray;
namespace CryptoJS {
/**
* Library namespace.
*/
export namespace lib {
/**
* An array of 32-bit words.
*/
interface WordArray {
//省略...
}
const WordArray: {
/**
* Initializes a newly created word array.
*
* @param words (Optional) An array of 32-bit words.
* @param sigBytes (Optional) The number of significant bytes in the words.
*
* @example
*
* var wordArray = CryptoJS.lib.WordArray.create();
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
*/
create(words?: number[], sigBytes?: number): WordArray;
};
}
}
这样看下来在CryptoJs内部WordArray是各算法主要的操作对象和结果,需要把message(密文)和key(密钥)转为一组32位字数组,根据此线索我们再次尝试。
- 再次尝试:
const key = CryptoJS.enc.Utf8.parse('abcdefg') // 加密的秘钥, 把Utf8字符串为32位字数组
const message = CryptoJS.enc.Utf8.parse('123456') // 加密的明文, 把Utf8字符串为32位字数组
const encrypted = CryptoJS.TripleDES.encrypt(message, key, {
mode: CryptoJS.mode.ECB, // 加密模式
padding: CryptoJS.pad.Pkcs7, // 加密填充模式
})
console.log('输出结果')
console.log(encrypted.ciphertext.toString(CryptoJS.enc.Base64))
输出结果一致!