# crypto
**Repository Path**: weiweqi/crypto
## Basic Information
- **Project Name**: crypto
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-01-19
- **Last Updated**: 2026-01-24
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Crypto
## 一、前置理论
### 1. 初等数论
#### 整数理论
- 整除定义和基本性质
- 带余数除法
- 辗转相除法
### 2. 同余基本知识
- 同余的定义和基本性质
**定义(同余)** 设 $m \neq 0$. 若 $m | a - b$,即 $a - b = km$,则称 $m$ 为**模**,并称 **$a$ 同余于 $b$ 模 $m$** 或 **$b$ 是 $a$ 对模 $m$ 的剩余**,记作
$$
a \equiv b \pmod m
$$
上式称为**模 $m$** 的同余式,简称**同余式**。转换为等式:$a = km + b$
**性质 1** 同余式一种等价关系,即有
$$
\begin{align}
& a \equiv a \pmod m \\
& a \equiv b \pmod m \Leftrightarrow b \equiv a \pmod m \\
& a \equiv b \pmod m, \ b \equiv c \pmod m \Rightarrow a \equiv c \pmod m
\end{align}
$$
### 同余式
### 模逆元
非零实数 $a\in\mathbf R$ 的乘法逆元就是它的倒数 $a^{-1}$.类似地,数论中也可以定义一个整数 $a$ 在模 $m$ 意义下的逆元 $a^{-1}\bmod m$,或简单地记作 $a^{-1}$.这就是 模逆元(modular multiplicative inverse),也称作 数论倒数.
**逆元**:对于非零整数 $a,m$,如果存在 $b$ 使得 $ab\equiv 1\pmod m$,就称 $b$ 是 $a$ 在模 $m$ 意义下的 逆元(inverse).
这相当于说,$b$ 是线性同余方程 $ax\equiv 1\pmod m$ 的解.根据 线性同余方程 的性质可知,当且仅当 $\gcd(a,m)=1$,即 $a,m$ 互素时,逆元 $a^{-1}\bmod m$ 存在,且在模 $m$ 的意义下是唯一的.
### 费马小定理
设 $p$ 是素数.对于任意整数 $p$ 且 $p\nmid a$,都成立 $a^{p-1} \equiv 1 \pmod p$.
设 $p$ 是素数.对于任意整数 $a$,都成立 $a^p \equiv a \pmod p$.
费马小定理的逆命题并不成立.即使对于所有与 $n$ 互素的 $a$,都有 $a^{n-1} \equiv 1 \pmod n$,那么,$n$ 也未必是素数.
### 欧拉函数
欧拉定理(Euler's theorem)将费马小定理推广到了一般模数的情形,但仍然要求底数与指数互素.
对于整数 $m>0$ 和整数 $a$,且 $\gcd(a,m)=1$,有 $a^{\varphi(m)}\equiv 1\pmod{m}$,其中,$\varphi(\cdot)$ 为 **欧拉函数**.
对于素数 $p$,有 $\varphi(p)=p-1$,因此,费马小定理是欧拉定理的一个特例.另外,欧拉定理中的指数 $\varphi(m)$ 在一般情形下并非使得该式成立的最小指数.它可以改进到 $\lambda(m)$,其中,$\lambda(\cdot)$ 是 **Carmichael 函数**.
### 扩展欧拉定理
扩展欧拉定理1进一步将结论推广到了底数与指数不互素的情形.由此,它彻底解决了任意模数下任意底数的幂次计算问题,将它们转化为指数小于 $\varphi(m)$ 的情形,从而可以通过 快速幂 在 $O(\log\varphi(m))$ 时间内计算.
### 欧几里得算法(辗转相除法)
已知两个数 $a$ 和 $b$,计算二者的最大公约数.
$\gcd(a,b)=\gcd(b,a \bmod b)$
```python
# 递归法
def gcd(a, b):
if b == 0:
return a
return gcd(b, a % b)
# 迭代法
def gcd(a, b):
while b != 0:
a, b = b, a % b
return a
# 辗转相减法(更相减损术)
def gcd(a, b):
while a != b:
if a > b:
a = a - b
else:
b = b - a
return a
```
### 扩展欧几里得算法(EXGCD)
扩展欧几里得算法(Extended Euclidean algorithm, EXGCD),常用于求 $ax+by=\gcd(a,b)$ 的一组可行解.
```python
def exgcd(a, b):
if b == 0:
return a, 1, 0
d, x, y = exgcd(b, a % b)
return d, y, x - (a // b) * y
```
### 线性同余方程
### 中国剩余定理(CRT)
**过程**
1. 计算所有模数的积 $n$;
2. 对于第 $i$ 个方程:
1. 计算 $m_i=\frac{n}{n_i}$;
2. 计算 $m_i$ 在模 $n_i$ 意义下的 逆元 $m_i^{-1}$;
3. 计算 $c_i=m_im_i^{-1}$(不要对 $n_i$ 取模).
3. 方程组在模 $n$ 意义下的唯一解为:$x=\sum_{i=1}^k a_ic_i \pmod n$.
```python
# 欧几里得算法
def egcd(a, b):
if a == 0:
return b, 0, 1
g, x1, y1 = egcd(b % a, a)
x = y1 - (b // a) * x1
y = x1
return g, x, y
# 模逆运算
def invmod(a, b):
g, x, y = egcd(a, b)
if g != 1:
raise ValueError('模逆不存在')
else:
return x % b
# 中国剩余定理
def crt(a, m):
for i in range(len(m)):
for j in range(i + 1, len(m)):
if egcd(m[i], m[j])[0] != 1:
print(f"m[{i}]和m[{j}]不互素,不能直接利用中国剩余定理")
sys.exit(1)
M = 1
for i in m:
M *= i
print(f"m = {M}")
M_j = [0] * len(m)
N_j = [0] * len(m)
x_j = [0] * len(m)
x_ans = 0
for j in range(len(m)):
M_j[j] = M // m[j]
N_j[j] = invmod(M_j[j], m[j])
x_j[j] = a[j] * M_j[j] * N_j[j] % M
print(f"M[{j}] = {M_j[j]}\nM[{j}]^-1 = {N_j[j]}\nx[{j}] = {x_j[j]}")
x_ans += x_j[j]
x_ans %= M
return x_ans % M
```
## 参考文献
1. [OI Wiki 数学部分](https://oi-wiki.org/math/)
2. [CTF Wiki Crypto部分](https://ctf-wiki.org/en/crypto/introduction/)
3. 初等数论(第四版)潘承洞,潘承彪编,北京大学出版社
4. 初等数论(第四版)闵嗣鹤、严士健编,高等教育出版社
## Python库和工具
- `openssl`
### 分解整数工具
- 网站分解:https://factordb.com/
- 命令行分解:https://github.com/ryosan-470/factordb-python
- yafu:https://sourceforge.net/projects/yafu/
- msieve:https://github.com/radii/msieve
### Python 工具
- `sympy`:[SymPy](https://docs.sympy.org/latest/index.html) 是一个用于符号数学的Python库,提供从基本符号算术到微积分、代数、离散数学和量子物理等领域的完整计算机代数系统功能。Crypto中主要使用素数操作、因数分解、最大公约数/最小公倍数等。
- `libnum`:提供整数操作、素数处理、模运算、RSA操作等常见数论和密码学功能,常用于字节转字符串、转数字。
- `pycryptodemo`:用于加解密
- `gmpy2`:
- `RSAtool`:https://github.com/ius/rsatool
```bash
# 安装 rsatool
git clone https://github.com/ius/rsatool.git
cd rsatool
pip install -r requirements.txt
python setup.py install
# 生成私钥
python rsatool.py -o prikey.pem -e 65537 -p 319576316814478949870590164193048041239 -q 275127860351348928173285174381581152299
# RSA爆破
python RsaCtfTool.py --publickey key.pem --uncipherfile cipher.bin
```
```bash
# 生成私钥, PEM output to key.pem:
python rsatool.py -f PEM -o key.pem -n 13826123222358393307 -d 9793706120266356337
# Supplying two primes, DER output to key.der:
python rsatool.py -f DER -o key.der -p 4184799299 -q 3303891593
```
- `RSA Converter`
## RSA
1. 选取两个不同的大素数 $p$ 和 $q$,计算 $N = p \cdot q$。
2. 根据欧拉函数,求得 $\varphi(N) = \varphi(pq) = \varphi(p)\varphi(q) = (p-1)(q-1)$
2. 然后取一个大整数 $e$,满足 $1 重要定理
- 若 $a \equiv b \pmod p$,则对任意的 c,都有 $(a+c) \equiv (b+c) \pmod p$
- 若 $a \equiv b \pmod p$,则对任意的 c,都有 $(a*c) \equiv (b*c) \pmod p$
- 若 $a \equiv b \pmod p$,$c \equiv d \pmod p$,则
- $(a+c) \equiv (b+d) \pmod p$
- $(a-c) \equiv (b-d) \pmod p$
- $(a*c) \equiv (b*d) \pmod p$
- $(a/c) \equiv (b/d) \pmod p$
### 逆元
在一个给定的模数 $p$ 下,如果存在一个数 $x$,使得数 $a$ 与 $x$ 相乘后对 $p$ 取模的结果为 $1$,那么 $x$ 就被称为 $a$ 的模乘法逆元(Modular Multiplicative Inverse)。公式表示如下:
$$
ax \equiv 1 \pmod p
$$
$x$ 就是 $a$ 在 模 $p$ 意义下的 逆元。
要求:
- $a$ 和 $m$ 互质,否则 $a$ 的逆元不存在。
- $x$ 的值通常在 $1$ 到 $m - 1$ 的范围内。
$a \pmod p$ 的逆元可以写作 $a * a' \pmod p \equiv 1$
### 推导过程
- 加密:式一 $c = m^e \mod N$
- 脱密:式二 $m = c^d \mod N$
将式一导入式二,得 $ m = (m^e \mod N)^d \mod N$
需要证明:$ m = (m^e \mod N)^d \mod N$
$$
\begin{align}
(m^e \mod N)^d \mod N &= (m^{e})^d \mod N \\
&= m^{ed} \mod N \\
&= m^{1 + k*\varphi(N)} \mod N \\
&= m*m^{k*\varphi(N)} \mod N \\
&= (m \mod N * m^{k*\varphi(N)} \mod N) \mod N \\
&= (m \mod N * (m^{\varphi(N)})^k \mod N) \mod N \\
&= (m \mod N * (m^{\varphi(N)} \mod N)^k \mod N) \mod N \\
&= (m \mod N * 1^k \mod N) \mod N \\
&= (m \mod N) \mod N \\
&= m \mod N \\
&= m \\
\end{align}
$$
1. 把 $a$ 看作 $m^e$,a ^ b % p = (a % p) ^ b % p
2. $e*d \equiv 1 \pmod {\varphi(N)}$
3. $e*d = 1 + k*\varphi(N)$
4. (a * b) % p = (a % p * b % p) % p
5. a ^ (b * c) = (a ^ b) ^ c
6. a ^ b % p = (a % p) ^ b % p
7. 欧拉定理 $a^{\varphi(n)} \mod n = 1$
8. $1^k \mod N = 1$
9. 因为 $m = c^d \mod N$,m是余数,$N$除数。而余数肯定小于除数,所以 $m < N$,$m \mod N = m$
## RSA攻击类型
模数相关攻击
- 暴力分解 N,条件:N 的比特位数小于 512。
- p 和 q 选取不当分解 N
- |p - q| 很大
- |p - q| 很小
- p - 1 光滑
- p + 1 光滑
- 模不互素:有两个公钥的 N 不互素,可对这两个数求最大公因数,然后直接获得 p 和 q。
- 共模攻击:有两个相同的 N、两个不同的e时,加密同一明文m。
公钥指数相关攻击
- 小公钥指数攻击:e 特别小,比如 e 为 3
- RSA 衍生算法——Rabin 算法:e = 2
私钥 d 相关攻击
- d 泄露攻击
- Wiener's Attack:在 $d$ 比较小($d < \frac{1}{3}N^{0.25}$)时,使用 Wiener's Attack 求解出 d。
Coppersmith 相关攻击
RSA 选择明密文攻击
RSA 侧信道攻击
Bleichenbacher's attack
### 模数相关攻击
#### 共模攻击
漏洞特征:n相同的,有两个e和两个c,两个e互素。
已知 n1,n2,e1,e2,c1,c2,要求n1 = n2,e1 和 e2 互素。
##### 原理
共模攻击基于扩展欧几里得算法。
扩展欧几里得算法:对于不完全为 0 的整数,$a,b,gcd(a, b)$,一定存在整数 x,y,使得 $gcd(a, b) = ax + by$.
```python
c1 = m1^e1 % n
c2 = m2^e2 % n
gcd(e1, e2) = 1
m1 = m2 = m
```
> 证明 ((c1^s1 % n) * (c2^s2 % n)) % n = m
```python
# 先去掉 最里面的 % n,根据:(a * b) % p = (a % p * b % p) % p
= ((c1^s1) * (c2^s2)) % n
# 将c1 和 c2 带入替换
= (((m1^e1 % n)^s1) * ((m2^e2 % n)^s2)) % n
# 最里面的 % n 移外面,根据:a ^ b % p = (a % p) ^ b % p
= (((m1^e1)^s1 % n) * ((m2^e2)^s2 % n)) % n
# 去掉 最里面的 % n,根据:(a * b) % p = (a % p * b % p) % p
= (((m1^e1)^s1) * ((m2^e2)^s2)) % n
# 合并指数幂,根据:(a^m)^n = a^(m*n)
= (m1^(e1*^s1) * m2^(e2*s2)) % n
# 因为 m1 = m2 = m,根据:a^m*a*n=a^(m+n)
= (m^(e1*s1+e2*s2)) % n
# 因为gcd(e1, e2)=1,根据扩展欧几里得算法,gcd(e1, e2)=e1*x+e2*y=1,
# 设x=s1,y=s2,即 gcd(e1, e2)=e1*^s1+e2*s2=1
= (m^1) % n
# 因为 c1 = m1^e1 % n > 0,所以 m < n => m % n = n
= m
```
#### 解题脚本
```python
import libnum
import gmpy2
n =
e1 =
e2 =
c1 =
c2 =
def exp_def(e1, e2, c1, c2, n):
s, s1, s2 = gmpy2.gcdext(e1, e2)
m = (pow(c1, s1, n) * pow(c2, s2, n)) % n
return int(m)
m = exp_def(e1, e2, c1, c2, n)
print(libnum.n2s(m))
```
### 维纳攻击(Wiener Attack)
漏洞特征:$e$ 过大或过小。
在 $e$ 过大或过小的情况下,可使用算法从 $e$ 中快速推断出 $d$ 的值。