簡單RSA攻擊方式


RSA攻擊方式總結

1.模數分解

1).解題思路

​ a).找到RSA算法中的公鑰(e,n)

​ b).通過n來找到對應的p和q,然后求得φ(n)

​ c).通過gmpy2.invert或者gmpy2.gcdext可以求得e的逆元d

​ d).通過pow函數將密文解密(pow(a,b,c)函數的速度比直接寫a**b mod c 要快)

2).直接分解n

​ a).通常情況下,如果n的長度小於256bit(二進制),那么可以通過本地的工具進行分解(RSATool2v17)

​ b).如果n的長度較大,可以嘗試在相關網站上進行查詢。這些網站上存儲着已經分解過的n對應的p和q

​ c).通常,如果n的長度大於512bit,可以考慮下面的方法進行解題

3).利用公約數(模不互素攻擊)

​ a).如果題目中兩次公鑰加密給出了n1和n2有相同的素因子,那么可以通過gmpy2.gcd求出素因子p,然后在分別對n1和n2求出q1和q2

​ b).這種需要利用公約數的題目,通常情況下給出的n長度都在2048bit,4096bit,無法強行破解

4).一些難度比較大的分解方法

​ a).針對大整數的分解有很多種算法,性能上各有優異,有指數級分解方法:Fermat平方差方法,Pollard 方法(ρ,ρ-1)(Pollard's rho algorithm),二次型分解算法,橢圓曲線分解法(ECM)和亞指數級分解方法:連分數分解算法,篩法(二次篩選法(QS),一般數域篩法(GNFS))等等。

​ b).但是,有一個開源項目yafu可以自動化的完成分解,不論n的大小(密碼學工具使用)

5).做題過程中get到的方法,有可能是方法4里面的包括的

  1. 知道了\(\phi (n)\),就可以開方:

    這個算法涉及兩個點,開方后的取值的大小 Q, Q<p<q, 或 p<Q<q

    1.p<Q<q

    假設 p=7,q=11,,則(p-1)*(q-1)=60,
    iroot(60,2)[0] = 7 (iroot()表示開根號,[0]表示取整數部分)
    所以用sympy.next(7),就可以求得7后面的一個素數11

    2.Q<p<q

    假設 p=3,q=5, 則(p-1)*(q-1)=8,
    iroot(8,2)[0] = 2 (iroot()表示開根號,[0]表示取整數部分)
    所以用sympy.next(2),就可以求得2后面的一個素數3

    3.

    雖然Q取值范圍不定,但是我們可以肯定的是,Q一定小於max(p,q),即p,q中最大的那個數。所以通過nextprime(Q),就可以求得p,q中任意的值。再用已知的 (ed-1)//k == (p-1)(q-1),就可以求得(p-1)或是(q-1)的值了。最后再進行素性檢測就可以了
    原文地址:BUUCTF RSA題目全解2的第十題

2.低加密指數攻擊

​ RSA中,e也被稱作加密指數,由於e是從(1,φ(n))中任意選取的,有些時候為了縮短加密時間,可以適當的選擇較小的e。

1).e=3的小明文攻擊(暴力開方破解)

​ a).當e=3時,如果明文過小,導致明文的三次方仍然小於n,那么直接對密文三次開方,就可以得到明文(a如果小於n,則a mod n==a)

​ b).如果明文的三次方大於n,但是不是很大,就可以設k,有:

\[c=m^e+kn \]

​ 對k進行爆破,若 \(c-kn\) 可以開三次根式,那么可以直接得到明文

​ c).使用加密指數e=\(2^{16} +1\)=65537(費馬素數[1])可以避免一些對e=3的攻擊

​ d).也可以將明文進行填充

2).低加密指數廣播攻擊(Johan Håstad廣播攻擊)

​ a).如果選取的加密指數e較小,且給多個接收方用這個e發送相同的明文(n不同),那么就可以進行廣播攻擊

​ b).當收集到的加密消息個數大於或等於e時,有(假設e=3)如果是根據中國剩余定理,那么加密消息至少得有三個(一個和兩個不能得出一組確切的解)

\[\begin{cases} c_1\equiv m^e (mod\ n_1)\\ c_2\equiv m^e (mod\ n_2)\\ c_3\equiv m^e (mod\ n_3)\end{cases} \]

​ 則根據中國剩余定理,可知:

\[m^e=(\sum_{i=1}^{n}{c_i*N_i*N_i^{-1}})\%N \]

​ 對m開e次方根,即可求得明文。

​ 注:\(N_i^{-1}\)\(N_i\)\(n_i\)的逆元

3)Coppersmith短填充攻擊

3.低解密指數攻擊

​ a).同樣的,低解密指數通常會加快解密的速度,但是也會帶來安全隱患

​ b).如果解密指數\(d<\frac{1}{3}N^\frac{1}{4}\),那么一種由Wiener提出的基於連分式的算法可以解出該解密指數(使用了連分式的經典數論理論以及如何找到用有理數對二次無理數最合理的逼近方法)。工具rsa_wiener_attack

​ c).再后來,Boneh指出,使用小於\(\sqrt{N}\)的解密指數的系統可能容易受到此類攻擊

image

由圖可知,解密指數的攻擊范圍被提高了

4.共模攻擊

​ 如果出現了用相同的模數n來加密相同的明文m(加密指數e不一樣),則會得到

\[\begin{cases} c_1\equiv m^{e_1} (mod\ n) \\ c_2\equiv m^{e_2} (mod\ n) \end{cases} \]

​ 此時

​ a).可以利用米勒公式,通過一個人的秘鑰(\(e_i,d_i\))分解n得到p,q,從而可以通過別人的公鑰來計算別人的私鑰

​ b).如果兩個加密指數互素,那么根據擴展你歐幾里得方程可知,有:

\[e_1s_1+e_2s_2=\gcd(e_1,e_2)=1 \]

​ 那么可得

\[\begin{equation} \begin{aligned} (c_1^{s_1}*c_2^{s_2})\%n &=((m^{e_1}\%n)^{s_1}*(m^{e_2}\%n)^{s_2})\%n \\ &=(m^{(e_1s_1+e_2s_2)})\%n \\ &=m\%n \end{aligned} \end{equation} \]

​ 所以,可以得到

\[c_1^{s_1}*c_2^{s_2}\equiv m (mod\ n) \]

​ 所以,我們在完全不知道密鑰的前提下,得到了明文m

​ 注意:在Python的pow函數中,指數不可以為負數,而\(s_1\)\(s_2\)中必然有一個是負數,則需要將對應的c取反,再用-s作為指數進行運算[2]

k,s1,s2=gmpy2.gcdext(e1,e2)
if s1<0:
    s1=-s1
    c1=gmpy2.invert(c1,n)
else:
    s2=-s2
    c2=gmpy2.invert(c2,n)
m=pow(c1,s1,n)*pow(c2,s2,n)%n   #雖然不知道為什么,但是好像這樣寫運算會很快

print("所求明文為:",m)
print(long_to_bytes(m))

5.前向搜索攻擊[3]

如果知道所有可能消息的集合,而且該集合相對來說比較小,則攻擊者只需要將所有的消息進行加密直到找到一個匹配者。例 如,如果已知消息為‘YES’或‘NO’,那么只需要計算一次就知道哪一個是明文。因此,特別是在比較短小的消息的情況下,應該通過在前面或者后面添加隨機位數的填充信息。

6.教科書RSA的兩個性質和攻擊方法[4]

教科書RSA是確定性的,意即同樣的明文m總是生成同樣的密文c。這就使密碼本攻擊成為可能:攻擊者預先計算出全部或部分的\(m\to c\) 對照表保存,然后搜索截獲的密文匹配即可。確定性也意味着教科書RSA不是語義安全的,密文會泄露明文的某些信息。密文重復出現,表明發送方在重復發送相同的消息。

教科書RSA具有延展性 (malleable),對密文進行特定形式的代數運算,結果會反映到解密的明文中。比如有兩段明文 \(m_1\)\(m_2\),加密后產生\(c_1= m_1^{e}\%N\)\(c_2= m_2^e\%N\),那么(\(c_1*c_2\))解密會得到什么?看如下等式:

\[(c_1*c_2)^d\equiv m_1^{ed}*m_2^{ed}\equiv m_1*m_2(mod\ N) \]

所以兩段密文的乘積解密后得到的明文,等於兩段明文的乘積。這一特性對一般的RSA加密系統是有害的,它為選擇密文攻擊 (chosen-ciphertext attack) 提供了機會。下面舉例兩種攻擊場景:

1.設想有一個RSA解密機可以用內部保存的私鑰(N,d)解密消息。基於安全考慮,解密機會拒絕同樣的密文重復輸入。攻擊者馬文發現一段密文,直接輸入到解密機被拒絕,因為密文c以前被解密過。馬文找到一種辦法破解。他自己准備一段明文,用公鑰(N,e)加密生成新的密文\(c'=r^ec\%N\),然后將密文\(c'\)輸入到解密機。解密機沒有解過這一段新的密文,所以不會拒絕。解密的結果是

\[m'\equiv (c')^d\equiv r^{ed}c^d\equiv rm(mod\ N) \]

現在馬文有了\(m'\),他用公式\(m\equiv m'r^{-1}(mod\ N)\)就可以計算出c對應的m

2.假設馬文想讓鮑勃在一段消息\(m\)上簽名,但是鮑勃在看過消息內容后拒絕了。馬文可以使用稱為盲簽名的攻擊手段可以達成他的目標。他挑選一段隨機的消息\(r\),生成 \(m'=r^em\%N\),然后把\(m'\)拿給鮑勃簽名。鮑勃可能覺得\(m'\)無關緊要,就簽了。鮑勃簽名的結果是\(s'=(m')^d\%N\)。現在馬文用公式\(s=s'r^{-1}\%N\)就拿到了鮑勃對原來消息的簽名。為什么?原因是

\[s^e\equiv (s')^er^{-e}\equiv(m')^{ed}r^{-e}\equiv m(mod\ N) \]

7.其它常見的題型總結

​ 1).給出了dp、dq的題

​ 首先明確dp、dq是什么:

\[dp= d\%(p-1) \\ dq=d\%(q-1) \]

情況1:dp、dq都給出來了

​ 解決方法:

\[\begin{aligned} &m_1\equiv c^{dq}(mod\ q)\\&m_2\equiv c^{dp}(mod\ p)\\&m\equiv (((m_2-m_1)*(p-1)\%q)*p+m_1)\%n \end{aligned} \]

​ 證明:已知\(m\equiv c^{d}(mod\ n)\)​,可得到\(m=c^{d}+k*n\)

​ 又因為\(n=p*q\),可得\(m=c^{d}+p*q*k\),對它分別取余p,q

​ 可得\(m_1\equiv c^{d}(mod\ p)\)(1),\(m_2\equiv c^{d}(mod\ q)\)(2)

​ 式(1)可以變形為\(c^{d}=kp+m_1\),帶入(2),可得\(m_2\equiv (kp+m_1)(mod\ q)\)

​ 兩邊同時減去\(m_1\),可得\((m_2-m_1)\equiv kp(mod\ q)\)

​ 因為p,q互素(\(gcd(p,q)=1\)),可以求得p的逆元,得到

\[(m_2-m_1)*p^{-1}\equiv k(mod\ q) \]

​ 將它變形為

\[k\equiv (m_2-m_1)*p^{-1}(mod\ q) \]

​ 然后與上面(1)的變形合並,可得

\[c^{d}=((m_2-m_1)*p^{-1}(mod\ q))*p+m_1 \]

​ 將\(m\equiv c^{d}(mod\ n)\),得到

\[m\equiv ((m_2-m_1)*p^{-1}(mod\ q))*p+m_1(mod\ n)\ \ (\alpha) \]

​ 現在根據費馬小定理[5]可以將dp、dq帶入\(m_1\)\(m_2\)中得到

\[m_1\equiv c^{dq}(mod\ q)\ \ (\beta)\\m_2\equiv c^{dp}(mod\ p)\ \ (\gamma) \]

​ 這一步帶入的證明見注釋[6]

​ 則式子\((\alpha)(\beta)(\gamma)\)即為所求。

from Crypto.Util.number import long_to_bytes
c=int(input("請輸入密文c"))
n=int(input("請輸入n(不存在請輸入0)"))   
#存在給出p,q沒有給出n的情況
p=int(input("請輸入p(不存在請輸入0)")) 
q=int(input("請輸入q(不存在請輸入0)")) 
dp=int(input("請輸入dp")) 
dq=int(input("請輸入dq")) 
if n==0:
    n=p*q
m1=pow(c,dq,q)
m2=pow(c,dp,p)
k=(m2-m1)*(p-1)%q
m=k*p+m1%n
print("所求明文為:",m)
print(long_to_bytes(m))

情況2:只給出了dp/dq的題

​ 假設給出的是dp,則有\(dp=d\%(p-1)\),變形可得

\[d*e=k_1*(p-1)*e+dp*e \]

​ 變形后與式子\(d*e\equiv 1(mod\ \phi(n))\)結合,可得

\[\begin{aligned} k_1*e*(p-1)+dp*e&=1+k_2*(p-1)*(q-1)\\ dp*e&=[k_2*(p-1)*(q-1)+1]-[k_1*e*(p-1)]+1\\ dp*e&=[k_2*(q-1)-k_1*e]*(p-1)+1 \end{aligned} \]

​ 設:X=\(k_2*(q-1)-k_1*e\),有\(dp*e=X*(p-1)+1\),因為\(dp=d\%(p-1)\),所以\(dp<p-1\),可得\(X<e\)\(X\in(0,e)\)和式子\((p-1)=\frac{dp*e-1}{X}\)

​ 則有遍歷區間(0,e),找到一個X可以整除(不是被整除)(dp*e-1),且對應的p能夠整除n的情況,然后求出q,即可得到明文。

​ 給出dq同理。

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

import gmpy2
e = 65537
n = 248254007851526241177721526698901802985832766176221609612258877371620580060433101538328030305219918697643619814200930679612109885533801335348445023751670478437073055544724280684733298051599167660303645183146161497485358633681492129668802402065797789905550489547645118787266601929429724133167768465309665906113
dp = 905074498052346904643025132879518330691925174573054004621877253318682675055421970943552016695528560364834446303196939207056642927148093290374440210503657

c = 140423670976252696807533673586209400575664282100684119784203527124521188996403826597436883766041879067494280957410201958935737360380801845453829293997433414188838725751796261702622028587211560353362847191060306578510511380965162133472698713063592621028959167072781482562673683090590521214218071160287665180751

for X in range(2,e):
    if (dp*e-1)%X == 0:
        if n%(((dp*e-1)//X)+1)==0:  #這里和下面的//如果換成/就會出現OverflowError: int too large to convert to float的問題
            p=((dp*e-1)//X)+1
            q=n//(((dp*e-1)//X)+1)
            phi = (p-1)*(q-1)
            d = gmpy2.invert(e,phi)%phi
            m=pow(c,d,n)

參考來源:

  1. 【技術分享】CTF中RSA的常見攻擊方法

  2. 《密碼學導引》(美)Paul Garrett著

  3. 《現代密碼分析學——破譯高級密碼的技術》(美)Christopher Swenson著

  4. CTF-RSA1(已知p、q、dp、dq、c)

  5. RSA的攻與防(一)

  6. RSA的dp泄露 [BUUCTF] RSA2


  1. 費馬素數:是一類特殊形式的數,形如\(2^m+1\)​的數如果是素數,那么它被稱作費馬素數。與之相對的是梅森素數:形如\(2^n-1\)​的素數 ↩︎

  2. \(c_1^{s}=(c_1^{-1})^{-s}\%n\) ↩︎

  3. 這一段來自參考來源2 ↩︎

  4. 這一段來自參考來源5 ↩︎

  5. 費馬小定理:如果有條件:1). p為素數,2). \(gcd(a,p)=1\),則有式子\(a^{p-1}\equiv1(mod\ p)\)成立。這個定理也常常用來計算乘法逆元:\(a*a^{p-2}\equiv1(mod\ p)\),則\(a^{p-2}\)是a的乘法逆元 ↩︎

  6. 證明:由於費馬小定理,可知在c和p互素的情況下(p必然是素數),那么將式子\(d=dp+k*(p-1)\)帶入式子\(m_2\equiv c^d (mod\ p)\),可得 \(m_2\equiv c^{dp+k(p-1)}(mod\ p)\)\(m_2\equiv c^{dp}*c^{k(p-1)}(mod\ p)\)。因為\(c^{(p-1)}\equiv 1(mod\ p)\),可得:\(m_2\equiv c^{dp}*(1)^k (mod\ p)\)\(m_2\equiv c^{dp}(mod\ p)\),根據對稱性,可知\(m_1\)同理。 ↩︎


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM