请教CryptAPI加密字符串的问题(菜鸟伸手贴)
本帖最后由 cainiaotiwen 于 2012-12-07 14:00:55 编辑 初学MFC不久,想要做一个利用CryptAPI加密字符串的MFC对话框程序(不使用Unicode库),主要功能为文本框1输入不限制长度的待加密文本,文本框2输入密码,点击“加密”按钮,在文本框3显示加密后的16进制文本,点击“解密”按钮,读取已经加密的16进制文本,进行解密后输出到文本框4。
从网上参考了些资料后编写如下代码,加密成功,解密失败。执行代码虽然提示加密成功,但加密过程中bl = CryptEncrypt(hCryptKey, 0, TRUE, 0, (BYTE*)szEntry, &dwLenOut,dwLenIn*2);取dwLenIn*2似乎存在问题;解密过程中DWORD dwLenIn = strlen(szEntry);DWORD dwLenOut=dwLenIn;取值似乎也有问题,请高人指点,最好能贴出完整代码,本人实在太菜,纯伸手帖,谢谢!
// JiaMiDlg.cpp : 实现文件
#include "stdafx.h"
#include "JiaMi.h"
#include "JiaMiDlg.h"
#include <wincrypt.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
HCRYPTHASH hCryptHash = NULL;
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hCryptKey = NULL;
CString sPassword, sSource, sDestination;
BOOL CJiaMiDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE);// 设置大图标
SetIcon(m_hIcon, FALSE);// 设置小图标
// TODO: 在此添加额外的初始化代码
SetValue(); //设置文本框文本
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CJiaMiDlg::SetValue(void)
{
GetDlgItem(IDC_EDIT1)->SetWindowTextA("TestString");
GetDlgItem(IDC_EDIT2)->SetWindowTextA("12345678");
}
void CJiaMiDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
GetDlgItem(IDC_EDIT1)->GetWindowTextA(sSource);
GetDlgItem(IDC_EDIT2)->GetWindowTextA(sPassword);
if(CryptAcquireContext(&hCryptProv,NULL,NULL,PROV_RSA_FULL,0))
{
if(CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hCryptHash))
{
char *szHash;
szHash = (char*)malloc(sPassword.GetLength()+1);
strcpy_s(szHash,sPassword.GetLength()+1,sPassword.GetBuffer());
DWORD dwLen=strlen(szHash);
CryptHashData(hCryptHash, (BYTE*)szHash, dwLen, 0);//哈希数据
CryptDeriveKey(hCryptProv, CALG_RC2, hCryptHash, 0, &hCryptKey);//派生密钥
char *szEntry;
szEntry = (char*)malloc(sSource.GetLength()+1);
strcpy_s(szEntry,sSource.GetLength()+1,sSource.GetBuffer());
DWORD dwLenIn = strlen(szEntry)+1;
DWORD dwLenOut=dwLenIn;
bool bl;
DWORD dw;
bl = CryptEncrypt(hCryptKey, 0, TRUE, 0, (BYTE*)szEntry, &dwLenOut,dwLenIn*2);
dw = GetLastError();
if (bl)
{
CString Str, Str1, tmpStr;
for (int i=0; i<strlen(szEntry)+1; i++)
{
tmpStr.Format("%02X", (unsigned char) *(szEntry+i));
Str1 += tmpStr;
}
sDestination = Str1;
AfxMessageBox("加密成功");
}
else
{
sDestination = "加密失败";
AfxMessageBox("加密失败");
}
GetDlgItem(IDC_EDIT3)->SetWindowTextA(sDestination);
CryptDestroyKey(hCryptKey);
}
}
if(hCryptHash!=NULL) CryptDestroyHash(hCryptHash);
if(hCryptProv!=NULL) CryptReleaseContext(hCryptProv,0);
}
void CJiaMiDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
GetDlgItem(IDC_EDIT3)->GetWindowTextA(sSource);
GetDlgItem(IDC_EDIT2)->GetWindowTextA(sPassword);
if(CryptAcquireContext(&hCryptProv,NULL,NULL,PROV_RSA_FULL,0))
{
if(CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hCryptHash))
{
char *szHash;
szHash = (char*)malloc(sPassword.GetLength()+1);
strcpy_s(szHash,sPassword.GetLength()+1,sPassword.GetBuffer());
DWORD dwLen=strlen(szHash);
CryptHashData(hCryptHash, (BYTE*)szHash, dwLen, 0);//哈希数据
CryptDeriveKey(hCryptProv, CALG_RC2, hCryptHash, 0, &hCryptKey);//派生密钥
char *szEntry;
szEntry = (char*)malloc(sSource.GetLength()+1);
strcpy_s(szEntry,sSource.GetLength()+1,sSource.GetBuffer());
//CString转16进制BYTE
CString m_StrByte;
for(int j=0;j<sSource.GetLength()/2;j++)
{
m_StrByte=sSource.Mid(j*2,2); //取两个字符
szEntry[j]=strtol(m_StrByte,NULL,16); //转换存储
}
DWORD dwLenIn = strlen(szEntry);
DWORD dwLenOut=dwLenIn;
bool bl;
DWORD dw;
bl = CryptDecrypt(hCryptKey, 0, TRUE, 0,(BYTE*)szEntry,&dwLenOut);
dw = GetLastError();
if (bl)
{
sDestination = (szEntry);
AfxMessageBox("解密成功");
}
else
{
sDestination = "解密失败";
AfxMessageBox("解密失败");
}
//sDestination = (szEntry); //该句仅供显示对比
GetDlgItem(IDC_EDIT4)->SetWindowTextA(sDestination);
CryptDestroyKey(hCryptKey);
}
}
if(hCryptHash!=NULL) CryptDestroyHash(hCryptHash);
if(hCryptProv!=NULL) CryptReleaseContext(hCryptProv,0);
}
if (bl) { CString Str, Str1, tmpStr; for (int i=0; i<strlen(szEntry)+1; i++) { tmpStr.Format("%02X", (unsigned char) *(szEntry+i)); Str1 += tmpStr; } sDestination = Str1; AfxMessageBox("加密成功"); }