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

一、实验要求与目的

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页实验报告,所以在报告上我只能代码截图。在这里我是把代码放出来了。

到达世界最高城,理塘!

python 复制代码
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生成,请仔细甄别。)

相关推荐
山登绝顶我为峰 3(^v^)34 小时前
如何录制带备注的演示文稿(LaTex Beamer + Pympress)
c++·线性代数·算法·计算机·密码学·音视频·latex
应长天2 天前
密码学(斯坦福)
密码学
Turbo正则3 天前
量子计算基础概念以及八大分支
密码学·量子计算
网安INF13 天前
公钥加密与签名算法计算详解(含计算题例子)
网络·算法·网络安全·密码学
电院工程师15 天前
基于机器学习的侧信道分析(MLSCA)Python实现(带测试)
人工智能·python·嵌入式硬件·安全·机器学习·密码学
电院工程师16 天前
SM3算法C语言实现(无第三方库,带测试)
c语言·算法·安全·密码学
小七mod18 天前
【BTC】密码学原理
web3·区块链·密码学·比特币·btc·肖臻·北大区块链
电院工程师23 天前
轻量级密码算法PRESENT的C语言实现(无第三方库)
c语言·算法·安全·密码学
电院工程师23 天前
轻量级密码算法CHAM的python实现
python·嵌入式硬件·算法·安全·密码学
电院工程师24 天前
SM3算法Python实现(无第三方库)
开发语言·python·算法·安全·密码学