ECDSA签名大小太长了?

时间:2013-11-28 12:34:08

标签: c++ crypto++

我正在使用

创建密钥对
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

1 个答案:

答案 0 :(得分:3)

  

我找不到任何可能编码签名的文档。所以我很好奇:额外的字节来自哪里?

Crypto ++使用{R,S}元组的IEEE P1363编码,这是一个简单的连接。 42是MaxImage()大小,这是签名最大的大小。这是基于P1363标准下{R,S}元组的编码。

如果感兴趣,我们会在Cryptographic Interoperability: Digital Signatures讨论数字签名格式。


  

00F9C6853895481DDA23517DE16AA44518CDB2C9A900FF9AACA718DFB2AAA9C10E45265224EC40C7FD63

这突破到:

00F9C6853895481DDA23517DE16AA44518CDB2C9A9
00FF9AACA718DFB2AAA9C10E45265224EC40C7FD63

是两个ASN.1编码值的串联,不带整数类型信息。 Crypto ++知道RS的大小,因为它是域参数的组成部分。具体来说,它的ASN1::secp160r1()是160位曲线。

ASN.1整数是两个恭维编码(见ITU的X.690 Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)和朋友),RS每个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}赞美格式中rs为负,则需要为前导0x00八位字节添加一个字节。所以它可能是48个字节。


Crypto ++提供了一种在名为DSAConvertSignatureFormat的P1363,Java和OpenPGP签名之间进行转换的功能。您可以在dsa.cpp中看到源代码(这里没有太多内容)。