1977年1月,美国政府颁布:采纳IBM公司设计的方案作为非机密数据的正式数据加密标准(Data Encryption Standard)。上周帮leojay看3DES算法,讲讲这个算法是如何进行的:)
先来讲讲DES加密:
首先,这个算法全程是按位运算的,每次计算64位的内容,也就是8个字节。密钥Key,为64位。
我们把内容经过一个初始置换,就是每位按如下表格进行位置交换:
然后把换好的东西经过16轮叫做DES的算法
每一轮这个算法是这样的:
我们先来生成子密钥:
把密钥Key的每个字节的最后一位扔掉,经过第1次缩小换位:
这样就从64位减少到56位了,把这56位分为左28位和右28位,分别称为Ci和Di。
将Ci和Di分别进行左移,左移的位数由第几论来决定:
把左移好的Ci和Di,通过第2次缩小换位:
这样生成了一组48位的子密钥Ki。
而刚刚左移好的Ci和Di将等待着下一轮的计算。
下面处理加密的内容:
把加密的内容分为左32位和右32位,分别称为Li和Ri,
Li先放着不管,先来看Ri,把这个Ri经过一个F函数的变化:
先通过放大换位表:
将这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位了。
然后通过置换函数P的变化:
将这32位的转换后的Ri与Li进行一次异或运算后放入Ri,
而将没有经过转换的那个Ri放入Li,这样就进行完一轮DES算法。
整个DES算法过程如下图所示:
连续进行16轮后,再进行一次逆置换:
这样就完成了一次DES加密过程,解密过程刚好与其相反:)
下面说说3DES:
共有两个密钥key1和key2:
加密过程:用key1加密,用key2解密再用key1加密
解密过程:用key1解密,用key2加密再用key1解密
下面是算法的实现程序:
先来讲讲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,
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
左: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
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
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, 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,
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,
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,
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;
}
#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;
}