使用 Crypto++ 将签名从 P1363 转换为 ASN.1/DER 格式?

pip*_*pou 5 c++ cryptography crypto++ der

我有一个以这种方式创建的签名:

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());
Run Code Online (Sandbox Code Playgroud)

我的签名大小为 64,包含:

ECCD530E5F232B7C566CA5322F990B3D55ED91156DF3845C4B9105BFE57606DDD68F332A0A5BF7CAB673E4970D10109B72F11457ACD78CED11457ACD7894ED

从我在dsa.h文件中阅读的内容来看,这个签名目前是DSA_P1363格式。我需要将其转换为DSA_DER格式。

要执行此操作,我尝试:

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);
Run Code Online (Sandbox Code Playgroud)

此转换的输出如下所示。它似乎只是签名的第一部分。它的大小为 8,包含:

300D020500ECCD53

怎么了?

谢谢。

jww*_*jww 3

这个转换的输出很奇怪,它似乎只是签名的第一部分。它的大小为 8,包含:

300D020500ECCD53
Run Code Online (Sandbox Code Playgroud)

怎么了 ?

代替:

size_t converted_size = DSAConvertSignatureFormat(
    (byte*) (derSign.data()), sizeof(derSign.data()), DSA_DER,
    (byte*) (signature.data()), sizeof(signature.data()), DSA_P1363);
Run Code Online (Sandbox Code Playgroud)

你应该使用类似的东西:

size_t converted_size = DSAConvertSignatureFormat(
    (byte*) (derSign.data()), derSign.size(), DSA_DER,
    (const byte*) (signature.data()), signature.size(), DSA_P1363);
Run Code Online (Sandbox Code Playgroud)

sizeof(derSign.data())产生sizeofa size_t,它与字符串数据的大小不同。

另外,由于derSign正在写入,因此您需要一个非常量指针。几乎所有 C++ 版本的实现方法都是使用第一个元素的地址:

size_t converted_size = DSAConvertSignatureFormat(
    (byte*) (&derSign[0]), derSign.size(), DSA_DER,
    (const byte*) (signature.data()), signature.size(), DSA_P1363);
Run Code Online (Sandbox Code Playgroud)

几乎最后,这就是 P1363 中的内容,其中rs是一个串联,每个都基于字段元素的大小和子组顺序:

[ r ] [ s ]
Run Code Online (Sandbox Code Playgroud)

这就是您在 ASN.1/DER 中所需要的。有 3 个 ASN.1 对象 - 一个序列和两个整数。每个对象需要 1 个八位字节用于 ASN.1 类型,最多需要 2 个八位字节用于长度。rs是字段元素的大小。r每个 ASN.1 整数可能需要一个前导 0,因此为和 都添加两个附加字节s

SEQUENCE = {
    INTEGER r;
    INTEGER s;
}
Run Code Online (Sandbox Code Playgroud)

因此,对于 ASN.1/DER 缓冲区,您需要 3+3+3+COUNTOF(r)+1+COUNTOF(s)+1。

最后,该片段可能如下所示:

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);
Run Code Online (Sandbox Code Playgroud)

Crypto++ 现在在 wiki 上有一个页面,网址为DSAConvertSignatureFormatDSAConvertSignatureFormatECDSA有一个使用示例| OpenSSL 和 Java,但转换是相反的。

(您的问题和缺乏文档实际上引发了一个错误,我们缩小了差距)。


我刚刚注意到这个...

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());
Run Code Online (Sandbox Code Playgroud)

而是使用这个:

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);
Run Code Online (Sandbox Code Playgroud)