VC实现数据的加密和解密
由于生产实习的时间有限,加上自己这段时间致力于考研,因此,仅仅是实现了通过MD5/DES/RSA的简单的字符串的加密解密,希望有兴趣的兄弟姐妹能够完善它。
主要的程序如下:
1)、MD5
// MD5.h: interface for the CMD5 class.
//
//
#if !defined(AFX_MD5_H__EA6A200B_1336_43F3_B866_2A2E28D54560__INCLUDED_)
#define AFX_MD5_H__EA6A200B_1336_43F3_B866_2A2E28D54560__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//测试判别:摘自http://www.ietf.org/rfc/rfc1321.txt
/*
MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
d174ab98d277d9f5a5611c2c9f419d9f
MD5 ("123456789012345678901234567890123456789012345678901234567890123456
78901234567890") = 57edf4a22be3c955ac49da2e2107b67a
*/
//补充MD5算法是不可逆的算法,也就是说不存在解密,惟有暴力解密才可以解密。 该算法主要是对摘要进行加密
//主要是用于用户口令的加密,例如:UNIX里面用户口令保存都是也MD5加密后进行存储,当用户登录时,首先要对输
//入的口令进行MD5进行加密,然后再和存储的MD5加密用户口令进行比较
#include <string>
using namespace std;
class CMD5
{
public:
//CONSTRUCTOR
CMD5();
//对基类的虚函数进行实现
void AddData(char const* pcData, int iDataLength);
void FinalDigest(char* pcDigest);
void Reset();
void DigestFile(string const& readFile, char* pcDigest);
virtual ~CMD5();
protected:
//设置附上64位的消息长度
enum { BLOCKSIZE=64 };
BOOL m_bAddData;
private:
//总共要经过4轮变换
enum { MD128LENGTH=4 };
//设定每次读取文件长度长度为1024位,数据长度为384(可以i自己设定)
enum { DATA_LEN=384, BUFF_LEN=1024 };
//四个32-位的变量,数值必须为正整数,就是A,B,C,D
unsigned int m_auiBuf[4];
unsigned int m_auiBits[2];
//获取M0-〉M64消息的64个子分组
unsigned char m_aucIn[64];
//主循环要经过四轮变换,第一轮要经过16次操作,都是由下面的基本运算组成
static unsigned int F(unsigned int x, unsigned int y, unsigned int z);
static unsigned int G(unsigned int x, unsigned int y, unsigned int z);
static unsigned int H(unsigned int x, unsigned int y, unsigned int z);
static unsigned int I(unsigned int x, unsigned int y, unsigned int z);
//对FF,GG,HH,II函数进行定义
//具体的参数说明:第一个参数为:F1、F2、F3、F4方法的选择,第二个参数为:运算的结果,即初始化的参数
//第三、四、五个参数为初始化的参数,具体为a,b,c,d中的不同的三个,第六个参数为:消息的第J个子分组,第七个参数为循环左移S位
static void MD5STEP(unsigned int (*f)(unsigned int x, unsigned int y, unsigned int z),
unsigned int& w, unsigned int x, unsigned int y, unsigned int z, unsigned int data, unsigned int s);
//MD5四轮变换算法,具体是对四轮中的每一轮进行16次运算
void MD5Transform();
};
//具体的函数可以参考http://www.ietf.org/rfc/rfc1321.txt,The MD5 Message-Digest Algorithm(MD5摘要加密算法)
//第一个非线性函数,即所谓的F函数:F(X,Y,Z) = (X&Y)|((~X)&Z)
inline unsigned int CMD5::F(unsigned int x, unsigned int y, unsigned int z)
{
return (x & y | ~x & z);
}
//第二个非线性函数,即所谓的G函数:G(X,Y,Z) = (X&Z)|(Y&(~Z))
inline unsigned int CMD5::G(unsigned int x, unsigned int y, unsigned int z)
{
return F(z, x, y);
}
//第三个非线性函数,即所谓的H函数:H(X,Y,Z) = X XOR Y XOR Z
inline unsigned int CMD5::H(unsigned int x, unsigned int y, unsigned int z)
{
return x ^ y ^ z;
}
//第四个非线性函数,即所谓的I函数:I(X,Y,Z) = Y XOR (X | (~Z))
inline unsigned int CMD5::I(unsigned int x, unsigned int y, unsigned int z)
{
return (y ^ (x | ~z));
}
//
inline void CMD5::MD5STEP(unsigned int (*f)(unsigned int x, unsigned int y, unsigned int z),
unsigned int& w, unsigned int x, unsigned int y, unsigned int z, unsigned int data, unsigned int s)
{
w += f(x, y, z) + data;
w = w << s | w >> (32-s);
w += x;
}
#endif // !defined(AFX_MD5_H__EA6A200B_1336_43F3_B866_2A2E28D54560__INCLUDED_)
// MD5.cpp: implementation of the CMD5 class.
//
//
#include "stdafx.h"
#include "EncryAndDecrypt.h"
#include "MD5.h"
#include "FileBuffer.h"
#include <fstream>
#include <strstream>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//
// Construction/Destruction
//
//初始化变量值
CMD5::CMD5():m_bAddData(false)
{
//对四个32位的变量进行初始化
m_auiBuf[0] = 0x67452301;
m_auiBuf[1] = 0xefcdab89;
m_auiBuf[2] = 0x98badcfe;
m_auiBuf[3] = 0x10325476;
m_auiBits[0] = 0;
m_auiBits[1] = 0;
}
CMD5::~CMD5()
{
}
void CMD5::AddData(char const* pcData, int iDataLength)
{
if(iDataLength < 0)
AfxMessageBox("MD5文件加密失败!,数据的长度必须大于0");
unsigned int uiT;
//更新位长度
uiT = m_auiBits[0];
//参考MD5Update函数
if((m_auiBits[0] = uiT + ((unsigned int)iDataLength << 3)) < uiT)
m_auiBits[1]++;
m_auiBits[1] += iDataLength >> 29;
uiT = (uiT >> 3) & (BLOCKSIZE-1); //转化为字节
//处理奇数块
if(uiT != 0)
{
unsigned char *puc = (unsigned char *)m_aucIn + uiT;
uiT = BLOCKSIZE - uiT;
if(iDataLength < uiT)
{
memcpy(puc, pcData, iDataLength);
return;
}
memcpy(puc, pcData, uiT);
MD5Transform();
pcData += uiT;
iDataLength -= uiT;
}
//处理长度为64字节数据块
while(iDataLength >= BLOCKSIZE)
{
memcpy(m_aucIn, pcData, BLOCKSIZE);
MD5Transform();
pcData += BLOCKSIZE;
iDataLength -= BLOCKSIZE;
}
//处理余下的数据
memcpy(m_aucIn, pcData, iDataLength);
//设置标志位
m_bAddData = true;
}
void CMD5::FinalDigest(char* pcDigest)
{
if(m_bAddData == false)
AfxMessageBox("MD5文件加密失败!,没有数据被添加");
unsigned int uiCount;
unsigned char* puc;
//参考MD5Update函数
//计算字节对64取余运算
uiCount = (m_auiBits[0] >> 3) & (BLOCKSIZE-1);
//参考static unsigned char PADDING[64]~~即对对一个填充位设置为0x80
puc = m_aucIn + uiCount;
*puc++ = 0x80;
//同时要通过填充来达到64个字节
uiCount = BLOCKSIZE - uiCount - 1;
//填充到64位长度
//假如填充的长度未达到64位长度
if(uiCount < 8)
{
//首先要填充前面64个字节
memset(puc, 0, uiCount);
MD5Transform();
//然后要填充后面的56个字节
memset(m_aucIn, 0, BLOCKSIZE-8);
}
//已经达到64位
else
{
//直接填充56个字节
memset(puc, 0, uiCount - 8);
}
//添加位长度同时进行MD5变换
((unsigned int*)m_aucIn)[(BLOCKSIZE>>2)-2] = m_auiBits[0];
((unsigned int*)m_aucIn)[(BLOCKSIZE>>2)-1] = m_auiBits[1];
MD5Transform();
memcpy(pcDigest, m_auiBuf, MD128LENGTH<<2);
//重新设置大小
Reset();
}
void CMD5::Reset()
{
//对四个32位的变量重新设置
m_auiBuf[0] = 0x67452301;
m_auiBuf[1] = 0xefcdab89;
m_auiBuf[2] = 0x98badcfe;
m_auiBuf[3] = 0x10325476;
m_auiBits[0] = 0;
m_auiBits[1] = 0;
//重设标志
m_bAddData = false;
}
//MD5四轮变换算法,具体的64次运算过程如下
void CMD5::MD5Transform()
{
unsigned int* puiIn = (unsigned int*)m_aucIn;
register unsigned int a, b, c, d;
a = m_auiBuf[0];
b = m_auiBuf[1];
c = m_auiBuf[2];
d = m_auiBuf[3];
//第一轮
MD5STEP(F, a, b, c, d, puiIn[0] + 0xd76aa478, 7);
MD5STEP(F, d, a, b, c, puiIn[1] + 0xe8c7b756, 12);
MD5STEP(F, c, d, a, b, puiIn[2] + 0x242070db, 17);
MD5STEP(F, b, c, d, a, puiIn[3] + 0xc1bdceee, 22);
MD5STEP(F, a, b, c, d, puiIn[4] + 0xf57c0faf, 7);
MD5STEP(F, d, a, b, c, puiIn[5] + 0x4787c62a, 12);
MD5STEP(F, c, d, a, b, puiIn[6] + 0xa8304613, 17);
MD5STEP(F, b, c, d, a, puiIn[7] + 0xfd469501, 22);
MD5STEP(F, a, b, c, d, puiIn[8] + 0x698098d8, 7);
MD5STEP(F, d, a, b, c, puiIn[9] + 0x8b44f7af, 12);
MD5STEP(F, c, d, a, b, puiIn[10] + 0xffff5bb1, 17);
MD5STEP(F, b, c, d, a, puiIn[11] + 0x895cd7be, 22);
MD5STEP(F, a, b, c, d, puiIn[12] + 0x6b901122, 7);
MD5STEP(F, d, a, b, c, puiIn[13] + 0xfd987193, 12);
MD5STEP(F, c, d, a, b, puiIn[14] + 0xa679438e, 17);
MD5STEP(F, b, c, d, a, puiIn[15] + 0x49b40821, 22);
//第二轮
MD5STEP(G, a, b, c, d, puiIn[1] + 0xf61e2562, 5);
MD5STEP(G, d, a, b, c, puiIn[6] + 0xc040b340, 9);
MD5STEP(G, c, d, a, b, puiIn[11] + 0x265e5a51, 14);
MD5STEP(G, b, c, d, a, puiIn[0] + 0xe9b6c7aa, 20);
MD5STEP(G, a, b, c, d, puiIn[5] + 0xd62f105d, 5);
MD5STEP(G, d, a, b, c, puiIn[10] + 0x02441453, 9);
MD5STEP(G, c, d, a, b, puiIn[15] + 0xd8a1e681, 14);
MD5STEP(G, b, c, d, a, puiIn[4] + 0xe7d3fbc8, 20);
MD5STEP(G, a, b, c, d, puiIn[9] + 0x21e1cde6, 5);
MD5STEP(G, d, a, b, c, puiIn[14] + 0xc33707d6, 9);
MD5STEP(G, c, d, a, b, puiIn[3] + 0xf4d50d87, 14);
MD5STEP(G, b, c, d, a, puiIn[8] + 0x455a14ed, 20);
MD5STEP(G, a, b, c, d, puiIn[13] + 0xa9e3e905, 5);
MD5STEP(G, d, a, b, c, puiIn[2] + 0xfcefa3f8, 9);
MD5STEP(G, c, d, a, b, puiIn[7] + 0x676f02d9, 14);
MD5STEP(G, b, c, d, a, puiIn[12] + 0x8d2a4c8a, 20);
//第三轮
MD5STEP(H, a, b, c, d, puiIn[5] + 0xfffa3942, 4);
MD5STEP(H, d, a, b, c, puiIn[8] + 0x8771f681, 11);
MD5STEP(H, c, d, a, b, puiIn[11] + 0x6d9d6122, 16);
MD5STEP(H, b, c, d, a, puiIn[14] + 0xfde5380c, 23);
MD5STEP(H, a, b, c, d, puiIn[1] + 0xa4beea44, 4);
MD5STEP(H, d, a, b, c, puiIn[4] + 0x4bdecfa9, 11);
MD5STEP(H, c, d, a, b, puiIn[7] + 0xf6bb4b60, 16);
MD5STEP(H, b, c, d, a, puiIn[10] + 0xbebfbc70, 23);
MD5STEP(H, a, b, c, d, puiIn[13] + 0x289b7ec6, 4);
MD5STEP(H, d, a, b, c, puiIn[0] + 0xeaa127fa, 11);
MD5STEP(H, c, d, a, b, puiIn[3] + 0xd4ef3085, 16);
MD5STEP(H, b, c, d, a, puiIn[6] + 0x04881d05, 23);
MD5STEP(H, a, b, c, d, puiIn[9] + 0xd9d4d039, 4);
MD5STEP(H, d, a, b, c, puiIn[12] + 0xe6db99e5, 11);
MD5STEP(H, c, d, a, b, puiIn[15] + 0x1fa27cf8, 16);
MD5STEP(H, b, c, d, a, puiIn[2] + 0xc4ac5665, 23);
//第四轮
MD5STEP(I, a, b, c, d, puiIn[0] + 0xf4292244, 6);
MD5STEP(I, d, a, b, c, puiIn[7] + 0x432aff97, 10);
MD5STEP(I, c, d, a, b, puiIn[14] + 0xab9423a7, 15);
MD5STEP(I, b, c, d, a, puiIn[5] + 0xfc93a039, 21);
MD5STEP(I, a, b, c, d, puiIn[12] + 0x655b59c3, 6);
MD5STEP(I, d, a, b, c, puiIn[3] + 0x8f0ccc92, 10);
MD5STEP(I, c, d, a, b, puiIn[10] + 0xffeff47d, 15);
MD5STEP(I, b, c, d, a, puiIn[1] + 0x85845dd1, 21);
MD5STEP(I, a, b, c, d, puiIn[8] + 0x6fa87e4f, 6);
MD5STEP(I, d, a, b, c, puiIn[15] + 0xfe2ce6e0, 10);
MD5STEP(I, c, d, a, b, puiIn[6] + 0xa3014314, 15);
MD5STEP(I, b, c, d, a, puiIn[13] + 0x4e0811a1, 21);
MD5STEP(I, a, b, c, d, puiIn[4] + 0xf7537e82, 6);
MD5STEP(I, d, a, b, c, puiIn[11] + 0xbd3af235, 10);
MD5STEP(I, c, d, a, b, puiIn[2] + 0x2ad7d2bb, 15);
MD5STEP(I, b, c, d, a, puiIn[9] + 0xeb86d391, 21);
//将ABCD分别加上abcd,
m_auiBuf[0] += a;
m_auiBuf[1] += b;
m_auiBuf[2] += c;
m_auiBuf[3] += d;
}
void CMD5::DigestFile(string const& readFile, char* pcDigest)
{
//以二进制的形式打开文件中的内容
ifstream Readin(readFile.c_str(), ios::binary);
if(!Readin)//打开失败
{
ostrstream ostr;
ostr<<"打开加密文件失败!"<<endl;
}
//打开文件成功
Reset();
//开始读取文件
char szLargeBuff[BUFF_LEN+1] = {0};
char szBuff[DATA_LEN+1] = {0};
//开始读取数据
CFileBuffer fileRead(Readin, szLargeBuff, BUFF_LEN, DATA_LEN);
int iRead;
//一直读取数据
while((iRead = fileRead.GetData(szBuff)) > 0)
AddData(szBuff, iRead);
//关闭文件
Readin.close();
//对文件进行最后一步进行加密
FinalDigest(pcDigest);
}
2)、RSA:
// RSA.h: interface for the CRSA class.
//
//
#if !defined(AFX_RSA_H__A0CC2413_F410_45CE_911B_7A21D7A5155B__INCL