0%

RSA进阶

之前学了点Coopersmith,但感觉似懂非懂,现在再学一遍后,很多知识有了新的理解。

也感谢网上一些详细易懂的资源!

Coopersmith方法

首先需要了解一些前置的代数知识

  1. 环:抽象代数中,不仅将具体的值当做操作对象进行运算,还把运算符和运算规则也作为一种操作对象进行运算,环就是这样的一个代数系统,它包含两种运算(加法和乘法),但具体运算和环定义有关

  2. 有限域(伽罗瓦域)

    存在乘法逆元的环是域,在模p下成立的域是有限域。

对于一个模n意义下的e阶多项式,Coopersmith方法可以求解得到两种根:

也就是说,我们可以求出模多项式的一个小根。

并且,如果题中给出一个模p的多项式,但没有给出p,直接模n也能得到结果。

题目1:m高位泄露

假设m高位是m1,低位为x,

根据c=m^e(mod n)

构造模多项式P(x)=(m1+x)^e−c(modn)

当x<n^1/e时,就能够用coopersmith进行求解得到m

1
2
3
4
5
6
7
8
9
10
11
12
13
#Sage
n =
e =
c =
mbar =
kbits =
beta = 1
nbits = n.nbits()
print("upper {} bits of {} bits is given".format(nbits - kbits, nbits))
PR.<x> = PolynomialRing(Zmod(n))
f = (mbar + x)^e - c
x0 = f.small_roots(X=2^kbits, beta=1)[0] # find root < 2^kbits with factor = n
print("m:", mbar + x0)

题目2:p高位泄露

假设有模p多项式为f(x)=x (mod p)

但没有p值,也就求不出来模p多项式下的根x,

但根据Coopersmith的第二条,我们可以构建一个模n多项式,这样不仅可以求解模n多项式的小根,还能求解n的因数的小根,此时需要满足p>=n^b(知道p高位是p的位数约1/2就行)

假设p_h为p高位,令p=p_h+x,

如果x足够小,我们可以求出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#Sage
n =
p4 = #p去0的剩余位
pbits = 1024
kbits = pbits - p4.nbits()
print(p4.nbits())
p4 = p4 << kbits
PR.<x> = PolynomialRing(Zmod(n))
f = x + p4
roots = f.small_roots(X=2^kbits, beta=0.4)
if roots:
p = p4 + int(roots[0])
q = n//p
print(f'n: {n}')
print(f'p: {p}')
print(f'q: {q}')

题目3:d低位泄露

首先我们知道一个条件

  1. 在二进制里,一个数除以2^a的余数就是它的低a位

假设d_l为d的低位,且d_l位数为a位,有

又因为ed=1+kphi_n,ed约等于k phi_n,而d<phi_n,e也小,所以k必须小,猜测k和e差不多大,就得到k在[1,e)中,遍历得到k。

然后只剩下一个未知数p,通过求解模多项式得到p。

此时我们可以将左边看做一个整体为p_l,显然p_l为p的最低a位,也就是

Rabin算法

明白下面这些定理之后可以更好地理解rabin算法

定理1:欧拉判别定理

证明充分性

证明必要性(不太严谨)

定理2:

定理3:

如果整数c满足:

1) c为 p的平方剩余

2) c为 q的平方剩余

则:c 为 p*q的平方剩余

参考Van1sh的博客https://jayxv.github.io

Rabin加密

已知p,q为私钥,n=p*q为公钥,密文c

​ c=m^2%n

c=m^2%n等价于c=m^2%p,c=m^2%q

根据上述定理3,用中国剩余定理解出m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import gmpy2

def rabin_decrypt(c, p, q, e=2):
n = p * q
mp = pow(c, (p + 1) // 4, p)
mq = pow(c, (q + 1) // 4, q)
yp = gmpy2.invert(p, q)
yq = gmpy2.invert(q, p)
r = (yp * p * mq + yq * q * mp) % n
rr = n - r
s = (yp * p * mq - yq * q * mp) % n
ss = n - s
return (r, rr, s, ss)

c =
p =
q =
m = rabin_decrypt(c,p,q)
for i in range(4):
try:
print(bytes.fromhex(hex(m[i])[2:]))
except:
pass

参考Lazzaro师傅的博客 https://lazzzaro.github.io

参考Van1sh的博客https://jayxv.github.io

参考NSS密码工坊课程RSA(四)

-------------本文结束感谢您的阅读-------------