# Wanna Champion 2024
> Nhan_laptop |
> --
> Trong lúc rảnh rỗi thì mình có nhìn lại giải của UIT tổ chức năm vừa rồi và chọn những chall mình thấy hay để làm lại.
## RAS - tvdat2004
chall:
```python!
from Crypto.Util.number import *
# from secret import flag
import random
flag = b'crypto{????????????????????????????}'
# print(len(flag))
class RAS(object):
def __init__(self, p, q):
self.p = p
self.q = q
self.n = (p**3 - p)*(q**3 - q)
"""
p ( p ** 2 - 1 ) q ( q ** 2 - 1 )
p ( p - 1 ) ( p + 1 ) q ( q - 1 ) q ( q + 1 )
"""
def generate_e(self):
e = random.randint(self.p * self.q, (self.p * self.q)**2)
return e
def encrypt(self, pt):
e = self.generate_e()
assert pt < self.n
c = pow(pt, e, self.n)
return e, c
flag1, flag2, flag3 = bytes_to_long(flag[:len(flag)//3]), bytes_to_long(flag[len(flag)//3:2*len(flag)//3]), bytes_to_long(flag[2*len(flag)//3:])
# shuffle it
m1 = flag1*flag2*flag3
m2 = flag1 + flag2 + flag3
m3 = flag1 * flag2 + flag2 * flag3 + flag3 * flag1
nbit = 256
menu = '''
Welcome to my RAS
1. Send primes
2. Get encrypted flag
'''
b = False
while True:
try:
choose = input(menu)
if choose == '1':
primes = input(f"Send me two {nbit}-bit strong primes, separated by comma: ")
try:
p, q = map(int, primes.strip().split(','))
except:
raise Exception("Invalid input")
if (isPrime(p) and isPrime(q) and
p != q and
p.bit_length() == q.bit_length() == nbit):
b = True
ras = RAS(p, q)
else:
print("Primes not strong enough!")
elif choose == '2':
if b:
print(ras.encrypt(m1))
print(ras.encrypt(m2))
print(ras.encrypt(m3))
else:
raise Exception("You must send strong primes first!!!")
else:
raise Exception("Invalid choice!!!")
except Exception as e:
print(f"Error: {str(e)}")
break
```
Tóm tắt là:
- Public key bài này là `n = (p ** 3 - p ) * ( q **3 -q )`
- Và cho mình không hạn lần để truy vấn
solve:
Và chú ý là mình kiểm soát được `p,q` nên chiến lược là mình sẽ lựa các p,q phù hợp rồi tìm `m_p, m_q` phù hợp với `phi_p, phi_q`.
### Part 1:
```python!
ps1 = []
ms1 = []
ps2 = []
ms2 = []
ps3 = []
ms3 = []
def decrypt(x,p):
e,c = x
if GCD(e ,p-1)!=1:
return None
phi = p-1
d = inverse(e,phi)
return pow(c,d,p)
while 1 :
p = getPrime(512)
q = getPrime(512)
resp = oracle(p,q)
m1 = decrypt(resp[0],p)
m2 = decrypt(resp[1],p)
m3 = decrypt(resp[2],p)
if m1 != None:
ms1.append(m1)
ps1.append(p)
if m2 != None:
ms2.append(m2)
ps2.append(p)
if m3 != None:
ms3.append(m3)
ps3.append(p)
m1 = decrypt(resp[0],q)
m2 = decrypt(resp[1],q)
m3 = decrypt(resp[2],q)
if m1 != None:
ms1.append(m1)
ps1.append(q)
if m2 != None:
ms2.append(m2)
ps2.append(q)
if m3 != None:
ms3.append(m3)
ps3.append(q)
print(len(ms3))
if len(ms3)> 80 and len(ms1) > 80 and len(ms2)> 80:
break
m1 = flag1*flag2*flag3
m2 = flag1 + flag2 + flag3
m3 = flag1 * flag2 + flag2 * flag3 + flag3 * flag1
assert m1 == crt(ms1,ps1)
assert m2 == crt(ms2,ps2)
assert m3 == crt(ms3,ps3)
```
Mình tìm được 3 giá trị chuẩn - trong code này mình đang cho các bạn biết thuật này đúng - cần truy vấn một lượng lớn mẫu `message_prime`,.
### Part 2:
```py!
m = [m1,m2,m3]
flag1,flag2,flag3 = PolynomialRing(ZZ,'x',3,order = 'lex').gens()
m1 = flag1*flag2*flag3 - m[0]
m2 = flag1 + flag2 + flag3 -m[1]
m3 = flag1 * flag2 + flag2 * flag3 + flag3 * flag1 -m[2]
sol = ideal([m1,m2,m3]).groebner_basis()
```
và biểu thức cuối của sol là :
```python!
x2^3 - 93081550437588504762415453164324824815512890448494127125481445*x2^2 + 105666576836626803617552219352359893258738438672438347484052785812492589634912853507595855810570916410282826314295714241368*x2 - 30113957810887199660425965901262837077808596976276277044244604618090976099024732025862764623637567079600132510545058461867624877630019579652029887142843302953305408592327770843664464
```
Và mình chỉ cần tìm trên này:
```python!
f = PolynomialRing(ZZ,'x2')
fi = f(sol[-1]).roots(multiplicities = False)
for i in fi[::-1]:
print(long_to_bytes(int(i)).decode(),end='')
# W1{wi3rd_ch41!En9e_n33d_4_WlErD_s0O!luti0n_6f339749663eeb3508c3b00c15872e41}
print()
```