DES 编码的原理及实现
2011-10-18 17:13
357 查看
DES(Data Encryption Standard), 出自于IBM的研究项目, 1977 年被美国政府正式采用.
DES的特点为 Working On Bits
假设有一组KEY为 "133457799BBCDFF1" 8 bytes, 资料为 "0123456789ABCDEF" 8 bytes, 则加密后的资料为 8 bytes 的 "85E813540F0AB405"
那么加密的算法为何?
Step1: 由 KEY 算出 16 组的 subkeys, 每一个 subkey 为 48 bits
1) 首先将 KEY "133457799BBCDFF1" 转换成 64 bits binary string:
K+: 0001001100110100010101110111100110011011101111001101111111110001
它是由一组对应表转换而成。
my %codemap = ('0' => '0000', '1' => '0001', '2' => '0010', '3' => '0011',
'4' => '0100', '5' => '0101', '6' => '0110', '7' => '0111',
'8' => '1000', '9' => '1001', 'A' => '1010', 'B' => '1011',
'C' => '1100', 'D' => '1101', 'E' => '1110', 'F' => '1111');
2) 再由一组置换阵列
(其数值就表示 K+ 中的第几个 bit, starting from 1, instead of from 0)
my @pc1map = (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);
转换成 56 bits binary string
K0: 11110000110011001010101011110101010101100110011110001111
3) 将 K0 分成左右两个部分,每个部分为 28 bits binary string
C0: 1111000011001100101010101111
D0: 0101010101100110011110001111
Ci 与 Di (i=1..16) 分别按下表进行位移处理:
my %iterations = ( 1 => 1, 2 => 1, 3 => 2, 4 => 2, 5 => 2, 6 => 2, 7 => 2,
8 => 2, 9 => 1, 10 => 2, 11 => 2, 12 => 2, 13 => 2,
14 => 2, 15 => 2, 16 => 1);
按上表 C1=》C0 位移 1 位: C0 的第 2 位为 C1 的第 1 位, C0 的第 3 位为 C1 的第 2 位,
..., C0 的第 1 位为 C1 的最后 1 位
D1=》D0 位移 1 位: D0 的第 2 位为 D1 的第 1 位, D0 的第 3 位为 D1 的第 2 位,
..., D0 的第 1 位为 D1 的最后 1 位
C3=》C2 位移 2 位: C2 的第 3 位为 C3 的第 1 位, C2 的第 4 位为 C3 的第 2 位,...,
C2 的第 1 位为 C3 的倒数第 2 位, C2 的第 2 位为 C3 的最后 1 位
D3=》D2 位移 2 位: D2 的第 3 位为 D3 的第 1 位, D2 的第 4 位为 D3 的第 2 位,...,
D2 的第 1 位为 D3 的倒数第 2 位, D2 的第 2 位为 D3 的最后 1 位
依此可得
C1 = 1110000110011001010101011111
D1 = 1010101011001100111100011110
C2 = 1100001100110010101010111111
D2 = 0101010110011001111000111101
C3 = 0000110011001010101011111111
D3 = 0101011001100111100011110101
C4 = 0011001100101010101111111100
D4 = 0101100110011110001111010101
C5 = 1100110010101010111111110000
D5 = 0110011001111000111101010101
C6 = 0011001010101011111111000011
D6 = 1001100111100011110101010101
C7 = 1100101010101111111100001100
D7 = 0110011110001111010101010110
C8 = 0010101010111111110000110011
D8 = 1001111000111101010101011001
C9 = 0101010101111111100001100110
D9 = 0011110001111010101010110011
C10 = 0101010111111110000110011001
D10 = 1111000111101010101011001100
C11 = 0101011111111000011001100101
D11 = 1100011110101010101100110011
C12 = 0101111111100001100110010101
D12 = 0001111010101010110011001111
C13 = 0111111110000110011001010101
D13 = 0111101010101011001100111100
C14 = 1111111000011001100101010101
D14 = 1110101010101100110011110001
C15 = 1111100001100110010101010111
D15 = 1010101010110011001111000111
C16 = 1111000011001100101010101111
D16 = 0101010101100110011110001111
4) 将 Ci, Di 组合起来 CiDi 再经过置换阵列
my @pc2map = (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);
转换可得 16 组 subkeys
K1 = 000110110000001011101111111111000111000001110010
K2 = 011110011010111011011001110110111100100111100101
K3 = 010101011111110010001010010000101100111110011001
K4 = 011100101010110111010110110110110011010100011101
K5 = 011111001110110000000111111010110101001110101000
K6 = 011000111010010100111110010100000111101100101111
K7 = 111011001000010010110111111101100001100010111100
K8 = 111101111000101000111010110000010011101111111011
K9 = 111000001101101111101011111011011110011110000001
K10 = 101100011111001101000111101110100100011001001111
K11 = 001000010101111111010011110111101101001110000110
K12 = 011101010111000111110101100101000110011111101001
K13 = 100101111100010111010001111110101011101001000001
K14 = 010111110100001110110111111100101110011100111010
K15 = 101111111001000110001101001111010011111100001010
K16 = 110010110011110110001011000011100001011111110101
Step2: 对每个 64 bit data block 进行编码
1) 将 Data '0123456789ABCDEF' 转换成 64 bits binary string
M = '0000000100100011010001010110011110001001101010111100110111101111'
2) 将 M 进行第一次的置换
my @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 = '1100110000000000110011001111111111110000101010101111000010101010'
3) 将 IP 分为左右两个部分, 每部分 32 bits binary string
L0 = 11001100000000001100110011111111
R0 = 11110000101010101111000010101010
4) 将 L0, R0 按如下规则迭代运算: i=1..16
L[i] = R[i-1]
R[i] = L[i-1] + f(R[i-1], K[i])
上式的加法为 XOR on bits, f 的作用为
*1 R[i-1] 为 32 bit, 而 K[i] 为 48 bit, 需要将 R[i-1] 扩充为 48 bit, 规则如下置换阵列
my @selection_table = (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);
以计算 L1, R1 为例: EXP = 011110100001010101010101011110100001010101010101
*2 扩充好的 binary string exp 与 K[i] 作用 xor on bits,
可得 48 bits binary string - xor
EXP = 011110100001010101010101011110100001010101010101
K1 = 000110110000001011101111111111000111000001110010
---------------------------------------------------------
XOR = 011000010001011110111010100001100110010100100111
*3 计算 XOR 的 sboxes: 将 XOR 6 bit 为 1 组分成 8 组 xor[i] (i=0..7)
每一组对应一组 sbox, 可得 8 个 sbox index
my @sb1 = (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);
my @sb2 = (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);
my @sb3 = (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);
my @sb4 = ( 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);
my @sb5 = ( 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);
my @sb6 = (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);
my @sb7 = ( 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);
my @sb8 = (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);
以上例解释: XOR 可分为 011000 010001 011110 111010 100001 100110 010100 100111
其 sbox index 的运算规则为 row number = 第 1 位与最后 1 位组合起来的值; col number = 中间 4 位组合起来的值
依序可得 sbox index
(00, 1100), (01, 1000), (00, 1111), (10, 1101), (11, 0000), (10, 0011), (00, 1010), (11, 0011)
取值为
(0, 12), (1, 8), (0, 15), (2, 13), (3, 0), (2, 3), (0, 10), (3, 3)
依序对应
SB1[0, 12], SB2[1, 8], SB3[0, 15], SB4[2, 13], SB5[3, 0], SB6[2, 3], SB7[0, 10], SB8[3, 3]
=>
5, 12, 8, 2, 11, 5, 9, 7
=>
0101, 1100, 1000, 0010, 1011, 0101, 1001, 0111
SBS = 0101 1100 1000 0010 1011 0101 1001 0111
*4 SBS 经置换阵列
my @sp = (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 = 00100011010010101010100110111011
依此规则可得:
L1 = 11110000101010101111000010101010
R1 = 11101111010010100110010101000100
L2 = 11101111010010100110010101000100
R2 = 11001100000000010111011100001001
L3 = 11001100000000010111011100001001
R3 = 10100010010111000000101111110100
L4 = 10100010010111000000101111110100
R4 = 01110111001000100000000001000101
L5 = 01110111001000100000000001000101
R5 = 10001010010011111010011000110111
L6 = 10001010010011111010011000110111
R6 = 11101001011001111100110101101001
L7 = 11101001011001111100110101101001
R7 = 00000110010010101011101000010000
L8 = 00000110010010101011101000010000
R8 = 11010101011010010100101110010000
L9 = 11010101011010010100101110010000
R9 = 00100100011111001100011001111010
L10 = 00100100011111001100011001111010
R10 = 10110111110101011101011110110010
L11 = 10110111110101011101011110110010
R11 = 11000101011110000011110001111000
L12 = 11000101011110000011110001111000
R12 = 01110101101111010001100001011000
L13 = 01110101101111010001100001011000
R13 = 00011000110000110001010101011010
L14 = 00011000110000110001010101011010
R14 = 11000010100011001001011000001101
L15 = 11000010100011001001011000001101
R15 = 01000011010000100011001000110100
L16 = 01000011010000100011001000110100
R16 = 00001010010011001101100110010101
5) 将 R16 与 L16 组合成 R16L16, 再经过最后一个置换即可得加密后的资料 FINAL
my @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);
FINAL = 85E813540F0AB405
Perl code 实现如下:
DES的特点为 Working On Bits
假设有一组KEY为 "133457799BBCDFF1" 8 bytes, 资料为 "0123456789ABCDEF" 8 bytes, 则加密后的资料为 8 bytes 的 "85E813540F0AB405"
那么加密的算法为何?
Step1: 由 KEY 算出 16 组的 subkeys, 每一个 subkey 为 48 bits
1) 首先将 KEY "133457799BBCDFF1" 转换成 64 bits binary string:
K+: 0001001100110100010101110111100110011011101111001101111111110001
它是由一组对应表转换而成。
my %codemap = ('0' => '0000', '1' => '0001', '2' => '0010', '3' => '0011',
'4' => '0100', '5' => '0101', '6' => '0110', '7' => '0111',
'8' => '1000', '9' => '1001', 'A' => '1010', 'B' => '1011',
'C' => '1100', 'D' => '1101', 'E' => '1110', 'F' => '1111');
2) 再由一组置换阵列
(其数值就表示 K+ 中的第几个 bit, starting from 1, instead of from 0)
my @pc1map = (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);
转换成 56 bits binary string
K0: 11110000110011001010101011110101010101100110011110001111
3) 将 K0 分成左右两个部分,每个部分为 28 bits binary string
C0: 1111000011001100101010101111
D0: 0101010101100110011110001111
Ci 与 Di (i=1..16) 分别按下表进行位移处理:
my %iterations = ( 1 => 1, 2 => 1, 3 => 2, 4 => 2, 5 => 2, 6 => 2, 7 => 2,
8 => 2, 9 => 1, 10 => 2, 11 => 2, 12 => 2, 13 => 2,
14 => 2, 15 => 2, 16 => 1);
按上表 C1=》C0 位移 1 位: C0 的第 2 位为 C1 的第 1 位, C0 的第 3 位为 C1 的第 2 位,
..., C0 的第 1 位为 C1 的最后 1 位
D1=》D0 位移 1 位: D0 的第 2 位为 D1 的第 1 位, D0 的第 3 位为 D1 的第 2 位,
..., D0 的第 1 位为 D1 的最后 1 位
C3=》C2 位移 2 位: C2 的第 3 位为 C3 的第 1 位, C2 的第 4 位为 C3 的第 2 位,...,
C2 的第 1 位为 C3 的倒数第 2 位, C2 的第 2 位为 C3 的最后 1 位
D3=》D2 位移 2 位: D2 的第 3 位为 D3 的第 1 位, D2 的第 4 位为 D3 的第 2 位,...,
D2 的第 1 位为 D3 的倒数第 2 位, D2 的第 2 位为 D3 的最后 1 位
依此可得
C1 = 1110000110011001010101011111
D1 = 1010101011001100111100011110
C2 = 1100001100110010101010111111
D2 = 0101010110011001111000111101
C3 = 0000110011001010101011111111
D3 = 0101011001100111100011110101
C4 = 0011001100101010101111111100
D4 = 0101100110011110001111010101
C5 = 1100110010101010111111110000
D5 = 0110011001111000111101010101
C6 = 0011001010101011111111000011
D6 = 1001100111100011110101010101
C7 = 1100101010101111111100001100
D7 = 0110011110001111010101010110
C8 = 0010101010111111110000110011
D8 = 1001111000111101010101011001
C9 = 0101010101111111100001100110
D9 = 0011110001111010101010110011
C10 = 0101010111111110000110011001
D10 = 1111000111101010101011001100
C11 = 0101011111111000011001100101
D11 = 1100011110101010101100110011
C12 = 0101111111100001100110010101
D12 = 0001111010101010110011001111
C13 = 0111111110000110011001010101
D13 = 0111101010101011001100111100
C14 = 1111111000011001100101010101
D14 = 1110101010101100110011110001
C15 = 1111100001100110010101010111
D15 = 1010101010110011001111000111
C16 = 1111000011001100101010101111
D16 = 0101010101100110011110001111
4) 将 Ci, Di 组合起来 CiDi 再经过置换阵列
my @pc2map = (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);
转换可得 16 组 subkeys
K1 = 000110110000001011101111111111000111000001110010
K2 = 011110011010111011011001110110111100100111100101
K3 = 010101011111110010001010010000101100111110011001
K4 = 011100101010110111010110110110110011010100011101
K5 = 011111001110110000000111111010110101001110101000
K6 = 011000111010010100111110010100000111101100101111
K7 = 111011001000010010110111111101100001100010111100
K8 = 111101111000101000111010110000010011101111111011
K9 = 111000001101101111101011111011011110011110000001
K10 = 101100011111001101000111101110100100011001001111
K11 = 001000010101111111010011110111101101001110000110
K12 = 011101010111000111110101100101000110011111101001
K13 = 100101111100010111010001111110101011101001000001
K14 = 010111110100001110110111111100101110011100111010
K15 = 101111111001000110001101001111010011111100001010
K16 = 110010110011110110001011000011100001011111110101
Step2: 对每个 64 bit data block 进行编码
1) 将 Data '0123456789ABCDEF' 转换成 64 bits binary string
M = '0000000100100011010001010110011110001001101010111100110111101111'
2) 将 M 进行第一次的置换
my @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 = '1100110000000000110011001111111111110000101010101111000010101010'
3) 将 IP 分为左右两个部分, 每部分 32 bits binary string
L0 = 11001100000000001100110011111111
R0 = 11110000101010101111000010101010
4) 将 L0, R0 按如下规则迭代运算: i=1..16
L[i] = R[i-1]
R[i] = L[i-1] + f(R[i-1], K[i])
上式的加法为 XOR on bits, f 的作用为
*1 R[i-1] 为 32 bit, 而 K[i] 为 48 bit, 需要将 R[i-1] 扩充为 48 bit, 规则如下置换阵列
my @selection_table = (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);
以计算 L1, R1 为例: EXP = 011110100001010101010101011110100001010101010101
*2 扩充好的 binary string exp 与 K[i] 作用 xor on bits,
可得 48 bits binary string - xor
EXP = 011110100001010101010101011110100001010101010101
K1 = 000110110000001011101111111111000111000001110010
---------------------------------------------------------
XOR = 011000010001011110111010100001100110010100100111
*3 计算 XOR 的 sboxes: 将 XOR 6 bit 为 1 组分成 8 组 xor[i] (i=0..7)
每一组对应一组 sbox, 可得 8 个 sbox index
my @sb1 = (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);
my @sb2 = (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);
my @sb3 = (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);
my @sb4 = ( 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);
my @sb5 = ( 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);
my @sb6 = (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);
my @sb7 = ( 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);
my @sb8 = (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);
以上例解释: XOR 可分为 011000 010001 011110 111010 100001 100110 010100 100111
其 sbox index 的运算规则为 row number = 第 1 位与最后 1 位组合起来的值; col number = 中间 4 位组合起来的值
依序可得 sbox index
(00, 1100), (01, 1000), (00, 1111), (10, 1101), (11, 0000), (10, 0011), (00, 1010), (11, 0011)
取值为
(0, 12), (1, 8), (0, 15), (2, 13), (3, 0), (2, 3), (0, 10), (3, 3)
依序对应
SB1[0, 12], SB2[1, 8], SB3[0, 15], SB4[2, 13], SB5[3, 0], SB6[2, 3], SB7[0, 10], SB8[3, 3]
=>
5, 12, 8, 2, 11, 5, 9, 7
=>
0101, 1100, 1000, 0010, 1011, 0101, 1001, 0111
SBS = 0101 1100 1000 0010 1011 0101 1001 0111
*4 SBS 经置换阵列
my @sp = (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 = 00100011010010101010100110111011
依此规则可得:
L1 = 11110000101010101111000010101010
R1 = 11101111010010100110010101000100
L2 = 11101111010010100110010101000100
R2 = 11001100000000010111011100001001
L3 = 11001100000000010111011100001001
R3 = 10100010010111000000101111110100
L4 = 10100010010111000000101111110100
R4 = 01110111001000100000000001000101
L5 = 01110111001000100000000001000101
R5 = 10001010010011111010011000110111
L6 = 10001010010011111010011000110111
R6 = 11101001011001111100110101101001
L7 = 11101001011001111100110101101001
R7 = 00000110010010101011101000010000
L8 = 00000110010010101011101000010000
R8 = 11010101011010010100101110010000
L9 = 11010101011010010100101110010000
R9 = 00100100011111001100011001111010
L10 = 00100100011111001100011001111010
R10 = 10110111110101011101011110110010
L11 = 10110111110101011101011110110010
R11 = 11000101011110000011110001111000
L12 = 11000101011110000011110001111000
R12 = 01110101101111010001100001011000
L13 = 01110101101111010001100001011000
R13 = 00011000110000110001010101011010
L14 = 00011000110000110001010101011010
R14 = 11000010100011001001011000001101
L15 = 11000010100011001001011000001101
R15 = 01000011010000100011001000110100
L16 = 01000011010000100011001000110100
R16 = 00001010010011001101100110010101
5) 将 R16 与 L16 组合成 R16L16, 再经过最后一个置换即可得加密后的资料 FINAL
my @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);
FINAL = 85E813540F0AB405
Perl code 实现如下:
#!/usr/bin/perl -w # DES algorithm - reference to http://orlingrabbe.com/des.htm sub iteration_handle { my ($bitstring, $pad) = @_; my $bitstringp = pack 'b*', $bitstring; my @bitarray = split(//, unpack('b*',$bitstringp)); my @subkey; # perl give four zeros append the last of packed string my ($d1, $d2) = (scalar(@bitarray) - 4, scalar(@bitarray) - 1); delete @bitarray[$d1..$d2]; #print "PAD=$pad\n"; # handle last $pad bits for ($n=$pad; $n>0; $n--) { $subkey[scalar(@bitarray)-$n] = $bitarray[$pad - $n]; } # handle head of bits for($i=0; $i<(scalar(@bitarray)-$pad); $i++) { #if ($i == $#bitarray) { # $subkey[$i] = $bitarray[0]; #} else { $subkey[$i] = $bitarray[$i+$pad]; #} #print $i. ": ". $subkey[$i]. "\n"; } return join('', @subkey); } sub tobit { my $uncode = shift; my %codemap = ('0' => '0000', '1' => '0001', '2' => '0010', '3' => '0011', '4' => '0100', '5' => '0101', '6' => '0110', '7' => '0111', '8' => '1000', '9' => '1001', 'A' => '1010', 'B' => '1011', 'C' => '1100', 'D' => '1101', 'E' => '1110', 'F' => '1111'); my $coded = ''; my @chars = split('', $uncode); foreach $c (@chars) { $coded .= $codemap{$c}; } return $coded; } sub tohex { my $origin = shift; my @hexbits = split(//, $origin); my $ret = ''; for ($j=0; $j<@hexbits; $j=$j+4) { $hex = join '', @hexbits[$j..($j+3)]; $ret .= sprintf ("%x", oct('0b' .$hex)); } return $ret; } sub permuted { my $unpermuted = shift; # the first permutation chooser map table my @pc1map = (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); my $permuted = ''; my @unpermutation = split(//, $unpermuted); foreach $d (@pc1map) { $permuted .= $unpermutation[$d-1]; # start from index 1 } return $permuted; } sub generate_subkey { my $origin = shift; # the second permutation chooser map table my @pc2map = (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); my $permuted = ''; my @unpermutation = split(//, $origin); foreach $d (@pc2map) { $permuted .= $unpermutation[$d-1]; # start from index 1 } return $permuted; } sub initial_permutation { my $origin = shift; # the initial permutation map table my @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); my $permuted = ''; my @unpermutation = split(//, $origin); foreach $d (@IP) { $permuted .= $unpermutation[$d-1]; # start from index 1 } return $permuted; } sub expand { my $origin = shift; # bit selection table my @selection_table = (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); my $permuted = ''; my @unpermutation = split(//, $origin); foreach $d (@selection_table) { #print "array of position $d: $unpermutation[$d-1]\n"; $permuted .= $unpermutation[$d-1]; # start from index 1 } return $permuted; } sub subxor { my ($a, $b) = @_; my @as = split(//, $a); my @bs = split(//, $b); my @targets; for ($z=0; $z<@as; $z++) { if ($as[$z] eq '0' && $bs[$z] eq '0') { $targets[$z] = '0'; } elsif ($as[$z] eq '1' && $bs[$z] eq '1') { $targets[$z] = '0'; } else { $targets[$z] = '1'; } } return join '', @targets; } sub cal_sboxes { my $origin = shift; my @sboxes; my @scalars = split(//, $origin); my @sb1 = (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); my @sb2 = (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); my @sb3 = (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); my @sb4 = ( 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); my @sb5 = ( 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); my @sb6 = (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); my @sb7 = ( 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); my @sb8 = (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); @sboxes = (\@sb1, \@sb2, \@sb3, \@sb4, \@sb5, \@sb6, \@sb7, \@sb8); my $ret = ''; my $index = 0; for ($i=0; $i<@scalars; $i=$i+6, $index++) { $row = oct('0b'. join ('', @scalars[$i,($i+5)])); $col = oct ('0b'. join ('', @scalars[($i+1)..($i+4)])); #print "ROW: $row, COL= $col\n"; $sindex = $row == 0 ? ($row * 15 + $col) : ($row * 16 + $col); #print "SINDEX = $sindex\n"; #print "ROW= $row, COL= $col, V= $sboxes[$index][$sindex]\n"; #print sprintf("%04b", $sboxes[$index][$sindex]); $ret .= sprintf("%04b", $sboxes[$index][$sindex]); } return $ret; } sub second_permutation { my $origin = shift; # bit selection table my @sp = (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); my $permuted = ''; my @unpermutation = split(//, $origin); foreach $d (@sp) { $permuted .= $unpermutation[$d-1]; # start from index 1 } return $permuted; } sub handle_func { my ($rp, $key) = @_; # expand $rp[n-1] from 32 bits to 48 bits my $expands = expand $rp; #print "EXP= $expands\n"; # XOR my $xor = subxor $key, $expands; #print "XOR= $xor\n"; my $ret = ''; # calcute sboxes my $sbs = cal_sboxes($xor); #print "SBS= $sbs\n"; $ret = second_permutation $sbs; #print "FP = $final\n"; return $ret; } sub final_permutation { my $origin = shift; # bit selection table my @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); my $permuted = ''; my @unpermutation = split(//, $origin); foreach $d (@fp) { $permuted .= $unpermutation[$d-1]; # start from index 1 } return $permuted; } # Step1: Create 16 subkeys, each of which is 48-bits long. $original_key = '133457799BBCDFF1'; print "KEY = ". $original_key. "\n"; my $keybits = tobit $original_key; print "K = ". $keybits. "\n"; $permutation = permuted $keybits; print "K+ = ". $permutation. "\n\n"; my @subkeys; $subkeys[0] = $permutation; my @permutations = split(//, $permutation); my @leftpart; my @rightpart; $leftpart[0] = join('', @permutations[0..27]); $rightpart[0] = join ('', @permutations[28..55]); print "C0: ". $leftpart[0]. "\n"; print "D0: ". $rightpart[0]. "\n\n"; # irations table for shift N my %iterations = (1 => 1, 2 => 1, 3 => 2, 4 => 2, 5 => 2, 6 => 2, 7 => 2, 8 => 2, 9 => 1, 10 => 2, 11 => 2, 12 => 2, 13 => 2, 14 => 2, 15 => 2, 16 => 1); for ($j=1; $j<=16; $j++) { $leftpart [$j] = iteration_handle $leftpart[$j-1], $iterations{$j}; $rightpart[$j] = iteration_handle $rightpart[$j-1], $iterations{$j}; #print "C". $j. " = ". $leftpart[$j]. "\n"; #print "D". $j. " = ". $rightpart[$j]. "\n\n"; $subkeys[$j] = generate_subkey($leftpart[$j]. $rightpart[$j]); print "K". $j. " = ". $subkeys[$j]. "\n"; } # Step 2: Encode each 64-bit block of data my $data = '0123456789ABCDEF'; print "DATA = ". tobit($data). "\n"; my $ip = initial_permutation(tobit($data)); print "IP = ". $ip. "\n"; # $ip = $lp[0] + $rp[0] my (@lp, @rp); $lp[0] = join '', (split(//, $ip))[0..31]; $rp[0] = join '', (split(//, $ip))[32..63]; print "L0 = ". $lp[0]. "\n"; print "R0 = ". $rp[0]. "\n"; for ($x=1; $x<=16; $x++) { $lp[$x] = $rp[$x-1]; #print "L". $x. " = ". $lp[$x]. "\n"; #print "R". ($x-1). " = ". $rp[$x-1]. "\n"; #print "K". $x. " = ". $subkeys[$x]. "\n"; #print "L". ($x-1). " = ". $lp[$x-1]. "\n"; $rp[$x] = subxor($lp[$x-1], handle_func($rp[$x-1], $subkeys[$x])); #print "R". $x. " = ". $rp[$x]. "\n"; } my $reverse = $rp[16]. $lp[16]; #print "R16L16 = ". $reverse. "\n"; my $final = final_permutation $reverse; $final = uc(tohex $final); print "FINAL = $final\n";
相关文章推荐
- 关于base64编码的原理及实现
- (4) 利用 Setter方式实现 【第一种方式】 依赖注入,编码剖析Spring依赖注入的原理
- H.264-AVC视频编码原理及实现(三)
- Linux开发中GSM 中文短信 SMS PDU编码原理及实现
- Golomb及指数哥伦布编码原理介绍及实现
- UTF-8编码的字符串拆分成单字、获取UTF-8字符串的字符个数的代码及原理(c++实现)
- Base64编码原理与实现
- 【知识笔记】Base64编码解码原理及手动实现(C#)
- H.264-AVC视频编码原理及实现(四)
- CRC校验原理和编码实现
- H.264-AVC视频编码原理及实现(四)
- 关于base64编码的原理和实现
- Golomb及指数哥伦布编码原理介绍及实现
- Spring 编码剖析@Resource注解的实现原理
- 关于base64编码的原理及实现
- 直方图均衡化原理和编码实现(C/C++)
- Atitit.Base64编码原理与实现设计
- H.264-AVC视频编码原理及实现(四)
- H.264-AVC视频编码原理及实现(三)
- H.264-AVC视频编码原理及实现(五)