「Bugku CTF」Easy Math
题意
题目给出了一份 task.py
,内容如下:
from Crypto.Util.number import getPrime, bytes_to_long
from secret import flag
p = getPrime(2048)
q = getPrime(2048)
x = getPrime(4096)
y = getPrime(4096)
n = p * q
e = 0x10001
c = pow(bytes_to_long(flag), e, n)
print(c)
print(x * p - y * q)
print(x)
print(y)
可以看出,\(p,q\) 为 \([0,2^{2048})\) 中的随机质数,\(x,y\) 为 \([0,2^{4096})\) 中的随机质数(已知)。现在 flag
被转换成二进制,你知道其 \(e\) 次方模 \(n\) 的值。
分析
首先 \(x,y\) 互质,又知道 \(xp-yq\) 的值,可以用 exgcd 求解出 \(p,q\)。由于 \(x,y\) 的值域比 \(p,q\) 大 \(2^{2048}\) 倍,极大概率 \(p,q\) 的解是唯一的(事实也如此)。
接着是 \(\text{flag}^{e}\equiv c\pmod n\),我们可以拆成 \(\pmod p\) 和 \(\pmod q\),再用 CRT 合并起来。
现在问题抽象为找到 \(x\),满足 \(x^e\equiv \text{R}\pmod{\text{M}}\)。我采用的是费马小定理。
注意到 \(e\bot (\text{M}-1)\),因此可以找到 \(eu\equiv 1\pmod{\text{M}-1}\),这样就有:
\[x\equiv x^{eu}\equiv \text{R}^u\pmod{\text{M}}
\]
最后,将 flag
二进制反解回去即可,这一步平凡。
代码
import sys
sys.setrecursionlimit(2 ** 20)
def gcd(x, y):
if y == 0:
return x
else:
return gcd(y, x % y)
rem = 819167649963114752409071690942828965596762225702125422224651455091514510699221689012200925546275830031560636434571675297352911785548562558995259185529739372065415320407815802186750343466069603564453133335339468465023669871194636196892019998935207213206263690388438074192184316296023645401077877114715985230518850300854162564541697624876005006316693763495665196932392860282743136069254457238426514217654211308356576587743413266816116398061386744037936492351734676350831535904555786373417782943462487966342446324586920268533217659394595673776791727030156809145044771214337720082482665839942679556775596805037563432378445332344070307192086425710019138340320155999228758718645401601922806183309005000232793295108264248107221425831137940764747440899967198929744597645010447079132413064685696595497031622178756728371427223009071172365660399862426808614310781649262366953422451061715753988547005171624561572800209843727720479076455447302266315465616082052292906817024385349625367335127791370192543189766366250792588949920001870810018187835769296432354197933863536721500934207233900135841304460719234606155627533870809427764337881255478336303687175976104216650172450886939797274047649899113069365776930432541285901134533586020261232876898556
x = 632789818728437249014397968661921775581544184224274756276433610798113468993672164321438530616013253289782663689077268876186151437864544302469108580709641566485290311420121506047579208345815027532791974738974313200169956832221919603190470863795222438259219096469376978228578380264663345353405438455186474301297012193183679157205629903265170130103917934683090733281473604073360246791105302237248347327779245961650717330972723138979527847182834557342036244971153338500301679961477335495638826895006083228659413981010440339548216034046748372206443701123739501069837327986187240490120446390477989503341189926203433991663521331801532805472205226609164816353391564959573141240378777470418994251339128482692796773797189201818245228107080728132313948392278762055786817726909473749863670490856099352687396397382321897116397931192027599070027627694680087783451302597521080702011592065963594511723809150300184064231573197933953378151145481864603829132945843828406023019349658403181028564910247213010151333549565330384930314823393041100958566895783471423052411323469971356896800670127810656782436426988914502569025478559937511734711601790440407326688723474002610311556839284338719325762246957198057778260962250609427063416142879689421634421458709
y = 643036772350048228226994649092616650645954632907587039823201793924675328231324332666556623349121829177212510871016658056913708287862858528109879661403451187304726709132260743678530717837451671681355571221280002404299107695652155670051078882192093123123561845252965958271768933274773257692931042446530995042732001095255062905223134293710172411977911384445547906762517497734345024155549903618728650384451421173225517825102299209880684634460331223065873651202939210708252359077003909032324005805452514172406303829425073706650894226101275953935372059009590759610077924785340813184927561117202564837188711962251575479458375013998344858887909613413912370566496257586437903234141740497499987400831528329286044181171784190933054960738806780037696966451373943646987424395266465375230570034361116196796918297724925148528750740437152338021273617526482564999975699692816362539898387887578959664017588135024295202965648259490954273611159737721618049049630608155576688331546213838011267525827596272825121479187503405108808503874817959024671313813455057255041638822640703012661546718752651979237589873357378433672292216062102553378571263015343101391160579720162709138758489316499316122410388218239186892007182433862338617140046642758913862484601497
z = 1699980137266557324344914328325272464132636282755221827458872463192020874135524827987217608051368206672934330683211276768709877840468972596490803759885813728690444018491934963720438572841678828429913822054802155884199440293180952789752415462639050713771680511777055884579458058757377759627744674844108633533334457344901084171274088270351873241352667334795523258220147308594499138453672732641220818083962784902673365318410315424514270533343700860737463941309778962170226910616237946542757166553717492195935533892236503442774023121626490914033401612167978954941330133300881931925497717512695171706212382578903001110920592500175461456995288709439779857319205707173662845644405055427904509419863606240680925061916382420684482076378518205523197463067938227019763990108007075242817656584738069628913136354101292332085988235385095314890393764303221439993179548360648981274242121283353602916815145403803542637335824051819986555363523349256992995614272850197795324686379321786728586563648175181401083465608646485432113720677594958984638724107125334720354094296357390072599568691394140689362397548059953034709737955082932844672007207996936767062822977154868592390902978952191044067944696085651546627109166427150923047360912876244376114967514367037960727491317506149228522989115013325839758536585180101058382614514947428328314724097308211883678572797106209083583109261376984483242047015474025283180602280795727273381785266819469972756514932048700356409177010293248246465560904863373454995512681663614120751469186425087937476277098506766986185341057569253541467185884718825148546913924405454412786581778526929471207590180161807679236125962298541766845327682689402342086818440002212258092785616843818868009803516765308135874826622684994974230341120600336001281979511703254112012642242186568042544945546342209510451281619322586082384591244651070733725666379203036
# px - qy = z
p = 0
q = 0
def exgcd(x, y):
global p
global q
if y == 0:
p = 1
q = 0
return
else:
exgcd(y, x % y)
r = p
p = q
q = r - (x // y) * p
exgcd(x, y)
assert(p * x + q * y == 1)
p = (p * z + y) % y
q = x - (q * z + x) % x
# print(p)
# print(q)
assert(p * x - q * y == z)
ep = 0x10001
def sol(rem, mod): # ?^{16^4+1} % mod = rem
assert(gcd(ep, mod - 1) == 1)
global p
global q
x = ep
y = mod - 1
exgcd(x, y)
assert(x * p + y * q == 1)
p = (p % y + y) % y
return pow(rem, p, mod)
pp = p
qq = q
k1 = sol(rem % pp, pp)
assert(pow(k1, ep, pp) == rem % pp)
k2 = sol(rem % qq, qq)
assert(pow(k2, ep, qq) == rem % qq)
exgcd(pp, qq)
p = ((k2 - k1) * p % qq + qq) % qq
flag = (k1 + p * pp) % (pp * qq)
print('flag:', flag)
assert(pow(flag, ep, pp * qq) == rem)
a = []
while flag:
a.append(flag % 2)
flag = flag // 2
while len(a) % 8 != 0:
a.append(0)
print(len(a))
for i in range(len(a) - 8, -1, -8):
num = 0
for j in range(0, 8):
num += (2 ** j) * a[i + j]
print(chr(num), end = '')