RSA算法是由MIT的Ron Rivest,Adi Shamir和Len Adleman于1977年提出并于1978年发表的算法。自其诞生之日起,该算法就成为被普遍接受并实现的通用公钥加密方法。算法
算法描述安全
RSA算法使用乘方模运算,明文以分组为单位进行加密,每一个分组的二进制值均小于模n(为两个大素数的乘积),在实际应用中,分组的大小是i位,其中2i < n ≤ 2i+1函数
对明文分组M和密文分组C,加密和解密过程以下:性能
C = Me mod n 测试
M = Cd mod n = Med mod n加密
公钥为PU = {e , n} 私钥位PR = {d , n}spa
该算法用到下列元素:对象
两个素数p,q (保密的,选定的)blog
n = pq (公开的,计算得出的)数学
e知足gcd(φ(n) , e) = 1; 1 < e < φ(n) (公开的,选定的)
d ≡ e-1 (mod φ(n)) (保密的,计算得出的)
当e和d互为模φ(n)的乘法逆时,Med mod n = M (当e与φ(n)互素时必有乘法逆)
证实: ed mod φ(n) = 1 等效于 ed = kφ(n) + 1 k∈Z
Mkφ(n) + 1 mod n = Mk(p - 1)(q - 1) + 1 mod n n = p × q
首先可证实 Mk(p - 1)(q - 1 ) + 1 mod p = M mod p
若M与p不互素,因为p是素数,则p必可整除M,此时M mod p = 0
Mk(p - 1)(q - 1) + 1 mod p = 0 = M mod p
若M与p互素,由欧拉定理,Mφ(p) mod p = 1
Mk(p - 1)(q - 1) + 1 mod p = [(M)Mk(p - 1)(q - 1) ] mod p
= [(M)(M(p - 1))k(q - 1) ] mod p
= [(M)(Mφ(p))k(q - 1) ] mod p
= (M mod p) × [(Mφ(p)) mod p]k(q - 1)
= M mod p
[Mk(p - 1)(q - 1) + 1 - M] mod p = [Mk(p - 1)(q - 1) + 1 mod p] - [M mod p] = 0
所以p整除[Mk(p - 1)(q - 1) + 1 - M] ,同理q也整除[Mk(p - 1)(q - 1) + 1 - M]。由于p和q是不一样的素数,因此一定存在一个整数r知足:
[Mk(p - 1)(q - 1) + 1 - M] = px1 = qx2 = pqr = nr
故n整除[Mk(p - 1)(q - 1) + 1 - M],因此Mkφ(n) + 1 mod n = Mk(p - 1)(q - 1) + 1 mod n = M
RSA的加密、解密过程及实例
在这个例子中,明文是一串字母,每一个字母与一个两位的十进制数字对应(如a=00,A=26),明文的每一分组块由四个十进制数字组成,即两个字母。
计算上的简化
一、模算术里的求幂运算
经过两个技巧进行计算上的简化,
1.应用模算术的如下性质来计算模幂运算,以免先求幂再求模带来中间值过大的问题
[(a mod n) × (b mod n)] mod n = (a × b) mod n
2.由于RSA中所用指数很大,因此还应考虑幂运算的效率问题。如x16,若直接计算须要15次乘法,若是重复计算每一个中间结果的平方,获得x2,x4,x8,x16,那么只须要4次乘法。同理,计算x11 mod n,能够先计算 x mod n,x2 mod n,x4 mod n,x8 mod n,再计算[(x mod n) × (x2 mod n) × (x8 mod n)] mod n
更通常地,假定咱们要计算ab,其中a,b∈正整数。若将b表示成二进制数bkbk-1···b0,则更加方便提升幂运算的效率。
二、用公钥进行有效运算
为了加快RSA算法在使用公钥是的运算速度,一般会选择一个特定的e,大多数状况下选为65537(216+1),其它两个经常使用的选择是3和17。之因此选这些数,是由于这些数里都只有两个有效位(65537 = 1000 0000 0000 0001b, 3 = 11, 17 = 1 0001),因此在求幂运算时须要的乘法次数极小化了。
若是指数过小,如e = 3,RSA甚至会遭受一些简单的攻击,假设有三个不一样的RSA用户,他们都使用指数e = 3,可是他们的模数n各不相同,即n1,n2,n3。现有一用户A以加密方式给他们三个发送相同的消息M,则三个密文为:C1 = M3 mod n1,C2 = M3 mod n2,C3 = M3 mod n3。颇有可能n1,n2,n3是两两互素的,因此运用中国剩余定理能够计算出M3 mod (n1n2n3)。根据RSA规则,M应该比模数ni小,因此有M3 < n1n2n3,从而攻击者只要计算M3就能够了。解决办法是给每个待加密的消息分组M填充一个惟一的伪随机位串能够阻止这种攻击。
此外,因为选定了e,为了确保e和φ(n)互素,由于e = 65537 是素数,p,q是大素数,故所选p,q须要知足如下式子
[(p-1)×(q-1)] mod e ≠ 0
[(p-1) mod e × (q-1) mod e] mod e ≠ 0
(p-1) mod e ≠ 0 且 (q-1) mod e ≠ 0
三、用私钥进行有效运算
因为d不像e同样是选定的为简化计算的值,为了加快幂运算,能够运用中国剩余定理。先定义一些中间值:
Vp = Cd mod p Vq = Cd mod q
应用CRT的公式有:
Xp = q × (q-1 mod p) Xq = p × (p-1 mod q)
M = (VpXp + VqXq) mod n
进一步用费马定理简化Vp,Vq的计算,即若是p和a互素,则ap-1 ≡ 1 (mod p),则
Vp = Cd mod p = Ck(p-1)+d mod (p-1) mod p = Ck(p-1) mod p × Cd mod (p-1) mod p
= Cd mod (p-1) mod p
同理 Vq = Cd mod q = Cd mod (q-1) mod q
其中d mod (p-1),d mod (q-1),Xp,Xq(求乘法逆元素可用扩展Euclid算法计算)均可预先计算出来,和直接计算M = Cd mod n相比,上述的计算速度大约快4倍。
四、密钥产生
在应用公钥密码进行通讯以前,通讯各方都必须产生一对密钥,即
1.肯定两个素数p和q
2.选择e,并计算d
首先为避免穷举攻击,p和q必须是大素数,此外要选择有效的算法来产生这样的大素数。目前并无有效的方法产生任意大素数,所以一般的方法是随机挑选一个指望大小的奇数,而后测试它是不是素数,若不是则挑选下一个随机数直至检测到素数为止。这里用到的各类素性测试方法几乎都是几率测试方法,须要执行屡次才能尽量逼近100%。
由数论中的素数定理可知,在N附近平均每隔lnN个整数就有一个素数,这样在找到一个素数以前,平均要测试大约lnN个整数。因为每隔偶数会被当即拒绝,故实际只须要测试lnN/2个整数。
若先肯定e,则须要进一步筛选知足(p-1) mod e ≠ 0 (q-1) mod e ≠ 0 的p和q。
若后肯定e,则需选择知足gcd(φ(n) , e) = 1 的e
最后应用扩展Euclid算法计算 d ≡ e-1 (mod φ(n))
RSA的安全性
对RSA算法的攻击可能有以下4种方式:
穷举攻击:试图穷举全部可能的密钥
数学攻击:实质是试图分解两个素数的乘积
计时攻击:依赖于解密算法的运行时间
选择密文攻击:利用了RSA算法的性质
数学攻击
用数学攻击RSA的途径有如下三种:
一、分解n为两个素因子,从而计算出φ(n) = (p-1)(q-1),进而肯定d ≡ e-1 (mod φ(n))
二、直接肯定φ(n)而不去肯定p和q,这样也能计算出d ≡ e-1 (mod φ(n))
三、直接肯定d,而不肯定φ(n)
对RSA的密码分析的讨论大都集中在第一种攻击方式,即因子分解n。如今已知从e和n肯定d的算法至少和因子分解n同样费时,所以,咱们能够将因子分解的性能做为基准来评价RSA的安全性。随着计算能力的不断加强,目前密钥大小取1024到2048位是合适的。此外p和q最好还知足如下限制条件:
一、p和q的长度应仅相差几位,对1024位(309个十进制位)的密钥而言,p和q都应约在1075到10100之间。
二、(p-1)和(q-1)都应有一个大的素因子。
三、gcd(p-1,q-1)应该较小
另外已证实,若e<n且d<n1/4,则d很容易被肯定
计时攻击
攻击者能够经过记录计算机解密消息所用的时间来肯定私钥。因为模乘函数的执行时间只在几种情形中其执行时间比整个模幂运算的平均执行时间要长得多,但在大多数情形下其执行速度至关快,计时攻击从最左位bk开始,一位一位地执行,攻击者根据每次执行时间的长度来推算。
解决办法:
一、不变的幂运算时间:保证全部幂运算在返回结果前执行的时间都相同。这种方法虽然简单,但会下降算法的性能。
二、随机延时:经过在求幂算法中加入随机延时来迷惑攻击者
三、隐蔽:执行幂运算以前先将密文乘上一个随机数,使得攻击者不知道计算机正在处理的是密文的哪些位,以防止攻击者一位一位地进行分析吗,而这种分析正是计时攻击的本质所在。
RSA数据安全公司在它们产品中就使用了隐蔽方法,其具体实现以下
一、产生0只n-1之间的秘密的随机数r
二、计算C’ = Cre mod n
三、计算M’ = (C’)d mod n
四、计算M = M’r-1 mod n 其中r-1是r的模n的乘法逆元。根据red mod n = r mod n可证实结论是正确的,据RSA公司声称应用了该隐蔽方法,运算性能下降了2%-10%
选择密文攻击
基本的RSA算法易受选择密文攻击(CCA)。攻击者能够选择一个明文,运用目标对象的公钥加密,而后再经过某些手段得到目标对象用私钥对密文解密后的明文。看起来好像没什么用处,实则否则,攻击者其实是将需破解的密文作了一番数学包装后,再发给攻击目标,因为解密后的明文咋看起来不是重要机密,所以就较容易被截获或者盗取。
利用CCA攻击RSA利用了RSA以下的性质
E(PU , M1) × E(PU , M2) = E(PU , [M1 × M2])
进而用以下方式解密C = Me mod n
一、计算 X = (C × 2e) mod n = (Me mod n) × (2e mod n) = (2M)e mod n
二、将X做为选择明文提交,并收到Y = Xd mod n = (2M)ed mod n = 2M
为了防止这种简单攻击,实用的基于RSA的密码体制在加密以前都会对明文进行随机填充。不过简单的随机填充已被证实不足以提升指望的安全性,所以RSA公司推荐了一种称为最优非对称加密填充(OAEP)的程序对明文进行修改。
一、首先将加密参数P经过Hash函数处理并输出到总体数据块DB一侧,明文的值也总体复制到DB的另外一侧,DB剩余部分用0进行填充。
二、而后随机选择一个种子,使用一种叫作掩码生成函数MGF,输出的Hash值和DB异或产生maskedDB。
三、该maskedDB一样经过MGF函数,输出Hash值与种子进行异或产生MaskedSeed
四、最后MaskedSeed和maskedDB共同组成EM做为最终的填充结果。
加密公式 DB = H(P) || Padding || M
maskedDB = DB⊕MGF(Seed)
maskedSeed = Seed⊕MGF(maskedDB)
EM = maskedSeed || maskedDB
解密公式 Seed = maskedSeed⊕MGF(maskedDB)
DB = maskedDB⊕MGF(Seed)