DES的Python实现

为了方便后续对其中某一个模块进行修改进而分析它的安全性,因此我将DES加密的每一个步骤都封装成了函数

完整代码

# 给定明文字符串,输出第一个IP置换后的结果,为一个列表
def IP(plaintext):
    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]

    result = []
    for i in range(64):
        result.append(plaintext[IP_table[i] - 1])

    return result


# IP逆置换,输入64位的密文列表,输出64位的明文列表
def IP_1(ciphertext):
    IP_1_table = [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]

    result = []
    for i in range(64):
        result.append(ciphertext[IP_1_table[i] - 1])

    return result


# 给定一个64位列表,输出左右两部分子列表
def LeftAndRight_64(text):
    left = text[:32]
    right = text[32:]
    return left, right


# 给定一个56位列表,输出左右两部分子列表
def LeftAndRight_56(text):
    left = text[:28]
    right = text[28:]
    return left, right


# 初始密钥64->56,同时执行PC-1置换,输入64位密钥字符串,输出56位密钥列表
def PC_1(key):
    PC_1_table = [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]

    result = []
    for i in range(56):
        result.append(key[PC_1_table[i] - 1])

    return result


# 56位密钥列表左移+PC-2,输入初始的经过PC-1置换后的密钥与轮数,输出左移后的结果列表
# 压缩置换后变成48位的轮密钥列表
def PC_2(K, round):
    # 左移位数
    shift = [1, 1, 2, 2, 2, 2, 2, 2,
             1, 2, 2, 2, 2, 2, 2, 1]

    PC_2_table = [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]

    # 左移
    left, right = LeftAndRight_56(K)
    for i in range(round):
        left = left[shift[i]:] + left[:shift[i]]
        right = right[shift[i]:] + right[:shift[i]]

    # 合并进行PC-2置换
    result = left + right
    result2 = []
    for i in range(48):
        result2.append(result[PC_2_table[i] - 1])

    return result2


# E扩展,输入32位的右半部分,输出48位的扩展结果,输入输出都是列表
def E(right):
    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]

    result = []
    for i in range(48):
        result.append(right[E_table[i] - 1])

    return result


# S盒代换,输入48位的扩展结果与轮密钥,输出32位的S盒代换结果,输入输出都是列表
def S(right_E, SubK):
    # 与轮密钥执行一次异或
    result = []
    for i in range(48):
        result.append(int(right_E[i]) ^ int(SubK[i]))

    # S盒代换
    S_table = [
        # 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]
        ]
    ]

    # S盒代换
    result2 = []
    for i in range(8):
        row = int(str(result[i * 6]) + str(result[i * 6 + 5]), 2)
        col = int(''.join([str(x) for x in result[i * 6 + 1:i * 6 + 5]]), 2)
        tmp = S_table[i][row][col]
        # 转为四位2进制
        tmp = bin(tmp)[2:]
        while len(tmp) < 4:
            tmp = '0' + tmp
        for j in range(4):
            result2.append(tmp[j])

    return result2


# P置换,输入32位的S盒代换结果,输出32位的P置换结果,输入输出都是列表
def P(S_result):
    # P置换表
    P_table = [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]

    result = []
    for i in range(32):
        result.append(S_result[P_table[i] - 1])

    return result


# DES加密,输入明文字符串与密钥字符串,输出加密后的结果,明文与密文都是64位二进制字符串
def DES(plaintext, key):
    # 初始置换IP
    plaintext = IP(plaintext)
    
    # 生成16个子密钥
    key = PC_1(key)
    keys = []
    for i in range(16):
        keys.append(PC_2(key, i + 1))

    # 初始左右两部分
    left, right = LeftAndRight_64(plaintext)
    for i in range(16):
        # E扩展
        right_E = E(right)

        # S盒代换
        right_S = S(right_E, keys[i])

        # P置换
        right_P = P(right_S)

        # 与左半部分异或
        right2 = []
        for j in range(32):
            right2.append(int(left[j]) ^ int(right_P[j]))

        # 交换左右两部分
        left = right
        right = right2

    # 交换左右两部分
    left, right = right, left
    # 合并
    result = left + right
    # 逆置换
    result = IP_1(result)

    return result


# 明文字符串
plaintext = "0011100011010101101110000100001011010101001110011001010111100111"
# 密文字符串
key = "1010101100110100100001101001010011011001011100111010001011010011"
print(DES(plaintext, key))

运行结果:

"E:\Python 3.11.0\python.exe" D:\Python程序\cryptology\DES.py 
[0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0]

分模块运行

更改上述DES代码,调用函数PC_2,传入参数设为1即可得到L1与R1,如下:

# 明文字符串
plaintext = "0011100011010101101110000100001011010101001110011001010111100111"
# 密文字符串
key = "1010101100110100100001101001010011011001011100111010001011010011"

# 明文初始IP置换
plaintext = IP(plaintext)
# 分左右
left0, right0 = LeftAndRight_64(plaintext)
# 生成第一个子密钥
key = PC_1(key)
key1 = PC_2(key, 1)
# E扩展
right_E = E(right0)
# S盒代换
right_S = S(right_E, key1)
# P置换
right_P = P(right_S)
# 与左半部分异或,得到R1
right1 = []
for j in range(32):
    right1.append(str(int(left0[j]) ^ int(right_P[j])))
# 得到L1
left1 = right0
# 打印
print("L0:", left0)
print("R0:", right0)
print("L1:", left1)
print("R1:", right1)

运行结果:

"E:\Python 3.11.0\python.exe" D:\Python程序\cryptology\DES.py 
L0: ['1', '0', '0', '1', '1', '0', '1', '0', '0', '1', '1', '1', '0', '1', '1', '1', '1', '1', '0', '1', '0', '0', '1', '0', '1', '1', '1', '1', '0', '0', '1', '0']
R0: ['1', '1', '0', '1', '0', '1', '1', '0', '1', '0', '1', '0', '0', '1', '0', '1', '0', '0', '1', '0', '0', '1', '0', '1', '1', '0', '0', '0', '1', '0', '0', '0']
L1: ['1', '1', '0', '1', '0', '1', '1', '0', '1', '0', '1', '0', '0', '1', '0', '1', '0', '0', '1', '0', '0', '1', '0', '1', '1', '0', '0', '0', '1', '0', '0', '0']
R1: ['1', '0', '1', '0', '0', '1', '1', '1', '0', '0', '0', '1', '0', '0', '0', '0', '0', '0', '1', '1', '1', '0', '0', '1', '0', '1', '0', '0', '0', '1', '0', '0']

删除DES中部分模块

先准备完整加密过程的六轮加密结果,包含改变前的与改变后的如下:

# 明文字符串
plaintext = "0011100011010101101110000100001011010101001110011001010111100111"
# 密文字符串
key = "1010101100110100100001101001010011011001011100111010001011010011"

# 明文初始IP置换
plaintext = IP(plaintext)
# 密文初始PC-1置换
key = PC_1(key)
# 分左右
left0, right0 = LeftAndRight_64(plaintext)
right0_change = right0.copy()
# 改变right0的最后一位
if right0_change[31] == '0':
    right0_change[31] = '1'
else:
    right0_change[31] = '0'

# 输出未改变的right0六轮加密的R与L
print("—————————————————————————未改变的right0六轮完整加密的R与L————————————————————————")
for i in range(6):
    # E扩展
    right_E = E(right0)
    # S盒代换
    right_S = S(right_E, PC_2(key, i + 1))
    # P置换
    right_P = P(right_S)
    # 与左半部分异或
    right2 = []
    for j in range(32):
        right2.append(str(int(left0[j]) ^ int(right_P[j])))
    # 交换左右两部分
    left0, right0 = right0, right2
    # 打印
    print("———————第", i + 1, "轮加密的R与L——————")
    print("R:", right0)
    print("L:", left0)

# 输出改变最后一位的right0六轮加密的R与L
print("—————————————————————————改变最后一位的right0六轮完整加密的R与L————————————————————————")
for i in range(6):
    # E扩展
    right_E = E(right0_change)
    # S盒代换
    right_S = S(right_E, PC_2(key, i + 1))
    # P置换
    right_P = P(right_S)
    # 与左半部分异或
    right2 = []
    for j in range(32):
        right2.append(str(int(left0[j]) ^ int(right_P[j])))
    # 交换左右两部分
    left0, right0_change = right0_change, right2
    # 打印
    print("———————第", i + 1, "轮加密的R与L——————")
    print("R:", right0_change)
    print("L:", left0)

输出结果如下:

—————————————————————————未改变的right0六轮完整加密的R与L————————————————————————
———————第 1 轮加密的R与L——————
R: ['1', '0', '1', '0', '0', '1', '1', '1', '0', '0', '0', '1', '0', '0', '0', '0', '0', '0', '1', '1', '1', '0', '0', '1', '0', '1', '0', '0', '0', '1', '0', '0']
L: ['1', '1', '0', '1', '0', '1', '1', '0', '1', '0', '1', '0', '0', '1', '0', '1', '0', '0', '1', '0', '0', '1', '0', '1', '1', '0', '0', '0', '1', '0', '0', '0']
———————第 2 轮加密的R与L——————
R: ['0', '1', '1', '0', '1', '0', '1', '1', '0', '0', '1', '0', '0', '1', '1', '1', '1', '0', '1', '0', '1', '1', '0', '0', '0', '0', '0', '0', '1', '0', '1', '1']
L: ['1', '0', '1', '0', '0', '1', '1', '1', '0', '0', '0', '1', '0', '0', '0', '0', '0', '0', '1', '1', '1', '0', '0', '1', '0', '1', '0', '0', '0', '1', '0', '0']
———————第 3 轮加密的R与L——————
R: ['1', '1', '0', '1', '1', '1', '1', '0', '1', '0', '1', '1', '0', '1', '1', '0', '1', '1', '0', '0', '0', '0', '1', '0', '1', '0', '0', '0', '0', '1', '1', '0']
L: ['0', '1', '1', '0', '1', '0', '1', '1', '0', '0', '1', '0', '0', '1', '1', '1', '1', '0', '1', '0', '1', '1', '0', '0', '0', '0', '0', '0', '1', '0', '1', '1']
———————第 4 轮加密的R与L——————
R: ['0', '0', '1', '1', '1', '1', '0', '1', '1', '0', '0', '0', '0', '0', '0', '1', '1', '0', '0', '0', '0', '0', '0', '0', '1', '0', '0', '0', '0', '1', '1', '0']
L: ['1', '1', '0', '1', '1', '1', '1', '0', '1', '0', '1', '1', '0', '1', '1', '0', '1', '1', '0', '0', '0', '0', '1', '0', '1', '0', '0', '0', '0', '1', '1', '0']
———————第 5 轮加密的R与L——————
R: ['1', '0', '1', '0', '0', '0', '0', '1', '0', '1', '1', '0', '1', '1', '1', '0', '1', '0', '0', '1', '0', '0', '1', '1', '1', '0', '0', '1', '0', '1', '0', '1']
L: ['0', '0', '1', '1', '1', '1', '0', '1', '1', '0', '0', '0', '0', '0', '0', '1', '1', '0', '0', '0', '0', '0', '0', '0', '1', '0', '0', '0', '0', '1', '1', '0']
———————第 6 轮加密的R与L——————
R: ['0', '1', '0', '0', '1', '1', '0', '1', '1', '1', '0', '1', '1', '1', '1', '1', '0', '1', '1', '0', '1', '0', '0', '1', '0', '0', '0', '0', '0', '1', '1', '0']
L: ['1', '0', '1', '0', '0', '0', '0', '1', '0', '1', '1', '0', '1', '1', '1', '0', '1', '0', '0', '1', '0', '0', '1', '1', '1', '0', '0', '1', '0', '1', '0', '1']
—————————————————————————改变最后一位的right0六轮完整加密的R与L————————————————————————
———————第 1 轮加密的R与L——————
R: ['1', '0', '0', '1', '0', '1', '0', '0', '1', '0', '0', '0', '1', '0', '1', '1', '1', '1', '1', '1', '1', '0', '1', '0', '0', '0', '0', '0', '0', '0', '0', '1']
L: ['1', '1', '0', '1', '0', '1', '1', '0', '1', '0', '1', '0', '0', '1', '0', '1', '0', '0', '1', '0', '0', '1', '0', '1', '1', '0', '0', '0', '1', '0', '0', '1']
———————第 2 轮加密的R与L——————
R: ['0', '0', '1', '0', '1', '0', '1', '1', '1', '0', '1', '0', '1', '1', '0', '1', '0', '0', '1', '1', '1', '0', '0', '1', '1', '1', '0', '0', '0', '1', '1', '0']
L: ['1', '0', '0', '1', '0', '1', '0', '0', '1', '0', '0', '0', '1', '0', '1', '1', '1', '1', '1', '1', '1', '0', '1', '0', '0', '0', '0', '0', '0', '0', '0', '1']
———————第 3 轮加密的R与L——————
R: ['0', '0', '0', '1', '0', '1', '1', '0', '1', '1', '1', '1', '0', '0', '0', '1', '1', '1', '0', '1', '0', '0', '1', '0', '1', '0', '1', '0', '1', '0', '1', '0']
L: ['0', '0', '1', '0', '1', '0', '1', '1', '1', '0', '1', '0', '1', '1', '0', '1', '0', '0', '1', '1', '1', '0', '0', '1', '1', '1', '0', '0', '0', '1', '1', '0']
———————第 4 轮加密的R与L——————
R: ['0', '0', '0', '1', '1', '0', '1', '1', '0', '0', '1', '1', '0', '0', '1', '0', '0', '1', '0', '0', '0', '0', '1', '1', '0', '0', '1', '0', '0', '1', '0', '0']
L: ['0', '0', '0', '1', '0', '1', '1', '0', '1', '1', '1', '1', '0', '0', '0', '1', '1', '1', '0', '1', '0', '0', '1', '0', '1', '0', '1', '0', '1', '0', '1', '0']
———————第 5 轮加密的R与L——————
R: ['1', '0', '0', '0', '1', '0', '1', '1', '1', '0', '0', '0', '1', '0', '0', '1', '1', '1', '0', '0', '1', '0', '0', '1', '0', '0', '0', '0', '0', '1', '0', '1']
L: ['0', '0', '0', '1', '1', '0', '1', '1', '0', '0', '1', '1', '0', '0', '1', '0', '0', '1', '0', '0', '0', '0', '1', '1', '0', '0', '1', '0', '0', '1', '0', '0']
———————第 6 轮加密的R与L——————
R: ['0', '0', '0', '0', '1', '0', '1', '0', '0', '0', '1', '1', '0', '0', '1', '0', '1', '0', '1', '1', '0', '1', '1', '1', '0', '0', '1', '1', '1', '1', '0', '1']
L: ['1', '0', '0', '0', '1', '0', '1', '1', '1', '0', '0', '0', '1', '0', '0', '1', '1', '1', '0', '0', '1', '0', '0', '1', '0', '0', '0', '0', '0', '1', '0', '1']

删除E扩散(32-48填充0)

删除E扩散,更改程序如下:

# 改变最后一位的right0六轮删除E扩散加密的R与L
print("—————————————————————————改变最后一位的right0六轮删除E扩散加密的R与L————————————————————————")
for i in range(6):
    # 给right0_change后面补0到48位
    right_E = right0_change.copy()
    right_E.extend(['0'] * 16)
    # S盒代换
    right_S = S(right_E, PC_2(key, i + 1))
    # P置换
    right_P = P(right_S)
    # 与左半部分异或
    right2 = []
    for j in range(32):
        right2.append(str(int(left0[j]) ^ int(right_P[j])))
    # 交换左右两部分
    left0, right0_change = right0_change, right2
    # 打印
    print("———————第", i + 1, "轮加密的R与L——————")
    print("R:", right0_change)
    print("L:", left0)

结果如下:

—————————————————————————改变最后一位的right0六轮删除E扩散加密的R与L————————————————————————
———————第 1 轮加密的R与L——————
R: ['1', '1', '1', '1', '0', '0', '1', '1', '1', '0', '0', '0', '1', '1', '0', '1', '1', '0', '0', '0', '0', '1', '1', '0', '0', '1', '0', '1', '0', '1', '1', '1']
L: ['0', '0', '0', '0', '1', '0', '1', '0', '0', '0', '1', '1', '0', '0', '1', '0', '1', '0', '1', '1', '0', '1', '1', '1', '0', '0', '1', '1', '1', '1', '0', '1']
———————第 2 轮加密的R与L——————
R: ['0', '1', '0', '0', '0', '1', '1', '1', '0', '1', '0', '1', '1', '1', '0', '0', '1', '0', '1', '0', '0', '0', '0', '1', '0', '1', '1', '0', '1', '1', '0', '0']
L: ['1', '1', '1', '1', '0', '0', '1', '1', '1', '0', '0', '0', '1', '1', '0', '1', '1', '0', '0', '0', '0', '1', '1', '0', '0', '1', '0', '1', '0', '1', '1', '1']
———————第 3 轮加密的R与L——————
R: ['0', '0', '0', '0', '0', '0', '1', '0', '1', '1', '0', '1', '1', '1', '0', '1', '0', '0', '1', '0', '1', '0', '0', '0', '0', '1', '0', '1', '0', '1', '0', '0']
L: ['0', '1', '0', '0', '0', '1', '1', '1', '0', '1', '0', '1', '1', '1', '0', '0', '1', '0', '1', '0', '0', '0', '0', '1', '0', '1', '1', '0', '1', '1', '0', '0']
———————第 4 轮加密的R与L——————
R: ['1', '1', '1', '0', '1', '0', '0', '0', '1', '0', '1', '0', '0', '1', '1', '1', '0', '1', '1', '1', '0', '0', '0', '1', '1', '0', '1', '0', '1', '1', '0', '0']
L: ['0', '0', '0', '0', '0', '0', '1', '0', '1', '1', '0', '1', '1', '1', '0', '1', '0', '0', '1', '0', '1', '0', '0', '0', '0', '1', '0', '1', '0', '1', '0', '0']
———————第 5 轮加密的R与L——————
R: ['0', '1', '1', '1', '0', '0', '1', '0', '0', '0', '1', '1', '0', '1', '1', '0', '1', '1', '0', '0', '1', '0', '1', '0', '0', '1', '1', '1', '0', '1', '0', '1']
L: ['1', '1', '1', '0', '1', '0', '0', '0', '1', '0', '1', '0', '0', '1', '1', '1', '0', '1', '1', '1', '0', '0', '0', '1', '1', '0', '1', '0', '1', '1', '0', '0']
———————第 6 轮加密的R与L——————
R: ['0', '0', '1', '1', '0', '0', '1', '1', '1', '1', '0', '0', '1', '0', '1', '1', '1', '0', '1', '1', '0', '1', '1', '0', '1', '1', '0', '1', '0', '1', '0', '0']
L: ['0', '1', '1', '1', '0', '0', '1', '0', '0', '0', '1', '1', '0', '1', '1', '0', '1', '1', '0', '0', '1', '0', '1', '0', '0', '1', '1', '1', '0', '1', '0', '1']

删除S-box(取S-box输入的中间4bit为输出)

修改S函数的代码,如下:

# 改变最后一位的right0六轮删除S核加密的R与L
# 重写S函数为S1,取中间的4bit为输出
def S1(right_E, SubK):
    # 与轮密钥执行一次异或
    result = []
    for i in range(48):
        result.append(str(int(right_E[i]) ^ int(SubK[i])))

    # 取六位中间的四位
    result2 = []
    for i in range(8):
        # 一个个加进result2
        result2.append(result[i * 6 + 1])
        result2.append(result[i * 6 + 2])
        result2.append(result[i * 6 + 3])
        result2.append(result[i * 6 + 4])

    return result2


print("—————————————————————————改变最后一位的right0六轮删除S盒加密的R与L————————————————————————")
for i in range(6):
    # E扩展
    right_E = E(right0_change)
    # 调用S1函数
    right_S = S1(right_E, PC_2(key, i + 1))
    # P置换
    right_P = P(right_S)
    # 与左半部分异或
    right2 = []
    for j in range(32):
        right2.append(str(int(left0[j]) ^ int(right_P[j])))
    # 交换左右两部分
    left0, right0_change = right0_change, right2
    # 打印
    print("———————第", i + 1, "轮加密的R与L——————")
    print("R:", right0_change)
    print("L:", left0)

结果如下:

—————————————————————————改变最后一位的right0六轮删除S盒加密的R与L————————————————————————
———————第 1 轮加密的R与L——————
R: ['1', '0', '1', '0', '1', '1', '0', '0', '1', '1', '0', '0', '1', '1', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '1', '1', '0', '1', '0', '0', '0', '0']
L: ['0', '0', '1', '1', '0', '0', '1', '1', '1', '1', '0', '0', '1', '0', '1', '1', '1', '0', '1', '1', '0', '1', '1', '0', '1', '1', '0', '1', '0', '1', '0', '0']
———————第 2 轮加密的R与L——————
R: ['1', '1', '0', '0', '0', '1', '1', '1', '1', '0', '1', '0', '1', '0', '1', '0', '1', '1', '0', '1', '1', '0', '0', '1', '0', '1', '1', '0', '0', '0', '0', '1']
L: ['1', '0', '1', '0', '1', '1', '0', '0', '1', '1', '0', '0', '1', '1', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '1', '1', '0', '1', '0', '0', '0', '0']
———————第 3 轮加密的R与L——————
R: ['1', '1', '0', '1', '1', '0', '0', '1', '0', '1', '0', '0', '0', '0', '1', '1', '1', '0', '0', '1', '1', '0', '0', '1', '0', '1', '0', '1', '1', '0', '1', '1']
L: ['1', '1', '0', '0', '0', '1', '1', '1', '1', '0', '1', '0', '1', '0', '1', '0', '1', '1', '0', '1', '1', '0', '0', '1', '0', '1', '1', '0', '0', '0', '0', '1']
———————第 4 轮加密的R与L——————
R: ['1', '0', '0', '1', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '1', '0', '0', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '0', '1', '0', '1', '0']
L: ['1', '1', '0', '1', '1', '0', '0', '1', '0', '1', '0', '0', '0', '0', '1', '1', '1', '0', '0', '1', '1', '0', '0', '1', '0', '1', '0', '1', '1', '0', '1', '1']
———————第 5 轮加密的R与L——————
R: ['1', '1', '1', '0', '0', '0', '1', '1', '0', '1', '0', '1', '1', '1', '0', '0', '0', '0', '1', '1', '1', '0', '1', '1', '1', '0', '1', '0', '1', '0', '1', '1']
L: ['1', '0', '0', '1', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '1', '0', '0', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '0', '1', '0', '1', '0']
———————第 6 轮加密的R与L——————
R: ['0', '1', '0', '0', '0', '0', '0', '0', '1', '0', '1', '1', '1', '1', '0', '1', '1', '0', '1', '0', '1', '0', '1', '1', '0', '0', '1', '1', '1', '0', '0', '0']
L: ['1', '1', '1', '0', '0', '0', '1', '1', '0', '1', '0', '1', '1', '1', '0', '0', '0', '0', '1', '1', '1', '0', '1', '1', '1', '0', '1', '0', '1', '0', '1', '1']

删除P置换

删除P置换函数,代码如下:

# 改变最后一位的right0六轮删除P置换加密的R与L
print("—————————————————————————改变最后一位的right0六轮删除P置换加密的R与L————————————————————————")
for i in range(6):
    # E扩展
    right_E = E(right0_change)
    # S盒代换
    right_S = S(right_E, PC_2(key, i + 1))
    # 与左半部分异或
    right2 = []
    for j in range(32):
        right2.append(str(int(left0[j]) ^ int(right_P[j])))
    # 交换左右两部分
    left0, right0_change = right0_change, right2
    # 打印
    print("———————第", i + 1, "轮加密的R与L——————")
    print("R:", right0_change)
    print("L:", left0)

结果如下:

—————————————————————————改变最后一位的right0六轮删除P置换加密的R与L————————————————————————
———————第 1 轮加密的R与L——————
R: ['0', '0', '1', '1', '0', '0', '1', '0', '0', '0', '0', '1', '1', '0', '1', '1', '1', '1', '1', '1', '0', '1', '1', '0', '0', '1', '1', '1', '1', '0', '0', '1']
L: ['0', '1', '0', '0', '0', '0', '0', '0', '1', '0', '1', '1', '1', '1', '0', '1', '1', '0', '1', '0', '1', '0', '1', '1', '0', '0', '1', '1', '1', '0', '0', '0']
———————第 2 轮加密的R与L——————
R: ['1', '0', '0', '1', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '1', '0', '0', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '0', '1', '0', '1', '0']
L: ['0', '0', '1', '1', '0', '0', '1', '0', '0', '0', '0', '1', '1', '0', '1', '1', '1', '1', '1', '1', '0', '1', '1', '0', '0', '1', '1', '1', '1', '0', '0', '1']
———————第 3 轮加密的R与L——————
R: ['1', '1', '1', '0', '0', '0', '1', '1', '0', '1', '0', '1', '1', '1', '0', '0', '0', '0', '1', '1', '1', '0', '1', '1', '1', '0', '1', '0', '1', '0', '1', '1']
L: ['1', '0', '0', '1', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '1', '0', '0', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '0', '1', '0', '1', '0']
———————第 4 轮加密的R与L——————
R: ['0', '1', '0', '0', '0', '0', '0', '0', '1', '0', '1', '1', '1', '1', '0', '1', '1', '0', '1', '0', '1', '0', '1', '1', '0', '0', '1', '1', '1', '0', '0', '0']
L: ['1', '1', '1', '0', '0', '0', '1', '1', '0', '1', '0', '1', '1', '1', '0', '0', '0', '0', '1', '1', '1', '0', '1', '1', '1', '0', '1', '0', '1', '0', '1', '1']
———————第 5 轮加密的R与L——————
R: ['0', '0', '1', '1', '0', '0', '1', '0', '0', '0', '0', '1', '1', '0', '1', '1', '1', '1', '1', '1', '0', '1', '1', '0', '0', '1', '1', '1', '1', '0', '0', '1']
L: ['0', '1', '0', '0', '0', '0', '0', '0', '1', '0', '1', '1', '1', '1', '0', '1', '1', '0', '1', '0', '1', '0', '1', '1', '0', '0', '1', '1', '1', '0', '0', '0']
———————第 6 轮加密的R与L——————
R: ['1', '0', '0', '1', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '1', '0', '0', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '0', '1', '0', '1', '0']
L: ['0', '0', '1', '1', '0', '0', '1', '0', '0', '0', '0', '1', '1', '0', '1', '1', '1', '1', '1', '1', '0', '1', '1', '0', '0', '1', '1', '1', '1', '0', '0', '1']

从结果分析混乱、扩散效果

通过比较正常DES和修改后DES的轮函数输出,我们可以看出E扩展、S盒和P置换在实现混乱和扩散方面的重要作用。这些组件的缺失显著影响了加密的强度和安全性,减少了由输入的微小变化所引起的广泛输出变化。因此,每一个组件都是DES高安全性的关键部分。

初始变化的影响

首先,考虑改变right0的最后一位后,第1轮的输出与原始数据的对比:

  • 未改变时的第1轮输出(原始):

    • R: ['1', '0', '1', '0', '0', '1', '1', '1', '0', '0', '0', '1', '0', '0', '0', '0', '0', '0', '1', '1', '1', '0', '0', '1', '0', '1', '0', '0', '0', '1', '0', '0']

    • L: ['1', '1', '0', '1', '0', '1', '1', '0', '1', '0', '1', '0', '0', '1', '0', '1', '0', '0', '1', '0', '0', '1', '0', '1', '1', '0', '0', '0', '1', '0', '0', '0']

  • 改变后的第1轮输出:

    • R: ['1', '0', '0', '1', '0', '1', '0', '0', '1', '0', '0', '0', '1', '0', '1', '1', '1', '1', '1', '1', '1', '0', '1', '0', '0', '0', '0', '0', '0', '0', '0', '1']

    • L: ['1', '1', '0', '1', '0', '1', '1', '0', '1', '0', '1', '0', '0', '1', '0', '1', '0', '0', '1', '0', '0', '1', '0', '1', '1', '0', '0', '0', '1', '0', '0', '1']

可以看到,单单是改变right0的最后一位,就已经导致了第1轮输出中R部分有多个位的显著变化。这展示了E扩展和S盒在加密过程中的混乱性,即输入的微小变化通过这些组件的处理被放大。

深入到后续轮次

继续分析到第6轮,我们可以看到初始的单一变化如何影响更多位:

  • 未改变时的第6轮输出(原始):

    • R: ['0', '1', '0', '0', '1', '1', '0', '1', '1', '1', '0', '1', '1', '1', '1', '1', '0', '1', '1', '0', '1', '0', '0', '1', '0', '0', '0', '0', '0', '1', '1', '0']

    • L: ['1', '0', '1', '0', '0', '0', '0', '1', '0', '1', '1', '0', '1', '1', '1', '0', '1', '0', '0', '1', '0', '0', '1', '1', '1', '0', '0', '1', '0', '1', '0', '1']

  • 改变后的第6轮输出:

    • R: ['0', '0', '1', '1', '0', '0', '1', '1', '1', '1', '0', '0', '1', '0', '1', '1', '1', '0', '1', '1', '0', '1', '1', '0', '1', '1', '0', '1', '0', '1', '0', '0']

    • L: ['0', '1', '1', '1', '0', '0', '1', '0', '0', '0', '1', '1', '0', '1', '1', '0', '1', '1', '0', '0', '1', '0', '1', '0', '0', '1', '1', '1', '0', '1', '0', '1']

从这些数据中可以看出,改变单个输入位对于最终输出的R和L部分产生了广泛的影响,覆盖了多个不同的位置。这种广泛的位变化说明DES算法的轮函数成功实现了扩散的目标,确保了密钥空间的高度安全性和预测难度。

删除E扩展的情况

E扩展操作通过将32位的数据扩展到48位,增加了冗余,使得每个输入位影响多个S盒的输出。删除E扩展意味着S盒将接收到较少的、未扩展的输入,这可能减少了混乱和扩散的效果。

  • 第6轮输出(删除E扩展):

    • R: ['0', '0', '1', '1', '0', '0', '1', '1', '1', '1', '0', '0', '1', '0', '1', '1', '1', '0', '1', '1', '0', '1', '1', '0', '1', '1', '0', '1', '0', '1', '0', '0']

    • L: ['0', '1', '1', '1', '0', '0', '1', '0', '0', '0', '1', '1', '0', '1', '1', '0', '1', '1', '0', '0', '1', '0', '1', '0', '0', '1', '1', '1', '0', '1', '0', '1']

与正常加密对比,可以看到删除E扩展后,虽然输出依旧有改变,但混乱和扩散的速率可能较正常情况为低,因为没有额外的位扩展带来的更广的影响。

删除S盒的情况

S盒提供非线性的变换,是DES中实现混乱的核心。删除S盒,理论上将大大减少加密过程中的混乱和扩散。

  • 第6轮输出(删除S盒):

    • R: ['0', '1', '0', '0', '0', '0', '0', '0', '1', '0', '1', '1', '1', '1', '0', '1', '1', '0', '1', '0', '1', '0', '1', '1', '0', '0', '1', '1', '1', '0', '0', '0']

    • L: ['1', '1', '1', '0', '0', '0', '1', '1', '0', '1', '0', '1', '1', '1', '0', '0', '0', '0', '1', '1', '1', '0', '1', '1', '1', '0', '1', '0', '1', '0', '1', '1']

从数据看,删除S盒后的输出仍然存在一些变化,但这些变化较为规律,可能不如完整的S盒带来的混乱性高。

删除P置换的情况

P置换的作用是将S盒输出重新排序,以增加扩散效果。删除P置换意味着减少了输出之间的交互,可能减缓了扩散速度。

  • 第6轮输出(删除P置换):

    • R: ['1', '0', '0', '1', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '1', '0', '0', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '0', '1', '0', '1', '0']

    • L: ['0', '0', '1', '1', '0', '0', '1', '0', '0', '0', '0', '1', '1', '0', '1', '1', '1', '1', '1', '1', '0', '1', '1', '0', '0', '1', '1', '1', '1', '0', '0', '1']

删除P置换后,输出依然存在变化,但由于没有了位的重新分配,变化的位可能较为集中,不如完整P置换的扩散性强。

多重DES中间件攻击

两个密钥(EDE)

\mathrm{c}=E_{k_{1}}\left(D_{k_{2}}\left(E_{k_{1}}(m)\right)\right)

假设我们已知一个明文P和一个密文C,定义两个中间值X1、X2,则有:

X1 = D(K1,C)=D(K2,E(K1,P))

X2 = E(K2,X1)=E(K1,P)

  1. 选取明文P,使用所有可能的K1进行加密,保存加密结果和对应的K1密钥。

  2. 选取密文C,使用第一步的K1进行解密,保存解密结果。

  3. 选取2. 的解密结果,使用可能的K2进行加密,若结果与1. 的加密结果相同,则找出密钥对K1、K2。

计算复杂度分析:

  1. 第一步使用到的K1共有256个,因此计算复杂度为256

  2. 第二部与第一步使用的密钥相等,因此计算复杂度为256

  3. 第三步结果与第二步相关联,且使用到的K2最坏情况下为256个,因此计算复杂度为O(256*256)+O(256)+O(1)=O(2112)

空间复杂度分析:

在上述三个步骤中,需要存储的其实只有第一步的结果,第二部算出的结果可以立即参与第三步,第三步的计算结果立即与第一步存储的结果进行比较,不相等即丢弃,因此空间复杂度为O(256)

三个密钥(EEE)

\mathrm{c}=E_{k_{1}}\left(E_{k_{2}}\left(E_{k_{3}}(m)\right)\right)

假设我们已知一个明文P和一个密文C,定义两个中间值X1、X2,则有:

X1 = D(K1,C)=E(K2,E(K3,P))

X2 = D(K2,X1)=E(K3,P)

  1. 选取明文P,使用所有可能的K3进行加密,保存加密结果和对应的K3密钥。

  2. 选取密文C,使用所有可能的K1进行解密,保存解密结果和对应的K1密钥。

  3. 选取2. 的解密结果,使用可能的K2进行加密,若结果与1. 的加密结果相同,则找出密钥对K1、K2。

计算复杂度分析:

  1. 第一步使用到的K3共有256个,因此计算复杂度为256

  2. 第一步使用到的K1共有256个,因此计算复杂度为256

  3. 第三步结果与第二步相关联,且使用到的K2最坏情况下为256个,因此计算复杂度为O(256*256)+O(256)+O(256)=O(2112)

空间复杂度分析:

在上述三个步骤中,第一步与第二部的结果需要存储起来,各有256个,第三步的计算结果可以直接与第一步的加密结果进行比较,可以不储存,因此空间复杂度为O(256+256)=O(257)