常见RSA套路脚本

常见RSA套路脚本


前言

目前CTF比赛中,密码学中的RSA已经是非常常见和频繁的题型了,一般难度也分高低等,但是都具有相应套路。
在RSA里面的几个基本参数:

N:大整数N,我们称之为模数(modulus)
p 和 q :大整数N的两个因子,两个素数(factor)
e 和 d:互为模反数的两个指数,公钥与私钥(exponent)
c 和 m:分别是密文和明文

RSA题目的思路
明文m(一般为flag)就像是一个锁,而私钥就是打开这个锁的钥匙。我们要做的就是根 据公钥来生成这把钥匙来打开锁。而私钥中的N又是可以从公钥中获得的,所以关键就是在d的获取,d的值和p,q,e有关。p,q又是N的 两个因子,所以RSA题目关键便是对N的分解,分解出N的两个因子题目便解决了。


接下来是常见的一些解密脚本

一、已知p,q,e,获取d

#python3
import gmpy2
p =gmpy2.mpz()
q =gmpy2.mpz()
e =gmpy2.mpz()
phi_n= (p - 1) * (q - 1)
d = gmpy2.invert(e, phi_n)
print("d is:")
print (d)

二、给出e,q,p,c

#python3
import gmpy2 as gp
import binascii
p =  gp.mpz()
q =  gp.mpz()
e =  gp.mpz()
c =  gp.mpz()
n = p*q
phi = (p-1) * (q-1)
d = gp.invert(e, phi)
m = pow(c, d, n)
print(m)

三、给出e,n,dp,c

#python3
import gmpy2 as gp

e = 
n = gp.mpz()
dp = gp.mpz()
c = gp.mpz()

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
        phin=(p-1)*(q-1)
        d=gp.invert(e, phin)
        m=gp.powmod(c, d, n)
        if(len(hex(m)[2:])%2==1):
            continue
        print('--------------')
        print(m)
        print(hex(m)[2:])
        print(bytes.fromhex(hex(m)[2:]))
        

四、给出p,q,dp,dp,c

#python3
import gmpy2 as gp

p = gp.mpz()
q = gp.mpz()
dp = gp.mpz()
dq = gp.mpz()
c = gp.mpz()

n = p*q
phin = (p-1)*(q-1)
dd = gp.gcd(p-1, q-1)
d=(dp-dq)//dd * gp.invert((q-1)//dd, (p-1)//dd) * (q-1) +dq
print(d)

m = gp.powmod(c, d, n)
print('-------------------')
print(m)
print(hex(m)[2:])

五、低解密指数攻击(e长度较大)

#python3
import  RSAwienerHacker
n=
e=
d =  RSAwienerHacker.hack_RSA(e,n)
if d:
    print(d)
import hashlib
flag = "flag{" + hashlib.md5(hex(d)).hexdigest() + "}"
print flag

五、共模攻击(n,m相同,c,e不同)

#python3
from libnum import n2s,s2n
from gmpy2 import invert
def egcd(a, b):
  if a == 0:
    return (b, 0, 1)
  else:
    g, y, x = egcd(b % a, a)
    return (g, x - (b // a) * y, y)

def main():
  n = 
  c1 = 
  c2 = 
  e1 = 
  e2 = 
  s = egcd(e1, e2)
  s1 = s[1]
  s2 = s[2]
  if s1<0:
    s1 = - s1
    c1 = invert(c1, n)
  elif s2<0:
    s2 = - s2
    c2 = invert(c2, n)

  m = pow(c1,s1,n)*pow(c2,s2,n) % n
  print hex(m)

if __name__ == '__main__':
  main()

六、e,m相同,存在两个n有公约数

#python3
import gmpy2
from gmpy2 import invert, iroot
import gmpy2 as gp
from libnum import xgcd, invmod

n=[,,,,,,,,,,,,,,,,,,,]
for i in n:
    for j in n:
        if (i<>j):
            pub_p=gmpy2.gcdext(i,j)
            if (pub_p[0]<>1)&(i>j):
                print i
                print j
                print pub_p[0]
                a=i,p=pub_p[0]
q=a/p
p =  gp.mpz()
q =  gp.mpz()
e =  gp.mpz()
c =  gp.mpz()
n = p*q
phi = (p-1) * (q-1)
d = gp.invert(e, phi)
m = pow(c, d, n)
print hex(m)

七、分解n的方式

1.在线网站分解n:

factordb(分解大素数) http://www.factordb.com

2.Yafu分解n:

在RSA中,当p、q的取值差异过大或过于相近的时候,使用yafu可以快速的把n值分解出p、q值,原理是使用Fermat方法与Pollard rho方法等。
windows下yafu的下载及其安装:
https://blog.csdn.net/CliffordR/article/details/82747087

3.利用公约数分解n:

识别此类题目,通常会发现题目给了多个n,均不相同,并且都是2048bit,4096bit级别,无法正面硬杠,并且明文都没什么联系,e也一般取65537。可以直接gcd(n1,n2)求出一个因数。 代码如下:
代码如下:

#python3
import gmpy2
n1 = ()
n2 = ()
p = gmpy2.gcd(n1, n2)
print ('gcd(n1, n2):\n', p)
q1 = n1 / p
q2 = n2 / p
print ('q1 is:\n', q1)
print ('q2 is:\n', q2)

以上便是常见的CTF种分解N的办法。在实际应用中,我总结出了以下的判断顺序
1.先网站在线查询
2.使用Yafu
3.如果所给为多个N,使用公因数攻击
4.当E为1,2或特别大时,使用Rabin攻击或低解密指数攻击
5.当E为3时,如果只给出一组明密文。使用低加密指数攻击,如果给出多组明密文,使用低加密指数广播攻击
6.如果所给为多次加密,使用同个N,使用共模攻击


总结(未完待续)

在RSA中,这些还只是一小部分,现在的rsa出题套路越来越灵活多变,一些常见的脚本套路完全不能支撑rsa的解密,所以还是要深入学习,发掘更多的脚本套路。

这篇文章借助了很多大佬的想法与思路,脚本都为转载,当然有不对的地方,希望大佬指正!!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值