我正在使用
创建密钥对ECDSA<ECP, SHA256>::Signer signer;
signer.AccessKey().Initialize(randomGeneratorM, ASN1::secp160r1());
...
ECDSA<ECP, SHA256>::PublicKey publicKey;
signer.AccessKey().MakePublicKey(publicKey);
加载,保存,签名和验证工作正常。但是我的签名总是42个字节,当我预期它是“40”时(是160个密钥位的两倍)。
签名生成为:
std::string data ...
ECDSA<ECP, SHA256>::Signer signer(privateKey);
byte signatureBuffer[42];
size_t signatureLength = signer.SignMessage(
randomGeneratorM, (const byte*)data.c_str(), data.size(), signatureBuffer);
我找不到任何可能编码签名的文档。所以我很好奇:额外的字节来自哪里?
事实上,signer.MaxSignatureLength()
返回“42”,对于目前为止生成的所有签名,签名长度绝不是其他任何签名。
我知道“42”是生命,宇宙和一切的答案;)
哦,和CryptoPP V5.6.2,Visual Studio 2008
样本签名(十六进制):
00F9C6853895481DDA23517DE16AA44518CDB2C9A900FF9AACA718DFB2AAA9C10E45265224EC40C7FD63
答案 0 :(得分:3)
我找不到任何可能编码签名的文档。所以我很好奇:额外的字节来自哪里?
Crypto ++使用{R,S}
元组的IEEE P1363编码,这是一个简单的连接。 42是MaxImage()
大小,这是签名最大的大小。这是基于P1363标准下{R,S}
元组的编码。
如果感兴趣,我们会在Cryptographic Interoperability: Digital Signatures讨论数字签名格式。
00F9C6853895481DDA23517DE16AA44518CDB2C9A900FF9AACA718DFB2AAA9C10E45265224EC40C7FD63
这突破到:
00F9C6853895481DDA23517DE16AA44518CDB2C9A9
00FF9AACA718DFB2AAA9C10E45265224EC40C7FD63
是两个ASN.1编码值的串联,不带整数类型信息。 Crypto ++知道R
和S
的大小,因为它是域参数的组成部分。具体来说,它的ASN1::secp160r1()
是160位曲线。
ASN.1整数是两个恭维编码(见ITU的X.690 Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)和朋友),R
和S
每个IEEE P1363都是正数(参见IEEE的P1363第5.6节)。 1 Converting Between Integers and Bit Strings)。所以你必须有一个领先的0x00
八位字节。
如果您使用secp256r1()
,那么MaxImage()
和MaxSignatureLength()
会相应增加。
为了完整性,Java使用不同形式的编码。这是:
SEQUENCE ::= {
r INTEGER,
s INTEGER
}
这意味着ASN.1整数编码有20个八位字节r
加2个八位字节,ASN.1整数编码有20个八位字节s
加2个八位字节,序列编码有2个八位字节。总共46个八位字节。如果{2}赞美格式中r
或s
为负,则需要为前导0x00八位字节添加一个字节。所以它可能是48个字节。
Crypto ++提供了一种在名为DSAConvertSignatureFormat
的P1363,Java和OpenPGP签名之间进行转换的功能。您可以在dsa.cpp中看到源代码(这里没有太多内容)。