非对称加密之RSA公钥加密算法
一. 公钥加密原理
Diffie和Hellman在1976年首次公开提出了公钥加密思想,这是有文字记载的几千年以来密码领域第一次真正革命性的进步。公钥算法基于数学函数,而不像对称加密算法那样是基于比特模式的简单操作。更为重要的是公钥加密系统是非对称的,它使用两个单独的密钥,使用两个密钥对于保密性、密钥分发和认证都产生了意义深远的影响。
公钥加密方案由6个部分组成:明文、公钥、加密算法、密文、私钥、解密算法。顾名思义,密钥对中的公钥是公开供其他人使用的,而只有自己知道私钥。通常的公钥加密算法根据一个密钥进行加密,根据密钥对中的另一个密钥进行解密(注意:并非只能使用公钥加密而使用私钥解密,某些非对称加密算法也可以使用私钥加密而使用公钥解密。)
对于一个公钥加密算法,必须满足以下要求:
- 容易计算生成密钥对;
- 已知公钥和明文,使用加密算法计算生成相应的密文对于软硬件是容易实现的;
- 已知私钥和密文,使用解密算法计算恢复原始的明文对于软硬件是容易实现的;
- 当攻击者已知公钥 PUb P U b 时,不可能通过计算推算出私钥 PRb P R b ;
- 当攻击者已知公钥 PUb P U b 和密文 C C 时,通过计算不可能恢复原始消息 M M ;
- 密钥对中任何一个都可用于加密,另一个则用于解密(这一点对于公钥加密算法来说不是必需的)。
二. 欧拉函数和扩展欧几里得算法
RSA加密算法是一种非对称加密算法,在公开密钥加密中被广泛使用。RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的,RSA就是他们三人姓氏开头字母拼在一起组成的。从那时起RSA便占据了公钥方案的绝对统治地位,成为最广泛接受和实现的公钥加密方法。
如上节所说,公钥加密算法基于数学函数,RSA也不例外,因此在正式介绍RSA之前,有必要先了解一下这个算法所用到的数据原理基础——欧拉函数和扩展欧几里得算法。
2.1 欧拉函数
互质数:公因数只有1的两个数,称为互质数。判断两数互质有以下法则:
- 任意两个质数互质;
- 两个不相等的数,较大的那个数是质数,两者互质;
- 两个不相等的数,较小的数是质数,较大的数不是较小数的倍数,两者互质;
- 1和任意自然数互质;
- 2和任意奇数互质;
- 如果 p>1 p > 1 ,那么 p p 和 p−1 p − 1 互质;
- 如果 p>1 p > 1 且 p p 是奇数,那么 p p 和 p−2 p − 2 互质。
欧拉函数 φ(n) φ ( n ) 求的是满足和 n n 互质且小于等于 n n 的整数个数。
欧拉函数有以下法则:
- n=1 n = 1 , φ(n)=1 φ ( n ) = 1 ;
- n n 为质数, φ(n)=n−1 φ ( n ) = n − 1 ;
- n=pm n = p m 其中 p p 为质数时, φ(n)=pm−pm−1=pm∗(1−1/p)=n∗(1−1/p) φ ( n ) = p m − p m − 1 = p m ∗ ( 1 − 1 / p ) = n ∗ ( 1 − 1 / p ) ;
- n=p1∗p2 n = p 1 ∗ p 2 其中 p1 p 1 , p2 p 2 都为质数时, φ(n)=φ(p1)∗φ(p2) φ ( n ) = φ ( p 1 ) ∗ φ ( p 2 ) ;
- 对于任意一个大于1的正整数 n n ,都可以写成质数的乘积: n=pk11∗pk22∗...∗pkrr n = p 1 k 1 ∗ p 2 k 2 ∗ . . . ∗ p r k r ,那么 φ(n)=n∗(1−1/p1)∗(1−1/p2)∗...∗(1−1/pr) φ ( n ) = n ∗ ( 1 − 1 / p 1 ) ∗ ( 1 − 1 / p 2 ) ∗ . . . ∗ ( 1 − 1 / p r ) 。
以上就是欧拉函数的通用计算公式。
简要证明一下上述法则3~5:
第3点, n=pm n = p m 时,由互质法则可知,比 p p 大的整数中,只要不是 p p 的倍数,都和 p p 互质,因此在 1∼pm 1 ∼ p m 中,只要不是 p p 的倍数,就都和 p p ,也和 pm p m 互质,因此 φ(pm)=pm−pm−1 φ ( p m ) = p m − p m − 1 ;
第4点, n=p1∗p2 n = p 1 ∗ p 2 时,同样由互质法则可知, 1∼p1∗p2 1 ∼ p 1 ∗ p 2 中,只要不是 p1 p 1 的倍数,就都和 p1 p 1 互质(共 p2 p 2 个),只要不是 p2 p 2 的倍数,就都和 p2 p 2 互质(共 p1 p 1 个),因此,不和 p1∗p2 p 1 ∗ p 2 互质的就是既不是 p1 p 1 倍数也不是 p2 p 2 倍数的整数,共 p1∗p2−p1−p2+1=(p1−1)∗(p2−1) p 1 ∗ p 2 − p 1 − p 2 + 1 = ( p 1 − 1 ) ∗ ( p 2 − 1 ) 个,即 φ(p1∗p2)=φ(p1)∗φ(p2) φ ( p 1 ∗ p 2 ) = φ ( p 1 ) ∗ φ ( p 2 ) ;
第5点, n=pk11∗pk11∗...∗pkrr n = p 1 k 1 ∗ p 1 k 1 ∗ . . . ∗ p r k r 时, pkxx p x k x 彼此互质,因此由第4点可知,
φ(pk11∗pk11∗...∗pkrr)=φ(pk11)∗φ(pk22)∗...∗φ(pkrr)=pk11∗pk22∗...∗pkrr∗(1−1/p1)∗(1−1/p2)∗...∗(1−1/pr)=n∗(1−1/p1)∗(1−1/p2)∗...∗(1−1/pr) φ ( p 1 k 1 ∗ p 1 k 1 ∗ . . . ∗ p r k r ) = φ ( p 1 k 1 ) ∗ φ ( p 2 k 2 ) ∗ . . . ∗ φ ( p r k r ) = p 1 k 1 ∗ p 2 k 2 ∗ . . . ∗ p r k r ∗ ( 1 − 1 / p 1 ) ∗ ( 1 − 1 / p 2 ) ∗ . . . ∗ ( 1 − 1 / p r ) = n ∗ ( 1 − 1 / p 1 ) ∗ ( 1 − 1 / p 2 ) ∗ . . . ∗ ( 1 − 1 / p r )
。
2.2 欧拉定理
如果两个正整数a和n互质,那么n的欧拉函数满足:
aφ(n)≡1(modn) a φ ( n ) ≡ 1 ( m o d n )
其中,如果n为质数p,那么可以表示为(
费马小定理):
ap−1≡1(modp) a p − 1 ≡ 1 ( m o d p )
2.3 乘法逆元
如果两个正整数a和n互质,那么一定可以找到整数b,使得ab-1被n整除,或者说ab被n除的余数是1。这时b被称为a的乘法逆元:
a∗b≡1(modn) a ∗ b ≡ 1 ( m o d n )
对于两个互质的正整数,乘法逆元一定存在且不唯一,而对于两个不互质的正整数,乘法逆元不存在。
2.4 扩展欧几里得算法
欧几里得算法使用辗转相除来求两个正整数a,b的最大公约数 gcd(a,b) g c d ( a , b ) :
gcd(a,b)=gcd(b,amodb) g c d ( a , b ) = g c d ( b , a m o d b )
扩展欧几里得算法则用来说明:对于两个正整数a,b,一定存在整数对
(x,y) ( x , y ) ,使得
ax+by=gcd(a,b) a x + b y = g c d ( a , b )
扩展欧几里得算法不仅用来求a, b的最大公约数,也用来求a mod b和b mod a的乘法逆元。(具体算法不在此赘述,有兴趣的同学可以了解一下扩展欧几里得算法)。
三. RSA算法
RSA算法利用了欧拉定理、乘法逆元的算法思想,来生成一对公钥和私钥,RSA是分组密码,对于某个正整数n,它的明文和密文是0~n-1之间的整数。
对于某一明文块 M M 和密文块 C C ,加密和解密有如下的形式:
C=MemodnM=Cdmodn=(Me)dmodn=Medmodn C = M e m o d n M = C d m o d n = ( M e ) d m o d n = M e d m o d n
其中
(e,n) ( e , n ) 为公钥,
(d,n) ( d , n ) 为私钥,
(e,d,n) ( e , d , n ) 要满足以下三个要求:
- 任意 0≤M<n 0 ≤ M < n , M=Medmodn M = M e d m o d n 总是成立;
- 任意 0≤M<n 0 ≤ M < n ,计算 Me M e 和 Cd C d 相对容易;
- 给定 e e 和 n n ,不可能推出 d d 。
3.1 RSA算法步骤
- 选择两个质数 p p 和 q q ;
- 计算 n=p∗q n = p ∗ q ;
- 计算 φ(n)=(p−1)(q−1) φ ( n ) = ( p − 1 ) ( q − 1 ) ;
- 选择 e e ,满足 e e 与 φ(n) φ ( n ) 互质,且 e<φ(n) e < φ ( n ) ;
- 计算并选择一个 e e 关于 φ(n) φ ( n ) 的乘法逆元 d<φ(n) d < φ ( n ) ,即 e∗d≡1(modn) e ∗ d ≡ 1 ( m o d n ) ;
- (e,n) ( e , n ) 为公钥, (d,n) ( d , n ) 为私钥;
- 加密明文块过程为 C=Memodn C = M e m o d n ,解密密文块过程为 M=Cdmodn M = C d m o d n 。
下面用一个简单的例子来说明一下算法步骤:
- 选择质数17和11;
- 计算 n=17∗11=187 n = 17 ∗ 11 = 187 ;
- 计算 φ(n)=16∗10=160 φ ( n ) = 16 ∗ 10 = 160 ;
- 选择 e=7 e = 7 ,与160互质;
- 计算选择一个 e e 关于 φ(n) φ ( n ) 的乘法逆元 d=23 d = 23 ;
- 公钥为 (7,187) ( 7 , 187 ) ,私钥为 (23,187) ( 23 , 187 ) ;
- 比如明文为88(<160),加密过程为 C=887mod187=11 C = 88 7 m o d 187 = 11 ;
- 解密过程为 M=1123mod187=88 M = 11 23 m o d 187 = 88 。
当e和d的比特数越大时,由(e,n)计算(d,n)越困难,算法越安全。
3.2 RSA算法公式论证
介绍完了RSA的算法步骤,有必要对其中步骤涉及的公式进行论证,首先让我们再来回顾一下我们一共出现的8个数字
- p: 质数;
- q:质数;
- n=p∗q n = p ∗ q ;
- φ(n)=φ(p∗q)=φ(p)∗φ(q)=(p−1)(q−1) φ ( n ) = φ ( p ∗ q ) = φ ( p ) ∗ φ ( q ) = ( p − 1 ) ( q − 1 ) ;
- e: 随机数,条件是 1<e<φ(n) 1 < e < φ ( n ) ,且 e e 与 φ(n) φ ( n ) 互质;
- d: e e 对于 φ(n) φ ( n ) 的乘法逆元 d d : ed≡1(modφ(n)) e d ≡ 1 ( m o d φ ( n ) ) ;
- m:明文;
- c:用公钥加密后的密文。
验证RSA算法成立,主要是验证解密公式成立:
cd≡m(modn)(3.1) (3.1) c d ≡ m ( m o d n )
根据加密算法:
me≡c(modn)→c=me−kn(3.2) (3.2) m e ≡ c ( m o d n ) → c = m e − k n
将公式3.2代入公式3.1中,可得
(me−kn)d≡m(modn) ( m e − k n ) d ≡ m ( m o d n )
由N次方和差公式分解多项式可知,
(me−kn)d ( m e − k n ) d 分解多项式中不包含
n n 的项只有
med m e d ,所以问题转为证明:
med≡m(modn)(3.3) (3.3) m e d ≡ m ( m o d n )
因为
d d 是
e e 关于
φ(n) φ ( n ) 的乘法逆元,所以
ed≡1(modφ(n))→ed=k∗φ(n)+1(3.4) (3.4) e d ≡ 1 ( m o d φ ( n ) ) → e d = k ∗ φ ( n ) + 1
将公式3.4代入公式3.3,可得
mk∗φ(n)+1≡m(modn)(3.5) (3.5) m k ∗ φ ( n ) + 1 ≡ m ( m o d n )
问题转为证明公式3.5。我们分两种情况来证明:
(1)
当m和n互质时
根据欧拉定理
mφ(n)≡1(modn)→mφ(n)=hn+1→(mφ(n))k=(hn+1)k≡1(modn)→(mφ(n))k=an+1→mφ(n)∗k+1=(an+1)∗m=amn+m≡m(modn) m φ ( n ) ≡ 1 ( m o d n ) → m φ ( n ) = h n + 1 → ( m φ ( n ) ) k = ( h n + 1 ) k ≡ 1 ( m o d n ) → ( m φ ( n ) ) k = a n + 1 → m φ ( n ) ∗ k + 1 = ( a n + 1 ) ∗ m = a m n + m ≡ m ( m o d n )
公式3.5得证,即:
med≡m(modn) m e d ≡ m ( m o d n )
(2) 当m和n不互质时:
因为 n=pq n = p q , p、q均为质数,所以m一定为p或q的倍数,以 m=kp m = k p 为例。考虑到m和q必定互质,根据欧拉定理和欧拉函数可得:
(m)φ(q)≡1(modq)→(kp)(q−1)≡1(modq)→(kp)(q−1)=jq+1→(kp)h(p−1)(q−1)≡1(modq)→(kp)h(p−1)(q−1)+1≡kp(modq)(3.6) (3.6) ( m ) φ ( q ) ≡ 1 ( m o d q ) → ( k p ) ( q − 1 ) ≡ 1 ( m o d q ) → ( k p ) ( q − 1 ) = j q + 1 → ( k p ) h ( p − 1 ) ( q − 1 ) ≡ 1 ( m o d q ) → ( k p ) h ( p − 1 ) ( q − 1 ) + 1 ≡ k p ( m o d q )
又因为
ed≡1(modφ(n))→ed=h∗φ(n)+1=h(p−1)(q−1)+1(3.7) (3.7) e d ≡ 1 ( m o d φ ( n ) ) → e d = h ∗ φ ( n ) + 1 = h ( p − 1 ) ( q − 1 ) + 1
将公式3.7代入公式3.6,得
(kp)ed≡kp(modq)→(kp)ed=kp+tq ( k p ) e d ≡ k p ( m o d q ) → ( k p ) e d = k p + t q
因为
(kp)ed≡0(modp) ( k p ) e d ≡ 0 ( m o d p ) ,所以
(kp+tq)≡0(modp) ( k p + t q ) ≡ 0 ( m o d p ) ,又p、q均为质数,所以
t=rp t = r p ,所以有
(kp)ed=kp+rpq→med=m+rn→med≡m(modn) ( k p ) e d = k p + r p q → m e d = m + r n → m e d ≡ m ( m o d n )
得证。
至此,我们已经论证了RSA算法的数论原理。
3.3 RSA算法可靠性
既然我们验证了RSA算法的有效性,那么该算法是不是真的可靠呢?也就是说算法是不是抗密码攻击呢?
再次回顾我们用过的六个数字: p,q,n,φ(n),e,d p , q , n , φ ( n ) , e , d ,这六个数字中,公钥用到了 e,n e , n 两个,其余四个数字都不是公开的,其中最关键的是 d d ,因为 d,n d , n 组成了私钥,一旦 d d 泄漏就等于私钥泄漏。
那么,有没有可能在知道 e,n e , n 两个数字的情况下,推导出 d d 来呢?
- ed≡1(modφ(n)) e d ≡ 1 ( m o d φ ( n ) ) 。只有知道 e e 和 φ(n) φ ( n ) ,才能算出 d d ;
- φ(n)=(p−1)(q−1) φ ( n ) = ( p − 1 ) ( q − 1 ) 。只有知道 p p 和 q q ,才能算出 φ(n) φ ( n ) ;
- n=pq n = p q 。只有将 n n 因数分解,才能算出 p p 和 q q 。
结论:如果 n n 可以被因式分解,d就可以算出,也就意味着私钥被破解。
那么 n n 的因式分解到底可不可行呢?庆幸的是,事实上大数的因式分解相当困难,也许你可以对3763进行分解(71*53),但是你没办法对下面的大整数分解:
123018668453011775513049495838496272077285356959533479219732245215172640050726
365751874520219978646938995647494277406384592519255732630345373154826850791702
6122142913461670429214311602221240479274737794080665351419597459856902143413
它等于两个质数的乘积:
33478071698956898786044169
84821269081770479498371376
85689124313889828837938780
02287614711652531743087737
814467999489
×
36746043666799590428244633
79962795263227915816434308
76426760322838157396665112
79233373417143396810270092
798736308917
这也是目前维基百科记录的人类分解的最大整数(232个十进制位,768个二进制位),除了暴力破解,还没有发现别的有效方法。所以,给RSA算法提供安全性保证的是当前人类计算能力对大数因式分解的限制,只要RSA算法的密钥对长度足够长(当然,和其他加密算法一样,这样做也限制了加解密速率),RSA算法就无法被破解。如果有一天,人们找到了大数因式分解的可行性算法,或者人类计算能力突破了大数因式分解的限制,那么这时,RSA算法就将退出历史舞台。