DES加密和解密过程的核心区别只有一个:子密钥的使用顺序相反。
由此:只需要知道加密过程,即能得出解密过程。
加密处理过程即原理解释:
本文按照程序语言实现顺序编写。
1.原文填充
为什么需要在加密原文的后面填充数据?
因为DES算法作为一种分组加密算法,其基本处理单元是固定的64位(8字节)数据块。如果待加密数据的长度不是8字节的整数倍,就必须通过填充来补足最后一个数据块,以确保算法能够正常处理所有数据。
有哪几类填充方式?
Python模块实现:
def pkcs5_pad(data):
"""PKCS5填充:数据末尾填充n个值为n的字节,使总长度为8的倍数。"""
pad_len = 8 - (len(data) % 8)
return data + bytes([pad_len] * pad_len)
def pkcs5_unpad(padded_data):
"""去除PKCS5填充:根据最后一个字节的值移除填充。"""
pad_len = padded_data[-1]
return padded_data[:-pad_len]2.生成子密钥
密钥置换表1(将64位密钥选择压缩成56位):
密钥置换表2(将56位密钥选择压缩成48位):
左移位数表,对应16轮中每一轮left和right左移多少位:
Python函数实现模块:
def generate_des_subkeys(key_64):
PC_1 = [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]
PC_2 = [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]
key_56 = ''.join([key_64[i - 1] for i in PC_1])
C = [key_56[:28]]
D = [key_56[28:]]
subkeys = []
for round_num in range(16):
shift_bits = shift_table[round_num]
C_prev = C[-1]
D_prev = D[-1]
C_new = C_prev[shift_bits:] + C_prev[:shift_bits]
D_new = D_prev[shift_bits:] + D_prev[:shift_bits]
C.append(C_new)
D.append(D_new)
CD_56 = C_new + D_new
subkey_48 = ''.join([CD_56[i - 1] for i in PC_2])
subkeys.append(subkey_48)
return subkeys
def hex_to_binary(hex_string):
int_value = int(hex_string, 16)
binary_string = bin(int_value)[2:].zfill(64)
return binary_string
def binary_to_hex(binary_string):
int_value = int(binary_string, 2)
hex_string = hex(int_value)[2:].upper().zfill(16)
return hex_string
if __name__ == "__main__":
example_key_hex = "133457799BBCDFF1"
key_binary = hex_to_binary(example_key_hex)
print(f"原始密钥 (64位): {example_key_hex}")
print(f"二进制表示: {key_binary}")
print()
subkeys = generate_des_subkeys(key_binary)
print("生成的16个子密钥:")
print("-" * 60)
for i, subkey in enumerate(subkeys, 1):
subkey_hex = binary_to_hex(subkey)
print(f"子密钥 K{i:2d}: {subkey_hex} (48位)")
print("\n第一个子密钥验证(标准测试向量):")
print(f"期望: 1B02EFFC7072")
print(f"实际: {binary_to_hex(subkeys[0])}")- 加密


加解密实现代码:
# DES加解密算法函数
def string_to_bit_array(text):
"""将字符串转换为位数组"""
array = []
for char in text:
bin_val = bin(ord(char))[2:].zfill(8)
array.extend([int(x) for x in list(bin_val)])
return array
def bit_array_to_string(array):
"""将位数组转换为字符串"""
res = []
for i in range(0, len(array), 8):
byte = array[i:i + 8]
char = chr(int(''.join(map(str, byte)), 2))
res.append(char)
return ''.join(res)
def bit_array_to_hex(array):
"""将位数组转换为十六进制字符串"""
res = []
for i in range(0, len(array), 8):
byte = array[i:i + 8]
value = int(''.join(map(str, byte)), 2)
res.append(f"{value:02x}")
return ''.join(res)
def hex_to_bit_array(hex_string):
"""将十六进制字符串转换为位数组"""
array = []
for i in range(0, len(hex_string), 2):
byte = hex_string[i:i + 2]
value = int(byte, 16)
bin_val = bin(value)[2:].zfill(8)
array.extend([int(x) for x in list(bin_val)])
return array
def permute(block, table):
"""根据置换表进行置换"""
return [block[x - 1] for x in table]
def left_shift(key, n):
"""循环左移"""
return key[n:] + key[:n]
def xor(a, b):
"""异或操作"""
return [x ^ y for x, y in zip(a, b)]
# DES置换表和S盒
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
]
FP = [
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 = [
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
]
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]
S_BOX = [
[
[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]
],
[
[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]
],
[
[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]
],
[
[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]
],
[
[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]
],
[
[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]
],
[
[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]
],
[
[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 s_box_substitution(block):
"""S盒替换"""
output = []
for i in range(8):
chunk = block[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]
output.extend([int(x) for x in bin(val)[2:].zfill(4)])
return output
def f_function(right, subkey):
"""f函数"""
expanded = permute(right, E)
xored = xor(expanded, subkey)
sboxed = s_box_substitution(xored)
output = permute(sboxed, P)
return output
def generate_subkeys(key):
"""生成16个子密钥"""
key_bits = string_to_bit_array(key)
key_pc1 = permute(key_bits, PC1)
left = key_pc1[:28]
right = key_pc1[28:]
subkeys = []
for i in range(16):
left = left_shift(left, SHIFT_SCHEDULE[i])
right = left_shift(right, SHIFT_SCHEDULE[i])
combined = left + right
subkey = permute(combined, PC2)
subkeys.append(subkey)
return subkeys
def encrypt_block(block, subkeys):
"""加密一个64位块"""
block = permute(block, IP)
left = block[:32]
right = block[32:]
for i in range(16):
temp = right
f_result = f_function(right, subkeys[i])
right = xor(left, f_result)
left = temp
combined = right + left
cipher_block = permute(combined, FP)
return cipher_block
def decrypt_block(block, subkeys):
"""解密一个64位块"""
block = permute(block, IP)
left = block[:32]
right = block[32:]
for i in range(15, -1, -1):
temp = right
f_result = f_function(right, subkeys[i])
right = xor(left, f_result)
left = temp
combined = right + left
plain_block = permute(combined, FP)
return plain_block
def pad_data(data):
"""PKCS7填充"""
pad_len = 8 - (len(data) % 8)
padding = chr(pad_len) * pad_len
return data + padding
def unpad_data(data):
"""去除PKCS7填充"""
pad_len = ord(data[-1])
return data[:-pad_len]
def encrypt(plaintext, key):
"""加密文本,返回十六进制字符串"""
if len(key) != 8:
return "错误:密钥必须是8个字符"
padded_text = pad_data(plaintext)
plain_bits = string_to_bit_array(padded_text)
subkeys = generate_subkeys(key)
cipher_bits = []
for i in range(0, len(plain_bits), 64):
block = plain_bits[i:i + 64]
encrypted_block = encrypt_block(block, subkeys)
cipher_bits.extend(encrypted_block)
cipher_hex = bit_array_to_hex(cipher_bits)
return cipher_hex
def decrypt(cipher_hex, key):
"""从十六进制字符串解密文本"""
if len(key) != 8:
return "错误:密钥必须是8个字符"
cipher_bits = hex_to_bit_array(cipher_hex)
subkeys = generate_subkeys(key)
plain_bits = []
for i in range(0, len(cipher_bits), 64):
block = cipher_bits[i:i + 64]
decrypted_block = decrypt_block(block, subkeys)
plain_bits.extend(decrypted_block)
plain_text = bit_array_to_string(plain_bits)
unpadded_text = unpad_data(plain_text)
return unpadded_text
# 主菜单
def main():
while True:
print("\n=== DES加解密系统 ===")
print("1. 加密")
print("2. 解密")
print("3. 退出")
choice = input("请选择操作 (1/2/3): ").strip()
if choice == '1':
plaintext = input("请输入要加密的明文: ")
key = input("请输入8字符密钥: ")
if len(key) != 8:
print("错误:密钥必须是8个字符")
continue
result = encrypt(plaintext, key)
print(f"加密结果: {result}")
elif choice == '2':
ciphertext = input("请输入要解密的密文(十六进制): ")
key = input("请输入8字符密钥: ")
if len(key) != 8:
print("错误:密钥必须是8个字符")
continue
result = decrypt(ciphertext, key)
print(f"解密结果: {result}")
elif choice == '3':
print("再见!")
break
else:
print("无效选择,请重新输入")
if __name__ == "__main__":
main()
评论
0 条