经典密码学算法实现

发布于:2025-05-08 ⋅ 阅读:(17) ⋅ 点赞:(0)
# AES-128 加密算法的规范实现(不使用外部库)
# ECB模式

S_BOX = [
    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,
    0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
    0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26,
    0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
    0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,
    0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
    0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED,
    0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
    0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,
    0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
    0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC,
    0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
    0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14,
    0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
    0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,
    0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
    0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F,
    0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
    0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11,
    0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
    0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F,
    0xB0, 0x54, 0xBB, 0x16
]

RCON = [
    0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
]

def sub_bytes(state):
    # 字节替代
    for i in range(4):
        for j in range(4):
            state[i][j] = S_BOX[state[i][j]]

def shift_rows(state):
    # 行移位
    state[1] = state[1][1:] + state[1][:1]
    state[2] = state[2][2:] + state[2][:2]
    state[3] = state[3][3:] + state[3][:3]

def xtime(a):
    # GF(2^8)乘法
    return ((a << 1) ^ 0x1B) & 0xFF if a & 0x80 else a << 1

def mix_single_column(a):
    # 单列混合
    t = a[0] ^ a[1] ^ a[2] ^ a[3]
    u = a[0]
    a[0] ^= t ^ xtime(a[0] ^ a[1])
    a[1] ^= t ^ xtime(a[1] ^ a[2])
    a[2] ^= t ^ xtime(a[2] ^ a[3])
    a[3] ^= t ^ xtime(a[3] ^ u)

def mix_columns(state):
    # 列混合
    for i in range(4):
        col = [state[row][i] for row in range(4)]
        mix_single_column(col)
        for row in range(4):
            state[row][i] = col[row]

def add_round_key(state, round_key):
    # 密钥加
    for i in range(4):
        for j in range(4):
            state[i][j] ^= round_key[i][j]

def key_expansion(key):
    # 密钥扩展
    expanded = [key[i:i+4] for i in range(0, 16, 4)]
    for i in range(4, 44):
        word = expanded[i-1][:]
        if i % 4 == 0:
            word = word[1:] + word[:1]
            word = [S_BOX[b] for b in word]
            word[0] ^= RCON[i//4]
        expanded.append([expanded[i-4][j] ^ word[j] for j in range(4)])
    return [expanded[4*i:4*(i+1)] for i in range(11)]

def encrypt_block(plain, key_schedule):
    # 单个区块(16字节)AES加密
    state = [plain[i:i+4] for i in range(0, 16, 4)]

    add_round_key(state, key_schedule[0])

    for rnd in range(1, 10):
        sub_bytes(state)
        shift_rows(state)
        mix_columns(state)
        add_round_key(state, key_schedule[rnd])

    sub_bytes(state)
    shift_rows(state)
    add_round_key(state, key_schedule[10])

    return [byte for row in state for byte in row]

def AES_encrypt(plaintext, key):
    # AES-128 ECB加密,plaintext和key为16字节
    assert len(plaintext) == 16 and len(key) == 16, "Plaintext and key must be 16 bytes."

    key_schedule = key_expansion(key)
    ciphertext = encrypt_block(plaintext, key_schedule)
    return ciphertext

'''
AES 解密算法
'''
INV_S_BOX = [
    0x52,0x09,0x6A,0xD5,0x30,0x36,0xA5,0x38,0xBF,0x40,0xA3,0x9E,0x81,0xF3,0xD7,0xFB,
    0x7C,0xE3,0x39,0x82,0x9B,0x2F,0xFF,0x87,0x34,0x8E,0x43,0x44,0xC4,0xDE,0xE9,0xCB,
    0x54,0x7B,0x94,0x32,0xA6,0xC2,0x23,0x3D,0xEE,0x4C,0x95,0x0B,0x42,0xFA,0xC3,0x4E,
    0x08,0x2E,0xA1,0x66,0x28,0xD9,0x24,0xB2,0x76,0x5B,0xA2,0x49,0x6D,0x8B,0xD1,0x25,
    0x72,0xF8,0xF6,0x64,0x86,0x68,0x98,0x16,0xD4,0xA4,0x5C,0xCC,0x5D,0x65,0xB6,0x92,
    0x6C,0x70,0x48,0x50,0xFD,0xED,0xB9,0xDA,0x5E,0x15,0x46,0x57,0xA7,0x8D,0x9D,0x84,
    0x90,0xD8,0xAB,0x00,0x8C,0xBC,0xD3,0x0A,0xF7,0xE4,0x58,0x05,0xB8,0xB3,0x45,0x06,
    0xD0,0x2C,0x1E,0x8F,0xCA,0x3F,0x0F,0x02,0xC1,0xAF,0xBD,0x03,0x01,0x13,0x8A,0x6B,
    0x3A,0x91,0x11,0x41,0x4F,0x67,0xDC,0xEA,0x97,0xF2,0xCF,0xCE,0xF0,0xB4,0xE6,0x73,
    0x96,0xAC,0x74,0x22,0xE7,0xAD,0x35,0x85,0xE2,0xF9,0x37,0xE8,0x1C,0x75,0xDF,0x6E,
    0x47,0xF1,0x1A,0x71,0x1D,0x29,0xC5,0x89,0x6F,0xB7,0x62,0x0E,0xAA,0x18,0xBE,0x1B,
    0xFC,0x56,0x3E,0x4B,0xC6,0xD2,0x79,0x20,0x9A,0xDB,0xC0,0xFE,0x78,0xCD,0x5A,0xF4,
    0x1F,0xDD,0xA8,0x33,0x88,0x07,0xC7,0x31,0xB1,0x12,0x10,0x59,0x27,0x80,0xEC,0x5F,
    0x60,0x51,0x7F,0xA9,0x19,0xB5,0x4A,0x0D,0x2D,0xE5,0x7A,0x9F,0x93,0xC9,0x9C,0xEF,
    0xA0,0xE0,0x3B,0x4D,0xAE,0x2A,0xF5,0xB0,0xC8,0xEB,0xBB,0x3C,0x83,0x53,0x99,0x61,
    0x17,0x2B,0x04,0x7E,0xBA,0x77,0xD6,0x26,0xE1,0x69,0x14,0x63,0x55,0x21,0x0C,0x7D
]


def inv_sub_bytes(state):
    for i in range(4):
        for j in range(4):
            state[i][j] = INV_S_BOX[state[i][j]]

def inv_shift_rows(state):
    state[1] = state[1][-1:] + state[1][:-1]
    state[2] = state[2][-2:] + state[2][:-2]
    state[3] = state[3][-3:] + state[3][:-3]

def inv_mix_single_column(a):
    u = xtime(xtime(a[0] ^ a[2]))
    v = xtime(xtime(a[1] ^ a[3]))
    a[0] ^= u
    a[1] ^= v
    a[2] ^= u
    a[3] ^= v

    mix_single_column(a)

def inv_mix_columns(state):
    for i in range(4):
        col = [state[row][i] for row in range(4)]
        inv_mix_single_column(col)
        for row in range(4):
            state[row][i] = col[row]

def decrypt_block(cipher, key_schedule):
    state = [cipher[i:i+4] for i in range(0, 16, 4)]

    add_round_key(state, key_schedule[10])
    for rnd in range(9, 0, -1):
        inv_shift_rows(state)
        inv_sub_bytes(state)
        add_round_key(state, key_schedule[rnd])
        inv_mix_columns(state)

    inv_shift_rows(state)
    inv_sub_bytes(state)
    add_round_key(state, key_schedule[0])

    return [byte for row in state for byte in row]

def AES_decrypt(ciphertext, key):
    key_schedule = key_expansion(key)
    plaintext = decrypt_block(ciphertext, key_schedule)
    return plaintext


# 在你的完整AES加解密函数定义之后,添加如下代码进行测试:

def main():
    # 原始明文(16字节)
    plaintext = [0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d,
                 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34]

    # 密钥(16字节)
    key = [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
           0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c]

    # 加密
    ciphertext = AES_encrypt(plaintext, key)
    ciphertext_hex = ''.join('{:02x}'.format(b) for b in ciphertext)
    print('AES加密后的密文:', ciphertext_hex)

    # 解密
    decrypted_text = AES_decrypt(ciphertext, key)
    decrypted_hex = ''.join('{:02x}'.format(b) for b in decrypted_text)
    print('AES解密后的明文:', decrypted_hex)

    # 验证解密结果与原文是否一致
    if decrypted_text == plaintext:
        print(' 解密成功,明文与原始数据一致。')
    else:
        print(' 解密失败,明文与原始数据不一致。')

if __name__ == '__main__':
    main()



# 标准DES实现(无任何外部库依赖)
# 完整实现DES算法,包括IP、IP逆置换、Feistel轮函数和密钥扩展
# 完全符合FIPS 46-3标准,代码规范、清晰易读

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
]


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


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],
    ]
]

def permute(block, table):
    return [block[i-1] for i in table]

def shift_left(key_half, shifts):
    return key_half[shifts:] + key_half[:shifts]

def xor(bits1, bits2):
    return [b1 ^ b2 for b1, b2 in zip(bits1, bits2)]

def sbox_substitution(block48):
    output = []
    for i in range(8):
        chunk = block48[i*6:(i+1)*6]
        row = (chunk[0] << 1) | chunk[5]
        col = (chunk[1] << 3) | (chunk[2] << 2) | (chunk[3] << 1) | chunk[4]
        val = S_BOX[i][row][col]
        bin_val = [int(b) for b in f'{val:04b}']
        output += bin_val
    return output

def generate_subkeys(key64):
    # PC-1, PC-2为标准密钥置换表,C和D为分半后的密钥
    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_SCHEDULE = [1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1]

    key56 = permute(key64, PC1)
    C, D = key56[:28], key56[28:]
    subkeys = []
    for shift in SHIFT_SCHEDULE:
        C, D = shift_left(C, shift), shift_left(D, shift)
        subkey = permute(C + D, PC2)
        subkeys.append(subkey)
    return subkeys

def feistel(R, subkey):
    E = [
        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
    ]

    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
    ]
    expanded_R = permute(R, E)
    xor_result = xor(expanded_R, subkey)
    substituted = sbox_substitution(xor_result)
    return permute(substituted, P)

def DES_encrypt(plaintext64, key64):
    permuted_text = permute(plaintext64, IP)
    L, R = permuted_text[:32], permuted_text[32:]
    subkeys = generate_subkeys(key64)

    for i in range(16):
        temp_R = R
        R = xor(L, feistel(R, subkeys[i]))
        L = temp_R

    preoutput = permute(R + L, IP_INV)  # 注意最后交换一次
    return preoutput

def DES_decrypt(ciphertext64, key64):
    """与加密过程完全对称,子密钥倒序"""
    permuted = permute(ciphertext64, IP)
    L, R = permuted[:32], permuted[32:]
    # 子密钥倒序
    for subkey in reversed(generate_subkeys(key64)):
        temp_R = R
        R = xor(L, feistel(R, subkey))  # ⚠ 这里必须用旧的 R
        L = temp_R
    # 轮结束后再交换一次,顺序与加密保持一致
    return permute(R + L, IP_INV)


# 辅助函数,将字符串转化为二进制位数组
def text_to_bits(text):
    return [int(bit) for char in text for bit in f'{ord(char):08b}']

def bits_to_text(bits):
    chars = [chr(int(''.join(map(str, bits[i:i+8])), 2)) for i in range(0, len(bits), 8)]
    return ''.join(chars)

# 3DES – EDE( Encrypt ▸ Decrypt ▸ Encrypt ) 实现
def triple_des_encrypt(block64, key1, key2, key3=None):
    """
    3DES EDE 加密单个 64‑bit 块
    - key1, key2, key3:  各自为 64‑bit 位列表
    - 若未提供 key3,则自动回退为 2‑Key 3DES (K3 = K1)
    """
    if key3 is None:
        key3 = key1                  # 2‑Key 3DES: K1, K2, K1

    step1 = DES_encrypt(block64, key1)   # 第 1 步:E_K1
    step2 = DES_decrypt(step1, key2)     # 第 2 步:D_K2
    step3 = DES_encrypt(step2, key3)     # 第 3 步:E_K3
    return step3

def triple_des_decrypt(block64, key1, key2, key3=None):
    """
    3DES EDE 解密单个 64‑bit 块
    顺序为 D_K3 ▸ E_K2 ▸ D_K1
    """
    if key3 is None:
        key3 = key1                  # 2‑Key 3DES 解密同理

    step1 = DES_decrypt(block64, key3)   # D_K3
    step2 = DES_encrypt(step1, key2)     # E_K2
    step3 = DES_decrypt(step2, key1)     # D_K1
    return step3

if __name__ == "__main__":
    # ------------ 测试数据 ------------
    plaintext = "ABCDEFGH"          # 8 字节(64bit)明文
    k1_ascii  = "12345678"
    k2_ascii  = "23456789"
    k3_ascii  = "34567890"          # 换成 None 可测试 2‑Key 3DES

    # ---- ASCII 转位列表 ----
    def str_to_bits(s):
        return [int(b) for ch in s for b in f"{ord(ch):08b}"]

    def bits_to_hex(bits):
        return hex(int("".join(map(str, bits)), 2))[2:].upper().zfill(16)

    def bits_to_str(bits):
        return "".join(
            chr(int("".join(map(str, bits[i:i+8])), 2))
            for i in range(0, len(bits), 8)
        )

    pt_bits = str_to_bits(plaintext)
    k1_bits, k2_bits, k3_bits = map(str_to_bits, (k1_ascii, k2_ascii, k3_ascii))

    # ------------ 3DES 加密 ------------
    ct_bits = triple_des_encrypt(pt_bits, k1_bits, k2_bits, k3_bits)
    # ------------ 3DES 解密 ------------
    pt_back_bits = triple_des_decrypt(ct_bits, k1_bits, k2_bits, k3_bits)

    # ------------ 输出结果 ------------
    print("密文 (Hex) :", bits_to_hex(ct_bits))
    print("解密后明文 :", bits_to_str(pt_back_bits))




网站公告

今日签到

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