CTF-Crypto-RSA共模攻击和模不互素攻击

RSA共模攻击

利用场景

俩次加密使用了相同的N,有不同的e和c。即已知条件:e1,e2,c1,c2,n;

根据

gcd(e1, e2) = 1
m = c1^d1 mod n
m = c2^d2 mod n

求m。

推导过程

先引入 欧几里德扩展算法 :

​ 扩展欧几里得算法用于求解两个整数的最大公约数(GCD)以及相应的贝祖等式(Bézout’s identity)。

​ 对于俩个整数e1和e2,如果它们的最大公约数为1,即gcd(e1, e2) = 1,那么存在整数s1和s2,使得

e1*s1 + e2*s2 = 1

这个等式表达了 e1 和 e2 的线性组合等于 1,其中 s1 和 s2 是整数。

所以根据欧几里德扩展算法,已知e1*s1 + e2*s2 = 1

因为

c1 = m^e1 mod n
c2 = m^e2 mod n 

所以

(c1^s1*c2^s2) mod n = ((m^e1 mod n)^s1*(m^e2 mod n)^s2) mod n

(c1^s1*c2^s2) mod n = (m^(e1^s1 + e2^s2)) mod n

所以

(c1^s1*c2^s2) mod n = (m^(1)) mod n

c1^s1*c2^s2= m

可以得证 m

注意的点:

因为 e1*s1 + e2*s2 = 1 这里可知 s1和s2中有一个为负数,在计算时需要判断哪一个为负数并进行模反转。

利用公式:

gcd, s, t = gmpy2.gcdext(e1, e2)

这里使用了 gmpy2 库中的 gcdext 函数来计算两个整数 e1e2 的最大公约数以及相应的 Bézout 系数。贝祖系数就是 s1和 s2;

例题分析

[SWPUCTF 2021 新生赛]crypto2

from gmpy2 import *
from Crypto.Util.number import *

flag  = '***************'

p = getPrime(512)
q = getPrime(512)
m1 = bytes_to_long(bytes(flag.encode()))

n = p*q
e1 = getPrime(32)
e2 = getPrime(32)
print()

flag1 = pow(m1,e1,n)
flag2 = pow(m1,e2,n)
print('flag1= '+str(flag1))
print('flag2= '+str(flag2))
print('e1= ' +str(e1))
print('e2= '+str(e2))
print('n= '+str(n))


#flag1= 100156221476910922393504870369139942732039899485715044553913743347065883159136513788649486841774544271396690778274591792200052614669235485675534653358596366535073802301361391007325520975043321423979924560272762579823233787671688669418622502663507796640233829689484044539829008058686075845762979657345727814280
#flag2= 86203582128388484129915298832227259690596162850520078142152482846864345432564143608324463705492416009896246993950991615005717737886323630334871790740288140033046061512799892371429864110237909925611745163785768204802056985016447086450491884472899152778839120484475953828199840871689380584162839244393022471075
#e1= 3247473589
#e2= 3698409173
#n= 103606706829811720151309965777670519601112877713318435398103278099344725459597221064867089950867125892545997503531556048610968847926307322033117328614701432100084574953706259773711412853364463950703468142791390129671097834871371125741564434710151190962389213898270025272913761067078391308880995594218009110313

已知条件c1,c2,e1,e2,n,且e1和e2互素。

EXP:

from Crypto.Util.number import long_to_bytes
from gmpy2 import gmpy2, invert

c1 = 100156221476910922393504870369139942732039899485715044553913743347065883159136513788649486841774544271396690778274591792200052614669235485675534653358596366535073802301361391007325520975043321423979924560272762579823233787671688669418622502663507796640233829689484044539829008058686075845762979657345727814280
c2 = 86203582128388484129915298832227259690596162850520078142152482846864345432564143608324463705492416009896246993950991615005717737886323630334871790740288140033046061512799892371429864110237909925611745163785768204802056985016447086450491884472899152778839120484475953828199840871689380584162839244393022471075
e1 = 3247473589
e2 = 3698409173
n = 103606706829811720151309965777670519601112877713318435398103278099344725459597221064867089950867125892545997503531556048610968847926307322033117328614701432100084574953706259773711412853364463950703468142791390129671097834871371125741564434710151190962389213898270025272913761067078391308880995594218009110313
gcd, s, t = gmpy2.gcdext(e1, e2)
if s < 0:
    s = -s
    c1 = invert(c1, n)
elif t < 0:
    t = -t
    c2 = invert(c2, n)
m = pow(c1, s, n) * pow(c2, t, n) % n
print(long_to_bytes(m))
参考文章:https://1ablades.github.io/2017/08/09/RSA%E5%85%B1%E6%A8%A1%E6%94%BB%E5%87%BB/
https://ctf-wiki.org/crypto/asymmetric/rsa/rsa_module_attack/#_7	

RSA共享素数

攻击原理

当存在两个公钥的 N 不互素时,我们显然可以直接对这两个数求最大公因数,然后直接获得 p,q,进而获得相应的私钥。

例题分析

[羊城杯 2021]Bigrsa

题目

from Crypto.Util.number import *
from flag import *

n1 = 103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061
n2 = 115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073
e = 65537
m = bytes_to_long(flag)
c = pow(m, e, n1)
c = pow(c, e, n2)

print("c = %d" % c)

# output
# c = 60406168302768860804211220055708551816238816061772464557956985699400782163597251861675967909246187833328847989530950308053492202064477410641014045601986036822451416365957817685047102703301347664879870026582087365822433436251615243854347490600004857861059245403674349457345319269266645006969222744554974358264
    

n1 和 n2 都不能直接分解,且n1和n2互质。

EXP:

from Crypto.Util.number import *

n1 = 103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061
n2 = 115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073
e = 65537
c = 60406168302768860804211220055708551816238816061772464557956985699400782163597251861675967909246187833328847989530950308053492202064477410641014045601986036822451416365957817685047102703301347664879870026582087365822433436251615243854347490600004857861059245403674349457345319269266645006969222744554974358264

q = GCD(n1,n2)
p1 = n1 // q
p2 = n2 // q

d1 = inverse(e, (q-1)*(p1-1))
d2 = inverse(e, (q-1)*(p2-1))

print(long_to_bytes(pow(pow(c, d2, n2), d1, n1)))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sciurdae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值