上篇文章中讲到了密码学的相关知识,今天来简单谈谈 RSA。之前有提到过,对称密码通过将明文转换为复杂的形式来保证其机密性的,而公钥密码则是基于数学上困难的问题来保证机密性的。 RSA 就是利用了大整数的质因数分解问题的困难度。在谈它之前,我们先来谈谈时钟(只有指向小时的一根指针)运算。
时钟运算
我们来想想指针的转动,运用加、减、乘、除、乘法、对数处理一下。
加法
假设现在时钟的指针指向 0,往右转一个刻度就是 1,再转一个刻度就是 2,以此类推,当转到 10、11 之后,就会回到 0,这样指针就转了整整一圈。如果现在指针指向 8,向右转动 20 个刻度是多少呢?按照常识可知,不是指向 28,而是 4,因为每隔 12 就会回到 0,所以为 4,计算方法为:(8+20) / 12 = 28 / 12 = 2 余 4
。上面的例子就是求余数,只要求得除以 12 的余数,无论时钟转了多少刻度,我们就能算出它最终指向哪个位置。在数学中,除数求余数的运算
有个一个运算符: mod 。 所以上面的例子可以写成:28 mod 12 = 4, 28 除以 12 的余数
。在数学上,也称28 与 4 以 12 为模同余
。
减法
减法可以看做是时钟向左转动。我们先规定指针不能左转,只能右转。那么(8+x) mod = 0, 8 加上多少除以 12 的余数为 0 ?
因为 x 只能为 0,1,2...11
,不可能为 -7,我们将候选值一个一个的试,可以知道x = 5
,5 这个数字,在时钟运算中和 -7 是等价的。这里我们将减法转换为加法了,将指针向左转动 X 个刻度
和将指针向右转动 Y 个刻度
这两个操作是等价的。
乘法
乘法其实相当于加法的多次运算:8 * 4 mod 12 = 32 mod 12 = 8
。
除法
减法是加法的逆运算,除法是乘法的逆运算。先看看:7 * x mod 12 = 1
,我们将 0,1,2...11
一个一个代入 x 可知,x = 7。也就是:7 * 7 mod 12 = 1
,也就是在 mod 12 的世界中, 7 * 7 = 1,也就是 1 / 7 = 7
。再来看看这个算是:x * y mod 12 = 1
,在 mod 12 的世界中, x 与 y 互为倒数。那么在 0,1,2...11
中,是不是每一个数都存在相对应的倒数呢?实际上,时钟运算中某个数是否存在倒数
这个问题,与 RSA 中一个公钥是否存在相对应的私钥
这个问题是直接相关的。我们来看看 0,1,2...11
中的情况
1 | 0 * x mod 12 = 1, 不存在,不管 x 为多少都为 0。 |
我们上面的关系,我们推断出:在 mod 12 的世界中,存在倒数的数,它们和 12 之间的最大公约数是 1。所以,某个数是否存在倒数,可以通过这个数和 12 的最大公约数是否为 1 这个条件来进行判断。和 12 的最大公约数为 1 的数(5、7、11),在数学上称为和 12 互质的数
,也可以理解为相对于 12 的质数
。
乘方
指数运算。举个例子吧:
1 | 7^4 mod 12 |
这里中间步骤求 mod 的方法,可以避免计算大整数的乘积,RSA 中加密和解密也是用的这种方法。
对数
乘法的逆运算称为对数。时钟运算中的对数称为离散对数。我们来求下:7^x mod 13 = 8
,我们将 0,1,2...12
代入 x 中算一下:
1 | 7^0 mod 13 = 1 |
当数字很大时,求离散对数非常困难,也非常耗时。能快速求出离散对数的算法到现在还没发现,RSA 就是利用了这一点。 Diffie-Hellman 密钥交换协议(下篇博文会简单介绍)和 ElGamal 公钥算法中也用到了离散对数。
RSA
RSA 的加密公式为:密文 = 明文^E mod N
。解密公式为:明文 = 密文^D mod N
。其中 E 是加密(Encryption)的首字母,D 是解密(Decryption)的首字母,N 是数字(Number)的首字母。E 和 N 的组合就是公钥,当然 E 和 N 不是什么随便的数字,它们是经过严密计算得到的。D 和 N 的组合就是私钥,加密和解密中的 N 是相同的,并且 D 也不是什么随便的数字,它和 E 有着相当紧密的关系,否则用 E 加密的结果用 D 来解密是无法实现的。
生成密钥对
我们只要求出 E、D 和 N 就能生成密钥对。它的步骤如下:
- 求 N
我们先得准备两个很大的质数 p 和 q。如果 p 和 q 太小的话,密码会很容易被破译,太大的话计算时间又会变得很长。例如,假设 p 和 q 都是 512 比特,它们相对于 155 为的十进制(2^512 约等于 10^155)。1
N = p * q
- 求 L(L 仅在生成密钥对的过程中使用)
L 是 p-1 和 q-1 的最小公倍数(least common multiple, lcm)。1
L = lcm(p-1,q-1)
- 求 E
E 是一个比 1 大、比 L 小的数,此外, E 和 L 的最大公约数(greatest common divisor, gcd)必须为 1,这里是为了保证一定存在解密时需要使用的 D,之前在讲时钟运算减法的时候有提到。1
21 < E < L
gcd(E,L) = 1 - 求 D
D 需要满足以下条件其中 p、q、E 都需要用伪随机数生成器生成。1
21 < D < L
E * D mod L = 1
实践
我们用具体的较小的数实践一下一下吧
- p = 17, q = 19, 两个都是质数
- N = 17 * 19 = 323
- L = lcm(p-1,q-1) = lcm(16,18) = 144
- 求 E,gcd(E,L) = 1,满足条件的有
5,7,11,13,17,19,23,25,29,31,...
这些数称为和 L “互质的数”,也就是相对于 L 是质数,所以 25 也是可以的。我们选择 5 为 E 吧,公钥就是 (E,N)=(5,323),它是公开的。 - 求 D,
E * D mod L = 1, 5 * 29 mod 144 = 145 mod 144 = 1
,那么就取 29 为 D 吧,私钥就是 (D,N)=(29,323),它必须要妥善保管,不能告诉任何人。
加密
注意,要加密的密文必须是小于 N 的数,这是因为在加密和解密过程中都需要执行mod N
操作,而mod N
的结果必然小于 N,所以如果明文本身大于 N,那么解密后就无法得到正确的明文。我们就取明文为 123 吧,根据加密公式:密文 = 明文^E mod N
。 123^5 mod 323 = 225,因此密文是 225。
1 | = ((123 mod 323) * (123 mod 323) * (123 mod 323) * (123 mod 323) * (123 mod 323)) mod 323 |
我们发现123 323 271
都是质数,质数A mod 质数B = 质数A
,质数真的是个有意思的东西。
解密
明文 = 密文^D mod N = 225^29 mod 323 = 123。
对 RSA 的攻击
任何密码总有一天会被破解的,只是时间问题而已。那来谈谈怎么破解 RSA,密码破译者知道的信息有:密文、E、N,不知道的有:明文、D、p、q、L。
通过密文来求得明文
RSA 的加密过程为:密文 = 明文^E mod N
。既然密文、E、N都知道了,那有没有一种方法能够求出密文呢?如果没有 mod N 即密文 = 明文^E
的话,这就是个求对数的问题,难道不大。加上 mod N 后,就变成了求离散对数的问题了,这是非常困难的,目前还没发现求离散对数的高效算法。PS:至于更深入的问题讨论,不是搞数学的就没啥必要去深究了,攻城狮还有很多事情要做。
通过暴力破解找出 D
当 D 足够长时,是不可能在现实的时间内通过暴力破解找出 D 的。现在,RSA 中所使用的 p 和 q 都是 1024 长度以上,那么 N 的长度为 2048 以上,E 和 D 的长度和 N 差不多,所以要找出 D,就需要进行 2048 以上的暴力破解(2^2048 = 10 ^x,自己算是 x 是多少吧)。
通过 E 和 N 找出 D
E 和 D 的关系:E * D mod L = 1
,而 L 为:lcm(p-1,q-1)
,所以通过 E 计算 D 需要求出 p 和 q,所以质数 p 和 q 不能被密码破译者知道。当然密码破译者也可以通过下面的方法来求出 p 和 q。
- 对 N 进行质因数分解。所以一旦发现了对大整数进行质因数分解的高效算法,那么 RSA 就能够被破解。而问题是现在还没发现,而且也尚未证明质因数分解是否真的是非常困难的问题,甚至也不知道是否存在一种质因数分解的简单方法。
- 通过推测 p 和 q 进行攻击。由于 p 和 q 是通过伪随机数生成器产生的,如果伪随机数生成器的算法很差的话,那么就有可能推测出 p 和 q 来。
中间人攻击
中间人攻击(man-in-the-middle attack),就是攻击者混入发送者和接收者之间,对发送者伪装成接收者,对接收者伪装成发送者的攻击方式。这种攻击不仅针对于 RSA ,而是可以针对任何公钥密码,这个需要证书防御。
对 RSA 的 Q&A
下面来说说关于 RSA 的一些比较重要的问题。
RSA 与质数
Q: 越来越多的人生成 RSA 密钥对,质数会不会用光?
A: 这个不需要担心,来看看一组数据吧。512 比特能够容纳的质数的数量大约为 10 的 150 次方(2^512 约等于 10^150),这个数量比整个宇宙中原子的数量还要多。我们现在来做个假设吧,如果现在地球上 100 亿人,每个人每秒中生成 100 亿个密钥对,那么经过 100 亿年会生成多少对呢?
1 | 1 年最多 365 天,也就是 366 * 24 * 60 * 60 = 31622400 秒 |
3.16244 * 10^37
比 10^150
差远了,所以不用担心,当然,质数组合偶然碰撞的可能性还是存在的,不过事实上也可以忽略咯。
RSA 的长度
Q: 要抵御质因数分解,N 的长度需要达到多少比特?
A: N 无论有多长,总有一天都能够被质因数分解,现在的问题是,在现实的时间内 N 是否能够被质因数分解。当然,随着计算机性能的提高,分解的时间会进一步缩短。目前能够分解的长度为 1024 比特的整数,目前 RSA-2048(617位)的整数应该是不大可能被分解的。
1 | 计算方法为 2^RSA长度 = 10^位 |
这里有趣的现象叫做密码劣势:随着计算机技术的进步等,以前被认为是安全的密码会被破译。
总结
这里只简单地讲述了 RSA 的加密功能,它可以用来数字签名,相信你会看到过RSASHA1
吧,下次有机会再谈。
**转载请注明出处!http://joakimliu.github.io/2017/08/17/浅谈-RSA/ 谢谢! **