Des算法的实现

博主分享了自己实现DES加密算法的过程,指出理解算法并不困难,但需注意int数组的数据准确性。提供了一张有助于理解DES算法的图表,并提供了代码文件结构,使用makefile进行管理。
摘要由CSDN通过智能技术生成

  之所以会来写这个,是觉得自己前一段时间一直在找关于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
DES算法C语言代码及实现 首先新建头文件des_encode.H 内容如下: void EncodeMain(); //EncodeMain function void DecodeMain(); //Sorry ,it has not used void Decode(int *str,int *keychar); //decode :input 8 chars,8 keychars void Encode(int *str,int *keychar); //encode: input 8 chars,8 keychars void keyBuild(int *keychar); //create key array void StrtoBin(int *midkey,int *keychar); //change into binary void keyCreate(int *midkey2,int movebit,int i); //call by keyBuild void EncodeData(int *lData,int *rData,int *srt); //encodedata function void F(int *rData,int *key); //F function void Expand(int *rData,int *rDataP); //Expand function void ExchangeS(int *rDataP,int *rData); //S-diagram change void ExchangeP(int *rData); //P change void FillBin(int *rData,int n,int s); // data to binary;call by S-Diagram change function void DecodeData(int *str,int *lData,int *rData); //DecodeData from binary int IP1[]={58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, //initial change 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, }; int IP2[]={40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, //opp initial change 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 }; int s[][4][16]={{ //S-diagram array {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} }, { {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} }, { {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} }, { {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} }, { {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} }, { {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} }, { {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} }, { {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} } }; int Ex[48]={ 32,1,2,3,4,5, //Expand array 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 }; int P[32]={16,7,20,21, //P-change 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 }; int PC1[56]={57,49,41,33,25,17,9, //PC-1 in keyBuild 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,33,15, 7,62,54,46,38,30,22, 14,6,61,53,45,37,29, 21,13,5,28,20,12,4 }; int PC2[48]={14,17,11,24,1,5, //PC-2 in keyBuild 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 }; 再创建des.cpp 内容如下: #include<stdio.h> #include<string.h> #include"des_encode.h" int key[16][48]; char str[8]; void main() //main function { EncodeMain(); } void EncodeMain() //EncodeMain function { int i; char keychar[8]; int key2[8]; int strkey[8]; printf("请输入8个要加密的字符:\n"); for(i=0;i<8;i++) scanf("%c",&str[i]); getchar(); for(i=0;i<8;i++) strkey[i]=str[i]; printf("\n输入明文的十六进制为:\n"); for(i=0;i<8;i++) printf("%10x",strkey[i]); printf("\n请输入密钥(8个字符):\n"); for(i=0;i<8;i++) scanf("%c",&keychar[i]); for(i=0;i<8;i++) key2[i]=keychar[i]; getchar(); // printf("%c",keychar[i]); Encode(strkey,key2); printf("\n加密后十六进制密文是:\n"); for(i=0;i<8;i++) printf("%10x",strkey[i]); printf("\n\n清输入解密密码\n"); for(i=0;i<8;i++) scanf("%c",&keychar[i]); for(i=0;i<8;i++) key2[i]=keychar[i]; Decode(strkey,key2); for(i=0;i<8;i++) printf("%10x",strkey[i]); for(i=0;i<8;i++) str[i]=strkey[i]; printf("\n明文为:\t"); for(i=0;i<8;i++) printf("%c",str[i]); printf("\n\n"); } void keyBuild(int *keychar){ //create key array int i,j; int movebit[]={1,1,2,2,2,2,2,2, 1,2,2,2,2,2,2,1}; int midkey2[56]; int midkey[64]; StrtoBin(midkey,keychar); for(i=0;i<56;i++) midkey2[i]=midkey[PC1[i]-1]; for(i=0;i<16;i++) keyCreate(midkey2,movebit[i],i); } void StrtoBin(int *midkey,int *keychar){ //change into binary int trans[8],i,j,k,n; n=0; for(i=0;i<8;i++){ j=0; while(keychar[i]!=0){ trans[j]=keychar[i]%2; keychar[i]=keychar[i]/2; j++; } for(k=j;k<8;k++)trans[k]=0; for(k=0;k<8;k++) midkey[n++]=trans[7-k]; } } void keyCreate(int *midkey2,int movebit,int n){ int i,temp[4]; temp[0]=midkey2[0]; temp[1]=midkey2[1]; temp[2]=midkey2[28]; temp[3]=midkey2[29]; if(movebit==2){ for(i=0;i<26;i++){ midkey2[i]=midkey2[i+2]; midkey2[i+28]=midkey2[i+30]; } midkey2[26]=temp[0];midkey2[27]=temp[1]; midkey2[54]=temp[2];midkey2[55]=temp[3]; } else { for(i=0;i<27;i++){ midkey2[i]=midkey2[i+1]; midkey2[i+28]=midkey2[i+29]; } midkey2[27]=temp[0];midkey2[55]=temp[2]; } for(i=0;i<48;i++) key[n][i]=midkey2[PC2[i]-1]; } void EncodeData(int *lData,int *rData,int *str){ //encodedata function int i,j,temp[8],lint,rint;//int h; int data[64]; lint=0,rint=0; for(i=0;i<4;i++){ j=0; while(str[i]!=0){ temp[j]=str[i]%2; str[i]=str[i]/2; j++; } while(j<8)temp[j++]=0; for(j=0;j<8;j++) lData[lint++]=temp[7-j]; j=0; while(str[i+4]!=0){ temp[j]=str[i+4]%2; str[i+4]=str[i+4]/2; j++; } while(j<8)temp[j++]=0; for(j=0;j<8;j++)rData[rint++]=temp[7-j]; } for(i=0;i<32;i++){ data[i]=lData[i]; data[i+32]=rData[i]; } for(i=0;i<32;i++){ lData[i]=data[IP1[i]-1];//printf("P1:%5d:%5d,%5d\n",IP1[i],lData[i],data[IP1[i]-1]); rData[i]=data[IP1[i+32]-1]; } } void F(int *rData,int *key){ //F function int i,rDataP[48]; Expand(rData,rDataP); for(i=0;i<48;i++){ rDataP[i]=rDataP[i]^key[i];// printf("%10d",rDataP[i]);if((i+1)%6==0)printf("\n"); } ExchangeS(rDataP,rData); ExchangeP(rData); } void Expand(int *rData,int *rDataP){ //Expand function int i; for(i=0;i<48;i++) rDataP[i]=rData[Ex[i]-1]; } void ExchangeS(int *rDataP,int *rData){ //S-diagram change int i,n,linex,liney; linex=liney=0; for(i=0;i<48;i+=6){ n=i/6; //printf("%10d\n",(rDataP[i]<<1)); linex=(rDataP[i]<<1)+rDataP[i+5]; liney=(rDataP[i+1]<<3)+(rDataP[i+2]<<2)+(rDataP[i+3]<<1)+rDataP[i+4]; FillBin(rData,n,s[n][linex][liney]); } } void ExchangeP(int *rData){ //P change int i,temp[32]; for(i=0;i<32;i++) temp[i]=rData[i]; for(i=0;i<32;i++) rData[i]=temp[P[i]-1]; } void FillBin(int *rData,int n,int s){ // data to binary;call by S-Diagram change function int temp[4],i; for(i=0;i<4;i++){ temp[i]=s%2; s=s/2; } for(i=0;i<4;i++) rData[n*4+i]=temp[3-i]; } void DecodeData(int *str,int *lData,int *rData){ //DecodeData from binary int i;int a,b;int data[64]; a=0,b=0; for(i=0;i<32;i++){ data[i]=lData[i]; data[i+32]=rData[i]; } for(i=0;i<32;i++){ lData[i]=data[IP2[i]-1]; rData[i]=data[IP2[i+32]-1]; } for(i=0;i<32;i++){ a=(lData[i]&0x1)+(a<<1); b=(rData[i]&0x1)+(b<<1); if((i+1)%8==0){ str[i/8]=a;a=0;//printf("%d",i/8); str[i/8+4]=b;b=0;//printf("%d",i/8+4); } } } void Encode(int *str,int *keychar){ //encode: input 8 chars,8 keychars int lData[32],rData[32],temp[32],rDataP[48]; int i,j; keyBuild(keychar); EncodeData(lData,rData,str); for(i=0;i<16;i++){ for(j=0;j<32;j++) temp[j]=rData[j]; F(rData,key[i]); for(j=0;j<32;j++){ rData[j]=rData[j]^lData[j]; } for(j=0;j<32;j++) lData[j]=temp[j]; } DecodeData(str,rData,lData); } void Decode(int *str,int *keychar){ //decode :input 8 chars,8 keychars int lData[32],rData[32],temp[32],rDataP[48]; int i,j; keyBuild(keychar); EncodeData(lData,rData,str); //这个位置 for(i=0;i<16;i++){ for(j=0;j<32;j++) temp[j]=rData[j]; F(rData,key[15-i]); for(j=0;j<32;j++){ rData[j]=rData[j]^lData[j]; } for(j=0;j<32;j++){ lData[j]=temp[j]; } } DecodeData(str,rData,lData); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值