RSA攻击解密算法进阶

引文

之前简单讲了一下RSA算法的原理以及计算方法大家有没有学会呢?今天给大家带来的是RSA算法的进阶,进阶内容不止拘泥于RSA的一般算法,也是我在平常经常遇见的类型,多了一些限制性的条件。下面我先带大家回顾一下基础知识吧。

基础知识

先看一下RSA算法涉及的参数:

N:整数N,模数。

p 和 q :N的两个因子(素数)。

e 和 d:互为模反数的两个指数。

c 和 m:密文和明文,求解d时用到函数(d=gmpy2.invert(e,n的欧拉函数)。

加密算法

密文等于m的e次方对N求余。

解密算法

明文是对代表密文的数字 c 的 d 次方对 N 求余。

图解

进阶

维纳攻击

当e过大时适用,e/n的连分数展开会逐渐趋向于k/d。由于连分数逼近原理可以得到两者之间的比值所以(p+q)是可以得到相对接近的值。

例子

GITHUB有个专门的RSA解密脚本:

link.zhihu.com/?target=htt…

from RSAwienerHacker import hack_RSA
e=354611102441307572056572181827925899198345350228753730931089393275463916544456626894245415096107834465778409532373187125318554614722599301791528916212839368121066035541008808261534500586023652767712271625785204280964688004680328300124849680477105302519377370092578107827116821391826210972320377614967547827619
n=460657813884289609896372056585544172485318117026246263899744329237492701820627219556007788200590119136173895989001382151536006853823326382892363143604314518686388786002989248800814861248595075326277099645338694977097459168530898776007293695728101976069423971696524237755227187061418202849911479124793990722597
d=hack_RSA(e,n)
c=38230991316229399651823567590692301060044620412191737764632384680546256228451518238842965221394711848337832459443844446889468362154188214840736744657885858943810177675871991111466653158257191139605699916347308294995664530280816850482740530602254559123759121106338359220242637775919026933563326069449424391192
m=pow(c ,d ,n)
print hex(m) 

dp泄露攻击

也是一个非常经典的题目,dp:d对(p-1)取模,当dp泄露时,n可分解成的素数种类大大降低,变得可以判断。

dp≡dmod(p−1) 

我们可以根据DP值求出P然后就可以按基础公式来求解了:

for i in range(1,65538):if (dp*e-1)%i == 0:if n%(((dp*e-1)/i)+1)==0:p=((dp*e-1)/i)+1q=n/(((dp*e-1)/i)+1)phi = (p-1)*(q-1)d = gmpy2.invert(e,phi)%phi 

低加密指数攻击

适用于e的值比较小的时候,原理如下:

m^e≡c(modn)

m^e=k×n+c(k为特定数值)

e非常小的时候k推断也会非常小,通过蛮力法得到m,然后就可以推导出e。

例子

import gmpy2
import binascii
enf = open('flag.enc', 'rb')
c = int(binascii.b2a_hex(enf.read()), 16)
print c
e = 3
n = 0x00b0bee5e3e9e5a7e8d00b493355c618fc8c7d7d03b82e409951c182f398dee3104580e7ba70d383ae5311475656e8a964d380cb157f48c951adfa65db0b122ca40e42fa709189b719a4f0d746e2f6069baf11cebd650f14b93c977352fd13b1eea6d6e1da775502abff89d3a8b3615fd0db49b88a976bc20568489284e181f6f11e270891c8ef80017bad238e363039a458470f1749101bc29949d3a4f4038d463938851579c7525a69984f15b5667f34209b70eb261136947fa123e549dfff00601883afd936fe411e006e4e93d1a00b0fea541bbfc8c5186cb6220503a94b2413110d640c77ea54ba3220fc8f4cc6ce77151e29b3e06578c478bd1bebe04589ef9a197f6f806db8b3ecd826cad24f5324ccdec6e8fead2c2150068602c8dcdc59402ccac9424b790048ccdd9327068095efa010b7f196c74ba8c37b128f9e1411751633f78b7b9e56f71f77a1b4daad3fc54b5e7ef935d9a72fb176759765522b4bbc02e314d5c06b64d5054b7b096c601236e6ccf45b5e611c805d335dbab0c35d226cc208d8ce4736ba39a0354426fae006c7fe52d5267dcfb9c3884f51fddfdf4a9794bcfe0e1557113749e6c8ef421dba263aff68739ce00ed80fd0022ef92d3488f76deb62bdef7bea6026f22a1d25aa2a92d124414a8021fe0c174b9803e6bb5fad75e186a946a17280770f1243f4387446ccceb2222a965cc30b3929L
k = 99999999
while True:k += 1if k % 1000000 == 0:print kres, isInt = gmpy2.iroot(c + k * n, e)if isInt:print k, resbreak 

共模攻击

数次加密,e不同,n相同,m相同。就可以在不分解n和求d的前提下,解出明文m。

推导过程如下:

实现公式因为太长这里就不具体贴了,贴一个最终运算的代码:

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

P&Q相差过大或者过小

根据基础知识我们知道:

N=P*Q

如果他们相差过大或者过小,根据经验来说更容易从N中分解出来,这里介绍一个分解N的工具YAFU。

WINDOWS版本:

sourceforge.net/projects/ya…

linux版本

github.com/DarkenCode/…

使用方法:

factor(*) 

dp,dq泄露

dp:d对(p-1)取模

dq:d对(q-1)取模

根据公式推导,我们可以通过dp,dq来算出M,进而求解。

设存在m1,m2:

c^d≡m1(modp)(m1为特定数值,使该式成立)

c^d≡m2(modq)(m2为特定数值,使该式成立)

进行一系列的推导,得到以下公式:

cd=((m2−m1)×p(−1)modq)×p+m1

m1≡c^(dp)modp

m2≡c^(dq)modq

合并运算可以求出m,脚本如下:

InvQ=gmpy2.invert(q,p)
mp=pow(c,dp,p)
mq=pow(c,dq,q)
m=(((mp-mq)*InvQ)%p)*q+mq
print '{:x}'.format(m).decode('hex') 

低加密指数广播攻击

选取的加密指数较低,并且使用了相同的加密指数给一个接受者的群发送相同的信息,那么可以进行广播攻击得到明文。原理如下:

n1,n2…为不同加密所使用的模数,c1,c2…为不同加密的密文。

根据条件:

me≡c1(modn1) …等,可以推断出m^e,然后我们就可以发送相同的信息爆破得到e。

例子

('n=', '0x683fe30746a91545a45225e063e8dc64d26dbf98c75658a38a7c9dfd16dd38236c7aae7de5cbbf67056c9c57817fd3da79dc4955217f43caefde3b56a46acf5dL', 'e=', '0x7', 'c=', '0x673c72ace143441c07cba491074163c003f1a550eab56b1255e5ea9fa2bbd68fd6a9ccb48db9fd66d5dfc6a55c79cad3d9de53f700a1e3c2a29731dc56ba43cdL')
('n=', '0xa39292e6ad271bb6a2d1345940dfab8001a53d28bc7468f285d2873d784004c2653549c589dae91c6d8238977ff1c4bea4f17d424a0fc4d5587661cc7dde3a77L', 'e=', '0x7', 'c=', '0x6111357d180d966a495f38566ebe4ea51fa0d54159b22bbd443cde9387687d87c08638483b39221883453a5ad09f6a0e3726b214e8e333037d178a3d0f125343L')
('n=', '0x52c32366d84d34564a5fdc1650fc401c41ad2a63a2d6ef57c32c7887bb25da9d42c0acfb887c6334c938839c9a43aca93b2c7468915d1846576f92c342046d1fL', 'e=', '0x7', 'c=', '0x26cd2225c0229b6a3f1d1d685e53d114aa3d792737d040fbc14189336ac12fb780872792b0c0b259847badffd1427897ede0d60247aa5e79633f27ccb43e7cc2L') 

给了我们三组数据,符合低加密指数广播攻击,于是我们找一个脚本:

import binascii,gmpy2


n =[0x683fe30746a91545a45225e063e8dc64d26dbf98c75658a38a7c9dfd16dd38236c7aae7de5cbbf67056c9c57817fd3da79dc4955217f43caefde3b56a46acf5d,0xa39292e6ad271bb6a2d1345940dfab8001a53d28bc7468f285d2873d784004c2653549c589dae91c6d8238977ff1c4bea4f17d424a0fc4d5587661cc7dde3a77,0x52c32366d84d34564a5fdc1650fc401c41ad2a63a2d6ef57c32c7887bb25da9d42c0acfb887c6334c938839c9a43aca93b2c7468915d1846576f92c342046d1f]
c =[0x673c72ace143441c07cba491074163c003f1a550eab56b1255e5ea9fa2bbd68fd6a9ccb48db9fd66d5dfc6a55c79cad3d9de53f700a1e3c2a29731dc56ba43cd,0x6111357d180d966a495f38566ebe4ea51fa0d54159b22bbd443cde9387687d87c08638483b39221883453a5ad09f6a0e3726b214e8e333037d178a3d0f125343,0x26cd2225c0229b6a3f1d1d685e53d114aa3d792737d040fbc14189336ac12fb780872792b0c0b259847badffd1427897ede0d60247aa5e79633f27ccb43e7cc2]
def CRT(mi, ai):assert(reduce(gmpy2.gcd,mi)==1)assert (isinstance(mi, list) and isinstance(ai, list))M = reduce(lambda x, y: x * y, mi)ai_ti_Mi = [a * (M / m) * gmpy2.invert(M / m, m) for (m, a) in zip(mi, ai)]return reduce(lambda x, y: x + y, ai_ti_Mi) % M
e=0x7
m=gmpy2.iroot(CRT(n, c), e)[0]
print(binascii.unhexlify(hex(m)[2:].strip("L"))) 

工具介绍

看了这么多RSA的解密方式是不是有点晕了,在遇到这些问题时一步一步做还是挺麻烦的,接下来给大家讲解一款专门用来解决RSA算法问题的工具:RsaCtfTool

github.com/6u661e/CTF-…

文件结构如下:

git clone https://github.com/ius/rsatool.git
cd rsatool//进入这个目录
python setup.py install 

基本用法:

已知公钥(自动求私钥) –publickey,密文 —-uncipherfile。

python RsaCtfTool.py --publickey 公钥文件 --uncipherfile 加密的文件 

已知公钥求私钥

python RsaCtfTool.py --publickey 公钥文件 --private 

openssl

openssl可以实现:秘钥证书管理、对称加密和非对称加密 。

生成PKCS#1私钥

openssl genrsa -out rsa_prikey.pem 1024-out 指定生成文件,此文件包含公钥和私钥两部分,所以即可以加密,也可以解密1024 生成密钥的长度(生成私钥为PKCS#1) 

根据私钥生成公钥

openssl rsa -in rsa_prikey.pem -pubout -out pubkey.pem-in 指定输入的密钥文件-out 指定提取生成公钥的文件(PEM公钥格式) 

公钥加密文件

openssl rsautl -encrypt -in input.file -inkey pubkey.pem -pubin -out output.file-in 指定被加密的文件-inkey 指定加密公钥文件-pubin 表面是用纯公钥文件加密-out 指定加密后的文件 

私钥解密文件

openssl rsautl -decrypt -in input.file -inkey key.pem -out output.file-in 指定需要解密的文件-inkey 指定私钥文件-out 指定解密后的文件 

RSA用法

openssl rsa [-inform PEM|NET|DER] [-outform PEM|NET|DER] [-in filename] [-passin arg] [-out filename] [-passout arg] [-sgckey] [-des] [-des3] [-idea] [-text] [-noout] [-modulus] [-check] [-pubin] [-pubout] [-engine id]</pre>
常用选项:
-in filename:指明私钥文件
-out filename:指明将提取出的公钥保存至指定文件中 
-pubin:根据公钥提取出私钥
-pubout:根据私钥提取出公钥 

结语

今天比较详细的总结了个人在遇到RSA题目时的一些经验,可能有一些确实不太好理解,这里也提供了工具去解决,喜欢的小伙伴不妨一键三连支持一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值