3DES算法

来源:互联网 发布:淘宝刷收藏有什么用 编辑:程序博客网 时间:2024/06/06 04:28




哈哈,来个加密算法普及讲座…… 


1977年1月,美国政府颁布:采纳IBM公司设计的方案作为非机密数据的正式数据加密标准(Data Encryption Standard)。上周帮leojay看3DES算法,讲讲这个算法是如何进行的:) 


先来讲讲DES加密: 
首先,这个算法全程是按位运算的,每次计算64位的内容,也就是8个字节。密钥Key,为64位。 
我们把内容经过一个初始置换,就是每位按如下表格进行位置交换: 


Initial Permutation 
58,50,12,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,


然后把换好的东西经过16轮叫做DES的算法 


每一轮这个算法是这样的: 


我们先来生成子密钥: 
把密钥Key的每个字节的最后一位扔掉,经过第1次缩小换位: 


Permuted Choice One 
左: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


这样就从64位减少到56位了,把这56位分为左28位和右28位,分别称为Ci和Di。 


将Ci和Di分别进行左移,左移的位数由第几论来决定: 


Schedule of Left Shifts: 
Round number: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 
Bits rotated:      1 1 2 2 2 2 2 2 1  2   2   2   2   2   2  1


把左移好的Ci和Di,通过第2次缩小换位: 


Permuted Choice Two 
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


这样生成了一组48位的子密钥Ki。 
而刚刚左移好的Ci和Di将等待着下一轮的计算。 


下面处理加密的内容: 
把加密的内容分为左32位和右32位,分别称为Li和Ri, 
Li先放着不管,先来看Ri,把这个Ri经过一个F函数的变化: 
先通过放大换位表: 


Expansion Permutation 
  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,


将这32位变成48位,然后和刚刚生成的子密钥Ki进行一次异或运算,再经过S-box这样一个选择运算将这48位变为32位。 


S-box的过程如下: 
将输入的48位分为8组,每组对应一个S-box表,每个表里有4行16列。 
这样每组有6位,取2、3、4、5位为列数,1、6位为行数,在所对应的表中寻找这个数字,将找到的数字转换为4位二进制数输出。这样一共8组,就将48位转换为32位了。 


Definition of DES S-boxes: 
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,




然后通过置换函数P的变化: 


Permutation Function 
  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位的转换后的Ri与Li进行一次异或运算后放入Ri, 
而将没有经过转换的那个Ri放入Li,这样就进行完一轮DES算法。 
整个DES算法过程如下图所示: 
 


连续进行16轮后,再进行一次逆置换: 


Inverse initial permutation: 
  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, 


这样就完成了一次DES加密过程,解密过程刚好与其相反:) 


下面说说3DES: 
共有两个密钥key1和key2: 
加密过程:用key1加密,用key2解密再用key1加密 
解密过程:用key1解密,用key2加密再用key1解密 


下面是算法的实现程序: 


//3DES加密解密算法 - SJW 
#include <iostream> 
#include <cstdlib> 
#include <cstring> 
#include <memory.h> 
using namespace std; 


typedef bool 
(*PSubKey)[16][48]; 


// 初始置换 
const static char Table_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 
}; 


// 末置换 
const static char Table_InverseIP[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 
}; 


// 扩展置换 
static const char Table_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 
}; 


// 密钥初始置换 
const static char Table_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 
}; 


// 左移运算 
const static char Table_Moveleft[16] = 

1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 
}; 


// 密钥压缩置换 
const static char Table_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 
}; 


// S盒 
const static char Box_S[8][4][16] = 

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


// P盒置换 
const static char Table_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 
}; 


static bool SubKey[2][16][48];//两个密钥的16轮子密钥 
static char Tmp[256], deskey[16]; 


#define ENCRYPT 0 
#define DECRYPT 1 


//通用置换函数 
void Transform(bool *Out, bool *In, const char *Table, int len) 

for(int i = 0; i < len; ++ i) 
Tmp[i] = In[ Table[i] - 1 ]; 
memcpy(Out, Tmp, len); 



//异或运算 
void Xor(bool *InA, const bool *InB, int len) 

for(int i = 0; i < len; ++ i) 
InA[i] ^= InB[i]; 



//循环左移 
void MoveLeft(bool *In, int len, int loop) 

memcpy(Tmp, In, loop); 
memcpy(In, In + loop, len - loop); 
memcpy(In + len - loop, Tmp, loop); 



//字节转换成位 
void Byte2Bit(bool *Out, const char *In, int bits) 

for(int i = 0; i < bits; ++ i) 
Out[i] = (In[i >> 3] >> (i & 7)) & 1; 



//位转换字节 
void Bit2Byte(char *Out, const bool *In, int bits) 

memset(Out, 0, bits >> 3); 
for(int i = 0; i < bits; ++ i) 
Out[i >> 3] |= In[i] << (i & 7); 



//S 盒置换 
void funS(bool Out[32], const bool In[48]) 

for(char i = 0, j, k; i < 8; ++ i, In += 6, Out += 4) 

j = (In[0] << 1) + In[5]; 
k = (In[1] << 3) + (In[2] << 2) + (In[3] << 1) + In[4]; 
Byte2Bit(Out, &Box_S[i][j][k], 4); 




//F 函数 
void funF(bool In[32], const bool Ki[48]) 

static bool MR[48]; 
Transform(MR, In, Table_E, 48); 
Xor(MR, Ki, 48); 
funS(In, MR); 
Transform(In, In, Table_P, 32); 



//生成子密钥 
void MakeSubKey(PSubKey pSubKey, const char Key[8]) 

static bool K[64], *KL = &K[0], *KR = &K[28]; 
Byte2Bit(K, Key, 64); 
Transform(K, K, Table_PC1, 56); 
for(int i = 0; i < 16; ++ i) 

MoveLeft(KL, 28, Table_Moveleft[i]); 
MoveLeft(KR, 28, Table_Moveleft[i]); 
Transform((*pSubKey)[i], K, Table_PC2, 48); 




//生成密钥 
void MakeKey(const char* Key, int len) 

memset(deskey, 0, 16); 
memcpy(deskey, Key, len > 16 ? 16 : len); 
MakeSubKey(&SubKey[1], &deskey[8]); 



//一重DES加/解密 
void DES(char Out[8], char In[8], const PSubKey pSubKey, bool Type) 

static bool M[64], tmp[32], *Li = &M[0], *Ri = &M[32]; 
Byte2Bit(M, In, 64); 
Transform(M, M, Table_IP, 64); 
if( Type == ENCRYPT ){ //加密 


for(int i = 0; i < 16; ++ i) 

memcpy(tmp, Ri, 32); 
funF(Ri, (*pSubKey)[i]); 
Xor(Ri, Li, 32); 
memcpy(Li, tmp, 32); 


else //解密 

for(int i = 15; i >= 0; -- i) 

memcpy(tmp, Li, 32); 
funF(Li, (*pSubKey)[i]); 
Xor(Li, Ri, 32); 
memcpy(Ri, tmp, 32); 


Transform(M, M, Table_InverseIP, 64); 
Bit2Byte(Out, M, 64); 



bool DoDES(char *Out, char *In, long datalen, const char *Key, int keylen, bool Type) 

if( !( Out && In && Key && (datalen=(datalen+7)&0xfffffff8) ) ) 
return false; 


MakeKey(Key, keylen); 
// 3次DES 加密:加(key0)-解(key1)-加(key0) 解密:解(key0)-加(key1)-解(key0) 
for(long i = 0, j = datalen >> 3; i < j; ++ i, Out += 8, In += 8) 

DES(Out, In,  &SubKey[0], Type); 
DES(Out, Out, &SubKey[1], !Type); 
DES(Out, Out, &SubKey[0], Type); 

return true; 



int main(int argc,char *argv[]) 

int i; 
char key[255]; 
char buf[255]; 
char str[255]; 
char key1[15]; 
char key2[8]; 


cout<<"Please input The string before encrypting: \n"; 
cin.getline(str, 255, '\n'); 
do 

cout<<"Please input Key1(8 chars): \n"; 
cin>>key1; 
} while (strlen(key1) != 8); //key1为8个字符 


cout<<"Please input Key2: \n"; 
cin>>key2; 


memset(key, 0, sizeof(key)); 
for (i = 0; i < 8; i ++) 

key[i] = key1[i]; 
key[i + 8] = key2[i]; 



memset(buf, 0, sizeof(buf)); 
strcpy(buf, str); 
cout<<"\nBefore encrypting\n"; 
cout<<buf<<endl; 


DoDES(buf, buf, sizeof(str), key, sizeof(key), ENCRYPT); 
cout<<"\nAfter encrypting\n"; 
cout<<buf<<endl; 


DoDES(buf, buf, sizeof(str), key, sizeof(key), DECRYPT); 
cout<<"\nAfter decrypting\n"; 
cout<<buf<<endl; 


return 0; 


0 0
原创粉丝点击