1. 題目信息
附件中包含實現加密的Python腳本,與密文文件。
2. 分析
2.1. 有限域\(GF(2^{n})\)
構造有限域\(GF(2^{n})\)時,首先需要\(GF(2)\)上次數為n的本原多項式\(g(x)\);對於\(GF(2^{n})\)上的每個元素\(a\),都可以用一個次數不超過\(n\)的多項式\(f_{a}\)表示:\(f_{a}(x)=\sum_{i=0}^{n-1}a_{i}\cdot x^{i}\),其中\(a_{n-1}\cdots a_{0}\)是\(a\)的二進制表示;從而\(GF(2^{n})\)上的四則運算定義如下:
-
加法:對於\(a,b\in GF(2^{n})\),它們的多項式表示分別為\(f_{a},f_{b}\),記\(f_{c}=f_{a}+f_{b}\)(其中系數的加法為\(GF(2)\)上的加法,即異或運算),則\(c_{n-1}\cdots c_{0}\)的二進制值\(c\)為\(a+b\)的值;
-
減法:由於\(GF(2)\)上的加法與減法等價,因此對於\(a,b\in GF(2^{n})\),\(a+b=a-b\);
-
乘法:同樣地,\(a,b\)的多項式表示\(f_{a},f_{b}\),記\(f_c=f_{a}\cdot f_{b}\ \textrm{mod}\ g\),由於多項式\(g\)的次數為\(n\),故多項式\(f_{c}\)的次數不超過\(n\),則\(c_{n-1}\cdots c_{0}\)的二進制值\(c\)為\(a\cdot b\)的值;
-
除法:先介紹(乘法)逆元,本原多項式是一種具有特殊性質的不可約多項式,對GF(2)上任意次數不超過\(n\)的多項式f,都存在\(GF(2)\)上次數不超過n的多項式\(h\),使得\(f\cdot h \equiv 1\ \textrm{mod}\ g\);與\(f\)作除法等價於與\(f\)的逆元\(h\)作乘法;
2.2. process(m,k)
考慮\(t^{2},t\in GF(2^{256})\),構造\(GF(2^{256})\)的本原多項式為\(g=x^{256}+x^{10}+x^{5}+x^{2}+1\),記\(t\)的二進制表示為\(t_{n-1}\cdots t_{0}\),則\(t\)的多項式表示\(f_{t}(x)=\sum_{i=0}^{n-1}t_{i}\cdot x^{i}=(((t_{n-1}\cdot x+t_{n-2})\cdot x+\cdots +t_{1})\cdot x+t_{0})\),考慮\(t^{2}\):
\(f_{t}^{2}\ \textrm{mod}\ g\)
\(=(((t_{n-1}\cdot x+t_{n-2})\cdot x+\cdots +t_{1})\cdot x+t_{0})\cdot f_{t}\ \textrm{mod}\ g\)
\(=((((t_{n-1}\cdot f_{t})\cdot x+t_{n-2}\cdot f_{t})\cdot x+\cdots +t_{1}\cdot f_{t})\cdot x+t_{0}\cdot f_{t})\ \textrm{mod}\ g\)
\(=((((((t_{n-1}\cdot f_{t})\cdot x+t_{n-2}\cdot f_{t})\ \textrm{mod}\ g)\cdot x+\cdots +t_{1}\cdot f_{t})\ \textrm{mod}\ g)\cdot x+t_{0}\cdot f_{t})\ \textrm{mod}\ g\)
我們再來對比函數process(m,k):
def process(m, k):
tmp = m ^ k
res = 0
for i in bin(tmp)[2:]:
res = res << 1;
if (int(i)):
res = res ^ tmp
if (res >> 256):
res = res ^ P
return res
res=res<<1代表乘以x,多項式的系數全體左移一位;
if (int(i)):res^=tmp等價於res^=int(i)*tmp,代表\(+t_{i}\cdot f_{t}\);
if (res>>256):res^=P代表模本原多項式g;
綜上,process(m,k)實際上實現了\(GF(2^256)\)上的元素\(m\)與\(k\)之和的平方\((m+k)^{2}\);
2.3. 解密過程
\(k_{2}=(k_{1}+secret)^{2},k_{3}=(k_{2}+secret)^{2}\)(在GF(2^256)上的運算)
\(c_{1}=m_{1}\oplus k_{1},c_{2}=m_{2}\oplus k_{2},c_{3}=m_{3}\oplus k_{3}\),其中\(c_{i}(i=1,2,3),m_{i}(i=1,2)\)已知
則\(k_{2}=m_{2}\oplus c_{2},k_{3}=m_{3}\oplus c_{3}\),可解出secret:\(secret=k_{3}^{1/2}+k_{2}\)(在GF(2^256)上的運算)
接下來解出\(k_{1}\):\(k_{1}=k_{2}^{1/2}+secret\)(在GF(2^256)上的運算)
然后解出flag(即\(m_{1}\)):\(m_{1}=c_{1}\oplus k_{1}\)
3. 解題
實現的sage腳本如下:
from Crypto.Util.number import bytes_to_long,long_to_bytes
K.<x>=GF(2L**256,modulus=x^256+x^10+x^5+x^2+1)
def polify(N):
bN=list(bin(N)[2:])
bN.reverse()
return K(bN)
def unpolify(Poly):
bN=Poly.polynomial().list()
bN.reverse()
return long(''.join([str(it) for it in bN]),2)
def solve():
cip1=polify(0xaf3fcc28377e7e983355096fd4f635856df82bbab61d2c50892d9ee5d913a07f)
cip2=polify(0x630eb4dce274d29a16f86940f2f35253477665949170ed9e8c9e828794b5543c)
cip3=polify(0xe913db07cbe4f433c7cdeaac549757d23651ebdccf69d7fbdfd5dc2829334d1b)
msg2=polify(bytes_to_long('I_am_not_a_secret_so_you_know_me'))
msg3=polify(bytes_to_long('feeddeadbeefcafefeeddeadbeefcafe'))
secret=cip2+msg2+(cip3+msg3).sqrt()
key1=(cip2+msg2).sqrt()+secret
msg1=cip1+key1
return long_to_bytes(unpolify(msg1))
if __name__=='__main__':
print 'flag{'+solve()+'}'
程序運行結果如下:
$ sage solve.sage
flag{t0_B3_r4ndoM_en0Ugh_1s_nec3s5arY}