OpenSSL偶尔会生成错误的签名 我有一个C++程序,ECDSA密钥对和一些要签名的字符串。程序生成签名并将其保存到文件中(signature.bin)。然后,我通过以下命令检查签名的有效性: openssl dgst -verify ec_public.pem -signature signature.bin ToSign.txt

OpenSSL偶尔会生成错误的签名 我有一个C++程序,ECDSA密钥对和一些要签名的字符串。程序生成签名并将其保存到文件中(signature.bin)。然后,我通过以下命令检查签名的有效性: openssl dgst -verify ec_public.pem -signature signature.bin ToSign.txt,openssl,sign,ecdsa,Openssl,Sign,Ecdsa,问题是程序有时会生成错误的签名。上述21个命令输出中的16次: Error Verifying Data 而在其余5次出现时,它输出: Verified OK 怎么可能呢 节目如下: SSL_library_init(); OPENSSL_config(nullptr); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); ERR_load_BIO_strings(); CRYPTO_set_id_callback(ThreadId

问题是程序有时会生成错误的签名。上述21个命令输出中的16次:

Error Verifying Data
而在其余5次出现时,它输出:

Verified OK
怎么可能呢

节目如下:

SSL_library_init();
OPENSSL_config(nullptr);
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
ERR_load_BIO_strings();
CRYPTO_set_id_callback(ThreadIdFunction);
CRYPTO_set_locking_callback(LockingFunction);

const TString pk = "-----BEGIN EC PRIVATE KEY-----\n"
                       "MHcCAQEEIG90zmo1o3NWNFa8wp2z4rdQXGSN8xAP/OATLpwlgi+1oAoGCCqGSM49\n"
                       "AwEHoUQDQgAE5TwpzBhjUWZoOf629GfwGG5WlRJD7TSuz+ZTHUaiK5mj2qgxBOPk\n"
                       "eqOrTYXsiPwnaWe23zHjIM8NOhAm1BiGgA==\n"
                       "-----END EC PRIVATE KEY-----\n";

const TString ToSign = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhc2RmIn0";

EVP_MD_CTX *Ctx    = EVP_MD_CTX_create();
BIO *       Bio    = BIO_new_mem_buf(pk.data(), pk.size());
EVP_PKEY *  EVPKey = PEM_read_bio_PrivateKey(Bio, nullptr, nullptr, nullptr);

EVP_DigestSignInit(Ctx, nullptr, EVP_sha256(), nullptr, EVPKey);
EVP_DigestSignUpdate(Ctx, ToSign.data(), ToSign.size());
size_t SignatureLength;
EVP_DigestSignFinal(Ctx, nullptr, &SignatureLength);

TString Result;
Result.resize(SignatureLength);
EVP_DigestSignFinal(Ctx, reinterpret_cast<unsigned char *>(const_cast<char *>(Result.data())), &SignatureLength);

// Saving to file...
SSL_库_init();
OPENSSL_配置(nullptr);
SSL_加载_错误_字符串();
OpenSSL_添加_所有算法();
ERR_load_BIO_strings();
加密集id回调(ThreadIdFunction);
加密设置锁定回调(锁定函数);
const TString pk=“----开始EC私钥------\n”
“MHCCAQEEIG90ZMO3NWFA8WP2Z4RDQXGSN8MAP/OATLpwlgi+1AOGCCQGSM49\n”
“AwEHoUQDQgAE5TwpzBhjUWZoOf629GfwGG5WlRJD7TSuz+zthaik5mj2qgxbopk\n”
“eqOrTYXsiPwnaWe23zHjIM8NOhAm1BiGgA==\n”
“----结束EC私钥------\n”;
const TString to sign=“eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhc2RmIn0”;
EVP_MD_CTX*CTX=EVP_MD_CTX_create();
BIO*BIO=BIO_new_mem_buf(pk.data(),pk.size());
EVP_PKEY*EVPKey=PEM_read_bio_PrivateKey(bio,nullptr,nullptr,nullptr);
执行副总裁(Ctx、nullptr、执行副总裁sha256()、nullptr、EVPKey);
EVP_DigestSignUpdate(Ctx,ToSign.data(),ToSign.size());
尺寸标志长度;
EVP_DigestSignFinal(Ctx、nullptr和SignatureLength);
t串结果;
结果。调整大小(SignatureLength);
EVP_DigestSignFinal(Ctx、重新解释强制转换(const_强制转换(Result.data())、&SignatureLength);
//正在保存到文件。。。

您正在调用正确的OpenSSL方法。但是,您没有详细说明如何将
结果
保存到文件中。根据其名称,
TString
可能表现为以0结尾的字符串。如果是这样,则签名将不会正确写入文件,而是在文件包含0字节时过早截断。请注意,ECDSA签名步骤包括一个随机组件,因此每次运行代码时签名都是不同的

下面的推理支持这种猜测,并大致解释了代码失败和成功的原因。如果您阅读,您将看到0字节在此类签名中非常常见。对于组合的
r
s
组件的第一个字节,概率约为3/4。然后还有一个额外的概率,即1-(255/256)^64,大约1/4,剩余的64个字节将包含一个0。因此,失效概率约为3/4+1/4*1/4,约为80%

您的示例空间很小,但考虑到该字符串错误,21次尝试中可能有5次成功