Data Encryption Standard(DES) 数据加密标准算法描述

一、算法介绍

DES算法是一种用56位密钥来加密64位数据的对称密钥算法。

DES算法的入口参数有三个:KeyDataMode。其中Key8个字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或被解密的数据;

ModeDES的工作方式,有两种:加密或解密。

 

二、实现步骤

1.变换密钥

A 8字节密钥转换为64字节字串,不足则补0(或自定义)

B 根据pc1进行变换成56字节

C 56字节密钥分为左右两部分C[0],D[0]

D 循环16(i1开始)

{

1)左移固定位数得到C[i]D[i];

2)C[i]D[i]pc2化简为48k[i];

}

 

2.数据处理

A 8字节数据转换为64字节字串,不足则补0(或自定义)

B 64字节数据转换为两部分L[0],R[0]

C 循环16(i1开始),用密钥加密数据

{

1)32位的R[i-1]exp扩展为48位的E[i-1];

2)异或E[i-1]K[i];

3)将异或结果分为86位长的部分B[8]

4)循环用S表替换(j1开始)

{

a)B[j]1位和第6位组合为M,作为S[j]的行号

b)B[j]25位组合为N,作为S[j]的列号

c)S[j][M][N]来取代B[j]

}

5)B[1]B[8]P组合得到p

6)R[i] = p xor L[i-1];

7)L[i] = R[i-1];

}

 

3.组合变换后的R[16]L[16]ip_1变换得到最后结果

 

三、注意事项

1. DES算法的解密过程是一样的,区别仅仅在于第一次迭代时用子密钥K15,第二次K14......,最后一次用K0,算法本身并没有任何变化.

2. DES密钥Key的使用、管理及密钥更换的过程中,应绝对避开DES 算法的应用误区,:绝对不能把Key的第8,16,24......64位作为有效数据位来对Key进行管理

 

四、实现源码

int  DES(

unsigned 
char   * bufferin,

unsigned 
char   * bufferout,

unsigned 
char   * key,

long  mode)

{

// 密钥变换为56字节(去掉校验位)

static  unsigned  char  pc1[ 56 =  {

56 48 40 32 24 16 8 ,

0 57 49 41 33 25 17 ,

9 1 58 50 42 34 26 ,

18 10 2 59 51 43 35 ,

62 54 46 38 30 22 14 ,

6 61 53 45 37 29 21 ,

13 5 60 52 44 36 28 ,

20 12 4 27 19 11 3  };

 

// 56字节变换为48 字节(数据压缩)

static  unsigned  char  pc2[ 48 =  {

13 16 10 23 0 4 ,

2 27 14 5 20 9 ,

22 18 11 3 25 7 ,

15 6 26 19 12 1 ,

40 51 30 36 46 54 ,

29 39 50 44 32 47 ,

43 48 38 55 33 52 ,

45 41 49 35 28 31  };

 

// 32字节变换为48字节(数据扩展)

static  unsigned  char  exp[ 48 =  {

31 0 1 2 3 4 ,

3 4 5 6 7 8 ,

7 8 9 10 11 12 ,

11 12 13 14 15 16 ,

15 16 17 18 19 20 ,

19 20 21 22 23 24 ,

23 24 25 26 27 28 ,

27 28 29 30 31 0  };

 

// 64位数据IP(Initial Permutation)变换表

static  unsigned  char  ip[ 64 =  {

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 ,

56 48 40 32 24 16 8 0 ,

58 50 42 34 26 18 10 2 ,

60 52 44 36 28 20 12 4 ,

62 54 46 38 30 22 14 6  };

 

// 数据逆置换(Final Permutation)

static  unsigned  char  ip_1[ 64 =  {

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 ,

32 0 40 8 48 16 56 24  };

 

// Permutation P

static  unsigned  char  pp[ 32 =  {

15 6 19 20 ,

28 11 27 16 ,

0 14 22 25 ,

4 17 30 9 ,

1 7 23 13 ,

31 26 2 8 ,

18 12 29 5 ,

21 10 3 24  };

 

/*  INITIALIZE THE TABLES  */

/*  Table - s1  */

static  unsigned  char  s1[ 4 ][ 16 =  {

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  };

 

/*  Table - s2  */

static  unsigned  char  s2[ 4 ][ 16 =  {

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  };

 

/*  Table - s3  */

static  unsigned  char  s3[ 4 ][ 16 =  {

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  };

 

/*  Table - s4  */

static  unsigned  char  s4[ 4 ][ 16 =  {

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  };

 

/*  Table - s5  */

static  unsigned  char  s5[ 4 ][ 16 =  {

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  };

 

/*  Table - s6  */

static  unsigned  char  s6[ 4 ][ 16 =  {

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  };

 

/*  Table - s7  */

static  unsigned  char  s7[ 4 ][ 16 =  {

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  };

 

/*  Table - s8  */

static  unsigned  char  s8[ 4 ][ 16 =  {

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  };

 

/*  密钥生成中的循环左移位的累计次数 */

static  unsigned  char  totrot[]  =  {

1 2 4 6 8 10 12 14 15 17 19 21 23 25 27 28  };

 

/* ---------------------------------------------- */

// long mode = 1;                                 // 模式,1:加密,2:解密

// unsigned char bufferin[9], bufferout[9];       // 明文,密文

/* ---------------------------------------------- */

long  i, j, k;

long  rotshift;                               // 密钥移位次数

// long keylen, buflen;                       // 密钥长度,明文长度

unsigned 
char  keybuf[ 65 ];                    // 密钥,密钥64字节缓冲区

unsigned 
char  keyreal[ 57 ], keys[ 17 ][ 49 ];     // 实际使用56字节密钥,48字节密钥数组

unsigned 
char  srcbuf[ 65 ], dstbuf[ 65 ];        // 明文,密文64字节缓冲区

unsigned 
char  L[ 17 ][ 33 ], R[ 17 ][ 33 ], LR[ 65 ], RL[ 65 ];     // 加密时临时数据左右两部分

unsigned 
char  E[ 17 ][ 49 ];                     // R数组的扩展数据

unsigned 
char  B[ 9 ][ 7 ], BB[ 33 ], P[ 33 ];        // E和K异或后的缓冲数组

unsigned 
char  C[ 17 ][ 29 ], D[ 17 ][ 29 ], CD[ 57 ];  // 56字节密钥的左右两部分

unsigned 
char  temp1, temp2, m, n, x;

 

// 1.变换密钥

// 密钥不足8字节则用0补足(或自定义)

// keylen = strlen((const char*)key);

// if(keylen<8)

//  memset(key+keylen, 0, (8-keylen));

// 将8字节密钥转换为64字节字串

for (i = 0 ;i < 8 ;i ++ )

{

=   * (key + i);

keybuf[
8 * i]  =  (j  /   128 %   2 ;

keybuf[
8 * i + 1 =  (j  /   64 %   2 ;

keybuf[
8 * i + 2 =  (j  /   32 %   2 ;

keybuf[
8 * i + 3 =  (j  /   16 %   2 ;

keybuf[
8 * i + 4 =  (j  /   8 %   2 ;

keybuf[
8 * i + 5 =  (j  /   4 %   2 ;

keybuf[
8 * i + 6 =  (j  /   2 %   2 ;

keybuf[
8 * i + 7 =  (j  /   1 %   2 ;

}

 

// 根据pc1进行变换成56字节,去掉奇偶校验位

for (i = 0 ;i < 56 ;i ++ )

{

keyreal[i] 
=  keybuf[pc1[i]];

}

 

// 将56字节密钥分为左右两部分C[0],D[0]

for (i = 0 ;i < 28 ;i ++ )

{

C[
0 ][i]  =  keyreal[i];

D[
0 ][i]  =  keyreal[i + 28 ];

}

 

// 循环16次(i从1开始)

for (i = 1 ;i < 17 ;i ++ )

{

// 根据加密或解密确定密钥顺序

if (mode)     // 加密

rotshift 
=  totrot[i - 1 ];

else          // 解密

rotshift 
=  totrot[ 16 - i];

 

// 1)左移固定位数得到C[i]和D[i];

for (j = 0 ;j < 28 ;j ++ )

{

C[i][j] 
=  C[ 0 ][j];

D[i][j] 
=  D[ 0 ][j];

}

for (j = 0 ;j < rotshift;j ++ )

{

temp1 
=  C[i][ 0 ];

temp2 
=  D[i][ 0 ];

for (k = 0 ;k < 27 ;k ++ )

{

C[i][k] 
=  C[i][k + 1 ];

D[i][k] 
=  D[i][k + 1 ];

}

C[i][
27 =  temp1;

D[i][
27 =  temp2;

}

 

// 2)将C[i]D[i]用pc2化简为48位k[i];

for (j = 0 ;j < 28 ;j ++ )

{

CD[j] 
=  C[i][j];

CD[j
+ 28 =  D[i][j];

}

for (j = 0 ;j < 48 ;j ++ )

{

keys[i][j] 
=  CD[pc2[j]];

}

}

 

// 2.数据处理

// 若明文不足8字节则补0(或自定义)

// buflen = strlen((const char*)bufferin);

// if(buflen<8)

//  memset(bufferin+buflen, 0, (8-buflen));

// 将8字节数据转换为64字节字串

for (i = 0 ;i < 8 ;i ++ )

{

=   * (bufferin + i);

srcbuf[i
* 8 =  (j  /   128 %   2 ;

srcbuf[i
* 8 + 1 =  (j  /   64 %   2 ;

srcbuf[i
* 8 + 2 =  (j  /   32 %   2 ;

srcbuf[i
* 8 + 3 =  (j  /   16 %   2 ;

srcbuf[i
* 8 + 4 =  (j  /   8 %   2 ;

srcbuf[i
* 8 + 5 =  (j  /   4 %   2 ;

srcbuf[i
* 8 + 6 =  (j  /   2 %   2 ;

srcbuf[i
* 8 + 7 =  (j  /   1 %   2 ;

}

 

// 将srcbuf按ip进行变换

for (i = 0 ;i < 64 ;i ++ )

LR[i] 
=  srcbuf[ip[i]];

 

// 将64字节数据转换为两部分L[0],R[0]

for (i = 0 ;i < 32 ;i ++ )

{

L[
0 ][i]  =  LR[i];

R[
0 ][i]  =  LR[i + 32 ];

}

 

// 循环16次(i从1开始),用密钥加密数据

for (i = 1 ;i < 17 ;i ++ )

{

// 1)将32位的R[i-1]按exp扩展为48位的E[i-1];

for (j = 0 ;j < 48 ;j ++ )

{

E[i
- 1 ][j]  =  R[i - 1 ][exp[j]];

}

 

// 2)异或E[i-1]和K[i];

for (j = 0 ;j < 48 ;j ++ )

{

keys[i][j] 
=  keys[i][j]  ^  E[i - 1 ][j];

}

 

// 3)将异或结果分为8个6位长的部分B[8]

for (j = 0 ;j < 8 ;j ++ )

{

B[j][
0 =  keys[i][j * 6 ];

B[j][
1 =  keys[i][j * 6 + 1 ];

B[j][
2 =  keys[i][j * 6 + 2 ];

B[j][
3 =  keys[i][j * 6 + 3 ];

B[j][
4 =  keys[i][j * 6 + 4 ];

B[j][
5 =  keys[i][j * 6 + 5 ];

}

 

// 4)循环用S表替换(j从1开始)

for (j = 0 ;j < 8 ;j ++ )

{

// a)B[j]第1位和第6位组合为M,作为S[j]的行号

=   2   *  B[j][ 0 +  B[j][ 5 ];

 

// b)B[j]第2到5位组合为N,作为S[j]的列号

=   2   *  ( 2   *  ( 2   *  B[j][ 1 +  B[j][ 2 ])  +  B[j][ 3 ])  +  B[j][ 4 ];

 

// c)用S[j][M][N]来取代B[j]

switch (j)

{

case   0 :

=  s1[m][n];

break ;

case   1 :

=  s2[m][n];

break ;

case   2 :

=  s3[m][n];

break ;

case   3 :

=  s4[m][n];

break ;

case   4 :

=  s5[m][n];

break ;

case   5 :

=  s6[m][n];

break ;

case   6 :

=  s7[m][n];

break ;

case   7 :

=  s8[m][n];

break ;

}

BB[j
* 4 =  (x  /   8 %   2 ;

BB[j
* 4   +   1 =  (x  /   4 %   2 ;

BB[j
* 4   +   2 =  (x  /   2 %   2 ;

BB[j
* 4   +   3 =  (x  /   1 %   2 ;

}

 

// 5)将B[1]到B[8]按P组合得到p

for (j = 0 ;j < 32 ;j ++ )

{

P[j] 
=  BB[pp[j]];

}

 

// 6)R[i] = p xor L[i-1];L[i] = R[i-1];

for (j = 0 ;j < 32 ;j ++ )

{

R[i][j] 
=  P[j]  ^  L[i - 1 ][j];

L[i][j] 
=  R[i - 1 ][j];

}

}

 

// 3.组合变换后的R[16]L[16]按ip_1变换得到最后结果

for (i = 0 ;i < 32 ;i ++ )

{

RL[i] 
=  R[ 16 ][i];

RL[i
+ 32 =  L[ 16 ][i];

}

for (i = 0 ;i < 64 ;i ++ )

{

dstbuf[i] 
=  RL[ip_1[i]];

}

 

// 将64字节数据转换为8字节

for  (i  =   0 ; i  <   8 ; i ++ )

{

* (bufferout  +  i)  =   0x00 ;

for  (k  =   0 ; k  <   7 ; k ++ )

* (bufferout  +  i)  =  (( * (bufferout  +  i))  +  dstbuf[ 8 * i + k])  *   2 ;

* (bufferout  +  i)  =   * (bufferout  +  i)  +  dstbuf[ 8 * i + 7 ];

}

return   0 ;

你可能感兴趣的:(Data Encryption Standard(DES) 数据加密标准算法描述)