Bugku-CTF加密篇之python(N1CTF) [HRlgC2ReHW1/WRk2DikfNBo1dl1XZBJrRR9qECMNOjNHDktBJSxcI1hZIz07YjVx]


python(N1CTF)

 
 
 
本題要點: Feistel加密結構、 DES算法、AES算法 
 
 

代碼如下:
1 from N1ES import N1ES
2 import base64
3 key = "wxy191iss00000000000cute"
4 n1es = N1ES(key)
5 flag = "N1CTF{*****************************************}"
6 cipher = n1es.encrypt(flag)
7 print base64.b64encode(cipher)  # HRlgC2ReHW1/WRk2DikfNBo1dl1XZBJrRR9qECMNOjNHDktBJSxcI1hZIz07YjVx

 

 
代碼如下:
# -*- coding: utf-8 -*-
def round_add(a, b):
    f = lambda x, y: x + y - 2 * (x & y)
    res = ''
    for i in range(len(a)):
        res += chr(f(ord(a[i]), ord(b[i])))
    return res
 
 
def permutate(table, block):
        return list(map(lambda x: block[x], table))
 
 
def string_to_bits(data):
    data = [ord(c) for c in data]
    l = len(data) * 8
    result = [0] * l
    pos = 0
    for ch in data:
        for i in range(0,8):
            result[(pos<<3)+i] = (ch>>i) & 1
        pos += 1
    return result
 
 
s_box = [54, 132, 138, 83, 16, 73, 187, 84, 146, 30, 95, 21, 148, 63, 65, 189, 188, 151, 72, 161, 116, 63, 161, 91, 37, 24, 126, 107, 87, 30, 117, 185, 98, 90, 0, 42, 140, 70, 86, 0, 42, 150, 54, 22, 144, 153, 36, 90, 149, 54, 156, 8, 59, 40, 110, 56,1, 84, 103, 22, 65, 17, 190, 41, 99, 151, 119, 124, 68, 17, 166, 125, 95, 65, 105, 133, 49, 19, 138, 29, 110, 7, 81, 134, 70, 87, 180, 78, 175, 108, 26, 121, 74, 29, 68, 162, 142, 177, 143, 86, 129, 101, 117, 41, 57, 34, 177, 103, 61, 135, 191, 74, 69, 147, 90, 49, 135, 124, 106, 19, 89, 38, 21, 41, 17, 155, 83, 38, 159, 179, 19, 157, 68, 105, 151, 166, 171, 122, 179, 114, 52, 183, 89, 107, 113, 65, 161, 141, 18, 121, 95, 4, 95, 101, 81, 156, 17, 190, 38, 84, 9, 171, 180, 59, 45, 15, 34, 89, 75, 164, 190, 140, 6, 41, 188, 77, 165, 105, 5, 107, 31, 183, 107, 141, 66, 63, 10, 9, 125, 50, 2, 153, 156, 162, 186, 76, 158, 153, 117, 9, 77, 156, 11, 145, 12, 169, 52, 57, 161, 7, 158, 110, 191, 43, 82, 186, 49, 102, 166, 31, 41, 5, 189, 27]
 
 
def generate(o):
    k = permutate(s_box,o)
    b = []
    for i in range(0, len(k), 7):
        b.append(k[i:i+7] + [1])
    c = []
    for i in range(32):
                pos = 0
                x = 0
                for j in b[i]:
                        x += (j<<pos)
                        pos += 1
                c.append((0x10001**x) % (0x7f))
    return c
 
 
 
 
 
 
class N1ES:
    def __init__(self, key):
        if (len(key) != 24 or isinstance(key, bytes) == False ):
            raise Exception("key must be 24 bytes long")
        self.key = key
        self.gen_subkey()
 
 
    def gen_subkey(self):
        o = string_to_bits(self.key)
        k = []
        for i in range(8):
                o = generate(o)
                k.extend(o)
                o = string_to_bits([chr(c) for c in o[0:24]])
        self.Kn = []
        for i in range(32):
            self.Kn.append(map(chr, k[i * 8: i * 8 + 8]))
        return
 
 
    def encrypt(self, plaintext):
        if (len(plaintext) % 16 != 0 or isinstance(plaintext, bytes) == False):
            raise Exception("plaintext must be a multiple of 16 in length")
        res = ''
        for i in range(len(plaintext) / 16):
            block = plaintext[i * 16:(i + 1) * 16]
            L = block[:8]
            R = block[8:]
            for round_cnt in range(32):
                L, R = R, (round_add(L, self.Kn[round_cnt]))
            L, R = R, L
            res += L + R
        return res
 

 

 
 
 
從兩個文件的代碼可以判斷:
  N1ES.py是封裝好的類, challenge.py是定義的對象。 
 
 
先來解釋一下:
 
  一、什么是Feistel加密結構? 
 
 
 
構造過程:
 
令F 為輪函數;令K1,K2,……,Kn 分別為第1,2,……,n 輪的子密鑰。那么基本構造過程如下:
(1)將明文信息均分為兩塊:(L0,R0);
(2)在每一輪中,進行如下運算(i 為當前輪數):
Li+1 = Ri;
Ri+1 = Li ⊕F (Ri,Ki)。(其中⊕為異或操作)
所得的結果即為:(Ri+1,Li+1)。
 
解密過程:
 
對於密文(Rn+1,Ln+1),我們將i 由n 向0 進行,即, i = n,n-1,……,0。然后對密文進行加密的逆向操作,如下:
(1)Ri = Li+1;
(2)Li = Ri+1⊕F (Li+1,Ki)。(其中⊕為異或操作)
所得結果為(L0,R0),即原來的明文信息。
 
 
(圖片摘自百度百科)
 
Feistel 密碼結構,在密碼學研究中,Feistel 密碼結構是用於分組密碼中的一種對稱結構。
Feistel 的優點:由於它是對稱的密碼結構,所以對信息的加密和解密的過程就極為相似,甚至完全一樣。這就使得在實施的過程中,對編碼量和線路傳輸的要求就減少了幾乎一半。
 
  二、什么是des算法? 
 
DES(Data Encryption Standard)是目前最為流行的加密算法之一。
DES是對稱的,也就是說它使用同一個密鑰來加密和解密數據。
DES還是一種分組加密算法,該算法每次處理固定長度的數據段,稱之為分組。
DES分組的大小是64位,如果加密的數據長度不是64位的倍數,可以按照某種具體的規則來填充位。
 
算法原理:
1.輸入64位明文數據,並進行初始置換IP。
2.在初始置換IP后,明文數據再被分為左右兩部分,每部分32位,以L0,R0表示。
3.在秘鑰的控制下,經過16輪運算(f)。
4.16輪后,左、右兩部分交換,並連接再一起,再進行逆置換。
5.輸出64位密文。
 
 
 
 
 
 
  三、什么是AES算法? 
 
AES的全稱是Advanced Encryption Standard,意思是高級加密標准。
AES的出現主要是為了取代DES加密算法的,因為我們都知道DES算法的密鑰長度是56Bit,因此算法的理論安全強度是2的56次方。
 
算法流程:
 
 
 
介紹完成。
 
 (密碼學是真的難學! )
 
challenge.py中:  HRlgC2ReHW1/WRk2DikfNBo1dl1XZBJrRR9qECMNOjNHDktBJSxcI1hZIz07YjVx 為密文。
 
 
參考這位大佬的解密代碼如下:
(本人太菜,寫不出來,QAQ)
 
 
# -*- coding: utf-8 -*-
import base64
def round_add(a,b):
    f = lambda x,y: x + y - 2 * (x & y)
    res = ''
    for i in range(len(a)):
        res += chr(f(ord(a[i]),ord(b[i])))
    return res
 
 
def permutate(table,block):
    return list(map(lambda x: block[x], table))
 
 
def string_to_bits(data):
    data = [ord(c) for c in data]
    l = len(data)*8
    result = [0] * l
    pos = 0
    for ch in data:
        for i in range(0,8):
            result[(pos<<3)+i] = (ch>>i) & 1
        pos += 1
    return result
 
 
s_box = [54, 132, 138, 83, 16, 73, 187, 84, 146, 30, 95, 21, 148, 63, 65, 189, 188, 151, 72, 161, 116, 63, 161, 91, 37, 24, 126, 107, 87, 30, 117, 185, 98, 90, 0, 42, 140, 70, 86, 0, 42, 150, 54, 22, 144, 153, 36, 90, 149, 54, 156, 8, 59, 40, 110, 56,1, 84, 103, 22, 65, 17, 190, 41, 99, 151, 119, 124, 68, 17, 166, 125, 95, 65, 105, 133, 49, 19, 138, 29, 110, 7, 81, 134, 70, 87, 180, 78, 175, 108, 26, 121, 74, 29, 68, 162, 142, 177, 143, 86, 129, 101, 117, 41, 57, 34, 177, 103, 61, 135, 191, 74, 69, 147, 90, 49, 135, 124, 106, 19, 89, 38, 21, 41, 17, 155, 83, 38, 159, 179, 19, 157, 68, 105, 151, 166, 171, 122, 179, 114, 52, 183, 89, 107, 113, 65, 161, 141, 18, 121, 95, 4, 95, 101, 81, 156, 17, 190, 38, 84, 9, 171, 180, 59, 45, 15, 34, 89, 75, 164, 190, 140, 6, 41, 188, 77, 165, 105, 5, 107, 31, 183, 107, 141, 66, 63, 10, 9, 125, 50, 2, 153, 156, 162, 186, 76, 158, 153, 117, 9, 77, 156, 11, 145, 12, 169, 52, 57, 161, 7, 158, 110, 191, 43, 82, 186, 49, 102, 166, 31, 41, 5, 189, 27]
 
 
def generate(o):
    k = permutate(s_box,o)
    b = []
    for i in range(0,len(k),7):
        b.append(k[i:i+7]+[1])
    c = []
    for i in range(32):
        pos = 0
        x = 0
        for j in b[i]:
            x += (j<<pos)
            pos += 1
        c.append((0x10001**x) % (0x7f))
    return c
 
 
class N1ES:
    def __init__(self,key):
        if (len(key) != 24 or isinstance(key,bytes) == False):
            raise Exception("key must be 24 bytes long")
        self.key = key
        self.gen_subkey()
    
    def gen_subkey(self):
        o = string_to_bits(self.key)
        k = []
        for i in range(8):
            o = generate(o)
            k.extend(o)
            o = string_to_bits([chr(c) for c in o[0:24]])
        self.Kn = []
        for i in range(32):
            self.Kn.append(map(chr,k[i*8: i*8+8]))
        return
    
    def decrypt(self,plaintext):
        res = ''
        for i in range(len(plaintext)/16):
            block = plaintext[i*16:(i + 1)*16]    
            L = block[:8]
            R = block[8:]
            for round_cnt in range(32):
                L,R = R, (round_add(L, self.Kn[31-round_cnt]))
            L,R = R,L
            res += L + R
        return res
 
 
 
key = "wxy191iss00000000000cute"
nles = N1ES(key)
flag = base64.b64decode("HRlgC2ReHW1/WRk2DikfNBo1dl1XZBJrRR9qECMNOjNHDktBJSxcI1hZIz07YjVx")
flag = nles.decrypt(flag)
print flag
 
 

 

 
注:
這段代碼的運行環境為py2哦~ 
py3運行會報錯~
(然而突然發覺自己沒裝py2的環境.....假如你也沒裝,我們可以用菜鳥工具的python的在線運行網站運行啦~哈哈哈哈)
 
菜鳥工具的python的在線運行網站:
https://c.runoob.com/compile/6
 
 
 
 
如果你有py2的環境,你也可以這樣操作:
 
解密的源碼(參考自N1CTF baby_N1ES writeup):
import base64,string,N1ES
key = "wxy191iss00000000000cute"
c = base64.b64decode("HRlgC2ReHW1/WRk2DikfNBo1dl1XZBJrRR9qECMNOjNHDktBJSxcI1hZIz07YjVx")
n1es = N1ES.N1ES(key)
f=""
for i in xrange(3):
    for j in xrange(16):
        for k in string.printable:
            s="x"*i*16+"x"*j+k+"x"*(48-i*16-j-1)
            e=n1es.encrypt(s)
            check=c[i*16+j+8]==e[i*16+j+8] if j<8 else c[i*16+j-8]==e[i*16+j-8]
            if check:
                f+=k
                break
print f
 

 

 
 
把題目中給的兩個py文件和解密的源碼放在同一個文件夾下,然后運行cmd,就可以得到同樣的答案啦~
 
 
提交:
 
  N1CTF{F3istel_n3tw0rk_c4n_b3_ea5i1y_s0lv3d_/--/} 
 
 
bingo~
 
 
 
參考資料:
 
 
https://bbs.pediy.com/thread-253884.htm
https://baike.baidu.com/item/des算法/10306073?fr=aladdin
https://blog.csdn.net/prowes5/article/details/85167667
https://findneo.github.io/180310N1CTFWP/
 
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM