You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
7.0 KiB
C++

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#pragma execution_character_set("utf-8")
//DES算法相应描述
/*
如何实现DES算法
原文Matthew Fischer
DES( Data Encryption Standard)算法于1977年得到美国政府的正式许可是一种用56位密钥来加密64位数据的方法。DES算法以被应用于许多需要安全加密的场合。UNIX的密码算法就是以DES算法为基础的。下面是关于如何实现DES算法的语言性描述如果您要其源代码可以到Http//Assassin.yeah.net下载后者您有任何问题也可以写信给我Assassin@ynmail.com
1-1、变换密钥
取得64位的密钥每个第8位作为奇偶校验位。
1-2、变换密钥。
1-2-1、舍弃64位密钥中的奇偶校验位根据下表PC-1进行密钥变换得到56位的密钥在变换中奇偶校验位以被舍弃。
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
1-2-2、将变换后的密钥分为两个部分开始的28位称为C[0]最后的28位称为D[0]。
1-2-3、生成16个子密钥初始I=1。
1-2-3-1、同时将C[I]、D[I]左移1位或2位根据I值决定左移的位数。见下表
I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
左移位数: 1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1
1-2-3-2、将C[I]D[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
1-2-3-3、从1-2-3-1处循环执行直到K[16]被计算完成。
2、处理64位的数据
2-1、取得64位的数据如果数据长度不足64位应该将其扩展为64位例如补零
2-2、将64位数据按下表变换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
2-3、将变换后的数据分为两部分开始的32位称为L[0]最后的32位称为R[0]。
2-4、用16个子密钥加密数据初始I=1。
2-4-1、将32位的R[I-1]按下表E扩展为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-4-2、异或E[I-1]和K[I]即E[I-1] XOR K[I]
2-4-3、将异或后的结果分为8个6位长的部分第1位到第6位称为B[1]第7位到第12位称为B[2]依此类推第43位到第48位称为B[8]。
2-4-4、按S表变换所有的B[J]初始J=1。所有在S表的值都被当作4位长度处理。
2-4-4-1、将B[J]的第1位和第6位组合为一个2位长度的变量MM作为在S[J]中的行号。
2-4-4-2、将B[J]的第2位到第5位组合作为一个4位长度的变量NN作为在S[J]中的列号。
2-4-4-3、用S[J][M][N]来取代B[J]。
Substitution Box 1 (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
2-4-4-4、从2-4-4-1处循环执行直到B[8]被替代完成。
2-4-4-5、将B[1]到B[8]组合按下表P变换得到P。
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
2-4-6、异或P和L[I-1]结果放在R[I]即R[I]=P XOR L[I-1]。
2-4-7、L[I]=R[I-1]
2-4-8、从2-4-1处开始循环执行直到K[16]被变换完成。
2-4-5、组合变换后的R[16]L[16]注意R作为开始的32位按下表IP-1变换得到最后的结果。
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
*/
#ifndef _ALGORITHM_DES_H
#define _ALGORITHM_DES_H
#include <string>
//加密解密
typedef enum
{
DT_ENCRYPT = 0, //加密
DT_DECRYPT //解密
}DES_TYPE;
//DES算法的模式
typedef enum
{
DM_ECB = 0, //ECB模式
DM_CBC //CBC模式
}DES_MODE;
//Pad填充的模式
typedef enum
{
PT_ISO_1 = 0, //ISO_1填充数据长度不足8比特的倍数以0x00补足如果为8比特的倍数补8个0x00
PT_ISO_2, //ISO_2填充数据长度不足8比特的倍数以0x80,0x00..补足如果为8比特的倍数补0x80,0x00..0x00
PT_PKCS_7 //PKCS7填充数据长度除8余数为n,以(8-n)补足为8的倍数
}PAD_TYPE;
class DES
{
public:
//DES();
DES(DES_MODE mode = DM_CBC, PAD_TYPE pad_type = PT_ISO_1);
virtual ~DES();
typedef bool (*PSubKey)[16][48];
bool Encrypt(char *in, unsigned int inLen, const char *key, unsigned char keyLen, char *out);
bool Decrypt(char *in, unsigned int inLen, const char *key, unsigned char keyLen, char *out);
/*******************************************************************
函 数 名 称: RunPad
功 能 描 述: 根据协议对加密前的数据进行填充
参 数 说 明: bType :类型PAD类型
In :数据串指针
Out :填充输出串指针
datalen :数据的长度
padlen :(in,out)输出buffer的长度填充后的长度
返回值 说明: bool :是否填充成功
*******************************************************************/
bool RunPad(const char* in,unsigned int inLen,char* out,unsigned int &padlen);
bool RunPad(std::string &in);
/*******************************************************************
函 数 名 称: RunDes
功 能 描 述: 执行DES算法对文本加解密
参 数 说 明: bType :类型加密ENCRYPT解密DECRYPT
bMode :模式ECB,CBC
In :待加密串指针
Out :待输出串指针
datalen :待加密串的长度同时Out的缓冲区大小应大于或者等于datalen
Key :密钥(可为8位,16位,24位)支持3密钥
keylen :密钥长度多出24位部分将被自动裁减
返回值 说明: bool :是否加密成功
*******************************************************************/
bool RunDes(DES_TYPE desType, const char* in,unsigned int inLen, const char* key,const unsigned char keyLen, char* out);
private:
//计算并填充子密钥到SubKey数据中
void SetSubKey(PSubKey pSubKey, const char Key[8]);
//DES单元运算
void Des(char Out[8], const char In[8], const PSubKey pSubKey, DES_TYPE desType);
private:
DES_MODE m_mode;
PAD_TYPE m_pad_type;
};
/*
std::string des_encrypt(std::string in, std::string key);
std::string des_decrypt(std::string in, std::string key);
*/
#endif