DES算法的C语言实现
本帖最后由 LegendSaber 于 2021-10-24 12:52 编辑曾经学习DES算法时候写过的一份C语言实现的DES加解密算法。现在提供给大家参考
首先,由于DES是在比特层面对输入进行加密的。所以,首先需要做到将输入的字符与其二进制形式的互相转换,这部分代码在CChar中实现
#include "CChar.h"
void CharToBit(char input[], char output[])
{
int i = 0, j = 0, k = 0;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
k = 7 - j;
output = (input >> k) & 0x1;
}
}
}
void BitToChar(char input[], char output[])
{
int i = 0, j = 0, k = 0;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
k = 7 - j;
output |= (input << k);
}
}
}
其次,为了完成DES加密需要用到的密钥以及置换表等等这部分内容在table.h中定义
#ifndef __MY_TABLE_
#define __MY_TABLE_
//存储程序所需要的表与密钥
//初始置换表IP
const char IP_Table = { 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};
//逆初始置换表IP^-1
const char IP_1_Table = { 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};
//扩展表E
const char E_Table = { 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};
//置换表P
const char P_Table = { 15, 6, 19, 20, 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};
//S盒
const char S =
{
//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
{{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}},
//S3
{{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}},
//S4
{{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}},
//S5
{{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}},
//S6
{{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}},
//S7
{{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}},
//S8
{{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}}
};
//置换选择1
int PC_1 = { 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};
//置换选择2
int PC_2 = { 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,46,43,48,38,55,
33,52,45,41,49,35,28,31};
//循环左移的位数
const char RoundLeft = {1, 1, 2, 2,
2, 2, 2, 2,
1, 2, 2, 2,
2, 2, 1, 1};
//加密密钥
const char cKey = {"12345678"};
char bKey = { 0 };
//IV向量
char cIV = {"IVVector"};
#endif
最后就是在主函数中对输入进行16轮的DES加密
#include <cstdio>
#include <cstring>
#include "table.h"
#include "CChar.h"
void DESAlgorithm(char cOrigData[]); //DES算法主体
//对左边32比特进行加密
void XOREncryptLeft(char cLeftChar[], char cRightChar[], int iIndex);
void InitBitKey(); //将密钥初始化为比特形式且进行置换
void EncryptByCBC(char cOrigData[], char cOrigData2[]); //采用CBC模式加密
void EncryptByCFB(char cOrigData[], char cOrigData2[]); //采用CFB模式加密
int main()
{
char cOrigData = {"1900Code"};
char cOrigData2 = {"I 1900"};
printf("加密前的数据: %s %s\n", cOrigData, cOrigData2);
EncryptByCBC(cOrigData, cOrigData2);
EncryptByCFB(cOrigData, cOrigData2);
getchar();
return 0;
}
void EncryptByCFB(char cOrigData[], char cOrigData2[])
{
InitBitKey();
DESAlgorithm(cIV);
for (int i = 0; i < 9; i++) cOrigData ^= cIV;
printf("CFB模式加密后的数据:%s ", cOrigData);
InitBitKey();
DESAlgorithm(cOrigData);
for (int i = 0; i < 9; i++) cOrigData2 ^= cOrigData;
printf("%s\n", cOrigData2);
for (int i = 0; i < 9; i++) cOrigData2 ^= cOrigData;
InitBitKey();
DESAlgorithm(cOrigData);
for (int i = 0; i < 9; i++) cOrigData ^= cIV;
printf("CFB模式解密的数据:%s %s\n", cOrigData, cOrigData2);
InitBitKey();
DESAlgorithm(cIV);
}
void EncryptByCBC(char cOrigData[], char cOrigData2[])
{
InitBitKey();
for (int i = 0; i < 9; i++) cOrigData ^= cIV;
DESAlgorithm(cOrigData);
InitBitKey();
for (int i = 0; i < 9; i++) cOrigData2 ^= cOrigData;
DESAlgorithm(cOrigData2);
printf("CBC模式加密后结果: %s %s\n", cOrigData, cOrigData2);
InitBitKey();
DESAlgorithm(cOrigData2);
for (int i = 0; i < 9; i++) cOrigData2 ^= cOrigData;
InitBitKey();
DESAlgorithm(cOrigData);
for (int i = 0; i < 9; i++) cOrigData ^= cIV;
printf("CBC模式解密后的数据: %s %s\n", cOrigData, cOrigData2);
}
void DESAlgorithm(char cOrigData[])
{
char cLeft = { 0 }, cRight = { 0 }, cOrigChar = { 0 };
char cTmp = 0, cOrigCpyChar = { 0 };
CharToBit(cOrigData, cOrigChar);
memset(cOrigCpyChar, 0, sizeof(cOrigCpyChar));
memcpy(cOrigCpyChar, cOrigChar, 64); //进行初始置换
for (int i = 0; i < 64; i++)
{
cOrigChar = cOrigCpyChar];
}
for (int i = 0; i < 32; i++)
{
cLeft = cOrigChar;
cRight = cOrigChar;
}
for (int i = 0; i < 16; i++) //进行16轮的加密
{
XOREncryptLeft(cLeft, cRight, i);
//除最后一轮,交换左右两边的比特
if (i < 15)
{
for (int j = 0; j < 32; j++)
{
cTmp = cLeft;
cLeft = cRight;
cRight = cTmp;
}
}
}
for (int i = 0; i < 32; i++)
{
cOrigChar = cLeft;
cOrigChar = cRight;
}
memset(cOrigCpyChar, 0, sizeof(cOrigCpyChar));
memcpy(cOrigCpyChar, cOrigChar, 64); //进行逆初始置换
for (int i = 0; i < 64; i++)
{
cOrigChar = cOrigCpyChar];
}
memset(cOrigData, 0, sizeof(cOrigData));
BitToChar(cOrigChar, cOrigData);
}
void XOREncryptLeft(char cLeftChar[], char cRightChar[], int iIndex)
{
char cExtendChar = { 0 };
int i = 0, moveNum = 0, col = 0, row = 0, j = 0, k = 0, l = 0;
char cLeftKey = { 0 }, cRightKey = { 0 };
char bEncryptKey = { 0 };
char bSData = { 0 };
char cSData = 0;
//进行扩展E置换
for (i = 0; i < 48; i++)
{
cExtendChar = cRightChar];
}
for (i = 0; i < 28; i++)
{
cLeftKey = bKey;
cRightKey = bKey;
}
moveNum = RoundLeft;
for (i = 0; i < 28 - moveNum; i++)
{
cLeftKey = cLeftKey;
cRightKey = cRightKey;
}
for (i = 28 - moveNum; i < 28; i++)
{
cLeftKey = 0;
cRightKey = 0;
}
for (i = 0; i < 28; i++)
{
bKey = cLeftKey;
bKey = cRightKey;
}
for (i = 0; i < 48; i++) bEncryptKey = bKey];
for (i = 0; i < 48; i++) cExtendChar |= bEncryptKey;
for (i = 0; i < 8; i++)
{
row = (cExtendChar - '0') * 2 + (cExtendChar - '0');
col = (cExtendChar - '0') * 8 + (cExtendChar - '0') * 4
+ (cExtendChar - '0') * 2 + (cExtendChar - '0');
cSData = S;
if (cSData >= 8)
{
bSData = 1;
cSData -= 8;
}
if (cSData >= 4)
{
bSData = 1;
cSData -= 4;
}
if (cSData >= 2)
{
bSData = 1;
cSData -= 2;
}
if (cSData == 1) bSData = 1;
}
for (i = 0; i < 32; i++) cLeftChar |= bSData;
}
void InitBitKey()
{
int i = 0, j = 0, k = 0;
char bCpyKey = { 0 };
for (i = 0; i < 7; i++)
{
for (j = 0; j < 8; j++)
{
k = 7 - j;
bKey = (cKey >> k) & 0x1;
}
}
memset(bCpyKey, 0, sizeof(bCpyKey));
memcpy(bCpyKey, bKey, 56);
for (i = 0; i < 56; i++)
{
bKey = bCpyKey];
}
}
可以看到最终的输出,程序成功对输入的字符进行DES的加密解密
Eaglecad 发表于 2021-10-24 12:51
感谢分享,要是再讲解下原理啥的更好
哦。。那是因为这种经典的密码算法原理网上真的特别特别多。。再写的话挺多余的。。。。 nanaqilin 发表于 2021-10-24 13:07
我早就不是学生了,我是社会人事,现在做项目都是用openssl
实际项目肯定是调包啊。。。谁能写的比那些人好啊。。。 感谢分享,要是再讲解下原理啥的更好 你这个挺厉害的,我都是用openssl来实现加解密 nanaqilin 发表于 2021-10-24 12:58
你这个挺厉害的,我都是用openssl来实现加解密
谁还不是被挂科的恐惧逼了一把。。。 LegendSaber 发表于 2021-10-24 13:00
谁还不是被挂科的恐惧逼了一把。。。
我早就不是学生了,我是社会人事,现在做项目都是用openssl DES,RSA 网络安全课上做过 LegendSaber 发表于 2021-10-24 13:00
谁还不是被挂科的恐惧逼了一把。。。
当年被密码学考试支配的恐惧{:1_909:} 有易语言的吗
页:
[1]
2