三张图让你全面掌握加密解密技术
前言
加密解密技术,涉及面很广,这里,把前人的研究成果汇总起来,通过图表的形式来帮助记忆和筛选,方便日后使用。内容主要包括两个方面,一个是场景与算法,一个是 Node.js 的相关模块或组件。共三张脑图,具体请看:
1.加密解密纵览
下面这张图,是在 《密码学一小时必知》(见参考)基础上完成的,原作者是 Colin Percival,密码学方面的专家,FreeBSD 项目的安全长官,Tarsnap 在线备份服务的创始人,scrypt 密钥衍生算法的作者,非常值得参考学习。译者是 @byronhe ,翻译贡献这样的好文,包括下面有关论述场景与算法的实践指南,值得去为他点赞。
这张图,可以告诉你密码学中的概念,目的,案例,以及最佳的实践经验。
2.场景与算法
这张图,是基于 《现代密码学实践指南(2015 年)》(见参考) 完成的。可以说,在上一张图的基础上,更加具体,特别是对于场景的描述,让码农可以更加方便的作出正确的选择,值得拥有。其中,标注序号的,是有优先级的。
3.Node.js 中的的加密和解密、签名与认证
这张图,主要参考了官方文档及其他一些文档(见参考),按照我个人的理解画得。如果你使用 Node.js,基本上拿来看看图解,就能直接用了。特别是,默认选择了 ed255519
组件,如果你看了上面两篇实践,就知道这是签名与认证最好的选择,因此这里可以肯定的说,Crypto 模块的签名与认证还是暂时不要用吧。 Ebookcoin
就是这么实践的,上一篇源码介绍的很详细。另一个是 Natrium
组件,也可以用于签名和认证,但主要是用来非对称加密和解密的。这张脑图里的三个组合,按照上面的实践经验来说,应该是当前 Node.js 加解密应用领域的最佳组合方案。
4.趣味实践
还是用在《 在 Node.js 中使用加密解密技术 》里的的例子吧。设定角色,男生叫做 Bob,他的女友叫 Alice。
场景
Bob 想向女友表达埋藏已久的心声“I love you!”,但碍于男人的颜面(男人都这样吗?),不好意思当面说出口,只好加密传输。这里基于一个可行的假设,就是他们已经拥有彼此的公钥,或者可以简单获得。
需求
- 加密:不能让别人看到信息;
- 解密:女友可以恢复并查看;
- 签名:Bob 可以签名信息,确保不被篡改;
- 认证:女友收到信息,可以验明正身,确认是 Bob 所发,而不是别人的恶作剧。
方案
利用以上三张图,我们可以很快拿出技术方案。
- 加密与解密技术:第二张图显示说,这种加密之后又解密原文的场景非常少见。技术上,最好使用 NaCl,其次是 libsodium(背后仍然是 NaCl),但是搜索了一下 github,Node.js 社区还没有相关 NaCl 稳定的封装包,libsodium 倒是有一个 Natrium(但是,写作本文时,连安装都没有成功,有验证成功的,请告诉我一声)。因此,只能选择使用 Crypto 简单加密和解密。
- 签名与验证技术:当然最好的选择是
ed25519
了。
编码
新建一个简单的 Node.js 工程, 代码在这里: https://github.com/imfly/node.js-practice/blob/master/crypto/index.js
(1) 生成密钥对
Bob 没有使用随机字符串,而是使用一个密码,并采取 SHA256 算法生成密钥对,请看思维导图,有关 hash 的部分。
var crypto = require('crypto');
var ed25519 = require('ed25519');
var bobsPassword = 'This is my password, you don`t guess it!';
var hash = crypto.createHash('sha256').update(bobsPassword).digest();
var bobKeypair = ed25519.MakeKeypair(hash);
(2) 给信息加密和签名
通常是先加密后签名。
这里使用 Crypto 给信息进行了简单加密,把 Bob 的公钥作为加密键值(但是既然是公钥,谁会不知道呢,除非 Bob 只把公钥给了 Alice),可能还得 Bob 告诉 Alice 使用什么算法来解密。
var message = 'Hi Alice, I love you!';
var msgCiphered = cipher('aes192', bobKeypair.publicKey, message); //公钥进行加密,如果是 Natrium,这里就是私钥加密
var signature = ed25519.Sign(new Buffer(msgCiphered, 'utf8'), bobKeypair.privateKey); //私钥进行签名
(3) 给 Alice 发送签名信息
这个就各显神通了。
(4)Alice 验证并解密
通常是先验证后解密。
作为 Bob 的好朋友,Alice 有他的公钥。
if (ed25519.Verify(new Buffer(msgCiphered, 'utf8'), signature, bobKeypair.publicKey)) {
// 验证函数返回了 true,通过验证
var msg = decipher('aes192', bobKeypair.publicKey, msgCiphered); //使用 Bob 的公钥解密
console.log('签名合法,信息来自 Bob!');
console.log('Bob said: ', msg); //显示信息
} else {
// 验证函数返回了 false,肯定不是 Bob 的信息.
console.log('签名不合法!');
}
(5) 补充代码
上面用到的 Crypto 的加密解密方法:
//解密
function (algorithm, key, buffer){
var encrypted = "";
var cip = crypto.createCipher(algorithm, key);
encrypted += cip.update(buffer, 'utf8', 'hex');
encrypted += cip.final('hex');
return encrypted;
}
//解密
function decipher(algorithm, key, encrypted){
var decrypted = "";
var decipher = crypto.createDecipher(algorithm, key);
decrypted += decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
(6) 运行实例
使用下面的命令,可以运行上述代码:
$ git clone https://github.com/imfly/node.js-practice
$ cd node.js-practice
$ npm install
$ node crypto/
输出结果:
签名合法,信息来自 Bob!
Bob said: Hi Alice, I love you!
参考
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论