问题
I have a signature created this way:
size_t siglenth = _signer.MaxSignatureLength();
QByteArray signature(siglenth, 0x00);
signature.reserve(siglenth);
siglenth = _signer.SignMessage(_prng,
(const CryptoPP::byte*) (message.constData()),
message.length(), (CryptoPP::byte*) signature.data());
My signature have a size of 64 and contains:
ECCD530E5F232B7C566CA5322F990B3D55ED91156DF3845C4B9105BFE57606DDD68F332A0A5BF7CAB673E4970D10109B72F114571E7474F93ED7C89CD1B89AD4
From what I have read in dsa.h
file this signature is currently in DSA_P1363
format. I need to convert it to DSA_DER
format.
To perform this action I try :
QByteArray derSign(70, 0xFF);
size_t converted_size = CryptoPP::DSAConvertSignatureFormat(
(CryptoPP::byte*) (derSign.data()), sizeof(derSign.data()), CryptoPP::DSA_DER,
(CryptoPP::byte*) (signature.data()), sizeof(signature.data()), CryptoPP::DSA_P1363);
The output of this conversion is shown below. It seems to be only the first part of the signature. It has a size of 8 and contains:
300D020500ECCD53
What is wrong?
Thanks.
回答1:
The output of this convertion is curious, it seems to be only the first part of the signature. It have a size of 8 and contains :
300D020500ECCD53
What is wrong ?
Instead of:
size_t converted_size = DSAConvertSignatureFormat( (byte*) (derSign.data()), sizeof(derSign.data()), DSA_DER, (byte*) (signature.data()), sizeof(signature.data()), DSA_P1363);
You should use something like:
size_t converted_size = DSAConvertSignatureFormat(
(byte*) (derSign.data()), derSign.size(), DSA_DER,
(const byte*) (signature.data()), signature.size(), DSA_P1363);
sizeof(derSign.data())
yields the sizeof
a size_t
, which is different then the size of the string data.
Also, since derSign
is being written to, you need a non-const pointer. The way to get that with nearly all versions of C++ is using the address of the first element:
size_t converted_size = DSAConvertSignatureFormat(
(byte*) (&derSign[0]), derSign.size(), DSA_DER,
(const byte*) (signature.data()), signature.size(), DSA_P1363);
Nearly finally, this is what you have in P1363, where r
and s
are a concatenation and each is based on the size of a field element and subgroup order:
[ r ] [ s ]
This is what you need in ASN.1/DER. There are 3 ASN.1 objects - one sequence and two integers. Each object needs one octet for the ASN.1 type, and at most two octets for the length. r
and s
are the size of the field element. Each ASN.1 integer may need a leading 0, so add two additional bytes for both r
and s
.
SEQUENCE = {
INTEGER r;
INTEGER s;
}
So, for the ASN.1/DER buffer, you need 3+3+3+COUNTOF(r)+1+COUNTOF(s)+1.
Finally, the snippet may look like:
using namespace CryptoPP;
// ... Other gyrations
std::string derSign, signature;
// ...Calculate signature
// Make room for the ASN.1/DER encoding
derSign.resize(3+3+3+2+signature.size())
size_t converted_size = DSAConvertSignatureFormat(
(byte*) (&derSign[0]), derSign.size(), DSA_DER,
(const byte*) (signature.data()), signature.size(), DSA_P1363);
ASSERT(converted_size <= derSign.size());
derSign.resize(converted_size);
Crypto++ now has a page on the wiki at DSAConvertSignatureFormat. There is an example of using DSAConvertSignatureFormat
at ECDSA | OpenSSL and Java, but the conversion is going the other way.
(Your question and lack of documentation effectively triggered a bug, and we closed the gap).
I just noticed this...
size_t siglenth = _signer.SignatureLength(); QByteArray signature(siglenth, 0x00); signature.reserve(siglenth); siglenth = _signer.SignMessage(_prng, (const CryptoPP::byte*) (message.constData()), message.length(), (CryptoPP::byte*) signature.data());
Instead use this:
QByteArray signature;
size_t siglenth = _signer.SignatureLength();
signature.resize(siglenth);
siglenth = _signer.SignMessage(_prng,
(const byte*) (message.constData()), message.length(),
(byte*) (&signature[0]));
signature.resize(siglenth);
来源:https://stackoverflow.com/questions/58097935/convert-signature-from-p1363-to-asn-1-der-format-using-crypto