密码学算法——DES密码算法
- DES密码算法
-
- 1.算法原理
- 2.结果展示
- 3.具体过程
-
- 3.1核心代码DESCipher类
- 3.1.1 set_keywords
- 3.1.2 set_plain
- 3.1.3 set_cipher
- 3.1.4 set_four()
- 3.1.5 child_key()
- 3.1.6 changetobin
- 3.1.7 IP_trans
- 3.1.8 NIP_trans
- 3.1.9 r0_to_r1 轮加密
- 3.1.10 CBC
- 3.1.11 Encryption_ECB()
- 3.1.12 Decryption_ECB()
- 3.3.13 Encryption_CBC()
- 3.1.14 Decryption_CBC()
- 3.1.15 加密函数
- 3.1.16 解密函数
- 3.2 其他函数
- 总结
DES密码算法
1.算法原理
DES 设计中使用了分组密码设计的两个原则:混淆(confusion)和扩散(diffusion),其目的是抗击敌手对密码系统的统计分析。
混淆是使密文的统计特性与密钥的取值之间的关系尽可能复杂化,以使密钥和明文以及密文之间的依赖性对密码分析者来说是无法利用的。
扩散的作用就是将每一位明文的影响尽可能迅速地作用到较多的输出密文位中,以便在大量的密文中消除明文的统计结构,并且使每一位密钥的影响尽可能迅速地扩展到较多的密文位中, 以防对密钥进行逐段破译。
DES 密码的加解密算法基本流程如下图所示。
加密算法常见的有ECB模式和CBC模式:
- ECB模式中,将数据按照8个字节一段进行DES加密或解密得到一段段的8个字节的密文或者明文,最后一段不足8个字节(一般补0或者F),按照需求补足8个字节进行计算(并行计算),之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。
- CBC模式中,实现机制使加密的各段数据之间有了联系。其实现的机理如下:
- 首先将数据按照8个字节一组进行分组得到D1D2…Dn(若数据不是8的整数倍,用指定的PADDING数据补位,本实验中补0)
- 第一组数据D1与初始化向量Ⅳ异或后的结果进行DES加密得到第一组密文C
- 第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C2
- 之后的数据以此类推,得到Cn
- 按顺序连为C1C2C3…Cn即为加密结果
比较CBC与ECB模式区别,如下图所示:
2.结果展示
本次算法没有使用MFC库,而是用Easy_X库手动画了一个,所以显得比较简陋,至于为什么呢,是因为我在汉字字符转换编码时用的GBK编码,做不了utf编码转换,而且我是用CLion写的,复制到VS时有些内容不兼容,所以干脆就用了Easy_X画了个界面出来。但作为DES算法核心的内容,应该也是通用的。
3.具体过程
本文主要是关于DES算法的具体实现过程,如果想要学习DES算法原理,推荐阅读DES加密算法这篇文章。
3.1核心代码DESCipher类
DESCipher.h
#include<iostream>
#include<sstream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<ctime>
#include<list>
#include<windows.h>
using namespace std;
class DESCipher{
private:
string keys;//八字节密钥
string keywords;//64位密钥
string plains;//明文
string plain_origin;//明文二进制
string cipher;//密文
string cipher_origin;//密文二进制
string hex=("0123456789ABCDEF");
string IV=("suixiang");
string IV_origin;//初始化向量二进制
char ckey[16][48];
int IP[64] = {
//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
};
int NIP[64] = {
//IP逆置换表
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
};
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 PC1[56] = {
//PC1换位表(64—>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 move[16] = {
//循环移位表
1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
};
int PC2[48] = {
//PC2换位表(56—>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 S[8][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}
},//S1
{
{
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,<