您的位置:首页 > 编程语言 > C语言/C++

信息安全专栏(一)用VC++6.0实现的DES加密工具源码

2006-03-23 15:16 495 查看
实验一:DES加密标准

一:DES算法详述

  DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位,整个算法的主流程图如下:

其功能是把输入的64位数据块按位重新组合,并把输出分为L0、R0两部分,每部分各长32位,其置换规则见下表:

58,50,12,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,

  即将输入的第58位换到第一位,第50位换到第2位,...,依此类推,最后一位是原来的第7位。L0、R0则是换位输出后的两部分,L0是输出的左32位,R0
是右32位,例:设置换前的输入值为D1D2D3......D64,则经过初始置换后的结果为:L0=D58D50...D8;R0=D57D49...D7。

  经过16次迭代运算后。得到L16、R16,将此作为输入,进行逆置换,即得到密文输出。逆置换正好是初始置的逆运算,例如,第1位经过初始置换后,处于第40位,而通过逆置换,又将第40位换回到第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,

放大换位表

  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,

单纯换位表

  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,

  在f(Ri,Ki)算法描述图中,S1,S2...S8为选择函数,其功能是把6bit数据变为4bit数据。下面给出选择函数Si(i=1,2......8)的功能表:

选择函数Si见源程序。
在此以S1为例说明其功能,我们可以看到:在S1中,共有4行数据,命名为0,1、2、3行;每行有16列,命名为0、1、2、3,......,14、15列。

  现设输入为: D=D1D2D3D4D5D6

令:列=D2D3D4D5

  行=D1D6

  然后在S1表中查得对应的数,以4位二进制表示,此即为选择函数S1的输出。下面给出子密钥Ki(48bit)的生成算法

  从子密钥Ki的生成算法描述图中我们可以看到:初始Key值为64位,但DES算法规定,其中第8、16、......64位是奇偶校验位,不参与DES运算。故Key
实际可用位数便只有56位。即:经过缩小选择换位表1的变换后,Key
的位数由64 位变成了56位,此56位分为C0、D0两部分,各28位,然后分别进行第1次循环左移,得到C1、D1,将C1(28位)、D1(28位)合并得到56位,再经过缩小选择换位2,从而便得到了密钥K0(48位)。依此类推,便可得到K1、K2、......、K15,不过需要注意的是,16次循环左移对应的左移位数要依据下述规则进行:

循环左移位数

1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1

  以上介绍了DES算法的加密过程。DES算法的解密过程是一样的,区别仅仅在于第一次迭代时用子密钥K15,第二次K14、......,最后一次用K0,算法本身并没有任何变化。
二:DES算法流程图:



S盒变换示意图:



在要加密的文件的长度不是8的整数倍的时候,需要进行短块处理,加密时短块处理原理的示意图如下(解密时原理相同):



三:功能设计
(1):界面设计



(2):功能介绍
1:打开文件和保存文件用Windows对话框实现和用户的交互;
2:具有加密和解密功能,打开的文件可以是明文也可以是密文,当加密时保存的是密文,解密时保存的是明文。
3:为了安全起见,应该隐藏用户输入的密钥。
4:显示文件大小和加密解密过程所用的时间。

四:源代码
(1):DES_Encrypt.h
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_DES_ENCRYPT_H__0927187A_753E_4DFD_8643_32E1E73B0F83__INCLUDED_)
#define AFX_DES_ENCRYPT_H__0927187A_753E_4DFD_8643_32E1E73B0F83__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class DES_Encrypt

{
private:

static int IP[64]; //IP置换表;

static int IP_1[64];//IP逆置换表;

static int PC_1[56];//生成56位子密钥时的压缩置换表;

static int PC_2[48];//生成48位轮加密密钥时的压缩置换表;

static int P_Replace[32];//P扩展置换;

static int step[16];
//子密钥生成时的移位表;

static int Expansion[48];
//E扩展置换表;

static int BOX[8][64];
//存放S盒置换表;

bool key64[64]; //保存64bit的用户密钥 ;

bool key48[16][48]; //保存经过转换后的16圈子密钥 ;

void ReTransform(bool*word); //解密时的函数变换;

void Transform(bool*word); //加密时的函数变换;

void Tobit(byte*A,bool*B); //将从文件中读取得8个字符转换成64bit二进制数保存在数组中;

void P_Change(bool*A); //P置换

void S_BOX(bool*A,bool*B); //S盒变换;

void XOR(bool*A,bool*B,int size);//异或运算;

void shift(bool*A,int step); //移位函数;

void CreateKey(bool*A); //生成子密钥;

void IP_Replace(bool*A,int*B); //IP置换和IP逆置换函数;

void Exchange(bool*A); //将数组左右交换;

void E_KuoZhan(bool*A,bool*B); //E扩展置换;

void make_key64(CString m_key,bool*key64);//将用户输入的密钥转换成64bit的二进制数;

void writefile(FILE*fp,bool*word); //将加密后的密文或是解密后的明文写入文件;
public:

DES_Encrypt();

virtual ~DES_Encrypt();

void DES_EncyptFile(CString OpenPath,CString SavePath,CString m_key);//加密函数;

void DES_DecryptFile(CString OpenPath,CString SavePath,CString m_key);//解密函数;

};
#endif // !defined(AFX_DES_ENCRYPT_H__0927187A_753E_4DFD_8643_32E1E73B0F83__INCLUDED_)
(2) DES_Encrypt.cpp
// DES_Encrypt.cpp: implementation of the DES_Encrypt class.
//说明:
本类包含DES加密解密的各种操作;
//
用户只需要从接口输入参数即可实现文件的加密解密;
//作者单位:
华中科技大学计算机学院信息安全0304班
//作者姓名:
祝涛
//文档完成日期:
2005年9月16日
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "DES.h"
#include "math.h"
#include "DES_Encrypt.h"

#include <fcntl.h>
#include <io.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

DES_Encrypt::DES_Encrypt()
{

}

DES_Encrypt::~DES_Encrypt()
{

}
int DES_Encrypt::
IP[64]={//初始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};
int
DES_Encrypt:: IP_1[64]={//结束时IP逆置换

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};
int
DES_Encrypt:: PC_1[56]={//由64位的密钥生成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};
int
DES_Encrypt:: PC_2[48]={//由56位的密钥生成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};
int
DES_Encrypt:: step[16]={

1,1,2,2,2,2,2,2,

1,2,2,2,2,2,2,1};
int
DES_Encrypt:: Expansion[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};
int
DES_Encrypt::P_Replace[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};

int
DES_Encrypt:: BOX[8][64]={

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

};

//功能:
实现DES加密的各种变换;
//入口参数:存放要加密的64bit数据的数组头指针;
//出口参数:变换后的64bit数据仍然保存在数组word[64]中
void DES_Encrypt::Transform(bool *word)
{

int times=0;//记录加密的圈数;

bool R_32[32],L_32[32];

bool word_48[48];

IP_Replace(word,IP); //IP置换

while(times<16)

{

for(int i=0;i<32;i++)

R_32[i]=word[32+i];

for(i=0;i<32;i++)

L_32[i]=word[i];

Exchange(word); //将word的右边交换到左边;

E_KuoZhan(R_32,word_48); //将右边32bit扩展成为48bit

XOR(word_48,key48[times],48);//与轮加密子密钥异或

S_BOX(word_48, R_32);

P_Change(R_32);

XOR(R_32,L_32,32);

if(times<15)

{

for(int i=32;i<64;i++) word[i]=R_32[i-32];

}

else

{

for(int i=0;i<32;i++) word[i+32]=word[i];

for(i=0;i<32;i++) word[i]=R_32[i];

}

times++;//记录加密轮数

}

IP_Replace(word,IP_1);//十六圈加密后IP逆置换
}
//功能:
实现DES解密的各种变换;
//入口参数:存放要加密的64bit数据的数组头指针;
//出口参数:变换后的64bit数据仍然保存在数组word[64]中
void DES_Encrypt::ReTransform(bool *word)
{

int times=15; //记录加密的圈数;

bool R_32[32],L_32[32];

bool word_48[48];

IP_Replace(word,IP);

while(times>=0)

{

for(int i=0;i<32;i++)

R_32[i]=word[32+i];

for(i=0;i<32;i++)

L_32[i]=word[i];

Exchange(word);
//将word的右边交换到左边;

E_KuoZhan(R_32,word_48); //将右边32bit扩展成为48bit

XOR(word_48,key48[times],48);

S_BOX(word_48, R_32);

P_Change(R_32);

XOR(R_32,L_32,32);

if(times>0)

{

for(int i=32;i<64;i++)word[i]=R_32[i-32];

}

else

{

for(int i=0;i<32;i++)word[i+32]=word[i];

for(i=0;i<32;i++)word[i]=R_32[i];

}

times--;

}

IP_Replace(word,IP_1); //十六圈加密后IP逆置换
}
//
功能:用DES实现任意格式的文件加密
//入口参数:OpenPath是要加密的文件路径;
//
SavePath是加密后的密文保存路径;
//
m_key是用户的加密密钥;
//出口参数:将加密后的密文保存在目标文件中;
void DES_Encrypt::DES_EncyptFile(CString OpenPath,CString SavePath,CString m_key)
{

int handle=open(OpenPath, O_CREAT);
//得到要加密的文件的长度;

long FileLength=filelength(handle);

close(handle);

if(FileLength==0)return;

long rounds=FileLength/8;//计算要加密的轮数;

int leave=FileLength%8;

if(leave!=0)rounds++;

long copy_rounds=rounds;

FILE*fp1=fopen(OpenPath,"rb");

FILE*fp2=fopen(SavePath,"wb");

make_key64(m_key,key64);

CreateKey(key64); //16圈加密用的48位子密钥都已经生成,

//存放在key64[16][48]中;

bool word[64]; //用来保存64bit的中间信息和最终结果

byte file[8]; //用来存放从文件中读取的八个字节的信息;

byte copy[8];
//短块处理的时候用
if(copy_rounds==1&&leave!=8)
{

fread(file,sizeof(byte),leave,fp1); //如果明文文件的长度是1-7个字节

for(int i=leave;i<8;i++)file[i]=0;

Tobit(file,word);

Transform(word);

writefile(fp2,word);

rounds--;
}

else if(copy_rounds>1&&leave!=0)
//如果明文长度大于8字节而且
{
//不是8字节的整数倍则在文件头

fread(file,sizeof(byte),8,fp1); //用叠加加密的方式进行加密。

Tobit(file,word);

Transform(word);

int k=0;

for(int i=0;i<64; )

{

int ch=0;

for(int j=0;j<8;j++)

{

ch+=word[i++];

ch<<=1;

}

ch/=2;

copy[k++]=ch;

}

fwrite(copy,sizeof(byte),leave,fp2);//将加密后的leave个字节写入fp2为头指针的文件中

int j=0;

for(i=leave;i<8;i++)file[j++]=copy[i];

fread(file+j,sizeof(byte),leave,fp1);//读取leave个字节和前面的密文组合成八个字节后加密

Tobit(file,word);//将数组file中的八个字节转化成64个bit存放在word中

Transform(word);//16圈加密变换

writefile(fp2,word);//将加密后word中存放的64bit密文保存在以fp2为头指针的文件中;

rounds-=2;//轮数减去二是因为已经加密了两轮了;

}
while(rounds)//处理是8字节的整数倍的情况
{

fread(file,sizeof(byte),8,fp1);//读取8个字节到数组file中

Tobit(file,word);//将数组file中的八个字节转化成64个bit存放在word中

Transform(word);//16圈加密变换

writefile(fp2,word);//将加密后word中存放的64bit密文保存在以fp2为头指针的文件中;

rounds--;//加密轮数计数;
}
fclose(fp1);//关闭文件
fclose(fp2);
}

//
功能:用DES对密文的解密
//入口参数:OpenPath是要解密的文件路径;
//
SavePath是解密后的明文保存路径;
//
m_key是用户的解密密钥;
//出口参数:将解密后的明文保存在目标文件中;
void DES_Encrypt::DES_DecryptFile(CString OpenPath,CString SavePath,CString m_key)
{

int handle= open(OpenPath, O_CREAT);
//得到要加密的文件的长度;

long FileLength=filelength(handle);

close(handle);

if(FileLength==0)return;

long rounds=FileLength/8;

int leave=FileLength%8;

if(leave!=0)rounds++;

long copy_rounds=rounds; //计算要加密的轮数;

FILE*fp1=fopen(OpenPath,"rb");

FILE*fp2=fopen(SavePath,"wb");

make_key64(m_key,key64);

CreateKey(key64); //16圈加密用的48位子密钥都已经生成,

//存放在key64[16][48]中;

bool word[64]; //用来存放64bit的解密中间信息和最后结果

byte file[8];

byte copy[8];
//短块处理的时候用作缓存;

if(leave!=0)

{

fread(copy,sizeof(byte),leave,fp1); //不是8字节的整数倍则在文件头

fread(file,sizeof(byte),8,fp1); //用叠加加密的方式进行加密。

Tobit(file,word);//将数组file中的八个字节转化成64个bit存放在word中

ReTransform(word);

int k=0;

byte temp[8];

for(int i=0;i<64; )

{

int ch=0;

for(int j=0;j<8;j++)

{

ch+=word[i++];

ch<<=1;

}

ch>>=1;

temp[k++]=ch;

}

k=0;

for(i=leave;i<8;i++)copy[i]=temp[k++];

Tobit(copy,word);//将数组file中的八个字节转化成64个bit存放在word中

ReTransform(word);//解密时的16圈变换

writefile(fp2,word);//将解密后word中存放的64bit明文保存在以fp2为头指针的文件中;

fwrite(temp+k,sizeof(byte),leave,fp2);

//将经过两次解密后得到的加密时发生叠加加密的部分写入文件

rounds-=2;//轮数减去二是因为已经解密了两轮了;

}
while(rounds)//处理是8字节的整数倍的情况
{

fread(file,sizeof(byte),8,fp1);//从fp1为头指针的文件中读取8个字节到数组file中

Tobit(file,word);//将数组file中的八个字节转化成64个bit存放在word中

ReTransform(word);//解密时的16圈变换

writefile(fp2,word);//将各轮加密的结果转换成字符串保存在文件中;

rounds--;//解密轮数计数
}
fclose(fp1);//关闭文件
fclose(fp2);
}
//功能:
E扩展,将右边的32bit扩展成为48bit

//说明:
本来可以用旋换查表实现的,但是为了提高速度不得不增加代码了;

void DES_Encrypt::E_KuoZhan(bool *A,bool*B)
{

B[0]=A[31]; B[1]=
A[0]; B[2]=A[1]; B[3]=
A[2]; B[4]= A[3];
B[5]=A[4];

B[6]=A[3]; B[7]=
A[4]; B[8]=A[5]; B[9]=
A[6]; B[10]= A[7]; B[11]=A[8];

B[12]=A[7]; B[13]= A[8];
B[14]=A[9]; B[15]=A[10]; B[16]=A[11];
B[17]=A[12];

B[18]=A[11]; B[19]=A[12]; B[20]=A[13]; B[21]=A[14];
B[22]=A[15]; B[23]=A[16];

B[24]=A[15]; B[25]=A[16];
B[26]=A[17]; B[27]=A[18]; B[28]=A[19];
B[29]=A[20];

B[30]=A[19]; B[31]=A[20];
B[32]=A[21]; B[33]=A[22]; B[34]=A[23];
B[35]=A[24];

B[36]=A[23]; B[37]=A[24]; B[38]=A[25]; B[39]=A[26];
B[40]=A[27]; B[41]=A[28];

B[42]=A[27];
B[43]=A[28]; B[44]=A[29]; B[45]=A[30];
B[46]=A[31]; B[47]=A[1];

//扩展后的结果存放在B数组中;返回数组指针
}
//功能:将右边的32bit交换到左边;
void DES_Encrypt::Exchange(bool *A)
{

for(int i=0;i<32;i++) A[i]=A[i+32];

}
//
功能:
初始的时候进行的IP置换;
//入口参数:
置换表B
//
64bit的明密文
void DES_Encrypt::IP_Replace(bool *A,int*B)
{

bool C[64];

for(int i=0;i<64;i++)

C[i]=A[i];//把A拷贝到C

for(i=0;i<64;i++)

{

A[i]=C[B[i]-1];

}
}
//功能:
由64位的密钥生成48位的密钥
//入口参数:
存放64bit密钥的数组头指针B
//出口参数:
子密钥存放在二维数组key48[16][48]中
void DES_Encrypt::CreateKey(bool *B)
{

bool A[56];

for(int i=0;i<56;i++)

A[i]=B[PC_1[i]-1];

bool L_28[28],R_28[28];

for(int k=0;k<16;k++)

{

int i=0;

for(;i<28;i++)

L_28[i]=A[i];

for( ;i<56;i++)

R_28[i-28]=A[i];

shift(L_28,step[k]);

shift(R_28,step[k]);

//将左右的28位合并成56位密钥

for(i=0;i<28;i++)

A[i]=L_28[i];

for(int j=0;j<28;j++,i++)

A[i]=R_28[j];

for(j=0;j<48;j++)

key48[k][j]=A[PC_2[j]-1];//之所以要减一是因为数组下标是从0开始的;

}

}
//功能:
生成子密钥时候进行循环左移;
//入口参数:A是28比特的密钥字;
//
step是移动步长;
void DES_Encrypt::shift(bool *A,int step)
{

bool B[2];

int i=0;

for(;i<step;i++)B[i]=A[i];//拷贝

for(i=0;i<28-step;i++)A[i]=A[i+step];

for(int j=0;j<step;j++)A[i++]=B[j];
}
//功能:
数据与子密钥异或;
void DES_Encrypt::XOR(bool *A, bool *B,int size)
{

for(int i=0;i<size;i++) A[i]^=B[i];
}
//入口参数:
A中存放的是48位的01序列;
//
B用来存放转换后的32位的01序列
void DES_Encrypt::S_BOX(bool *A, bool *B)
{

int X[8];//存放在S盒中的行坐标

int Y[8];//存放在S盒中的列坐标

//以下部分计算下标;

//左移移位相当于乘以2,右移一位相当于除以2,但是移位运算效率更快

//所以程序中乘除一律采用移位运算;

X[0]=A[0];X[0]<<=1;X[0]+=A[5];

Y[0]=A[1];Y[0]<<=1;Y[0]+=A[2]; Y[0]<<=1;Y[0]+=A[3];Y[0]<<=1;Y[0]+=A[4];

X[1]=A[6]; X[1]<<=1;X[1]+=A[11];

Y[1]=A[7]; Y[1]<<=1;Y[1]+=A[8];Y[1]<<=1;Y[1]+=A[9];Y[1]<<=1;Y[1]+=A[10];

X[2]=A[12];X[2]<<=1;X[2]+=A[17];

Y[2]=A[13];Y[2]<<=1;Y[2]+=A[14];Y[2]<<=1;Y[2]+=A[15];Y[2]<<=1;Y[2]+=A[16];

X[3]=A[18];X[3]<<=1;X[3]+=A[23];

Y[3]=A[19];Y[3]<<=1;Y[3]+=A[20];Y[3]<<=1;Y[3]+=A[21];Y[3]<<=1;Y[3]+=A[22];

X[4]=A[24];X[4]<<=1;X[4]+=A[29];

Y[4]=A[25];Y[4]<<=1;Y[4]+=A[26];Y[4]<<=1;Y[4]+=A[27];Y[4]<<=1;Y[4]+=A[28];

X[5]=A[30];X[5]<<=1;X[5]+=A[35];

Y[5]=A[31];Y[5]<<=1;Y[5]+=A[32];Y[5]<<=1;Y[5]+=A[33];Y[5]<<=1;Y[5]+=A[34];

X[6]=A[36];X[6]<<=1;X[6]+=A[41];

Y[6]=A[37];Y[6]<<=1;Y[6]+=A[38];Y[6]<<=1;Y[6]+=A[39];Y[6]<<=1;Y[6]+=A[40];

X[7]=A[42];X[7]<<=1;X[7]+=A[47];

Y[7]=A[43];Y[7]<<=1;Y[7]+=A[44];Y[7]<<=1;Y[7]+=A[45];Y[7]<<=1;Y[7]+=A[46];

int S_data;int k=0;

for(int i=0;i<8;i++)

{

int a;

a=X[i]*16+Y[i];

S_data=BOX[i][a];

B[k+3]=S_data%2;S_data>>=1;

B[k+2]=S_data%2;S_data>>=1;

B[k+1]=S_data%2;S_data>>=1;

B[k]=S_data%2; S_data>>=1;

k+=4;

}
}
//功能:实现P盒置换;
void DES_Encrypt::P_Change(bool *A)
{

bool B[32];

for(int i=0;i<32;i++)

B[i]=A[i];//备份数组;

for(i=0;i<32;i++)

A[i]=B[P_Replace[i]-1];
}

//
功能:
保存明文或是密文;
//入口参数:fp为目标文件的头指针;
//
word存放的是加密后的64bit的密文;
void
DES_Encrypt::writefile(FILE* fp,bool*word)
{

byte temp[8];

int ch,k=0;

for(int i=0;i<64; )

{ //以下将64bit的信息转换成8个字节存在数组temp中

ch=0;

for(int j=0;j<8;j++)

{

ch+=word[i++];

ch<<=1;

}

ch/=2;

temp[k++]=ch;

}
fwrite(temp,sizeof(byte),8,fp);//将temp中的8个字节写入fp为头指针的文件中;
}
//
功能:
将8字节的明文或是密文转换成64比特的二进制数
//入口参数:
存放字符的数组头指针A
//出口参数:
存放64比特二进制数字的bool型数组头指针;
void DES_Encrypt::Tobit(byte *A,bool *B)
{

unsigned __int64 key=0;

for(int i=0;i<7;i++)

{ //将字符串类型的密钥转换成64

key+=A[i];

key=key<<8;

}

key+=A[i];

for(i=63;i>=0;i--)

{

B[i]=key%2; key/=2;

}
}
//功能:
将用户输入的密钥字转换成64比特的二进制数;
//入口参数:
CString m_key 用户输入的密钥
//
key64 用来存放转换后的64bit密钥;
void DES_Encrypt::make_key64(CString m_key,bool*key64)
{

unsigned __int64 key=0;

for(int i=0;i<m_key.GetLength()&&i<8;i++)

{

//将字符串类型的密钥转换成64bit的序列存放在64位的整形数key中

key+=m_key[i];

if(i<7&&i!=(m_key.GetLength()-1))key=key<<8;

}

for(i=63;i>=0;i--)

{ //将64bit的序列中的位信息映射到数组key64中;

if(key%2==0)key64[i]=0;

else key64[i]=1;

key/=2;

}
}

以下为事件处理部分的代码:
void CDESDlg::OnButtonClear() //清除
{

// TODO: Add your control notification handler code here

//清除编辑框中的字符;

UpdateData(true);

m_OpenPath.Empty();

m_SavePath.Empty();

m_key.Empty();

UpdateData(false);
}

void CDESDlg::OnButtonEncrypt() //加密
{

// TODO: Add your control notification handler code here

//加密字符串

UpdateData(true);

if(m_key.GetLength()<8)

{

MessageBox("您输入的密钥长度过短,为了安全起见请您输入八个字母或是数字或符号的组合作为密钥!");

exit(0);

}
int
handle= open(m_OpenPath, O_CREAT); //得到文件的句柄

m_FileLength=filelength(handle);//得到要加密的文件的长度;

close(handle);//关闭文件

m_FileLength/=1000.0;//计算文件的长度,千字节为单位;

UpdateData(false);//更新以将数据显示在编辑框中

MessageBox("哈哈,开始加密了!");

CTime Time1 = CTime::GetCurrentTime() ;//得到加密的起始时间
int t_min1=Time1.GetMinute();
int t_sec1=Time1.GetSecond();

DES_Encrypt p; //申请一个类对象,以这个对象来调用方法进行加密

//入口参数 m_OpenPath :要加密的文件路径

// m_SavePath :密文的保存路径

// m_key :用户密钥

p.DES_EncyptFile(m_OpenPath,m_SavePath, m_key);

CTime Time2 = CTime::GetCurrentTime() ;

int t_min2=Time2.GetMinute();

int t_sec2=Time2.GetSecond();

m_time=60*(t_min2-t_min1)+(t_sec2-t_sec1);//计算加密所用的时间

UpdateData(false);

MessageBox("哈哈,加密已经完成了!");

}

void CDESDlg::OnButtonDeEncrypt() //解密
{

UpdateData(true);
int
handle= open(m_OpenPath, O_CREAT); //得到要解密的文件的句柄;

m_FileLength=filelength(handle);//得到要解密的文件的长度;

close(handle);//关闭文件;

m_FileLength/=1000.0;//计算文件的长度,千字节为单位;

UpdateData(false);//更新以将数据显示在编辑框中

MessageBox("哈哈,开始解密了!");

CTime Time1 = CTime::GetCurrentTime();//得到解密的起始时间;
int
t_min1=Time1.GetMinute();
int
t_sec1=Time1.GetSecond();

DES_Encrypt p; //申请一个对象,通过对象来调用方法实现解密操作

//入口参数 m_OpenPath :要解密的文件路径

// m_SavePath :明文的保存路径

// m_key :用户密钥

p.DES_DecryptFile(m_OpenPath,m_SavePath, m_key);

CTime Time2 = CTime::GetCurrentTime() ;

int t_min2=Time2.GetMinute();

int t_sec2=Time2.GetSecond();

m_time=60*(t_min2-t_min1)+(t_sec2-t_sec1);//计算解密所用的时间

UpdateData(false);

MessageBox("哈哈,解密已经完成了!");

}

void CDESDlg::OnOpenFile() //打开文件
{
UpdateData(true);
//申请一个CFileDialog
类对象

CFileDialog fileselect(TRUE,NULL,NULL,OFN_HIDEREADONLY|

OFN_OVERWRITEPROMPT,"*.txt||",NULL);

fileselect.DoModal();//打开文件对话框;

m_OpenPath=fileselect.GetPathName();//得到文件的长度;

UpdateData(false);//更新将路径和文件长度等显示在编辑框中
}

void CDESDlg::OnSaveFile()//保存文件

{
UpdateData(true);
//申请一个CFileDialog
类对象
CFileDialog fileselect(TRUE,NULL,NULL,OFN_HIDEREADONLY|

OFN_OVERWRITEPROMPT,"*.txt||",NULL);

fileselect.DoModal();//打开文件对话框;

m_SavePath=fileselect.GetPathName();//得到文件的长度;

UpdateData(false);//更新将路径和文件长度等显示在编辑框中
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐