在上一篇的简单的ctf题目我们看到整个加解密过程都是围绕着一个公钥和一个私钥展开的,这里不想太多赘述那些看起来非常繁琐的加解密过程。有关RSA背后涉及的数学的详细说明可以在Wikipedia上找到。
第一次看到关于RSA秘钥的生成的步骤,我看到一共出现了六个数字
p, q, n, φ(n), e, d
说实话,我当时是懵逼的,不过耐下心来看还是很有乐趣的,这里不对每个数字具体的作用做过多介绍。说实在的之所以不想再过多描述这些是因为目前互联网上有大批的文章做了同样的事情,但我还是绝得不够深入,有一种知其然而不知其所以然的味道。我打算用更多的篇章来记录分享我对RSA算法的理解。
谈到算法那必须的跟数学有关,What Is Mathematics(什么是数学),也是很棒的一本数,也是我强烈推荐给有强烈求知欲望和钻研精神的人的一本好书。抱歉,这篇文章可能会让你看起来写的很水。
对极大整数做因数分解的难度决定了RSA算法的可靠性。目前为止世界上还没有任何可靠的攻击RSA算法的方式。只要密钥长度足够长,用RSA加密的信息实际上是不能被解破的。
通常在CTF题目里都是满足了特定的条件,但这恰恰说明了安全性的取决定性因素的是使用者本身。做任何事情都一样最好的不一定是最适合你的。我感觉我的思绪又有一点飘,这里我想介绍一下欧几里得算法也叫(欧几里得辗转相除法)。
这里有一个一般定理:如果a是任意一整数而b是任意一大于零的整数,则我们总能找到一整数q,使
a = b*q+r
这里r是满足不等式0<=r
不必用除法来证明这个定理,我们只须注意,任意整数a,或它本身是b的一个倍数
a = bq
或它在b的两个相邻的倍数之间
bq < a < b(q+1) = bq + b
在第一种情况下,r = 0,等式a = b*q+r.在第二种情形下,从上面的第一个不等式我们有
a - bq = r > 0 和 a - bq = r < b,
从上述简单的事实出发,我们推测出许多重要的结论,其中第一个就是找两个整数的最大公因子的方法。
设a和b是任意两个不全为零的整数,考虑能同时整除a和b的全体正整数集合,这集合肯定是有限的,因为如果,比如说,a != 0,那么不管b怎样,都不会有一个比a大的数能是a的因子。因此a和b只能有有限多个公因子,**设d是其中最大的。整数d称为a和b的最大公因子,记作d = (a, b).**对a = 8和b = 12,我们通过直接实验求出(8, 12) = 4,而对a = 5, b = 9我们有(5, 9) = 1,当a和b是较大的数时,例如a = 1804,b = 328,试图通过试算和不断校正试算来求(a, b)这是很烦人的事。
辗转相除法(一个算法是指一个系统的计算程序)提供了一个简短而确定的方法。它建立在如下事实上:从形如:
a = bq + r
的任意关系式中可以推出:
(a, b)=(b, r)
因为对任意同时整除a和b的数u,有
a = su, b = tu,
它也整除r, 因为r = a - bq = su - qtu = (s - qt)u.反过来,每一个整除b和r的整数u有
b = s1u, r = t1u.
它也整除a,这是因为a = bq + r = s1uq + t1u = (s1q + t1)u.因此a和b的每一个公因子同时也是b和r的一个公因子,反之亦然。这样由于a和b的全体公因子集合与b和r的全体公因子集合相同,所以a和b的最大公因子必须等于b和r的最大公因子,这就证明了(a, b) = (b, r)
回过头来找1804和328的最大公因子,按照普通除法我们有 1804 = 5 * 328 + 164, 可以得到:
(1804, 328) = (328,164).
这时我们看到找(1804, 328)的问题,已经被一个只涉及较小的数的问题代替了。我们可以继续上述步骤:
(1804, 328)= (328, 164) = (164, 0) = 164.
因此164就是我们想要的结果。
找两个数的最大公因子的这个过程,在欧几里得的原本中是以几何形式给出的。对于任意两个不全为0的整数a和b,它可以用算数的形式如下描述,
由于(a, 0) = a ,我们可以假设b != 0,这样通过连除我们能够写出:
a = bq1 + r1 (0 < r1 < b)
b = r1q2 + r2 (0 < r2 < r1)
r1 = r2q3 + r3 (0 < r3 < r2)
…
只要余数r1, r2, r3,,不是0就继续写下去。从右边的不等式,我们看到一连串的余数形成正整数的一个严格递减序列:
b > r1 > r2 > r3 > r4 …>0.
因此最多b步(经常是更少的,因为两个相继的r之间的差通常是大于1的),0这个余数必然出现
rn-2 = rn-1qn + rn
rn-1 = rnqn+1 + 0
这时,我们知道 (a, b) = rn
另外有一个重要的性质.如果d = (a, b),则能找到正的或负的整数k和l,使
d = ka + lb
为了证明这点,让我们考虑连续的余数序列有:
r1 = a - q1b
r2 = b - q2r1 = b - q2(k1a + l1b)
= (-q2k1)a + (1 - q2l1)b = k2a + l2b
显然,这过程通过这一串余数r3, r4,…可以重复下去,直到得到一个表达式:
rn = ka + lb
这就是所要证明的。这一事实可以用来证明算数基本定理。这里是不是很熟悉,曾经让我们痛苦的
(二元一次方程式)
上面提到的定理应用在了RSA加密算法中,我认为这在其中起了至关重要的作用,因为这跟计算其中的d值密切相关。关于RSA加密算法我想分更多的篇幅来讲。
不得不说的是数学是一个奇妙且有趣的学科,数学是严谨的同时也是富有创造性的,这里不得不吐槽几句我们现在越来越流行的快餐文化,有越来越多的人在纯粹的不求甚解中在靠“直觉”和”经验“来做事情,,这使得我们更多人丧失了更多个的那%1的灵感。