You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将字符串传入要求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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 03:34:59