使用OpenSSL的HMAC时触发Access violation错误求助
解决HMAC-SHA512调用中的访问违规错误
你的代码里有两个关键错误直接导致了内存访问违规,我来逐个拆解说明:
1. 数据缓冲区的类型定义错误
你把data定义成了uint8_t* data[]——这是一个指针数组,而非你需要的原始字节数组。当你把这个数组传给HMAC函数时,它会把指针数组里的每个指针值当成原始数据字节处理,直接触发越界访问内存的错误。
正确的定义应该去掉星号,声明为字节数组:
uint8_t data[] = { 0x14, 0xf7, 0xbd, 0x95, 0x57, 0x9a, 0x7e, 0xa1, 0x5c, 0xf7, 0x27, 0x91, 0x0d, 0x61, 0x58, 0x01, 0xa3, 0x12, 0x17, 0x54, 0x0b, 0x2e, 0xb4, 0xc5, 0xb1, 0xeb, 0xab, 0xe0, 0x43, 0x9b, 0x8e, 0x1f, 0x39, 0x7d, 0x85, 0x1a, 0x3a, 0x4b, 0x9c, 0xf4, 0xbf, 0x31, 0x55, 0x72, 0x41, 0xf5, 0xdb, 0xcb, 0xb3, 0xa6, 0xb5, 0xb8, 0x82, 0xe5, 0xef, 0x18, 0x72, 0xa0, 0x59, 0x08, 0x9b, 0xfa, 0x17, 0xa3 };
2. HMAC函数最后一个参数的错误传递
HMAC函数的最后一个参数是unsigned int *len,它是一个指针,用来接收生成的HMAC实际长度(虽然SHA512的HMAC固定为64字节,但函数要求通过指针返回值)。你直接传递(unsigned int)64,相当于把数值64转换成指针,函数会尝试往内存地址0x40(64的十六进制)写入数据——这个低地址属于系统保护内存,必然触发访问违规。
你需要声明一个unsigned int变量,传递它的地址:
unsigned int result_len; HMAC(EVP_sha512(), key, 12, data, sizeof(data), result, &result_len);
修正后的完整代码
我还优化了几个细节,比如用sizeof(data)代替硬编码的64,用strlen(key)代替硬编码的12,让代码更健壮:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/hmac.h> #include <openssl/evp.h> int main(int argc, char** argv) { // 修正:将指针数组改为字节数组 uint8_t data[] = { 0x14, 0xf7, 0xbd, 0x95, 0x57, 0x9a, 0x7e, 0xa1, 0x5c, 0xf7, 0x27, 0x91, 0x0d, 0x61, 0x58, 0x01, 0xa3, 0x12, 0x17, 0x54, 0x0b, 0x2e, 0xb4, 0xc5, 0xb1, 0xeb, 0xab, 0xe0, 0x43, 0x9b, 0x8e, 0x1f, 0x39, 0x7d, 0x85, 0x1a, 0x3a, 0x4b, 0x9c, 0xf4, 0xbf, 0x31, 0x55, 0x72, 0x41, 0xf5, 0xdb, 0xcb, 0xb3, 0xa6, 0xb5, 0xb8, 0x82, 0xe5, 0xef, 0x18, 0x72, 0xa0, 0x59, 0x08, 0x9b, 0xfa, 0x17, 0xa3 }; uint8_t* key = (uint8_t*)"some_rand_pw"; // 分配SHA512 HMAC所需的64字节缓冲区 uint8_t* result = malloc(64); if (!result) { fprintf(stderr, "内存分配失败\n"); return 1; } memset(result, 0, 64); unsigned int result_len; // 修正参数:传递正确的数据缓冲区和长度指针 HMAC(EVP_sha512(), key, strlen((char*)key), data, sizeof(data), result, &result_len); // 可选:输出验证结果 printf("HMAC-SHA512长度: %u\n", result_len); for (int i = 0; i < result_len; i++) { printf("%02x", result[i]); } printf("\n"); free(result); return 0; }
关于线程安全的说明
你提到的HMAC(..., NULL, NULL)返回静态缓冲区确实是非线程安全的,所以你自己分配独立缓冲区的思路完全正确——只要参数传递正确,这种方式每个线程使用自己的内存空间,不会出现竞争问题,是线程安全的实现方案。
内容的提问来源于stack exchange,提问作者MrPuzzler
相关产品推荐
相关产品推荐

