OpenSSL Ed25519签名验证C/C++代码示例及正确性咨询
OpenSSL Ed25519 验签功能实现说明
官方文档提供的Ed25519算法C代码可直接用于C/C++程序的消息签名场景,但未配套给出签名验证的对应实现,即和文档中do_sign()匹配的do_verify()函数。
以下是对自行编写的验签代码的校验结论,以及可直接使用的正确实现:
原有代码存在的问题
你写的实现有3个容易出故障的隐患:
- 缺少空指针防护:
EVP_MD_CTX_new()申请内存失败时会返回NULL,直接传入后续API会触发空指针崩溃。 - 运算符优先级不规范:C语言中
==优先级高于&&,现有判断逻辑虽然靠短路规则不会直接返回错误结果,但后续调整判断条件时极易出现逻辑偏差,且所有OpenSSL API的返回值应该单独校验,不建议写在同一个链式判断里。 - 错误类型混淆:
EVP_DigestVerify()的返回值有三种:验签成功返回1,签名不匹配返回0,参数错误/内部运行错误返回-1。原有写法会把运行错误和验签失败都归为返回0,排查问题时无法区分是签名本身不对,还是程序传参出了问题。
可直接使用的正确验签实现
int do_verify(EVP_PKEY* pkey, const unsigned char* sig, size_t sig_len, const unsigned char* msg, size_t msg_len) { int ret = 0; EVP_MD_CTX* md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { return -1; // 内存申请失败 } // Ed25519为无哈希的原生签名算法,不需要传入摘要类型,第三、第四个参数传NULL符合官方规范 if (EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, pkey) != 1) { ret = -1; goto cleanup; } int verify_ret = EVP_DigestVerify(md_ctx, sig, sig_len, msg, msg_len); if (verify_ret == 1) { ret = 1; // 验签通过 } else if (verify_ret == 0) { ret = 0; // 签名不匹配 } else { ret = -1; // 参数非法、内部运算错误等异常 } cleanup: EVP_MD_CTX_free(md_ctx); return ret; }
补充说明:Ed25519的签名固定长度为64字节,API内部已经做了签名长度校验,如果传入的
sig_len不是64,会直接返回-1抛出参数错误,不需要业务层额外加判断。
内容的提问来源于stack exchange,提问作者Decaf Sux
相关产品推荐
相关产品推荐

