defguess_k_d(frac): """ 这样嵌套写是为了看起来更清晰知道,本次连分数求和的目的是为了猜测 k 和 d """ return calc_continued_Frac(frac)
defcalc_d(k, d, e, n): """ 通过 Delta 判断是否有解,确定 d 是否正确 phi = (ed-1)/k """
if (e*d-1) % k != 0: returnFalse
phi = (e*d-1)//k
a = 1 b = phi - n - 1 c = n
delta = b**2-4*a*c x = gmpy2.iroot(delta, 2) ifnot x[1]: returnFalse
p = (-b+x[0])//(2*a) q = (-b-x[0])//(2*a) d = gmpy2.invert(e, phi)
return (p, q, d)
defwieners_attack(e, n): """ wiener's attack to get d by (e, n) """ FRAC = get_continued_Frac(e, n)
for i inrange(len(FRAC)): k, d = guess_k_d(FRAC[:i]) # 0 的逼近没有意义 if k == 0: continue
tag = calc_d(k, d, e, n) if tag: print("success!") return tag
if __name__ == "__main__": e = 3047442173541658754667464233797118324917469250436575767227172319344577259865313428705759330024959317716760816959590728238918140105663188172228696589411452947738069773833351725455888549656717874059636289036277785342126992626060696063089487811946920569580454880169977542532087635095357205433679009382368108273 n = 135568509670260054049994954417860747085442883428459182441559553532993752593294067458983143521109377661295622146963670193783017382697726454953197805014428888491744355387957923382241961401063461549210355871385000347645387907568135032087942016502668629010859519249039662555733548461551175133582871220209515648241
p, q, d = wieners_attack(e, n) print(f"p = {p}\nq = {q}\nd = {d}")
例题
题目
听说前面你都搞定啦?这次就很不一样了!
1 2 3
e = 11850552481503020257392808424743510851763548184936536180317707155841959788151862976445957810691568475609821000653594584717037528429828330763571556164988619635320288125983463358648887090031957900011546300841211712664477474767941406651977784177969001025954167441377912326806132232375497798238928464025466905201977180541053129691501120197010080001677260814313906843670652972019631997467352264392296894192998971542816081534808106792758008676039929763345402657578681818891775091140555977382868531202964486261123748663752490909455324860302967636149379567988941803701512680099398021640317868259975961261408500449965277690517 n = 12238605063252292170613110607692779326628090745751955692266649177882959231822580682548279800443278979485092243645806337103841086023159482786712759291169541633901936290854044069486201989034158882661270017305064348254800318759062921744741432214818915527537124001063995865927527037625277330117588414586505635959411443039463168463608235165929831344586283875119363703480280602514451713723663297066810128769907278246434745483846869482536367912810637275405943566734099622063142293421936734750356828712268385319217225803602442033960930413469179550331907541244416573641309943913383658451409219852933526106735587605884499707827 c = 6423785507684416773666948899915169554070001400671738254418895224701431744592066315840324501358322894303666459029450295999767148813342646167264341287124393625378316616139863708766163081219598771527606199602984020288261461737264281249264845116375731213029934802447231553854792109268285484082449452535764527888708733739012186167288822598437102840518848315984522212122067222074782253835923782275677317977038532227511279242281012000471845266622423324215667858024608033813931825929847132259909037530308932262269043122554140838785194939880489778556772907801622627958920544315663033749462060571279761917620516943658053070420
defguess_k_d(frac): """ 这样嵌套写是为了看起来更清晰知道,本次连分数求和的目的是为了猜测 k 和 d """ return calc_continued_Frac(frac)
defcalc_d(k, d, e, n): """ 通过 Delta 判断是否有解,确定 d 是否正确 phi = (ed-1)/k """
if (e*d-1) % k != 0: returnFalse
phi = (e*d-1)//k
a = 1 b = phi - n - 1 c = n
delta = b**2-4*a*c x = gmpy2.iroot(delta, 2) ifnot x[1]: returnFalse
p = (-b+x[0])//(2*a) q = (-b-x[0])//(2*a) d = gmpy2.invert(e, phi)
return (p, q, d)
defwieners_attack(e, n): """ wiener's attack to get d by (e, n) """ FRAC = get_continued_Frac(e, n)
for i inrange(len(FRAC)): k, d = guess_k_d(FRAC[:i]) # 0 的逼近没有意义 if k == 0: continue
tag = calc_d(k, d, e, n) if tag: print("success!") return tag
if __name__ == "__main__": e = 3047442173541658754667464233797118324917469250436575767227172319344577259865313428705759330024959317716760816959590728238918140105663188172228696589411452947738069773833351725455888549656717874059636289036277785342126992626060696063089487811946920569580454880169977542532087635095357205433679009382368108273 n = 135568509670260054049994954417860747085442883428459182441559553532993752593294067458983143521109377661295622146963670193783017382697726454953197805014428888491744355387957923382241961401063461549210355871385000347645387907568135032087942016502668629010859519249039662555733548461551175133582871220209515648241 c = 130120812377832417286104222457458309983570304365625148630229089933000228028818603755020533891985367026152405860566430269955539189768231036509478907868355152155314871113690115899272595597568805364726625998391205488017790451017392782657028623338866335943620081638386626654885413162134521065866286150284452978399
p, q, d = wieners_attack(e, n) m = pow(c, d, n) flag = long_to_bytes(m) print(flag) # b"flag{baby_RSA_wiener's_attack_so_easy}"