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

gcrypt签名返回16777281错误(提示Invalid Object)求助

解决gcrypt签名返回"Invalid Object"(错误码16777281)的问题

从你给出的错误信息和代码来看,错误码16777281对应gcrypt的GPG_ERR_INV_OBJECT(0x1000001),提示"Invalid Object",核心问题是你构建签名用的data S表达式格式完全错误,导致gcrypt无法识别这个对象。

具体问题分析

你的代码中构建data的这一行存在两个关键错误:

gcry_sexp_build(&data, nullptr, "(data (flags raw) (value (100, 2, 254, 88, 90, 45, 23))");
  1. 括号不匹配:整个S表达式最外层是(data ...),内部嵌套了(value ...),但你最后只写了一个闭合括号,缺少一个)来闭合最外层的(data。
  2. value字段格式错误:当指定(flags raw)时,value需要传入十六进制字符串,或者使用gcrypt支持的字节字面量格式(#xx#xx,其中xx是两位十六进制数),而不是用逗号分隔的十进制数字列表——这种格式gcrypt根本无法解析。

修正后的代码

下面是修正后的关键代码部分,同时补充了必要的错误检查(不要仅依赖assert,生产环境应该检查gcrypt函数的返回值):

// 首先将你的十进制字节转换为十六进制字符串:100→64, 2→02, 254→fe, 88→58, 90→5a,45→2d,23→17
std::cout << gcry_check_version(nullptr) << std::endl;
gcry_control(GCRYCTL_SUSPEND_SECMEM_WARN);
gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0);
gcry_control(GCRYCTL_RESUME_SECMEM_WARN);
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);

gcry_sexp_t keypair = nullptr;
gcry_sexp_t params = nullptr;
gcry_error_t err = gcry_sexp_build(&params, nullptr, "(genkey (rsa (nbits 4:3072)))");
if (err != GPG_ERR_NO_ERROR) {
    std::cerr << "Failed to build params: " << gcry_strerror(err) << std::endl;
    return 1;
}

err = gcry_pk_genkey(&keypair, params);
if (err != GPG_ERR_NO_ERROR) {
    std::cerr << "Failed to generate key pair: " << gcry_strerror(err) << std::endl;
    gcry_sexp_release(params);
    return 1;
}
gcry_sexp_release(params);

gcry_sexp_t priv = gcry_sexp_find_token(keypair, "private-key", 0);
gcry_sexp_t pub = gcry_sexp_find_token(keypair, "public-key", 0);
if (!priv || !pub) {
    std::cerr << "Failed to extract private/public key" << std::endl;
    gcry_sexp_release(keypair);
    return 1;
}

gcry_sexp_t data = nullptr;
// 修正:使用十六进制字符串作为raw value,同时补全括号
err = gcry_sexp_build(&data, nullptr, "(data (flags raw) (value 6402fe585a2d17))");
if (err != GPG_ERR_NO_ERROR) {
    std::cerr << "Failed to build data: " << gcry_strerror(err) << std::endl;
    gcry_sexp_release(priv);
    gcry_sexp_release(pub);
    gcry_sexp_release(keypair);
    return 1;
}

gcry_sexp_t r_sig = nullptr;
err = gcry_pk_sign(&r_sig, data, priv);
std::cout << "Sign result: " << err << " (" << gcry_strerror(err) << ")" << std::endl;

// 记得释放所有资源
gcry_sexp_release(data);
gcry_sexp_release(r_sig);
gcry_sexp_release(priv);
gcry_sexp_release(pub);
gcry_sexp_release(keypair);

额外注意事项

  • 永远不要忽略gcrypt函数的返回值:assert只适合调试阶段,生产环境必须检查每个gcrypt调用的gcry_error_t返回值,避免潜在的崩溃或安全问题。
  • S表达式是gcrypt的核心数据格式,必须严格遵循其语法规则,任何括号不匹配、格式错误都会导致"Invalid Object"这类错误。
  • 如果需要直接传入字节数组,也可以使用gcry_sexp_build的占位符语法,比如:
    unsigned char raw_data[] = {100, 2, 254, 88, 90, 45, 23};
    err = gcry_sexp_build(&data, nullptr, "(data (flags raw) (value %b))", raw_data, sizeof(raw_data));
    
    这种方式更直观,也避免了手动转换十六进制的麻烦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 16:22:30