mfc实现哈希Hash算法(MD5和SHA1)加密
2016-02-20 16:19
417 查看
不要存储明文密码,而是存储密码的哈希值
Hash函数我们可以自己用C来编写,但是如果在VC中就不必了,因为在VC中有实现hash算法的 函数可以调用,就是CryptAcquireContext函数,这个函数的定义在wincrypt.h头文件中。下面是我在MFC中实现的,因为想要结果输出到messagebox中,所以就在视类里定义和实现了GetHash函数来计算哈希值。
首先是在View类的头文件中包含下列文件和内容:
#define _WIN32_WINNT 0x0400
#include <tchar.h>
#include <wincrypt.h>
其中我们用到的CryptAcquireContex函数就在wincrypy.h中定义了。
然后我们在View类中定义GetHash函数,函数类型为DWORD类型,参数为:
GetHash(BYTE
*pbData, DWORD dwDataLen, ALG_ID algId, LPTSTR pszHash)
先看一下这个函数几个参数的意义吧.
// 计算Hash,成功返回0,失败返回GetLastError()
// CONST BYTE *pbData, // 输入数据
// DWORD dwDataLen, // 输入数据字节长度
// ALG_ID algId // Hash 算法:CALG_MD5,CALG_SHA
// LPTSTR pszHash, // 输出16进制Hash字符串,MD5长度为32+1, SHA长度为40+1
然后我们在View类中完成对GetHash函数的定义,如下:
DWORD CHash_testView::GetHash(BYTE *pbData, DWORD dwDataLen, ALG_ID algId, LPTSTR pszHash)
{
DWORD dwReturn = 0;
HCRYPTPROV hProv;
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
return (dwReturn = GetLastError());
HCRYPTHASH hHash;
//Alg Id:CALG_MD5,CALG_SHA
if(!CryptCreateHash(hProv, algId, 0, 0, &hHash))
{
dwReturn = GetLastError();
CryptReleaseContext(hProv, 0);
return dwReturn;
}
if(!CryptHashData(hHash, pbData, dwDataLen, 0))
{
dwReturn = GetLastError();
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
return dwReturn;
}
DWORD dwSize;
DWORD dwLen = sizeof(dwSize);
CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)(&dwSize), &dwLen, 0);
BYTE* pHash = new BYTE[dwSize];
dwLen = dwSize;
CryptGetHashParam(hHash, HP_HASHVAL, pHash, &dwLen, 0);
lstrcpy(pszHash, _T(""));
TCHAR szTemp[3];
for (DWORD i = 0; i < dwLen; ++i)
{
//wsprintf(szTemp, _T("%X%X"), pHash[i] >> 4, pHash[i] & 0xf);
wsprintf(szTemp, "%02X", pHash[i]);
lstrcat(pszHash, szTemp);
}
delete [] pHash;
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
return dwReturn;
}
有了这个GetHash函数之后,我们就可以通过调用它而计算一些字符串或者Char类型的数据的hash值了。像我们经常在网上见得一些hash校验器也可以比较容易的实现了,如下面的:
![](http://s11.sinaimg.cn/bmiddle/4b503921473ac38a30eda&690)
这里为了简单的验证一下,我们就测试一个字符串,然后它的hash值我们用一个messagebox输出,看看结果,我们测试的字符串是“Hello,Hash!你好,哈希!”其中没有空格,标点符号为英文状态。我们在OnDraw函数中加入测试代码:
TCHAR szStr[20] = {0};
TCHAR szHash[41] = {0};
strcpy(szStr,"Hello,Hash!你好,哈希!");
GetHash((BYTE*)szStr, strlen(szStr), CALG_MD5,szHash);
MessageBox(szHash,MB_OK);
结果如下:
![](http://s14.sinaimg.cn/bmiddle/4b503921473ac5720a69d&690)
然后我们用上面的hash计算工具算一下是不是对。
![](http://s6.sinaimg.cn/bmiddle/4b503921473ac5aadbfe5&690)
可以看出结果相同,证明对了。当然用python实现也是相当的简单,我们看一下:
![](http://s10.sinaimg.cn/bmiddle/4b503921473ac68793b19&690)
当然上面都是实现的MD5算法,如果想用SHA算法,可以修改调用GetHash((BYTE*)szStr, strlen(szStr), CALG_MD5,szHash);的第三个参数为CALG_SHA
有兴趣的就可以自己编写一个hash计算工具了。
。
Hash函数我们可以自己用C来编写,但是如果在VC中就不必了,因为在VC中有实现hash算法的 函数可以调用,就是CryptAcquireContext函数,这个函数的定义在wincrypt.h头文件中。下面是我在MFC中实现的,因为想要结果输出到messagebox中,所以就在视类里定义和实现了GetHash函数来计算哈希值。
首先是在View类的头文件中包含下列文件和内容:
#define _WIN32_WINNT 0x0400
#include <tchar.h>
#include <wincrypt.h>
其中我们用到的CryptAcquireContex函数就在wincrypy.h中定义了。
然后我们在View类中定义GetHash函数,函数类型为DWORD类型,参数为:
GetHash(BYTE
*pbData, DWORD dwDataLen, ALG_ID algId, LPTSTR pszHash)
先看一下这个函数几个参数的意义吧.
// 计算Hash,成功返回0,失败返回GetLastError()
// CONST BYTE *pbData, // 输入数据
// DWORD dwDataLen, // 输入数据字节长度
// ALG_ID algId // Hash 算法:CALG_MD5,CALG_SHA
// LPTSTR pszHash, // 输出16进制Hash字符串,MD5长度为32+1, SHA长度为40+1
然后我们在View类中完成对GetHash函数的定义,如下:
DWORD CHash_testView::GetHash(BYTE *pbData, DWORD dwDataLen, ALG_ID algId, LPTSTR pszHash)
{
DWORD dwReturn = 0;
HCRYPTPROV hProv;
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
return (dwReturn = GetLastError());
HCRYPTHASH hHash;
//Alg Id:CALG_MD5,CALG_SHA
if(!CryptCreateHash(hProv, algId, 0, 0, &hHash))
{
dwReturn = GetLastError();
CryptReleaseContext(hProv, 0);
return dwReturn;
}
if(!CryptHashData(hHash, pbData, dwDataLen, 0))
{
dwReturn = GetLastError();
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
return dwReturn;
}
DWORD dwSize;
DWORD dwLen = sizeof(dwSize);
CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)(&dwSize), &dwLen, 0);
BYTE* pHash = new BYTE[dwSize];
dwLen = dwSize;
CryptGetHashParam(hHash, HP_HASHVAL, pHash, &dwLen, 0);
lstrcpy(pszHash, _T(""));
TCHAR szTemp[3];
for (DWORD i = 0; i < dwLen; ++i)
{
//wsprintf(szTemp, _T("%X%X"), pHash[i] >> 4, pHash[i] & 0xf);
wsprintf(szTemp, "%02X", pHash[i]);
lstrcat(pszHash, szTemp);
}
delete [] pHash;
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
return dwReturn;
}
有了这个GetHash函数之后,我们就可以通过调用它而计算一些字符串或者Char类型的数据的hash值了。像我们经常在网上见得一些hash校验器也可以比较容易的实现了,如下面的:
这里为了简单的验证一下,我们就测试一个字符串,然后它的hash值我们用一个messagebox输出,看看结果,我们测试的字符串是“Hello,Hash!你好,哈希!”其中没有空格,标点符号为英文状态。我们在OnDraw函数中加入测试代码:
TCHAR szStr[20] = {0};
TCHAR szHash[41] = {0};
strcpy(szStr,"Hello,Hash!你好,哈希!");
GetHash((BYTE*)szStr, strlen(szStr), CALG_MD5,szHash);
MessageBox(szHash,MB_OK);
结果如下:
然后我们用上面的hash计算工具算一下是不是对。
可以看出结果相同,证明对了。当然用python实现也是相当的简单,我们看一下:
当然上面都是实现的MD5算法,如果想用SHA算法,可以修改调用GetHash((BYTE*)szStr, strlen(szStr), CALG_MD5,szHash);的第三个参数为CALG_SHA
有兴趣的就可以自己编写一个hash计算工具了。
。
相关文章推荐
- javascript getTime()
- DC4C代码阅读(5)——计算节点
- 蓝桥杯 历届试题 打印十字图 java详解
- 如何在 kernel 和 hal 层读取同一个标志
- 索引
- ServiceManager的启动过程分析
- 单例模式
- 根据数组元素包含某字符串过滤并生成新的数组
- 介绍 Android DropBoxManager Service
- CodeForces 626C Block Towers
- Jmeter报告优化之New XSL stylesheet
- Jmeter默认报告优化
- list 基本操作 1 -- 创建,插入,删除,计算长度
- PHP绘图函数生成图片验证码
- CodeForces 626B Cards
- nginx的基本使用(启动、关闭及域名映射访问)
- 搭建持续集成接口测试平台(Jenkins+Ant+Jmeter)
- shiro入门实战笔记(11)--加密/解密
- Android属性动画一
- 站在巨人的肩膀上看ADO.Net