DES原理及Python實現

簡介

DES是分組密碼的一類,是一種對稱密碼技術,使用了Feistel的網絡結構,將明文分成多個等長模塊,使用確定的算法以及對稱並且相同的密鑰對明密文進行加解密。

F5u1LF.png

算法流程

  1. 64位的明文經過初始置換而被重新排列,並將其分爲左右兩個分組L0和R0各32位。
  2. 在密鑰的參與下,最左右兩個分組進行16輪相同函數的迭代,每輪迭代都有置換和代換。注意最後一輪迭代的輸出爲64位。左半部分和右半部分不進行交換。
  3. 最後的預輸出再通過逆初始置換產生64位的密文。
  4. 加解密過程一樣,反過來即可,也就是祕鑰列表得倒過來。所以得注意一下。

核心代碼及算法分析

第一部經過分是明文經過IP置換的操作,這裏可以直接用一維數組去完成,這需要注意的是數組下標不要寫錯,會導致數組越界,最後一部分IP逆的那一部分也一樣的道理。

def ip_change(bin_str):
    res = ""
    for i in IP_table:
        res += bin_str[i-1]     #數組下標i-1
    return res

#IP逆盒處理
def ip_re_change(bin_str):
    res = ""
    for i in IP_re_table:
        res += bin_str[i-1]
    return res

再下來就是經過16輪迭代的過程,每一步的迭代過程裏面又包含了F函數,還有密鑰的產生。

首先是一個大致的迭代過程,很清楚首先產生了16輪迭代的祕鑰,每一輪的迭代都有密鑰參與,並且通過切片完成了每一輪的左右分組,然後右邊的分組作爲了新的左邊,左邊的分組以及右邊的分組還有密鑰通過F函數的計算獲得新的右分組,最後一輪不做交換,這也就是我爲什麼只循環了15輪。

def des_encrypt_one(bin_message,bin_key): #64位二進制加密的測試
    #bin_message = deal_mess(str2bin(message))
    mes_ip_bin = ip_change(bin_message)
    #bin_key = input_key_judge(str2bin(key))
    key_lst = gen_key(bin_key)
    mes_left = mes_ip_bin[0:32]
    mes_right = mes_ip_bin[32:]
    for i in range(0,15):
        mes_tmp = mes_right
        f_result = fun_f(mes_tmp,key_lst[i])
        mes_right = str_xor(f_result,mes_left)
        mes_left = mes_tmp
    f_result = fun_f(mes_right,key_lst[15])
    mes_fin_left = str_xor(mes_left,f_result)
    mes_fin_right = mes_right
    fin_message = ip_re_change(mes_fin_left + mes_fin_right)
    return fin_message

再看看產生密鑰的關鍵代碼gen_key,傳進去的參數密鑰實際是64位的,但實際發揮作用的是56位,是因爲僅過了一次PC-1的置換,這也解釋了這段代碼爲什麼到後面切片的時候以28爲中心分左右。然後根據是第幾輪然後對左右分組的密鑰進行循環左移,出來的56位再經過一次置換生成48位的密鑰,最後用數組將所有密鑰都裝好。

def gen_key(key):
    key_list = []
    divide_output = change_key1(key)
    key_C0 = divide_output[0:28]
    key_D0 = divide_output[28:]
    for i in SHIFT:
        key_c = left_turn(key_C0,i)
        key_d = left_turn(key_D0,i)
        key_output = change_key2(key_c + key_d)
        key_list.append(key_output)
    return key_list

PC-1,PC-2的置換過程,跟IP置換差不多,都是利用了打表然後字符串拼接的方式實現

#祕鑰的PC-1置換
def change_key1(my_key):
    res = ""
    for i in PC_1:
        res += my_key[i-1]
    return res

#祕鑰的PC-2置換
def change_key2(my_key):
    res  = ""
    for i in PC_2:
        res += my_key[i-1]
    return res

重點還有F函數的處理,也即是代碼裏面的fun_f,這裏面主要有四個步驟,分別是擴展置換,密鑰加,經過S盒的代換,最後經過了P盒的置換,最終把32位的輸入變成48位的輸出。E盒以及P盒的置換也是很簡單打好表然後用字符串拼接就好。關鍵是S盒的變換原理,6位的輸入4位的輸出,輸入前兩位作爲S盒橫座標,中間4位作爲列,但是我這裏是以bin輸出得注意位數不夠四位得補齊

# F函數的實現
def fun_f(bin_str,key):
    first_output = e_key(bin_str)
    second_output = str_xor(first_output,key)
    third_output = s_box(second_output)
    last_output = p_box(third_output)
    return last_output

#E盒置換
def e_key(bin_str):
    res = ""
    for i in E:
        res += bin_str[i-1]
    return res

# S盒過程
def s_box(my_str):
    res = ""
    c = 0
    for i in range(0,len(my_str),6):
        now_str = my_str[i:i+6]
        row = int(now_str[0]+now_str[5],2)
        col = int(now_str[1:5],2)
        num = bin(S[c][row*16 + col])[2:]   #利用了bin輸出有可能不是4位str類型的值,所以纔有下面的循環並且加上字符0
        for gz in range(0,4-len(num)):
            num = '0'+ num
        res += num
        c  += 1
    return res

#P盒置換
def p_box(bin_str):
    res = ""
    for i in  P:
        res += bin_str[i-1]
    return res

正確性

加密解密內容都會放到文件裏面,然後通過讀寫文件的方式將內容成功加解密,以"helloworld"爲例,能夠正確加解密

F51J8s.png

詳細代碼(放在github上了):DES加解密

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