Des算法的实现

来源:互联网 发布:雨露计划软件下载 编辑:程序博客网 时间:2024/05/29 11:41

  之所以会来写这个,是觉得自己前一段时间一直在找关于DES加密算法的资料,确实有很多代码,但是不同代码得出的结果都不一样。这我就不能忍了,最后还是决定自己去写一份代码。然后就有了现在这个代码。

    其实DES算法理解起来不难的,流程多看几遍也就理解了,要注意的是几个int数组一定不能有数据出错,我就是这么被坑了。。。。

  找资料的时候有一张图,一直受用,很清晰介绍DES加密的算法:





  废话不多说,下面上代码,我是用makefile管理和编译代码,所以文件分得会细一点,读者可以把几个.c文件都放到一个.c文件中,这样就可以实现单文件了。(用一个文件 可以跳过makefile的部分)

  文件结构如下图:




    首先是makefile文件。

main:main.o changeStr.o round.o doDes.occ -g -o $@ $^main.o:main.ccc -g -c $<changeStr.o:changeStr.ccc -g -c $<round.o:round.ccc -g -c $<doDes.o:doDes.ccc -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_LOG0//字符及字符串转换类函数,changeStr.c中定义int changeAscToInt(char ch);//十六进制ASC码转换成Int类型,'2'->2,'A'->10char changeIntToAsc(int a);//十进制转换成字符2>"02",10->"8F"int changeStrAscToHex(char *asc,char *hex,int len);//"ABC123"-->0xABC123,压缩成半长intchangeStrHexToAsc(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长度的ASC字符串,并转换成len/2长度的hex字符串#endif
  几个字符串进制转换的函数,和输出调试的接口changeStr.c如下:

  

#include <stdio.h>#include <stdlib.h>#include <string.h>#include "def.h"//十六进制ASC码转换成Int类型,'2'->2,'A'->10int changeAscToInt(char ch){    int ret = 0;    if(ch>='A' && ch<='Z'){        ret = ch-'A'+10;    }if(ch>='a' && ch<='z'){        ret = ch-'a'+10;    }    else if(ch>='0' && ch<='9'){        ret = ch-'0';    }    else{    ret = '\0';    }    return ret;}//十进制转换成字符0x02->'2',0x0f->'F'char changeIntToAsc(int a){char ret = 0;    if(a>=10 && a<=15){        ret = a-10+'A';    }else if(a>=0 && a<=9){        ret = a+'0';    }else{    ret = '\0';    }    return ret;}//将ASC字符串转换成HEX字符串int changeStrAscToHex(char *asc,char *hex,int len){int i,j;char high,low;if(len%2 != 0)//只处理偶数长度的ASCII字符串{hex[0] = '\0';return -1;}for(i=0,j=0; i<len; i+=2){high = changeAscToInt(asc[i]);low = changeAscToInt(asc[i+1]);hex[j++] = (high<<4)+low;//printf("high=%02x,low=%02x,hex=%02x\n",high,low,hex[j-1]);}return 0;}//将HEX字符串转换成ASC字符串,0x02->"02",0x8F->"8F"int changeStrHexToAsc(char *hex,char *asc,int len){int i,j;char high,low;int tmp=0;for(i=0,j=0; i<len; i++){tmp = 0;low = (int)hex[i]&0x0F;tmp = hex[i]&0xF0;//high = hex[i]>>4;会出错high = tmp>>4;asc[j++] = changeIntToAsc(high);asc[j++] = changeIntToAsc(low);}return 0;}// 如changeIntToIntBit(arr,0,4,27);27=(00011011),arr[0]=1,arr[1]=0,arr[2]=1,arr[3]=1int changeIntToIntArray(int *to, int begin, int len, int n)  {int i,j,pos;for(i=begin+len-1;i>=begin;i--){to[i] = n%2;n = n>>1;}}// 如changeHexStrToIntBit(hex,a,4);*hex="AB12"--->a[0-15]=1010,1011,0001,0010void changeHexStrToIntArray(char *hex, int *in, int len){char ch;int i,j,pos,value;for(i=0,j=0;i<len; i++,j+=4){//取出一个ch类型,并获得其十进制值0-15ch = hex[i];if(ch>='A' && ch<='Z'){        value = ch-'A'+10;    }else if(ch>='a' && ch<='z'){        value = ch-'a'+10;    }else if(ch>='0' && ch<='9'){        value = ch-'0';    }else{    value = '\0';    }    //将十进制数转换并存储到int数组中    for(pos=3; pos>=0; pos--){    in[j+pos] = value%2;    value = value>>1;    }}  }// 如changeHexStrToIntBit(a,hex,16);a[0-15]=1010,1011,0001,0010--->hex[0-3]="AB12"void changeIntArrayToHexStr(int *in, char *hex, int len){int i,j;int n;int out;n = len/4;for(i=0; i<n; i++){j = i*4;out = 0;out = (in[j]<<3)+(in[j+1]<<2)+(in[j+2]<<1)+in[j+3];if(out>=0&&out<=9){out = out + '0';}else if(out>=10&&out<=15){out = out -10 + 'A';}else{out = '\0';}hex[i] = out;}}void print_intArraybyHex(char *title,int *in,int len){char hex[100];hex[len/4] = '\0';changeIntArrayToHexStr(in,hex,len);printf("%-15s%s\n",title,hex);}
  然后是DES处理过程中的解密流程round.c:

  

#include <stdio.h>#include <stdlib.h>#include <string.h>#include "def.h"//密钥循环左移时的左移数目表const static int loopTable[16] ={    1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};//s-box运算盒子,/* S1~S8盒 */const static int 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 } },    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 } },    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 } },    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 } },    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 } },    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 } },    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 } },    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 } };/* 置换函数 */void exchange(int *from, int *to, const int *rule,int n){int i, j;  //计数的i,jfor (i = 0; i < n; i++){j = rule[i];//根据rule数组进行置换,也就是赋值to[i] = from[j-1];}return;}//左右半部分别循环左移void key28MoveByTimes(int key[28], int times){int i;int bit26,bit27;//缓存移1位和移2位时差异的后2位int n = loopTable[times];//标记要移位的位数bit26 = key[ (n+26)%28 ];//末两个特殊位处理bit27 = key[ (n+27)%28 ];for(i=0; i<26; i++)//移1位或者2位时,左右半部前26位都是要移的,先处理{key[i] = key[i+n];}key[26] = bit26;key[27] = bit27;}/* 异或函数 */void xorInt(int *to, int *comp,int len){int i;  //计数的i,没什么大的含义for (i = 0; i < len; i++){if (to[i] != comp[i])  //两数相同结果取0,两数不同取1to[i] = 1;elseto[i] = 0;}}/* S盒运算函数 8个S盒,每执行一次,输入数据偏移6位,每执行一次,输出数据偏移4位,第0位与第5位决定行下标,第1、2、3、4位决定列下标,把找到的每个点数据换为4位的二进制  */void do_sbox(int sbox1_r32[32],int right48[48]){int i;//计数的i,没什么大的含义;int hang,lie,jie;  //hang是S盒的行下标;lie是S盒的列下标;jie是根据行、列下标查询出的结果for (i = 0; i < 8; i++){//第0位与第5位决定行下标,第1、2、3、4位决定列下标hang = right48[i*6]*2 + right48[i*6+5];  lie = right48[ i*6+1 ]*8 + right48[ i*6+2 ]*4 + right48[ i*6+3 ]*2 + right48[ i*6+4 ];  switch (i)  //第i个数查询Si盒{case 0:jie = s1[hang][lie]; break;case 1:jie = s2[hang][lie]; break;case 2:jie = s3[hang][lie]; break;case 3:jie = s4[hang][lie]; break;case 4:jie = s5[hang][lie]; break;case 5:jie = s6[hang][lie]; break;case 6:jie = s7[hang][lie]; break;case 7:jie = s8[hang][lie]; break;}// printf("%04d",jie);printf("\n");changeIntToIntArray(sbox1_r32,i*4,4,jie);//S盒为十六进制,须转换回二进制进行存放}}  
<pre name="code" class="cpp">最后是几个测试用例doDes.c:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include "def.h"const static int tb_excg_m_IP[64] = {     //tb_excg_m_IP是明文处理的置换1 (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 static int tb_excg_m_IPBack[64] = {  //tb_excg_m_IPBack是明文处理的置换3(IP^-1表)      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 static int e[48] = {                 //e是明文处理的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 static int tb_excg_m32[32] = {       //tb_excg_m32是明文处理右半部经S盒转化华的置换表(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 static int tb_excg_key64To56[56] = {          //tb_excg_key64To56是密钥处理的置换1,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 static int tb_excg_key56To48[48] = {         //tb_excg_key56To48是密钥处理的置换2,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 };void <span style="white-space:pre"></span>doSingleDes(char* in_data, char*key_data, char *out_data, int doDesType){  <span style="white-space:pre"></span>int   in[64],mIp[64],mRound[64];<span style="white-space:pre"></span>//明文IP置换后的数组  <span style="white-space:pre"></span>int   left[32],right32[32],right48[48];   //明文的L部分,明文右部的32位和48位数组  <span style="white-space:pre"></span>int   key[64],k56[56],k48[16][48];              <span style="white-space:pre"></span>//k56,k48密钥置换处理需要的缓存数组  <span style="white-space:pre"></span>int   sbox1_r32[32],sbox2_r32[32];        //s_box操作中的中间变量  <span style="white-space:pre"></span>int   out[64];  <span style="white-space:pre"></span>int <span style="white-space:pre"></span>i,j;  <span style="white-space:pre"></span>changeHexStrToIntArray(in_data,in,16);<span style="white-space:pre"></span>//输入的16位数据转换成64位int数组  <span style="white-space:pre"></span>changeHexStrToIntArray(key_data,key,16);<span style="white-space:pre"></span>//16位密钥数据转换成64位int数组  <span style="white-space:pre"></span>//密钥置换成56位,明文IP置换<span style="white-space:pre"></span>  <span style="white-space:pre"></span>exchange(key,k56,tb_excg_key64To56,56);<span style="white-space:pre"></span>//密钥第一次置换后的56位数组  <span style="white-space:pre"></span>exchange(in,mIp,tb_excg_m_IP,64);  <span style="white-space:pre"></span>//明文IP置换后的64位数组  <span style="white-space:pre"></span>//取明文左右半部  <span style="white-space:pre"></span>i = sizeof(int)*32;  <span style="white-space:pre"></span>memcpy(left, mIp, i);                  //取左半部  <span style="white-space:pre"></span>memcpy(right32, mIp+32, i);            //取右半部#if PRINT_LOG<span style="white-space:pre"></span>//打印调试  <span style="white-space:pre"></span>print_intArraybyHex("密钥原数据:",key,64);print_intArraybyHex("密钥置换56:",k56,56);  <span style="white-space:pre"></span>print_intArraybyHex("明文原数据:",in,64);  <span style="white-space:pre"></span>print_intArraybyHex("明文置换P1左半部:",left,32);print_intArraybyHex("明文置换P1右半部:",right32,32);#endif  //因为加密解密的过程,差别在于子密钥使用顺序的不同,所以可以先生成子密钥,  <span style="white-space:pre"></span>for(j=0; j<16; j++)  <span style="white-space:pre"></span>{  <span style="white-space:pre"></span>key28MoveByTimes(k56,j);<span style="white-space:pre"></span>  //左移    <span style="white-space:pre"></span>key28MoveByTimes(k56+28,j);    <span style="white-space:pre"></span>exchange(k56,k48[j],tb_excg_key56To48,48); <span style="white-space:pre"></span>//密钥压缩成48位,生成子密钥 #if PRINT_LOG      <span style="white-space:pre"></span>print_intArraybyHex("子密钥:   ",k48[j],48);    #endif  <span style="white-space:pre"></span>}  <span style="white-space:pre"></span>//16次循环运算  <span style="white-space:pre"></span>for(j=0; j<16; j++)     <span style="white-space:pre"></span>{  <span style="white-space:pre"></span>exchange(right32,right48,e,48);   <span style="white-space:pre"></span>//明文进行e盒扩展置换运算,从32位扩展到48位 #if PRINT_LOG      <span style="white-space:pre"></span>printf("\n第%d次循环操作:\n",j);      <span style="white-space:pre"></span>print_intArraybyHex("明文e盒32-48:",right48,48);#endif   <span style="white-space:pre"></span>if(doDesType == 1)<span style="white-space:pre"></span>//加密,用的密钥是k0,k1,...,k15   <span style="white-space:pre"></span>{   <span style="white-space:pre"></span>xorInt(right48, k48[j],48);<span style="white-space:pre"></span>//经过密钥置换2运算后的子密钥与从e盒出来的子明文异或    <span style="white-space:pre"></span>}   <span style="white-space:pre"></span>else<span style="white-space:pre"></span>//解密,,用的密钥是k15,k14,...,k0   <span style="white-space:pre"></span>{   <span style="white-space:pre"></span>xorInt(right48, k48[15-j],48);   <span style="white-space:pre"></span>}      <span style="white-space:pre"></span>do_sbox(sbox1_r32, right48);<span style="white-space:pre"></span>//调用s盒运算函数,对扩展成48位后的明文右半部进行运算,并压缩回32位      <span style="white-space:pre"></span>exchange(sbox1_r32,sbox2_r32,tb_excg_m32,32);<span style="white-space:pre"></span>//明文右半部再次置换P-置换 #if PRINT_LOG      <span style="white-space:pre"></span>print_intArraybyHex("明文e盒32-48:",right48,48);      <span style="white-space:pre"></span>print_intArraybyHex("密钥明文异或:",right48,48);       <span style="white-space:pre"></span>print_intArraybyHex("明文S盒48-32:",sbox1_r32,32);      <span style="white-space:pre"></span>print_intArraybyHex("明文S盒P置换:",sbox2_r32,32);#endif      <span style="white-space:pre"></span>//原左半与右半异或成新的右半,原右半成新一轮左半      <span style="white-space:pre"></span>xorInt(sbox2_r32,left,32);    <span style="white-space:pre"></span>//sbox2_r32作为新的右半缓存区      <span style="white-space:pre"></span>memcpy(left,right32,sizeof(int)*32);<span style="white-space:pre"></span>//左右半部赋值,第二轮准备      <span style="white-space:pre"></span>memcpy(right32,sbox2_r32,sizeof(int)*32);         <span style="white-space:pre"></span>#if PRINT_LOG      <span style="white-space:pre"></span>print_intArraybyHex("明文的异或:",sbox2_r32,32);      <span style="white-space:pre"></span>i = sizeof(int)*32;memcpy(mRound,left,i);memcpy(mRound+32,right32,i);      <span style="white-space:pre"></span>print_intArraybyHex("此轮密文:",mRound,64);#endif  <span style="white-space:pre"></span>}  <span style="white-space:pre"></span>//取出最后一次没有进行循环重组前的数据,进行IP^-1逆置换  <span style="white-space:pre"></span>i = sizeof(int)*32;<span style="white-space:pre"></span>  <span style="white-space:pre"></span>memcpy(mRound,right32,i);  <span style="white-space:pre"></span>memcpy(mRound+32,left,i);  <span style="white-space:pre"></span>exchange(mRound,out,tb_excg_m_IPBack,64);<span style="white-space:pre"></span>//进行IP^-1逆置换  <span style="white-space:pre"></span>changeIntArrayToHexStr(out, out_data, 64);#if PRINT_LOG  <span style="white-space:pre"></span>print_intArraybyHex("合并左右半部:",mRound,64);    print_intArraybyHex("DES加密后密文:",out,64);#endif  }/*那么,双倍长3DES的加密方法为:DES( DATA, LK, TMP1 );UDES( TMP1, RK, TMP2 );DES( TMP2, LK, DEST );DEST是最终得到的密文。具体过程简述如下:1)使用密钥的前16字节,对数据DATA进行加密,得到加密的结果TMP1;2)使用密钥的后16字节,对第一的计算结果TMP1,进行解密,得到解密的结果TMP2;3)再次使用密钥的前16字节,对第二次的计算结果TMP2,进行加密,得到加密的结果DEST。DEST就为最终的结果。*/// void <span style="white-space:pre"></span>doDoubleDes(int in[64], int key[64], int out[64], int doDesType)// {// }void <span style="white-space:pre"></span>doDoubleDes(char* in_data, char*key_data, char *out_data, int doDesType){<span style="white-space:pre"></span>char lkey[16],rkey[16];<span style="white-space:pre"></span>char tmp1[16],tmp2[16];<span style="white-space:pre"></span>//获取左右密钥<span style="white-space:pre"></span>memcpy(lkey, key_data, 16);<span style="white-space:pre"></span>memcpy(rkey, key_data+16, 16);  if(doDesType==1)        //加密  {    //左密钥加密数据到tmp1    doSingleDes(in_data, lkey, tmp1, 1);    //右密钥解密数据到tmp2    doSingleDes(tmp1, rkey, tmp2, 0);    //用左密钥加密tmp2到输出缓冲区    doSingleDes(tmp2, lkey, out_data, 1);  }<span style="white-space:pre"></span>else  {    doSingleDes(in_data, lkey, tmp1,0);    //用左Key解密    doSingleDes(tmp1, rkey, tmp2, 1);  //用右Key加密    doSingleDes(tmp2, lkey, out_data,0);//用左Ke解密  }}/*对于三倍长3DES,密钥长度的为48字节长。可以分为LK(密钥的左边16字节),CK(密钥的中间16字节),RK(密钥的左边16字节)。与二倍长3DES的加密过程基本相同,只是第一次计算,使用密钥LK;第二次计算,使用密钥CK;第三次计算,使用密钥LK。基本过程如下:DES( DATA, LK, TMP1 );UDES( TMP1, CK, TMP2 );DES( TMP2, RK, DEST );*/void  doTripleDes(char* in_data, char*key_data, char *out_data, int doDesType){  char lkey[16],ckey[16],rkey[16];  char tmp1[16],tmp2[16];  //获取左中右密钥  memcpy(lkey, key_data, 16);  memcpy(ckey, key_data+16, 16);  memcpy(rkey, key_data+32, 16);  if(doDesType==1)        //加密  {    //左密钥加密数据到tmp1    doSingleDes(in_data, lkey, tmp1, 1);    //右密钥解密数据到tmp2    doSingleDes(tmp1, ckey, tmp2, 0);    //用左密钥加密tmp2到输出缓冲区    doSingleDes(tmp2, rkey, out_data, 1);  }  else  {    doSingleDes(in_data, rkey, tmp1,0);    //用左Key解密    doSingleDes(tmp1, ckey, tmp2, 1);  //用右Key加密    doSingleDes(tmp2, lkey, out_data,0);//用左Ke解密  }}
  文件有点长,因为废话比较多,希望不影响阅读。对应我还写了一个QT的有界面的小程序,需要代码可以私聊。







0 0
原创粉丝点击