如何将字符串传入要求BYTE*参数的函数?替换HMAC示例中Data1/Data2
解决HMAC示例中字符串替换字节数组的哈希不一致问题
问题出在字符串的长度计算错误:原代码里的sizeof(Data1)是直接获取字节数组的总字节数,但如果换成char*类型的字符串,sizeof(字符串变量)得到的是指针的大小(4或8字节,取决于系统位数),而不是字符串的实际字节长度,这就导致CryptHashData哈希了错误长度的数据,结果自然不对。
正确的修改方式
把字符串的长度计算从sizeof()换成strlen(),同时将char*强制转换为BYTE*(因为CryptHashData要求第二个参数是BYTE*类型):
修改后的关键代码片段
// 假设函数参数为 const char* passwordStr 和 const char* messageStr if (!CryptHashData( hHash, (BYTE*)passwordStr, // 强制转换为BYTE* strlen(passwordStr), // 用strlen获取字符串实际长度(不含终止符'\0') 0)) { printf("Error in CryptHashData 0x%08x \n", GetLastError()); goto ErrorExit; } // ... if (!CryptHashData( hHmacHash, (BYTE*)messageStr, // 强制转换为BYTE* strlen(messageStr), // 用strlen获取字符串实际长度 0)) { printf("Error in CryptHashData 0x%08x \n", GetLastError()); goto ErrorExit; }
额外注意事项
- 如果你的字符串是宽字符(wchar_t*),需要先将其转换为多字节字符串(比如用
WideCharToMultiByte函数),再传递给CryptHashData,否则会因为宽字符的字节编码(比如UTF-16)导致哈希结果不符合预期。 - 确保输入的字符串是ASCII或UTF-8编码(和原示例的字节数组编码一致),如果是其他编码,需要先统一编码格式。
完整封装函数示例
#include <windows.h> #include <wincrypt.h> #include <stdio.h> #include <string.h> // 释放资源的辅助宏 #define SAFE_RELEASE_HCRYPT(h) if(h) { CryptDestroyHash(h); h = NULL; } #define SAFE_RELEASE_HCKEY(h) if(h) { CryptDestroyKey(h); h = NULL; } #define SAFE_RELEASE_HCPROV(h) if(h) { CryptReleaseContext(h, 0); h = NULL; } // 计算HMAC的函数,输入密码和消息字符串,输出哈希结果(需提前分配足够内存,比如SHA-1是20字节) BOOL ComputeHMAC(const char* password, const char* message, BYTE* outHmac, DWORD* outHmacLen) { BOOL result = FALSE; HCRYPTPROV hProv = NULL; HCRYPTHASH hHash = NULL; HCRYPTKEY hKey = NULL; HCRYPTHASH hHmacHash = NULL; // 获取加密服务提供者 if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { printf("CryptAcquireContext failed: 0x%08x\n", GetLastError()); goto Cleanup; } // 创建哈希对象(原示例用SHA-1,可根据需要修改为其他算法,比如CALG_SHA_256) if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash)) { printf("CryptCreateHash failed: 0x%08x\n", GetLastError()); goto Cleanup; } // 哈希密码 if (!CryptHashData(hHash, (BYTE*)password, strlen(password), 0)) { printf("CryptHashData (password) failed: 0x%08x\n", GetLastError()); goto Cleanup; } // 从哈希派生密钥 if (!CryptDeriveKey(hProv, CALG_HMAC, hHash, 0, &hKey)) { printf("CryptDeriveKey failed: 0x%08x\n", GetLastError()); goto Cleanup; } // 创建HMAC哈希对象 if (!CryptCreateHash(hProv, CALG_HMAC, hKey, 0, &hHmacHash)) { printf("CryptCreateHash (HMAC) failed: 0x%08x\n", GetLastError()); goto Cleanup; } // 设置HMAC的哈希算法(和之前一致,比如SHA-1) DWORD algId = CALG_SHA1; if (!CryptSetHashParam(hHmacHash, HP_ALGID, (BYTE*)&algId, 0)) { printf("CryptSetHashParam failed: 0x%08x\n", GetLastError()); goto Cleanup; } // 哈希消息 if (!CryptHashData(hHmacHash, (BYTE*)message, strlen(message), 0)) { printf("CryptHashData (message) failed: 0x%08x\n", GetLastError()); goto Cleanup; } // 获取哈希结果长度 DWORD hmacLen = *outHmacLen; if (!CryptGetHashParam(hHmacHash, HP_HASHVAL, outHmac, &hmacLen, 0)) { printf("CryptGetHashParam failed: 0x%08x\n", GetLastError()); goto Cleanup; } *outHmacLen = hmacLen; result = TRUE; Cleanup: SAFE_RELEASE_HCRYPT(hHmacHash); SAFE_RELEASE_HCKEY(hKey); SAFE_RELEASE_HCRYPT(hHash); SAFE_RELEASE_HCPROV(hProv); return result; } // 测试函数 int main() { const char* password = "password"; const char* message = "message"; BYTE hmac[20]; // SHA-1的哈希长度是20字节 DWORD hmacLen = sizeof(hmac); if (ComputeHMAC(password, message, hmac, &hmacLen)) { printf("HMAC Result: "); for (DWORD i = 0; i < hmacLen; i++) { printf("%02x", hmac[i]); } printf("\n"); } return 0; }
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

