复数rsa,没遇到过这种类型的题,可以记录一下相关知识
先来看一段
from gmpy2 import invert,lcm,is_prime
import sys
sys.setrecursionlimit(2047)
f = (378122348642214690905411683807377396279362526734068034297186493255873563264253248095197659138069664908850853277799239471404715546747080714581633876343291058815268009173602365587463522797812239900814474973941995698621021680129530453282192603316731832323767320307650941745085796583822798379896337325L, 205549984221850341303682190742446959375043769671555741781145106776498798455293849755553794941345135675348633855787880355726112506553703853175271830126908219803257875131387292937296039523359975622001865593227631119497003599166091642640101746534401068507972834895023584843991641629874709898672559632L)
e = 59107
p = 228517792080140341
q = 1675909164550923263854591345270445396052847869117231939809062226222204253885693425526434134321712288675268468398852452684029376569327518089966506865838909486699078280423099271324646863671350838232140981094611254627738568184261530942469845202934677427234062382272736609418198352717
n = p*q
def cadd(a,b,n):
return (a[0]+b[0]%n,a[1]+b[1]%n)
def cmul(a,b,n):
return ((a[0]*b[0]-a[1]*b[1])%n,(a[0]*b[1]+a[1]*b[0])%n)
def cpow(a,k,n):
if(k==0):
return (1,0)
if(k==1):
return a
if(k%2==0):
a=cmul(a,a,n)
return cpow(a,k/2,n)
else:
return cmul(a,cpow(cmul(a,a,n),(k-1)/2,n),n)
o=lcm((p*p-1),(q*q-1))
fm=cpow(f,invert(e,o),n)
print(fm)
来源:https://github.com/Ariana1729/CTF-Writeups/blob/master/2019/CryptoCTF/Complex%20RSA/README.md
We first consider the order of C/pC* where p is a prime. The real and imaginary parts ranges from 0 to p-1, so a valid assumption is that the order is a multiple of p*p-1(since 0,0 can't be in the group). The order is exactly p*p-1 for p=3 mod 4 since it cannot be expressed as the sum of 2 squares, but for p=1 mod 4 it is less, and it is a multiple of p*p-1. Thus if we want to find g given g^e=a mod p, we simply invert e under p*p-1. For n=pq, the order is a multiple of lcm(p*p-1,q*q-1), then it's trivial For factoring n we simply use yafu
函数cadd:实现两个复数的加法。
函数cmul:实现两个复数的乘法
函数cpow:实现复数的幂运算,其中k为指数,n为模数
该段实现了一个复数域上的rsa解题过程
复数中欧拉函数:
p
h
i
(
p
)
=
p
2
−
1
p
h
i
(
q
)
=
q
2
−
1
p
h
i
(
n
)
=
(
p
2
−
1
)
∗
(
q
2
−
1
)
phi(p) = p^2 - 1\\phi(q) = q^2 - 1\\phi(n) = (p^2 - 1)*(q^2 - 1)
phi(p)=p2−1phi(q)=q2−1phi(n)=(p2−1)∗(q2−1)
[GeekChallenge-2023] EzComplex
题目描述:
from Crypto.Util.number import *
flag = b'FAKE{Do_You_know_Complex_numbers}'
p = random_prime(1 << 384)
q = random_prime(1 << 384)
n = p * q
e = 0x10001
N = pow(p, 2) + pow(q, 2)
m = bytes_to_long(flag)
c = pow(m,e,n)
print(c)
print(N)
'''
122977267154486898127643454001467185956864368276013342450998567212966113302012584153291519651365278888605594000436279106907163024162771486315220072170917153855370362692990814276908399943293854077912175867886513964032241638851526276
973990451943921675425625260267293227445098713194663380695161260771362036776671793195525239267004528550439258233703798932349677698127549891815995206853756301593324349871567926792912475619794804691721625860861059975526781239293017498
'''
题目分析:
N
=
p
2
+
q
2
=
(
p
+
q
∗
i
)
∗
(
p
−
q
∗
i
)
N = p^2 + q^2 = (p + q*i)*(p - q*i)
N=p2+q2=(p+q∗i)∗(p−q∗i)
遍历所有因子得到p,q,之后常规rsa解密
from Crypto.Util.number import *
c = 122977267154486898127643454001467185956864368276013342450998567212966113302012584153291519651365278888605594000436279106907163024162771486315220072170917153855370362692990814276908399943293854077912175867886513964032241638851526276
N = 973990451943921675425625260267293227445098713194663380695161260771362036776671793195525239267004528550439258233703798932349677698127549891815995206853756301593324349871567926792912475619794804691721625860861059975526781239293017498
e = 65537
zn = ZZ[i](N)
for d in divisors(zn):
p = int(d[0])
q = int(d[1])
if isPrime(p) and isPrime(q) and p.bit_length() > 380:
break
phi = (p-1)*(q-1)
n = p*q
d = inverse(e,phi)
print(long_to_bytes(int(pow(c,d,n))))
# SYC{D0_you_like_r41n?_i_pref3r_R1_ng}
ZZ(i)[N]:创建了一个整数高斯环。这个环的元素由整数和虚数部分组成,且整数和虚数部分都是整数。其中N是一个整数,表示高斯环的模,元素中整数和虚数部分的取值范围是[-N/2, N/2]
假设复数: a + b ∗ i a + b * i a+b∗i,那么 a,b ∈[-N/2, N/2]
其中有一种特殊情况:a = N,b = 0
题2
题目描述:
import os
import hashlib
from Crypto.Util.number import *
from secret import flag, totient
# where totient is a function used to calculate phi
class Complex:
def __init__(self, re, im):
self.re = re
self.im = im
def __mul__(self, c):
re_ = self.re * c.re - self.im * c.im
im_ = self.re * c.im + self.im * c.re
return Complex(re_, im_)
def show(self):
print([self.re, self.im])
def complex_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
def pad(msg, length):
pad_length = length - len(msg) - 1
pad_data = os.urandom(pad_length)
return msg + b'\x00' + pad_data
def unpad(msg):
return msg.split(b"\x00")[0]
bits = 512
p = getPrime(bits)
q = getPrime(bits)
n = p * q
sha_flag = hashlib.sha256(flag).digest()
m1 = Complex(
int.from_bytes(sha_flag[:len(sha_flag)//2], "big"),
int.from_bytes(sha_flag[len(sha_flag)//2:], "big"),
)
m2 = Complex(
int.from_bytes(pad(flag[:len(flag)//2], bits//4-1), "big"),
int.from_bytes(pad(flag[len(flag)//2:], bits//4-1), "big"),
)
phi = totient(p, q)
e = q * inverse(p, phi)
c1 = complex_pow(m1, e, n)
c2 = complex_pow(m2, e, n)
c1.show()
c2.show()
print(f'n = {n}')
"""
[90554536599623574119664951128649936419332926063696768860765928746438458550068553748440108394673303800443215316190882880737918820592384729010491685487061658710808286341751196450604089438847354206384322610922839055308138101241906861635339635907663440043442187064090630207952625897567214431195621589834131462698, 9144096375153318849308858335764188418198064372272913164911615933938183103747900881824918069830188301084043148828961577193063557255905230182831945580084452509300200269659063051152684191139872067872645370760797859584822240361290678189844670289832298393156571913616456958845361092243648857334156534377833472900]
[62925714576233017213228404230949787334346543378320798964656732359587152905032848271156799538355748406136742979043729040728123730886381468564779041856310262770766050213464073568850702827835472680885186487027698395099598698463717279017013124488699475168052581476224742146967412904416266652605031934025266540003, 62818668456104375760667670741457826560706388018921820295286033114468271151921637926389738844622672202424650967678199715932465104135980734708459543588178208672956785650944371545080965650112025782049517299538052360417245732776384089052839997333049599655001615752078742624898059780909287845495731050387891926520]
n = 94040393367054633265453751757391098049234338193258976478647369399924701067077628840760704857546243644552533845934146003988635403227234096447871132283820920489003286967145732739404245319615714787916756200564828237043658350145929927911058782352154997346295194977765305107634012698472977467843980475009837261877
"""
题目分析:
可以看出是一道基于复数的rsa,re实部,im虚部
complex_pow(m,e,n)
函数计算的是
m
e
m
o
d
n
m^e \mod n
memodn
其中phi = totient(p,q)
,e = q * inverse(p,phi)
里面提示totient is a function used to calculate phi
,而此题又是基于复数域上的,那么可以猜测
p
h
i
=
t
o
t
i
e
n
t
(
p
,
q
)
=
(
p
2
−
1
)
∗
(
q
2
−
1
)
phi = totient(p,q) = (p^2-1)*(q^2-1)
phi=totient(p,q)=(p2−1)∗(q2−1)
从加密流程可以看出:
c1的实部是sha_flag前半部分,虚部是sha_flag后半部分
c2的实部是flag前半部分,虚部是flag后半部分
e
≡
q
∗
p
−
1
m
o
d
p
h
i
e
∗
p
≡
q
m
o
d
p
h
i
e
∗
n
≡
q
2
m
o
d
p
h
i
c
1
n
≡
m
1
e
∗
n
≡
m
1
q
2
m
o
d
n
c
1
n
≡
m
1
q
2
≡
m
1
m
o
d
q
(
回到上面
p
h
i
(
q
)
=
q
2
−
1
)
e \equiv q * p^{-1} \mod phi\\ e*p \equiv q \mod phi\\ e * n \equiv q^2 \mod phi\\ c_1^n \equiv m_1^{e*n} \equiv m_1^{q^2} \mod n\\ c_1^n \equiv m_1^{q^2} \equiv m_1\mod q\\ (回到上面phi(q) = q^2 - 1)\\
e≡q∗p−1modphie∗p≡qmodphie∗n≡q2modphic1n≡m1e∗n≡m1q2modnc1n≡m1q2≡m1modq(回到上面phi(q)=q2−1)
c
1
n
−
m
1
=
k
∗
q
c_1^n - m_1 = k * q
c1n−m1=k∗q
m
1
m_1
m1只有128比特,比q的一半位数还小的多,完全可以copper求出
m
1
m_1
m1
之后gcd(k*q,n)得到q,那么p,q就都出了
然后常规rsa解题思路得到flag
注意,这里实现pow用它定义的complex_pow()
from Crypto.Util.number import *
from gmpy2 import *
class Complex:
def __init__(self, re, im):
self.re = re
self.im = im
def __mul__(self, c):
re_ = self.re * c.re - self.im * c.im
im_ = self.re * c.im + self.im * c.re
return Complex(re_, im_)
def show(self):
print([self.re, self.im])
def get_value(self):
return self.re,self.im
def complex_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
c1 = [90554536599623574119664951128649936419332926063696768860765928746438458550068553748440108394673303800443215316190882880737918820592384729010491685487061658710808286341751196450604089438847354206384322610922839055308138101241906861635339635907663440043442187064090630207952625897567214431195621589834131462698, 9144096375153318849308858335764188418198064372272913164911615933938183103747900881824918069830188301084043148828961577193063557255905230182831945580084452509300200269659063051152684191139872067872645370760797859584822240361290678189844670289832298393156571913616456958845361092243648857334156534377833472900]
c2 = [62925714576233017213228404230949787334346543378320798964656732359587152905032848271156799538355748406136742979043729040728123730886381468564779041856310262770766050213464073568850702827835472680885186487027698395099598698463717279017013124488699475168052581476224742146967412904416266652605031934025266540003, 62818668456104375760667670741457826560706388018921820295286033114468271151921637926389738844622672202424650967678199715932465104135980734708459543588178208672956785650944371545080965650112025782049517299538052360417245732776384089052839997333049599655001615752078742624898059780909287845495731050387891926520]
n = 94040393367054633265453751757391098049234338193258976478647369399924701067077628840760704857546243644552533845934146003988635403227234096447871132283820920489003286967145732739404245319615714787916756200564828237043658350145929927911058782352154997346295194977765305107634012698472977467843980475009837261877
c1 = Complex(c1[0],c1[1])
c2 = Complex(c2[0],c2[1])
cc1 = complex_pow(c1,n,n).get_value()
P.<m> = Zmod(n)[]
f = cc1[0] - m
f = f.monic()
m1 = f.small_roots(2^128,0.4)[0]
q = gcd(cc1[0]-int(m1),n)
p = n // q
phi = (p^2 - 1) * (q ^ 2 - 1)
e = q * inverse(p, phi)
d = inverse(e,phi)
m2 = complex_pow(c2,d,n).get_value()
print(long_to_bytes(int(m2[0])))
print(long_to_bytes(int(m2[1])))
# flag{3ef6db06-b837-11ed-9825-00155dfcdef9}
感觉这道题真的很有意思
浅记一下:
关键词:
复数欧拉,ZZ(i)[N],coppersmith
2024/05/11更新
[XYCTF2024] Complex_rsa
题目描述:
from Crypto.Util.number import *
from secrets import flag
class Complex:
def __init__(self, re, im):
self.re = re
self.im = im
def __mul__(self, c):
re_ = self.re * c.re - self.im * c.im
im_ = self.re * c.im + self.im * c.re
return Complex(re_, im_)
def __str__(self):
if self.im == 0:
return str(self.re)
elif self.re == 0:
if abs(self.im) == 1:
return f"{'-' if self.im < 0 else ''}i"
else:
return f"{self.im}i"
else:
return f"{self.re} {'+' if self.im > 0 else '-'} {abs(self.im)}i"
def complex_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
已知 : c = m e ( m o d n ) h = ( p + q i ) ( p + q i ) = ( p 2 − q 2 ) + 2 p q i h 的实部和虚部已知,那么 p , q 便能求出来 之后发现 e 与 p h i 不互素 g c d ( e , p h i ) = e g c d ( e , p 2 − 1 ) = g c d ( e , q 2 − 1 ) = 3 可知 : e ∗ d p ≡ 3 ( m o d p 2 − 1 ) , e ∗ d q ≡ 3 ( m o d q 2 − 1 ) 利用拓展欧几里得算法求出 d p 和 d q , 得到: m e d p ≡ m 3 ≡ c d p ( m o d p ) m e d q ≡ m 3 ≡ c d q ( m o d q ) 设 m = ( a + b i ) ,则 m 3 = ( a 3 − 3 a b 2 ) + ( 3 a 2 b − b 3 ) i 通过 c d p ( m o d p ) , c d q ( m o d q ) 解出所以可能的 a , b ,即 : a p ≡ a ( m o d p ) , a q ≡ a ( m o d q ) ① b p ≡ b ( m o d p ) , b q ≡ b ( m o d q ) ② 对①,②分别进行 c r t 得到所有可能的 a , b ,即 k e y 和 C 然后遍历异或找到最终符合的即可得到最终结果 已知:\\ c = m^e \pmod n\\ h = (p + qi) (p + qi) = (p^2 - q^2) + 2pqi\\ h的实部和虚部已知,那么p,q便能求出来\\ 之后发现e与phi不互素\\ gcd(e,phi) = e\\ gcd(e,p^2 - 1) = gcd(e,q ^ 2 - 1) = 3\\ 可知:\\ e * d_p \equiv 3 \pmod{p^2 - 1},e * d_q \equiv 3 \pmod{q^2 - 1}\\ 利用拓展欧几里得算法求出d_p和d_q,得到:\\ m^{ed_p} \equiv m^3 \equiv c^{d_p} \pmod p\\ m^{ed_q} \equiv m^3 \equiv c^{d_q} \pmod q\\ 设m = (a + bi),则m^3 = (a^3 - 3ab^2) + (3a^2b - b^3)i\\ 通过c^{d_p} \pmod p ,c^{d_q} \pmod q 解出所以可能的a,b,即:\\ a_p \equiv a \pmod p,a_q \equiv a\pmod q ①\\ b_p \equiv b \pmod p,b_q \equiv b\pmod q ②\\ 对①,②分别进行crt得到所有可能的a,b,即key和C\\ 然后遍历异或找到最终符合的即可得到最终结果 已知:c=me(modn)h=(p+qi)(p+qi)=(p2−q2)+2pqih的实部和虚部已知,那么p,q便能求出来之后发现e与phi不互素gcd(e,phi)=egcd(e,p2−1)=gcd(e,q2−1)=3可知:e∗dp≡3(modp2−1),e∗dq≡3(modq2−1)利用拓展欧几里得算法求出dp和dq,得到:medp≡m3≡cdp(modp)medq≡m3≡cdq(modq)设m=(a+bi),则m3=(a3−3ab2)+(3a2b−b3)i通过cdp(modp),cdq(modq)解出所以可能的a,b,即:ap≡a(modp),aq≡a(modq)①bp≡b(modp),bq≡b(modq)②对①,②分别进行crt得到所有可能的a,b,即key和C然后遍历异或找到最终符合的即可得到最终结果
exp:
from Crypto.Util.number import *
from sage.matrix.matrix2 import Matrix
from gmpy2 import *
def resultant(f1, f2, var):
return Matrix.determinant(f1.sylvester_matrix(f2, var))
class Complex:
def __init__(self, re, im):
self.re = re
self.im = im
def __mul__(self, c):
re_ = self.re * c.re - self.im * c.im
im_ = self.re * c.im + self.im * c.re
return Complex(re_, im_)
def __str__(self):
if self.im == 0:
return str(self.re)
elif self.re == 0:
if abs(self.im) == 1:
return f"{'-' if self.im < 0 else ''}i"
else:
return f"{self.im}i"
else:
return f"{self.re} {'+' if self.im > 0 else '-'} {abs(self.im)}i"
def complex_pow(c, exp, n):
result = Complex(1, 0)
while exp > 0:
if exp % 2:
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
p2_q2 = -28814875173103880290298835537218644402443395484370652510062722255203946330565951328874411874019897676900075613671629765922970689802650462822117767927082712245512492082864958877932682404829188622269636302484189627580600076246836248427780151681898051243380477561480415972565859837597822263289141887833338111120
pq2 = 235362412848885579543400940934854106052672292040465052424316433330114813432317923674803623227280862945857543620663672974955235166884830751834386990766053503640556408758413592161122945636548462064584183165189050320898315823173824074873376450569212651128285746330837777597290934043912373820690250920839961482862
e = 9
# print(solve([p^2 - q^2 == p2_q2,p * q * 2 == pq2],[p,q]))
p = 10205509456040823453782883291824829705816298450992336115902525676510986341532486274067943978039013674207011185602314114359146043975207543018267242312660911
q = 11531144714660489617244423924607904114688972598683439999377362467380544567879231460623526800789918614728790840508257630983753525432337178000220918002499321
c = [66350931528185981323649477263900844564494528747802437244889229343520648562164950914433406604580038018765783183569276743239888668912948977370163046257917321742455772852779551569446155827368453262479370103326286297164105599131090881306108546341785251895116423206455175290083968296281375908109039893280371271943,65266730684129269806656018828265187384002656633231286337130178390517924611751697965395744944541329793503617856896706439809241745206839328124348693486741656130890593895436661857688522977866438805549144904296596887218275440542852887148071837153436265722614658566275517205322945316112048487893204059562830581004]
c = Complex(c[0],c[1])
phi = (p ** 2 - 1) * (q ** 2 - 1)
t1,dp,k1 = gmpy2.gcdext(e,p^2-1) # e * dp + k1 * (p ^ 2 - 1) = t1 = 3
t2,dq,k2 = gmpy2.gcdext(e,q^2-1)
dp = dp % (p^2 - 1)
dq = dq % (q^2 - 1)
# 得到a % p, b % p
# dp = inverse(3,(p ** 2 - 1) // 3),两个一起除3,有这种方式吗?
m3 = complex_pow(c,dp,p)
re = m3.re
im = m3.im
PR.<a,b> = PolynomialRing(Zmod(p))
f1 = a ** 3 - 3 * a * b ** 2 - re
f2 = 3 * a ** 2 * b - b ** 3 - im
g = resultant(f1,f2,a)
h = resultant(f2,f1,b)
res_ap = g.univariate_polynomial().monic().roots()
res_bp = h.univariate_polynomial().monic().roots()
# 得到a % q, b % q
m3 = complex_pow(c,dq,q)
re = m3.re
im = m3.im
P.<a,b> = PolynomialRing(Zmod(q))
f1 = a ** 3 - 3 * a * b ** 2 - re
f2 = 3 * a ** 2 * b - b ** 3 - im
g = resultant(f1,f2,a)
h = resultant(f2,f1,b)
res_aq = g.univariate_polynomial().monic().roots()
res_bq = h.univariate_polynomial().monic().roots()
key = []
for i in res_ap:
for j in res_aq:
k = CRT_list([int(i[0]),int(j[0])],[p,q])
if k not in key:
key.append(k)
C = []
for i in res_bp:
for j in res_bq:
cc = CRT_list([int(i[0]),int(j[0])],[p,q])
if cc not in C:
C.append(cc)
for i in key:
for j in C:
m = long_to_bytes(i ^^ j)
if b'CTF' in m or b'flag' in m:
print(m)
break
# flag{Complex_is_so_fun_and_I_think_you_know_Sylvester!}
[XYCTF2024] Complex_dlp
题目描述:
from Crypto.Util.number import *
from secrets import flag
class Complex:
def __init__(self, re, im):
self.re = re
self.im = im
def __mul__(self, c):
re_ = self.re * c.re - self.im * c.im
im_ = self.re * c.im + self.im * c.re
return Complex(re_, im_)
def __str__(self):
if self.im == 0:
return str(self.re)
elif self.re == 0:
if abs(self.im) == 1:
return f"{'-' if self.im < 0 else ''}i"
else:
return f"{self.im}i"
else:
return f"{self.re} {'+' if self.im > 0 else '-'} {abs(self.im)}i"
def complex_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)
print(complex_pow(g, x, p))
# 5699996596230726507553778181714315375600519769517892864468100565238657988087817 + 198037503897625840198829901785272602849546728822078622977599179234202360717671908i
题目分析:
c
=
a
+
b
i
c
的模
:
∣
c
∣
=
a
2
+
b
2
c
的平方
:
c
2
=
(
a
2
−
b
2
)
+
2
a
b
i
c
方的模
:
∣
c
2
∣
=
(
a
2
−
b
2
)
2
+
4
a
2
b
2
=
a
2
+
b
2
可以得出
:
∣
c
m
∣
=
∣
c
∣
m
=
(
a
2
+
b
2
)
m
知道这个结论那么这题差不多就搞定了,里面的
p
又是光滑数,直接
d
i
s
c
r
e
r
t
e
_
l
o
g
便能解决
c = a + bi\\ c的模:\\ \left| c \right| = \sqrt{a^2 + b^2}\\ c的平方:\\ c^2 = (a^2 - b^2) + 2abi\\ c方的模:\\ \left| c^2 \right| = \sqrt{(a^2 - b^2)^2 + 4a^2b^2} = a^2 + b^2\\ 可以得出:\\ \left| c^m \right| = \left| c \right| ^ m = (\sqrt{a^2 + b^2})^m\\ 知道这个结论那么这题差不多就搞定了,里面的p又是光滑数,直接discrerte\_log便能解决
c=a+bic的模:∣c∣=a2+b2c的平方:c2=(a2−b2)+2abic方的模:
c2
=(a2−b2)2+4a2b2=a2+b2可以得出:∣cm∣=∣c∣m=(a2+b2)m知道这个结论那么这题差不多就搞定了,里面的p又是光滑数,直接discrerte_log便能解决
exp:
from Crypto.Util.number import *
cc = [5699996596230726507553778181714315375600519769517892864468100565238657988087817,198037503897625840198829901785272602849546728822078622977599179234202360717671908]
p = 1127236854942215744482170859284245684922507818478439319428888584898927520579579027
G = Zmod(p)
c = cc[0] ^ 2 + cc[1] ^ 2
m = discrete_log(G(c),G(3 ** 2 + 7 ** 2))
print(long_to_bytes(m))
# XYCTF{___c0mp13x_d1p_15_3@5y_f0r_y0u___}
只能说又学到了