RSA攻击方法整理

RSA算法简述

① 选两个保密的大素数p和q。
② 计算n=p×q,φ(n)=(p-1)(q-1),其中φ(n)是n的欧拉函数值。
③ 选一整数e,满足1

需要注意点

  1. 公钥和私钥互为逆元隐含着1
  2. gcd(φ(n),e)=1(即φ(n)和e互素)则一定存在一组s1,s2使得s1*φ(n)+s2*e=1
    一般出题方式
    pem文件:网络中的证书文件,里面藏着n,e用
    openssl rsa -pubin -text -modulus -in warmup -in public.pem
    可以提取出来
    flag.enc文件:被加密后的文件
    .py文件:加密算法

0x01模数分解

得到φ(n)之后的计算原理:de=1 mod φ(n)且gcd(e,φ(n))=1 
即de=k*φ(n)+1 ==> de+k*φ(n)=1
分解思路:
	直接分解:爆破(利用工具比较稳)
	适用:n比较小的情况(512bit-768bit以内)
	查询了解一下:http://factordb.com
	利用公约数: 如果有2个n,并且2个n有相同的公约数
	欧几里得算法时间复杂度为O(log n)即使是4096bit也是秒破。

分解之后的计算

#coding=utf-8
import gmpy2

p = 3487583947589437589237958723892346254777
q = 8767867843568934765983476584376578389
e = 65537

def modinv(a,m):
    g,y,x=gmpy2.gcdext(a,m)
    if g!=1:
        raise Exception('modular inverse does not exist')
    else:
        return x%m
#加密的时候说d是e的逆元也就是d和e的取值范围相同,所以得到的d是唯一的


#x*a+y*φ(n)=1   gcd(x,y)=1   
#de=1mod φ(n)  即de=k*φ(n)+1==>de+k*φ(n)=1

d=modinv(e,(p-1)*(q-1))
#d=f(e,fai(n))
print d
#d为私钥

分解方式
1.直接分解
小素数分解工具msieve
安装方法

wget http://downloads.sourceforge.net/project/msieve/msieve/Msieve%20v1.52/msieve152.tar.gz
tar zxvf msieve152.tar.gz
mv msieve-1.52 msieve
cd msieve
make all

测试

➜  msieve ./msieve 0x1bc89d92391beeb473fbaa776c751f38e9da272c05b835132776a8114df29a7b01286c0f623af

2.利用公约数
简介:如果有2个n,并且2个n有相同的公约数欧几里得算法时间复杂度为O(log n)即使是4096bit也是秒破。
特征:有不止一个n,n比较大,无从下手。

def gcd(a, b):
   if a < b:
     a, b = b, a
   while b != 0:
     temp = a % b
     a = b
     b = temp
   print a
   return a


if __name__ == '__main__':
    n1=input("n1:")
    n2=input("n2:")
    gcd(n1,n2)

3.查询:
http://factordb.com

4.yafu分解

在p,q的取值差异过大,或者p,q的取值过于相近的时候,Format方法与Pollard rho方法都可以很快将n分解成功。

此类分解方法有一个开源项目yafu将其自动化实现了,不论n的大小,只要p和q存在相差过大或者过近时,都可以通过yafu很快地分解成功。
使用
RSA攻击方法整理_第1张图片
https://www.cnblogs.com/pcat/p/7508205.html

下载
https://sourceforge.net/projects/yafu/

0x02低加密指数分解

低加密指数:当e=3时,如果明文过小,导致明文的三次方仍然小于n,那么通过直接对密文三次开方,即可得到明文。
原理:加密为c=m^e mod n
	   解密为m=c^d mod n
分析:如果e过小(m^e

m^e=k*n+c中m是要求的,e,n,c已知,需要爆破n。
在开e次方得到整数的时候这时候的k和m是需要的值。
识别:在e比较小的时候使用这种方法(一般是3)
https://www.jarvisoj.com (Extremely hard RSA)

#!/usr/bin/python
# coding=utf-8
import gmpy
from Crypto.PublicKey import RSA


def calc(j):

    a, b = gmpy.root(cipher + j * N, 3)
    if b > 0:
        m = a
        print '{:x}'.format(int(m)).decode('hex')
        # pool.terminate()

# 读入公钥
with open('pubkey.pem', 'r') as f:
    key = RSA.importKey(f)
    N = key.n
    e = key.e

# 读入密文
with open('flag.enc', 'r') as f:
    cipher = f.read().encode('hex')
    cipher = int(cipher, 16)

# 暴力破解
inputs = range(0, 118720000)
result = []
map(calc, inputs)
print len(result)

低加密指数广播攻击

c1=m^e mod n1
c2=m^e mod n2
c3=m^e mod n3
在e=3时可以得到c_x=m^3 mod (n_1*n_2*n_3)
对c_x开3次方可以的出明文。

识别:3组密文,公钥相同,由同一个明文加密而成。
https://github.com/ctfs/write-ups-2014/blob/master/hack-you-2014/crypto/400/README.md
低解密指数攻击
就是解密指数也就是秘钥d比较小呗
解法上工具吧https://github.com/pablocelayes/rsa-wiener-attack

识别:只管的看起来就是e比较大

0x03
共模攻击

说明:如果在RSA的使用中使用了相同的模n对相同的明文m进行了加密,那么就可以在不分解n的情况下还原出明文m的值。(e_1和e_2互素)
c_1=m^(e_1)mod n
c_2=m^(e_2)mod n
需要:密文c_1,c_2 并且n相同.
 结果:
c_1^{s_1}*c_2^{s_2}=m mod n
s_1*e_1+s_2*e_2=1
证明:gcd (e_1,e_2)=1 
即存在s_1 ,s_2使得:
s_1*e_1+s_2*e_2=1
又因为: c_1= m^{e_1}mod n
c_2= m^{e_2} mod n
通过代入化简可以得出:
c_1^{s_1}*c_2^{s_2}= m mod n

识别:不只有一个c,有相同的n
例题 https://www.jarvisoj.com (very hard RSA)

#coding=utf-8
import gmpy2
from libnum import n2s,s2n
n=0x00b0bee5e3e9e5a7e8d00b493355c618fc8c7d7d03b82e409951c182f398dee3104580e7ba70d383ae5311475656e8a964d380cb157f48c951adfa65db0b122ca40e42fa709189b719a4f0d746e2f6069baf11cebd650f14b93c977352fd13b1eea6d6e1da775502abff89d3a8b3615fd0db49b88a976bc20568489284e181f6f11e270891c8ef80017bad238e363039a458470f1749101bc29949d3a4f4038d463938851579c7525a69984f15b5667f34209b70eb261136947fa123e549dfff00601883afd936fe411e006e4e93d1a00b0fea541bbfc8c5186cb6220503a94b2413110d640c77ea54ba3220fc8f4cc6ce77151e29b3e06578c478bd1bebe04589ef9a197f6f806db8b3ecd826cad24f5324ccdec6e8fead2c2150068602c8dcdc59402ccac9424b790048ccdd9327068095efa010b7f196c74ba8c37b128f9e1411751633f78b7b9e56f71f77a1b4daad3fc54b5e7ef935d9a72fb176759765522b4bbc02e314d5c06b64d5054b7b096c601236e6ccf45b5e611c805d335dbab0c35d226cc208d8ce4736ba39a0354426fae006c7fe52d5267dcfb9c3884f51fddfdf4a9794bcfe0e1557113749e6c8ef421dba263aff68739ce00ed80fd0022ef92d3488f76deb62bdef7bea6026f22a1d25aa2a92d124414a8021fe0c174b9803e6bb5fad75e186a946a17280770f1243f4387446ccceb2222a965cc30b3929L
e1=17
e2=65537
fo1=open("flag.enc1",'rb')
fo2=open("flag.enc2","rb")

datafo1=fo1.read()
message1=s2n(datafo1)
fo1.close()
datafo2=fo2.read()
message2=s2n(datafo2)

gcd,s,t=gmpy2.gcdext(e1,e2)
print message1
print gcd,s,t


#s和t一定有一个位负数,若s<0,求a^s <=> (1/a)^(-s)

plain=gmpy2.powmod(message1 ,s,n)*gmpy2.powmod(message2,t,n)%n

print plain

print n2s(plain)




#gcdext(...) gcdext(a, b) returns a 3-element tuple (g, s, t) such that
#g == gcd(a, b) and g == a * s + b * t


#invert(...) invert(x, m) returns y such that x * y == 1 modulo m, or 0 if no such y exists.

总结
题目按照如下顺序测试
直接分解:适用n比较短,跑一下msieve
利用公因数:公因数分解有2个n比较大没有其他特征有限使用
查询:接着尝试查询
yafu:再尝试yafu
低加解密指数:如果e比较小,或者比较大,没有其他东西,试一下低加解密指数
共模攻击:2个密文,一个n2个不同的公钥互素
参考https://www.anquanke.com/post/id/84632

你可能感兴趣的:(密码)