【应用密码学】实验一 分组密码(1)

发布于:2025-04-16 ⋅ 阅读:(23) ⋅ 点赞:(0)

一、实验要求与目的

1) 复习Feistel结构原理

2) 复习3DES的算法原理

3) 学习3DES算法的编程实现

二、实验内容与步骤记录(只记录关键步骤与结果,可截图,但注意排版与图片大小)

设计步骤:

1.先学习DES,自上而下设计好DES的整体算法结构。

2.设计好字符串和字节流的转换函数,因为return的一般都是字符串形式,所以需要特别注意这个问题。

3.一步一步具体填充DES的流程,四大板块包括“初始置换与逆置换”“密钥生成函数”“f函数”“异或运算”。

4.最后考虑DES的三重变换,如果是用EEE模式,直接调用三次DES函数即可。

查验步骤:

1.验证子密钥生成过程:

2.验证R和L的迭代过程

三、Feistel结构轮函数F算法设计

Feistel结构主要是以下内容,核心是迭代。

L[i+1]=R[i],R[i+1]=L[i]+f(R[i],K[i+1])

F函数分为以下部分。

3.1 将32位的R[i]右半部分进行扩展,得到一个48位的数据块。

3.2 子密钥的生成

但是,我其实把子密钥的生成单独拎出来了,不在f函数内。因为F函数是在一个循环里面的。而子密钥的生成实际上生成的是一整块列表,因此提到外面更方便。

3.3 扩展开的R[i]与密钥异或,得到48位的比特流wait_to_S

3.4 进行S盒变换,之后用P盒替换。

四、源代码记录(关键代码需备注)(今日糖分)

今日糖分:但是老师说实验报告是需要打印出纸质版的,并且建议我们每个实验都写4页差不多了。如果ctrlcctrlv源代码,250+行,那么喜提11页实验报告,所以在报告上我只能代码截图。在这里我是把代码放出来了。

到达世界最高城,理塘!

def DES(m,key):
    after_replace = replace(m)

    # 初始化 L 和 R 的列表,用于存储 L0~L16, R0~R16
    L = [''] * 17
    R = [''] * 17

    # 生成密钥
    K = generate_keys(key)
    # print(K)

    # 设置初始的 L0 和 R0
    L[0] = after_replace[:32]
    R[0] = after_replace[32:]

    for i in range(16):
        L[i+1] = R[i]
        temp = f(R[i],K[i+1])
        R[i+1] = xor_bits(L[i],temp)
        # print(f"L{i+1} = {L[i+1]}")
        # print(f"R{i+1} = {R[i+1]}")

    res = R[16] + L[16]  # 注意顺序是 R16 + L16
    b = inreplace(res)
    return bin_to_str(b)
#--------------初始置换与逆置换----------------#
#初始置换函数
def replace(m):
     IP = [
          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
     ]
     return ''.join(m[i - 1] for i in IP)

def inreplace(m):
    IP_inverse = [
        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
    ]
    return ''.join(m[i - 1] for i in IP_inverse)
#--------------初始置换与逆置换----------------#

#--------------密钥生成函数--------------#
#连接
def permute(bits, table):
    return ''.join(bits[i - 1] for i in table)

#左移
def left_shift(bits, n):
    return bits[n:] + bits[:n]

def generate_keys(k_64):
    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
    ]
    shift_table = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]

    # Step 1: 初始置换 PC-1(64 -> 56)
    k_56 = permute(k_64, PC1)

    # Step 2: 拆分成 C 和 D,各28位
    C = k_56[:28]
    D = k_56[28:]

    # Step 3: 每轮移位 + PC-2 生成子密钥
    K = [''] * 17
    for i in range(16):
        shift = shift_table[i]
        C = left_shift(C, shift)
        D = left_shift(D, shift)
        combined = C + D
        K[i+1] = permute(combined, PC2)

    return K
#--------------密钥生成函数--------------#

#--------------f函数--------------#
#扩展函数
def extend(m):
    IP = [
        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,
    ]
    return ''.join(m[i - 1] for i in IP)

#S盒变换
def Schange(wait_to_S_48):
    S_BOX = [
        [  # 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]
        ]
    ]

    result_32 = ''
    for i in range(8):
        block = wait_to_S_48[i * 6:(i + 1) * 6]
        row = int(block[0] + block[5], 2)
        col = int(block[1:5], 2)
        s_value = S_BOX[i][row][col]
        bin_value = format(s_value, '04b')
        result_32 += bin_value

    # 添加P置换
    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
    ]
    fnl_32 = ''.join(result_32[i - 1] for i in P)
    return fnl_32

#f函数
def f(r_32,key_48):
    after_extend_48 = extend(r_32)
    wait_to_S = xor_bits(after_extend_48,key_48)
    return Schange(wait_to_S)
#--------------f函数--------------#

#-------------异或运算通用版本----------------#
def xor_bits(bits1, bits2):
    return ''.join('0' if b1 == b2 else '1' for b1, b2 in zip(bits1, bits2))
#-------------异或运算通用版本----------------#
#-------------转-----------#
def bin_to_str(b):
    return ''.join(chr(int(b[i:i+8], 2)) for i in range(0, len(b), 8))
def str_to_bin(s):
    return ''.join([format(ord(c), '08b') for c in s])
#-------------转-----------#

if __name__ == "__main__":
    m1 = "Cryptosy"
    m2 = "stem lab"
    key1 = "12345678"
    key2 = "abcdfegh"
    key3 = "12345678"

    # 将字符串转为比特流(字符串形式的0和1)
    bit_stream1 = str_to_bin(m1)
    bit_stream2 = str_to_bin(m2)
    bit_streamk1 = str_to_bin(key1)
    bit_streamk2 = str_to_bin(key2)
    bit_streamk3 = str_to_bin(key3)


    print("原始字符串:", m1)
    print("比特流:", bit_stream1)
    print("原始字符串:", m2)
    print("比特流:", bit_stream2)

    c1 = DES(bit_stream1, bit_streamk1)
    c2 = DES(bit_stream2, bit_streamk1)
    bit_streamc1 = str_to_bin(c1)
    bit_streamc2 = str_to_bin(c2)

    print("c1", c1)
    print("比特流:", bit_streamc1)
    print("c2:", c2)
    print("比特流:", bit_streamc2)

    c3 = DES(bit_streamc1, bit_streamk2)
    c4 = DES(bit_streamc2, bit_streamk2)
    bit_streamc3 = str_to_bin(c3)
    bit_streamc4 = str_to_bin(c4)

    print("c3:", c3)
    print("比特流:", bit_streamc3)
    print("c4:", c4)
    print("比特流:", bit_streamc4)

    c5 = DES(bit_streamc3, bit_streamk3)
    c6 = DES(bit_streamc4, bit_streamk3)
    print("加密结果:", c5)
    print("加密结果:", c6)

五、实验思考

3DES算法与DES算法有什么区别?

答:3DES(Triple DES)相较于传统的DES算法,在安全性上有显著提升,主要体现在其更长的密钥长度和更高的破解难度。

DES:​使用56位密钥,密钥空间为2⁵⁶,那么暴力破解密钥概率为1/2⁵⁶。​在1998年,电子前哨基金会(EFF)构建的专用硬件“DES Cracker”成功在约4.5天内通过暴力破解攻破了DES加密。​​而​在单个RTX 3070上,平均每秒可尝试约3.87亿个密钥,预计需要约215天完成整个密钥空间的搜索。

3DES:​通过对每个数据块执行三次DES加密操作,使用三个独立的56位密钥,理论上密钥长度为168位, ​由于“中间相遇攻击”(meet-in-the-middle attack)的存在,实际安全性约为112位。那么暴力破解密钥概率为1/2112。​​由于其更大的密钥空间,即使在大规模GPU集群上,暴力破解3DES仍被认为在当前技术条件下是不切实际的.

3DES通过三次应用DES算法,显著增加了密钥空间,从而大幅提升了安全性。​与传统DES相比,3DES的密钥空间从2⁵⁶增加到2¹¹²,使得暴力破解所需的时间从几天增加到数百万年甚至更长。​因此,在需要较高安全性的场景中,3DES比传统DES更为可靠。然而,考虑到性能和安全性的进一步提升,现代应用中更推荐使用AES等更先进的加密算法。

(博主人工调用AI生成,请仔细甄别。)


网站公告

今日签到

点亮在社区的每一天
去签到