有关DES的加密流程详解des算法加密流程_lkw23333的博客-CSDN博客_des密钥加密过程
此处只做简略介绍,或者看代码注释
简要流程
(1)输入8位字符明文以及设定8位字符的加密密钥;
(2)将字符串的明文转换为64位的二进制表示;密钥也转换为64位二进制表示;
(3)对64位的密钥进行密钥扩展生16个48位的子密钥;
(4)对64位明文进行ip置换,分成L与R两组各32位;
(5)R经过轮函数F后与L进行异或操作生成新的R,新的L由之前的R代替;
(6)重复上述步骤16次后再进行一次IP逆置换即可得到64位密文;
(7)将加密后64位密文转为16位16进制输出方便显示;
(8)解密与加密步骤相同只是部分操作相反;
总结
整个des算法涉及到的那种晦涩的理论知识并不多所以理解起来很容易。各种操作通过代码实现起来都很ez,理解起来也很ez。就是过程稍微有点繁杂,而且在写代码的过程中不能调试,只能写完了调,这就导致找bug有点痛苦。不过这个过程是有收获的。
#include<stdio.h>
#include<string.h>
int IP_Table[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
};
// IP-1置换表
int IPR_Table[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
};
// E扩展表
int E_Table[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
};
// PC1置换表
int PC1_Table[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
};
// pc2表
int PC2_Table[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 LOOP_Table[16]={
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
// S盒
int S_Box[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, 0, 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, 0, 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置换表
int P_Table[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
};
//执行des加密
void doDes(int *mingBit, char *ciphertext, int *keyBit);
//拷贝数组
void bitCopy(int *input, int *output, int length);
//做ip置换和逆置换
void doIp(int *array, int length, int *table);
//异或运算
void doXor(int *output, int *input, int length);
//E盒扩展
void doE(int *R, int *eTemp, int length);
//S盒压缩
void doS(int *R, int *eTemp);
//P盒置换
void doP(int *array);
//两个PC表的置换
void doPc_1(int *keyBit, int *output);
void doPc_2(int *iKey, int *C, int *D);
//循环左移动
void lMove(int *C, int *D, int moveBit);
//子密钥生成
void setIkey(int *keyBit, int iKey[16][48]);
//轮函数F
void lunF(int *R, int *iKey);
//字符转位
void charToBit(char *input , int *output, int length);
//位转字符
void bitToChar(int *input, char *output, int length);
//des解密函数
void deDes(char *mingWen,char *ciphertext, char *keyBit);
//ip置换根据table确定
void doIp(int *array, int length, int *table){
int temp[64] = {0};
bitCopy(array, temp, 64);
for(int i = 0; i < length; ++i){
array[i] = temp[table[i] - 1];
}
}
//整个程序的异或运算执行函数
void doXor(int *output, int *input, int length){
for(int i=0; i<length; ++i){
output[i] = output[i] ^ input[i];
}
}
//E盒扩展 32——>48,方便后面与子密钥异或
void doE(int *R, int *eTemp, int length)
{
for(int i = 0; i < length; ++i){
eTemp[i] = R[E_Table[i] - 1];
}
}
//S盒压缩 48——>32
void doS(int *R, int *eTemp)
{
int i, x, y;
//注意指针的移动步数
for(i = 0; i < 8; ++i, eTemp += 6, R += 4){
x = eTemp[0]*2 + eTemp[5];
y = eTemp[1]*8 + eTemp[2]*4 + eTemp[3]*2 + eTemp[4];
// printf("%d %d\n", x, y);
char T = (char)S_Box[i][x][y];
charToBit(&T, R, 4);
}
}
//简单的P盒置换
void doP(int *array)
{
int temp[32] = {0};
bitCopy(array, temp, 32);
for(int i = 0; i < 32; ++i){
array[i] = temp[P_Table[i] - 1];
}
}
//密钥的pc_1表置换,剔除奇偶校验位
void doPc_1(int *keyBit, int *output){
for(int i = 0; i < 56; ++i){
output[i] = keyBit[PC1_Table[i] - 1];
}
}
//合并c,d两部分进行pc_2的置换 56——>48
void doPc_2(int *iKey, int *C, int *D){
int temp[56]={0};
bitCopy(C, temp, 28);
bitCopy(D, temp+28, 28);
for(int i=0; i<48; ++i){
iKey[i] = temp[PC2_Table[i]-1];
}
}
//密钥循环左移
void lMove(int *C, int *D, int moveBit){
int temp[28] = {0};
bitCopy(C, temp, 28);
bitCopy(temp+moveBit, C, 28-moveBit);
bitCopy(temp, C+28-moveBit, moveBit);
bitCopy(D, temp, 28);
bitCopy(temp+moveBit, D, 28-moveBit);
bitCopy(temp, D+28-moveBit, moveBit);
}
//生成子密钥
void setIkey(int *keyBit, int iKey[16][48])
{
int temp[56]={0};
int C[28];
int D[28];
doPc_1(keyBit, temp);//先做pc1剔除校验位,在拆成两组
bitCopy(temp, C, 28);
bitCopy(temp+28, D, 28);
for(int i=0; i<16; ++i){
lMove(C, D, LOOP_Table[i]);
doPc_2(iKey[i], C, D);
}
}
void lunF(int *R, int *iKey)
{
int eTemp[48]={0};
//E盒扩展
doE(R, eTemp, 48);
//和密钥异或
doXor(eTemp, iKey, 48);
//S盒压缩
doS(R, eTemp);
//P盒压缩
doP(R);
}
//字符转换为位方便加密
void charToBit(char *input , int *output, int length)
{
int i=0;
for(i=0;i < length;i++)
{
output[i]=(input[i/8]>>(i%8))&1;
}
}
//位转字符,复原
void bitToChar(int *input, char *output, int length)
{
int i;
for(i=0;i<(length/8);i++)
{
output[i]=0;
}
for(i=0;i<length;i++)
{
output[i/8]|= input[i]<<(i%8);
}
}
//整个程序,拷贝用的函数
void bitCopy(int *input, int *output, int length)
{
int i;
for(i = 0; i < length; ++i){
output[i] = input[i];
}
}
//执行DES
void doDes(int *mingBit, char *ciphertext, int *keyBit){
int *L = &mingBit[0];
int *R = &mingBit[32];
int temp[32] = {0};//借助temp实现L,R的赋值
int iKey[16][48] = {0};
//ip置换
doIp(mingBit, 64, IP_Table);
//生成子密钥
setIkey(keyBit, iKey);
//16轮跑起来
for(int i=0; i<16; ++i){
bitCopy(R, temp, 32);
//执行F函数
lunF(R, iKey[i]);
//与L异或
doXor(L, R, 32);
bitCopy(L, R, 32);
bitCopy(temp, L, 32);
}
//IP逆置换
doIp(mingBit, 64, IPR_Table);
//将密文转成16进制显示
bitToHex(ciphertext, mingBit, 64);
}
//解密函数,与des差不多
void deDes(char *mingWen,char *ciphertext, char *keyBit)// DES轮解密算法;
{
int cBit[64]={0};
int *L=&cBit[0];
int *R=&cBit[32];
int temp[32]={0};
int iKey[16][48] = {0};
hexToBit(cBit, ciphertext, 64);
doIp(cBit, 64, IP_Table);
setIkey(keyBit, iKey);
//密钥从后往前,L,R与DES相反
for(int i=15;i>=0;i--)
{
bitCopy(L, temp, 32);
lunF(L, iKey[i]);
doXor(R, L, 32);
bitCopy(R, L, 32);
bitCopy(temp, R, 32);
}
doIp(cBit, 64, IPR_Table);
printf("\n");
bitToChar(cBit, mingWen, 64);
}
void bitToHex(char *output, int *input, int length)
{
int i;
for(i=0;i<length/4;i++)
{
output[i]=0;
}
for(i=0;i<length/4;i++)
{
output[i]=input[4*i]+input[4*i+1]*2+input[4*i+2]*4+input[4*i+3]*8;
if(output[i]%16>9)
{
output[i]=output[i]%16+'7';
}
else
output[i]=output[i]%16+'0';
}
}
void hexToBit(int *output, char *input,int length)
{
int i;
for(i=0;i<length;i++)
{
if(input[i/4]<='9')
{
output[i]=((input[i/4]-'0')>>(i%4))&0x01;
}
else
{
output[i]=((input[i/4]-'7')>>(i%4))&0x01;
}
}
}
int main(){
int mingBit[64] = {0};
char ciphertext[16];
int keyBit[64] = {0};
char mingWen[8]="lkw23333";
char key[8]="ssssssss";
char deKey[8];
printf("明文为:\n");
for(int i = 0; i < 8; ++i)
{
printf("%c", mingWen[i]);
}
printf("\n");
charToBit(mingWen, mingBit, 64);
charToBit(key, keyBit, 64);
doDes(mingBit, ciphertext, keyBit);
printf("加密后:\n");
for(int i = 0; i < 16; ++i)
{
printf("%c", ciphertext[i]);
}
printf("\n");
printf("请输入密钥解密:");
gets(deKey);
charToBit(deKey, keyBit, 64);
deDes(mingWen, ciphertext, keyBit);
printf("明文为:\n");
for(int i = 0; i < 8; ++i)
{
printf("%c", mingWen[i]);
}
printf("\n");
return 0;
}