[Node.js] 对称加密、公钥加密和RSA
原文地址:http://www.moye.me/2015/06/14/cryptography_rsa/
引子
对于加解密,我一直处于一种知其然不知其所以然的状态,项目核心部分并不倚重加解密算法时,可以勉强对付过去,一旦需要频繁应用诸如 AES/RSA等算法,这种状态就颇令人捉急了。
是时候了解一下原理了,所以找来了这本图解密码技术 给自己补补课:
在该书深入浅出的指引下 ,补充了一些常识,在此进行一番梳理:
对称加密算法(共享密钥)
顾名思义,对称加密就是用相同的密钥进行加密和解密。说到对称加密,异或加密又是一个不得不提的概念:
XOR(异或加密)
明文与密钥进行一次 异或 (记做㊉ ) 运算将成为密文,密文再与密钥进行一次异或运算将还原为明文:
例如,字符串“Wiki”(8位ASCII:01010111 01101001 01101011 01101001) 可以按如下的方式用密钥11110011进行加密:
01010111 01101001 01101011 01101001 11110011 11110011 11110011 11110011 = 10100100 10011010 10011000 10011010 此种加密方法类似对称加密,故解密的方式如下:
10100100 10011010 10011000 10011010 11110011 11110011 11110011 11110011 = 01010111 01101001 01101011 01101001
我们也可以用代码验证这一特性:
var key = 0b10110010;
var number = 22;
var encrypted = number ^ key; // ㊉ => 密文 164
console.log(encrypted ^ key); // ㊉ => 明文 22
光使用XOR,就能实现最基本的对称加密,前提是选择一个合适的密钥。而其它对称加密算法 如DES/AES 等,无不是在 XOR 基础上的扩展。
AES 对称加密
AES 即 高级加密标准(Advanced Encryption Standard),是取代前任标准(DES)成为新标准的一种对称加密算法(DES被取代是因为其算法有缺陷,导致其能被短时间内暴力破解,所以DES被弃用,建议使用AES)。现行AES的实现算法为 Rijndael,是比利时科学家Joan Daemen 和 Vincent Rijmen 设计的分组密码算法。
分组的意思是说,AES 算法的输入是要分组的,分组长度可以在 128/196/256 比特中进行选择(即一轮可加密这么多比特的明文生成同样长度的密文,一次加密可能需要迭代多轮)。
模式
分组密码算法只能加密固定长度的分组,但是我们需要加密的明文长度可能会超过分组密码的分组长度,这时就需要对分组密码算法进行迭代,以便将一段很长的明文全部加密。而迭代的方法就称为分组密码的模式。
模式有很多种类,分组密码的主要模式有:
- ECB 模式:Electronic Codebook mode (电子密码本模式)
- CBC 模式:Cipher Block Channing mode(密码分组链接模式)
- CFB 模式:Cipher FeedBack mode (密文反馈模式)
- OFB 模式:Output FeedBack mode(输出反馈模式)
- CTR 模式:CounTeR mode(计数器模式)
这几种模式的运作流程这里不做赘述,只需知道:
- ECB过于简单而不安全,已被弃用;
- CFB可被施以重放攻击;
- OFB 和 CTR 都可被主动攻击者反转密文,而引起解密后明文中的相应比特也发生变化;CTR比之OFB,多出能支持并发计算的特性,此外CTR是流式密码;
- CBC虽不支持并行计算,但是却是这些模式中最为安全的
下图为CBC模式的算法结构图:
公钥加密算法
公开密钥加密,也称为非对称加密(asymmetric cryptography),一种密码学算法类型,在这种密码学方法中,需要一对密钥,一个是私人密钥,另一个则是公开密钥。这两个密钥是数学相关,用某用户密钥加密后所得的信息,只能用该用户的解密密钥才能解密。如果知道了其中一个,并不能计算出另外一个。因此如果公开了一对密钥中的一个,并不会危害到另外一个的秘密性质。称公开的密钥为公钥;不公开的密钥为私钥。
公钥加密解决了一个对称加密的密钥配送难题:如何安全的传递解密用的密钥。方案是:不传递,加密者和解密者所持密钥不一样,特点如下:
- 密文发送者只需要加密密钥(公钥
- 密文接收者只需要解密密钥(私钥
- 解密密钥不可以被窃听者获取
- 加密密钥被窃听者获取也没有安全问题
RSA 公钥加密
RSA 是一种公钥加密算法,它的名字是用三位开发者 R. Rivest、A. Shamir 和 L. Adleman 的姓氏首字母组成。RSA 可被用于公钥密码和数字签名,算法于1983年在美国取得专利,目前该专利已过期(由于该算法在申请专利前就已经被发表了,在世界上大多数其它地区这个专利权不被承认)。
在RSA中,明文、密钥和密文都是数字,公私钥对是两对数字:
- 公钥是 (数E,数N)
- 私钥是 (数D,数N)
加密就是 用明文数字的E次方求 mod N (取余)的结果,过程可以用下列公式来表达:
密文 = 明文 E mod N
对密文的数字的D次方求 mod N就可以得到明文,解密过程可以用如下公式来表达:
明文 = 密文 D mod N
生成密钥对流程
(1) 求 N
随机生成两个很大的质数 p 和 q,那么 N = p * q
(2) 求 L
临时量 L 仅被用于生成密钥对的过程中,它是 p -1 和 q - 1 的最小公倍数(least common multiple, lcm),用lcm(X, Y) 来表示 “X和Y的最小公倍数” ,则L可用公式表示为:
L = lcm(p-1, q-1)
(3) 求E
E 和 L 之间存在如下关系:
1 < E < L
gcd(E, L) = 1 E 和 L 的最大公约数为1 (E 和 L 互质)
要找出满足 gcd(E, L) = 1 的数,还是要使用伪随机数生成器。通过伪随机数生成器在 1 < E < L 的范围内生成 E 的候选数,然后再判断其是否满足 gcd(E, L) = 1 这个条件。
(4) 求D
数D 是由数 E 计算得到的。D、E 和 L 之间必须具备如下关系:
1 < D < L
E * D mod L = 1
只要数 D 满足上述条件,则通过 (数E,数N) 加密的密文,都可以通过 (数D,数N) 进行解密。
模拟实践
用较小的数来实践一把RSA的密钥生成和加解密:
(1) 求N
选择两个质数,比如: p = 17 和 q = 19
N = 17 * 19 = 323
(2) 求 L
L = lcm (p-1, q-1) = lcm(16, 18) = 144
(3) 求 E
E 和 L 的最大公约数必须是1:
gcd(E, L) = 1
满足条件的数 E有很多,100以内的质数有:
5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
我们挑一个,比如 5 作为E,那么 公钥对就是(E=5, N=323)
(4) 求 D
D 必须满足:
E * D mod L = 1
在 E = 3 的情况下,D = 59 是满足的,因为:
5 * 29 mod 144 = 1
所以 私钥对就是(D=29, N=323)
公/私钥对都有了,就可用于加解密了,假设有明文 42:
(5) 加密
密文 = 明文 E mod N => 42 5 mod 323 = 264
(6) 解密
明文 = 密文 D mod N => 264 29 mod 323 => 数比较大,可分解求幂 :
(264 10 mod 323) * (264 10 mod 323) * (264 9 mod 323) mod 323 = 42
RSA 的算法原理
想了解更多RSA背后的数学知识,可以参考阮一峰的 RSA算法原理(一)和 (二)
AES和RSA的应用
混合密码系统
通过比较,我们知道:
- RSA 比 AES 更难破解,因为它不需要担心密钥在传递过程中有泄露,只存在暴力破解一种可能;
- AES的优势是以分组为轮,加解密速度非常快,一般而言,AES 速度上数百倍于 RSA
所以在实际应用中,我们会混合应用AES和RSA,比如 需要加密一个尺寸不小的文件,可能会这么干:
- 生成一个一次性随机密钥,算法上采用 AES 的CBC模式 aes-256-cbc(加密分组为256比特)对文件进行加密
- 加密完成后,为了安全的传递这个一次性随机密钥,我们使用 接收方的RSA公钥 对其进行加密,随加密后的文件一起发送
- 接收方使用私钥进行解密,得到AES密钥原文,并用其解密文件
例子
以上场景的应用,比如在 Node.js 中,可以这么实现:
(1) 生成 AES 随机密钥:
var passwdLength = 256; // 初始化随机向量长度
var aesPassword = require('crypto').randomBytes(passwdLength);
require('fs').writeFileSync('aesPassword', aesPassword); // 写入文件供openssl使用
(2) 使用openssl aes 加密 filename代表的文件:
openssl enc -aes--cbc -kfile aesPassword -in filename -out filename.out
(3) 使用open rsa 加密密钥
openssl enc rsautl -encrypt -pubin -inkey id_rsa.pub -in aespassword -out aespassword.out
将 filename.out 和 aespassword.out 一并发给对方即可,接收方使用openssl 进行一次逆操作即可实现解密。
参考
- openssl 命令手册:http://netkiller.github.io/cryptography/openssl/index.html
- Node-RSA: https://github.com/rzcoder/node-rsa
更多文章请移步我的blog新地址: http://www.moye.me/
[Node.js] 对称加密、公钥加密和RSA的更多相关文章
- java结合node.js非对称加密,实现密文登录传参——让前后端分离的项目更安全
前言 在参考互联网大厂的登录.订单.提现这类对安全性操作要求较高的场景操作时发现,传输的都是密文.而为了目前项目安全,我自己负责的项目也需要这方面的技术.由于,我当前的项目是使用了前后端分离技术, ...
- Node.js 内置模块crypto加密模块(5) RSA
RSA加密算法 写在前面: 了解RSA算法的原理请查看下面的文章 一文搞懂 RSA 算法 来源:简书 作者:somenzz 在使用 Node 进行 RSA 加密之前我们首先需要获取RSA公共和私有密 ...
- Node.js des加密
常见的加密算法基本分为这几类,1 :线性散列算法.2:对称性加密算法.3.非对称性加密算法 (记记记) 线性散列算法(签名算法):MD5,SHA1,HMAC比如MD5:即Message-Digest ...
- Node.js 使用 RSA 做加密
RSA RSA加密算法是一种非对称加密算法. 假设 A 与 B 通信.A 和 B 都提供一个公开的公钥.A 把需要传递的信息,先用自己的私钥签名,再用 B 的公钥加密.B 接收到这串密文后,用自己的私 ...
- node.js下使用RSA加密事例(windows)
1.安装openss 直接下载window下的安装包 http://houjixin.blog.163.com/blog/static/3562841020144143494875/ 以我发博文现在的 ...
- RSA不对称加密,公钥加密私钥解密,私钥加密公钥解密
RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作. RSA是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一 ...
- Node.js进阶:5分钟入门非对称加密方法
前言 刚回答了SegmentFault上一个兄弟提的问题<非对称解密出错>.这个属于Node.js在安全上的应用,遇到同样问题的人应该不少,基于回答的问题,这里简单总结下. 非对称加密的理 ...
- AES,RSA对称加密和非对称加密
1.关于RSA加密机制:是非对称加密方式,两个钥,公钥和私钥,公钥用于加密数据,可以分享给其他用户,私钥可以用于解密用公钥加密的数据,关于安全问题是公钥泄露不会影响安全问题,公钥与私钥是一一对应的关系 ...
- Node.js 加密
稳定性: 2 - 不稳定; 正在讨论未来版本的 API 改进,会尽量减少重大变化.详见后文. 使用 require('crypto') 来访问这个模块. 加密模块提供了 HTTP 或 HTTPS 连接 ...
随机推荐
- Android中实现多彩的霓虹灯
1.布局文件 <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:androi ...
- Android ExpandableListView
ExpandableListView 结合SimpleExpandableListAdapter用法 最终实现效果: activity_main.xml <?xml version=" ...
- c# 列举所有窗口和子窗口
private delegate bool WNDENUMPROC(IntPtr hWnd, int lParam); [DllImport("user32.dll", Exact ...
- [leetcode 37]sudoku solver
1 题目: 根据给出的数独,全部填出来 2 思路: 为了做出来,我自己人工做了一遍题目给的数独.思路是看要填的数字横.竖.子是否已经有1-9的数字,有就剔除一个,最后剩下一个的话,就填上.一遍一遍的循 ...
- 解剖SQLSERVER 第十篇 OrcaMDF Studio 发布+ 特性重温(译)
解剖SQLSERVER 第十篇 OrcaMDF Studio 发布+ 特性重温(译) http://improve.dk/orcamdf-studio-release-feature-recap/ ...
- 欢迎访问我的最新个人技术博客http://zhangxuefei.top
博客园已停止更新,欢迎访问我的最新个人技术博客http://zhangxuefei.top
- PHP版微信公共平台消息主动推送,突破订阅号一天只能发送一条信息限制
2013年10月06日最新整理. PHP版微信公共平台消息主动推送,突破订阅号一天只能发送一条信息限制 微信公共平台消息主动推送接口一直是腾讯的私用接口,相信很多朋友都非常想要用到这个功能. 通过学习 ...
- 树莓派(Raspberry Pi)搭建简单的lamp服务
树莓派(Raspberry Pi)搭建简单的lamp服务: 1. LAMP 的安装 sudo apt-get install apache2 mysql-server mysql-client php ...
- Java设计模式4:单例模式
前言 非常重要,单例模式是各个Java项目中必不可少的一种设计模式.本文的关注点将重点放在单例模式的写法以及每种写法的线程安全性上.所谓"线程安全性"的意思就是保证在创建单例对象的 ...
- 人人都是 DBA(XIV)存储过程信息收集脚本汇编
什么?有个 SQL 执行了 8 秒! 哪里出了问题?臣妾不知道啊,得找 DBA 啊. DBA 人呢?离职了!!擦!!! 程序员在无处寻求帮助时,就得想办法自救,努力让自己变成 "伪 DBA& ...