# [crypto] Party Ticket - CakeCTF 2021
###### tags: `CakeCTF 2021`
## overview
$C_i = M(M + B_i) \mod N_i$ という式が2つある。言うまでもなくこれはRabin Cryptosystem
```python=
from Crypto.Util.number import getPrime, isPrime
import random
def getSafePrime(bits):
while True:
p = getPrime(bits - 1)
q = 2*p + 1
if isPrime(q):
return q
def make_inivitation():
with open("flag.txt", "rb") as f:
m = int.from_bytes(f.read().strip(), "big")
p = getSafePrime(512)
q = getSafePrime(512)
n = p * q
b = random.randint(2, n-1)
c = m*(m + b) % n
return c, n, b
# print("Dear Moe:")
print(make_inivitation())
# print("Dear Lulu:")
print(make_inivitation())
```
## solution
Rabin Cryptosystemは$e = 2$のRSAの素朴な変形のように捉えることもできる。Padding付きの平文に対するHastad's Broadcast Attackが適用できる
$f_1(x) = x^2 + xb_1 - c_1, f_2(x) = x^2 + xb_2 - c_2$とすると、$f_1, f_2$はそれぞれ$\mod n_1, \mod n_2$で$m$を根に持つ
ここで$\mod n_1$で$1$、$\mod n_2$で$0$となるような$k_1$と$\mod n_1$では$0$、$\mod n_2$では$1$となるような$k_2$を考えて$f = k_1f_1 + k_2f_2$とする
すると$f(m) \equiv 0 \mod n_1$, $f(m) \equiv 0 \mod n_2$より、$f(m) \equiv 0 \mod n_1n_2$ であるから、$m$は$f$の$\mod n_1n_2$での根であることがわかる。$m < n_1, n_2 < n_1n_2$であるから、およそ$m < (n_1n_2)^{1/2}$であり、$f$の次数が2であることを考えると十分小さい。
したがって、$f$を定義して$\mod n_1n_2$でのsmall_rootを求めることで$m$が求まる。
```python=
import ast
with open("./distfiles/output.txt") as f:
c1, n1, b1 = ast.literal_eval(f.readline().strip())
c2, n2, b2 = ast.literal_eval(f.readline().strip())
N = n1 * n2
PR.<x> = PolynomialRing(Zmod(N))
k1 = crt([1, 0], [n1, n2])
k2 = crt([0, 1], [n1, n2])
f1 = x*(x + b1) - c1
f2 = x*(x + b2) - c2
f = k1*f1 + k2*f2
f = f.monic()
for root in f.small_roots():
print(int(root).to_bytes(100, "big").strip(b"\0"))
```