您的位置:首页 > 其它

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 实现如下:

#!/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";
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: