護網杯比賽,一道不算難的密碼學卻思路繞了很久才和出題人相符合,這裏記錄一下作題的過程及感想安全
題目的源碼以下:app
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變量也是一串隨機的字符串dom
加密函數最外層是fez,而後fez中循環調用round函數進行加密,每一次循環都是使用K盒子中的一個隨機字符串,其中round是真正實現加密的過程,是一個異或的過程,異或是將傳入的明文的兩部分還有一個K做爲變量。函數
第一種思路:剛開始的時候,一看到urandom,便想到是否是僞隨機數,可是google了一段時間發現urandom算是一個強僞隨機數,仍是比較安全的,並且就算我知道隨機數種子,對於我前面解flag也沒有幫助,還得靠暴力破解,應該不是出題人想要考的,因此這條路是行不通的,主要是以往在比賽中作的一些題目不少用到了暴力破解,因此看到密碼學造成了一種思惟定式,就想看看能不能結合暴力破解來解題。。。。唉google
第二種思路:由於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異或,產生的新一輪的左右兩部分拼接成爲新的密文。spa
即假設初始明文爲M,分爲L和R兩部分code
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盒子和初始的明文的兩部分組成 blog
又由於在包含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.逆向分析,從後往前推