護網杯一道密碼學的感想

       護網杯比賽,一道不算難的密碼學卻思路繞了好久才和出題人相符合,這裏記錄一下做題的過程及感想

       題目的源碼如下:

import os
def xor(a,b):
    assert len(a)==len(b)
    c=""
    for i in range(len(a)):
        c+=chr(ord(a[i])^ord(b[i]))
    return c
def f(x,k):
    return xor(xor(x,k),7)
def round(M,K):
    L=M[0:27]
    R=M[27:54]
    new_l=R
    new_r=xor(xor(R,L),K)
    return new_l+new_r
def fez(m,K):
    for i in K:
        m=round(m,i)
    return m

K=[]
for i in range(7):
    K.append(os.urandom(27))
m=open("flag","rb").read()
assert len(m)<54
m+=os.urandom(54-len(m))

test=os.urandom(54)
print test.encode("hex")
print fez(test,K).encode("hex")
print fez(m,K).encode("hex")

除了源碼,還給了三行16進制的數,看到這道題目時,首先分析一下題目,給了一個K盒子,用於加密過程使用,K是一個由7個隨機字符串產生的。其中m變量的前面一部分包含着flag,test變量也是一串隨機的字符串

加密函數最外層是fez,然後fez中循環調用round函數進行加密,每一次循環都是使用K盒子中的一個隨機字符串,其中round是真正實現加密的過程,是一個異或的過程,異或是將傳入的明文的兩部分還有一個K作爲變量。

       第一種思路:剛開始的時候,一看到urandom,便想到是不是僞隨機數,但是google了一段時間發現urandom算是一個強僞隨機數,還是比較安全的,而且就算我知道隨機數種子,對於我前面解flag也沒有幫助,還得靠暴力破解,應該不是出題人想要考的,所以這條路是行不通的,主要是以往在比賽中做的一些題目很多用到了暴力破解,所以看到密碼學形成了一種思維定式,就想看看能不能結合暴力破解來解題。。。。唉

       第二種思路:因爲test是已知的,第一次fez的調用中用到了test和K,並且密文也是已知的,那麼能不能解出來K,然後去解flag?於是回到round函數,可以看到最後一次加密結束時,用到的是K7,那麼最後一次的E_L和E_R我們是知道的,我們能不能推出前一次的L和R,也就是沒有經過輪加密的L和R,我們已經知道下一輪的密文L等於上一輪的R,下一輪的R等於上一輪的R異或L再異或當前輪所使用的K,那麼很容易得出我們能獲得上一輪所使用的明文的右半部分,有了上一輪的右半部分,加密後的新的右半部分,如果我們求出上一輪的左邊的部分,就能求出當前輪所使用的K,但是根絕目前已知的所有條件,上一輪的明文的左半部分是無法求出的,卡在這裏了很長時間,結果無奈放棄了

      第三種思路:正向來模擬加密的過程,來發現是否存在漏洞,在round函數中,新一輪的左半部分等於上一輪的右半部分,下一輪的右半部分等於上一輪的左右兩部分異或之後再和當前輪的K異或,產生的新一輪的左右兩部分拼接成爲新的密文。

      即假設初始明文爲M,分爲L和R兩部分

  

1 第一輪:R+R^L^K1
2 第二輪:R^L^K1+R^R^L^K1=>R^L^K1+L^K1^K2
3 第三輪:L^K1^K2+R^K2^K3
4 第四輪:R^K2^K3+L^R^K1^K3^K4
5 第五輪:L^R^K1^K3^K4+L^K1^K2^K4^K5
6 第六輪:L^K1^K2^K4^K5+R^K2^K3^K5^k6
7 第七輪:R^K2^K3^K5^k6+R^L^K1^K3^K4^K6^K7

由最終的形式可以看到,結果由K盒子和初始的明文的兩部分組成  

又因爲在包含flag的m變量中進行了相同的fez函數加密,所以和test調用fez函數以後的結果形式是相同的,只是初始的明文不同,又因爲根據異或運算的計算邏輯,相同的數異或爲0,0異或任何數還是其本身,所i有即使我們不知道K盒子,因爲兩次運算結果的K盒子在結果中的形式相同,所以可以抵消掉。

因此解爲兩部分:

1.第七輪結束後的密文的左半部分異或後實際就是test變量的右半部分和flag的右半部分進行了一次異或,再和test本身的右半部分異或一次,就能得到m變量的右半部分。

2.第七輪結束後的密文的左右兩部分異或得到只剩下原明文左半部分和K盒組成的結果,即兩次fez加密的結果的各自的左右兩部分先做異或運算,然後再把兩組異或結果再一起異或一次,即爲test變量的左半部分和m變量的左半部分異或的結果,又因爲test變量已知,所以把結果再和test變量的左半部分異或一次就能得到m的左半部分。

經過以上兩步,就能得到明文m,又因爲m中包含了flag,所以我們就解出了答案。

還是自己不懂套路,K盒屬於中間變量,並且加密爲異或加密,更何況這是已知密文的攻擊,調用了兩次相同的加密方式,使用的K盒也是相同的,所以才產生了這樣的漏洞,下次分析題目2條路:

1.先正向分析加密流程,分析加密後的結果組成,能不用暴力解決就不要用

2.逆向分析,從後往前推

 

 

     

 

 

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