defcomplex_pow(c, exp, n): result = Complex(1, 0) while exp > 0: if exp & 1: result = result * c result.re = result.re % n result.im = result.im % n c = c * c c.re = c.re % n c.im = c.im % n exp >>= 1 return result
flag = flag.strip(b"XYCTF{").strip(b"}") p = 1127236854942215744482170859284245684922507818478439319428888584898927520579579027 g = Complex(3, 7) x = bytes_to_long(flag) #complex_pow(g, x, p)==5699996596230726507553778181714315375600519769517892864468100565238657988087817 + 198037503897625840198829901785272602849546728822078622977599179234202360717671908i
做的时候一直卡在复数转实数上,想到了共轭复数但是没有去仔细研究。
赛后看wp知道了定义
这样题目中的g和c都可以通过实部和虚部平方相加的方式转为实数再进行普通的dlp求解
exp:
1 2 3 4 5 6 7 8
from Cryptodome.Util.number import * import gmpy2 from sympy.ntheory import discrete_log p=1127236854942215744482170859284245684922507818478439319428888584898927520579579027 g=58 c=(5699996596230726507553778181714315375600519769517892864468100565238657988087817**2)+(198037503897625840198829901785272602849546728822078622977599179234202360717671908**2) flag=discrete_log(p,c,g) print(long_to_bytes(flag))
defcomplex_pow(c, exp, n): result = Complex(1, 0) while exp > 0: if exp & 1: result = result * c result.re = result.re % n result.im = result.im % n c = c * c c.re = c.re % n c.im = c.im % n exp >>= 1 return result
m = bytes_to_long(flag) key = getRandomNBitInteger(m.bit_length()) c = m ^ key com = Complex(key, c) p = getPrime(512) q = getPrime(512) e = 9 enc = complex_pow(com, e, p * q) print(enc) print(Complex(p, q) * Complex(p, q)) # 66350931528185981323649477263900844564494528747802437244889229343520648562164950914433406604580038018765783183569276743239888668912948977370163046257917321742455772852779551569446155827368453262479370103326286297164105599131090881306108546341785251895116423206455175290083968296281375908109039893280371271943 + 65266730684129269806656018828265187384002656633231286337130178390517924611751697965395744944541329793503617856896706439809241745206839328124348693486741656130890593895436661857688522977866438805549144904296596887218275440542852887148071837153436265722614658566275517205322945316112048487893204059562830581004i # -28814875173103880290298835537218644402443395484370652510062722255203946330565951328874411874019897676900075613671629765922970689802650462822117767927082712245512492082864958877932682404829188622269636302484189627580600076246836248427780151681898051243380477561480415972565859837597822263289141887833338111120 + 235362412848885579543400940934854106052672292040465052424316433330114813432317923674803623227280862945857543620663672974955235166884830751834386990766053503640556408758413592161122945636548462064584183165189050320898315823173824074873376450569212651128285746330837777597290934043912373820690250920839961482862i
m = bytes_to_long(pad(flag)) p = getStrongPrime(512) q = getStrongPrime(512) n = p * q e = 3 print(pow(m, e, n)) print(n) # c=120440199294949712392334113337541924034371176306546446428347114627162894108760435789068328282135879182130546564535108930827440004987170619301799710272329673259390065147556073101312748104743572369383346039000998822862286001416166288971531241789864076857299162050026949096919395896174243383291126202796610039053 # n=143413213355903851638663645270518081058249439863120739973910994223793329606595495141951165221740599158773181585002460087410975579141155680671886930801733174300593785562287068287654547100320094291092508723488470015821072834947151827362715749438612812148855627557719115676595686347541785037035334177162406305243 # m=1252734178929444996144243699830218307941015280272407466795285950142407741311749512416560379489724065530428888294520405996969464281930538422811270188075397985
e = 3 c = 120440199294949712392334113337541924034371176306546446428347114627162894108760435789068328282135879182130546564535108930827440004987170619301799710272329673259390065147556073101312748104743572369383346039000998822862286001416166288971531241789864076857299162050026949096919395896174243383291126202796610039053 n = 143413213355903851638663645270518081058249439863120739973910994223793329606595495141951165221740599158773181585002460087410975579141155680671886930801733174300593785562287068287654547100320094291092508723488470015821072834947151827362715749438612812148855627557719115676595686347541785037035334177162406305243
PR.<x> = PolynomialRing(Zmod(n)) for length in trange(20,50): suffix = bytes_to_long(hash(str(length))) f = (256^32*x + suffix)^3 - c f = f.monic() res = f.small_roots(X=256^length,beta=1,epsilon=0.05) if(res != []): print(long_to_bytes(int(res[0]))) break