这样好像要挂个 40 分钟的样子,因为 Wiener 攻击需要求在每次都要求连分数,以及判断是否为解。
1 2 3 4 5 6 7 8 9 10
for Nl in trange(2^7): for el inrange(2^8): N = Nh + 2 * Nl + 1 e = eh + el d = solve_pell(N, e) if (d isnotNone): print('AOLIGEI!!!') print(f'{N = }') print(f'{e = }') print(f'{d = }')
defsolve_pell(N, e): cf = continued_fraction (N / e) i = 0 whileTrue: denom = cf . denominator ( i ) numer = cf . numerator ( i ) d = numer if d.nbits() == 64and is_prime(d): return d i += 1
d = solve_pell(Nh, eh)
for Nl in trange(2^7): for el inrange(2^8): N = Nh + 2 * Nl + 1 e = eh + el g = 2 ifpow(g, e*d, N) == g: print('AOLIGEI!!!') print(f'{N = }') print(f'{e = }') print(f'{d = }')
求出 $N$ 和 $e$ 之后,枚举 $c$ 的低 8 位解密即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
from Crypto.Util.number import *
N = 28781418259071163834545208786492597316357138268450456443121779857237190669654679502925616925907115061139426651454246296829614929839091896732956124186768298711851015827257060255218333952539548249210858753648965921585289379414151961197198777686222970660319202167442420274437451557166736926361972983650143650097981777542950972139757680517744639660898696901009088978971506526002932830312595664154921938706240176536981793499426543601513874115451315768319593051858239793153849410530285884330866972048864103208648273010126369559341912163849839663249252300813799486995834473605326584986843653735963725697383056972744506296271 e = 19152712448778858582528734875468196678366984818842265525346340114296810907435357813959451387293270496095878944786775775749129832803842508074794234774568097809721690831345120778762600713106116293626590641716601095020202233532544196547654794913903350183891867544539554967347396716482565232986995497267273877597593761608770699282404807896050347585632153075234094034163801474316224123620090879021107631960008144066862084573910442635526649884938724881478713853362879412453150893601267748827792136092224063120914443976032390554506925020506643629449426005820918745312311984391868895996772772355715765028825561022860823765675 d = 10254340117704573547