关于RSA再进行一个系统性的复习和学习
原理(维基百科)
假设Alice想要通过不可靠的媒体接收Bob的私人消息。她可以用以下方式来产生一个公钥和一个私钥:
- 随机选择两个大的素数p和q, p ≠ q,计算N = pq。
- 根据欧拉函数,求得r = φ(N) = φ(p)φ(q) = (p − 1)(q − 1)
- 选择一个小于r的整数e,使e与r互质。并求得关于e的模逆元,命名为d (求ed ≡ 1 (mod r))。(模逆元存在,当且仅当e与r互质)
- 将p和q的记录销毁。
(N, e)是公钥,(N, d)是私钥。Alice将她的公钥(N, e)传给Bob,而将她的私钥(N, d)藏起来。
加密消息
假设Bob想给Alice送消息m,他知道Alice产生的N和e。
将明文m按照比特进行分组,确保每一位的m都小于n,然后对每一个分组m进行加密运算
c ≡ me (mod n)
解密信息
对分组密文进行解密运算 m ≡ cd (mod n) 正确性证明
- 第一种情况
ed ≡ 1 (mod φ(N))
ed = 1 + kφ(N)
med ≡ med − 1 ⋅ m ≡ mkφ(N) ⋅ m ≡ m (mod N)
第二种情况
若gcd(m, N) ≠ 1,则m为p或q的整数,设m = hp,有
其中 mk(p − 1)(q − 1) = (mk(p − 1))q − 1 = 1 + xq
共模攻击
我们在对同一个明文中加密时采用的是共同的N,采用不同的公钥e进行加密得到不同的明文 c1 ≡ me1 (mod n)
c2 ≡ me2 (mod n)
第一种情况gcd(e1, e2) = 1
通过欧几里得扩展算法我们能得到x, y满足e1x + e2y = 1 ∴ c1x × c2y ≡ me1x + e2y ≡ m (mod n)
1 | m = pow(c1,x,n) * pow(c2,y,n) % n |
第一种情况gcd(e1, e2) ≠ 1
同样通过欧几里德扩展算法我们能够得到x, y满足e1x + e2y = s 如果s的值不大,那么就可以直接开方 如果s的很大,那就再当作一次RSA进行计算
1 | from Crypto.Util.number import * |
测一下就知道e1和e2不互素 照着解题抄exp即可
1 | n = 27855350163093443890983002241607629119744539643165776358993469078731521668677421483556132628708836721737685936980427467856642738196111748018522018598646125626995613169001111504706363742194664774823604738939411512861441742683157275818500991834651769368178320088982759626122029956515159435424882855075032400667120376075618896752694718491438251810609878021717559466498493103257912108879328270813061231904227056671621363669388496383136964549879459562004569059185078204867346250733489663015417879915436157806942021693920206071715538430633494012923651469196048546309592946901609803631751035364478773126967010589504275776307 |
低加密指数攻击
原理:
加密指数e很小一般是3
第一种情况:me < n则c ≡ me (mod n) → c = me这种情况下对c开e次方就可以得到m的值
第二种情况:me > n(略大一点点),则me = k * n + c这种情况需要爆破k
1 | def exp(n, e, c): |
广播攻击
原理 加密指数e非常小 一份明文使用不同的模数n,相同的加密指数e进行多次加密 可以拿到每一份加密后的密文和对应的模数n、加密指数e
第一种解决
1 | m = xxxxxxxx |
每两个n求一次公约数,看看是否有不为1的一组n,如果有的话,p就是这个公约数
1 | from Crypto.Util.number import * |
第二种情况
中国剩余定理,会有很多组同余式子
然后构造成一个式子
C ≡ me (mod N)N = lcm(n1, n2, n3)(求最小公倍数)
实际上就是辗转相除法的思想
1 | import libnum |
1 | from Crypto.Util.number import* |
欧拉函数的计算
- n = 1, 则ϕ(n) = 1
- n是素数, 则ϕ(n) = n − 1
- n = pr(p为素数, r为大于等于1的整数), 则ϕ(n) = pr − 1(p − 1)
, 则
共享素数
两个素数有共同的公因子,gcd求公约数就好了
1 | GCD(n1,n2) |
dp泄露
第一种情况
∴ dp ≡ d (mod p − 1)
左右同乘e得 dp × e ≡ d × e (mod p − 1) 即 d × e = k1(p − 1) + dp × e
∴ d × e ≡ 1 (mod ϕ(n))
∴ d × e = k2(p − 1)(q − 1) + 1
∴ k1(p − 1) + dp × e = k2(p − 1)(q − 1) + 1
化简得 dp × e = (p − 1)[k2(q − 1) − k1] + 1
∴ dp < p − 1
∴ 0 < k2(q − 1) − k1
遍历i ∈ (0, e)的所有值, 如果dp × e − 1能够整除i, 我们就可以求得p − 1
1 | e = 65537 |
1 | from Crypto.Util.number import * |
第二种情况
e很大的dp泄露
欧拉降幂
ab (mod c) = ab (mod φ(c)) + φ(c) (mod c)
adpe − a ≡ 0 (mod p)
所以有(adpe − a)|p
1 | from Crypto.Util.number import * |
第三种情况
dp高位泄露
1 | for k in range(): |
如果e很大,那么就需要二元copper攻击
1 | #sage |
dp,dq泄露
如果题目给出 p, q, dp, dq, 那么直接在模 p 和模 q 下求解即可. 如果模不够大, 再用中国剩余定理即可
e和phi不互素
gcd (e, φ(n)) ≠ 1时,
e 与
计算
则 cd′ ≡ mgcd (e, φ(n)) (mod n)。 此时我们就要对t = gcd (e, φ(n))的值进行一个判断
第一种情况
这个值过小的时候,那么我们可以直接对明文开t次方即可(mt < n) 第二种情况 如果这个值比较大,那么我们此时要用有限域开方的方式来解决这个问题
有限域开根 分别对密文在模p和模q下进行开方,然后用中国剩余定理求线性同余式
AMM算法(e=65537)
这种情况一般是在e等于65537时候需要用的
先贴个板子,原理后续再补充
1 | def AMM(o, r, q): |
维娜攻击
方法采用的是连分数的思想,是将式子构造成形如
原理
对于有理数α,若整数c, d满足
1 | def continuedFra(x, y): |
在sage中我们有
1 | #sage |
扩展维娜攻击
先贴一下脚本,后续原理明白了再写
1 | def wienerAttack2(N, e1, e2): |
1 | e1 = 5077048237811969427473111225370876122528967447056551899123613461792688002896788394304192917610564149766252232281576990293485239684145310876930997918960070816968829150376875953405420809586267153171717496198336861089523701832098322284501931142889817575816761705044951705530849327928849848158643030693363143757063220584714925893965587967042137557807261154117916358519477964645293471975063362050690306353627492980861008439765365837622657977958069853288056307253167509883258122949882277021665317807253308906355670472172346171177267688064959397186926103987259551586627965406979118193485527520976748490728460167949055289539 |
Rabin
密钥生成
选取两个大素数p, q,并且满足 p ≡ 3 (mod 4), q ≡ 3 (mod 4) 即p, q都是4k + 3形式的素数。
加密 c ≡ m2 (mod n)
解密
开根号得
然后我们构造两个同余式
1 | inv_p = gmpy2.invert(p, q) |
或者构造两个式子有限域开根然后再中国剩余定理也可以解决
高次rabin
多次调用求解rabin解密
1 | def rabin(c): |