DES algorithm Python implementation source code

Introduction to DES

DES is a symmetric key encryption algorithm originally developed by IBM in the 1970s. DES uses a 56-bit key and a series of permutation, replacement, and XOR operations to encrypt and decrypt data. Although DES is considered a strong encryption algorithm, it is currently considered insecure due to its short key length and has been replaced by more powerful algorithms such as AES.

Algorithm implementation flow chart

Encryption Algorithm

DES flow chart

Key expansion algorithm

The 64-bit subkey generates 16 48-bit subkeys through permutation selection 1, circular left shift, and permutation selection 2. The number of circular left shifts is related to the number of iteration rounds . The 1st, 2nd, 9th, and 16th rounds are circular left shifts
Key expansion algorithm
. 1 bit, the rest rotate left by 2 bits

source code

Encryption Algorithm

IP_table = [58, 50, 42, 34, 26, 18, 10, 2,
            60, 52, 44, 36, 28, 20, 12, 4,
            62, 54, 46, 38, 30, 22, 14, 6,
            64, 56, 48, 40, 32, 24, 16, 8,
            57, 49, 41, 33, 25, 17, 9, 1,
            59, 51, 43, 35, 27, 19, 11, 3,
            61, 53, 45, 37, 29, 21, 13, 5,
            63, 55, 47, 39, 31, 23, 15, 7]
IP_table_reverse = [40, 8, 48, 16, 56, 24, 64, 32,
          39, 7, 47, 15, 55, 23, 63, 31,
          38, 6, 46, 14, 54, 22, 62, 30,
          37, 5, 45, 13, 53, 21, 61, 29,
          36, 4, 44, 12, 52, 20, 60, 28,
          35, 3, 43, 11, 51, 19, 59, 27,
          34, 2, 42, 10, 50, 18, 58, 26,
          33, 1, 41, 9,  49, 17, 57, 25]
E_table = [32, 1, 2, 3, 4, 5,
           4, 5, 6, 7, 8, 9,
           8, 9, 10, 11, 12, 13,
           12, 13, 14, 15, 16, 17,
           16, 17, 18, 19, 20, 21,
           20, 21, 22, 23, 24, 25,
           24, 25, 26, 27, 28, 29,
           28, 29, 30, 31, 32, 1
           ]
S_boxs = [
# 定义8个S盒
    # S1盒
    [
        [14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7],
        [0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8],
        [4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0],
        [15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13]
    ],
    # S2盒
    [
        [15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10],
        [3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5],
        [0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15],
        [13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9]
    ],
    # S3盒
    [
        [10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8],
        [13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1],
        [13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7],
        [1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12]
    ],
    # S4盒
[
    [ 7, 13, 14,  3,  0,  6, 9,  10,  1, 2, 8,  5, 11,  12,  4,  15],
    [13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9],
    [10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4],
    [ 3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14],
],
    # S5
[
    [2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9],
    [14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6],
    [4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14],
    [11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3]
],
    #S6盒
[
    [12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11],
    [10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8],
    [9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6],
    [4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13]
],
    # S7盒
[
    [4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1],
    [13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6],
    [1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2],
    [6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12]
],
    # S8盒
[
    [13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7],
     [1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2],
     [7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8],
     [2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11]
]


]
P = [
    16,7,20,21,
    29,12,28,17,
    1,15,23,26,
    5,18,31,10,
    2,8,24,14,
    32,27,3,9,
    19,13,30,6,
    22,11,4,25
]
PC1 = [57, 49, 41, 33, 25, 17, 9,
       1, 58, 50, 42, 34, 26, 18,
       10, 2, 59, 51, 43, 35, 27,
       19, 11, 3, 60, 52, 44, 36,
       63, 55, 47, 39, 31, 23, 15,
       7, 62, 54, 46, 38, 30, 22,
       14, 6, 61, 53, 45, 37, 29,
       21, 13, 5, 28, 20, 12, 4]
PC2 = [14, 17, 11, 24, 1, 5,
       3, 28, 15, 6, 21, 10,
       23, 19, 12, 4, 26, 8,
       16, 7, 27, 20, 13, 2,
       41, 52, 31, 37, 47, 55,
       30, 40, 51, 45, 33, 48,
       44, 49, 39, 56, 34, 53,
       46, 42, 50, 36, 29, 32]


def input_binary(ls, str, length):
    while True:  # input key
        s = input("please input {}(length is {} bit):".format(str, length))
        if len(s) != length:
            print("the length of {} should be {},please input again:".format(str, length))
        else:
            break;
    for c in s:
        ls.append(int(c))


def output_ls(ls, s):
    print(s+":")
    space = 0
    for i in ls:
        print(i, end="")
        space += 1
        if space == 8:
            space = 0
            print(" ", end="")
    print("\n")




def product_transformation(ls, k, od):
    """

    :param ls: 乘积变换输入
    :param k: 每一轮的轮密钥
    :param od: 判断是不是第16轮
    :return:
    """
    l = ls[0:32]
    r = ls[32:64]
    s = []
    s2 = [0]*32
    temp = []
    for i in range(0,48):                # 选择运算扩展位数
        temp.append(r[E_table[i]-1])
    temp = [a^b for a,b in zip(temp,k)]  # 结果与轮密钥k异或
    for i in range(0,8):                 # 查S盒
        index = i*6
        row =2*temp[index]+temp[index+5]
        col = 8*temp[index+1]+4*temp[index+2]+2*temp[index+3]+temp[index+4]
        s_box = S_boxs[i]
        a = s_box[row][col]
        st = bin(a)[2:]
        binary_list = [int(bit) for bit in st]
        s1=[0]*(4-len(binary_list))+binary_list
        s.extend(s1)
        # 置换运算P
    for i in range(0,32):
        s2[i] = s[P[i]-1]
        # 异或运算
    xor_list = [a ^ b for a, b in zip(l, s2)]    # 结果与Li异或
    lis = [0]*32
    for i in range(0, 32):
        lis[i] = ls[i+32]
    ls = ls[32:]+xor_list
    return ls


def generate_round_key(ls, round_key):
    bit_num = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]
    ls1 = [0]*56
    k = [0]*48
    for i in range(0, 56):
       ls1[i] = ls[PC1[i]-1]      # PC1置换
    for i in range(0, 16):
        ls1 = ls1[bit_num[i]:28]+ls1[0:bit_num[i]]+ls1[28+bit_num[i]:]+ls1[28:28+bit_num[i]]  # 循环左移
        for j in range(0, 48):
            k[j] = ls1[PC2[j]-1] # PC2置换
        round_key.append(k.copy())


def des_encode():
    key = [] # 0011000100110010001100110011010000110101001101100011011100111000
    M = []  #  0011000000110001001100100011001100110100001101010011011000110111
    round_key = []
    temp_list = [0]*64
    ciphertext = [0]*64
    input_binary(M, "plaintext", 64)  # 输入明文
    input_binary(key, "key", 64)        # input 密钥

    # sk = "0011000100110010001100110011010000110101001101100011011100111000"  # private key
    # sm = "0011000000110001001100100011001100110100001101010011011000110111"   # plaintext
    # for c in sk:
    #     key.append(int(c))
    # for c in sm:
    #         M.append(int(c))

    generate_round_key(key, round_key)
    for i in range(0, 64):                   # IP 置换
        temp_list[i] = M[IP_table[i]-1]
    for i in range(0, 16):
        if i != 15:
            od = 0
        else:od = 1
        temp_list=product_transformation(temp_list,round_key[i],od)   # od=1 第16轮特殊处理
    temp_list=temp_list[32:]+temp_list[0:32]
    for i in range(0, 64):
        ciphertext[i] = temp_list[IP_table_reverse[i]-1]
    output_ls(ciphertext,"ciphertext:")


des_encode()



Decryption algorithm

        if i != 15:
            od = 0
        else: od = 1
        temp_list = product_transformation(temp_list, round_key[15-i], od)

Just replace the corresponding positions.
Since the operation of DES is an involution operation , the encryption and decryption algorithms are the same, except that the order of using round keys is reversed, that is, round_key16 is used in the first iteration...round_key1 is used in the 16th iteration.

operation result

please input plaintext(length is 64 bit):0011000000110001001100100011001100110100001101010011011000110111
please input key(length is 64 bit):0011000100110010001100110011010000110101001101100011011100111000
ciphertext::
10001011 10110100 01111010 00001100 11110000 10101001 01100010 01101101 

Guess you like

Origin blog.csdn.net/Rm_mR/article/details/129780395
Recommended