下載附件後,打開來爲四個簽名文件、被簽名的信息以及一份pem形式的公鑰spa
題目提示說此題的攻擊方式曾被用於PS3的破解。3d
首先了解一下DSA的簽名以及驗證的過程。blog
在簽名和驗證以前,須要肯定過程所須要的參數。ssl
公鑰密鑰:(公鑰)ci
P:512~1024位的素數input
Q:160位長,並於p-1互素的因子openssl
G:\(g=h^{(p-1)/q} mod p\),其中 h 小於 p-1 而且 \(h^{(p-1)/q} mod p > 1\)hash
Y:\(g^{x} mod p\)(此處的x爲私鑰)it
私鑰:class
x:x<q
簽名過程:
①隨機選取<q的一個隨機數k
②算出\(r=(g^k mod p)mod q\)
③算出\(s=k^{-1}*(H(m)+r*s) mod q\),此處的h(m)爲對消息m進行哈希運算
④得出簽名爲(r,s)
驗證過程:
①算出\(w=s^{-1} mod q\)
②算出\(u1=H(m)*w mod q\)
③算出\(u2=r*w mod q\)
④算出v=\((g^{u1})*(y^{u2}) mod q\)
⑤若v==r,則簽名有效,驗證成功
瞭解DSA簽名與驗證的過程後,再瞭解對於破解PS3的攻擊方式。這種方式其實就是基於隨機數k的重用攻擊。
若是在對消息的簽名過程當中,k的取值相同,那麼得出的簽名r是相同的,假設有兩份簽名,(r1,s1)與(r2,s2)且隨機值k相等,則:
r1=r2
\(s1=(k^{-1})*(H(m1)+r1*x) mod q\) —①
\(s2=(k^{-1})*(H(m2)+r2*x) mod q\) —②
利用②-①則
\((s2-s1)=(k^{-1})*(H(m2)-H(m1)) mod q\)
再轉換一下得:
\(k=((s2-s1)^{-1}) *(H(m2)-H(m1)) mod q\)
獲得k後,就能夠根據①式或者②式獲得私鑰x,這裏利用①式
\(x=(s1*k-H(m1))*(r1^{-1}) mod q\)
瞭解完原理後,轉到題目中來,若是運用了PS3的破解攻擊方式,那麼簽名中的r必定是相等的,使用010editor 觀察每份簽名文件,發現sign3.bin與sign4.bin的前部分字節相等。
這裏須要注意的是已知q的位數爲160位,所以r和s的位數都小於160位,觀察這兩份文件的sign.bin的字節,發現前26個字節都相等,說明須要判斷r與s的具體位置,能夠觀察得出0x0214很特殊,0x0124日後到下一個0x0214以前即是r,下一個0x0214以後即是s。最後,再根據pem文件格式的公鑰,使用openssl來獲得其中的p、q、g、y
這裏簡介一下這裏的用法
-in val Input key(val是個參數變量;如,-in key 就是放入密鑰)
-text Print the key in text (打印公鑰的參數值)
-modulus Print the DSA public value(打印出pub的值)
-pubin Expect a public key in input file(放入須要解析公鑰的輸入文件)
from Crypto.Util.number import *
from libnum import *
import hashlib
from Crypto.Hash import SHA
y=0x45BB18F60EB051F9D48218DF8CD956330A4FF30AF5344F6C9540061D5383292D95C4DFC8AC26CA452E170DC79BE15CC6159E037BCCF564EF361C18C99E8AEB0BC1ACF9C0C35D620D60BB7311F1CF08CFBC34CCAA79EF1DAD8A7A6FACCE86659006D4FAF057716857EC7CA604ADE2C3D731D6D02F933198D390C3EFC3F3FF046F
p=0xc0596c3b5e933d3378be3626be315ee70ca6b5b11a519b5523d40e5ba74566e22cc88bfec56aad66918b9b30ad281388f0bbc6b8026b7c8026e91184bee0c8ad10ccf296becfe50505383cb4a954b37cb588672f7c0957b6fdf2fa0538fdad83934a45e4f99d38de57c08a24d00d1cc5d5fbdb73291cd10ce7576890b6ba089b
q=0x868f78b8c8500bebf67a58e33c1f539d3570d1bd
g=0x4cd5e6b66a6eb7e92794e3611f4153cb11af5a08d9d4f8a3f250037291ba5fff3c29a8c37bc4ee5f98ec17f418bc7161016c94c84902e4003a7987f0d8cf6a61c13afd5673caa5fb411508cdb3501bdff73e747925f76586f4079fea12098b3450844a2a9e5d0a99bd865e0570d5197df4a1c9b8018fb99cdce9157b98500179
r1=0x5090DA81FEDE048D706D80E0AC47701E5A9EF1CC
s2=0x5E10DED084203CCBCEC3356A2CA02FF318FD4123
s1=0x30EB88E6A4BFB1B16728A974210AE4E41B42677D
m1=open("C:\ctf_exercise\jarvis\dsa\dsa\packet3\message3","rb")
m1=(m1.read())
m2=open("C:\ctf_exercise\jarvis\dsa\dsa\packet4\message4","rb")
m2=(m2.read())
sha = SHA.new()
sha.update(m1)
hm1=int(sha.hexdigest(),16)
sha = SHA.new()
sha.update(m2)
hm2=int(sha.hexdigest(),16)
print(hm1,hm2)
k=((hm2-hm1)*invmod((s2-s1),q))%q
x=(s1k-hm1)invmod(r1,q)
print(x%q)
運行結果以下:
獲得flag:CTF{520793588153805320783422521615148687785086070744}