gpt4 book ai didi

c++ - 如何从 Crypto++ ECDSA 中的签名体获取签名长度

转载 作者:行者123 更新时间:2023-11-30 04:44:16 24 4
gpt4 key购买 nike

我使用 Crypto++ (libcrypto++ 1.11) 在我的应用程序中嵌入 JWT。我制作了使用 CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256> 签名和验证消息的方法算法(带有 secp256r1 曲线)。用于验证的 token 可以来自外部世界,因此我需要在知道公钥的情况下验证 token 内容(文本数据)签名。

问题是 Crypto++ 会导致无效签名的 SegFault,这给我的 Web 服务器带来了很多痛苦。

我希望 BER 格式(库中默认的序列化格式)的签名具有固定长度,所以我只需要将签名的长度与某个常量进行比较即可。但是,我发现更大的内容会产生更大的签名,因此需要更深入的方法。

bool ES256Verifier::Verify(const std::string& data,
const std::string& signature) {
bool result = false;
try {
CryptoPP::StringSource ss(
signature + data, true,
new CryptoPP::SignatureVerificationFilter(
verifier_,
new CryptoPP::ArraySink((byte*)&result, sizeof(result))));
} catch (const CryptoPP::BERDecodeErr& err) {
LOG_WARNING() << "Signature `" << signature << "` has invalid (non-BER) format";
} catch (const CryptoPP::Exception& ex) {
LOG_WARNING() << "Signature verification has failed: " << ex.what();
}
return result;
}

验证者 verifier_已正确初始化(并成功验证 token ,除了 SegFaults),但给定 data = ""signature = "" ,例如,我总是得到 SegFault:

__memmove_avx_unaligned_erms 0x00007fb4b9da6b38
CryptoPP::ArraySink::Put2(unsigned char const*, unsigned long, int, bool) 0x00007fb4ba414fb2
CryptoPP::BufferedTransformation::ChannelPut2(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned char const*, unsigned long, int, bool) 0x00007fb4ba3acedc
CryptoPP::StringStore::CopyRangeTo2(CryptoPP::BufferedTransformation&, unsigned long long&, unsigned long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool) const 0x00007fb4ba414e02
CryptoPP::BufferedTransformation::Peek(unsigned char*, unsigned long) const 0x00007fb4ba3ad74a
CryptoPP::Integer::Decode(CryptoPP::BufferedTransformation&, unsigned long, CryptoPP::Integer::Signedness) 0x00007fb4ba45885c
CryptoPP::Integer::Decode(unsigned char const*, unsigned long, CryptoPP::Integer::Signedness) 0x00007fb4ba458c16
CryptoPP::DL_VerifierBase<CryptoPP::ECPPoint>::InputSignature pubkey.h:1560
CryptoPP::SignatureVerificationFilter::LastPut(unsigned char const*, unsigned long) 0x00007fb4ba4159a0
CryptoPP::FilterWithBufferedInput::PutMaybeModifiable(unsigned char*, unsigned long, int, bool, bool) 0x00007fb4ba418107
CryptoPP::BufferedTransformation::ChannelPut2(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned char const*, unsigned long, int, bool) 0x00007fb4ba3acedc
CryptoPP::BufferedTransformation::TransferMessagesTo2(CryptoPP::BufferedTransformation&, unsigned int&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool) 0x00007fb4ba3ad8fa
CryptoPP::BufferedTransformation::TransferAllTo2(CryptoPP::BufferedTransformation&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool) 0x00007fb4ba3adb21
CryptoPP::SourceTemplate<CryptoPP::StringStore>::PumpAll2 filters.h:1238
CryptoPP::Source::PumpAll filters.h:1182
CryptoPP::Source::SourceInitialize filters.h:1215
CryptoPP::StringSource::StringSource filters.h:1271
jwt::signature::algorithm::ES256Verifier::Verify es256_verifier.cpp:40
ES256_SignatureTest_Test::TestBody es256_test.cpp:29
...

那么,有没有办法查看数据和签名,并确定这种特定组合是否会由于签名长度无效而导致 SegFault?

最佳答案

下面是一些使用字段元素、签名者和验证者确定签名长度的示例代码。第一个输出打印元素长度和 r||s 长度,因为 r||s 是 P1363 格式的签名。

第二个和第三个输出只是打印SignatureLength() 的结果。您的程序应该拒绝短于 SignatureLength() 的签名。甚至尝试验证一个简短的签名也没有意义,因为它不好。

请注意:这仅适用于 DL_* 签名方案(基于离散日志)。它不适用于TF_* 签名方案(基于陷门函数)。

#include "cryptlib.h"
#include "eccrypto.h"
#include "osrng.h"
#include "oids.h"

#include <iostream>

int main(int argc, char* argv[])
{
using namespace CryptoPP;
AutoSeededRandomPool prng;

///// Element
DL_GroupParameters_EC<ECP> params(ASN1::secp256r1());

unsigned int elemLength = params.GetCurve().GetField().MaxElementByteLength();
std::cout << "Element length: " << elemLength << std::endl;
std::cout << "r||s length: " << 2*elemLength << std::endl;

///// Signer
ECDSA<ECP, SHA256>::Signer signer;
signer.AccessKey().Initialize(prng, params);

unsigned int signerLength = signer.SignatureLength();
std::cout << "Signer signature length: " << signerLength << std::endl;

///// Verifier
ECDSA<ECP, SHA256>::Verifier verifier(signer);

unsigned int verifierLength = verifier.SignatureLength();
std::cout << "Verifier signature length: " << verifierLength << std::endl;

return 0;
}

运行程序结果如下。

$ ./test.exe
Element length: 32
r||s length: 64
Signer signature length: 64
Verifier signature length: 64

如果将曲线切换为 ASN1::secp521r1(),则运行程序会产生以下结果。

$ ./test.exe
Element length: 66
r||s length: 132
Signer signature length: 132
Verifier signature length: 132

关于c++ - 如何从 Crypto++ ECDSA 中的签名体获取签名长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57872901/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com