使用OpenSSL SHA512库时同一输入生成不同摘要的问题排查
问题分析与修复方案
核心问题
- 混淆位与字节的概念:你定义的
KEY_SIZE注释标注为“number of bits in the key”,但代码中所有使用KEY_SIZE的地方都当作字节数处理。SHA512哈希的输出固定为512位(即64字节),但你给public_key和check_public_key分配了512字节的空间,且memcmp时对比整个512字节——这导致除前64字节的有效哈希值外,剩余448字节都是未初始化的垃圾数据,两次对比时这些垃圾值大概率不同,最终验证失败。
修复步骤
- 修正长度定义:
- 将私钥长度明确为字节单位,比如需要512位私钥则定义为64字节;
- 单独定义SHA512的固定输出长度(64字节),避免和私钥长度混淆。
- 调整数组与对比范围:
- 公钥、验证用的临时哈希数组大小改为64字节;
memcmp仅对比64字节的有效哈希结果,而非整个512字节的数组。
修正后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <openssl/sha.h> #include <openssl/rand.h> #include <openssl/bn.h> #include <limits.h> #define SECRET_KEY_SIZE 64 // 私钥长度:64字节=512位 #define SHA512_OUTPUT_SIZE 64 // SHA512输出固定为64字节 void key_gen(unsigned char *secret_key, unsigned char *public_key) { RAND_bytes(secret_key, SECRET_KEY_SIZE); SHA512(secret_key, SECRET_KEY_SIZE, public_key); } void sign(unsigned char *message, unsigned char *signature, unsigned char *secret_key){ memcpy(signature, secret_key, SECRET_KEY_SIZE); } int verify(unsigned char *message, unsigned char *signature, unsigned char *public_key){ unsigned char check_public_key[SHA512_OUTPUT_SIZE]; SHA512(signature, SECRET_KEY_SIZE, check_public_key); if(memcmp(check_public_key, public_key, SHA512_OUTPUT_SIZE) != 0){ printf("not valid"); return 0; } printf("valid"); return 1; } int main() { unsigned char secret_key[SECRET_KEY_SIZE]; unsigned char public_key[SHA512_OUTPUT_SIZE]; key_gen(secret_key, public_key); unsigned char message[] = "Hello World"; unsigned char signature[SECRET_KEY_SIZE]; sign(message, signature, secret_key); verify(message, signature, public_key); return 0; }
额外说明
- 当前签名逻辑仅为测试示例,直接复制私钥作为签名在实际场景中完全不安全;
- 编译时需链接OpenSSL库,例如使用命令:
gcc your_code.c -o your_program -lcrypto
内容的提问来源于stack exchange,提问作者hah
相关产品推荐
相关产品推荐

