6.1.1 三张图让你全面掌握加密解密技术
前言
加密解密技术,涉及面很广,这里,把前人的研究成果汇总起来,通过图表的形式来帮助记忆和筛选,方便日后使用。内容主要包括两个方面,一个是场景与算法,一个是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!
链接
本系列文章即时更新,若有兴趣,可通过Star
收藏,^-^
本源文地址: https://github.com/imfly/bitcoin-on-nodejs
电子书阅读: http://bitcoin-on-nodejs.ebookchain.org
电子书下载: 下载页面 PDF文件 ePub文件 Mobi文件