点击此处获得更好的阅读体验
WriteUp来源
题目描述
题目考点
- RSA
解题思路
题目总共用了3种不同的rsa加密需要我们逐层求解。
考察了3种不同的rsa攻击加密
第一层
rsa加密使用的公钥n是3个质数的乘积,且3个质数具有一定的联系
1
2
3x = getPrime(290)
y = next_prime(21*x)
z = next_prime(3*x*y)
经过推算,可以发现最终的n约等于 21 * 21 * 3 * x**4
我们可以直接对 n 进行开发,得到近似的x的值。
1
guessx = iroot(n/(21*21*3),4)[0]
然后在附近进行爆破即可获得正确的x
完整的脚本如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15def generate(x):
y = next_prime(21*x)
z = next_prime(3*x*y)
n = x*y*z
return x,y,z,n
def solve_level1(n):
guessp = iroot(n/(21*21*3),4)[0]-1000
guessp = next_prime(guessp)
while True:
x,y,z,guessn = generate(guessp)
if n == guessn:
return x,y,z
else:
assert(guessn<n)
guessp = next_prime(guessp)
这样就分解了n1
第二层
第二层rsa使用的n是4个质数的积,同样这些质数之间存在关系
1
2
3
4o = getPrime(300)
s = getPrime(300)
t = next_prime(o)
u = next_prime(s)
next_prime意味着o和t,以及s和u之间是很相近的,我们可以假设
1
2t = o + m1
u = s + m2
m1和m2一般是1000以内的整数
这样我们就有
1
2n1 = o * s
n2 = (o+m1)*(s+m2)
由于m1和m2较小,我们可以直接爆破,在已知m1和m2的情况下,可以构造一元二次方程进行求解
完整脚本如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28def quadratic(ga,gb,gc,n):
delta=gb**2-4*ga*gc
if delta<=0 or ga==0:
return 0
tmp=iroot(delta,2)
if tmp[1]==True:
x1 = (-gb + tmp[0]) / (2*ga)
x2 = (-gb - tmp[0]) / (2 * ga)
if x1>0 and n%x1==0:
return x1
if x2>0 and n%x2==0:
return x2
return 0
def solve_level2(n,m):
for x in range(1500):
for y in range(1500):
a=y
b=x*y-m+n
c=x*n
tmp = quadratic(a,b,c,n)
if tmp!=0:
p = tmp
q = n/tmp
assert(p*q == n)
pp = p+x
qq = q+y
assert(pp*qq == m)
return p,q,pp,qq
这样就分解了n2
第三层
第三层的n是整行的两个大质数的积,但是这个题目没有给出加密公钥e。
同时注意到该题的e生成方式和奇怪
1
2
3
4s = getPrime(10)
if(gcd(s,p-1) == 1):
sinv = invert(s,p-1)
e = 4*s*sinv+3
根据模逆运算的性质,我们有
1
e % (p-1) = 4 + 3 = 7
因此对于加密的密文 pow(m,e)我们有
1
pow(m,e) % p = pow(m,7+k*(p-1)) % p = (pow(m,7) % p) *(pow(m,k*(p-1))%p) % p = pow(m,7) % p
因此有
1
2
3A = pow(m,e)-pow(m,7) = k * p
B = pow(m,e) = q * p
gcd(A,B) = p
分解了p和q之后 还需要恢复e
注意到生成e的中间变量 s是很小的,因此可以爆破。在有了p的情况下能很容易的根据s生成e并校验爆破的s是否正确。
代码如下
1
2
3
4
5
6
7
8
9
10
11
12def solve_level3(m,c,n):
p = gcd((c-pow(m,7)),n)
assert(n%p == 0)
q = n/p
while True:
s = getPrime(10)
if(gcd(s,p-1)):
sinv = invert(s,p-1)
e = 4*s*sinv+3
if pow(m,e,n) == c:
break
return e,p,q
解密
当n1,n2,n3都被分解了之后,可以很容易的根据rsa解密原理,计算出解密密钥并还原flag
Flag
1
flag{4c2fd4e6-44de-445f-8c34-1235464de2de}