之所以会来写这个,是觉得自己前一段时间一直在找关于DES加密算法的资料,确实有很多代码,但是不同代码得出的结果都不一样。这我就不能忍了,最后还是决定自己去写一份代码。然后就有了现在这个代码。
其实DES算法理解起来不难的,流程多看几遍也就理解了,要注意的是几个int数组一定不能有数据出错,我就是这么被坑了。。。。
找资料的时候有一张图,一直受用,很清晰介绍DES加密的算法:
废话不多说,下面上代码,我是用makefile管理和编译代码,所以文件分得会细一点,读者可以把几个.c文件都放到一个.c文件中,这样就可以实现单文件了。(用一个文件 可以跳过makefile的部分)
文件结构如下图:
首先是makefile文件。
main:main.o changeStr.o round.o doDes.o
cc -g -o $@ $^
main.o:main.c
cc -g -c $<
changeStr.o:changeStr.c
cc -g -c $<
round.o:round.c
cc -g -c $<
doDes.o:doDes.c
cc -g -c $<
clean:
rm -f main\
rm -f main.exe\
rm *.o
main主函数如下:其中包含了三个测试的函数,分别对应单DES加解密,3DES双倍长和三倍长加解密。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "def.h"
void doFflushWithC()
{
char ch;
while ( (ch = getchar()) != '\n' && ch != EOF ) ; /* 通过 while 循环把输入流中的余留数据“吃”掉 */
//fflush(stdin);标准库里面没有定义,所以没有效果,
//使用 scanf("%*[^\n]"); 也可以清空输入流,不过会残留 \n 字符。 */
}
void test_single()
{
char in_data[17]={'\0'}; //存放用户输入的明文
char key_data[17]={'\0'}; //存放用户输入的密码
char out_data[17]={'\0'},out_data2[17]={'\0'}; //存放得出的加密密文
//模拟数据输入
memcpy(in_data,"a406753854abcdef",16);
memcpy(key_data,"a34457799bbcdff1",16);
//单DES加密产生密文
doSingleDes(in_data, key_data, out_data, 1); //加密密文
doSingleDes(out_data, key_data, out_data2, 0); //解密密文
printf("加密前的明文:%s\n",in_data);
printf("加密用的密钥:%s\n",key_data);
printf("加密后的密文:%s\n",out_data);
printf("解密后的明文:%s\n",out_data2);
}
void test_double()
{
char in_data[17]={'\0'}; //存放用户输入的明文
char key_data[33]={'\0'}; //存放用户输入的密码
char out_data[17]={'\0'},out_data2[17]={'\0'}; //存放得出的加密密文
//模拟数据输入
memcpy(in_data,"a406753854abcdef",16);
memcpy(key_data,"a34457799bbcdff10102030405060708",32);
//单DES加密产生密文
doDoubleDes(in_data, key_data, out_data, 1); //加密密文
doDoubleDes(out_data, key_data, out_data2, 0); //解密密文
printf("加密前的明文:%s\n",in_data);
printf("加密用的密钥:%s\n",key_data);
printf("加密后的密文:%s\n",out_data);
printf("解密后的明文:%s\n",out_data2);
}
void test_triple()
{
char in_data[17]={'\0'}; //存放用户输入的明文
char key_data[49]={'\0'}; //存放用户输入的密码
char out_data[17]={'\0'},out_data2[17]={'\0'}; //存放得出的加密密文
//模拟数据输入
memcpy(in_data,"a406753854abcdef",16);
memcpy(key_data,"a34457799bbcdff101020304050607089092939495969798",48);
//单DES加密产生密文
doTripleDes(in_data, key_data, out_data, 1); //加密密文
doTripleDes(out_data, key_data, out_data2, 0); //解密密文
printf("加密前的明文:%s\n",in_data);
printf("加密用的密钥:%s\n",key_data);
printf("加密后的密文:%s\n",out_data);
printf("解密后的明文:%s\n",out_data2);
}
int main()
{
test_triple();
return 0;
}
头文件定义了一些函数:
#ifndef _DEF_H_
#define _DEF_H_
#define PRINT_LOG 0
//字符及字符串转换类函数,changeStr.c中定义
int changeAscToInt(char ch); //十六进制ASC码转换成Int类型,'2'->2,'A'->10
char changeIntToAsc(int a); //十进制转换成字符2>"02",10->"8F"
int changeStrAscToHex(char *asc,char *hex,int len); //"ABC123"-->0xABC123,压缩成半长
int changeStrHexToAsc(char *hex,char *asc,int len); //0xABC123-->"ABC123",扩展成双倍长
int changeIntToIntArray(int *to, int begin, int len, int n) ;//将一个int转换成n个二进制存入to数组中
void changeHexStrToIntArray(char *hex, int *in, int len);//将len长的十六进制字符串,转换并存入int数组中
void changeIntArrayToHexStr(int *in, char *hex, int len); //将int数组中转换存储到十六进制字符串hex中
void print_intArraybyHex(char *title,int *in,int len); //将int数组按十六进制来打印显示
//转换函数,round.c中定义
void exchange(int *from, int *to, const int *rule,int n);//按转换表及长度转换数组到别一个数组
void xorInt(int *to, int *comp,int len); //int类型的异或函数
void key28MoveByTimes(int key[56], int times); //密钥16次循环中左移函数
//DES加密的接口函数,在doDes.c中定义,doDesType=1时为加密,其他值时为解密
void doSingleDes(char* in_data, char*key_data, char *out_data, int doDesType); //单倍长的DES加/解密
void doDoubleDes(char* in_data, char*key_data, char *out_data, int doDesType); //双倍长双DES加/解密
//标准输入操作,main.c函数中定义
void doFflushWithC(); //C语言中实现fflush()清空标准输入缓冲区的实现
int inputAscStrToHex(char *hex,int len); //输入len