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))");
- 括号不匹配:整个S表达式最外层是
(data ...),内部嵌套了(value ...),但你最后只写了一个闭合括号,缺少一个)来闭合最外层的(data。 - 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(¶ms, 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
相关产品推荐
相关产品推荐

