Rsa基础知识

1
rsa是经常出现在ctf考题中的一类题,它是基于大素因数分解难题产生的公钥密码

数学基础

素数

素数又叫质数,除了1和其本身,不能被其他数整除的数叫做素数

模运算

模运算是取余运算,其符号为modmod

同余

两个数aabb 对同一个数mm取余结果相同,则称aabbmm同余

互质

当两个正整数除了1之外没有其他公因子,我们就称这两个数互质

任意两个质数一定互质

欧拉函数

数论中,对正整数nn,欧拉函数φ(n)\varphi(n)指的是小于或等于nn的正整数中与nn互质的数

易知质数nn的欧拉函数是n1n-1

若不是质数,其欧拉函数有公式:

欧拉定理

若两个正整数a, na,\ n互质,则如下等式成立

aφ(n)1modna^{\varphi(n)}\equiv1\mod{n}

费马小定理

是欧拉定理的特例,当nn是质数并且aann互质

ap11modpa^{p-1}\equiv1\mod{p}

模逆元

对整数a,ba,b,若 ab1modnab\equiv1\mod{n} 则称 aabb 关于模 nn 互为模倒数,也称为模反元素或模逆元,还可以记作

b=a1modnb=a^{-1}\mod{n}

Rsa原理

  • 准备两个非常大的素数p,qp,q
  • 计算n=pqn=p*q
  • 计算φ(n)\varphi(n),由于p, qp,\ q都是素数,所以φ( n)=φ( p)φ( q)\varphi(\ n)=\varphi(\ p)*\varphi(\ q),根据数论基础知识,φ( p)= p  1,φ( q)= q  1\varphi({\ p})=\ p\ -\ 1,\varphi({\ q})=\ q\ -\ 1
  • 选取公钥eeφ(n)\varphi(n)互素φ( p)\varphi(\ p)
  • 求得私钥ddde1modφ(n)d*e\equiv1\mod{\varphi(n)},也就是ddeeφ(n)\varphi(n)的逆元

加密公式

用公钥对明文mm进行加密,得到密文cc

c=E(m)=memodnc=E(m)=m^{e}\mod{n}

解密公式

用私钥进行解密

m=D(c)=cdmodnm=D({c})=c^{d}\mod{n}

RSA证明

由于de1modφ(n)d*e\equiv1\mod{\varphi(n)},所以de=kφ(n)+1d*e=k*{\varphi(n)}+1

已知cmemodnc\equiv m^{e}\mod{n},则

cdmodnmedmodnmkφ(n)+1modn\begin{aligned} c^{d}\mod{n}&\equiv m^{e*d}\mod{n} \\&\equiv m^{k*\varphi(n)+1}\mod{n} \end{aligned}

此时要分情况讨论

  • mmnn互质的时候

     mφ(n)=1modn\ m^{\varphi(n)}=1\mod{n}则此时有

    mkφ(n)1kmodn1modnmkφ(n)+1mmodn\begin{aligned} m^{k*\varphi(n)}&\equiv1^{k}\mod{n} \\&\equiv 1\mod{n} \\m^{k*\varphi(n)+1}&\equiv m\mod{n} \end{aligned}

    也就是说cdmodnmc^d\mod{n}\equiv m

  • mmnn不互质的时候

    由于m<n,n=pqm<n,n=pq,所以mmpp或者qq的倍数,意为m=tqm=t*q,这里的tt为正整数

    也就是说gcd(m,p)=1gcd(m,p)=1

    由费马小定理,mφ(p)=1modpm^{\varphi(p)}=1\mod{p},两边同时进行φ(q)\varphi(q)次方得到mφ(n)1modpm^{\varphi(n)}\equiv1\mod{p}

    那么存在正整数n,使得mφ(n)=1+npm^{\varphi(n)}=1+n*p

    两边同时乘以m=tqm=t*q,得到mφ(n)+1=m+ntpqm^{\varphi(n)+1}= m+nt*p*q,也即是

    mφ(n)+1mmodnm^{\varphi(n)+1}\equiv m\mod{n}

Rsa常见攻击方式

关于模数的攻击

模不互素

攻击原理

当两个模数nn不互素的时候,其公因子就是ppqq,因此可以直接将nn分解

共模攻击

生成秘钥的过程中使用了相同的模数n,此时用不同的秘钥e加密同一信息m:

c1=me1modnc_1=m^{e_1}\mod{n}

c2=me2modnc_2=m^{e_2}\mod n

若是两次生成的公钥 e1\ e_1 e2\ e_2 互素,则根据扩展欧几里得算法,存在 sstt 使得:

se1+te2=gcd(e1,e2)=1s*{e_1}+t*{e_2}=gcd(e_1,e_2)=1

所以

c1sc2tmse1mte2modnmse1+te2modnmmodn\begin{aligned} c_1^sc_2^t &\equiv m^{se_1}m^{te_2} \mod n \\&\equiv m^{se_1+te_2} \mod n \\&\equiv m \mod n \end{aligned}

因此只要计算c1sc2tc_1^sc_2^t即可得出明文c

此处贴上通解代码:

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
import primefac

def same_n_attack(n,e1,e2,c1,c2):
def egcd(a,b):
x, lastX = 0, 1
y, lastY = 1, 0
while (b != 0):
q = a // b
a, b = b, a % b
x, lastX = lastX - q * x, x
y, lastY = lastY - q * y, y
return (lastX, lastY)
s = egcd(e1,e2)
s1 = s[0]
s2 = s[1]
if s1 < 0:
s1 = -s1
c1 = primefac.modinv(c1, n)
if c1 < 0:
c1 += n
elif s2 < 0:
s2 = -s2
c2 = primefac.modinv(c2, n)
if c2 < 0:
c2 += n
m = (pow(c1, s1, n) * pow(c2, s2, n)) % n
return m

dp泄露

首先dpdmod(p1)dp \equiv d \mod (p-1),这个dpdp是比较重要的,因为其中蕴含了pp的信息,只要稍加推导就能得到ppqq

此时推导如下:

dpedemod(p1)dpe=de+k1(p1)de=dpe+k1(p1)\begin{aligned} dp*e &\equiv d*e \mod (p-1) \\ dp*e &= d*e+k_1*(p-1) \\d*e &= dp*e+k_1(p-1) \end{aligned}

由于de1modφ(n)d*e \equiv 1 \mod \varphi(n),所以

dpe+k1(p1)1modφ(n)dpe+k1(p1)1mod(p1)(q1)dpe+k1(p1)=k2(p1)(q1)+1dpe=k2(p1)(q1)+1k1(p1)dpe=(k2(q1)k1)(p1)+1(k2(q1)k1)x,则该式变成:dpe=x(p1)+1\begin{aligned} dp*e+k_1(p-1) &\equiv 1\mod \varphi(n) \\dp*e+k_1(p-1) &\equiv 1\mod (p-1)(q-1) \\dp*e+k_1(p-1) &= k_2*(p-1)(q-1)+1 \\dp*e &= k_2(p-1)(q-1)+1-k_1(p-1) \\dp*e &= (k_2(q-1)-k_1)(p-1)+1 \\令(k_2(q-1)-k_1)&为x,则该式变成: \\dp*e &= x(p-1)+1 \end{aligned}

此时由于dp<(p1)dp<(p-1),因此e>xe>x,所以xx就在(1,e)(1,e),此时只要遍历(1,e)(1,e),并且计算

(dpe1)/x(dp*e-1)/x

只要最后结果是整数,那么就大概率是(p1)(p-1),这时候继续往下算,如果解密结果不是乱码就基本上是正确的了。脚本如下:

1
2
3
4
5
6
7
for i in range(1,e):
if (dp*e-1)%i == 0:
if n%(((dp*e-1)/i)+1)==0:
p=((dp*e-1)/i)+1
q=n/(((dp*e-1)/i)+1)
phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)%phi

e特别大的情况

ee特别大的时候遍历都需要花很长的时间,再进行判断以及计算更需要大量时间,可能跑一年都跑不出来。这时候我们换一种分析方式:

dpedemod(p1)dpe1mod(p1)2dpe11modpkp=2dpe11p=gcd(2dpe11,n)\begin{aligned} dp*e &\equiv d*e \mod (p-1) \\dp*e &\equiv 1 \mod(p-1) \\2^{dp*e-1} &\equiv 1 \mod p \\k*p&= 2^{dp*e-1}-1 \\p&=gcd(2^{dp*e-1}-1,n) \end{aligned}

p和q选取的特别近