Easy_RSA - Writeup by AI
题目信息
- 来源: Bugku CTF
- 类别: Crypto (密码学)
- 文件: file.txt
题目描述
Hey, you're a hacker, right? I think I am too, look at what I made!
-----------
(2531257, 43)
My super secret message: 906851 991083 1780304 2380434 438490 356019 921472 822283 817856 556932 2102538 2501908 2211404 991083 1562919 38268
-----------
Problem is, I don't remember how to decrypt it... could you help me out?
考点分析
| 考点 | 权重 | 说明 |
|---|---|---|
| RSA基础原理 | 30% | 理解RSA加密解密流程 |
| 小模数分解 | 25% | n较小时可直接分解获取私钥 |
| 编码识别 | 25% | 识别非标准的ASCII编码方式 |
| 模式分析 | 20% | 通过部分解密结果推测完整Flag |
技术背景:
- 标准RSA加密:
c = m^e mod n - RSA安全性依赖于大整数分解的困难性
- 当n较小时(如本题n≈2^21),可以通过试除法快速分解
解题思路
攻击策略
- 分解模数n: 由于n=2531257相对较小,使用试除法分解
- 计算私钥d: 利用扩展欧几里得算法求模逆元
- 标准RSA解密 :
m = c^d mod n - 编码分析: 识别明文数值的编码规则
- 模式推断: 根据已知字符推测完整Flag
技术路线
file.txt → 提取参数(n,e,密文) → 分解n得到p,q
→ 计算φ(n)和私钥d → RSA解密得到明文数值
→ 分析编码规则 → 还原Flag
详细步骤
步骤1: 提取RSA参数
从题目文件中提取:
- 公钥 :
(n=2531257, e=43) - 密文序列: 16个数字
python
n = 2531257
e = 43
ciphertexts = [906851, 991083, 1780304, 2380434, 438490, 356019,
921472, 822283, 817856, 556932, 2102538, 2501908,
2211404, 991083, 1562919, 38268]
步骤2: 分解模数n
由于n只有约21位(2531257 ≈ 2^21.3),可以使用试除法快速分解:
python
import math
def factorize(n):
for i in range(2, int(math.isqrt(n)) + 1):
if n % i == 0:
p = i
q = n // i
return p, q
return None, None
p, q = factorize(n)
# 结果: p = 509, q = 4973
# 验证: 509 × 4973 = 2531257 ✓
步骤3: 计算私钥d
使用RSA密钥生成公式:
python
# 计算欧拉函数
phi_n = (p - 1) * (q - 1)
# phi_n = 508 × 4972 = 2525776
# 扩展欧几里得算法求模逆元
def extended_gcd(a, b):
if a == 0:
return b, 0, 1
gcd, x1, y1 = extended_gcd(b % a, a)
x = y1 - (b // a) * x1
y = x1
return gcd, x, y
def mod_inverse(e, phi):
gcd, x, _ = extended_gcd(e % phi, phi)
if gcd != 1:
raise Exception('模逆元不存在')
return x % phi
d = mod_inverse(e, phi_n)
# 结果: d = 58739
# 验证: e×d mod φ(n) = 43×58739 mod 2525776 = 1 ✓
步骤4: RSA解密
对每个密文执行标准RSA解密 m = c^d mod n:
python
plaintexts = [pow(c, d, n) for c in ciphertexts]
# 解密结果:
# [103, 105103, 101109, 12383, 97118, 97103, 10195, 83105,
# 12095, 70108, 121105, 110103, 9584, 105103, 101114, 115125]
步骤5: 分析编码规则
观察解密后的数值,发现它们不是直接的ASCII码,而是多个ASCII码的十进制拼接:
| 索引 | 明文数值 | 分解方式 | ASCII码 | 字符 |
|---|---|---|---|---|
| 0 | 103 | 103 | 'g' | g |
| 1 | 105103 | 105+103 | 'i'+'g' | ig |
| 2 | 101109 | 101+109 | 'e'+'m' | em |
| 3 | 12383 | 123+83 | '{'+'S' | {S |
| 4 | 97118 | 97+118 | 'a'+'v' | av |
| 5 | 97103 | 97+103 | 'a'+'g' | ag |
| 6 | 10195 | 101+95 | 'e'+'_' | e_ |
| 7 | 83105 | 83+105 | 'S'+'i' | Si |
| 8 | 12095 | 120+95 | 'x'+'_' | x_ |
| 9 | 70108 | 70+108 | 'F'+'l' | Fl |
| 10 | 121105 | 121+105 | 'y'+'i' | yi |
| 11 | 110103 | 110+103 | 'n'+'g' | ng |
| 12 | 9584 | 95+84 | '_'+'T' | _T |
| 13 | 105103 | 105+103 | 'i'+'g' | ig |
| 14 | 101114 | 101+114 | 'e'+'r' | er |
| 15 | 115125 | 115+125 | 's'+'}' | s} |
编码规则: 将1-2个字符的ASCII码(十进制表示)直接拼接成一个整数。
例如:
'ig'→ ASCII: 105, 103 → 拼接:105103'{S'→ ASCII: 123, 83 → 拼接:12383
步骤6: 还原Flag
将所有解码后的字符片段拼接:
g + ig + em + {S + av + ag + e_ + Si + x_ + Fl + yi + ng + _T + ig + er + s}
= gigem{Savage_Six_Flying_Tigers}
完整代码
python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Easy_RSA - CTF解题脚本
"""
import math
def extended_gcd(a, b):
"""扩展欧几里得算法"""
if a == 0:
return b, 0, 1
gcd, x1, y1 = extended_gcd(b % a, a)
x = y1 - (b // a) * x1
y = x1
return gcd, x, y
def mod_inverse(e, phi):
"""计算模逆元 d = e^(-1) mod phi"""
gcd, x, _ = extended_gcd(e % phi, phi)
if gcd != 1:
raise Exception('模逆元不存在')
return x % phi
def factorize(n):
"""试除法分解n"""
for i in range(2, int(math.isqrt(n)) + 1):
if n % i == 0:
return i, n // i
return None, None
def solve():
# RSA参数
n = 2531257
e = 43
# 密文序列
ciphertexts = [906851, 991083, 1780304, 2380434, 438490, 356019,
921472, 822283, 817856, 556932, 2102538, 2501908,
2211404, 991083, 1562919, 38268]
print("[*] Step 1: 分解模数n")
p, q = factorize(n)
print(f" p = {p}, q = {q}")
print(f" 验证: {p} × {q} = {p*q}")
print("\n[*] Step 2: 计算私钥d")
phi_n = (p - 1) * (q - 1)
d = mod_inverse(e, phi_n)
print(f" φ(n) = {phi_n}")
print(f" d = {d}")
print(f" 验证: e×d mod φ(n) = {(e*d) % phi_n}")
print("\n[*] Step 3: RSA解密")
plaintexts = [pow(c, d, n) for c in ciphertexts]
for i, m in enumerate(plaintexts):
print(f" [{i:2d}] {m}")
print("\n[*] Step 4: 分析编码并还原Flag")
# 根据分析,分组解码
groups = [
'g', 'ig', 'em', '{S', 'av', 'ag', 'e_',
'Si', 'x_', 'Fl', 'yi', 'ng', '_T', 'ig', 'er', 's}'
]
flag = ''.join(groups)
print(f"\n[+] Flag: {flag}")
# 最终验证
print("\n[*] Step 5: 验证Flag")
encoded_nums = []
for group in groups:
num = int(''.join(str(ord(c)) for c in group))
encoded_nums.append(num)
encrypted = [pow(m, e, n) for m in encoded_nums]
if encrypted == ciphertexts:
print(" ✓✓✓ 加密验证通过!Flag确认无误! ✓✓✓")
else:
print(" [-] 验证失败")
if __name__ == "__main__":
solve()
运行结果
[*] Step 1: 分解模数n
p = 509, q = 4973
验证: 509 × 4973 = 2531257
[*] Step 2: 计算私钥d
φ(n) = 2525776
d = 58739
验证: e×d mod φ(n) = 1
[*] Step 3: RSA解密
[ 0] 103
[ 1] 105103
...
[*] Step 4: 分析编码并还原Flag
[+] Flag: gigem{Savage_Six_Flying_Tigers}
[*] Step 5: 验证Flag
✓✓✓ 加密验证通过!Flag确认无误! ✓✓✓