C语言实现3DES文件加密系统

  • DES算法
    • 密钥操作
    • 明文操作
  • 3DES算法
  • C语言代码实现
  • 代码效果展示

DES算法

DES(数据加密标准)是一种分组密码。明文,密文和密钥的分组长度都是64位。

DES算法是一种对称加密,通过同一组秘钥进行加密和解密。利用64位秘钥对64位数据进行加密生成一组新的64位数据,其中的转换都是利用统一的表格数组对秘钥和数据转换。

密钥操作

①64 位密钥通过置换选择 1 得到 56 位密钥。置换选择 1 的作用有两个:一是从 64 位密钥 中去掉 8 个就校验位;二是把其余 56 位密钥重新打乱,且将前 28 位作为 L0,后 28 位作为 R0。
置换矩阵如下:(以 57 为例,代表原密钥第 57 位,后同)

int TBL_PC_1[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
};

②将 56 位密钥分为左右 28 位子密钥 L0,R0。对 L0,R0 分别进行循环左移,获得 16 组 28 位子密钥。
循环左移位数表:

const int TBL_MOVE[16]={1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};

③将循环左移得到的 32 组左、右 28 位子密钥相合,得到 16 组 56 位子密钥,再通过置换选 择 2 得到 16 组 48 位子密钥 Ki,i=1,……,16。
置换矩阵如下:

int TBL_PC_2[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
};

明文操作

①64 位明文通过初始置换打乱顺序。
初始置换IP如下:

int TBL_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 };

②将打乱顺序后的明文分为左右两份 L0、R0,各 32 位,进行加密迭代,其框图如下:
其过程为:将Ri-1赋值给Li,i=1,2,……,16,同时作为输入,经过选择运算E扩展得到48位结果。
扩展矩阵如下:

int TBL_EXT[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
};

再将获得到的结果与48位子密钥Ki进行异或得到新的48位数据,(如果是解密的话,则和子密钥K16-i进行异或),送入S盒。将此48位数据以6位为单位分作8个单位,取每个单位第一位和最后一位作为S盒行号,中间四位作为S盒列号。以101011为例,行号为11,列号为0101。于是共取S盒8个数据,每个数据占4位,即能够合并得到32位的结果。
S盒如下:

int TBL_S1[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}
};int TBL_S2[4][16]={{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}
};int TBL_S3[4][16]={{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}
};int TBL_S4[4][16]={{ 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}
};int TBL_S5[4][16]={{ 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}
};int TBL_S6[4][16]={{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}
};int TBL_S7[4][16]={{ 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}
};int TBL_S8[4][16]={{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}
};

将得到的32位结果进行置换运算打乱顺序。
置换运算P如下:

int TBL_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
};

最终将打乱顺序后的32位数据与Li-1进行异或运算,得到Ri。至此,一轮加密迭代结束。
经过16轮加密迭代最终得到L16和R16两个32位数据,以R16作为左32位,L16作为右32位,合并得到64位数据。

③将上述经过16轮加密迭代得到的64位数据进行逆初始置换IPr即得到最终密文(或者是解密出明文)。
逆初始置换IPr如下:

int TBL_IPR[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
};

3DES算法

3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称。它相当于是对每个数据块应用三次DES加密算法。
由于计算机运算能力的增强,原版DES密码的密钥长度变得容易被暴力破解;3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。

C语言代码实现

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<unistd.h>
#include<time.h>#define _ENC_OPT_ 1
#define _DEC_OPT_ 2//密钥第一次置换矩阵
//64位密钥跨过8 16 24 32 40 48 56 64 位取得打乱的56位
int TBL_PC_1[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
};//半截密钥偏移表
//将56位密钥分为左右两段28位,分别左移16次并保存每次的值,再将左右两段合并成
//16组数据
const int TBL_MOVE[16]={1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};//密钥第二次置换矩阵
//用上一步偏移后的16组数据,取56位密匙的48位组成16段子密钥
int TBL_PC_2[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
};//IP置换矩阵
//64位明文打乱顺序
int TBL_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
};//扩展矩阵
//分成两段32位左右值,分别拓展成48位,其中有重复位,48位再与48位子密钥进行异或
int TBL_EXT[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
};//8个s盒
//48位数据按6位一段分成8组获得下标取s1-s8表中的值,获取32位数据
//6位数据首位2位一段,中间4位为一段,取第四行第二列值
int TBL_S1[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}
};int TBL_S2[4][16]={{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}
};int TBL_S3[4][16]={{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}
};int TBL_S4[4][16]={{ 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}
};int TBL_S5[4][16]={{ 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}
};int TBL_S6[4][16]={{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}
};int TBL_S7[4][16]={{ 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}
};int TBL_S8[4][16]={{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盒
//8轮s盒查询结果获得的32位,再次进行顺序打乱
int TBL_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
};//逆IP置换矩阵
//16轮迭代后,再将左右两段交换,使用逆置换表打乱顺序得到最终加密结果
int TBL_IPR[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
};//该多维数组方便将S盒中的数据转化为2进制字符串
unsigned char agSboxMapList[16][5]={"0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111"
};//该函数实现将输入16进制字符串转化为ASCII码,in为输入,out为输出。
//如输入in:313233343536,则out:12345678
int hex_str2bytes(unsigned char*in, unsigned char*out)
{int i=0,j=0;int num=0;int tmp=0;for(i=0;i<strlen((char*)in);i++){if(in[i]<58&&in[i]>47) //0-9tmp=in[i]-48;else if(in[i]<71&&in[i]>64) //A-Ftmp=10+in[i]-65;else if(in[i]<103&&in[i]>96) //a-ftmp=10+in[i]-97;else{printf("Invalid arg!\n");return -1;}if(i%2==0)num=tmp*16;else{num+=tmp;out[j++]=num;}}return 0;
}//该函数实现将输入ASCII码字符串转化为16进制字符串,in为输入,in_len为输入字符串的长度,out为输出。
//如输入in:12345678  in_len:8,则输出out:3132333435363738
int  bytes2hex_str(unsigned char*in,int in_len,unsigned char*out)
{int i;for(i=0;i<in_len;i++){sprintf((char*)out+i*2,"%02x",in[i]);}return 0;
}//该函数实现将ASCII码转化成2进制字符串,in为输入,in_len为输入长度,out为输出。
//如输入in:12345678 in_len:8,则输出:00110001 00110010 00110011 00110100 00110101 00110110 00110111 00111000。
void bytes2bits_str(unsigned char*in,int in_len, unsigned char*out)
{int i=0;for(i=0;i<in_len*8;i++){if(in[i/8]&(0x01<<(7-i%8)))out[i]='1';elseout[i]='0';}
}//该函数实现将2进制字符串转化为ASCII码字符串。in为输入,out为输出。
//如输入in:00110001 00110010 00110011 00110100 00110101 00110110 00110111 00111000,则输出out:12345678
void bits_str2bytes(unsigned char*in, unsigned char*out)
{int i=0,j=0;int num=0;for(i=0;i<strlen((char*)in);i++){if(in[i]=='1'){num+=pow(2,7-i%8);}if((i+1)%8==0){out[j++]=num;num=0;}}
}//该函数实现将2进制字符串转化为10进制整数。
//str为输入,num为输出。如输入str:1101,则输出num:13。
void bits_str2deci(unsigned char*str, int *num)
{int i=0,j=0;*num=0;for(i=strlen((char*)str)-1;i>=0;i--){if(str[i]=='1'){*num+=pow(2,j);}j++;}
}//该函数实现将输入64长度2进制密钥按照置换选择1打乱顺序和选择,得到56长度2进制子密钥。
void getBitsByPc1(unsigned char*in ,unsigned char*out)
{int i=0;int index=0;for(i=0;i<56;i++){index=TBL_PC_1[i];out[i]=in[index-1];}
}//该函数实现将56长度2进制子密钥分为左、右两组进行循环左移得到左、右28长度子密钥各16组。
void getBitsListByMove(unsigned char*key56Bits, unsigned char keyLeft28BitsList[][28+1],unsigned char keyRight28BitsList[][28+1])
{int i=0;int shift=0;memcpy(keyLeft28BitsList[0],key56Bits,28);memcpy(keyRight28BitsList[0],key56Bits+28,28);for(i=0;i<16;i++){shift=TBL_MOVE[i];memcpy(keyLeft28BitsList[i+1],keyLeft28BitsList[i]+shift,28-shift);memcpy(keyLeft28BitsList[i+1]+28-shift,keyLeft28BitsList[i],shift);memcpy(keyRight28BitsList[i+1],keyRight28BitsList[i]+shift,28-shift);memcpy(keyRight28BitsList[i+1]+28-shift,keyRight28BitsList[i],shift);}
}//该函数实现将输入的16组56位子密钥进行置换选择2,得到16组48位长度子密钥。
void getBitsListByPc2(unsigned char in[][56+1],unsigned char out[][48+1])
{int i=0;int j=0;int index=0;for(i=0;i<16;i++){for(j=0;j<48;j++){index=TBL_PC_2[j];out[i][j]=in[i][index-1];}}
}//该函数实现将64长度明文按照初始置换IP打乱顺序,得到64长度打乱顺序的明文。
void getBitsByIp(unsigned char*in, unsigned char*out)
{int i=0;int index=0;for(i=0;i<64;i++){index=TBL_IP[i];out[i]=in[index-1];}
}//即DES中的f函数,该函数实现将32长度输入数据先通过扩展矩阵转为48长度,再与48长度子密钥进行异或,
//再将异或后得到的数据输入S盒得到32长度数据,最终通过置换矩阵P运算得到32长度result。
unsigned char*getBitsByFunc(unsigned char*data, unsigned char*key, unsigned char *result)
{int i=0;int index=0;char extData[48+1]={0};int x=0;int y=0;unsigned char xBits[2+1]={0};unsigned char yBits[4+1]={0};unsigned char SboxRet[32+1]={0};for(i=0;i<48;i++){index=TBL_EXT[i];extData[i]=data[index-1];}for(i=0;i<48;i++){if(extData[i]==key[i])extData[i]='0';elseextData[i]='1';}for(i=0;i<8;i++){memcpy(xBits, extData+i*6,1);memcpy(xBits+1,extData+i*6+5,1);memcpy(yBits,extData+i*6+1,4);bits_str2deci(xBits, &x);bits_str2deci(yBits, &y);switch(i){case 0:memcpy(SboxRet+i*4,agSboxMapList[TBL_S1[x][y]],4);break;case 1:memcpy(SboxRet+i*4,agSboxMapList[TBL_S2[x][y]],4);break;case 2:memcpy(SboxRet+i*4,agSboxMapList[TBL_S3[x][y]],4);break;case 3:memcpy(SboxRet+i*4,agSboxMapList[TBL_S4[x][y]],4);break;case 4:memcpy(SboxRet+i*4,agSboxMapList[TBL_S5[x][y]],4);break;case 5:memcpy(SboxRet+i*4,agSboxMapList[TBL_S6[x][y]],4);break;case 6:memcpy(SboxRet+i*4,agSboxMapList[TBL_S7[x][y]],4);break;case 7:memcpy(SboxRet+i*4,agSboxMapList[TBL_S8[x][y]],4);break;default:break;}}for(i=0;i<32;i++){index=TBL_P[i];*(result+i)=SboxRet[index-1];}return result;
}//将32长度的str1、和str2进行异或,结果保存到result中。
void xor_bits_str(unsigned char*str1, unsigned char*str2, unsigned char*result)
{int i=0;for(i=0;i<32;i++){if(*(str1+i)==*(str2+i)){memcpy(result+i,"0",1);}elsememcpy(result+i,"1",1);}
}//该函数实现将64长度数据in按照逆初始置换Ipr打乱重排,结果保存到out中。
void getBitsByIpr(unsigned char*in, unsigned char*out)
{int i=0;int index=0;for(i=0;i<64;i++){index=TBL_IPR[i];out[i]=in[index-1];}
}//该函数为DES加解密函数,实现将字符串进行DES加解密功能。
//key为密钥,input为明文,input_len为明文长度,output为输出字符串,为ASCII码,opt为要进行的加解密操作,分别有_ENC_OPT_和_DEC_OPT_。
int proc_enc_dec(unsigned char*key,unsigned char*input,int input_len,unsigned char*output,int opt)
{int i=0;unsigned char keyHexStr[16+1]={0};unsigned char keyBits[1024]={0};unsigned char key56Bits[56+1]={0};unsigned char keyLeft28BitsList[17][28+1]={{0}};unsigned char keyRight28BitsList[17][28+1]={{0}};unsigned char key56BitsList[16][56+1]={{0}};unsigned char key48BitsList[16][48+1]={{0}};unsigned char inputHexStr[16+1]={0};unsigned char inputBits[1024]={0};unsigned char inputByIp[64+1]={0};unsigned char inputLeftDataList[1+16][32+1]={{0}};unsigned char inputRightDataList[1+16][32+1]={{0}};unsigned char inputAfterFunc[32+1]={0};unsigned char inputAfterXor[32+1]={0};unsigned char inputLast[64+1];unsigned char binRet[64+1]={0};unsigned char strRet[8+1]={0};unsigned char hexRet[16+1]={0};if(input_len==8){for(i=0;i<8;i++){sprintf((char*)keyHexStr+i*2,"%02x",key[i]);sprintf((char*)inputHexStr+i*2,"%02x",input[i]);}}else{for(i=0;i<input_len;i++){sprintf((char*)keyHexStr+i*2,"%02x",key[i]);sprintf((char*)inputHexStr+i*2,"%02x",input[i]);}for(;i<8;i++){sprintf((char*)keyHexStr+i*2,"%02x",key[i]);sprintf((char*)inputHexStr+i*2,"00");}}bytes2bits_str(key,8,keyBits);bytes2bits_str(input,8,inputBits);getBitsByPc1(keyBits,key56Bits);getBitsListByMove(key56Bits,keyLeft28BitsList,keyRight28BitsList);for(i=0;i<16;i++){memcpy(key56BitsList[i],keyLeft28BitsList[i+1],28);memcpy(key56BitsList[i]+28,keyRight28BitsList[i+1],28);}getBitsListByPc2(key56BitsList,key48BitsList);//开始对加解密内容操作getBitsByIp(inputBits,inputByIp);memcpy(inputLeftDataList[0],inputByIp,32);memcpy(inputRightDataList[0],inputByIp+32,32);for(i=1;i<=16;i++){memcpy(inputLeftDataList[i],inputRightDataList[i-1],32);if(opt==_ENC_OPT_){xor_bits_str(inputLeftDataList[i-1],getBitsByFunc(inputRightDataList[i-1],key48BitsList[i-1],inputAfterFunc),inputAfterXor);}else if(opt==_DEC_OPT_){xor_bits_str(inputLeftDataList[i-1],getBitsByFunc(inputRightDataList[i-1],key48BitsList[16-i],inputAfterFunc),inputAfterXor);}else{printf("[ERROR] Invalid option!\n");}memcpy(inputRightDataList[i],inputAfterXor,32);}memcpy(inputLast,inputRightDataList[16],32);memcpy(inputLast+32,inputLeftDataList[16],32);getBitsByIpr(inputLast,binRet);bits_str2bytes(binRet,strRet);for(i=0;i<8;i++){sprintf((char*)&hexRet[i*2],"%02x",strRet[i]);}memcpy(output,strRet,8);return 0;
}//该函数为3DES加解密函数,实现将字符串进行3DES加解密功能。
//key为密钥,input为明文,input_len为明文长度,output为输出字符串,为ASCII码,opt为要进行的加解密操作,分别有_ENC_OPT_和_DEC_OPT_。函数运行成功返回0。
int  _3des_enc_dec(unsigned char*key,unsigned char*input,int input_len,unsigned char*output,int opt)
{unsigned char key1[8+1]={0};unsigned char key2[8+1]={0};unsigned char key3[8+1]={0};unsigned char ip[8+1]={0};memcpy(key1,key,8);memcpy(key2,key+8,8);memcpy(key3,key,8);if(opt==_ENC_OPT_){strcpy((char*)ip,(char*)input);if(proc_enc_dec(key1,ip,input_len,output,_ENC_OPT_))return -1;memcpy(ip,output,8);if(proc_enc_dec(key2,ip,8,output,_DEC_OPT_))return -1;memcpy(ip,output,8);if(proc_enc_dec(key3,ip,8,output,_ENC_OPT_))return -1;}else if(opt==_DEC_OPT_){hex_str2bytes(input,ip);if(proc_enc_dec(key1,ip,8,output,_DEC_OPT_))return -1;memcpy(ip,output,8);if(proc_enc_dec(key2,ip,8,output,_ENC_OPT_))return -1;memcpy(ip,output,8);if(proc_enc_dec(key3,ip,8,output,_DEC_OPT_))return -1;}else{printf("Invalid args!\n");return -2;}return 0;
}//自定义读取函数
void fgets_t(unsigned char*str,int count)
{fgets((char*)str,count,stdin);str[strlen((char*)str)-1]='\0';
}//简单操作交互界面
int getTip()
{system("cls");puts("+----------------------------------------------------------------+");puts("|         Welcome to easy 3DES file encrpt-decrypt system!       |");puts("+-----------------------------------------------------------------");puts("\n");puts("Please enter the given number:");puts("1.encrypt str to hex using DES.");puts("2.decrypt hex to str using DES.");puts("3.encrypt str to hex using 3DES.");puts("4.edcrypt hex to str using 3DES.");puts("5.encrypt file.");puts("6.decrypt file.");puts("==================================================================");puts("(c)cls (#)exit");return 1;
}//该函数实现从文件流fp中默认提取8个字符,返回为提取到的字符个数。
int get8Bits(FILE*fp,char*str)
{int count;memset(str,0,8);count=fread(str,1,8,fp);return count;
}//该函数实现文件3DES加密功能。file_in为输入文件,file_out为输出函数,key为密钥
int file_enc(char*file_in, char*file_out,unsigned char*key)
{FILE*fp_in,*fp_out;int count;int bytes=0;double speed;int start_time,finish_time,time_cost;unsigned char input[8+1]={0};unsigned char output[8+1]={0};unsigned char outputHex[16+1]={0};if((fp_in=fopen(file_in,"rb"))==NULL){perror("file_enc can not open file_in");return -1;}if((fp_out=fopen(file_out,"wb"))==NULL){perror("file_enc can not open file_out");return -1;}time_t t;t=time(NULL);start_time=time(&t);printf("Start encrypting\n");while((count=get8Bits(fp_in,(char*)input))){bytes+=count;_3des_enc_dec(key,input,count,output,_ENC_OPT_);bytes2hex_str(output,8,outputHex);fwrite(outputHex,16,1,fp_out);}finish_time=time(&t);time_cost=finish_time-start_time;speed=(double)bytes/time_cost;printf("Encryption finished, %d bytes in total, used %d seconds, speed: %.2f B/s\n",bytes,time_cost,speed);fclose(fp_in);fclose(fp_out);return 0;
}//该函数实现文件3DES解密功能。file_in为输入文件,file_out为输出函数,key为密钥
int file_dec(char*file_in,char*file_out,unsigned char*key)
{FILE*fp_in,*fp_out;int count;int bytes=0;double speed;int start_time,finish_time,cost_time;unsigned char inputHex[16+1]={0};unsigned char input[8+1]={0};unsigned char output[8+1]={0};if((fp_in=fopen(file_in,"rb"))==NULL){perror("file_dec can not open file_in");return -1;}if((fp_out=fopen(file_out,"wb"))==NULL){perror("file_dec can not open file_out");return -1;}printf("Start decryting\n");time_t t;t=time(NULL);start_time=time(&t);while((count=fread(inputHex,1,16,fp_in))){bytes+=count;_3des_enc_dec(key,inputHex,16,output,_DEC_OPT_);fwrite(output,strlen((char*)output),1,fp_out);}finish_time=time(&t);cost_time=finish_time-start_time;speed=(double)bytes/cost_time;printf("Decryption finished %d bytes in total, used %d seconds,speed: %.2f B/s\n",bytes,cost_time,speed);fclose(fp_in);fclose(fp_out);
}int main(int argc, char**argv)
{FILE *fp_in,*fp_out;unsigned char fin_input;unsigned char temp[8+1]={0};unsigned char enc_key[16+1]={0};unsigned char dec_key[16+1]={0};unsigned char buff[16+1]={0};unsigned char in_buff[8+1]={0};unsigned char in_buff_hex[16+1]={0};unsigned char out_buff[8+1]={0};unsigned char out_buff_hex[16+1]={0};char file_in[32+1]={0};char file_out[32+1]={9};getTip();while(1){printf("enter your choice: ");memset(temp,0,8);scanf("%8s",temp);dofin_input=getchar();while(fin_input!='\n'&&fin_input!='\xff');if(strlen((char*)temp)!=1){puts("you should enter one number!");continue;}if(strlen((char*)temp)==1&&temp[0]!='#'){if(strlen((char*)temp)==1&&temp[0]!='c'){switch(temp[0]){case '1':memset(in_buff,0,8);memset(out_buff,0,8);memset(out_buff_hex,0,16);memset(enc_key,0,16);printf("Input 8bytes key like 12345678 : ");memset(buff,0,16);fgets_t(buff,16);if(strlen((char*)buff)!=8){puts("Key error! you should input 8bytes key!");break;}strcpy((char*)enc_key,(char*)buff);printf("Input 8bytes str like 12345678 : ");memset(buff,0,16);fgets_t(buff,16);if(strlen((char*)buff)!=8){puts("Str error! you should input 8bytes str!");break;}strcpy((char*)in_buff,(char*)buff);proc_enc_dec(enc_key,in_buff,8,out_buff,_ENC_OPT_);bytes2hex_str(out_buff,8,out_buff_hex);printf("Encrpted: %s\n",out_buff_hex);break;case '2':memset(in_buff,0,8);memset(in_buff_hex,0,16);memset(out_buff,0,8);memset(dec_key,0,16);printf("Input 8bytes key like 12345678 : ");memset(buff,0,16);fgets_t(buff,18);if(strlen((char*)buff)!=8){puts("Key error! you should input 8bytes key!");break;}strcpy((char*)dec_key,(char*)buff);printf("input hex str like 3132333435363738 : ");memset(buff,0,16);fgets_t(buff,18);if(strlen((char*)buff)!=16){puts("Str error! you should input 16bytes hes str!");break;}strcpy((char*)in_buff_hex,(char*)buff);hex_str2bytes(in_buff_hex,in_buff);proc_enc_dec(dec_key,in_buff,8,out_buff,_DEC_OPT_);printf("Decrypted: %s\n",out_buff);break;case '3':memset(enc_key,0,16);memset(in_buff,0,8);memset(out_buff,0,8);memset(out_buff_hex,0,8);printf("Input 16bytes key like 1234567887654321 : ");memset(buff,0,16);fgets_t(buff,18);if(strlen((char*)buff)!=16){puts("Key error! you should input 16bytes key!");break;}strcpy((char*)enc_key,(char*)buff);printf("Input 8bytes  str like 12345678 : ");memset(buff,0,16);fgets_t(buff,16);if(strlen((char*)buff)!=8){puts("Str error! you should input 8bytes str!");break;}strcpy((char*)in_buff,(char*)buff);_3des_enc_dec(enc_key,in_buff,8,out_buff,_ENC_OPT_);bytes2hex_str(out_buff,8,out_buff_hex);printf("Encrypted: %s\n",out_buff_hex);break;case '4':memset(dec_key,0,16);memset(in_buff_hex,0,16);memset(out_buff,0,8);printf("Input 16bytes key like 1234567887654321 : ");memset(buff,0,16);fgets_t(buff,18);if(strlen((char*)buff)!=16){puts("Key error! you should input 16bytes key!");break;}strcpy((char*)dec_key,(char*)buff);printf("Input hex str like 313233343536 : ");memset(buff,0,16);fgets_t(buff,18);if(strlen((char*)buff)!=16){puts("Str error! you should input 16bytes str!");break;}strcpy((char*)in_buff_hex,(char*)buff);_3des_enc_dec(dec_key,in_buff_hex,16,out_buff,_DEC_OPT_);printf("Decrpted: %s\n",out_buff);break;case '5':memset(file_in,0,32);memset(file_out,0,32);memset(enc_key,0,16);printf("Input file to encrpt: ");fgets_t((unsigned char*)file_in,32);if((fp_in=fopen(file_in,"rb"))==NULL){perror("file_in");break;}fclose(fp_in);printf("Input filePath to save encrypted file: ");fgets_t((unsigned char*)file_out,32);if((fp_out=fopen(file_out,"wb"))==NULL){perror("file_out");break;}fclose(fp_out);printf("Input 16bytes key like 1234567887654321 : ");memset(buff,0,16);fgets_t(buff,18);if(strlen((char*)buff)!=16){puts("Key error! you should input 16bytes key!");break;}strcpy((char*)enc_key,(char*)buff);file_enc(file_in,file_out,enc_key);break;case '6':memset(file_in,0,32);memset(file_out,0,32);memset(dec_key,0,16);printf("Input file to decrypt: ");fgets_t((unsigned char*)file_in,32);if((fp_in=fopen(file_in,"rb"))==NULL){perror("file_in");break;}fclose(fp_in);printf("Input filePath to save decrypted file: ");fgets_t((unsigned char*)file_out,32);if((fp_out=fopen(file_out,"wb"))==NULL){perror("file_out");break;}fclose(fp_out);printf("Input 16bytes key like 1234567887654321 : ");memset(buff,0,16);fgets_t(buff,18);if(strlen((char*)buff)!=16){puts("Key error! you should input 16bytes key!");break;}strcpy((char*)dec_key,(char*)buff);file_dec(file_in,file_out,dec_key);break;default:puts("Wrong args!");break;}}elsegetTip();}elsebreak;}}

代码效果展示

人机交互界面:
字符加解密功能(DES,3DES,对于3DES,其中key如1234567887654321前8位作为K1,后8位作为K2):
文件加解密功能(加解密速度统计功能,短块加密填充法处理):
文件加解密效果展示(windows下):

DES原始代码参考:https://blog.csdn.net/jiujiederoushan/article/details/100008198

C语言实现DES,3DES以及基于3DES的文件加密系统相关推荐

  1. linux透明加密系统,基于Linux的透明加密系统的设计与实现

    摘要: 随着互联网时代的到来,人们用于接触事物的方式不仅仅局限于简单的通讯工具了,如:口语交流,书信传递等等,现在已经越来越多地通过手机,电脑,平板等电子设备进行信息的交流和信息的存储.但是在我们享受 ...

  2. C#毕业设计——基于C#+asp.net+C++的RSA文件加密系统设计与实现(毕业论文+程序源码)——RSA文件加密系统

    基于C#+asp.net+C++的RSA文件加密系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于C#+asp.net+C++的RSA文件加密系统设计与实现,文章末尾附有本毕业设计的论文 ...

  3. 基于python的文件加密传输系统 毕业论文_20183411 李丞灏 2020-2021 《python程序设计》 实验三 加密传输文件 实验报告...

    20183411 李丞灏 2020-2021 <python程序设计> 实验三 加密传输文件 实验报告 课程:<Python程序设计> 班级: 1834 姓名: 李丞灏 学号: ...

  4. 基于python的文件加密传输_基于python实现文件加密功能

    {"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],&q ...

  5. 基于python的文件加密传输_Python优雅的加密传输文件

    最近需要通过网络加密传输一些文件,首先想到的是RSA,公钥 + 私钥的搭配,不能再好. 2. 导入模块,创建密钥对. 3. 然后用公钥加密,用私钥解密. 运行结果如下 4. 如果只是简单的,小字符串的 ...

  6. 基于python的文件加密传输_python 利用Crypto进行AES解密加密文件

    背景:工作需要,部分数据进行了加密传输,对方使用了AES对密码进行了加密,需要获取到解密的数据. 目标:通过密钥成功解密文件. 关键词:AES_ECB,AES_CBC,Java和Python的AES加 ...

  7. 基于C++的文件加密解密(密码学课程设计)

    资源下载地址:https://download.csdn.net/download/sheziqiong/86882054 资源下载地址:https://download.csdn.net/downl ...

  8. C语言程序设计-文件加密系统01

    题目:文件加密系统 [问题描述] 文件的传输会有明文和密文的区别,明文发送是不安全的,用一个程序实现发送文件的加密和解密操作.加密算法,密钥设计由同学自己选择现有的加密解密算法或是自己设计. [基本要 ...

  9. 毕业设计-基于微信小程序的文件加密系统

    目录 前言 课题背景与简介 实现设计思路 一.文件加密系统现状 二.系统总体设计 三.系统流程设计 四.系统实现 五.总结 实现效果样例 更多帮助 前言

最新文章

  1. python之socketserver实现并发
  2. Asp SqlDataSource将数据库数据绑定在 GridView
  3. qt 实现 以图片为中心 让它旋转_QT图片旋转动画
  4. 技术分享丨华为鲲鹏架构Redis知识二三事
  5. 一篇非常有用的文章-《台湾清华彭明辉教授的研究生手册》如何发现一个研究课题?
  6. 硬核黑科技、技术大咖、AI 音乐节……科大讯飞全球 1024 开发者节太燃了!
  7. 2种造成sqlserver自增列不连续的原因
  8. HDU2098 分拆素数和【筛选法】
  9. 【渝粤教育】国家开放大学2018年春季 3819-21T燃气安全管理 参考试题
  10. Python求解拉普拉斯矩阵及其特征值
  11. LPVOID傳遞參數的問題
  12. CALIPSO数据批量下载方法
  13. 初识C语言之详解char类型
  14. 【matlab】记一次微信聊天文字记录导出到Excel工作
  15. 杭电ACM:人见人爱A-B
  16. 【新刊邀稿】计算机视觉图像类,SCIEI双检,正刊,进展顺利
  17. 8年开发经验,帮你总结这帮双面HR们
  18. html 表格自动计算,表格怎么自动计算加减
  19. 微服务基础模块搭建过程
  20. 游戏测试 | 游戏工具:做一个可以即时修改卡牌属性的工具方便测试

热门文章

  1. Java Iterator 使用
  2. Unix/Linux/Mac os下 文件互传
  3. OWASP TOP10(2017)
  4. 决策树模型与学习《一》
  5. C++ 笔记(13)— 函数(函数声明、函数定义、函数调用[传值、指针、引用]、函数参数默认值、函数重载)
  6. Go 学习笔记(50)— Go 标准库之 net/url(查询转义、查询参数增/删/改/查、解析URL)
  7. .ARM.exidx
  8. Newtonsoft.Json文件错误
  9. python科学计算整理
  10. http编程学习(C#)