三张图让你全面掌握加密解密技术

前言

加密解密技术,涉及面很广,这里,把前人的研究成果汇总起来,通过图表的形式来帮助记忆和筛选,方便日后使用。内容主要包括两个方面,一个是场景与算法,一个是Node.js的相关模块或组件。共三张脑图,具体请看:

1.加密解密纵览

下面这张图,是在 《密码学一小时必知》(见参考)基础上完成的,原作者是Colin Percival,密码学方面的专家,FreeBSD项目的安全长官,Tarsnap在线备份服务的创始人,scrypt密钥衍生算法的作者,非常值得参考学习。译者是 @byronhe ,翻译贡献这样的好文,包括下面有关论述场景与算法的实践指南,值得去为他点赞。

这张图,可以告诉你密码学中的概念,目的,案例,以及最佳的实践经验。

加密解密.png

2.场景与算法

这张图,是基于 《现代密码学实践指南(2015年)》(见参考) 完成的。可以说,在上一张图的基础上,更加具体,特别是对于场景的描述,让码农可以更加方便的作出正确的选择,值得拥有。其中,标注序号的,是有优先级的。

场景与算法选择.png

3.Node.js中的的加密和解密、签名与认证

这张图,主要参考了官方文档及其他一些文档(见参考),按照我个人的理解画得。如果你使用Node.js,基本上拿来看看图解,就能直接用了。特别是,默认选择了ed255519组件,如果你看了上面两篇实践,就知道这是签名与认证最好的选择,因此这里可以肯定的说,Crypto模块的签名与认证还是暂时不要用吧。Ebookcoin就是这么实践的,上一篇源码介绍的很详细。另一个是Natrium组件,也可以用于签名和认证,但主要是用来非对称加密和解密的。这张脑图里的三个组合,按照上面的实践经验来说,应该是当前Node.js加解密应用领域的最佳组合方案。

Node.js中的的加密和解密、签名与认证.png

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的部分。

  1. var crypto = require('crypto');
  2. var ed25519 = require('ed25519');
  3. var bobsPassword = 'This is my password, you don`t guess it!';
  4. var hash = crypto.createHash('sha256').update(bobsPassword).digest();
  5. var bobKeypair = ed25519.MakeKeypair(hash);

(2)给信息加密和签名

通常是先加密后签名。

这里使用Crypto给信息进行了简单加密,把Bob的公钥作为加密键值(但是既然是公钥,谁会不知道呢,除非Bob只把公钥给了Alice),可能还得Bob告诉Alice使用什么算法来解密。

  1. var message = 'Hi Alice, I love you!';
  2. var msgCiphered = cipher('aes192', bobKeypair.publicKey, message); //公钥进行加密,如果是Natrium,这里就是私钥加密
  3. var signature = ed25519.Sign(new Buffer(msgCiphered, 'utf8'), bobKeypair.privateKey); //私钥进行签名

(3)给Alice发送签名信息

这个就各显神通了。

(4)Alice验证并解密

通常是先验证后解密。

作为Bob的好朋友,Alice有他的公钥。

  1. if (ed25519.Verify(new Buffer(msgCiphered, 'utf8'), signature, bobKeypair.publicKey)) {
  2. // 验证函数返回了true,通过验证
  3. var msg = decipher('aes192', bobKeypair.publicKey, msgCiphered); //使用Bob的公钥解密
  4. console.log('签名合法,信息来自Bob!');
  5. console.log('Bob said: ', msg); //显示信息
  6. } else {
  7. // 验证函数返回了false,肯定不是Bob的信息.
  8. console.log('签名不合法!');
  9. }

(5)补充代码

上面用到的Crypto的加密解密方法:

  1. //解密
  2. function (algorithm, key, buffer){
  3. var encrypted = "";
  4. var cip = crypto.createCipher(algorithm, key);
  5. encrypted += cip.update(buffer, 'utf8', 'hex');
  6. encrypted += cip.final('hex');
  7. return encrypted;
  8. }
  9. //解密
  10. function decipher(algorithm, key, encrypted){
  11. var decrypted = "";
  12. var decipher = crypto.createDecipher(algorithm, key);
  13. decrypted += decipher.update(encrypted, 'hex', 'utf8');
  14. decrypted += decipher.final('utf8');
  15. return decrypted;
  16. }

(6)运行实例

使用下面的命令,可以运行上述代码:

  1. $ git clone https://github.com/imfly/node.js-practice
  2. $ cd node.js-practice
  3. $ npm install
  4. $ node crypto/

输出结果:

  1. 签名合法,信息来自Bob
  2. Bob said: Hi Alice, I love you!

链接

本系列文章即时更新,若有兴趣,可通过Star收藏,^-^

本源文地址: https://github.com/imfly/bitcoin-on-nodejs

电子书阅读: http://bitcoin-on-nodejs.ebookchain.org

电子书下载: 下载页面 PDF文件 ePub文件 Mobi文件

参考

Ed25519第三方组件

Ed25519官方网站

现代密码学实践指南(2015年)

密码学一小时必知

浅谈node.js中的Crypto模块