第一次做到以不经意传输(Oblivious transfer)为背景的题目,记录一下. 本题基于 RSA,类似的题目还有
题目代码
from Crypto.Util.number import bytes_to_long, getPrime
from secrets import randbelow
from hashlib import shake_128
flag1 = b"fake{flag-1}"
flag2 = b"fake{flag-2}"
def gen():
e = 65537
nbits = 1024
p = getPrime(nbits)
while p % e == 1:
p = getPrime(nbits)
q = getPrime(nbits)
while q % e == 1:
q = getPrime(nbits)
n = p * q
phi = (p - 1) * (q - 1)
d = pow(e, -1, phi)
return n, e, d, p, q
level = int(input("Please select the level[1/2]: "))
assert level in [1, 2]
n, e, d, p, q = gen()
if level == 1:
f = bytes_to_long(flag1 + shake_128(flag1).digest(128-len(flag1)))
else:
f = bytes_to_long(flag2 + shake_128(flag2).digest(128-len(flag2)))
x0 = randbelow(n)
x1 = randbelow(n)
print(f"{n = }")
print(f"{e = }")
print(f"{x0 = }")
print(f"{x1 = }")
print("Which message do you want to know?")
v = int(input("v = "))
if level == 1:
v0 = (pow(v-x0, d, n) + pow(p+q, d, n) + f) % n
v1 = (pow(v-x1, d, n) + pow(p-q, d, n) + f) % n
else:
v0 = (pow(v-x0, d, n) + pow(p+q, d, n) + f) % n
v1 = (pow(v-x1, d, n) + pow(p-q, d, n) + pow(f, -1, n)) % n
print()
print(f"{v0 = }")
print(f"{v1 = }")
Flag 1
{v0v1≡(v−x0)d+(p+q)d+f≡(v−x1)d+(p−q)d+f(modn)(modn)
两式都有 f,考虑作差
v0−v1=(v−x0)d−(v−x1)d+(p+q)d−(p−q)d(modn)
由二项式定理
(p+q)d−(p−q)d=2k odd∑(kd)pd−kqk=K⋅q
把模数换到 q 下有
v0−v1=(v−x0)d−(v−x1)d(modq)
此时考虑 v 的取值,让右侧尽量简单,尝试
(v−x0)d=−(v−x1)d
由于 d 为奇数,那么 v−x0=−(v−x1),即 v=2x0+x1.
此时有
v0−v1(v0−v1)e(v0−v1)eK′⋅q=2(v−x0)d(modq)=2e(v−x0)(modq)=2e(v−x0)+K′⋅q=(v0−v1)e−2e(v−x0)
计算 GCD(K′⋅q,n) 即分解 n. 接下来不难求得 f.
Flag 2
{v0v1≡(v−x0)d+(p+q)d+f≡(v−x1)d+(p−q)d+f−1(modn)(modn)
仍取 v=2x0+x1,有
v0+v1v0+v1v0+v1≡(v−x0)d+(v−x1)d+(p+q)d+(p−q)d+f+f−1≡(v−x0)d+(−1)d(v−x0)d+(p+q)d+(p−q)d+f+f−1≡(p+q)d+(p−q)d+f+f−1(modn)(modn)(modn)
由二项式定理
(p+q)d+(p−q)d=K⋅p
把模数换到 p 下有
v0+v1f2−(v0+v1)f+1≡f+f−1≡0(modp)(modp)
这里 f 是 1024-bit 的,相对于 p 不够小. 可以多取几组数据构成方程组
⎩⎨⎧f2−g0⋅f+1f2−g1⋅f+1f2−g2⋅f+1≡0≡0⋯≡0(modp0)(modp1)(modp5)
应用多项式的中国剩余定理得到
f2−g⋅f+1≡0(modp0p1⋯p5)(1)
注意这里的模数实际上我们是不知道的,不过 CopperSmith 算法的扩展 允许我们在模数未知的情况下求小根,也就是对 (2) 式应用 CopperSmith
f2−g⋅f+1≡0(modn0n1⋯n5)(2)
能够求出 (1) 式的小根,注意这里令 β=61.
这种解「模单变量多项式方程组」的问题被称为 SMUPE-problem,N1CTF 2022-babyecc 也是类似的姿势~