RSA算法是最重要算法之一,它是计算机通信安全的基石,安全可靠只要有计算机网络的地方就有RSA算法,在它诞生之前—即1976年以前,加解密信息使用同一种规则:

  • 甲方选择某一种加密规则,对信息进行加密;
  • 乙方使用同一种规则,对信息进行解密

虽然理论上,只要加解密“规则”(即“密钥”)足够复杂,这种方式也可安全的传递信息。但这种方法最大的弱点就是,密钥在传递的过程中易被泄露,这种加密和解密使用同样规则的方法,被称为“对称加密算法”。

一、RSA算法

倘若在加解密信息的过程中,能让加密密钥(公钥)与解密密钥(私钥)不同,即:

  1. 甲要传密信给乙,乙先根据某种算法得出本次与甲通信的公钥与私钥;
  2. 乙将公钥传给甲(公钥可以让任何人知道,即使泄露也没有任何关系);
  3. 甲使用乙传给的公钥加密要发送的信息原文m,发送给乙密文c;
  4. 乙使用自己的私钥解密密文c,得到信息原文m .

就可以很好的克服对称加密算法的弱点,这种新的加密模式被称为“非对称加密算法”。可以观察到,从始至终,私钥一直都在信息接收方乙处,只要乙自己不泄露出去,私钥就没有泄露的可能。

1977年,三位数学家Rivest、Shamir和Adleman设计了一种算法,可以实现非对称加密。这种算法用他们三个人的名字首字母命名,叫做RSA算法,RSA算法非常可靠,密钥越长,它就越难破解。

二、质数与互质数

这是小学数学的概念:一个大于1的自然数,除了1和它本身外,不能被其他自然数整除(除0以外)的数称之为质数(素数);否则称为合数

例如,15=3×5,所以15不是素数;13除了等于13×1以外,不能表示为其它任何两个整数的乘积,所以13是一个素数;1不是质数,也不是合数。

公约数只有1的两个数,叫做互质数。判断或选取互质数的方法/定理有很多,如下所示:

  1. 任意两个质数一定构成互质数(如3与11、53与61);
  2. 大数是质数的两个数一定是互质数(如97与88);
  3. 一个质数如果不能整除另一个合数,这两个数为互质数;即一个数是质数,另一个数只要不是前者的倍数,两者就构成互质关系(如3与10、5与26);
  4. 1和任何一个自然数在一起都是互质数;
  5. 相邻的两个自然数是互质数(如15与16);
  6. 相邻的两个奇数是互质数(如49与51)

在RSA算法中,我们通常使用以上第1条与第2条,即选取两个本身都是质数的数作为互质数,而以上第2条定理对于计算欧拉函数值有着积极作用。

三、模运算

模运算的定义如下:让m去被n整除,只取所得的余数作为结果,就叫做模运算

例如,10 mod 3 = 1 、26 mod 6 = 2 、28 mod 2 = 0

四、同余

“≡”是数论中表示同余的符号,同余的定义如下:

给定一个正整数m,如果两个整数a和b满足a-b能被m整除,即(a-b)modm=0, 那么就称整数a与b对模m同余,记作a≡b(modm),同时可成立amodm=b

再次提醒注意,同余与模运算是不同的

1a≡b(mod m)仅可推出b=a mod m

五、欧拉函数

欧拉函数本身需要一系列复杂推导,本部分仅介绍对认识RSA算法有帮助的部分:任意给定正整数n,计算在小于等于n的正整数之中,有多少个与n构成互质关系? 计算这个值的方法就叫做欧拉函数,以φ(n)表示.

例如,在1到8之中,与8形成互质关系的是1、3、5、7,所以φ(n)=4 。在RSA算法中,我们需要明白欧拉函数对以下定理成立:

  1. 如果n可以分解成两个互质的整数之积,即n=p×q,则有:φ(n)=φ(pq)=φ(p)φ(q);
  2. 根据“大数是质数的两个数一定是互质数”可以知道:一个数如果是质数,则小于它的所有正整数与它都是互质数;所以如果一个数p是质数,则有:φ(p)=p-1

由上易得,若我们知道一个数n可以分解为两个质数p和q的乘积,则有:

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

六、欧拉定理与模反元素

欧拉函数的用处,在于欧拉定理。“欧拉定理”指的是:如果两个正整数a和n互质,则n的欧拉函数φ(n)可以让下面的等式成立:

1(n)≡1(modn)  //φ(n)是a的平方数

也就是说,a的φ(n)次方被n除的余数为1,模反元素的推导过程如下:

Euler-Theorem
Euler-Theorem

意即,如果两个正整数a和n互质,那么一定可以找到整数b,使得ab-1被n整除,或者说ab被n 除的余数是1

七、加解密示例

根据以上介绍的定义和数学知识,假设甲要发送一串秘密数字m=65给乙,乙发送了一个公钥(n,e)=(3233,17)给甲。甲根据以下公式及公钥对密文m加密成c :

1me≡c(modn)  //m的e次方

代入相关的值后为:

c=memod n=6517mod3233=2790

甲将使用公钥加密的密文c=2790发送给乙,乙收到c=2790的密文后,使用私钥(n,d)=(3233,2753)根据以下公式进行解密:

cd=m(mod n)

代入相关的值后为:

m=cdmodn=27902753mod3233=65

乙使用与公钥不同的私钥成功计算出密文m,发现了吗?从始至终,用来解密的私钥(n,d)=(3233,2753)一直都在乙处,从未泄露。乙给甲的仅仅是用来加密的公钥(3233,17),这个公钥并不能用来解密,即使被他人截获,也没有任何泄密的风险。那么,乙是如何计算出给甲的公钥(3233,17)和私钥(3233,2753)的呢?

八、计算密钥

根据以上“真实的例子”,看看乙是如何计算密钥(公钥和私钥)的。

1、随机选择两个不相等的质数p和q(乙选择了61和53)

2、计算p和q的乘积n=p×q=61×53=3233

3、根据本文“欧拉函数”介绍过的公式

1φ(n)=(p-1)(q-1)
2代入计算n的欧拉函数值
3φ(3233)=(61-1)×(53-1)=60×52=3120

4、随机选择一个整数e,条件是1<e<φ(n),且e与φ(n)互质。乙就在1到3120之间,随机选择了17

5、因为e与φ(n)互质,根据求模反元素的公式计算e,对于e的模反元素d有:

1ed≡1(modφ(n))
2这个式子等价于
3(ed-1)(n)=k(k为任意正整数)
45ed-kφ(n)=1,代入数据得:
617d-3120k=1
7实质上就是对以上这个二元一次方程求解
8得到一组解为:(d,k)=(2753,-15)

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

1n=3233,e=17,d=2753
2所以公钥就是(3233,17),私钥就是(3233,2753)
3其中,n的长度就是密钥长度,3233写成二进制是110010100001

一共有12位,所以这个密钥就是12位。实际应用中,RSA密钥一般是1024位,重要场合则为2048位。

九、密钥组成与加解密公式

rsa-key
rsa-key

十、安全性

根据以上实例,也许会有疑问:公钥中已包含n=3233,我将其因式分解回n=3233=61×53 ,再根据乙计算密钥的流程,不就可以根据公钥得出私钥了。事实上,RSA的安全性就是源自你没办法轻易的对大整数“因式分解”,上面的例子,密钥长度是12位,因为这只是个示例,所以密钥长度实在是太短了。你可以将示例中的n作因式分解,但是你没法对下面这个整数进行因数分解:

 112301866845301177551304949
 258384962720772853569595334
 379219732245215172640050726
 436575187452021997864693899
 556474942774063845925192557
 632630345373154826850791702
 761221429134616704292143116
 802221240479274737794080665
 9351419597459856902143413
10它等于这样两个质数的乘积:
1133478071698956898786044169
1284821269081770479498371376
1385689124313889828837938780
1402287614711652531743087737
15814467999489
16×
1736746043666799590428244633
1879962795263227915816434308
1976426760322838157396665112
2079233373417143396810270092
21798736308917

事实上,这大概是人类已经分解的最大整数(232个十进制位,768个二进制位),对极大整数做因数分解的难度决定了RSA算法的可靠性。实际应用中,RSA密钥一般是1024位(安全),重要场合则为2048位(极其安全)。

本文摘自于 黄映焜的博客 — RSA算法基础详解 ,同样还推荐三个关于RSA不错的讲解链接。

阮一峰的RSA算法原理(二)

“不给力啊,老湿!”:RSA加密与破解

维基百科RSA (cryptosystem)

基本上上面提到的三篇都是在维基百科的基础上进行的翻译和再加工。