密码挑战 - ^o^ writeup by AI
题目描述
这是一道密码学挑战题,给出了以下加密代码和输出参数:
python
from Crypto.Util.number import *
from secret import n,o,_,flag
def any(m):
return bytes_to_long(m)^o^pow(2,2**_,n)
print(n,o,_,any(flag))
已知参数
- n = 126176329335043454027341235009057683290541781096785538088437185779950106283534462102786883
- o = 22456023784134158064387550786352078427103553489348641216173010466267938277785173301732037264951635050700506776189809535326121257316490294752439819127486709456258090566784874248887194200916292508316349668172694553726134727726937633467532396106605496205841004277926961591604901357597262377953003319850049478502819166543968493292912201066602832545685929727421332846592671475883986049409546411338070434784675992855275254782158499562211464363321053581615280674425860714715529804670567409115827118589244016504450514019111124308126165185658681843519312254372108072512792854040590016772780908271525769845284796145687079308339
- _ = 1138895128842708275167
- encrypted_flag = 22456023784134158064387550786352078427103553489348641216173010466267938277785173301732037264951635050700506776189809535326121257316490294752439819127486709456258090566784874248887194200916292508316349668172694553726134727726937633467532396106605496205841004277926961591604901357597262377953003319850049478502819166543968493292912201066602832545685929727421332846592671475883986049409546411338070434784675992855275254782158499562211464363321053581615280674425860714715529804670567409115827118589244016504450514019111124308126165145471041075065947806083270394708336810934202426175949363009508477208686445248781032485832
考点分析
- 异或运算的性质 :
A ^ B ^ C = D⇒A = D ^ B ^ C - 欧拉定理 :当
gcd(a, n) = 1时,a^φ(n) ≡ 1 (mod n) - 大整数因子分解:使用 Pollard's rho 算法
- 模幂运算优化:利用欧拉函数简化超大指数计算
解题思路
1. 分析加密公式
加密函数:
python
def any(m):
return bytes_to_long(m) ^ o ^ pow(2, 2**_, n)
解密公式(利用异或性质):
python
bytes_to_long(flag) = encrypted_flag ^ o ^ pow(2, 2**_, n)
2. 关键难点
直接计算 pow(2, 2**_, n) 是不可能的,因为:
_ = 1138895128842708275167(70 位)2**_是一个天文数字(2 的 10^21 次方)- 无法直接存储或计算这么大的指数
3. 使用欧拉定理优化
根据欧拉定理:
- 若
gcd(a, n) = 1,则a^φ(n) ≡ 1 (mod n) - 因此
a^b mod n = a^(b mod φ(n)) mod n
所以:pow(2, 2**_, n) = pow(2, 2**_ mod φ(n), n)
现在问题转化为:
- 分解 n,计算 φ(n)
- 计算
2**_ mod φ(n) - 计算
pow(2, 结果,n)
4. 分解 n
n 是 296 位的大整数,使用 Pollard's rho 算法成功分解为 10 个素因子:
n = 806952673 × 648863389 × 973139887 × 914351299 × 611738359
× 834612803 × 856368371 × 940957051 × 775357619 × 848994661
5. 计算 φ(n)
对于多素因子的情况:
φ(n) = n × ∏(1 - 1/p) = n × (p1-1)/p1 × (p2-1)/p2 × ... × (pk-1)/pk
6. 逐步计算
python
# 步骤 1: 计算 2**_ mod φ(n)
exp_mod = pow(2, _, phi)
# 步骤 2: 计算 pow(2, exp_mod, n)
power_result = pow(2, exp_mod, n)
# 步骤 3: 解密 flag
flag_long = encrypted_flag ^ o ^ power_result
flag = long_to_bytes(flag_long)
详细步骤
步骤 1: 实现 Pollard's rho 算法分解 n
python
def pollard_rho(n):
if n % 2 == 0:
return 2
x = 2
y = 2
d = 1
c = 1
def f(x):
return (x * x + c) % n
while d == 1:
x = f(x)
y = f(f(y))
d = math.gcd(abs(x - y), n)
if d != 1 and d != n:
return d
if x == y:
c += 1
x = 2
y = 2
d = 1
return d
步骤 2: 递归分解获取所有素因子
python
def factorize(n):
if n == 1:
return []
if isPrime(n):
return [n]
# 试除法检查小素数
small_primes = [2, 3, 5, 7, 11, ...]
for p in small_primes:
if n % p == 0:
return [p] + factorize(n // p)
# 使用 Pollard's rho
factor = pollard_rho(n)
return factorize(factor) + factorize(n // factor)
步骤 3: 计算 φ(n)
python
factors = factorize(n) # 得到 10 个素因子
phi = n
unique_factors = set(factors)
for p in unique_factors:
phi = phi // p * (p - 1)
步骤 4: 使用欧拉定理简化指数
python
# 计算 2**_ mod φ(n)
exp_mod = pow(2, _, phi)
# 计算 pow(2, exp_mod, n)
power_result = pow(2, exp_mod, n)
步骤 5: 解密 flag
python
flag_long = encrypted_flag ^ o ^ power_result
flag = long_to_bytes(flag_long)
完整代码
python
from Crypto.Util.number import *
import math
def pollard_rho(n):
"""Pollard's rho 算法分解大整数"""
if n % 2 == 0:
return 2
x = 2
y = 2
d = 1
c = 1
def f(x):
return (x * x + c) % n
while d == 1:
x = f(x)
y = f(f(y))
d = math.gcd(abs(x - y), n)
if d != 1 and d != n:
return d
# 如果失败,改变参数重试
if x == y:
c += 1
x = 2
y = 2
d = 1
return d
def factorize(n):
"""递归分解 n"""
if n == 1:
return []
if isPrime(n):
return [n]
# 试除法检查小素数
small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
for p in small_primes:
if n % p == 0:
return [p] + factorize(n // p)
# 使用 Pollard's rho
factor = pollard_rho(n)
if factor == n:
print(f"无法分解:{n}")
return [n]
return factorize(factor) + factorize(n // factor)
def solve():
# 已知参数
n = 126176329335043454027341235009057683290541781096785538088437185779950106283534462102786883
o = 22456023784134158064387550786352078427103553489348641216173010466267938277785173301732037264951635050700506776189809535326121257316490294752439819127486709456258090566784874248887194200916292508316349668172694553726134727726937633467532396106605496205841004277926961591604901357597262377953003319850049478502819166543968493292912201066602832545685929727421332846592671475883986049409546411338070434784675992855275254782158499562211464363321053581615280674425860714715529804670567409115827118589244016504450514019111124308126165185658681843519312254372108072512792854040590016772780908271525769845284796145687079308339
_ = 1138895128842708275167
encrypted_flag = 22456023784134158064387550786352078427103553489348641216173010466267938277785173301732037264951635050700506776189809535326121257316490294752439819127486709456258090566784874248887194200916292508316349668172694553726134727726937633467532396106605496205841004277926961591604901357597262377953003319850049478502819166543968493292912201066602832545685929727421332846592671475883986049409546411338070434784675992855275254782158499562211464363321053581615280674425860714715529804670567409115827118589244016504450514019111124308126165145471041075065947806083270394708336810934202426175949363009508477208686445248781032485832
print("=== 分解 n ===")
factors = factorize(n)
print(f"因子:{factors}")
if len(factors) == 2:
p, q = sorted(factors, reverse=True)
print(f"\np = {p}")
print(f"q = {q}")
# 计算 φ(n)
phi = (p - 1) * (q - 1)
print(f"\nφ(n) = {phi}")
# 计算 2**_ mod φ(n)
print(f"\n=== 计算指数 ===")
exp_mod = pow(2, _, phi)
print(f"2**_ mod φ(n) = {exp_mod}")
# 计算 pow(2, 2**_, n)
print(f"\n=== 计算幂 ===")
power_result = pow(2, exp_mod, n)
print(f"pow(2, 2**_, n) = {power_result}")
# 解密
print(f"\n=== 解密 ===")
flag_long = encrypted_flag ^ o ^ power_result
print(f"flag_long = {flag_long}")
# 转换为字节
flag_bytes = long_to_bytes(flag_long)
print(f"flag = {flag_bytes}")
# 尝试打印为字符串
try:
flag_str = flag_bytes.decode('utf-8')
print(f"flag (文本) = {flag_str}")
except:
print("无法解码为 UTF-8")
# 检查是否包含可打印字符
printable = all(32 <= b < 127 or b in [10, 13, 9] for b in flag_bytes)
print(f"是否全为可打印字符:{printable}")
else:
print(f"因子数量不是 2,无法继续:{len(factors)}")
if __name__ == "__main__":
solve()
总结
这道题的核心在于:
- 识别异或运算的可逆性:加密过程全是异或操作,解密只需再次异或相同值
- 处理超大指数 :
2**(10^21)无法直接计算,必须使用数学优化 - 欧拉定理的应用 :
a^b mod n = a^(b mod φ(n)) mod n - 大整数分解:296 位的 n 虽然很大,但它是多个小素数的乘积,可以用 Pollard's rho 算法快速分解
- 多素因子的φ(n) 计算:当 n 有多个不同素因子时,需要正确应用公式
关键公式回顾:
- 加密:
ciphertext = flag_long ^ o ^ pow(2, 2**_, n) - 解密:
flag_long = ciphertext ^ o ^ pow(2, 2**_, n) - 欧拉定理:
pow(2, 2**_, n) = pow(2, pow(2, _, φ(n)) % φ(n), n)
提问
请阅读代码,解出这道CTF题目。