强网杯-Qualifier-2022/强网先锋/ASR writeup
强网杯-Qualifier-2022/强网先锋/ASR writeup
1. challenge
from Crypto.Util.number import getPrime
from secret import falg
pad = lambda s:s + bytes([(len(s)-1)%16+1]*((len(s)-1)%16+1))
n = getPrime(128)**2 * getPrime(128)**2 * getPrime(128)**2 * getPrime(128)**2
e = 3
flag = pad(flag)
print(flag)
assert(len(flag) >= 48)
m = int.from_bytes(flag,'big')
c = pow(m,e,n)
print(f'n = {n}')
print(f'e = {e}')
print(f'c = {c}')
'''
n = 8250871280281573979365095715711359115372504458973444367083195431861307534563246537364248104106494598081988216584432003199198805753721448450911308558041115465900179230798939615583517756265557814710419157462721793864532239042758808298575522666358352726060578194045804198551989679722201244547561044646931280001
e = 3
c = 945272793717722090962030960824180726576357481511799904903841312265308706852971155205003971821843069272938250385935597609059700446530436381124650731751982419593070224310399320617914955227288662661442416421725698368791013785074809691867988444306279231013360024747585261790352627234450209996422862329513284149
'''
2. 分析
n是一个平方数,平方根是4个128bit素数的乘积,应该可以通过ecm分解。
e = 3
c = 945272793717722090962030960824180726576357481511799904903841312265308706852971155205003971821843069272938250385935597609059700446530436381124650731751982419593070224310399320617914955227288662661442416421725698368791013785074809691867988444306279231013360024747585261790352627234450209996422862329513284149
n = 8250871280281573979365095715711359115372504458973444367083195431861307534563246537364248104106494598081988216584432003199198805753721448450911308558041115465900179230798939615583517756265557814710419157462721793864532239042758808298575522666358352726060578194045804198551989679722201244547561044646931280001
pqrs = 2872432989693854281918578458293603200587306199407874717707522587993136874097838265650829958344702997782980206004276973399784460125581362617464018665640001
assert pqrs*pqrs == n
使用yafu在一台8U的云主机上可以分解n。
docker run -ti ssst0n3/yafu:2.10
# yafu -threads 128
...
Total factoring time = 977.9845 seconds
***factors found***
P39 = 218566259296037866647273372633238739089
P39 = 225933944608558304529179430753170813347
P39 = 223213222467584072959434495118689164399
P39 = 260594583349478633632570848336184053653
ans = 1
接下来可以考虑求得d。
p = 225933944608558304529179430753170813347
assert(p.is_prime())
assert(n%p==0)
q = 260594583349478633632570848336184053653
assert(q.is_prime())
assert(n%q==0)
r = 223213222467584072959434495118689164399
assert(r.is_prime())
assert(n%r==0)
s = 218566259296037866647273372633238739089
assert(s.is_prime())
assert(n%s==0)
phi = p*(p-1)*q*(q-1)*r*(r-1)*s*(s-1)
print(gcd(e, phi))
# d = inverse_mod(e, phi)
3
但本题中e和phi不互素。
因为e较小,可以在对每个素数的模域上,解出$c^{\frac{1}{3}}$, 每组会有至多3个解,共4组。
对每个解要与素因子进行CRT还原出原始解。
from itertools import product
def euler_totient(factors):
return reduce(lambda t, p: t * (p - 1), factors, 1)
def e_phi_not_coprime(primes, e, c):
"""
for gcd(e, phi) != 1 and it's small
"""
phi = euler_totient(primes)
gcd_e_phi = gcd(phi, e)
small_roots = []
for prime in primes:
P.<a> = PolynomialRing(Zmod(prime),implementation='NTL')
f = a^gcd_e_phi-c
roots = f.monic().roots()
# print(roots)
for root in roots:
assert len(root) == 2
assert root[1] == 1
small_roots.append([Integer(root[0]) for root in roots])
roots = []
for iter_roots in product(*small_roots):
roots.append(CRT_list(list(iter_roots), primes))
return roots
def solve():
primes = [p,q,r,s]
roots = e_phi_not_coprime(primes, e, c)
for root in roots:
flag = int(root).to_bytes(64, 'big')
if b"flag" in flag:
print(flag)
break
solve()
b'\x00\x00\x00\x00flag{Fear_can_hold_you_prisoner_Hope_can_set_you_free}\x06\x06\x06\x06\x06\x06'