# [CH] Ultra Easy RSA
###### tags: `Writeup` `Crypto` `Chinese`
> [name=Curious]
## 先備知識
### 費馬分解
$p$ 和 $q$ 是 $n$ 的兩個因數,如果 $|p - q|$ 很小,可以假設 $p \gt q$
$$
\begin{cases}
p = a + b\\
q = a - b
\end{cases}
\;\Rightarrow\;
n = pq = a^2 - b^2
\;\Rightarrow\;
n + b^2 = a^2
$$
因為 $p - q$ 很小,所以 $b$ 也會很小,所以可以讓 $a$ 是
$$
\sqrt n + 1, \sqrt n + 2, \sqrt n + 3, ...
$$
當 $\sqrt{a^2 - n} \in \mathbb N$ 時,就可以計算得知 $a$ 和 $b$,進而分解 $n$
---
## 思路和解法
從 `chal.py` 可以看到 `p` 和 `q` 都是由 `base + 1` 加上一個 32 bits 的質數構建而來的,所以 `p` 和 `q` 基本上不會距離很遠,所以可以用費馬分解來分解 `n`,分解之後就可以計算出密鑰 `d` 來解密 `c`
> 實際上可以直接把 `n` 那去 http://factordb.com 就可以分解出 `p` 和 `q` 了
Solve Script :
```python=
from gmpy2 import isqrt, iroot
from Crypto.Util.number import long_to_bytes
def fermat_factor(n: int):
"""
- input : `n (int)`
- output : `(p, q) (int, int)`
"""
a = int(isqrt(n)) + 1
b = iroot(a ** 2 - n, 2)
while not b[1]:
a += 1
b = iroot(a ** 2 - n, 2)
print(a)
b = int(b[0])
return (a - b), (a + b)
n = ...
e = 65537
c = ...
p, q = fermat_factor(n)
d = pow(e, -1, (p - 1) * (q - 1))
m = pow(c, d, n)
print(long_to_bytes(m))
```
{%hackmd M1bgOPoiQbmM0JRHWaYA1g %}