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

使用C风格函数调用无法验证签名,代码输出FAIL求技术排查

ECDSA签名验证失败(C风格函数调用场景)

嘿,我来帮你捋捋为啥你的代码会输出FAIL。先把你给出的代码片段整理出来,方便排查问题:

#include <cryptopp/eccrypto.h>
#include <cryptopp/oids.h>
#include <cryptopp/osrng.h>
#include <iostream>
using namespace std;
using namespace CryptoPP;
int main() {
    AutoSeededRandomPool prng;
    ECDSA<ECP, SHA256>::PrivateKey private_key;
    ECDSA<ECP, SHA256>::PublicKey public_key;
    private_key.Initialize( prng, ASN1::secp160r1() );
    private_key.MakePublicKey(public_key);
    ECDSA<ECP, SHA256>::Signer signer(...);
    // 后续签名、验证逻辑...
}

从你的描述来看,核心问题是用C风格函数调用(直接调用底层签名/验证成员函数)时验证失败,大概率是你在流程中忽略了某个关键步骤,我给你拆解下常见的坑和正确实现方式:

常见出错原因

  1. 哈希处理不一致:高层接口会自动计算消息哈希,但底层函数需要手动计算哈希值,如果哈希算法不匹配或计算错误,直接会导致验证失败
  2. 签名格式不统一:ECDSA签名通常是DER编码的字节串(包含r和s两个整数),如果签名时生成的是DER格式,但验证时直接把原始字节流传给底层函数(没解析出r和s),肯定会失败
  3. 参数传递错误:底层Sign和Verify函数对参数要求严格,比如哈希值长度、r/s的类型,稍有不对就会验证不通过

正确的底层函数调用示例

我补全了完整的可运行代码,你可以对照看看自己哪里出错了:

#include <cryptopp/eccrypto.h>
#include <cryptopp/oids.h>
#include <cryptopp/osrng.h>
#include <cryptopp/sha.h>
#include <cryptopp/der.h>
#include <iostream>
using namespace std;
using namespace CryptoPP;

int main() {
    AutoSeededRandomPool prng;
    ECDSA<ECP, SHA256>::PrivateKey private_key;
    ECDSA<ECP, SHA256>::PublicKey public_key;

    // 初始化私钥与公钥
    private_key.Initialize(prng, ASN1::secp160r1());
    private_key.MakePublicKey(public_key);

    // 待签名的测试消息
    const string message = "Test ECDSA Signature";
    bool verify_result = false;

    // --------------------------
    // 步骤1:手动计算消息的SHA256哈希(底层函数需要预计算哈希)
    // --------------------------
    byte digest[SHA256::DIGESTSIZE];
    SHA256 hash_alg;
    hash_alg.CalculateDigest(digest, reinterpret_cast<const byte*>(message.data()), message.size());

    // --------------------------
    // 步骤2:用底层Sign函数生成r和s签名分量
    // --------------------------
    Integer r, s;
    private_key.Sign(prng, digest, sizeof(digest), r, s);

    // 如果需要把签名转成字符串存储,要序列化为DER格式
    string signature_str;
    StringSink sink(signature_str);
    DEREncoder encoder(sink);
    encoder.StartSequence();
    encoder.Encode(r);
    encoder.Encode(s);
    encoder.EndSequence();

    // --------------------------
    // 步骤3:用底层Verify函数验证签名
    // --------------------------
    // 先把DER格式的签名解析回r和s分量
    Integer r_decoded, s_decoded;
    StringSource source(signature_str, true);
    BERDecoder decoder(source);
    decoder.StartSequence();
    decoder.Decode(r_decoded);
    decoder.Decode(s_decoded);
    decoder.EndSequence();

    // 调用底层Verify函数验证哈希值与签名分量
    verify_result = public_key.Verify(digest, sizeof(digest), r_decoded, s_decoded);

    // 输出结果
    cout << (verify_result ? "PASS" : "FAIL") << endl;

    return 0;
}

关键注意点

  • 一定要确保签名和验证时用的哈希算法完全一致,这里是SHA256,不能中途换成其他哈希
  • 如果你把签名作为字节串传输/存储,必须统一用DER(或BER)编码,验证时要先解析出r和s才能传给底层Verify函数
  • 不要直接把整个签名字节串当作参数传给Verify,底层函数只认单独的r和s整数分量

你可以对照自己的代码,看看是不是在哈希计算、签名解析这两步出了问题,应该就能解决验证失败的问题啦。

内容的提问来源于stack exchange,提问作者user1226313

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:52:07