1.nc远程连接:
nc node4.buuoj.cn 29831
2.查看题目task:
from secret import flag
from Crypto.Util.number import *
from random import getrandbits
from hashlib import sha256
class EzRsa:
def __init__(self):
self.E = 0x10001
self.P = getPrime(1024)
self.Q = getPrime(1024)
while GCD((self.P-1)*(self.Q-1), self.E) != 1:
self.Q = getPrime(1024)
self.N = self.P*self.Q
def encrypt(self):
f = getrandbits(32)
c = pow(f, self.E, self.N)
return (f, c)
def encrypt_flag(self, flag):
f = bytes_to_long(flag)
c = pow(f, self.E, self.N)
return c
def proof():
seed = getrandbits(32)
print(seed)
sha = sha256(str(seed).encode()).hexdigest()
print(f"sha256({seed>>18}...).hexdigest() = {sha}")
sha_i = input("plz enter seed: ")
if sha256(sha_i.encode()).hexdigest() != sha:
exit(0)
if __name__ == "__main__":
proof()
print("welcome to EzRsa")
print("""
1. Get flag
2. Encrypt
3. Insert
4. Exit
""")
A = EzRsa()
coin = 5
while coin > 0:
choose = input("> ")
if choose == "1":
print(f"pow(flag,e,n) = {A.encrypt_flag(flag)}\ne = 0x10001")
exit(0)
elif choose == "2":
f, c = A.encrypt()
print(f"plain = {f}\ncipher = {c}")
coin -= 1
elif choose == "3":
q = getrandbits(1024)
n = A.P*q
f = getrandbits(32)
c = pow(f, 0x10001, n)
print(f"plain = {f}\ncipher = {c}")
coin -= 1
elif choose == "4":
print("bye~")
else:
print("wrong input")
print("Now you get the flag right?")
3.分析过程:
5个硬币,5次选择机会,最终目标是获取choice1中的flag=pow(c,d,n)。
所以需要求出p,q,n,在choice3中可以看到A.P来自与EzRsa这个类,因为种子固定,所以每次的A.P都相同,由于p一般为kp比较大,无法爆破,所以可以根据选择两次3,求最大公约数的方式求kp:
推导过程:
c31=m31^e%n
=m31^e-k1n
=m31^e-k1*p*q1
c32=m32^e%n
=m32^e-k2n
=m32^e-k2*p*q2
所以:
k1*p*q1=m31^e-c31
k2*p*q2=m32^e-c32
所以,通过欧几里得算法求公约数:
gcd(m31^e-c31,m32^e-c32)
p为公约数,如果k1和k2互素,公约数则为p;不互素,公约数为kp
同理,选择两次choice2,求出公约数n:
推导过程:
c21=m21^e%n
=m21^e-k1n
c22=m22^e%n
=m22^e-k2n
所以:
k1n=m21^e-c21
k2n=m22^e-c22
n为公约数,如果k1和k2互素,公约数则为n;不互素,公约数为kn
所以需要写循环判断k1和k2是否互素
4.exp:该脚本先计算出kn的k值,然后,注释掉n的函数调用,直接计算n=kn//3
import libnum
import gmpy2
from Crypto.Util.number import *
m32 = 3323861755
c32 = 3189600455343045434080347477377637509639599093851483905469324364325280015612695035974460965906143466590067058820022037215171320039106501227090699765870079884516902376220489075658195797239624361978029353515372989346970685866580974883414497877056461544490050501294946867616806663820642287073662764555736921469660321660426415536232186568006099805750142302915837627738705008958091128158815612024425841213331717831045875324620701104247050280930690805178761910513823571401611581282576469913633179017318736801189219784253867305021130959131652677457283221377437538402795936136989234771438450126125288004100790674284118174245
m31= 2905310453
c31 = 2120565633610951077941408013358952516811861122789219625789934408897427578162721586466656928552605179729112639291741870081373303246269810410969173072036339930701012508737104606501941337497152394658336331350370845697411306670862802768866713312047784662830052433356420834207281572915360197159247150939609324108293693018061893203755507115913362099001088934356822665537267849572444146470179382854418790912627138058547478480232826854971403641267130040586290801692807074115787085791944837845074067423725376086847943520064232425683298621813358060198654633324986211798423617076959313361715754819102009643187348797398069765786
m22 = 616858868
c22 = 605563881409216330847669526462868481426198351625605143143266962817465835792648878756702619432683534965294072375800100712154114554144606972279812467636022968304993315143809363224197826056890452379708490559111716835856182100890741862972071504150399911275224860125286182474924846242400198673855143951141264794223514979858497124028733290900826044914905952895104924912862844974767484534446183511008350846185437719281973039843561565537371670697761880512290430164465139031441558044768964316607817344296736994028669368360274702222505694753759958463980495408150250582691160167727479506569386708621967079259357962735901575139
m21 = 3634632521
c21 = 1413535001511989764430561420750992223439084726181291612751329294086131401295033206111884399389132757372373421411093951829105632559387812507997223640686969347737187572441734790693531411682686131585735490815603314930183293261226164898661688481751362320548282386718963976466919534178881782027426154450358177644252281757378349193675527673605562843736598993426404303110768026085252784297480654365997826769452386577613167377385502329569051341885040492915597541098427570666977195876149288107417212891503323773577021450417252250704450118861155868563857637982731085076955391888769802874741035176160901513860209444453095501149
c = 12220699867583389713189337563070388502884711983567881601567164519070090130746870615727797479813679364921988322629180343147954990329314605951355031756186402654953156028344200485817682150494402566738965512529164151673986717059696437660614129716871283169617251674891552386020328591497805753589519339410450250717056044384508363366278793241787814076134681307520678937377712136397588221480066278249164880616307557346834844908222674060238693168924763195094750799943451157049128567967860995613642063540796703533664520023681811737488844905521105858034719053389672368379599366604446837961399110377113163256957097411924626051947
e = 0x10001
import gmpy2
def p_def(p):
k=1
while 1:
if gmpy2.is_prime(p):
print(p)
print(k)
return p
elif p % (k) == 0 and k != 1:
p=p//k
print(k)
else:
k+=1
kp=gmpy2.gcd(m31**e-c31,m32**e-c32)
# print(kp)
#print(gmpy2.is_prime(kp))
p=p_def(kp)
# print(p)
#print(gmpy2.is_prime(p))
kn=gmpy2.gcd(m21**e-c21,m22**e-c22)
#print(kn)
#kn=p_def(kn)
n=kn//3
q=n//p
print(gmpy2.is_prime(q))
phi_n=(p-1)*(q-1)
d=gmpy2.invert(e,phi_n)
m=pow(c,d,n)
print(libnum.n2s(int(m)))