非对称加密

avatar

小序

先来讲个密码学历史故事

自从密码学诞生的那一天起,人们就面对着一个悖论。加密是为了安全地传递信息,但为了让接受者解开加密的信息,你又需要把密钥给他,那这个密钥又该怎么传递呢?如果不加密传递给他的话,有被截获的风险。但如果加密发送的话,接受者还没有密钥,又怎么能解开呢?这就变成了一个鸡生蛋、蛋生鸡的问题。

如果用形象一点的例子来说明的话,相当于A要向B传递一封信,但他不信任邮差,所以他把信放在一个箱子里锁起来,再让邮差把箱子送给B。但B收到箱子也是没有用的,因为他没有钥匙。那么这把钥匙要怎么送给B呢?直接让邮差送是不行的,因为邮差可能会打开箱子看信里的内容。那把第一个箱子的钥匙放进第二个箱子再锁起来呢?这样也不行,因为B也没有第二个箱子的钥匙。这样就陷入了一个死循环。

后来,有人想到了一个办法:A先把信放到箱子里后上一把锁,然后让邮差把箱子送给B。B在接到箱子后不打开,而是再上一把锁,这样箱子上就有两把锁了。B再让邮差把箱子送回给A,然后A把箱子上自己那把锁打开,让邮差再把箱子送回给B。这时箱子上只有B的一把锁了,B用自己的钥匙把箱子打开就可以了。这个过程中,邮差接触不到任何一把钥匙。

这种方法用箱子和锁来操作虽然行得通,但计算机算法却很难实现。因为一份数据先后经过了A算法加密、B算法加密,却要先用A的密钥来解密。而且同样的数据要来来回回发送三次,严重降低了通信效率。

1977年,三位科学家Rivest、Shamir、Adleman共同发明了一种神奇的算法,彻底解决了这个问题。

在这种算法中有公钥和私钥两种密钥,其中公钥可以公布给全世界的人知道,人们可以用公钥给数据加密。而只有拥有对应私钥的人才能对加密后的数据进行解密。这样人们就避免了密钥传递的问题。

如果用前面锁和箱子的例子来比喻的话,就相当于B制造了无数的处于开启状态的锁,并把这些锁丢在一个公共的广场上,同时B手里掌握着能打开这些锁的唯一的钥匙。如果有人要向B写一封信,他就把信放进到箱子里,然后从广场上捡一把锁回来把箱子锁上。接下来,他让邮差把这个箱子送到B那里去,B再用手里的钥匙把箱子打开。整个过程中,邮差都没有接触过钥匙。 就这样,划时代的非对称式加密算法诞生了。人们用三名科学家姓氏的首字母来命名这种算法:RSA算法。

定义

对称加密算法在加密和解密时使用的是同一个秘钥;而非对称加密算法需要两个密钥来进行加密和解密,这两个密钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。

与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

非对称加密优缺点

  • 优点:安全性更高,公钥是公开的,秘钥是自己保存的,不需要将私钥给别人。

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

RSA算法

RSA算法是现今使用最广泛的非对称加密算法,也是号称地球上最安全的加密算法。

生成密钥对

1.接收方随机选择两个不相等的质数p和q 例如,选择61和53(实际应用中,这两个质数越大,就越难破解。)

2.计算p和q的乘积n

n = 61×53 = 3233

n的长度就是密钥长度。3233写成二进制是110010100001,一共有12位,所以这个密钥就是12位。实际应用中,RSA密钥一般是1024位,重要场合则为2048位。

3.计算n的欧拉函数φ(n)

φ(n) = (p-1)(q-1)

算出φ(3233)等于60×52,即3120

4.随机选择一个整数e,条件是1< e < φ(n),且e与φ(n) 互质。

随机选择了17。(实际应用中,常常选择65537)

5.计算e对于φ(n)的模反元素d

所谓"模反元素"就是指有一个整数d,可以使得ed被φ(n)除的余数为1。

ed ≡ 1 (mod φ(n))

这个式子等价于 ed - 1 = kφ(n),即ed + φ(n)k = 1,即17d+3120k = 1

这个方程可以用"扩展欧几里得算法"求解,此处省略具体过程。总之,爱丽丝算出一组整数解为 (d,k)=(2753,-15),即 d=2753。

6.将n和e封装成公钥,n和d封装成私钥。

上面计算可知n=3233,e=17,d=2753

所以公钥就是(n,e)= (3233,17),私钥就是(n,d)=(3233, 2753)

RSA算法的可靠性

回顾上面的密钥生成步骤,一共出现六个数字:

 p,q,n,φ(n),e,d

这六个数字之中,公钥用到了两个(n和e),其余四个数字都是不公开的。其中最关键的是d,因为n和d组成了私钥,一旦d泄漏,就等于私钥泄漏。

那么,有无可能在已知n和e的情况下,推导出d?

结论:如果n可以被因数分解,d就可以算出,也就意味着私钥被破解。

可是,大整数的因数分解,是一件非常困难的事情。目前,除了暴力破解,还没有发现别的有效方法。维基百科这样写道

"对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA算法愈可靠。假如有人找到一种快速因数分解的算法,那么RSA的可靠性就会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的RSA密钥才可能被暴力破解。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要密钥长度足够长,用RSA加密的信息实际上是不能被解破的。"

加密和解密

假如一个人要向另外一个人发送加密信息m(m < n),则用上述的公钥(n,e)对m加密

所谓"加密",就是算出下式的c: me ≡ c (mod n)

上述公钥是 (3233, 17),加密信息m假设是65,

则me ≡ c (mod n)即是 6517 ≡ 2790 (mod 3233),c等于2790,所以加密后的数字就是2790,把这个加密数字传输出去。

拿到2790这个加密后的数据,就可以用自己的私钥(3233,2753)解密

可以证明以下等式一定成立 cd ≡ m (mod n) ,这里不细说

c为2790.则可以计算出 27902753 ≡ 65 (mod 3233),因此可以计算得加密前的数字为m=65

至此,"加密--解密"的整个过程全部完成。

我们可以看到,如果不知道d,就没有办法从c求出m。而前面已经说过,要知道d就必须分解n,这是极难做到的,所以RSA算法保证了通信安全。

总结

以上 RSA 算法的工作原理了。宏观上的思路就是,要找到一个包含取模运算的单向函数,保证信息加密容易,而反向解密很难。另外,还要找到第二个单向函数,也就是整数分解问题的函数,保证在知道分解结果的条件下,从公钥算出私钥是容易的,而如果不知道,就不可能算出私钥。真正的 RSA 算法,是这两个单向函数的综合使用。但是对于如何进行解密,公钥和私钥生成的细节,我们没有展开,因为这涉及到更多的数学推导。