RSA原理及其攻击方法

RSA原理及其攻击方法

RSA 基于一个简单的数论事实,两个大素数相乘十分容易,将其进行因式分解却是困难的

密钥产生:

1.选两个大素数p和q

2.计算n=p*q,欧拉函数*φ(n) =(p-1) (q-1)

3.选一整数e,满足1<e<φ(n),且gcd(φ(n),e)=1,即φ(n)与e互质

4.计算d,满足d *e≡1 mod φ(n),即d是e在模φ(n)下的乘法逆元,因为e与φ(n)互素,由模运算可知,它的乘法逆元一定存在(欧拉定理:若a与n互素,则a^φ(n)≡1 mod n)

5.以{e,n}为公钥,{d,n}为私钥

加密:

加密前先进行分组,使得每个分组对应的十进制数小于n,即分组长度小于 log2n,然后对明文分组m做加密运算:c≡m^e mod n

解密:

分组解密运算:m ≡ c^d mod n

RSA算法中的计算问题

加密解密:

加密解密过程中直接求一个整数的整数次幂再进行取模很有可能直接爆了,所以这里需要用到模运算的性质减小中间量的值:

(a*b)mod n=[(a mod n) * (b mod n)] mod n

再考虑指数运算的有效性,例如x ^ 16 , 直接计算会计算15次,如果重复对部分结果进行平方运算,即x,x^ 2 , x^ 4,x ^ 8,x^16,就只需要计算4次

一般求a ^ m可以先将m化为二进制形式,即m=bk2^k+ bk-12^k-1+…+b12+b0

因此,a^m=(…((( a^ bk ) ^2 * a ^ bk-1)^ 2 * a^ bk-2) ^ 2)…a^ b1)^2* a^b0

例如:

19=>10011#化为二进制

19=1*2^4+0 *2^3+0 *2^2+1 *2^1+1 *2^0

a^19=((((a ^ 1)^2 *a ^ 0)^2 *a ^ 0)^2 *a ^ 1)^2 *a^1

密钥的产生:

为了防止穷搜索发现p,q这两个大素数应是在足够大的整数集合中选取的大数,如果选取p,q为10 ^ 100 左右的大数,那么n的阶就大概再10^ 200左右,那么每个明文分组就可以包含664位(因为10^ 200 ≈ 2^664),即83个8byte字节,所以如何寻找这两个大素数是一个比较重要的问题,首先一般先随机选取一个大的奇数

然后用素性检验算法检验这一奇数是否为素数,如果不是,则选取另一大奇数,重复过程直到找到为止

之后是选取需要满足1<e<φ(n)和gcd(φ(n),e)=1的e并且计算d *e≡1 mod φ(n)的d(使用欧几里得算法实现)

RSA的安全问题

如果RSA的p,q被成功分解就可以立即获取φ(n),从而可以通过d ≡e^-1 mod φ(n)(快速幂求取乘法逆元)获取私钥d,攻击成功,经过较长时间的发展,如今被破解的最长RSA密钥是768个二进制位,目前密钥长度介于1024~2048比特之间的RSA密钥是安全的

为保证RSA算法的安全性,对p,q提出以下要求:

1.|p-q|要相对大

2.p-1和q-1都应有大素因子,

此外,如果e<n,d<n^1/4,则d能被容易地确定

目前针对rsa的攻击

即便 RSA 算法目前来说是安全可靠的,但是错误的应用场景,错误的环境配置,以及错误的使用方法都会导致 RSA 的算法体系出现问题,从而也派生出针对各种特定场景下的 RSA 攻击方法

n可直接分解

n的大小小于256bites,可以直接利用windows的RSATool对n进行分解

那么n可分解的情况下实际上就已经知道φ(n)的了,通过欧几里得算法求模逆元就可以得出私钥d

例题:

p = 3487583947589437589237958723892346254777
q = 8767867843568934765983476584376578389
e = 65537
求 d

code:

import gmpy2

p = 3487583947589437589237958723892346254777
q = 8767867843568934765983476584376578389
e = 65537

print(gmpy2.invert(e, (p - 1) * (q - 1)))#求模逆元

yafu

当大整数N的两个因子p和q相差不大时,我们可以通过费马分解的办法很快分解大整数,当p,q相差较大时,我们可以通过pollard rho算法分解,yafu使用此类强大的现代算法自动化地实现分解的目的,大多数的算法都实现了多线程,让yafu能充分利用多核处理器(算法包括 SNFS, GNFS, SIQS, 和 ECM)。

factordb

n大于768bite时或者对一个大整数用一些特殊算法也分解不了的时候,我们可以在 http://factordb.com/ 中查询一下数据库,此网站存储一些已经分解成功的n

n1,n2具有相同素因子

通过欧几里得算法可以直接求出 n1 和 n2 的最大公约数 p:

gcd(n1,n2)=p

可以得出:

n1=pq1

n2=pq2

例题:

n1 = 9051013965404084482870087864821455535159008696042953021965631089095795348830954383127323853272528967729311045179605407693592665683311660581204886571146327720288455874927281128121117323579691204792399913106627543274457036172455814805715668293705603675386878220947722186914112990452722174363713630297685159669328951520891938403452797650685849523658191947411429068829734053745180460758604283051344339641429819373112365211739216160420494167071996438506850526168389386850499796102003625404245645796271690310748804327
n2 = 13225948396179603816062046418717214792668512413625091569997524364243995991961018894150059207824093837420451375240550310050209398964506318518991620142575926623780411532257230701985821629425722030608722035570690474171259238153947095310303522831971664666067542649034461621725656234869005501293423975184701929729170077280251436216167293058560030089006140224375425679571181787206982712477261432579537981278055755344573767076951793312062480275004564657590263719816033564139497109942073701755011873153205366238585665743

code:

import gmpy2

n1 = 9051013965404084482870087864821455535159008696042953021965631089095795348830954383127323853272528967729311045179605407693592665683311660581204886571146327720288455874927281128121117323579691204792399913106627543274457036172455814805715668293705603675386878220947722186914112990452722174363713630297685159669328951520891938403452797650685849523658191947411429068829734053745180460758604283051344339641429819373112365211739216160420494167071996438506850526168389386850499796102003625404245645796271690310748804327
n2 = 13225948396179603816062046418717214792668512413625091569997524364243995991961018894150059207824093837420451375240550310050209398964506318518991620142575926623780411532257230701985821629425722030608722035570690474171259238153947095310303522831971664666067542649034461621725656234869005501293423975184701929729170077280251436216167293058560030089006140224375425679571181787206982712477261432579537981278055755344573767076951793312062480275004564657590263719816033564139497109942073701755011873153205366238585665743

p=gmpy2.gcd(n1,n2)#求最大公约数p
q1=n1/p#求q1
q2=n2/p#求q2

print(q1,q2)
d=gmpy2.invert(e,(p-1)*(q1-1))
m=pow(c1,d,n1)#c1的d次方模n1
print(long_to_bytes(m))#long型转byte型

低加密指数攻击

加密指数较小可以加快加密过程,但同时也存在安全问题

第一种情况
当 e=3 时,如果明文过小,导致明文的三次方仍然小于 n,那么就可以通过直接对m开三次方,即可得到明文。

即:

c≡m^e mod n

如果 e=3, m^3<n

=>c=m^3

=>m=c^1/3

还有一种情况是

如果明文的 3 次方比 n 大,但不足够大,那么可以设 k,就有:

c=m^3+kn

爆破 k,如果 c − kn 能开三次根式得到整数k,那么可以直接得到明文

例题:

Extremely hard RSA

得到
一个pem文件:网络中的证书文件,里面藏着n,e
openssl rsa -pubin -text -modulus -in warmup -in public.pem
可以提取出来,注意文件需放到同一目录下
一个flag.enc文件:被加密后的文件,写解密脚本时打开

先用openssl命令找到n和e,发现e=3那么就可以试试低加密指数攻击了

在这里插入图片描述
exp:

import gmpy2
import rsa
from rsa import transform, core

c = open('flag.enc', 'rb').read()
c = transform.bytes2int(c)  # 字节数组转为大整数
n = 721059527572145959497866070657244746540818298735241721382435892767279354577831824618770455583435147844630635953460258329387406192598509097375098935299515255208445013180388186216473913754107215551156731413550416051385656895153798495423962750773689964815342291306243827028882267935999927349370340823239030087548468521168519725061290069094595524921012137038227208900579645041589141405674545883465785472925889948455146449614776287566375730215127615312001651111977914327170496695481547965108836595145998046638495232893568434202438172004892803105333017726958632541897741726563336871452837359564555756166187509015523771005760534037559648199915268764998183410394036820824721644946933656264441126738697663216138624571035323231711566263476403936148535644088575960271071967700560360448191493328793704136810376879662623765917690163480410089565377528947433177653458111431603202302962218312038109342064899388130688144810901340648989107010954279327738671710906115976561154622625847780945535284376248111949506936128229494332806622251145622565895781480383025403043645862516504771643210000415216199272423542871886181906457361118669629044165861299560814450960273479900717138570739601887771447529543568822851100841225147694940195217298482866496536787241
print(hex(c)) #提取密文c

def dec(c, N): # 爆破k
    k=0
    #k =118719487
    while 1:
        print(k)
        (x, y) = gmpy2.iroot(c + k * N, 3)
        if y:
            print(gmpy2.iroot(c + k* N, 3))
            break
        k = k + 1


dec(c, n)
m = 440721643740967258786371951429849843897639673893942371730874939742481383302887786063966117819631425015196093856646526738786745933078032806737504580146717737115929461581126895844008044713461807791172016433647699394456368658396746134702627548155069403689581548233891848149612485605022294307233116137509171389596747894529765156771462793389236431942344003532140158865426896855377113878133478689191912682550117563858186
m = transform.int2bytes(m)  # 大整数转为字节数组
print(m)

flag:

(mpz(440721643740967258786371951429849843897639673893942371730874939742481383302887786063966117819631425015196093856646526738786745933078032806737504580146717737115929461581126895844008044713461807791172016433647699394456368658396746134702627548155069403689581548233891848149612485605022294307233116137509171389596747894529765156771462793389236431942344003532140158865426896855377113878133478689191912682550117563858186), True)#可完全开方,不带根号
b"Didn't you know RSA padding is really important? Now you see a non-padding message is so dangerous. And you should notice this in future.Fl4g: PCTF{Sm4ll_3xpon3nt_i5_W3ak}\n"

低解密指数攻击(Wiener’s attack)

一种基于连分数的特殊攻击类型,与低加密指数相同,低解密指数可以加快解密的过程,因此它也会存在一些安全问题

如果满足e很大, d < (1/3) N^(1/4),q<p<2q时,我们可以通过Wiener’s attack分解得到d

原理:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E2X3fpgo-1625906380089)(C:\Users\罗昕蕊\AppData\Roaming\Typora\typora-user-images\image-20210708091839351.png)]

Boneh Durfee Method

当满足 d ≤ N^0.292 时(d没有足够小),我们可以利用该方法分解N,理论上比wiener attack要强一些。

参考github代码

Rabin算法

仅限用于e等于2

例题:

用同样的方法进行提取,发现e=2所以可以用到Rabin算法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l4c8vpCN-1625906380097)(C:\Users\罗昕蕊\AppData\Roaming\Typora\typora-user-images\image-20210707200214883.png)]
提取出n和e后对n进行yafu分解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1ObViBsB-1625906380100)(C:\Users\罗昕蕊\AppData\Roaming\Typora\typora-user-images\image-20210707200556010.png)]
code:

import gmpy2
import string
from Crypto.PublicKey import RSA

with open('pubkey.pem', 'r')as f:#提取n,e
    key = RSA.importKey(f)
    N = key.n
    e = key.e

with open('flag.enc', 'r')as f:
    cipher = f.read().encode('hex')
    cipher = string.atoi(cipher, base=16)  # atoi()字符串转换成整数型
    print(cipher)

p = 275127860351348928173285174381581152299
q = 319576316814478949870590164193048041239
inv_p = gmpy2.invert(p, q)
inv_q = gmpy2.invert(q, p)
mp = pow(cipher, (p + 1) / 4, p)
mq = pow(cipher, (q + 1) / 4, q)
a = (inv_p * p * mq + inv_q * q * mp) % N
b = N - int(a)
c = (inv_p * p * mq - inv_q * q * mp) % N
d = N - int(c)
for i in (a, b, c, d):
    s = '%x' % i
    if len(s) % 2 != 0:
        s = '0' + s
print s.decode('hex')

Rabin算法具有其致命的缺陷:一个密文对应四个明文。但此算法仍然包含了密码学中的基本概念和技巧,如单向函数、整数的因数分解等。

Rabin算法的安全性基于整数的因式分解问题:只有将公钥n正确分解为私钥p、q,才可以将公钥加密后的密文还原为原文,而通常p、q都会取相当大的素数,因此n也是一个非常大的数字;数字越大,其因式分解越困难。

共模攻击

条件:在RSA的使用中使用了相同的模n对明文m进行加密

解决方法:可以在不分解n的情况下还原明文m

要求:e1与e2互质

c1≡m^e1 mod n
c2≡m^e2 mod n

c1 ^ r* c2 ^ s≡m^(e1 * r+e2 * s) ≡m^1 (mod n)

e1 r + e2 s=1 # 扩展欧几里得算法求出r,s,其中一个必定为负,设为s<0

,再次用扩展欧几里得算法求出c1 ^-1由此(c1 -1) ^-s1 * c2^s2≡m mod n

m=(c1^ s1*c2^s2)mod n #最终结果

推导过程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bfrGK35T-1625906380102)(C:\Users\罗昕蕊\AppData\Roaming\Typora\typora-user-images\image-20210710152027128.png)]

def exgcd(a,b):#扩展欧几里得算法
    if b==0:
        return (1,0)
    else:
        x,y=exgcd(b,a%b)
        tempx=x
        x=y
        y=tempx-int((a/b))*y
    return x,y
a=exgcd(13,2)
print(a)

调用函数:

gmpy2.gcdext(x,y)#扩展欧几里得算法

已知p+q或p-q

可以通过解方程组或推导求出p和q

p*q=n

p+q=a

使用SageMath解方程组:

var('p q')
solve([p*q==n,p+q==a],[p,q])

Small q

当q较小时,即|p-q|较大时,我们可以直接爆破因子

d泄露攻击

如果我们知道一组过期的(N,n1,d1)和一组由新的e2组成的公钥及其加密的密文(N,e2,c),我们可以由(e1,d1)得到模数N的两个因子p和q,之后求出φ(n),再去算e2的模逆元d2,然后解出密文

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cd4z4ium-1625906380104)(C:\Users\罗昕蕊\AppData\Roaming\Typora\typora-user-images\image-20210710153148077.png)]

已知明文高位攻击

Coppersmith定理指出在一个e阶modn的多项式f(x)中,如果又一个根小于n^1/e,就可以运用一个o(log n)的算法求出这些根

所以在e=3,并且已知明文高位,就可以尝试Coppersmith攻击

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wa7iJxbp-1625906380105)(C:\Users\罗昕蕊\AppData\Roaming\Typora\typora-user-images\image-20210710153645635.png)]

Partial p攻击

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8hDkn63u-1625906380106)(C:\Users\罗昕蕊\AppData\Roaming\Typora\typora-user-images\image-20210710153937561.png)]

RSA Last BIt Oracle Attack

假设存在一个Oracle,它会对一个给定的密文进行解密,并且会检查解密的密文的奇偶性,并根据奇偶性返回相应的值,比如1表示奇数,0表示偶数,那么给定一个加密后的密文,我们只需要log(N)次就可以知道这个密文对应的明文消息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7IPKqv92-1625906380107)(C:\Users\罗昕蕊\AppData\Roaming\Typora\typora-user-images\image-20210710154420241.png)]

服务器会计算得到2Pmod N

2P是偶数,它的幂次也是偶数

N是奇数,因为它是由两个大素数相乘得到的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sVFr7XYY-1625906380108)(C:\Users\罗昕蕊\AppData\Roaming\Typora\typora-user-images\image-20210710155346193.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Deh7c2Mf-1625906380109)(C:\Users\罗昕蕊\AppData\Roaming\Typora\typora-user-images\image-20210710155452506.png)]
最后还需要在小范围之内枚举确定明文的正确性

总结:

虽然目前密钥选择在1024~2048比特 的时候安全性比较高,但是我们选择其他参数时也要合理才能尽量避免攻击保证算法的安全

参数长度选择

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
RSA广播攻击是一种利用RSA加密算法的漏洞,攻击者通过将相同的明文消息分别使用不同的公钥加密,然后将密文广播给多个用户,从而达到获取私钥的目的。 在Python中,我们可以通过使用`Crypto`库来实施RSA广播攻击。首先,我们需要生成一对公私钥对,并将公钥分发给多个用户。 ```python from Crypto.PublicKey import RSA # 生成RSA密钥对 key = RSA.generate(2048) # 获取公私钥 public_key = key.publickey().export_key() private_key = key.export_key() ``` 然后,我们可以使用公钥对明文进行加密,并将密文发送给多个用户。 ```python from Crypto.Cipher import PKCS1_OAEP # 创建RSA加密器 cipher = PKCS1_OAEP.new(key) # 加密明文 message = b"Hello, RSA Broadcast Attack!" ciphertext = cipher.encrypt(message) # 广播密文给多个用户 broadcast(ciphertext) ``` 接下来,多个用户使用相同的RSA公钥来解密密文。 ```python # 从广播接收密文 ciphertext = receive_ciphertext() # 创建RSA解密器 cipher = PKCS1_OAEP.new(key) # 解密密文 plaintext = cipher.decrypt(ciphertext) print("Plaintext:", plaintext) ``` 由于RSA广播攻击实际上是利用相同的明文进行多次加密,然后对比多个密文,因此可以通过简单地比较多个密文是否相同来判断是否存在安全漏洞。 为了防止RSA广播攻击,我们应当使用随机化的因子(nonce)来对明文进行加密,这样即使使用相同的明文进行加密,也会得到不同的密文。此外,密文的传输应该使用安全的通信渠道来防止被截获。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值