DES加解密時產(chǎn)生的子密鑰
DES算法共需要進(jìn)行16輪迭代運(yùn)算,每輪迭代運(yùn)算使用一個子密鑰,共需要16個子密鑰。子密鑰是從用戶輸入的初始密鑰產(chǎn)生的,用戶輸入的初始密鑰K為64位,其中有8位用于奇偶校驗,分別位于第8,16,24,32,40,48,56,64位。奇偶校驗位用于檢查密鑰K在產(chǎn)生和分配以及存儲過程中可能發(fā)生的錯誤,這樣DES的密鑰實際上只有56位。
加密過程生成的子密鑰
首先密鑰經(jīng)過PC-1表置換后
Permuted
Choice 1 (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
將變換后的密鑰分為兩個部分,開始的28位稱為C[0],最后的28位稱為D[0]。
C[i-1],D[i-1]作為下一輪i的輸入(把C[i-1]復(fù)制給C[i],將D[i-1]復(fù)制給D[i]),之后同時將C[i]、D[i]左移1位或2位,根據(jù)輪數(shù)值決定左移的位數(shù)。
左移位數(shù): 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
由C[i]、D[i]合成CD[i][i]
將CD[i] [i]作為一個整體按下表(PC-2)變換,得到48位的K[i]
Permuted
Choice 2 (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
解密過程生成的子密鑰
跟加密時產(chǎn)生子密鑰的算法基本一樣,只是每輪變成想右位移1或2位
右移位數(shù): 0, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
加解密過程
一、取得64位的數(shù)據(jù),如果數(shù)據(jù)長度不足64位,應(yīng)該將其擴(kuò)展為64位
將64位數(shù)據(jù)按下表變換(IP)
Initial Permutation (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
將變換后的數(shù)據(jù)分為兩部分,開始的32位稱為L[0],最后的32位稱為R[0]。用16個子密鑰加密數(shù)據(jù),初始i=1。每輪迭代都利用上一輪的L[i-1],R[i-1]。
L[i] = R[i-1];R[i] = Li-1⊕F(Ri-1,Ki);
二、F(Ri-1,Ki)實現(xiàn)過程:
1、將32位的R[I-1]按下表(E)擴(kuò)展為48位的E[i-1]
Expansion (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
2、異或E[i-1]和K[i],即E[i-1] XOR K[i]
3、S盒替換:將異或后的結(jié)果分為8個6位長的部分,每部分成為S盒的輸入,跟有8個輸入,對應(yīng)8個S盒。如Bi=b1b2b3b4b5b6,將x=b1b6作為行號,y=b2b3b4b5作為列好,在S[i]中查找第x行第y列的值c=S[i][x][y]。將c轉(zhuǎn)化為4為2進(jìn)制,代替原來的Bi。經(jīng)過8個替換后,產(chǎn)生32位比特串。
4、P盒替換:將S盒產(chǎn)生的32位比特串經(jīng)過P盒置換,輸出結(jié)果就為F(Ri-1, Ki);
Permutation 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
5、與L[i-1]:置換將F(Ri-1, Ki)⊕Li-1得出Ri
三、逆置換IP-1
64位的明文經(jīng)過IP置換、16輪迭代運(yùn)算、逆初始置換IP-1后,得到的結(jié)果極為DES加密的密文輸出。
Final Permutation (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
解密過程跟加密一樣,只是加密時第i輪跟第i個子密鑰異或,而解密時16子密鑰被倒過來異或,只要在產(chǎn)生子密鑰的過程中做文章就可以實現(xiàn)加解密過程一字不差。
以下是S盒:
S盒
Substitution
Box
S[1]
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
S[2]
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
S[3]
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
S[4]
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
S[5]
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
S[6]
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
S[7]
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
S[8]
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int SubKey[17][48];
int C[17][28], D[17][28], CD[17][56];
int LS[2][16] =
{
{1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1},
{0, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1}
};
int L[17][32], R[17][32];
int en[64];
int PC1[56] =
{
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};
int PC2[48] =
{
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};
int IP[64] =
{
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};
int E[48] =
{
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};
int S[8][4][16] =
{
//S[1]
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,
//S[2]
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,
//S[3]
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,
//S[4]
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,
//S[5]
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,
//S[6]
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,
//S[7]
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,
//S[8]
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
};
int P[32] =
{
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};
int RIP[64] =
{
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,
};
void LR(int * in, int *out, int ls)//將in左移ls位存到out
{
int i;
for (i = 0; i < ls; i++)
out[28 - ls + i] = in[i];
for (i = ls; i < 28; i++)
out[i-ls] = in[i];
}
void RR(int * in, int * out, int ls)//將in右移ls位存到out
{
int i;
for (i = 0; i < 28 - ls; i++)
out[i+ls] = in[i];
for (i = 28 - ls; i < 28; i++)
out[i - (28 - ls)] = in[i];
}
//Key是64位密鑰,f為0表示該過程是產(chǎn)生加密的子密鑰,f為1表示該過程是產(chǎn)生解密的子密鑰
//因為加密過程產(chǎn)生的16個子密鑰,在解密時時倒過來的。之所以會這樣主要是加密過程是左移操作,解密是右移操作
void CreateSubKey(int * Key, int f)
{
int i, j;
for (i = 0; i < 56; i++)
CD[0][i] = Key[PC1[i]-1];
for (i = 0; i < 28; i++)
{
C[0][i] = CD[0][i];
//printf("%d", C[0][i]);
}//printf("--");
for (i = 28; i < 56; i++)
{
D[0][i-28] = CD[0][i];
//printf("%d", D[0][i-28]);
}//printf("\n");
for (i = 1; i <= 16; i++)
{
if (f == 0)
{
LR(C[i-1], C[i], LS[f][i-1]);
LR(D[i-1], D[i], LS[f][i-1]);
}
else
{
RR(C[i-1], C[i], LS[f][i-1]);
RR(D[i-1], D[i], LS[f][i-1]);
}
// printf("ls%d:", LS[f][i-1]);for (j = 0; j < 28; j++)printf("%d", C[i][j]);
// printf("--");for (j = 0; j < 28; j++)printf("%d", D[i][j]);printf("\n");
for (j = 0; j < 28; j++)
{
CD[i][j] = C[i][j];
CD[i][j+28] = D[i][j];
}
for (j = 0; j < 48; j++)
{
SubKey[i][j] = CD[i][PC2[j]-1];
}
// printf("i=%d:", i);
// for (j = 0; j < 48; j++)
// {
// printf("%d", SubKey[i][j]);
// }printf("\n");
}
}
void ip(int *mw)//IP置換,64為明文經(jīng)過IP置換產(chǎn)生L0和R0
{
int i;
for (i = 0; i < 64; i++)
{
if (i < 32)
L[0][i] = mw[IP[i]-1];
else
R[0][i-32] = mw[IP[i]-1];
}
}
void ebox(int * in, int *out)//e盒,in為輸入,結(jié)果為out
{
int i;
for (i = 0; i < 48; i++)
out[i] = in[E[i]-1];
}
void xorK(int * key, int * in)//將in與key異或
{
int i;
for (i = 0; i < 48; i++)
in[i] = in[i] ^ key[i];
}
void sbox(int * in, int * out)//s盒,in為輸入,結(jié)果為out
{
int i, x, y, z;
for (i = 0; i < 8; i++)
{
x = (in[0] << 1) + in[5];
y = (in[1] << 3) + (in[2] << 2) + (in[3] << 1) + in[4];
z = S[i][x][y];
// out[0] = z & 1;
// out[1] = (z >> 1) & 1;
// out[2] = (z >> 2) & 1;
// out[3] = (z >> 3) & 1;
out[0] = (z >> 3) & 1;
out[1] = (z >> 2) & 1;
out[2] = (z >> 1) & 1;
out[3] = z & 1;
in += 6, out += 4;
}
}
void pbox(int * in, int * out)//P盒置換in為輸入,結(jié)果存于out
{
int i;
for (i = 0; i < 32; i++)
out[i] = in[P[i]-1];
}
void fun(int * ri, int * ki, int * out)//將R[i-1],Key[i]作為輸入進(jìn)行F(Ri-1,Ki)存于out
{
int tmp[48], res[32];
ebox(ri, tmp);//將Ri進(jìn)行E盒置換存于tmp
xorK(ki, tmp);//將tmp與子密鑰異或仍存于tmp
sbox(tmp, res);//將tmp進(jìn)行S盒置換存于res
pbox(res, out);//將res進(jìn)行P盒置換存于out
}
void xorLi(int * li, int * in, int * out)//li為Li-1,將F(Ri-1,Ki)的結(jié)果作為in,out = Li-1 ^ F(Ri-1, Ki);
{
int i;
for (i = 0; i < 32; i++)
out[i] = in[i] ^ li[i];
}
void Rip(int * l, int * r, int * out)//逆置換IP-1,將L16跟R16作為輸入,結(jié)果存于out中
{
int lr[64], i;
for (i = 0; i < 32; i++)
lr[i] = r[i];
for (i = 32; i < 64; i++)
lr[i] = l[i-32];
for (i = 0; i < 64; i++)
out[i] = lr[RIP[i]-1];
}
int Binary_To_Decimal(int *bit, int len)//將一個8位2進(jìn)制轉(zhuǎn)為一個10進(jìn)制數(shù)
{
int sum = 0, i;
for (i = 0; i < len; i++)
{
sum = sum * 2 + bit[i];
}
return sum;
}
void asc(int * w, int len, char * as)//將64bit轉(zhuǎn)化成一字符串
{
int *p = w;
int i, j;
for (i = 0, j = 0; i < 64; i += 8, p += 8, j++)
{
as[j] = Binary_To_Decimal(p, 8);
}
as[j] = 0;
puts(as);
}
void OX(int * w, int len, char * ans)//將64bit轉(zhuǎn)化成16進(jìn)制
{
int i, j, k, a;
int * p = w;
for (i = 0, k = 0; i < len; k++, i = j)
{
j = i + 4;
if (j > len)
{
j = len;
}
a = Binary_To_Decimal(p + i, j - i);
if (a <= 9)
{
ans[k] = a + '0';
}
else
{
ans[k] = a - 10 + 'A';
}
}
ans[k] = 0;
puts(ans);
}
int str_to_bit(char * in, int * out)//將字符串in轉(zhuǎn)化為二進(jìn)制數(shù)組,返回二進(jìn)制數(shù)組的長度
{
char tmp[1000];
int i, j, len, k;
strcpy(tmp, in);
len = strlen(tmp);
if (len % 8 != 0)
{
j = len / 8 * 8+ 8;//printf("%d ", j);
for (; len < j; len++)
tmp[len] = ' ';
tmp[len] = 0;
}
//printf("%s_\n", tmp);
for (i = 0, j = 0; tmp[i]; i++)
{
for (k = 7; k >= 0; k--, j++)
{
out[j] = (tmp[i] >> k) & 1;
}
}
return j;
}
void cry(int * mw, int * ans)//加解密,結(jié)果為ans
{
int tmp[32];
int i, j;
char ox[100];
ip(mw);
for (i = 1; i <= 16; i++)
{
for (j = 0; j < 32; j++)
L[i][j] = R[i-1][j];
fun(R[i-1], SubKey[i], tmp);
xorLi(L[i-1], tmp, R[i]);
}
Rip(L[16], R[16], ans);
for (printf("ans:\n"), i = 0; i < 64; i++)
{
if (i % 8 == 0)printf("\n");
printf("%d", ans[i]);
}printf("\n");
asc(ans, 64, ox);
//OX(en, 64, ox);
}
void crying(int * mw, int * ans, int len)//加解密,結(jié)果為ans
{
int i;
char ox[100];
for (i = 0; i < len; i += 64)
{
cry(mw, ans);
mw += 64, ans += 64;
}
}
/*
learning
computer
*/
int main()
{
int key[64] =
{
1,1,0,0,0,1,1,0,
1,1,0,1,1,1,1,0,
1,1,0,1,1,0,1,1,
1,1,1,0,0,0,0,1,
1,1,1,0,1,0,1,1,
1,1,1,0,1,0,0,0,
1,1,0,0,1,0,1,0,
1,1,1,0,0,1,0,0};
int mw[1000] =
{
0,1,1,0,1,1,0,0,
0,1,1,0,0,1,0,1,
0,1,1,0,0,0,0,1,
0,1,1,1,0,0,1,0,
0,1,1,0,1,1,1,0,
0,1,1,0,1,0,0,1,
0,1,1,0,1,1,1,0,
0,1,1,0,0,1,1,1
};
int ans[1000], len;
char strm[1000], strk[10];
while (scanf("%s%s", strm, strk) - EOF)
{
len = str_to_bit(strm, mw);
CreateSubKey(key, 0);
crying(mw, ans, len);
CreateSubKey(key, 1);
crying(ans, ans, len);
//puts(ans);
}
system("pause");
}
/*
learinglearingleari
computer
*/