from Crypto.Util.number import getPrime, bytes_to_long import gmpy2
# 生成小d的RSA密钥 defgenerate_weak_key(): whileTrue: p = getPrime(512) q = getPrime(512) n = p * q phi = (p-1)*(q-1) # 寻找小d d = gmpy2.next_prime(1 << 100) # 小d try: e = gmpy2.invert(d, phi) if e.bit_length() == n.bit_length(): return n, e, d except: continue
n, e, d = generate_weak_key() m = bytes_to_long(b"flag{This_is_a_test_flag}") c = pow(m, e, n)
import gmpy2 from Crypto.Util.number import long_to_bytes
defcommon_modulus_attack(c1, c2, e1, e2, n): gcd, x, y = gmpy2.gcdext(e1, e2) if gcd != 1: returnNone if x < 0: c1 = gmpy2.invert(c1, n) x = -x if y < 0: c2 = gmpy2.invert(c2, n) y = -y m = (pow(c1, x, n) * pow(c2, y, n)) % n return m
import gmpy2 from Crypto.Util.number import long_to_bytes
defdp_leak_attack(e, n, c, dp, max_x=1000000): k = e * dp - 1 for x inrange(1, max_x): if k % x != 0: continue p = (k // x) + 1 if n % p == 0: q = n // p d = gmpy2.invert(e, (p-1)*(q-1)) m = pow(c, d, n) return m returnNone
n = # 从题目获取 e = # 从题目获取 c = # 从题目获取 dp = # 从题目获取
m = dp_leak_attack(e, n, c, dp) if m isnotNone: print(long_to_bytes(int(m)))
题型 5 Pollard p-1 分解
数学 若 p-1 所有素因子均 < B,则 a^(B!) ≡ 1 mod p ⇒ gcd(a^(B!) - 1, n) 非平凡
from Crypto.Util.number import getPrime, bytes_to_long import gmpy2
# 生成p-1光滑的素数 defgenerate_smooth_prime(bits, smoothness): whileTrue: p = 2 for i inrange(2, smoothness): p *= i p = gmpy2.next_prime(p) if gmpy2.is_prime(p) and p.bit_length() == bits: return p
# 使用小素数生成p,使其p-1光滑 p = generate_smooth_prime(512, 1000) q = getPrime(512) n = p * q e = 65537
m = bytes_to_long(b"flag{This_is_a_test_flag}") c = pow(m, e, n)
import gmpy2 from Crypto.Util.number import long_to_bytes
defcca_attack(decrypt_oracle, c, e, n): s = gmpy2.mpz_random(gmpy2.random_state(), n) c_prime = (c * pow(s, e, n)) % n m_prime = decrypt_oracle(c_prime) if m_prime == b"Filtered: contains flag": returnNone m = (m_prime * gmpy2.invert(s, n)) % n return m
n = # 从题目获取 e = # 从题目获取 c = # 从题目获取
# 假设decrypt_oracle是远程服务 m = cca_attack(decrypt_oracle, c, e, n) if m isnotNone: print(long_to_bytes(m))
题型 8 已知 p 高位攻击
数学 已知 p 的高位部分,设未知部分为 x,则 p = p_high + x,可建立方程: (p_high + x) * q = n 利用 Coppersmith 方法求小根。
加密脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
from Crypto.Util.number import getPrime, bytes_to_long import gmpy2
p = getPrime(512) q = getPrime(512) n = p * q e = 65537
# 只泄露p的高位(前400位) p_high = p >> 112# 512-400=112,保留高位
m = bytes_to_long(b"flag{This_is_a_test_flag}") c = pow(m, e, n)
#!/usr/bin/env python3 import gmpy2 from Crypto.Util.number import long_to_bytes
e = 0x10001 n = # 从题目获取 dp = # 从题目获取 c = # 从题目获取
defdp_leak_attack(e, n, c, dp, max_x=1000000): k = e * dp - 1 for x inrange(1, max_x): if k % x != 0: continue p = (k // x) + 1 if n % p == 0: q = n // p d = gmpy2.invert(e, (p-1)*(q-1)) m = pow(c, d, n) return m returnNone
m = dp_leak_attack(e, n, c, dp) if m isnotNone: print(long_to_bytes(int(m)))