3825 字
19 分钟
DES加密算法

简介#

DES 算法是最早的对称加密算法,虽然已经被 AES 所取代了,但是在安卓逆向的过程中还是有可能会遇到这个算法,所以对它有一定了解还是必要的

基本参数:

  • 分组大小:64 位(8 字节)
  • 密钥长度:56 位有效密钥(实际 64 位,含 8 位奇偶校验)
  • 迭代轮数:16 轮
  • 工作模式:ECB,CBC,CFB,OFB 等 DES 分成两部分,一部分是明文的处理,另一部分是密钥的编排

第一部分:密钥的编排(子密钥生成)#

密钥编排是指从 64 位的主密钥生成 16 个 48 位主密钥的过程,使用官方测试向量:

  • 明文:0x0123456789ABCDEF(64 位)
  • 密钥:0x133457799BBCDFF1(64 位,含奇偶校验)
  • 期望密文:0x85E813540F0AB405(64 位)

密钥初始置换#

目的:去除 8 个奇偶校验位,将 64 位密钥压缩成 56 位有效密钥
PC-1 置换表(56 个位置):

Terminal window
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-1 置换
主密钥的二进制展开:

Terminal window
00010011 00110100 01010111 01111001
10011011 10111100 11011111 11110001

按 PC-1 表逐位提取:

  • 新第 1 位<=原 57 位,第 57 位在第 8 个字节的第一位(57/8=7 余 1)
    • 第 8 个字节 11110001 的第一位是 1
  • 新第 2 位<=原 49 位,第 49 位在第 7 个字节的第一位(49/8=6 余 1)
    • 第 7 个字节 11011111 的第一位是 1
  • 新第 3 位<=原 41 位,第 41 位在第 6 个字节的第一位(41/8=5 余 1)
    • 第 6 个字节 10111100 的第一位是 1
  • 以此类推,继续提取 56 位…

PC-1 置换结果(56 位):

Terminal window
1111000 0110011 0010101 0101111
0101010 1011001 1001111 0001111

分别拆分成 C0 和 `D0

  • C0=前 28 位= 1111000 0110011 0010101 0101111
  • D0=后 28 位= 0101010 1011001 1001111 0001111

循环左移生成 16 对#

左移规则表:

轮次12345678910111213141516
左移1122222212222221

先计算一下前两轮:
第一轮:左移 1 位

  • C0= 1111000 0110011 0010101 0101111
  • 循环左移 1 位: 1110000 1100110 0101010 1011111 即 C1
  • D0= 0101010 1011001 1001111 0001111
  • 循环左移 1 位: 1010101 0110011 0011110 0011110 即 D1 第二轮:左移 1 位
  • C1= 1110000 1100110 0101010 1011111
  • 循环左移 1 位: 1100001 1001100 1010101 0111111 即 C2
  • D1= 1010101 0110011 0011110 0011110
  • 循环左移 1 位: 0101010 1100110 0111100 0111101 即 D2 继续左移得到 16 对…(按照左移规则)

PC-2 置换生成 16 个子密钥#

PC-2 置换表:(56 位=>48 位)

Terminal window
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

生成 K1 子密钥:

  • 合并 C1 和 D1=56 位
  • 按 PC-2 选择 48 位
    • 新第 1 位<-原 14 位
    • 新第 2 位<-原 17 位
    • 以此类推…
  • 得到了 K1= 000110 110000 001011 101111 111111 000111 000001 110010 16 个子密钥的生成(十六进制)
Terminal window
K₁ = 0x1B02EFFC7072
K₂ = 0x79AED9DBC9E5
K₃ = 0x55FC8A42CF99
K₄ = 0x72A9F92972A9
K₅ = 0x6D114CC2685F
K₆ = 0x5BA61D20C3B6
K₇ = 0x4B7DC64A3F4A
K₈ = 0x27A7D8495E4A
K₉ = 0x42B1D6A3F4A7
K₁₀ = 0x7D8495E4A27A
K₁₁ = 0x1D6A3F4A742B
K₁₂ = 0xD8495E4A27A7
K₁₃ = 0xD6A3F4A742B1
K₁₄ = 0x8495E4A27A7D
K₁₅ = 0x6A3F4A742B1D
K₁₆ = 0x495E4A27A7D8

至此,16 个子密钥生成完毕

第二部分:明文的处理#

初始置换(IP 置换)#

明文: 0x0123456789ABCDEF
二进制明文展开:

Terminal window
字节1: 00000001 (0x01)
字节2: 00100011 (0x23)
字节3: 01000101 (0x45)
字节4: 01100111 (0x67)
字节5: 10001001 (0x89)
字节6: 10101011 (0xAB)
字节7: 11001101 (0xCD)
字节8: 11101111 (0xEF)

IP 置换表(64 位重排)

Terminal window
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 置换计算示例:

  • 新第 1 位<-原第 58 位,第 58 位在第 8 个字节的第二位(58/8=7 余 2)
    • 第 8 个字节: 11101111 第二位是 1
  • 新第 2 位<-原第50 位,第 50 位在第 7 个字节的第二位(50/8=6 余 2)
    • 第 7 个字节: 11001101 第二位是 1
  • …继续 64 位

IP 置换结果:

Terminal window
11001100 00000000 11001100 11111111
11110000 10101010 11110000 10101010

16 进制: 0xCC00CCFFF0AAF0AA
分别拆分成 L0 和 R0:

  • L0=左 32 位=0xCC00CCFF= 11001100 00000000 11001100 11111111
  • R0=右 32 位=0xF0AAF0AA= 11110000 10101010 11110000 10101010

16 轮运算#

轮函数 f(R,K) 的完整计算过程:
步骤 1:扩展置换(32 位=>48 位) 因为下面需要与子密钥进行异或,子密钥是 48 位,所以需要进行密钥扩展
E 扩展表:

Terminal window
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

R0 的位级扩展:
R0= 11110000 10101010 11110000 10101010 (32 位)
按 E 表逐位映射:

  • 新第 1 位<=原第 32 位:R0 第 32 位是 0
  • 新第 2 位<=原第 1 位:R0 第 1 位是 1
  • 新第 3 位<=原第 2 位:R0 第 2 位是 1
  • 新第 4 位<=原第 3 位:R0 第 3 位是 1
  • 新第 5 位<=原第 4 位:R0 第 4 位是 1
  • 新第 6 位<=原第 5 位:R0 第 5 位是 0
  • 新第 7 位<=原第 4 位:R0 第 4 位是 1(重复利用)
  • 新第 8 位<=原第 5 位:R0 第 5 位是 0
  • …继续 48 位 E(R0)的结果就是:
Terminal window
011110 100001 010101 010101 011110 100001 010101 010101

步骤 2:与子密钥 K1 进行异或
子密钥: 0x1B02EFFC7072 (前面密钥编排得到)
二进制: 000110 110000 001011 101111 111111 000111 000001 110010
异或运算:

Terminal window
E(R₀): 011110 100001 010101 010101 011110 100001 010101 010101
K₁: 000110 110000 001011 101111 111111 000111 000001 110010
结果: 011000 010001 011110 111010 100001 100110 010100 100111

16 进制:0x6117BA86F527
步骤 3 盒替换 S 盒定义:

Terminal window
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]]
]

将步骤 2 得到的结果进行分组:

Terminal window
B1: 011000
B2: 010001
B3: 011110
B4: 111010
B5: 100001
B6: 100110
B7: 010100
B8: 100111

以 B1 为例:
行号:第 1 位和最后一位合起来:00,对应 10 进制就是 0,表示第 1 行
列号:中间 4 位:1100=12(列)即第 13 列
所以: S[0][12]=5 =>二进制 0101

Terminal window
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]
]

再来以 B2 来演示一组吧:
行号:第 1 位和最后 1 位合起来就是 01,对应的 10 进制就是 1,表示第 2 行
列号:中间 4 位 1000=8(列),即第 9 列
所以: S[1][8]=12 =>二进制:1100

Terminal window
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]
]

下面,以此内推;一共 8 组,每组 4 位,生成 32 位
步骤 4

盒置换(32 位=>32 位)
P 盒表:

Terminal window
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

重新排列之后得到 32 位
步骤 5:计算本轮输出
L1 = R0 = 0xF0AAF0AA
R1 = L₀ xor f(R₀, K₁) = 0xCC00CCFF xor 0x5E8350FA= 0x92839C05

周而复始:搞到 16 轮之后得到结果:

Terminal window
L16: 01000011 01000010 00110010 00110100
R16: 00001010 01001100 11011001 10010101

第三部分:末置换#

R16+L16= 00001010 01001100 11011001 10010101 01000011 01000010 00110010 00110100
最后通过 PC_1 置换表置换:

Terminal window
IP_1 = [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]

得到结果:

Terminal window
0x85E813540F0AB405

代码实现#

from typing import List
# IP置换表
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置换表
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]
# 扩展置换E表
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]
# PC-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]
# PC-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]
# 左移位数表
SHIFT_SCHEDULE = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]
# S盒定义(8个)
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 str_to_bits(text: str, size: int) -> List[int]:
"""将字符串转换为位列表"""
bits = []
for i in range(size):
byte = i // 8
bit = 7 - (i % 8)
if byte < len(text):
bits.append((ord(text[byte]) >> bit) & 1)
else:
bits.append(0)
return bits
def hex_to_bits(hex_str: str, size: int) -> List[int]:
"""将十六进制字符串转换为位列表"""
bits = []
hex_str = hex_str.replace(" ", "").replace("0x", "").zfill(size//4)
for char in hex_str:
val = int(char, 16)
for i in range(3, -1, -1):
bits.append((val >> i) & 1)
return bits[:size]
def bits_to_hex(bits: List[int]) -> str:
"""将位列表转换为十六进制字符串"""
hex_str = ""
for i in range(0, len(bits), 8):
byte = 0
for j in range(8):
if i+j < len(bits):
byte = (byte << 1) | bits[i+j]
hex_str += f"{byte:02X}"
return hex_str.lower()
def permute(bits: List[int], table: List[int]) -> List[int]:
"""按置换表进行置换"""
return [bits[table[i]-1] for i in range(len(table))]
def left_shift(bits: List[int], n: int) -> List[int]:
"""循环左移"""
return bits[n:] + bits[:n]
def generate_subkeys(key_bits: List[int]) -> List[List[int]]:
"""生成16个子密钥"""
# PC-1置换
key_pc1 = permute(key_bits, PC1)
# 分成左右两部分
C = key_pc1[:28]
D = key_pc1[28:]
subkeys = []
for round_num in range(16):
# 循环左移
shift = SHIFT_SCHEDULE[round_num]
C = left_shift(C, shift)
D = left_shift(D, shift)
# PC-2置换生成子密钥
combined = C + D
subkey = permute(combined, PC2)
subkeys.append(subkey)
return subkeys
def f_function(R: List[int], K: List[int]) -> List[int]:
"""f函数"""
# 扩展置换E
R_expanded = permute(R, E)
# 与子密钥异或
xor_result = [R_expanded[i] ^ K[i] for i in range(48)]
# S盒替换
sbox_output = []
for i in range(8):
# 取6位
block = xor_result[i*6:(i+1)*6]
row = (block[0] << 1) | block[5]
col = (block[1] << 3) | (block[2] << 2) | (block[3] << 1) | block[4]
val = S_BOX[i][row][col]
# 转换为4位
sbox_output.extend([(val >> 3) & 1, (val >> 2) & 1, (val >> 1) & 1, val & 1])
# P盒置换
return permute(sbox_output, P)
def des_encrypt(plaintext_bits: List[int], key_bits: List[int]) -> List[int]:
"""DES加密"""
# 初始置换IP
bits = permute(plaintext_bits, IP)
# 生成子密钥
subkeys = generate_subkeys(key_bits)
# 分成左右两部分
L = bits[:32]
R = bits[32:]
# 16轮迭代
for i in range(16):
L_next = R[:]
f_result = f_function(R, subkeys[i])
R_next = [L[j] ^ f_result[j] for j in range(32)]
L, R = L_next, R_next
# 最后交换(算法中先交换再末置换)
combined = R + L
# 末置换IP^-1
ciphertext = permute(combined, IP_INV)
return ciphertext
# 测试
if __name__ == "__main__":
plaintext_hex = "0123456789ABCDEF"
key_hex = "133457799BBCDFF1"
# 转换为位列表
plaintext_bits = hex_to_bits(plaintext_hex, 64)
key_bits = hex_to_bits(key_hex, 64)
print(f"明文: {plaintext_hex}")
print(f"密钥: {key_hex}")
# 加密
ciphertext_bits = des_encrypt(plaintext_bits, key_bits)
ciphertext_hex = bits_to_hex(ciphertext_bits)
print(f"密文: {ciphertext_hex}")
DES加密算法
https://819229.xyz/posts/des加密算法/
作者
0xnonce
发布于
2026-01-31
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。

继续阅读

沿着主题读

基于共同的标签与分类

换条路线

从其他文章中稳定抽取

评论

正在加载评论...
0/2000

    最后更新于 ,距今已过 211

    部分内容可能已过时