C++ OpenSSL secp256k1 ECDSA问题:相同哈希副本验证失败
问题:ECDSA签名验证时相同内容哈希副本验证失败
我尝试使用OpenSSL的secp256k1曲线ECDSA对哈希进行签名,创建该哈希的副本(模拟客户端/服务器场景),但使用副本验证签名时失败,尽管两个哈希变量内容完全一致。此外,直接传入相同内容的字符串字面量验证也失败,复制signature变量无影响。
相关代码
int main() { EC_KEY* myecc = NULL; EVP_PKEY* pkey_ = NULL; myecc = EC_KEY_new_by_curve_name(NID_secp256k1); EC_KEY_generate_key(myecc); pkey_ = EVP_PKEY_new(); EVP_PKEY_assign_EC_KEY(pkey_, myecc); myecc = EVP_PKEY_get1_EC_KEY(pkey_); const EC_GROUP* ecgrp = EC_KEY_get0_group(myecc); std::string hash = "126420fb81d58bbb7d86c98e1818f4c9d44acf216471e196ed403a608954cf1d"; std::string hashCopy = hash; std::vector<unsigned char> signature; unsigned char pchSig[10000]; unsigned int nSize = 0; ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, myecc); signature.resize(nSize); memcpy(&signature[0], pchSig, nSize); if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &signature[0], signature.size(), myecc) == 1) { std::cout << "Original hash variable verify success\n\n"; } else { std::cout << "Original hash variable verify fail\n\n"; } if (ECDSA_verify(0, (unsigned char*)&hashCopy, sizeof(hashCopy), &signature[0], signature.size(), myecc) == 1) { std::cout << "Hash copy variable verify success\n\n"; } else { std::cout << "Hash copy variable verify fail\n\n"; } }
代码输出
Original hash variable verify success Hash copy variable verify fail
问题原因与解决方法
核心问题
你传递给ECDSA_sign和ECDSA_verify的参数完全错误:
(unsigned char*)&hash取的是std::string对象本身的内存地址,而非字符串存储的哈希内容;sizeof(hash)获取的是std::string结构体的固定大小(通常24或32字节),不是哈希字符串的实际长度。- 原hash变量验证成功只是巧合:签名和验证时用的是同一个std::string对象的结构体内存,内部指针、长度值等内容刚好一致;而hashCopy是独立的std::string对象,结构体内存内容和原hash不同,因此验证失败。
修正方案
传递哈希字符串的实际内容和长度:
- 用
hash.data()(或hash.c_str())获取字符串内容的首地址,转成unsigned char*类型 - 用
hash.size()获取字符串的实际长度,替代sizeof(hash)
修正后的关键代码片段:
// 签名操作 ECDSA_sign(0, reinterpret_cast<unsigned char*>(hash.data()), hash.size(), pchSig, &nSize, myecc); // 验证原哈希 if (ECDSA_verify(0, reinterpret_cast<unsigned char*>(hash.data()), hash.size(), &signature[0], signature.size(), myecc) == 1) { std::cout << "Original hash variable verify success\n\n"; } // 验证哈希副本 if (ECDSA_verify(0, reinterpret_cast<unsigned char*>(hashCopy.data()), hashCopy.size(), &signature[0], signature.size(), myecc) == 1) { std::cout << "Hash copy variable verify success\n\n"; }
额外提示
你的hash变量是十六进制字符串形式的哈希值,而ECDSA签名通常是对原始二进制哈希值操作。如果你的真实需求是签名哈希值本身,需要先把十六进制字符串转换成二进制数组,否则你签名的是十六进制字符的ASCII码(比如"12"会被当作0x31和0x32,而非0x12)。
内容的提问来源于stack exchange,提问作者random5999
相关产品推荐
相关产品推荐

