RSA加密解密原理


引言
        CTF密碼學類題目中,RSA加密可謂是很重要且常見的加密類型,今天就總結下 RSA加密的原理及解密方法。


RSA算法簡介:

  • RSA加密算法是一種 非對稱加密 算法,RSA算法相比別的算法思路非常清晰,但是想要破解的難度非常大。

  • RSA算法基於一個非常簡單的數論事實:兩個素數相乘得到一個大數很容易,但是由一個大數分解為兩個素數相乘卻非常難。

1、什么是非對稱加密算法:

  • 對稱加密 算法使用同一個密鑰進行加密解密的方式不同,非對稱加密 算法是使用不同密鑰進行加密和解密的算法,也稱為公私鑰加密。

非對稱加密算法實現機密信息交換的基本過程:

  • 甲方生成 一對密鑰 並將其中的一把作為 公鑰 向其它方公開,得到該公鑰的乙方使用該密鑰對機密信息進行加密后再發送給甲方,甲方再用自己保存的另一把 私鑰 對加密后的信息進行解密。

圖解:
在這里插入圖片描述

2、RSA 加密原理:

了解了非對稱加密算法的原理,我們再來說說 RSA 加密算法的基本流程。

如圖:在這里插入圖片描述

3、RSA加密算法過程詳解:

先來了解一下什么是 互質數:

  • 兩個或多個整數的公因數只有1的非0自然數,則兩個非0自然數叫做互質數。例如 2 和 3,公因數只有1,所以為互質數。
1、找出質數 :

隨機找兩個質數 p 和 q ,p 與 q 越大,越安全。

2、計算公共模數:
 n = p * q 

假設 p = 65 ,q = 71。計算他們的乘積 n = p * q = 4615 ,轉化為二進制為 1001000000111,即該加密算法即為 13 位。位數越長,算法則越難被破解。實際應用中,RSA密鑰一般是1024位,重要場合則為2048位。

3、計算歐拉函數 φ(n):
φ(n) = φ(p*q) = (p-1)(q-1)

φ(n) 表示:在小於等於 n 的正整數之中,與 n 構成互質關系的數的個數。

例:

在 1 到 8 之中,與 8 形成互質關系的是1、3、5、7,所以 φ(n) = 4。

計算公式(即歐拉函數)為

前提:P 與 Q 均為質數

φ(n) = φ(P*Q)= (P-1)(Q-1) 

設:

P = 65 ,Q = 71

φ(n) = 64 * 70 = 4480 

即有4480 個數與 n(4615)互質。

4、計算公鑰 e:
1 < e < φ(n)

要求:

  • e 的取值必須是整數
  • e 和 φ(n) 必須是互質數
5、計算私鑰 d:

計算公式:

e * d % m = 1  其中(φ(n) = m)

即找一個整數 d,使得 (e * d ) % m = 1,等價於 e * d - 1 = y * m ( y 為整數)

得到 d ,實質就是對下面二元一次方程求解:

e * x - m * y = 1 e,m為已知量,求 x,y。

這個方程可以用 擴展歐幾里得算法 求解,此處就不詳細介紹了,可以看這個了解下: 擴展歐幾里得算法

得到:

  • 公鑰=(e,n)

  • 私鑰=(d,n)

對外,只暴露公鑰。

6、加密生成密文:

C = M e M^e Me mod n

C:密文 M:明文

7、解密生成明文:

M = C d C^d Cd mod n

C:密文 M:明文


下面舉一個完整的例子

4、示例:

1、找出質數 p 、q :

p = 3  
q = 11

2、計算公共模數 n:

n = p * q = 3 * 11 = 33
n = 33

3、計算歐拉函數 φ(n):

φ(n) = (p-1)(q-1) = 2 * 10 = 20
φ(n) = 20

4、計算公鑰 e:

1 < e < φ(n)
1 < e < 20

e 的取值范圍為: { 3, 7, 9, 11, 13, 17, 19 }

為了方便測試,我們取最小的值 e =3,3 和 φ(n) = 20 互為質數,滿足條件。

5、計算私鑰 d:

e * d % φ(n) = 1
3 * d % 20 = 1   

計算出 d = 7

6、公鑰加密:

公式:C = M e M^e Me mod n

隨便拿一個數字,這里方便演示 取 M = 2

C = 3 3 3^3 33 % 33 = 8

" M = 3 " 經過RSA加密后變成了 " C = 8 "

7、私鑰解密:

M = C d C^d Cd mod n

C = 8
d = 7
n = 33

計算:

M = 8 7 8^7 87 % 33

解得: M = 2


🆗,簡單了解 RSA的基本原理之后,來看幾個CTF中的RSA例題。

5、例題:

1、easy_RSA:

在這里插入圖片描述
打開附件:
在這里插入圖片描述
這題很簡單,就是求參數d 的值,那么如何計算d 呢?也就是如何求 e * x - m * y =1 式子中的 x ?

步驟:

1、先計算歐拉函數:
在這里插入圖片描述
得到 φ(n) = 2135733082216268400

2、求 d:

根據加密原理,解密的方法就是:把歐拉函數的值 +1,再除以17 * n(這里 n 先取1)
在這里插入圖片描述
得到 d = 125631357777427553,嘗試提交flag: cyberpeace{125631357777427553} 正確,看來 n 的值確實為 1 。( ̄▽ ̄)"

提供一個求私鑰腳本:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import gmpy2

p = 473398607161
q = 4511491
e = 17

m = (p-1)*(q-1)
d = int(gmpy2.invert(e,m)) //invert: 求逆元,返回值是一個 mpz 對象
print('私鑰為:',d)

運行結果(我的python出了點小問題):
在這里插入圖片描述
得到 d = 125631357777427553

2、i春秋 RSA :

在這里插入圖片描述
打開附件:
在這里插入圖片描述
可以看到題目給出了 n,e,c 三個值 ,求明文的值。

首先先對 n 進行因式分解,使用在線網站:大數分解網站

得到 p ,q :

在這里插入圖片描述

p = 310935513029228809998830208036655366162721470228774287453148308675193510132489142448801010943658159980501154153084396100667001391643762749806500051502679498536716532334917842894939889468693960937309663256592497965458780801192062835123429808
544757340971089756707788360038227894054989413747980167536893779923551227744017809301855984582408943622461942486239113822841696775958645014753081946441406022729616992302829930205076689399802050792392219242304302303180769915076199603301447453
07022538024878444458717587446601559546292026245318907293584609320115374632235270795633933755350928537598242214216674496409625928797450473
q = 310935513029228809998830208036655366162721470228774287453148308675193510132489142448801010943658159980501154153084396100667001391643762749806500051502679498536716532334917842894939889468693960937309663256592497965458780801192062835123429808
544757340971089756707788360038227894054989413747980167536893779923551227744017809301855984582408943622461942486239113822841696775958645014753081946441406022729616992302829930205076689399802050792392219242304302303180769915076199603301447453
07022538024878444458717587446601559546292026245318907293584609320115374632235270795633933755350928537598242214216674496409625928997877221

2、相關參數都已得到,就可以編寫腳本求明文信息了:

#!/usr/bin/env python
# coding:utf-8
import gmpy2   

p = gmpy2.mpz(31093551302922880999883020803665536616272147022877428745314830867519351013248914244880101094365815998050115415308439610066700139164376274980650005150267949853671653233491784289493988946869396093730966325659249796545878080119206283512342980854475734097108975670778836003822789405498941374798016753689377992355122774401780930185598458240894362246194248623911382284169677595864501475308194644140602272961699230282993020507668939980205079239221924230430230318076991507619960330144745307022538024878444458717587446601559546292026245318907293584609320115374632235270795633933755350928537598242214216674496409625928997877221)
q = gmpy2.mpz(31093551302922880999883020803665536616272147022877428745314830867519351013248914244880101094365815998050115415308439610066700139164376274980650005150267949853671653233491784289493988946869396093730966325659249796545878080119206283512342980854475734097108975670778836003822789405498941374798016753689377992355122774401780930185598458240894362246194248623911382284169677595864501475308194644140602272961699230282993020507668939980205079239221924230430230318076991507619960330144745307022538024878444458717587446601559546292026245318907293584609320115374632235270795633933755350928537598242214216674496409625928797450473)
e = gmpy2.mpz(65537)

#計算私鑰d
m = (p - 1) * (q - 1)
d = gmpy2.invert(e, m)
print "private key:",d

#求密文M
c = gmpy2.mpz(168502910088858295634315070244377409556567637139736308082186369003227771936407321783557795624279162162305200436446903976385948677897665466290852769877562167487142385308027341639816401055081820497002018908896202860342391029082581621987305533097386652183849657065952062433988387640990383623264405525144003500286531262674315900537001845043225363148359766771033899680111076181672797077410584747509581932045540801777738548872747597899965366950827505529432483779821158152928899947837196391555666165486441878183288008753561108995715961920472927844877569855940505148843530998878113722830427807926679324241141182238903567682042410145345551889442158895157875798990903715105782682083886461661307063583447696168828687126956147955886493383805513557604179029050981678755054945607866353195793654108403939242723861651919152369923904002966873994811826391080318146260416978499377182540684409790357257490816203138499369634490897553227763563553981246891677613446390134477832143175248992161641698011195968792105201847976082322786623390242470226740685822218140263182024226228692159380557661591633072091945077334191987860262448385123599459647228562137369178069072804498049463136233856337817385977990145571042231795332995523988174895432819872832170029690848)
print "明文:"
M  =  pow(c,d,p*q)
print '10進制: '+str(M)
flag = str(hex(M))[2:]# 從第3位為往后截取
print '16進制: '+flag
print 'ASCII碼: '+flag.decode('hex')

注釋:

  • gmpy2.mpz(x): 初始化一個大整數x
  • pow( x, y, z): 計算 x y x^y xy mod z

得到 flag:
在這里插入圖片描述
🆗,關與RSA的總結暫時就到這里了,以后發現好用的方法或解題技巧會接着更新。╰( ̄ω ̄o)


免責聲明!

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



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