RSA 进阶 中
数论
二项式定理
费马小定理
基础练习
[金盾信安杯2023]babyrsa
题目:
#! /usr/bin/env python
from libnum import *
from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes
from secret import p1, q1, p2, q2, e, d, flag, N
from random import randint
def round1(m):
e = 10
N = open('round1.txt', 'r').read()
N = eval(N)
c = []
for n in N:
c.append(pow(m, e, n))
FILE = open('round1.txt', 'a+')
FILE.write('#' * 100 + '\n')
FILE.write(str(c)+'\n')
FILE.close()
return c, N
def round2(m, n):
e1 = 65537
e2 = 84731
c1 = pow(m, e1, n)
c2 = pow(m, e2, n)
c = [c1, c2]
open('round2.txt', 'w').write(str(c) + '\n')
def round3(m, n):
assert p1 * q1 == n
rand = randint(1, n - 1)
test_enc = pow(rand, e, n)
assert pow(test_enc, d, n) == rand
key = e * d
new_e = 65537
c = pow(m, new_e, n)
f = open('round3.txt', 'w')
f.write(str(key) + '\n')
f.write(str(c) + '\n')
f.close()
def round4(m, n):
p, q = p2, q2
e = 65537
c = pow(m, e, n)
f = open('round4.txt', 'w')
f.write(str(c) + '\n')
f.write(str(pow(p + q, 2019, n)) + '\n')
f.write(str(pow(p + 2019, q, n)) + '\n')
f.close()
n1, n2, n3, n4 = N
print 'n1 =', n1
# n1 = 11177704342647691670070109831808378482821379302566268464943167206480241387551242120970561253786504223799891058773501288553907233379501460184102021531940602831324488818584481982166938165369946708273616214479706319082928159418133324715707808391767322038274030554057692976849636562898606740933056248870247255267420120488136713203337167713048960270135675134979523980774070773134748108563438318851158022122836766753248988837577239024669497444315476147384635493684855045085484618938995056978709390818568630471778630936743950045419782341697342117812959693992029294299582179507853091511833090186389981102903683178276414062363
round1(n2)
round2(n3, n2)
round3(n4, n3)
round4(bytes_to_long(flag), n4)
思路:
低加密指数广播攻击
+共模攻击
+已知n和e*d
+数论推导
解:
import gmpy2
import sympy
from functools import reduce
from Crypto.Util.number import *
# .txt删除了[]、L和部分换行
path1 = r'D:\Downloads\Crypto-babyrsa\round1 - n.txt'
path2 = r'D:\Downloads\Crypto-babyrsa\round1 - c.txt'
path3 = r'D:\Downloads\Crypto-babyrsa\round2 - n.txt'
path4 = r'D:\Downloads\Crypto-babyrsa\round3.txt'
path5 = r'D:\Downloads\Crypto-babyrsa\round4.txt'
# 中国剩余定理
def chinese_remainder(modulus,remainders):
sum = 0
prod = reduce(lambda a,b:a*b,modulus)
for m_i,r_i in zip(modulus,remainders):
p = prod // m_i
sum += r_i * (inverse(p,m_i)*p)
return sum % prod
# 低加密指数广播攻击
def de_round1():
e = 10
n = []
c = []
with open(path1, 'r') as f:
data = f.read()
n = data.split("L, ")
n = [item.rstrip('L') for item in n]
n = list(map(lambda x: int(x), n))
with open(path2, 'r') as f:
data = f.read()
c = data.split("L, ")
c = [item.rstrip('L') for item in c]
c = list(map(lambda x: int(x), c))
pow_m_e = chinese_remainder(n,c)
m = gmpy2.iroot(pow_m_e, e)[0]
# print(m)
return m
# 共模攻击
def de_round2(n):
e1 = 65537
e2 = 84731
c = []
with open(path3, 'r') as f:
data = f.read()
c = data.split("L, ")
c = [item.rstrip('L') for item in c]
c = list(map(lambda x: int(x), c))
r , s1 , s2 = gmpy2.gcdext(e1,e2)
m = (gmpy2.powmod(c[0],s1,n)*gmpy2.powmod(c[1],s2,n)) % n
# print(m)
return m
# 已知n和e*d
def de_round3(n):
e = 65537
with open(path4, 'r') as f:
data = f.readlines()
data = [line.strip("\n") for line in data]
data = list(map(lambda x: int(x), data))
ed = data[0]
c = data[1]
p = 0
q = 2
k = ed - 1
while q:
k=k//2
p=gmpy2.gcd(gmpy2.powmod(q,k,n)-1,n)%n
if p>1:
q = n//p
break
else:
q=int(sympy.nextprime(q))
z = (p-1)*(q-1)
d = gmpy2.invert(e,z)
m = gmpy2.powmod(c,d,n)
# print(m)
return m
# 数论推导
def de_round4(n):
e = 65537
with open(path5, 'r') as f:
data = f.readlines()
data = [line.strip("\n") for line in data]
data = list(map(lambda x: int(x), data))
c = data[0]
hint1 = data[1]
hint2 = data[2]
p = gmpy2.gcd(hint1 - pow(hint2-2019, 2019, n), n)
# p = gmpy2.gcd(hint2 - pow(2019, n, n), n)
q = n // p
z = (p-1)*(q-1)
d = inverse(e, z)
m = gmpy2.powmod(c, d, n)
return m
if __name__ == "__main__":
n2 = de_round1()
n3 = de_round2(n2)
n4 = de_round3(n3)
m = de_round4(n4)
print(bytes.fromhex(hex(m)[2:]))
flag{y0U_R_th3_ch0sen_on3_1n_the_field_of_Crypt0gr4phy}
BUUCTF-[De1CTF2019]babyrsa
思路:
低加密指数广播攻击
+低加密指数分解攻击
+大N分解
+数论推导
。关键在于数论推导
。
在第四部分的数论推导中,我们已知\(c1,c2,e1,e2,p,q1,q2\)
根据条件,先进行常规解码,发现两个e都没有逆元,说明 e
和 z
(\(z_1 = (p-1)*(q_1-1)\)) 之间有公因数14。
拿\(e_1\)举例:
令\(e = \frac{1}{14} * e_1\) , \(d = 14 * d_1\),则有\(e * d = 1\;mod\;z_1\),从而求出d。
因为\(m = c_1^{d_1}\;mod\;n_1\), 所以有\(m^{14} = c_1^{14*d_1}\;mod\;n_1 = c_1^d\;mod\;n_1\),这样我们就求出了\(m^{14}\)。同理通过\(e_2\)求得\(m^{14}\)。
令通过\(e_1\)解出的\(m^{14}\)为cc1
,通过\(e_2\)解出的\(m^{14}\)为cc2
,则有
这样也不能进行常规解密,因为gcd((p-1)*(q1-1) , 14) = 14。看看是哪个(p或q1)导致这样的情况产生的,结果发现gcd(p-1, 14) = 14, gcd(q1-1, 14) = 2。
为了尽量不要使得gcd(e,φ(n)) = e(因为这样会非常难求),所以我们可以选择q1作为模数,即将上面的式子拆分,得到如下结果(模数p * q2的式子同理):
这里我们舍弃掉模数为p的式子,剩下
因为 e = 14 分别和\(q_1-1\)、\(q_2-1\)之间的公因数为2,令\(m_2 = M\),这样新的指数 e = 7 就不会与\(q_1-1\)、\(q_2-1\)之间有公因数了,则
再利用中国剩余定理求出cc3,使得\(M^7 = cc3\;mod\;q_1*q_2\)
这样的话,e = 7
, n = q1*q2
,c = cc3
,很容易就求出M,再开根就可以求出明文m。
解:
import gmpy2
from functools import reduce
from Crypto.Util.number import *
# 中国剩余理论
def chinese_remainder(modulus,remainders):
sum = 0
prod = reduce(lambda a,b:a*b,modulus)
for m_i,r_i in zip(modulus,remainders):
p = prod // m_i
sum += r_i * (inverse(p,m_i)*p)
return sum % prod
# 中国剩余理论
def broadcast_attack(data):
def extended_gcd(a,b):
x,y = 0,1
lastx,lasty = 1,0
while b:
a,(q,b) = b,divmod(a,b)
x,lastx = lastx-q*x,x
y,lasty = lasty-q*y,y
return (lastx,lasty,a)
def chinese_remaindor_theorem(items):
N = 1
for a,n in items:
N *= n
result = 0
for a,n in items:
m = N//n
r,s,d = extended_gcd(n,m)
if d != 1:
N = N//n
continue
result += a*s*m
return result%N
x= chinese_remaindor_theorem(data)
return x
# 求p-低加密指数广播攻击
def part1():
n = [20129615352491765499340112943188317180548761597861300847305827141510465619670536844634558246439230371658836928103063432870245707180355907194284861510906071265352409579441048101084995923962148527097370705452070577098780246282820065573711015664291991372085157016901209114191068574208680397710042842835940428451949500607613634682684113208766694028789275748528254287705759528498986306494267817198340658241873024800336013946294891687591013414935237821291805123285905335762719823771647853378892868896078424572232934360940672962436849523915563328779942134504499568866135266628078485232098208237036724121481835035731201383423, 31221650155627849964466413749414700613823841060149524451234901677160009099014018926581094879840097248543411980533066831976617023676225625067854003317018794041723612556008471579060428898117790587991055681380408263382761841625714415879087478072771968160384909919958010983669368360788505288855946124159513118847747998656422521414980295212646675850690937883764000571667574381419144372824211798018586804674824564606122592483286575800685232128273820087791811663878057827386379787882962763290066072231248814920468264741654086011072638211075445447843691049847262485759393290853117072868406861840793895816215956869523289231421, 29944537515397953361520922774124192605524711306753835303703478890414163510777460559798334313021216389356251874917792007638299225821018849648520673813786772452822809546571129816310207232883239771324122884804993418958309460009406342872173189008449237959577469114158991202433476710581356243815713762802478454390273808377430685157110095496727966308001254107517967559384019734279861840997239176254236069001453544559786063915970071130087811123912044312219535513880663913831358790376650439083660611831156205113873793106880255882114422025746986403355066996567909581710647746463994280444700922867397754748628425967488232530303, 25703437855600135215185778453583925446912731661604054184163883272265503323016295700357253105301146726667897497435532579974951478354570415554221401778536104737296154316056314039449116386494323668483749833147800557403368489542273169489080222009368903993658498263905567516798684211462607069796613434661148186901892016282065916190920443378756167250809872483501712225782004396969996983057423942607174314132598421269169722518224478248836881076484639837343079324636997145199835034833367743079935361276149990997875905313642775214486046381368619638551892292787783137622261433528915269333426768947358552919740901860982679180791]
c = [19131432661217908470262338421299691998526157790583544156741981238822158563988520225986915234570037383888112724408392918113942721994125505014727545946133307329781747600302829588248042922635714391033431930411180545085316438084317927348705241927570432757892985091396044950085462429575440060652967253845041398399648442340042970814415571904057667028157512971079384601724816308078631844480110201787343583073815186771790477712040051157180318804422120472007636722063989315320863580631330647116993819777750684150950416298085261478841177681677867236865666207391847046483954029213495373613490690687473081930148461830425717614569, 15341898433226638235160072029875733826956799982958107910250055958334922460202554924743144122170018355117452459472017133614642242411479849369061482860570279863692425621526056862808425135267608544855833358314071200687340442512856575278712986641573012456729402660597339609443771145347181268285050728925993518704899005416187250003304581230701444705157412790787027926810710998646191467130550713600765898234392350153965811595060656753711278308005193370936296124790772689433773414703645703910742193898471800081321469055211709339846392500706523670145259024267858368216902176489814789679472227343363035428541915118378163012031, 18715065071648040017967211297231106538139985087685358555650567057715550586464814763683688299037897182845007578571401359061213777645114414642903077003568155508465819628553747173244235936586812445440095450755154357646737087071605811984163416590278352605433362327949048243722556262979909488202442530307505819371594747936223835233586945423522256938701002370646382097846105014981763307729234675737702252155130837154876831885888669150418885088089324534892506199724486783446267336789872782137895552509353583305880144947714110009893134162185382309992604435664777436197587312317224862723813510974493087450281755452428746194446, 2282284561224858293138480447463319262474918847630148770112472703128549032592187797289965592615199709857879008271766433462032328498580340968871260189669707518557157836592424973257334362931639831072584824103123486522582531666152363874396482744561758133655406410364442174983227005501860927820871260711861008830120617056883514525798709601744088135999465598338635794275123149165498933580159945032363880613524921913023341209439657145962332213468573402863796920571812418200814817086234262280338221161622789516829363805084715652121739036183264026120868756523770196284142271849879003202190966150390061195469351716819539183797]
e = 4
pow_m_e = chinese_remainder(n,c)
m = gmpy2.iroot(pow_m_e, e)[0]
return m
# 求e1,e2-低加密指数分解攻击
def part2():
ee1 = 42
ee2 = 3
ce1 = 45722651786340123946960815003059322528810481841378247280642868553607692149509126962872583037142461398806689489141741494974836882341505234255325683219092163052843461632338442529011502378931140356111756932712822516814023166068902569458299933391973504078898958921809723346229893913662577294963528318424676803942288386430172430880307619748186863890050113934573820505570928109017842647598266634344447182347849367714564686341871007505886728393751147033556889217604647355628557502208364412269944908011305064122941446516990168924709684092200183860653173856272384
ce2 = 13908468332333567158469136439932325992349696889129103935400760239319454409539725389747059213835238373047899198211128689374049729578146875309231962936554403287882999967840346216695208424582739777034261079550395918048421086843927009452479936045850799096750074359160775182238980989229190157551197830879877097703347301072427149474991803868325769967332356950863518504965486565464059770451458557744949735282131727956056279292800694203866167270268988437389945703117070604488999247750139568614939965885211276821987586882908159585863514561191905040244967655444219603287214405014887994238259270716355378069726760953320025828158
tmp = 864078778078609835167779565982540757684070450697854309005171742813414963447462554999012718960925081621571487444725528982424037419052194840720949809891134854871222612682162490991065015935449289960707882463387
n = 15911581555796798614711625288508309704791837516232122410440958830726078821069050404012820896260071751380436992710638364294658173571101596931605797509712839622479368850251206419748090059752427303611760004621378226431226983665746837779056271530181865648115862947527212787824629516204832313026456390047768174765687040950636530480549014401279054346098030395100387004111574278813749630986724706263655166289586230453975953773791945408589484679371854113457758157492241225180907090235116325034822993748409011554673180494306003272836905082473475046277554085737627846557240367696214081276345071055578169299060706794192776825039
k = 0
while 1:
res = gmpy2.iroot(k*n+ce1,ee1)
if(res[1] == True):
e1 = res[0]
break
k += 1
k = 0
while 1:
res = gmpy2.iroot(k*n+ce2,ee2)
if(res[1] == True):
e2 = res[0] - tmp
break
k += 1
return e1,e2
# 求q1p,q1q-大N分解
def part3():
q1p = 127587319253436643569312142058559706815497211661083866592534217079310497260365307426095661281103710042392775453866174657404985539066741684196020137840472950102380232067786400322600902938984916355631714439668326671310160916766472897536055371474076089779472372913037040153356437528808922911484049460342088834871
q1q = 127587319253436643569312142058559706815497211661083866592534217079310497260365307426095661281103710042392775453866174657404985539066741684196020137840472950102380232067786400322600902938984916355631714439668326671310160916766472897536055371474076089779472372913037040153356437528808922911484049460342088835693
return q1p, q1q
# 数论推导
def part4(e1,e2,p,q1p):
res = 0
c1 = 262739975753930281690942784321252339035906196846340713237510382364557685379543498765074448825799342194332681181129770046075018122033421983227887719610112028230603166527303021036386350781414447347150383783816869784006598225583375458609586450854602862569022571672049158809874763812834044257419199631217527367046624888837755311215081173386523806086783266198390289097231168172692326653657393522561741947951887577156666663584249108899327053951891486355179939770150550995812478327735917006194574412518819299303783243886962455399783601229227718787081785391010424030509937403600351414176138124705168002288620664809270046124
c2 = 7395591129228876649030819616685821899204832684995757724924450812977470787822266387122334722132760470911599176362617225218345404468270014548817267727669872896838106451520392806497466576907063295603746660003188440170919490157250829308173310715318925771643105064882620746171266499859049038016902162599261409050907140823352990750298239508355767238575709803167676810456559665476121149766947851911064706646506705397091626648713684511780456955453552020460909638016134124590438425738826828694773960514221910109473941451471431637903182205738738109429736425025621308300895473186381826756650667842656050416299166317372707709596
q1 = q1p
q2 = 114401188227479584680884046151299704656920536168767132916589182357583461053336386996123783294932566567773695426689447410311969456458574731187512974868297092638677515283584994416382872450167046416573472658841627690987228528798356894803559278308702635288537653192098514966089168123710854679638671424978221959513
z1 = (p-1)*(q1-1)
z2 = (p-1)*(q2-1)
xx1 = gmpy2.gcd(e1,z1)
xx2 = gmpy2.gcd(e2,z2)
#均为14
d1 = gmpy2.invert(e1//xx1,z1)
d2 = gmpy2.invert(e2//xx2,z2)
a1 = gmpy2.powmod(c1, d1, p*q1)
a2 = gmpy2.powmod(c2, d2, p*q2)
data = [(a1,q1),(a2,q2)]
res = broadcast_attack(data)
d = gmpy2.invert(7, (q1-1)*(q2-1))
mm = gmpy2.powmod(res, d, q1*q2)
flag = gmpy2.iroot(mm,2)[0]
print(bytes.fromhex(hex(flag)[2:]))
if __name__ == "__main__":
p = part1()
e1, e2 = part2()
q1p, q1q = part3()
part4(e1,e2,p,q1p)
flag{9b10a98b-71bb-4bdf-a6ff-f319943de21f}
BUUCTF-[NPUCTF2020]认清形势,建立信心
题目:
from Crypto.Util.number import *
from gmpy2 import *
from secret import flag
p = getPrime(25)
e = # Hidden
q = getPrime(25)
n = p * q
m = bytes_to_long(flag.strip(b"npuctf{").strip(b"}"))
c = pow(m, e, n)
print(c)
print(pow(2, e, n))
print(pow(4, e, n))
print(pow(8, e, n))
'''
169169912654178
128509160179202
518818742414340
358553002064450
'''
思路:
经典求n
的方法:构造两个含 n 的乘积式,通过gcd来求解
所以\(n = gcd(c_1^2-c_2,c_1^3-c_3)\)
再通过yafu
解n得到
去掉2 即为p,q
已知明文反求加密指数e,直接用sympy自带的discrete_log函数解决即可
解:
from gmpy2 import *
from sympy import *
c = 169169912654178
c1 = 128509160179202
c2 = 518818742414340
c3 = 358553002064450
print("n = {}".format(gmpy2.gcd(c1*c1-c2,c1*c1*c1-c3)))
p = 18195301
q = 28977097
n = p*q
e = discrete_log(n,c1,2)
z = (p-1)*(q-1)
d = gmpy2.invert(e,z)
m = gmpy2.powmod(c,d,n)
print(bytes.fromhex(hex(m)[2:]))
flag{345y!}
BUUCTF-[NPUCTF2020]共 模 攻 击
题目:
hint.py
from gmpy2 import *
from Crypto.Util.number import *
from secret import hint
m = bytes_to_long(hint)
p = getPrime(256)
c = pow(m, 256, p)
print(p)
p, q = getPrime(256), getPrime(256)
n = p * q
e1, e2 = getPrime(32), getPrime(32)
c1, c2 = pow(c, e1, n), pow(c, e2, n)
print(n)
print(e1, c1)
print(e2, c2)
'''
107316975771284342108362954945096489708900302633734520943905283655283318535709
6807492006219935335233722232024809784434293293172317282814978688931711423939629682224374870233587969960713638310068784415474535033780772766171320461281579
2303413961 1754421169036191391717309256938035960912941109206872374826444526733030696056821731708193270151759843780894750696642659795452787547355043345348714129217723
2622163991 1613454015951555289711148366977297613624544025937559371784736059448454437652633847111272619248126613500028992813732842041018588707201458398726700828844249
'''
task.py
from gmpy2 import *
from Crypto.Util.number import *
from secret import flag
flag = flag.strip(b"npuctf{").strip(b"}")
m = bytes_to_long(flag)
p, q = getPrime(512), getPrime(512)
n = p * q
e1, e2 = p, q
c1, c2 = pow(m, e1, n), pow(m, e2, n)
print(n)
print(c1)
print(c2)
'''
128205304743751985889679351195836799434324346996129753896234917982647254577214018524580290192396070591032007818847697193260130051396080104704981594190602854241936777324431673564677900773992273463534717009587530152480725448774018550562603894883079711995434332008363470321069097619786793617099517770260029108149
96860654235275202217368130195089839608037558388884522737500611121271571335123981588807994043800468529002147570655597610639680977780779494880330669466389788497046710319213376228391138021976388925171307760030058456934898771589435836261317283743951614505136840364638706914424433566782044926111639955612412134198
9566853166416448316408476072940703716510748416699965603380497338943730666656667456274146023583837768495637484138572090891246105018219222267465595710692705776272469703739932909158740030049375350999465338363044226512016686534246611049299981674236577960786526527933966681954486377462298197949323271904405241585
'''
思路:
解:
import gmpy2
import sympy
def de_hint():
n = 6807492006219935335233722232024809784434293293172317282814978688931711423939629682224374870233587969960713638310068784415474535033780772766171320461281579
e1 = 2303413961
e2 = 2622163991
c1 = 1754421169036191391717309256938035960912941109206872374826444526733030696056821731708193270151759843780894750696642659795452787547355043345348714129217723
c2 = 1613454015951555289711148366977297613624544025937559371784736059448454437652633847111272619248126613500028992813732842041018588707201458398726700828844249
e = 256
p = 107316975771284342108362954945096489708900302633734520943905283655283318535709
r , s1 , s2 = gmpy2.gcdext(e1,e2)
c = (gmpy2.powmod(c1,s1,n)*gmpy2.powmod(c2,s2,n)) % n
m = sympy.nthroot_mod(c, e, p, all_roots=True)
print(bytes.fromhex(hex(m[0])[2:]))
# sagemath
# def de_task():
# n = 128205304743751985889679351195836799434324346996129753896234917982647254577214018524580290192396070591032007818847697193260130051396080104704981594190602854241936777324431673564677900773992273463534717009587530152480725448774018550562603894883079711995434332008363470321069097619786793617099517770260029108149
# c1 = 96860654235275202217368130195089839608037558388884522737500611121271571335123981588807994043800468529002147570655597610639680977780779494880330669466389788497046710319213376228391138021976388925171307760030058456934898771589435836261317283743951614505136840364638706914424433566782044926111639955612412134198
# c2 = 9566853166416448316408476072940703716510748416699965603380497338943730666656667456274146023583837768495637484138572090891246105018219222267465595710692705776272469703739932909158740030049375350999465338363044226512016686534246611049299981674236577960786526527933966681954486377462298197949323271904405241585
# PR.<m> = PolynomialRing(Zmod(n))
# f = m^2-(c1+c2)*m+c1*c2
# x0 = f.small_roots(X=2^400)
# print(x0)
if __name__ == "__main__":
de_hint()
m = 4242839043019782000788118887372132807371568279472499477998758466224002905442227156537788110520335652385855
print(bytes.fromhex(hex(m)[2:]))
flag{verrrrrrry_345yyyyyyy_rsaaaaaaa_righttttttt?}
BUUCTF-[羊城杯 2020]RRRRRRRSA
BUUCTF-[GKCTF 2021]RRRRsa
BUUCTF-[watevrCTF 2019]Swedish RSA
BUUCTF-[羊城杯 2020]Power
参考链接:
https://blog.csdn.net/XiongSiqi_blog/article/details/130175464
https://blog.csdn.net/qq_52193383/article/details/120092207
https://www.cnblogs.com/U-L-G-A-N-O-Y/articles/17744675.html
https://www.cnblogs.com/vict0r/p/13292511.html