当前位置: 首页 > news >正文

DES 加密算法:核心组件、加解密流程与安全特性

DES对称加密算法

一、DES算法原理

算法流程:

  1. 初始置换(IP置换):将输入的64位明文块进行置换和重新排列,生成新的64位数据块。

  2. 加密轮次:DES加密算法共有16个轮次,每个轮次都包括四个步骤:

    1. 将64位数据块分为左右两个32位块。

    2. 右侧32位块作为输入,经过扩展、异或、置换等操作生成一个48位的数据块。这个48位的数据块被称为“轮密钥”,它是根据加密算法的主密钥生成的子密钥。

    3. 将左侧32位块和轮密钥进行异或运算,结果作为新的右侧32位块。

    4. 将右侧32位块与原来的左侧32位块进行连接,生成一个新的64位数据块,作为下一轮的输入。

  3. 末置换(FP置换):在最后一个轮次完成后,将经过加密的数据块进行置换和重新排列,得到加密后的64位密文。

算法原理:

  • PC1(密钥置换选择 1) :将 64 位原始密钥去除 8 位校验位,得到 56 位有效密钥,并调整位顺序。

  • PC2(密钥置换选择 2) :将 56 位密钥进一步置换为 48 位,生成每轮的子密钥。

  • IP(初始置换) :对 64 位明文分组进行初始位重排,打破明文原始位顺序。

  • IP_INV(逆初始置换) :与 IP 互为逆作,用于加密最后一步,还原位顺序。

  • E(扩展置换) :将 32 位数据扩展为 48 位,使数据长度与子密钥长度匹配

  • P(P 盒置换) :对 S 盒输出的 32 位数据进行位重排

  • S_BOXES(S 盒) :8 个 4×16 的非线性替代盒,将 6 位输入转换为 4 位输出

对称性数学验证(以 第 2 轮为例)

以 2 轮 Feistel 迭代为例,可直观验证解密的正确性:

  • 加密过程:​(加密输出​)。

  • 解密过程(输入​,子密钥顺序​):第 1 轮解密(用​):​,​(异或抵消轮函数)。第 2 轮解密(用​):​,​(最终还原​)。

通过数学推导可见,反向使用子密钥可完全还原原始数据,证明了 DES 加解密的对称性。

二、DES 算法的弱密钥与安全性

  1. 弱密钥(Weak Keys)

DES 存在 4 个弱密钥,其特点是 “加密与解密等价”(​),且 “加密两次还原明文”(​),核心原因是弱密钥生成的 16 轮子密钥完全相同。4 个弱密钥(64 位,十六进制):

  • 0000000000000000

  • FFFFFFFFFFFFFFFF

  • 00000000FFFFFFFFFFFFFFFF

  • FFFFFFFFFFFFFFFF00000000

  1. 半弱密钥(Semi-weak Keys)

半弱密钥成对存在(共 6 对),特点是 “用 K1 加密后再用 K2 加密,还原明文”(​),核心原因是两对密钥生成的子密钥互为补集。经典半弱密钥对(十六进制):

  • 0101010101010101​ 与 ​FEFEFEFEFEFEFEFE

  • 1F1F1F1F0E0E0E0E​ 与 ​E0E0E0E0F1F1F1F1

  • 01FE01FE01FE01FE​ 与 ​FE01FE01FE01FE01

  • 1FE01FE00EF10EF1​ 与 ​​E01FE01FF10EF10E

  • 01E001E001F101F1​ 与 ​E001E001F101F101

  • 1FFE1FFE0EFE0EFE​ 与 ​FE1FFE1FFE0EFE0E

三、DES算法代码实现

"""
请使用编程语言实现对称加密算法DES(语言不限)
要求:
论述DES算法的原理及实现过程
请给出DES算法弱密钥,并通过程序验证弱密钥的危害
编程语言不限
"""
import sys
from typing import List, Tuple# DES常量定义
# 密钥置换选择1矩阵
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
]
# 密钥置换选择2矩阵
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
]
# 加密扩展置换矩阵
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盒置换矩阵
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
]
# S盒置换矩阵
S_BOXES = [# 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]]
]
# 初始置换矩阵
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
]# 循环左移位数
SHIFT_SCHEDULE = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]# 根据置换表对数据块进行置换
def permute(block: int, table: List[int], n: int) -> int:"""根据置换表对数据块进行置换"""result = 0for i, pos in enumerate(table):bit = (block >> (n - pos)) & 1result |= (bit << (len(table) - 1 - i))return resultdef generate_subkeys(key: int) -> List[int]:"""从64位密钥生成16个48位子密钥"""# 密钥置换1 (PC1),丢弃8个奇偶校验位key_56 = permute(key, PC1, 64)# 分为C0和D0C = (key_56 >> 28) & 0x0FFFFFFFD = key_56 & 0x0FFFFFFFsubkeys = []for i in range(16):# 循环左移shift = SHIFT_SCHEDULE[i]C = ((C << shift) | (C >> (28 - shift))) & 0x0FFFFFFFD = ((D << shift) | (D >> (28 - shift))) & 0x0FFFFFFF# 合并并应用PC2置换CD = (C << 28) | Dsubkey = permute(CD, PC2, 56)subkeys.append(subkey)return subkeysdef feistel(R: int, subkey: int) -> int:"""Feistel函数"""# 扩展置换expanded = permute(R, E, 32)# 与子密钥异或xored = expanded ^ subkey# S盒替代s_output = 0for i in range(8):block = (xored >> (42 - i * 6)) & 0x3F# row = ((block >> 5) << 1) | (block & 0x01)# col = (block >> 1) & 0x0Frow = ((block & 0x20) >> 4) | (block & 0x01)col = (block >> 1) & 0x0Fval = S_BOXES[i][row][col]s_output |= (val << (28 - i * 4))# P盒置换return permute(s_output, P, 32)def des_block(block: int, subkeys: List[int], encrypt: bool = True) -> int:"""加密或解密单个64位数据块"""# 初始置换block = permute(block, IP, 64)# 分为左右两部分L = (block >> 32) & 0xFFFFFFFFR = block & 0xFFFFFFFF# 16轮Feistel网络for i in range(16):round_key = subkeys[i] if encrypt else subkeys[15 - i]new_L = Rnew_R = L ^ feistel(R, round_key)L, R = new_L, new_R# 合并左右部分combined = (R << 32) | L# 逆初始置换return permute(combined, IP_INV, 64)def pkcs7_pad(data: bytes, block_size: int = 8) -> bytes:"""PKCS#7填充"""pad_len = block_size - (len(data) % block_size)return data + bytes([pad_len] * pad_len)def pkcs7_unpad(data: bytes) -> bytes:"""去除PKCS#7填充"""pad_len = data[-1]if pad_len < 1 or pad_len > 8:raise ValueError("Invalid padding")for b in data[-pad_len:]:if b != pad_len:raise ValueError("Invalid padding")return data[:-pad_len]# 将8字节转换为64位整数
def bytes_to_block(b: bytes) -> int:"""将8字节转换为64位整数"""return int.from_bytes(b, byteorder='big')def block_to_bytes(block: int) -> bytes:"""将64位整数转换为8字节"""return block.to_bytes(8, byteorder='big')def des_encrypt(key: bytes, plaintext: bytes) -> bytes:"""DES加密函数"""if len(key) != 8:raise ValueError("Key must be 8 bytes (64 bits)")key_int = bytes_to_block(key)subkeys = generate_subkeys(key_int)# 填充明文padded = pkcs7_pad(plaintext)ciphertext = []for i in range(0, len(padded), 8):block = bytes_to_block(padded[i:i + 8])encrypted = des_block(block, subkeys, encrypt=True)ciphertext.append(block_to_bytes(encrypted))return b''.join(ciphertext)def des_decrypt(key: bytes, ciphertext: bytes) -> bytes:"""DES解密函数"""if len(key) != 8:raise ValueError("Key must be 8 bytes (64 bits)")if len(ciphertext) % 8 != 0:raise ValueError("Ciphertext length must be multiple of 8")key_int = bytes_to_block(key)subkeys = generate_subkeys(key_int)plaintext = []for i in range(0, len(ciphertext), 8):block = bytes_to_block(ciphertext[i:i + 8])decrypted = des_block(block, subkeys, encrypt=False)plaintext.append(block_to_bytes(decrypted))# 去除填充return pkcs7_unpad(b''.join(plaintext))def test_des():"""测试DES加密解密功能"""key = b'22922922'plaintext = b'This is a test message for DES encryption.'ciphertext = des_encrypt(key, plaintext)decrypted = des_decrypt(key, ciphertext)print("明文:", plaintext)print("密钥:", key)print("密文:", ciphertext.hex())print("解密:", decrypted)assert decrypted == plaintext, "Encryption/decryption failed"def test_weak_keys():"""测试DES弱密钥和半弱密钥"""# 弱密钥(Weak Keys)weak_keys = [b'\x01\x01\x01\x01\x01\x01\x01\x01',  b'\xFE\xFE\xFE\xFE\xFE\xFE\xFE\xFE',  b'\xE0\xE0\xE0\xE0\xF1\xF1\xF1\xF1', b'\x1F\x1F\x1F\x1F\x0E\x0E\x0E\x0E'  ]# 半弱密钥对(Semi-weak Key Pairs)semiweak_pairs = [(b'\x01\xFE\x01\xFE\x01\xFE\x01\xFE', b'\xFE\x01\xFE\x01\xFE\x01\xFE\x01'),(b'\x1F\xE0\x1F\xE0\x0E\xF1\x0E\xF1', b'\xE0\x1F\xE0\x1F\xF1\x0E\xF1\x0E'),(b'\x01\xE0\x01\xE0\x01\xF1\x01\xF1', b'\xE0\x01\xE0\x01\xF1\x01\xF1\x01'),(b'\x1F\xFE\x1F\xFE\x0E\xFE\x0E\xFE', b'\xFE\x1F\xFE\x1F\xFE\x0E\xFE\x0E'),(b'\x01\x1F\x01\x1F\x01\x0E\x01\x0E', b'\x1F\x01\x1F\x01\x0E\x01\x0E\x01'),(b'\xE0\xFE\xE0\xFE\xF1\xFE\xF1\xFE', b'\xFE\xE0\xFE\xE0\xFE\xF1\xFE\xF1')]# 使用正好8字节的明文plaintext_block = b'12345678'print(f"\n弱密钥测试明文块: {plaintext_block.decode()}")# ==== 测试弱密钥 ====print("===== 弱密钥测试 =====")for i, key in enumerate(weak_keys):key_int = bytes_to_block(key)subkeys = generate_subkeys(key_int)block = bytes_to_block(plaintext_block)encrypted = des_block(block, subkeys, encrypt=True)double_encrypted = des_block(encrypted, subkeys, encrypt=True)double_encrypted_bytes = block_to_bytes(double_encrypted)print(f"弱密钥 #{i+1}: {key.hex()}")if double_encrypted_bytes == plaintext_block:print("✅ 弱密钥特性成立: 加密两次等于明文")else:print("❌ 弱密钥特性不成立")# 验证解密decrypted = des_block(encrypted, subkeys, encrypt=False)if block_to_bytes(decrypted) == plaintext_block:print("✅ 解密正确")else:print("❌ 解密失败")print("\n===== 半弱密钥测试 =====")for i, (key1, key2) in enumerate(semiweak_pairs):key1_int = bytes_to_block(key1)key2_int = bytes_to_block(key2)subkeys1 = generate_subkeys(key1_int)subkeys2 = generate_subkeys(key2_int)block = bytes_to_block(plaintext_block)# 半弱密钥特性测试:E_{K2}(E_{K1}(P)) = Pencrypted1 = des_block(block, subkeys1, encrypt=True)  # K1加密encrypted2 = des_block(encrypted1, subkeys2, encrypt=True)  # K2加密print(f"半弱密钥对 #{i + 1}:\n  K1: {key1.hex()}\n  K2: {key2.hex()}")if block_to_bytes(encrypted2) == block_to_bytes(block):print("✅ 半弱密钥特性成立: E_{K2}(E_{K1}(P)) = P")else:print("❌ 半弱密钥特性不成立: E_{K2}(E_{K1}(P)) != P")if __name__ == "__main__":test_des()test_weak_keys()

http://www.dtcms.com/a/469921.html

相关文章:

  • 游戏怎么做充值网站天津市建设工程监理公司网站
  • 01-Python简介与环境搭建-练习
  • Flink面试题及详细答案100道(81-100)- 部署、优化与生态
  • 机器学习实践项目(一)- Rossman商店销售预测 - 预处理数据
  • spring-Integration
  • SQL核心语言详解:DQL、DML、DDL、DCL从入门到实践!
  • 相亲网站怎么做的免费做网站tk
  • 在阿里巴巴上做网站要多少钱怎样制作自己的app
  • 数据湖Hudi - 二级索引:配置方法、存储位置与自动构建全解析(附电商实操案例)
  • 基于K近邻(KNN)算法的高光谱数据分类MATLAB实现
  • 石油网页设计与网站建设万网如何上传网站
  • 乐迪信息:智慧煤矿输送带安全如何保障?AI摄像机全天候识别
  • VMware vCenter 基础命令的 6 大核心模块
  • 龙华建设局网站做社区生意的网站
  • 【STM32项目开源】基于STM32的智能语音台灯系统
  • 构建和部署Spark、Hadoop与Zeppelin集成环境
  • 网站建设引擎广西住房和城乡建设厅领导班子
  • 把dxf转化成图片喂给vlm实现图纸检查比如尺寸有没有漏标
  • C++基础:(十一)vector深度剖析:底层原理与模拟实现
  • 【自用】request.ts 封装,带 token 过期后自动刷新 token 的功能
  • 成都定制网站建设服合肥公司注册地址
  • 分布式事务在前后端分离场景下的最终一致性实现
  • 农产品电子商务网站建设要求锦州网站建设公司
  • SSH命令建立隧道
  • [GazeTracking] 依赖项管理 | Docker化执行环境
  • uniapp web-view相互通信方法
  • (2)Kafka架构原理与存储机制
  • uniapp学习【项目创建+项目结构解析】
  • 虚拟机所需的硬件功能在目标主机上不受支持或已禁用:*长模式:对于支持64位客户机操作系统而言是必需的。
  • Uniapp微信小程序开发:http请求封装。