DES加密和解密算法的实现(C语言)

主要是做个记录,害怕以后代码丢了,先放到这里了。

DES再不进行介绍了,可以看上一篇的 DES 的python实现

转载请注明出处:https://www.cnblogs.com/wangyanzhong123/p/13784272.html

说明

这个版本用了很多位运算,也没有添加注释,所以可能阅读起来会有一些困难。其中实现的是 DES 的 CBC 模式下的加解密,可以保证的是结果一定是正确的。

源代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h> const uint8_t 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
}; const uint8_t invIP[] = {
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
}; const uint8_t 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
}; const uint8_t 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
}; const uint8_t S[8][64] = {{
/* 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, 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
},{
/* S7 */
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
},{
/* 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
}}; const uint8_t PC1[] = {
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
}; const uint8_t PC2[] = {
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
}; const uint8_t shift_steps[] = {
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
}; uint64_t pc1(uint64_t key){
uint64_t result = 0;
for (int i = 0; i < 56; i ++){
result = result << 1;
result = result | ((key >> (64-PC1[i])) & 0x0000000000000001);
}
return (result & 0x00ffffffffffffff);
} uint64_t pc2(uint64_t key){
uint64_t result = 0;
for (int i = 0; i < 48; i ++){
result = result << 1;
result = result | (uint64_t)((key >> (56-PC2[i])) & 0x0000000000000001);
}
return (result & 0x0000ffffffffffff);
} uint64_t ip(uint64_t input){
uint64_t result = 0;
for (int i = 0; i < 64; i ++){
result = result << 1;
result = result | ((input >> (64-IP[i])) & 0x0000000000000001);
}
return result;
} uint64_t inv_ip(uint64_t input){
uint64_t result = 0;
for (int i = 0; i < 64; i ++){
result = result << 1;
result = result | ((input >> (64-invIP[i])) & 0x0000000000000001);
}
return result;
} uint64_t extend(uint32_t input){
uint64_t result = 0;
for (int i = 0; i < 48; i ++){
result = result << 1;
result = result | (uint64_t)((input >> (32-E[i])) & 0x00000001);
}
return (result & 0x0000ffffffffffff);
} // uint32_t s(uint64_t input){
// uint32_t result = 0;
// uint8_t *blocks = (uint8_t*)malloc(sizeof(uint8_t)*8);
// uint8_t row, column;
// for (int i = 0; i < 8; i ++){
// blocks[i] = (uint8_t)((input >> (42 - 6*i)) & 0x000000000000003f);
// row = ((blocks[i] >> 4) & 0x02) | (blocks[i] & 0x01);
// column = (blocks[i] >> 1) & 0x0f;
// result = result << 4;
// result = result | (uint32_t)(S[i][row*16+column] & 0x0f);
// }
// free(blocks);
// return result;
// } uint32_t s(uint64_t input) {
uint32_t res = 0;
int row = 0;
int col = 0;
for (int i = 0; i < 8; i++) {
row = (uint8_t) ((input & (0x0000840000000000 >> 6*i)) >> (42-6*i));
row = (row >> 4) | (row & 0x01);
col = (uint8_t) ((input & (0x0000780000000000 >> 6*i)) >> (43-6*i));
res <<= 4;
res |= (uint32_t) (S[i][16*row+col] & 0x0f);
}
return res;
} uint32_t p(uint32_t input){
uint32_t result = 0;
for (int i = 0; i < 32; i ++){
result = result << 1;
result = result | ((input >> (32-P[i])) & 0x00000001);
}
return result;
} void to_uint64(uint8_t *buffer, size_t buffersize, uint64_t *result){
uint32_t tmp1 = 0, tmp2 = 0;
for (int i = 0; i < (buffersize/8); i ++){
tmp1 = (((uint32_t)buffer[8*i] << 24) & 0xff000000) | (((uint32_t)buffer[8*i+1] << 16) & 0x00ff0000) |
(((uint32_t)buffer[8*i+2] << 8) & 0x0000ff00) | (((uint32_t)buffer[8*i+3]) & 0x000000ff);
tmp2 = (((uint32_t)buffer[8*i+4] << 24) & 0xff000000) | (((uint32_t)buffer[8*i+5] << 16) & 0x00ff0000) |
(((uint32_t)buffer[8*i+6] << 8) & 0x0000ff00) | (((uint32_t)buffer[8*i+7]) & 0x000000ff);
result[i] = (((uint64_t)tmp1 << 32) & 0xffffffff00000000) | ((uint64_t)tmp2 & 0x00000000ffffffff);
}
} void to_uint8(uint64_t *buffer, size_t buffersize, uint8_t *result){
for (int i = 0; i < buffersize; i ++){
for (int j = 0; j < 8; j ++){
result[8*i+j] = (uint8_t)(buffer[i] >> (56-8*j));
}
}
} uint64_t hex_2_uint64(char *string){
uint64_t result = 0;
size_t len = 0;
len = strlen(string);
for (int i = 0; i < len; i ++){
if (string[15-i] >= '0' && string[15-i] <= '9') {
result += (uint64_t)(string[15-i]-'0') * ((uint64_t)(1) << (4*i));
} else if (string[15-i] >= 'a' && string[15-i] <= 'f') {
result += (uint64_t)(string[15-i]-'a' + 10) * ((uint64_t)(1) << (4*i));
} else if (string[15-i] >= 'A' && string[15-i] <= 'F') {
result += (uint64_t)(string[15-i]-'A' + 10) * ((uint64_t)(1) << (4*i));
}
}
return result;
} void generateSubkeys(uint64_t key, uint64_t* subkeys){
uint32_t left, right;
uint64_t roundkey = 0;
uint64_t key_tmp = 0;
key_tmp = pc1(key);
left = (uint32_t)((key_tmp >> 28) & 0x000000000fffffff);
right = (uint32_t)(key_tmp & 0x000000000fffffff);
for (int i = 0; i < 16; i ++){
int shift = shift_steps[i];
left = (0x0fffffff & (left << shift)) | (left >> (28-shift));
right = (0x0fffffff & (right << shift)) | (right >> (28-shift));
roundkey = ((uint64_t)left << 28) | (uint64_t)right;
roundkey = pc2(roundkey);
subkeys[i] = roundkey;
}
} uint64_t raw_des(uint64_t text, uint64_t key, uint8_t mode){
uint64_t* subkeys = (uint64_t*)malloc(sizeof(uint64_t)*16);
generateSubkeys(key, subkeys);
uint32_t L = 0, R = 0, SR = 0, PR = 0, tmp = 0;
uint64_t ER = 0, output = 0, subkey = 0;
text = ip(text);
L = (text >> 32) & 0x00000000ffffffff;
R = text & 0x00000000ffffffff;
for (int i = 0; i < 16; i ++){
ER = extend(R);
subkey = (mode == 0) ? subkeys[i] : subkeys[15-i];
ER = ER ^ subkey;
SR = s(ER);
PR = p(SR);
tmp = R;
R = L ^ PR;
L = tmp;
}
free(subkeys);
output = inv_ip(((uint64_t)(R) << 32 ) | (uint64_t)(L));
return output;
} uint64_t des_ede2(uint64_t text, uint64_t key1, uint64_t key2, uint8_t mode){
uint64_t result;
result = (mode == 0) ? raw_des(text, key1, 0) : raw_des(text, key1, 1);
result = (mode == 0) ? raw_des(result, key2, 1) : raw_des(result, key2, 0);
result = (mode == 0) ? raw_des(result, key1, 0) : raw_des(result, key1, 1);
return result;
} void des_cbc_enc(FILE* in, FILE* out, uint64_t key, uint64_t iv){
uint8_t *filebuffer;
size_t filesize = 0, padding_size = 0;
uint64_t *blocks, *output;
clock_t start, end;
fseek(in, 0, SEEK_END);
filesize = ftell(in);
rewind(in);
padding_size = 8 - filesize % 8;
filebuffer = (uint8_t*)malloc(sizeof(uint8_t)*(filesize + padding_size));
blocks = (uint64_t*)malloc(sizeof(uint64_t)*((filesize + padding_size)/8));
output = (uint64_t*)malloc(sizeof(uint64_t)*((filesize + padding_size)/8));
fread(filebuffer, sizeof(uint8_t), filesize, in);
memset(filebuffer+filesize, (uint8_t)padding_size, padding_size);
to_uint64(filebuffer, (filesize+padding_size), blocks);
start = clock();
for (int i = 0; i < (filesize+padding_size)/8; i ++){
output[i] = raw_des((blocks[i] ^ iv), key, 0);
iv = output[i];
}
end = clock();
fwrite(output, sizeof(uint64_t), ((filesize + padding_size)/8), out);
printf("time cost: %f s\n", (double)(end-start)/CLOCKS_PER_SEC);
free(filebuffer);
free(blocks);
free(output);
} void des_cbc_dec(FILE* in, FILE* out, uint64_t key, uint64_t iv){
uint64_t *filebuffer;
uint64_t *outbuffer;
uint8_t *out8_tbuffer;
size_t filesize = 0, padding_size = 0;
clock_t start, end;
fseek(in, 0, SEEK_END);
filesize = ftell(in);
rewind(in);
filebuffer = (uint64_t*)malloc(sizeof(uint64_t)*(filesize/8));
outbuffer = (uint64_t*)malloc(sizeof(uint64_t)*(filesize/8));
out8_tbuffer = (uint8_t*)malloc(sizeof(uint8_t)*filesize);
fread(filebuffer, sizeof(uint64_t), filesize/8, in);
start = clock();
for (int i = 0 ; i < (filesize/8); i ++){
outbuffer[i] = raw_des(filebuffer[i], key, 1) ^ iv;
iv = filebuffer[i];
}
end = clock();
to_uint8(outbuffer, filesize/8, out8_tbuffer);
padding_size = (size_t)out8_tbuffer[filesize-1];
fwrite(out8_tbuffer, sizeof(uint8_t), filesize-padding_size, out);
printf("time cost: %f s\n", (double)(end-start)/CLOCKS_PER_SEC);
free(filebuffer);
free(outbuffer);
free(out8_tbuffer);
} int main(int argc, char **argv){
char *inputfile = "-f";
char *inputstring = "-s";
char *mod = "-enc";
if (argc < 2){
printf("usage: %s 'string'\n", argv[0]);
return 1;
} else {
if (!strcmp(argv[1], inputfile)){
FILE *in, *out;
in = fopen(argv[3], "rb");
if (in == NULL) {
printf("%s not exist\n",argv[3]);
return -1;
} else {
out = fopen(argv[4], "wb+");
(!strcmp(argv[2],mod))? des_cbc_enc(in, out, hex_2_uint64(argv[5]), hex_2_uint64(argv[6]))
: des_cbc_dec(in, out, hex_2_uint64(argv[5]), hex_2_uint64(argv[6]));
fclose(in);
fclose(out);
}
} else if (!strcmp(argv[1], inputstring)) {
uint64_t cipher = 0;
clock_t start, end;
double duration;
start = clock();
for (int i = 0; i < 1000; i ++)
if(!strcmp(argv[2],mod))
cipher = des_ede2(hex_2_uint64(argv[3]), hex_2_uint64(argv[4]), hex_2_uint64(argv[5]), 0);
else
cipher = des_ede2(hex_2_uint64(argv[3]), hex_2_uint64(argv[4]), hex_2_uint64(argv[5]), 1);
end = clock();
duration = (double)(end - start) / (double)(CLOCKS_PER_SEC);
printf("%llx\n", cipher);
printf("enc/dec for 1000 times cost: %f s\n", duration);
}
}
system("pause");
}

DES加解密算法(C语言实现)的更多相关文章

  1. DES加解密算法Qt实现

      算法解密qt加密table64bit [声明] (1) 本文源码 大部分源码来自:DES算法代码.在此基础上,利用Qt编程进行了改写,实现了DES加解密算法,并添加了文件加解密功能.在此对署名为b ...

  2. JavaScript与C#互通的DES加解密算法

    原文地址:传送门 本文提供了一个能使JavaScript与C#互通的DES加解密算法的实现,在前台页面中用JavaScript版本的DES算法将数据加密之后,传到服务器端,在服务器端可用C#版本的DE ...

  3. DES加密解密算法C语言代码实现

    代码: #include<stdio.h> #include<string.h> #include<stdlib.h> /*-------------------- ...

  4. 实验一:C语言实现DES加解密算法

    计算程序执行10万次需要的时间: 总共需要175秒 加解密一次的时间小于:0.00175秒 纯计算加解密的时间会更短 去除IO操作后的时间 也就是说加解密一次的时间为0.07毫秒 /*-------- ...

  5. 实现与JS相同的Des加解密算法【转】

    Java代码 import java.util.ArrayList; import java.util.List; /** * DES加密/解密 * * @Copyright Copyright (c ...

  6. Des加解密算法

    class DesHelper    {        /// <summary>        /// DES加密方法        /// </summary>       ...

  7. C#加解密算法

    先附上源码 加密解密算法目前已经应用到我们生活中的各个方面 加密用于达到以下目的: 保密性:帮助保护用户的标识或数据不被读取. 数据完整性:帮助保护数据不被更改. 身份验证:确保数据发自特定的一方. ...

  8. JavaScript与C#互通的DES加解密算法的实现(转)

    本文提供了一个能使JavaScript与C#互通的DES加解密算法的实现,在前台页面中用JavaScript版本的DES算法将数据加密之后,传到服务器端,在服务器端可用C#版本的DES解密算法将其解密 ...

  9. PHP 基础篇 - PHP 中 DES 加解密详解

    一.简介 DES 是对称性加密里面常见一种,全称为 Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法.密钥长度是64位(bit),超过位数密钥被忽略.所谓对 ...

随机推荐

  1. Unity代码混淆

    https://www.zhihu.com/question/25414422 http://blog.csdn.net/kun1234567/article/details/7917847 http ...

  2. C# .NET容器的源码

    这里有List<T>的源码http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs

  3. golang 内置print/println、fmt、log的区别

    fmt.Println与fmt.Print区别 换行区别不用多说,另外一个区别在于fmt.Print只有在参数间都不是字符串时才会产生间隔 fmt与log的重要区别 fmt没有做同步处理 fmt标准输 ...

  4. ZT:15 个你非了解不可的 Linux 特殊字符

    https://os.51cto.com/art/202003/611595.htm 不知道大家接触 Linux 系统有多久了,可曾了解过 Linux 中有哪些特殊的字符呢?其实啊,那些特殊字符都大有 ...

  5. nginx高可用

    15.1. 传统的高可用思路 tomcat的高可用的思路,是在tomcat集群前面加一层负载服务nginx.如下图 这种做法,解决了tomcat的高可用问题.但是引入了前面的负载机器的高可用问题(Ng ...

  6. Mybati源码解析篇之六剑客!!!

    目录 前言 环境版本 Mybatis的六剑客 SqlSession 有何方法 语句执行方法 立即批量更新方法 事务控制方法 本地缓存方法 获取映射方法 有何实现类? Executor 实现类 Base ...

  7. RocketMQ生产部署架构如何设计

    前言 看了我们之前的文章,相信小伙伴们对RocketMQ已经有了一个初步的了解,那么今天我们就来聊一聊具体如何来设计一套高可用的生产部署架构. 在聊如何设计这套架构的同时,我们再补充一些之前没提到的知 ...

  8. ThinkPHP6.0 模型搜索器的使用

    搜索器用于封装查询条件表达式,必须在模型中定义,只有使用模型操作数据时才能用搜索器.调用搜索器时使用的是数据表字段,可以不用定义搜索器方法,默认是 = 条件:如果不是数据表字段,必须定义对应的搜索器方 ...

  9. jenkins参数传递

    官方说明:https://wiki.jenkins.io/display/JENKINS/Parameterized+Build 1.添加参数传递 参数类型解析: 2.在 Execute shell ...

  10. Linux:apache安装

    1.查询是否已安装 rpm -qa httpd 如果已安装,先卸载 发现有依赖包,先把依赖卸载 或者加上--nodeps参数,不考虑依赖,直接卸载   rpm -e --nodeps httpd-2. ...