網絡安全:非對稱加密RSA算法

RSA算法

RSA算法可以說是使用最爲廣泛的非對稱加密算法。在1977年由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的,並取三人名字的首字母命名。其中的數學原理大致如下:

加密過程

RSA加密過程簡單描述如下:

  1. 選兩個大質數 p,qp, q,計算n=pqn=p\cdot q
  2. 選一個大於1的整數ee,滿足ee(p1)(q1)(p-1)(q-1) 互質,ee要小於後者;
  3. 數據xx加密後爲yy,那麼加密後的數據 y=xemod  ny=x^e\mod n;

這裏(n,e)(n,e)就作爲公鑰。其中(p1)(q1)(p-1)(q-1)nn歐拉函數ϕ(n)\phi(n)

解密過程

  1. 找到一個數字dd,滿足 de1mod  (p1)(q1)de\equiv1\mod(p-1)(q-1);
  2. 數據yy解密還原爲xx ,那麼 x=ydmod  nx=y^d\mod n;

這裏(n,d)(n,d)就作爲私鑰。其中ddeeϕ(n)\phi(n)模反元素

舉例

  1. p=11,q=17p=11, q=17,那麼n=1117=187n=11\cdot17=187;
  2. e=3e=3, 與(111)(171)=160(11-1)(17-1)=160互質,公鑰(n,e)(n,e)
  3. d=107d=107, 滿足de1mod  160d\cdot e\equiv1 \mod160,私鑰(n,d)(n,d);
  4. 加密數字x=20x=20,那麼y=xemod  n=203mod  187=146y=x^e\mod n=20^3\mod187=146;
  5. 解密數據y=146y=146, 那麼x=ydmod  n=146107mod  187=20x=y^d\mod n=146^{107}\mod 187=20;

使用python內置的pow函數, pow(x,y[,z])就是x的y次方對z取模。

>>> x = 20
>>> y = pow(x, 3, 187)  # 公鑰(187, 3), 加密x
>>> y
146
>>> pow(y, 107, 187)    # 私鑰(187, 107), 解密y
20

應用場景

通過前面RSA的數學過程可以看出,公鑰私鑰在加解密上是對稱的,即公鑰加密私鑰解密,私鑰加密公鑰也可以解密。那麼結合公鑰私鑰的公開與保密特點,可以看出有如下經典實用場景:

  • 數據加密:公鑰廣而告之,公鑰所有者都可加密數據,只有私鑰所有者可以解密數據;
  • 數字簽名:私鑰私密擁有,只有私鑰所有者可以製作數字簽名,任何有公鑰的人可驗證簽名;

這裏再詳細說一下數字簽名。數字簽名通常還需要結合摘要算法。完整的數據報文通過摘要算法hash出一個固定長度的字符串,比如Git使用的SHA1算法,文件MD5算法等。然後對摘要內容使用私鑰加密生成數字簽名。對方驗證數字簽名的時候,也是先用同樣的摘要算法算出摘要,然後使用公鑰解密簽名還原摘要,對比兩者是否相同。

理論證明

RSA算法用到的數論知識有:歐拉定理費馬小定理擴展歐幾里得算法(生成一組公私鑰)。理解這些數論原理的證明是有一定難度,但是通過這些數論原理來理解RSA的如何加密解密就相對簡單了,致敬那些偉大的數學家。

在知乎上如何用通俗易懂的話來解釋非對稱加密,有個回答很形象:

讓對方任意想一個3位數,並把這個數和91相乘,然後告訴我積的最後三位數,我就可以猜出對方想的是什麼數字啦!

比如對方想的是123,那麼對方就計算出123 * 91等於11193,並把結果的末三位193告訴我。看起來,這麼做似乎損失了不少信息,讓我沒法反推出原來的數。不過,我仍然有辦法:只需要把對方告訴我的結果再乘以11,乘積的末三位就是對方剛開始想的數了。可以驗證一下,193 * 11 = 2123,末三位正是對方所想的祕密數字!

其實道理很簡單,91乘以11等於1001,而任何一個三位數乘以1001後,末三位顯然都不變(例如123乘以1001就等於123123)。

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章