首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

请问CryptAPI加密字符串的有关问题(初学者伸手贴)

2012-12-17 
请教CryptAPI加密字符串的问题(菜鸟伸手贴)本帖最后由 cainiaotiwen 于 2012-12-07 14:00:55 编辑初学MFC

请教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("加密成功");                               }  


你加密这块就错了.
加密后的数据是二进制der编码,不能使用strlen来获取编码的长度,你可以把加密后的der编码转成base64编码,来进行存储.
解密的方法我没有看,应该同样的道理  先把base64编码转der编码 在解密.

你看看这2个函数:CryptBinaryToString der编码转base64字符串
                 CryptStringToBinary base64字符串转der编码
具体参见msdn说明.

热点排行