攻防世界-不僅僅是RSA

wyuu101發表於2024-12-01

一、題目
給出以下幾個檔案

py檔案程式碼如下

二、解題思路
1、聽C1,C2的音訊, 由長短聲很快確定是摩斯密碼,上網一搜,果然有線上摩斯密碼音訊解密網站,上去解密即可

這裡初步判斷可能是密文

2、進一步分析程式碼

分析程式碼發現這就是一個簡單的RSA加密演算法,並且有兩個不同公鑰的RSA加密過程,
但是可以發現他們的n中都有一個共同的q,由於p和q都是素數,所以可以從求解n1和n2的最大公因式入手。

3、但是公鑰都不知道,這時想起還有兩個檔案沒有用到,這不就是公鑰嗎

上網一查發現“.pem”檔案常常用來儲存公鑰,用檔案檢視器可以看到裡面的公鑰用base64的格式進行編碼。

但是這裡不進行解碼,因為公鑰只是一些無序的二進位制資料,並沒有什麼實際的文字意義,python的Crypto.PublicKey庫中的RSA模組提供公鑰檔案讀取函式,直接呼叫即可讀取入的公鑰有n和e,用圖示的辦法可以分別調出它們。

在安裝Crypto庫後出現了仍然無法呼叫庫函式的情況

上網查了一下找到了解決辦法:參考文章

4、有了n1和n2,現在可以利用歐幾里得輾轉相除法求取n1和n2的最大公約數q,這樣p1和p2就有了,一切都變得簡單。

5、由於n=p*q,求解出q後就可以求解p1和p2,需要注意的是使用整除符號“//”而不是除號“/”。

解釋:

  • 普通除法 /:會返回一個浮動型別的結果,即使除數能夠整除。
  • 整數除法 //:返回一個整數結果,去掉小數部分。

這裡可以驗證一下,如果使用“/”,可以看到p的型別是浮點數,而“//”的結果中p的型別是整數:

6、然後就是求解逆元d1和d2,最後利用d1和d2進行解密。第三方庫中的inverse()函式就是求解逆元d的函式,引數為e和尤拉數phi,引數只能接收整數,這也是之前需要使用整除符號的原因。

phi = (p-1)*(q-1) 這時RSA的常識

7、利用私鑰(n1,d1)和(n2,d2)解出明文m1和m2,再拼接即可得出flag

解密:m = e^d mod n

這裡需要注意Crypto.Util.number庫中的long_to_bytes模組,它是用來把這麼一大串長數字轉化為位元組串顯示。

補充:

  • 位元組串(bytes)是二進位制資料的原始表示,每個位元組表示一個數字值,範圍從0到255。它們用於儲存影像、音訊、影片、加密密文等非文字型別的資料。這些位元組可以是列印字元的編碼,也可以是無法顯示的控制字元或其他資料。
  • 位元組串中的每個位元組都可以用 \x 後跟十六進位制數字的形式表示,這些位元組值不一定對應於可列印字元。
  • print函式在列印位元組串的時候會預設使用utf-8進行解碼,如果位元組串不能被utf-8正確解碼,就會出現如下形式:

    這時可能要如果出現這種情況,要麼就是解密出現錯誤,要麼就是密文並不是簡單的文字形式,需要進行特殊的轉化。

8、指令碼程式碼

from Crypto.PublicKey import RSA
from Crypto.Util.number import inverse,long_to_bytes


with open("pubkey1.pem","rb") as f:
    pk1_bit= f.read()
with open("pubkey2.pem","rb") as f:
    pk2_bit =f.read();

pk1 = RSA.importKey(pk1_bit)
pk2 = RSA.importKey(pk2_bit)

n1 = pk1.n
e1 = pk1.e
n2 = pk2.n
e2 = pk2.e

c1 = 4314251881242803343641258350847424240197348270934376293792054938860756265727535163218661012756264314717591117355736219880127534927494986120542485721347351
c2 = 485162209351525800948941613977942416744737316759516157292410960531475083863663017229882430859161458909478412418639172249660818299099618143918080867132349

#求解兩數的最大公約數
def gcd(a,b):
    while(b!=0):
        r=a%b
        a=b
        b=r
    return a

p = gcd(n1,n2)
q1 = n1//p
q2 = n2//p

phi_1 = (p-1)*(q1-1)
phi_2 = (p-1)*(q2-1)

d1= inverse(e1,phi_1)
d2= inverse(e2,phi_2)

m1_bit = pow(c1,d1,n1)
m2_bit = pow(c2,d2,n2)

m1 = long_to_bytes(m1_bit)
m2 = long_to_bytes(m2_bit)


print(m1+m2)

9、最終答案
b'UNCTF{ac01dff95336aa470e3b55d3fe43e9f6}'

相關文章