非对称加密算法之RSA

DinS          Written on 2017/11/23

本文介绍如何在crypto++中使用RSA加密算法,确保阅读过《crypto++框架介绍》,特别是要理解pipelining模式。

一图流解释非对称加密:

图片来源:https://baike.baidu.com/item/%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86

简单来说,非对称加密就是用两把密钥分别加密、解密,所以叫非对称。用于加密的密钥称为公钥(public key),用于解密的密钥称为私钥(private key)。
比如上图中乙生成一个公钥和一个私钥,然后把公钥公开给合作伙伴甲。想给乙发送机密信息的甲使用乙给的公钥加密信息,将密文发给乙。乙获得密文后用私钥才能解密得到明文。

优点:更加安全。因为只能用私钥解密,所以即使获得了甲的公钥也无法破译信息;另外私钥只自己保存,所以不存在传递密钥、同步密钥的问题,减小了泄露可能。

缺点:加密和解密花费时间长、速度慢,只适合对少量数据进行加密。

RSA加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA是目前最有影响力和最常用的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击。今天只有短的RSA钥匙才可能被强力方式解破,只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。当然这个不能破解是针对目前计算机运算而言的。

RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难。
对于RSA一个基本的介绍见http://blog.csdn.net/dbs1215/article/details/48953589
更深入的数学知识与RSA见http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html

了解了基本概念后就可以用Crypto++来试验了。
当然有一点要说明,RSA的私钥和公钥并不是随意拍脑袋得到的,所以Crypto++提供了密钥生成方法。

大图点这里

这是RSA加密部分的代码。
总体而言还是清晰的,上面简单介绍过pipelining所以这里从语义上看应该不构成障碍,唯一存疑的应该是那个随机数生成器。在AES中并没有出现这个东西,我们直接人为设计了密钥然后就用了。

这里存在随机数生成器是因为RSA本质上是大数分解,如果私钥和公钥设计的不好可以暴力破解。但是设计密钥程序员是不关注的,这是数学家的事,所以Crypto++提供了一个数字生成器RandomNumberGenerator用来生成各种数,方便不同的加密算法调用。

但是我们这里定义的是AutoSeededRandomPool,这是一个更加抽象的概念,是为了使用方便设计的。Crypto++里有各种数字生成器,但是你多少得懂一点密码学才能用好。如果只是想简单使用,那么就用这个AutoSeededRandomPool,就回避了数学问题。

另外提一句,这里出现了OAEP,是RSA加密方法的一种,另外还有PKCS1v15,但是已经不安全了所以不要使用。具体这个OAEP是什么超出了本文的讨论范围,读者感兴趣可以自行查找,在这里把它理解为一种加密方式即可。

运行结果:

明显比AES加密得到的密文长,这也说明了RSA的效率确实要低,只适合加密短字符串。

再看看解密过程:

大图点这里

没有什么太多可以说的,理解了pipelining都是套路,看看结果:

解密成功了!

不过呢这里有点问题,发现了没有?
我们用的是随机数生成器,所以每次加密出来的内容不一样,为之奈何?
答案就是自己设计,或者把key保存下来。显然后者更现实一点,Crypto++也提供了相应的功能,可参考https://www.cryptopp.com/wiki/Keys_and_Formats,这里暂时不讲了,以后有时间补上。

另外RSA还有一个数字签名的东西,我们在上例中没有涉及。什么是数字签名可参考http://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.html,
非常通俗易懂。如何使用可以参考Crypto++的wiki。

最后是完整的代码:

(大图点这里)

至于其他几种常见加密算法,可见《crypto++框架介绍》文末。