Winapi 使用Crypto***API的HMAC_SHA1的base64字符串的结果错误
我正在尝试使用winapi加密api获取base64编码的哈希。我复制并修改了下面的函数。我主要是从这里得到的- 使用Winapi 使用Crypto***API的HMAC_SHA1的base64字符串的结果错误,winapi,cryptoapi,hmacsha1,Winapi,Cryptoapi,Hmacsha1,我正在尝试使用winapi加密api获取base64编码的哈希。我复制并修改了下面的函数。我主要是从这里得到的- 使用calcHmacSha1(“消息”、“键”)运行它应该会得到IIjfdNXyFGtIFGyvSWU3fp0L46Q=。然而,它给了我SlLDwKvAoGBJ0atki7QFfj/181k=,它给出的非base64版本是4a 52 c3 c0 ab c0 a0 60 49 d1 ab 64 8b b4 05 7e 3f f5 f3 59。这与这里遇到的情况相同——但是他的解决方案对
calcHmacSha1(“消息”、“键”)
运行它应该会得到IIjfdNXyFGtIFGyvSWU3fp0L46Q=
。然而,它给了我SlLDwKvAoGBJ0atki7QFfj/181k=
,它给出的非base64版本是4a 52 c3 c0 ab c0 a0 60 49 d1 ab 64 8b b4 05 7e 3f f5 f3 59
。这与这里遇到的情况相同——但是他的解决方案对于大于16个字符的key不起作用,这是我的需要
#pragma comment (lib, "Crypt32.lib")
#include <wincrypt.h>
std::string calcHmacSha1(std::string msg, std::string key) {
std::string hash;
std::vector<BYTE> msgbytebuffer(msg.begin(), msg.end());
std::vector<BYTE> keybytebuffer(key.begin(), key.end());
// http://msdn.microsoft.com/en-us/library/Aa379863
HCRYPTPROV hProv = NULL;
HCRYPTHASH hHash = NULL;
HCRYPTKEY hKey = NULL;
HCRYPTHASH hHmacHash = NULL;
PBYTE pbHash = NULL;
DWORD dwDataLen = 0;
BYTE* Data1 = &keybytebuffer[0]; // {0x6b,0x65,0x79};
BYTE* Data2 = &msgbytebuffer[0]; // {0x6D,0x65,0x73,0x73,0x61,0x67,0x65};
HMAC_INFO HmacInfo;
//--------------------------------------------------------------------
// Zero the HMAC_INFO structure and use the SHA1 algorithm for
// hashing.
debug_log("sizeof(Data2)", sizeof(Data2));
debug_log("sizeof(BYTE)", sizeof(BYTE));
ZeroMemory(&HmacInfo, sizeof(HmacInfo));
HmacInfo.HashAlgid = CALG_SHA1;
//--------------------------------------------------------------------
// Acquire a handle to the default RSA cryptographic service provider.
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
debug_log(" Error in AcquireContext 0x%08x", GetLastError());
goto ErrorExit;
}
//--------------------------------------------------------------------
// Derive a symmetric key from a hash object by performing the
// following steps:
// 1. Call CryptCreateHash to retrieve a handle to a hash object.
// 2. Call CryptHashData to add a text string (password) to the
// hash object.
// 3. Call CryptDeriveKey to create the symmetric key from the
// hashed password derived in step 2.
// You will use the key later to create an HMAC hash object.
if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash)) {
debug_log("Error in CryptCreateHash 0x%08x \n", GetLastError());
goto ErrorExit;
}
if (!CryptHashData(hHash, Data1, key.length() * sizeof(BYTE), 0)) {
debug_log("Error in CryptHashData 1 0x%08x", GetLastError());
goto ErrorExit;
}
if (!CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey)) {
debug_log("Error in CryptDeriveKey 0x%08x", GetLastError());
goto ErrorExit;
}
//--------------------------------------------------------------------
// Create an HMAC by performing the following steps:
// 1. Call CryptCreateHash to create a hash object and retrieve
// a handle to it.
// 2. Call CryptSetHashParam to set the instance of the HMAC_INFO
// structure into the hash object.
// 3. Call CryptHashData to compute a hash of the message.
// 4. Call CryptGetHashParam to retrieve the size, in bytes, of
// the hash.
// 5. Call malloc to allocate memory for the hash.
// 6. Call CryptGetHashParam again to retrieve the HMAC hash.
if (!CryptCreateHash(hProv, CALG_HMAC, hKey, 0, &hHmacHash)) {
debug_log("Error in CryptCreateHash key 0x%08x", GetLastError());
goto ErrorExit;
}
if (!CryptSetHashParam(hHmacHash, HP_HMAC_INFO, (BYTE*)&HmacInfo, 0)) {
debug_log("Error in CryptSetHashParam 0x%08x", GetLastError());
goto ErrorExit;
}
if (!CryptHashData(hHmacHash, Data2, msg.length() * sizeof(BYTE), 0)) {
debug_log("Error in CryptHashData 2 0x%08x", GetLastError());
goto ErrorExit;
}
//--------------------------------------------------------------------
// Call CryptGetHashParam twice. Call it the first time to retrieve
// the size, in bytes, of the hash. Allocate memory. Then call
// CryptGetHashParam again to retrieve the hash value.
if (!CryptGetHashParam(hHmacHash, HP_HASHVAL, NULL, &dwDataLen, 0)) {
debug_log("Error in CryptGetHashParam 0x%08x", GetLastError());
goto ErrorExit;
}
pbHash = (BYTE*)malloc(dwDataLen);
if(NULL == pbHash) {
debug_log("unable to allocate memory\n");
goto ErrorExit;
}
if (!CryptGetHashParam(hHmacHash, HP_HASHVAL, pbHash, &dwDataLen, 0)) {
debug_log("Error in CryptGetHashParam 0x%08x", GetLastError());
goto ErrorExit;
}
DWORD base64Size = 0;
if (!CryptBinaryToString(pbHash, dwDataLen, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, &base64Size)) {
debug_log("Error in CryptBinaryToString 1 0x%08x", GetLastError());
goto ErrorExit;
};
WCHAR* base64 = new WCHAR[ base64Size + 1 ];
if (!CryptBinaryToString(pbHash, dwDataLen, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, base64, &base64Size)) {
debug_log("Error in CryptBinaryToString 2 0x%08x", GetLastError());
goto ErrorExit;
};
hash = string_cast<std::string>(base64);
delete[] base64;
debug_log("hash:", hash);
// printf("The hash is: ");
// char chash[512];
// for(DWORD i = 0 ; i < dwDataLen ; i++) {
// printf("%.2x ",pbHash[i]);
// }
MessageBox(NULL, L"hi", L"cap", 0);
// Free resources.
ErrorExit:
if(hHmacHash) CryptDestroyHash(hHmacHash);
if(hKey) CryptDestroyKey(hKey);
if(hHash) CryptDestroyHash(hHash);
if(hProv) CryptReleaseContext(hProv, 0);
if(pbHash) free(pbHash);
return hash;
}
#pragma注释(lib,“Crypt32.lib”)
#包括
std::string calcHmacSha1(std::string msg,std::string键){
std::字符串散列;
std::vector msgbytebuffer(msg.begin(),msg.end());
向量keybytebuffer(key.begin(),key.end());
// http://msdn.microsoft.com/en-us/library/Aa379863
HCRYPTPROV hProv=NULL;
HCRYPTHASH hHash=NULL;
HCRYPTKEY hKey=NULL;
HCRYPTHASH hHmacHash=NULL;
PBYTE pbHash=NULL;
DWORD dwDataLen=0;
字节*Data1=&keybytebuffer[0];/{0x6b,0x65,0x79};
字节*Data2=&msgbytebuffer[0];/{0x6D,0x65,0x73,0x73,0x61,0x67,0x65};
HMAC_信息HmacInfo;
//--------------------------------------------------------------------
//将HMAC_信息结构归零,并使用SHA1算法
//散列。
调试日志(“sizeof(Data2)”,sizeof(Data2));
调试日志(“sizeof(BYTE)”,sizeof(BYTE));
零内存(&HmacInfo,sizeof(HmacInfo));
HmacInfo.HashAlgid=CALG_SHA1;
//--------------------------------------------------------------------
//获取默认RSA加密服务提供程序的句柄。
if(!CryptAcquireContext(&hProv,NULL,NULL,PROV\u RSA\u FULL,CRYPT\u VERIFYCONTEXT)){
调试日志(“AcquireContext 0x%08x中的错误”,GetLastError());
转到错误退出;
}
//--------------------------------------------------------------------
//通过执行
//以下步骤:
//1.调用CryptCreateHash检索哈希对象的句柄。
//2.调用CryptHashData将文本字符串(密码)添加到
//散列对象。
//3.调用CryptDeriveKey从
//在步骤2中派生的哈希密码。
//稍后将使用该键创建HMAC哈希对象。
如果(!CryptCreateHash(hProv、CALG_SHA1、0、0和hHash)){
调试日志(“CryptCreateHash 0x%08x\n中的错误”,GetLastError());
转到错误退出;
}
if(!CryptHashData(hHash,Data1,key.length()*sizeof(BYTE),0)){
调试日志(“CryptHashData 1 0x%08x中的错误”,GetLastError());
转到错误退出;
}
if(!CryptDeriveKey(hProv、CALG_RC4、hHash、0和hKey)){
调试日志(“CryptDeriveKey 0x%08x中的错误”,GetLastError());
转到错误退出;
}
//--------------------------------------------------------------------
//通过执行以下步骤创建HMAC:
//1.调用CryptCreateHash创建哈希对象并检索
//它的把手。
//2.调用CryptSetHashParam来设置HMAC_信息的实例
//结构转换为哈希对象。
//3.调用CryptHashData来计算消息的散列。
//4.调用CryptGetHashParam以检索的大小(以字节为单位)
//杂烩。
//5.调用malloc为哈希分配内存。
//6.再次调用CryptGetHashParam以检索HMAC哈希。
如果(!CryptCreateHash(hProv、CALG_HMAC、hKey、0和hHmacHash)){
调试日志(“CryptCreateHash密钥0x%08x中的错误”,GetLastError());
转到错误退出;
}
if(!CryptSetHashParam(hHmacHash,HP_HMAC_INFO,(字节*)&HmacInfo,0)){
调试日志(“CryptSetHashParam 0x%08x中的错误”,GetLastError());
转到错误退出;
}
if(!CryptHashData(hHmacHash,Data2,msg.length()*sizeof(BYTE),0)){
调试日志(“CryptHashData 2 0x%08x中的错误”,GetLastError());
转到错误退出;
}
//--------------------------------------------------------------------
//调用CryptGetHashParam两次。第一次调用它进行检索
//哈希的大小,以字节为单位。分配内存。然后调用
//再次使用CryptGetHashParam检索哈希值。
if(!CryptGetHashParam(hHmacHash,HP_HASHVAL,NULL,&dwDataLen,0)){
调试日志(“CryptGetHashParam 0x%08x中的错误”,GetLastError());
转到错误退出;
}
pbHash=(字节*)malloc(dwDataLen);
if(NULL==pbHash){
调试日志(“无法分配内存”);
转到错误退出;
}
if(!CryptGetHashParam(hHmacHash、HP_HASHVAL、pbHash和dwDataLen,0)){
调试日志(“CryptGetHashParam 0x%08x中的错误”,GetLastError());
转到错误退出;
}
DWORD base64Size=0;
if(!CryptBinaryToString(pbHash、dwDataLen、CRYPT_STRING_BASE64、CRYPT_STRING_NOCRLF、NULL和base64Size)){
调试日志(“CryptBinaryToString 1 0x%08x中的错误”,GetLastError());
转到错误退出;
};
WCHAR*base64=新的WCHAR[base64Size+1];
if(!CryptBinaryToString(pbHash、dwDataLen、CRYPT_STRING_BASE64、CRYPT_STRING_NOCRLF、BASE64和base64Size)){
调试日志(“CryptBinaryToString 2 0x%08x中的错误”,GetLastError());
转到错误退出;
};
哈希=字符串\u转换(base64);
删除[]base64;
调试日志(“哈希:”,哈希);
//printf(“散列为:”);
//char chash[512];
//对于(DWORD i=0;i#define BLOCK_SIZE 64
BOOL hmac(PCSTR key, PCSTR message, ALG_ID Algid)
{
UCHAR i_key_pad[BLOCK_SIZE], o_key_pad[BLOCK_SIZE];
HCRYPTPROV hProv;
HCRYPTHASH hHash;
ULONG len = (ULONG)strlen(key), cb;
BOOL f;
if (f = CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
if (len > BLOCK_SIZE)
{
if (f = CryptCreateHash(hProv, Algid, 0, 0, &hHash))
{
f = CryptHashData(hHash, (PBYTE)key, len, 0) &&
CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&len, &(cb = sizeof(len)), 0) &&
CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)(key = (PCSTR)alloca(len)), &len, 0);
CryptDestroyHash(hHash);
}
}
if (f)
{
ULONG i = BLOCK_SIZE;
do
{
UCHAR c = --i < len ? key[i] : 0;
i_key_pad[i] = 0x36 ^ c;
o_key_pad[i] = 0x5c ^ c;
} while (i);
if (f = CryptCreateHash(hProv, Algid, 0, 0, &hHash))
{
f = CryptHashData(hHash, i_key_pad, sizeof(i_key_pad), 0) &&
CryptHashData(hHash, (PBYTE)message, (ULONG)strlen(message), 0) &&
CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&len, &(cb = sizeof(len)), 0) &&
CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)(key = (PCSTR)alloca(len)), &len, 0);
CryptDestroyHash(hHash);
if (f && (f = CryptCreateHash(hProv, Algid, 0, 0, &hHash)))
{
f = CryptHashData(hHash, o_key_pad, sizeof(o_key_pad), 0) &&
CryptHashData(hHash, (PBYTE)key, len, 0) &&
CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)key, &len, 0);
CryptDestroyHash(hHash);
if (f && len)
{
DbgPrint("\nThe hash is: ");
do
{
DbgPrint("%02x", (UCHAR)*key++);
} while (--len);
DbgPrint("\n");
}
}
}
}
CryptReleaseContext(hProv, 0);
}
return f;
}
//The hash is: 2088df74d5f2146b48146caf4965377e9d0be3a4
hmac("key","message", CALG_SHA1);