defpossible(e,alist,N): for x in alist: if x==0: continue phi=(e*x.denominator()-1)//x.numerator() if (N-phi+1)%2==0and sqrt(pow((N-phi+1)//2,2)-N).is_integer(): (p,q)=var('p q') x=solve([(p-1)*(q-1)==phi,p*q==N],p,q) return x else: continue defwienner_attack(e,N): c=continued_fraction(e/N)#获取连分数集合 alist=c.convergents()#利用连分数得到连分数收敛 return possible(e,alist,N) ''' x.denominator():
whileTrue: p = random_prime(2**(p_bits), lbound=2**(p_bits-1)) q = random_prime(2**(q_bits), lbound=2**(q_bits-1)) if p != q and p > q and p < 2*q: break
N = p * q phi = (p**4 - 1) * (q**4 - 1)
d_bits = 1024 d_bound = 2**d_bits
whileTrue: d_small = randint(2, d_bound) d = phi - d_small if gcd(d, phi) == 1: if d_small.bit_length() == 1021: break
e = inverse_mod(d, phi)
return N, e
defencrypt(m, N, e): n = 4 r = 2 R = Integers(N) P = PolynomialRing(R, 't') t = P.gen() Q = P.quotient(t**n - r)
m_poly = Q([m, 0, 0, 0])
c_poly = m_poly ** e
return c_poly.lift()
if __name__ == "__main__": N, e = generate_vulnerable_key() m = int.from_bytes(flag, 'big') c = encrypt(m, N, e)
# N = 99697845285265879829811232968100099666254250525000506525475952592468738395250956460890611762459685140661035795964867321445992110528627232335703962897072608767840783176553829502743629914407970206513639916759403399986924602596286330464348286080258986075962271511105387188070309852907253486162504945490429185609 # e = 74900336437853271512557457581304251523854378376434438153117909482138661618901386551154807447783262736408028580620771857416463085746907317126876189023636958838207330193074215769008709076254356539808209005917645822989554532710565445155350102802675594603406077862472881027575871589046600011223990947361848608637247276816477996863812313225929441545045479384803449990623969591150979899801722841101938868710054151839628803383603849632857020369527380816687165487370957857737696187061619496102857237814447790678611448197153594917852504509869007597997670022501500067854210261136878917620198551551460145853528269270832725348151160651020188255399136483482428499340574623409209151124687319668989144444549871527949104436734300277004316939985015286758651969045396343970037328043635061226100170529991733947365830164811844853806681198818875837903563263114249814483901121700854712406832325690101810786429930813776784979083590353027191492894890551838308899148551566437532914838098811643805243593419063566975400775134981190248113477610235165151367913498299241375039256652674679958159505112725441797566678743542054295794919839551675786573113798857814005058856054462008797386322048089657472710775620574463924678367455233801970310210504653908307254926827 # c = 98460941530646528059934657633016619266170844887697553075379408285596784682803952762901219607460711533547279478564732097775812539176991062440097573591978613933775149262760936643842229597070673855940231912579258721734434631479496590694499265794576610924303262676255858387586947276246725949970866534023718638879
N = 99697845285265879829811232968100099666254250525000506525475952592468738395250956460890611762459685140661035795964867321445992110528627232335703962897072608767840783176553829502743629914407970206513639916759403399986924602596286330464348286080258986075962271511105387188070309852907253486162504945490429185609 e = 74900336437853271512557457581304251523854378376434438153117909482138661618901386551154807447783262736408028580620771857416463085746907317126876189023636958838207330193074215769008709076254356539808209005917645822989554532710565445155350102802675594603406077862472881027575871589046600011223990947361848608637247276816477996863812313225929441545045479384803449990623969591150979899801722841101938868710054151839628803383603849632857020369527380816687165487370957857737696187061619496102857237814447790678611448197153594917852504509869007597997670022501500067854210261136878917620198551551460145853528269270832725348151160651020188255399136483482428499340574623409209151124687319668989144444549871527949104436734300277004316939985015286758651969045396343970037328043635061226100170529991733947365830164811844853806681198818875837903563263114249814483901121700854712406832325690101810786429930813776784979083590353027191492894890551838308899148551566437532914838098811643805243593419063566975400775134981190248113477610235165151367913498299241375039256652674679958159505112725441797566678743542054295794919839551675786573113798857814005058856054462008797386322048089657472710775620574463924678367455233801970310210504653908307254926827 c = 98460941530646528059934657633016619266170844887697553075379408285596784682803952762901219607460711533547279478564732097775812539176991062440097573591978613933775149262760936643842229597070673855940231912579258721734434631479496590694499265794576610924303262676255858387586947276246725949970866534023718638879 A = N**4
from gmpy2 import invert def possible(e,alist,N): for x in alist: if x==0: continue phi=(e*x.denominator()-1)//x.numerator() if (N-phi+1)%2==0andsqrt(pow((N-phi+1)//2,2)-N).is_integer(): (p,q)=var('p q') Phi=phi return Phi else: continue def wienner_attack(e,N): c=continued_fraction(e/N)#获取连分数集合 alist=c.convergents()#利用连分数得到连分数收敛 return possible(e,alist,N) _t= _c = _n = _e = phi=wienner_attack(_t,_n) d1=invert(_e,phi) e1=pow(_c,d1,_n) print(e1)
利用e1构造矩阵得到phi在求出m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
from gmpy2 import invert from Crypto.Util.number import bytes_to_long, long_to_bytes c = e2 = e1 = N = a = 5./14 M1=N**0.5 M2= N **(a+1) D = diagonal_matrix(ZZ,[N,M1,M2,1]) M=matrix(ZZ,[[1,-N,0,N**2],[0,e1,-e1,-e1*N],[0,0,e2,-e2*N],[0,0,0,e1*e2]])*D L=M.LLL() t=vector(ZZ,L[0]) x=t*M**(-1) phi = int(x[1]/x[0]*e1) d = invert(0x10001,phi) m=int(pow(c,d,N)) print(long_to_bytes(m))