昨天写一个在线加密工具,今天介绍下使用 Node 如何使用 crypto-js 包实现散列运算及加密。
- 散列 MD5 SHA1 HmacMD5 HmacSHA1
- 对称加密 AES DES TripleDES
首先我想强调一下 MD5 等散列运算,属于一种不可逆的加密。为什么我要提到这一点,因为以前真的有一个同事跟我争论,说 MD5 可以解密,并信誓旦旦的找到在线工具给我演示,现在想起来我都哭笑不得。
将数据(如一段文字)运算变为另一固定长度值,是散列算法的基础原理
通过这段描述,我们需要注意两个点,一段文字和固定长度,运算的结果是固定长度,但是作为数据源的一段文字却没有限制长度,理论上这段文字可以无限大。那么问题来了,以 MD5 为例,他可以任意长度的数据加密到 32 位长度,如果他竟然可以解密的话,那他岂不是成了最牛逼的压缩工具了,还要那些压缩工具干啥。
之所以有些工具可以将它解密,是因为散列算法生成的结果是不变的,我们大可以将常用的数据算出 MD5 值并一一对应储存起来,这样一些常用的 MD5 就可以反推出原数据。这也是数据库单纯使用 MD5 等散列算法加密储存密码带来的隐患性。
好,扯的有点远,先回来看看 crypto-js 怎么使用。
下载
npm1
$ npm install --save crypto-js
yarn1
$ yarn add crypto-js
散列
MD5 等散列算法,因为计算结果的唯一性,常被用来作为检验文件是否被修改,如果某人
给你网传了一份数据,并把他计算得到的 MD5 告诉你,你拿到数据后也计算下 MD5 值,
如果一致,则数据在传递的过程中没有被修改过(等等,如果这个 MD5 值也在传递过程修
改了呢?闭嘴,就你话多),我们看下如何计算1
2
3
4
5
6var CryptoJS = require("crypto-js");
var hash = CryptoJS.MD5('message');
console.log(hash.toString()); // 78e731027d8fd50ed642340b7c9a63b3
var hash = CryptoJS.SHA1('message');
console.log(hash.toString()); // 6f9b9af3cd6e8b8a73c2cdced37fe9f59226e27d
Hmac
1996年后被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如SHA-2。2004年,证实MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。
想想也是,任意长度的本文都可以压缩到 32 位来表达,肯定会有可能产生重复,并且上边提到过,所有人运算得到的结果都是一样的,那这样数据的安全性就有了隐患,即使现在有个 SHA1, SHA256, SHA512
等等的 Plus 算法,但原理终归是一样的。同样一个密码,我如何跟其他人计算的不一样呢?稍微思考一下,你可能会得到这样的结果,我可以在原数据后面跟一个只有我和朋友才知道的数据(secret key),带着他一起计算,这样别人得到的结果肯定就不一样了。
对,这就是 Hmac 算法的原理1
2
3
4
5
6var CryptoJS = require("crypto-js");
var hash = CryptoJS.HmacMD5('message', 'secret-key');
console.log(hash.toString()); // 48ef0b47f0dde34665d4a3f548c2c591
var hash = CryptoJS.SHA1('message', 'secret-key');
console.log(hash.toString()); // 48de2656eac2c9c21b04faeec4f1be9672ef53c1
就这样,同样的文本因为有了 secret-key
的加入,计算的 MD5 /SHA1 就不再相同,你可以为自己的项目准备不同的 secret-key
,并最好定期更换。
对称加密
对称加密顾名思义,加解密双方使用相同的 key,就可以对数据进行加解密操作,注意,这里是可以解密,那就意味着,加密的结果长度取决于愿数据的长度,数据越大,结果越大。1
2
3
4var result = CryptoJS.AES.encrypt('message', 'secret-key').toString()
console.log(result); // U2FsdGVkX1+deb0glX+i9JpO9WiqJAXRVNnTD+3aeK8=
var msg = CryptoJS.AES.decrypt(result, 'secret-key').toString(CryptoJS.enc.Utf8);
console.log(msg); // message
并且每次计算的加密结果都是不一样的,这样也就减少了碰撞几率,加强了数据安全性。
还有更多算法见文档
更多思考
有对称加密,就有不对称加密,这种情况加解密双方使用的 key 就是不一样的了,这样就
避免了前面提到的,这个 key 在传递的过程中被窃取的情况,目前这也是最安全的加密方
式,但是不在本次文章的探讨范围内,以后有机会我们再聊。