rsa解密

一、基本原理

1.两个素数:p,q

2.n=p*q

3.欧拉函数:phi(n)=(p-1)*(q-1)

4.取数e,使得1<e<phi,且gcd(e,phi)=1,即互质

5.取数d,使得1<d<phi,且gcd(d,phi)=1,即互质

6.(e,n):公钥;(d,n):私钥

7.满足(e * d) % phi = 1,e是d的乘法逆元

二、加密,解密

1.m=c^d(mod n)

2.c=m^e(mod n)

三、有关理论

1.乘法逆元(原文链接:http://t.csdnimg.cn/rqxL4

2.费马小定理(原文链接:费马小定理(通俗易懂) - 乾奕的文章 - 知乎
https://zhuanlan.zhihu.com/p/616185983)

 3.射影定理,欧几里得定理

gcd(a, b) = gcd(b, a%b)

 四、解密工具推荐

参考这篇:http://t.csdnimg.cn/FInqX

五、rsa一些题型及其脚本

1.已知p,q,e,求d
import gmpy2
p=#填入p的内容
q=#填入q的内容
n=p*q
phi_n=(p-1)*(q-1)
print(phi_n)
e=#填入e的值
d=gmpy2.invert(e,phi_n) # e*d mod phi_n = 1 e*d=1+k*phi_n
print(d)
2.已知p,q,e,c,求m
import gmpy2
p =  #填入p的内容
q =  #填入q的内容
n=p*q
phi_n=(p-1)*(q-1)
e =  #填入e的内容
d=gmpy2.invert(e,phi_n)
c =  #填入c的内容
m=gmpy2.powmod(c,d,n)
print(m)
3.已知dp,dq,p,q,c ,求m(dp,dq泄露)
import gmpy2
from Crypto.Util.number import long_to_bytes

p = #填入p的内容
q = #填入q的内容
dp =#填入dp的内容
dq = #填入dq的内容
c = #填入c的内容

I = gmpy2.invert(q, p)  # q*I mod p = 1
mp = pow(c, dp, p)
mq = pow(c, dq, q)
m = (((mp-mq) * I) % p) * q + mq

print(long_to_bytes(m))

4.已知c1,c2,n,e1,e2,求m(一个n,多个e,共模攻击)

 参考文章:http://t.csdnimg.cn/eC3Vk 

  • e1, e2互质,即gcd(e1, e2) = 1
import gmpy2

c1 = #填入c1值
n = #填入n值
e1 = #填入e1值
c2 = #填入c2值
e2 = #填入e2值

s = gmpy2.gcdext(e1, e2)  # 拓展欧几里得算法,计算s1和s2
m1 = gmpy2.powmod(c1, s[1], n)
m2 = gmpy2.powmod(c2, s[2], n)
m = (m1 * m2) % n

print(bytes.fromhex(hex(m)[2:]))  # 16进制转文本


  • e1、e2不互质
#设gcd(e1, e2) = a,得到s1 * e1 + s2 * e2 = a
即最后求得的m还需要开a次根
//
a, s1, s2 = gcdext(e1, e2)
m1 = gmpy2.powmod(c1, s[1], n)
m2 = gmpy2.powmod(c2, s[2], n)
m = (m1 * m2) % n

while True:
    if iroot(m, a)[1]:
        m = iroot(m, a)[0]
        print(long_to_bytes(m))
        break
    m += n
//
5.已知e,n,dp,c,求m(dp泄露)
import gmpy2

e = #填入e的内容
n = #填入n的内容
dp = #填入dp的内容
c = #填入c的内容

for i in range(1, e):  # 在范围(1,e)之间进行遍历
    if (dp * e - 1) % i == 0:
        if n % (((dp * e - 1) // i) + 1) == 0:  # 存在p,使得n能被p整除
            p = ((dp * e - 1) // i) + 1
            q = n // (((dp * e - 1) // i) + 1)
            phi = (q - 1) * (p - 1)  # 欧拉定理
            d = gp.invert(e, phi)  # 求模逆
            m = pow(c, d, n)  # 快速求幂取模运算
print(bytes.fromhex(hex(m)[2:]))  # 16进制转文本
6.公钥解析\rightarrow提取p,q\rightarrow脚本解密
  • 简单版
​
import rsa
​
e = #填入e的内容
n = #填入n的内容
p = #填入p的内容
q = #填入q的内容
d = #填入d的内容
​
key = rsa.PrivateKey(n, e, d, q, p)
​
with open("#复制key文件路径","rb+") as f:
    f = f.read()
    print(rsa.decrypt(f, key))


​
  • 复杂版(PKCS1 OAEP)
import gmpy2
from Crypto.Cipher import PKCS1_OAEP
# PKCS1 OAEP 是一种基于 RSA 和 OAEP 填充的非对称密码
from Crypto.PublicKey import RSA
e = 
n = 
p = 
q = 
​
phi_n = (p - 1) * (q - 1)
d = int(gmpy2.invert(e, phi_n))
​
rsakey = RSA.importKey(open(.key的地址,"r").read())
privatekey = RSA.construct((n, e, d, p, q))
rsa = PKCS1_OAEP.new(privatekey)
m = rsa.decrypt(open(.flag的地址,"rb").read())
print(m)

 7.n+e+c+p+q= m + n分解,(Roll按行加密)(参考文章:http://t.csdnimg.cn/HtX39

import libnum
from Crypto.Util.number import long_to_bytes
list1=[#插入flag滚动里的内容]
flag=""
n=#填入n的内容
q=#填入q的内容
p=#填入p的内容
e=#填入e的内容
for i in list1:
	c=i
	d = libnum.invmod(e, (p - 1) * (q - 1)) 		#invmod(a, n) - 求a对于n的模逆,这里逆向加密过程中计算ψ(n)=(p-1)(q-1),对ψ(n)保密,也就是对应根据ed=1modψ(n),求出d
	m = pow(c, d, n)  						# pow(x, y[, z])--函数是计算 x 的 y 次方,如果 z 在存在,则再对结果进行取模,其结果等效于 pow(x,y) %z,对应前面解密算法中M=D(C)=C^d(mod n)
#print(m) #明文的十进制格式
	string = long_to_bytes(m)  				# m明文,用长字节划范围
	flag+=string.decode()
print(flag)
8.费马分解法
  • p,q已知素数
'''生成两个挨得近的素数p,q'''
p = getPrime(512)
q = gmpy2.next_prime(p)
#这是其特征代码
​
'''开始破解'''
temp=gmpy2.iroot(n,2)[0]  
#iroot函数,这个函数专门用来进行大数开根号,gmpy2.iroot(n,t)。n就是大整数,t是你要开几次幂。
p=gmpy2.next_prime(temp)
q=n//p
print(p)
print(q)
  • p,q不确定是否为素数
'''生成两个挨得近的素数p,q'''
p = getPrime(512)
q = gmpy2.next_prime(p)
n=p*q
​
​
print('开始破解')
'''开始破解'''
a=gmpy2.iroot(n,2)[0]
while 1: 
    B2=pow(a,2)-n
    if gmpy2.is_square(B2):
        b=gmpy2.iroot(B2,2)[0]
        p=a+b
        q=a-b
        print(p)
        print(q)
        break
    a+=1
9.n,c有多个且不同(n不互素)
import gmpy2
from Crypto.Util.number import *
from Crypto.Util.number import long_to_bytes
e=
c=
n1=
n2=
#输入对应内容的值
p = gmpy2.gcd(n1,n2)
q = n1//p
phi_n = (p-1)*(q-1)
d = inverse(e,phi_n)
m = gmpy2.powmod(c,d,n1)
print(long_to_bytes(m))
10.低加密指数攻击(e特别小,一般是3)
import gmpy2
import libnum
​
def de(c, e, n):
    k = 0
    while True:
        mm = c + n*k
        result, flag = gmpy2.iroot(mm, e)
        if True == flag:
            return result
        k += 1
e= 3
n=
c=
​
m=de(c,e,n)
print(m)
print(libnum.n2s(int(m)).decode())
11.低解密指数攻击-维纳攻击

http://t.csdnimg.cn/hSHlI

import gmpy2
def transform(x,y):       #使用辗转相处将分数 x/y 转为连分数的形式
    res=[]
    while y:
        res.append(x//y)
        x,y=y,x%y
    return res
    
def continued_fraction(sub_res):
    numerator,denominator=1,0
    for i in sub_res[::-1]:      #从sublist的后面往前循环
        denominator,numerator=numerator,i*numerator+denominator
    return denominator,numerator   #得到渐进分数的分母和分子,并返回
​
    
#求解每个渐进分数
def sub_fraction(x,y):
    res=transform(x,y)
    res=list(map(continued_fraction,(res[0:i] for i in range(1,len(res)))))  #将连分数的结果逐一截取以求渐进分数
    return res
​
def get_pq(a,b,c):      #由p+q和pq的值通过维达定理来求解p和q
    par=gmpy2.isqrt(b*b-4*a*c)   #由上述可得,开根号一定是整数,因为有解
    x1,x2=(-b+par)//(2*a),(-b-par)//(2*a)
    return x1,x2
​
def wienerAttack(e,n):
    for (d,k) in sub_fraction(e,n):  #用一个for循环来注意试探e/n的连续函数的渐进分数,直到找到一个满足条件的渐进分数
        if k==0:                     #可能会出现连分数的第一个为0的情况,排除
            continue
        if (e*d-1)%k!=0:             #ed=1 (mod φ(n)) 因此如果找到了d的话,(ed-1)会整除φ(n),也就是存在k使得(e*d-1)//k=φ(n)
            continue
        
        phi=(e*d-1)//k               #这个结果就是 φ(n)
        px,qy=get_pq(1,n-phi+1,n)
        if px*qy==n:
            p,q=abs(int(px)),abs(int(qy))     #可能会得到两个负数,负负得正未尝不会出现
            d=gmpy2.invert(e,(p-1)*(q-1))     #求ed=1 (mod  φ(n))的结果,也就是e关于 φ(n)的乘法逆元d
            return d
    print("该方法不适用")
    
    
e = 
n = 
c = 
d=wienerAttack(e,n)
print("d=",d)
m = gmpy2.powmod(c,d,n)
print(long_to_bytes(m))
12.已知高位攻击(coppersmith)

需要使用到sagemath

Coppersmith 攻击

http://t.csdnimg.cn/JeEGp

  • 已知p高位
n=
p4=            #已知P的高位
e=
pbits=          #P原本的位数
​
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)
# 经过以上一些函数处理后,n和p已经被转化为10进制
if roots:
    p= p4 + int(roots([0]))
    print ("n",n)
    print ("p",p)
    print ("q",n/p)
  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值