宁波市第八届网络安全大赛 -- Crypto -- WriteUp
宁波市第八届网络安全大赛 -- Crypto -- WriteUp
Three-prime RSA
task
import gmpy2
from Crypto.Util.number import *
from secret import flag
p = getPrime(512)
q = getPrime(512)
r = getPrime(512)
n = p * q * r
random_num = getPrime(28)
D = ((p + q + r) * random_num) % n
e = 65537
d = gmpy2.invert(e,(p-1)*(q-1)*(r-1))
m = bytes_to_long(flag)
c = pow(m,e,n)
m = long_to_bytes(pow(c,d,n))
print(f'n = {n}')
print(f"c = {c}")
print(f'e = {e}')
print(f'D = {D}')
print(f'r_cubed = {r**3}')
#n = 1797464363937803574178366635456301143459899987065195402238965688630854838574693129181564969286593529451541315147307698518248164419022745845149367101229289853511043305315113437055463741220310201972952525360384401292742908307617104187282410207011086837143526628825853819176582961596474273863005403315519262514987973727415369569624782351302222624317374956732149792365793683939133163240811987601690584296532495636077337007058250072691770687934895196018165482285074087
#c = 334735157214244327583157709091138850291255337497549444727968382625552814752420162774889355435597239850801444255501536062808665271447071394852127129645007823666189408974242614895090473463544656321304260276646862158621490436794225048527190465633048027777929676430778187663379548454777508032938086766087680923109105263450337252432956611495124284902807201570660674571972801630769083508865730870372239801449723990206104741555109361529711228109643651552666016767418334
#e = 65537
#D = 9293355851986591081591521098987501845963630839756264676294309115767555607188666083544593308349243222711109037704690481694680479223233813272567476445999227440933917
#r_cubed = 1733587395810445026263077101568701832386760527292029091732688691632302263295044364907002644024851393182111273947443724875261726589148427101911382909265190107241975414590360694235677890202731336061400362438326929279259311961356096293232720988325040307146370196619971302229486629240899410846744560517421971004381582157573816044985536221126650590038003165043945929284756476920639015271502102636205225479117479735091470661892665348612065863317686928100311559126824531
exp
from Crypto.Util.number import *
from gmpy2 import iroot
n = 1797464363937803574178366635456301143459899987065195402238965688630854838574693129181564969286593529451541315147307698518248164419022745845149367101229289853511043305315113437055463741220310201972952525360384401292742908307617104187282410207011086837143526628825853819176582961596474273863005403315519262514987973727415369569624782351302222624317374956732149792365793683939133163240811987601690584296532495636077337007058250072691770687934895196018165482285074087
c = 334735157214244327583157709091138850291255337497549444727968382625552814752420162774889355435597239850801444255501536062808665271447071394852127129645007823666189408974242614895090473463544656321304260276646862158621490436794225048527190465633048027777929676430778187663379548454777508032938086766087680923109105263450337252432956611495124284902807201570660674571972801630769083508865730870372239801449723990206104741555109361529711228109643651552666016767418334
e = 65537
D = 9293355851986591081591521098987501845963630839756264676294309115767555607188666083544593308349243222711109037704690481694680479223233813272567476445999227440933917
r_cubed = 1733587395810445026263077101568701832386760527292029091732688691632302263295044364907002644024851393182111273947443724875261726589148427101911382909265190107241975414590360694235677890202731336061400362438326929279259311961356096293232720988325040307146370196619971302229486629240899410846744560517421971004381582157573816044985536221126650590038003165043945929284756476920639015271502102636205225479117479735091470661892665348612065863317686928100311559126824531
r = iroot(r_cubed, 3)[0]
phi = r - 1
d = inverse(e, phi)
print(long_to_bytes(pow(c, d, r)))
# b'DASCTF{5521a971-9bed-11ef-bfda-14ac6024b6a8}'
earsa_6
task
from sage.all import *
# from secret import flag
flag = b'flag{this_is_a_test_flag_lalala~~~}'
from Crypto.Util.number import *
p = next_prime(ZZ.random_element(2 ** 512))
q = next_prime(ZZ.random_element(2 ** 512))
m = bytes_to_long(flag)
n = p * q
print(f"p = {p}")
print(f"q = {q}")
phi_n = (p+1)*(q+1)
e = ZZ.random_element(phi_n)
while gcd(e, phi_n) != 1:
e = ZZ.random_element(phi_n)
d = inverse_mod(e, phi_n)
c = pow(m, e, n) # c = (mod(m ** 2, n) * power_mod(e, 2, n)) % n
print(f"n = {n}")
print(f"e = {e}")
print(f"c = {c}")
# "n = 103290940605767097772547367608381852550255311740089066062370678669736584831966972390296508499564302740251039905216525828381026059914694968711341442279592794179645755109637276941753470671672492643863307674183032056063497595618158607559032052302672569850017317721983409928424751468273419269585837187792579680441"
# "e = 4153390199995099394559502199356876987641001700181798065618463687883377896662802735692294514592974848815256220220567520414785101204978084883084168277609953983317089255372031928914225544973810429741972241310760306291217083076283386527880407979441234845945200062237779009000326020732264366320464844100039711500073849140628815801055506193561725597087896534906132971553150940778821878782222775892376719019037312704365897736892636528690951714686191932520762021674718730306167017168655476030445903413293206451445350127989832224321862119769332948547212450481322973363484001293075189230923276019258476580885163774258459928467"
# "c = 100933162705070380579705358896231615705264597351634019368382319632347917048149032133717183415739431564428093428992978229723659108455837366449426780119900838833128284699424510443364272415543344735540591444863458191423494866766098524960586274161507718151409519858841560317649453200969001613445259145496747256869"
analysis
- 根据题目描述信息搜集到相关的题型,先前也没有见过,但是有类似的题型以及攻击策略。
- 再利用现有的
attack
分解n
之后,我们进行下一步的求解。这里前面按照原有的题目,发现这里的e
并非题目脚本生成的。这里和赛事方进行了很长时间的沟通,按照原有的思路,我会进行有限域内开放求解m
但是这里并没有解,知道比赛题目难度降低,分解n
之后直接RSA
解密即可。
exp
from Crypto.Util.number import *
from sage.all import *
def attack(N, e):
"""
Recovers the prime factors of a modulus and the private exponent if two prime factors share most significant bits
:param N: the modulus
:param e: the public exponent
:return: a tuple containing the prime factors and the private exponent, or None if the private exponent was not found
"""
PR = PolynomialRing(ZZ, 'x')
x = PR.gen()
convergents = continued_fraction(ZZ(e) / ZZ((N - 1) ** 2)).convergents()
for c in convergents:
k = c.numerator()
d = c.denominator()
try:
f = x ** 2 - x * (N ** 2 + 1 - int((e * d - 1) / k)) + N ** 2
if f.discriminant() > 0:
root = f.roots()
p2 = root[0][0]; q2 = root[1][0]
if is_square(p2) and is_square(q2):
p = isqrt(p2); q = isqrt(q2)
if p * q == N:
return p, q, d
except:
continue
return None
n = 103290940605767097772547367608381852550255311740089066062370678669736584831966972390296508499564302740251039905216525828381026059914694968711341442279592794179645755109637276941753470671672492643863307674183032056063497595618158607559032052302672569850017317721983409928424751468273419269585837187792579680441
e = 4153390199995099394559502199356876987641001700181798065618463687883377896662802735692294514592974848815256220220567520414785101204978084883084168277609953983317089255372031928914225544973810429741972241310760306291217083076283386527880407979441234845945200062237779009000326020732264366320464844100039711500073849140628815801055506193561725597087896534906132971553150940778821878782222775892376719019037312704365897736892636528690951714686191932520762021674718730306167017168655476030445903413293206451445350127989832224321862119769332948547212450481322973363484001293075189230923276019258476580885163774258459928467
c = 100933162705070380579705358896231615705264597351634019368382319632347917048149032133717183415739431564428093428992978229723659108455837366449426780119900838833128284699424510443364272415543344735540591444863458191423494866766098524960586274161507718151409519858841560317649453200969001613445259145496747256869
# print(attack(n, e))
p, q, d = attack(n, e)
assert n % p == 0
flag = long_to_bytes(int(pow(c, d, n)))
print(flag)
写在最后
-
第一题不知道是出题人故意而为之还是没有考虑到
flag
过短导致可以直接开方r
下转素数进行求解。 -
第二题未修正之前有点看不懂加密,修正的时候说是为了降低难度,后续针对于赛事方的数据进行了测试,感觉很......
from sage.all import * from Crypto.Util.number import * # 提交正确的flag flag = b'DASCTF{5e1eddfb-dda2-11ed-8d28-ac675d417bad}' m = bytes_to_long(flag) # 题目附件给出的n n = 103290940605767097772547367608381852550255311740089066062370678669736584831966972390296508499564302740251039905216525828381026059914694968711341442279592794179645755109637276941753470671672492643863307674183032056063497595618158607559032052302672569850017317721983409928424751468273419269585837187792579680441 # 题目附件给出的e e = 4153390199995099394559502199356876987641001700181798065618463687883377896662802735692294514592974848815256220220567520414785101204978084883084168277609953983317089255372031928914225544973810429741972241310760306291217083076283386527880407979441234845945200062237779009000326020732264366320464844100039711500073849140628815801055506193561725597087896534906132971553150940778821878782222775892376719019037312704365897736892636528690951714686191932520762021674718730306167017168655476030445903413293206451445350127989832224321862119769332948547212450481322973363484001293075189230923276019258476580885163774258459928467 # 题目附件给出的c c = 100933162705070380579705358896231615705264597351634019368382319632347917048149032133717183415739431564428093428992978229723659108455837366449426780119900838833128284699424510443364272415543344735540591444863458191423494866766098524960586274161507718151409519858841560317649453200969001613445259145496747256869 # print(pow(m, e, n) == c1) True # 未降低难度前给出的加密流程 """😀😀😀😀😀""" c2 = (mod(m ** 2, n) * power_mod(e, 2, n)) % n print(c2 == c) # False