RSA常见解密
Crypto.Util.number 是 Python 中一个常用的密码学工具库,提供了许多常用的数字操作函数。以下是其中一些常用的函数:
bytes_to_long
: 将字节串转换为长整数。long_to_bytes
: 将长整数转换为字节串。getPrime
: 生成一个指定位数的素数。isPrime
: 判断一个数是否为素数。GCD
: 计算两个整数的最大公约数。inverse
: 计算一个数的模逆。random\_prime
: 生成一个随机的素数。size
: 返回一个整数的位数。getStrongPrime
: 生成一个强素数。
dp,dq泄露
特征:
dp=d%(p-1)
dq=d%(q-1)
原理:
正常来说,解密用到的这个公式:
m
=
c
d
(
m
o
d
n
)
。但是由于
n
=
p
q
,所以刚刚那个式子可以化为
{
m
1
≡
c
d
(
m
o
d
p
)
(
1
)
m
2
≡
c
d
(
m
o
d
q
)
(
2
)
。
正常来说,解密用到的这个公式:m=c^{d}(mod~n)。但是由于n=pq,所以刚刚那个式子可以化为\begin{array}{l} \left\{\begin{matrix} m_{1}\equiv c^{d}(mod~p)(1)\\ m_{2}\equiv c^{d}(mod~q) (2) \end{matrix}\right. \end{array} 。
正常来说,解密用到的这个公式:m=cd(mod n)。但是由于n=pq,所以刚刚那个式子可以化为{m1≡cd(mod p)(1)m2≡cd(mod q)(2)。
证明过程如下:
对于公式
m
=
c
d
(
m
o
d
n
)
我们可以这样理解:
m
除以
n
得到某个商
k
和余数
c
d
.
于是可以转换成等式
m
=
c
d
+
k
n
。而
n
=
p
∗
q
,
所以可以进一步写成
m
=
c
d
+
k
n
=
c
d
+
k
p
q
,其中
k
为假设的商。
然后两边分别同时对
p
,
q
取余,
k
p
q
那一项就被消去了,就得到
{
m
1
≡
c
d
(
m
o
d
p
)
m
2
≡
c
d
(
m
o
d
q
)
。
对于公式m=c^{d}(mod~n)我们可以这样理解:m除以n得到某个商k和余数c^{d}.\\ 于是可以转换成等式m=c^{d}+kn。而n=p*q,所以可以进一步写成m=c^{d}+kn=c^{d}+kpq,其中k为假设的商。\\ 然后两边分别同时对p,q取余,kpq那一项就被消去了,就得到\begin{array}{l} \left\{\begin{matrix} m_{1}\equiv c^{d}(mod~p)\\ m_{2}\equiv c^{d}(mod~q) \end{matrix}\right. \end{array} 。
对于公式m=cd(mod n)我们可以这样理解:m除以n得到某个商k和余数cd.于是可以转换成等式m=cd+kn。而n=p∗q,所以可以进一步写成m=cd+kn=cd+kpq,其中k为假设的商。然后两边分别同时对p,q取余,kpq那一项就被消去了,就得到{m1≡cd(mod p)m2≡cd(mod q)。
由于dp=d(mod p-1),dq=d(mod q-1),在集合欧拉定理或者费马小定理,上面的同余式组可以进一步化为
{
m
1
≡
c
d
p
(
m
o
d
p
)
(
3
)
m
2
≡
c
d
q
(
m
o
d
q
)
(
4
)
。
\begin{array}{l} \left\{\begin{matrix} m_{1}\equiv c^{dp}(mod~p)~(3)\\ m_{2}\equiv c^{dq}(mod~q)~(4) \end{matrix}\right. \end{array} 。
{m1≡cdp(mod p) (3)m2≡cdq(mod q) (4)。
由( 1 )可得 m 1 + k p = c d ( 这里的 k 和上面证明中的 k 没有关系 ) ,不妨将其记为 ( 5 ) 式,然后代入 ( 2 ) 式可得 k p ≡ ( m 2 − m 1 ) ( m o d q ) , 又因为 g c d ( p , q ) = 1 , 即 p , q 互素,所以可以在刚刚得到式子的两边同时乘上 p 的逆元,得到 k = p ′ ( m 2 − m 1 ) ( m o d q ) , 其中 p ′ 是 p 关于 q 的逆元。 将这个 k 的表达式代入( 5 )式,得到 c d ≡ m 1 + [ p ′ ( m 2 − m 1 ) ( m o d q ) ] ∗ p 。其中的 m 1 和 m 2 可以通过上面的式子( 3 )( 4 )计算得到。 最后就可以得到 c d 的值从而解出明文 m 。 由(1)可得m_{1}+kp=c^{d}(这里的k和上面证明中的k没有关系),不妨将其记为(5)式,然后代入(2)式可得kp≡( m 2 − m 1 ) ( m o d~q) ,\\ 又因为gcd(p,q)=1,即p,q互素,所以可以在刚刚得到式子的两边同时乘上p的逆元,得到k=p^{'}(m_{2}-m_{1})(mod~q),其中p^{'}是p关于q的逆元。\\ 将这个k的表达式代入(5)式,得到c^{d}\equiv m_{1}+[p^{'}(m_{2}-m_{1})(mod~q)]*p。其中的m_{1}和m_{2}可以通过上面的式子(3)(4)计算得到。\\ 最后就可以得到c^{d}的值从而解出明文m。 由(1)可得m1+kp=cd(这里的k和上面证明中的k没有关系),不妨将其记为(5)式,然后代入(2)式可得kp≡(m2−m1)(mod q),又因为gcd(p,q)=1,即p,q互素,所以可以在刚刚得到式子的两边同时乘上p的逆元,得到k=p′(m2−m1)(mod q),其中p′是p关于q的逆元。将这个k的表达式代入(5)式,得到cd≡m1+[p′(m2−m1)(mod q)]∗p。其中的m1和m2可以通过上面的式子(3)(4)计算得到。最后就可以得到cd的值从而解出明文m。
from gmpy2 import *
from Crypto.Util.number import *
# dp+dq+p+q+c => m
def rsa(dp,dq,p,q,c):
m1=pow(c,dp,p)
m2=pow(c,dq,q)
p_q=invert(p,q)
m=m1+p_q*((m2-m1)%q)*p
print(long_to_bytes(m))
if __name__ == "__main__":
p = 8637633767257008567099653486541091171320491509433615447539162437911244175885667806398411790524083553445158113502227745206205327690939504032994699902053229
q = 12640674973996472769176047937170883420927050821480010581593137135372473880595613737337630629752577346147039284030082593490776630572584959954205336880228469
dp = 6500795702216834621109042351193261530650043841056252930930949663358625016881832840728066026150264693076109354874099841380454881716097778307268116910582929
dq = 783472263673553449019532580386470672380574033551303889137911760438881683674556098098256795673512201963002175438762767516968043599582527539160811120550041
c = 24722305403887382073567316467649080662631552905960229399079107995602154418176056335800638887527614164073530437657085079676157350205351945222989351316076486573599576041978339872265925062764318536089007310270278526159678937431903862892400747915525118983959970607934142974736675784325993445942031372107342103852
rsa(dp,dq,p,q,c)
dp泄露
所以这里就可以得出
p − 1 = ( d p ∗ e − 1 ) / X 所以 p = ( d p ∗ e − 1 ) / X + 1 这里的话还要满足 p 能整除 n 。即 q = n / / q p-1=(dp*e-1)/X\\ 所以p=(dp*e-1)/X+1\\ 这里的话还要满足p能整除n。即q=n//q p−1=(dp∗e−1)/X所以p=(dp∗e−1)/X+1这里的话还要满足p能整除n。即q=n//q
import gmpy2
e =
n =
dp =
c =
for x in range(1, e):
if(e*dp%x==1):
p=(e*dp-1)//x+1
if(n%p!=0):
continue
q=n//p
phi=(p-1)*(q-1)
d=gmpy2.invert(e, phi)
m=pow(c, d, n)
if(len(hex(m)[2:])%2==1):
continue
print('--------------')
print(m)
print(hex(m)[2:])
print(bytes.fromhex(hex(m)[2:]))