OpenSSL ECDSA 签名比预期长 [英] OpenSSL ECDSA signatures longer than expected
问题描述
我正在尝试生成用于加密芯片的原始"、未编码的 ECDSA 签名.目标是在主机 pc 上签署某些内容,然后将其发送到芯片进行验证.但是,我遇到了一个小问题.我的理解是 ECDSA 签名应该是 64 个字节(对于 secp256v1).而且,当我使用芯片生成签名时,它的长度确实是 64 个字节.但是,当我使用 openssl 时,签名的长度是 71 个字节.签名的开头似乎是某种前缀,但我找不到关于它是什么的任何数据.
这是我尝试做所有事情的方式:
生成密钥:
openssl ecparam -genkey -name secp256r1 -noout -out privkeyv1.pem
生成要签名的消息":
echo -n "Hello World" >测试.txt
我尝试了两种签署消息的方法.两者都会导致相同的意外输出.
第一种方法 - 生成测试文件的 sha256 哈希值,然后对其进行签名:
sha256sum test.txt |cut -f 1 -d " " >散列
使用 pkutil 签名
openssl pkeyutl -sign -in hash -inkey privkeyv1.pem -out test_sig_meth1
方法二:用openssl dgst签名
如您所见,这两种方法在开头都会生成一些看起来像头字节的字节( 问题:我如何使用 openssl 生成一个 64 字节的原始(未编码,没有标头)ECDSA 签名,我可以在这个方案中使用? 出于效率原因,大多数芯片只会将 要从这样的序列转换,您可以首先使用 BER 解析器进行 BER 解码以检索整数.然后实现一个 I2OSP 算法(整数到八位字节流原语),它需要以字节/八位字节为单位的值和密钥大小作为参数.该数字应该是大整数形式,但这很好,因为 ASN.1 BER 编码的整数也是大整数.如果数字太小,基本上你必须用零字节填充.然后连接数字. 我不会进入将字节数组转换为整数的 OS2IP.请注意,如果您以 BER 形式对其进行编码,那么整数应该不用零字节填充.所以仍然需要一些技巧. 所以尽管签名改变了形式,但签名仍然有效;你可以简单地在一种形式和另一种形式之间进行转换,签名仍然会验证 - 只要你使用正确的库来完成这项工作,显然. I am attempting to generate "raw", unencoded ECDSA signatures for use with a cryptographic chip. The goal is to sign something on the host pc, then send it to the chip to be validated. However, I am running into a little problem. My understanding is that the ECDSA signature should be 64 bytes (for secp256v1). And, when I use the chip to generate a signature, it is indeed 64 bytes in length. However, when I use openssl, the signature is 71 bytes in length. The beginning of the signature seems to be some kind of prefix, but I can't find any data about what that is. Here is how I am trying to do everything: Generate the key: Generate the "message" to be signed: I have tried two methods for signing the message. Both lead to the same, unexpected output. First method - generate sha256 hash of test file, then sign it: Sign with pkutil Method 2: Sign with openssl dgst And the output of As you can see, both of these methods generate some bytes at the beginning that look like header bytes (the The question: How can I use openssl to generate a 64 byte raw (unencoded, with no header) ECDSA signature I can use with this scheme? Most chips will, for efficiency reasons, just output the To convert from such a sequence you can first BER decode using a BER parser to retrieve the integer. Then implement an I2OSP algorithm (integer to octet stream primitive) which requires the value and the key size in bytes/octets as arguments. The number should be in big integer form, but that's fine as ASN.1 BER encoded integers are also big integers. Basically you must left pad with zero bytes if the number is too small. Then you concatenate the number. I won't go into OS2IP which converts a byte array to an integer. Note thought that if you encode it in BER form then the integers should not be left padded with zero bytes. So some trickery is required still. So although the signature changes form, the signature still stays valid; you can simply convert between one form and the other and the signature will still verify - as long as you use the right library for the job, obviously. 这篇关于OpenSSL ECDSA 签名比预期长的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!openssl dgst -sha256 -binary -sign privkeyv1.pem -out test_sig_meth2 test.txt
问题:这是 xxd -p -c 256 test_sig_meth1
的输出:3045022000a86fb146d5f8f6c15b962640bc2d1d928f5e0f96a5924e4db2853ec8b66fb002210085431613d0a230909a408c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c86e0f96a5924e4db28532000
xxd -p -c 256 test_sig_meth2
的输出:30450220693732cd53d9f2ba3deae213d74cdf69a00e7325a10ddc6a4445ff2b33f95e62022100b6d2561e3afba10f95247ed09022100b6d2561e3afba10f95247ed0905c8c6e8c8c6e8c8c8c5c8c6e8c80dc8c8dc5c8dc8dc8c8dc6e8c6e8c80dc6e8c10ddc6a4450e7325a10ddc6a
30450220
,可能更长),但我不确定它们的用途或方法删除它们.作为参考,这里是在加密芯片上生成的相同方法的签名.如果删除末尾的空字节填充,则为 64 字节.<代码> 4677AD09F2AF49D7445ED5D6AC7253ADC863C6D5DB6D3CFBF9C6D3E221D0A7BA2561942524F46B590AEES749D827FBF80A961E85503A7D85C75FE48ADBC0BD000000000 r
和 s
作为字节数组或八位字节字符串,其中每个r
和s
与八位字节中的字段大小(即密钥大小)相同.另一种方法是将 r
和 s
作为数字序列输出,因为最终,这就是 r
和 s
是.使用 ASN.1,这将变成整数值的序列.openssl ecparam -genkey -name secp256r1 -noout -out privkeyv1.pem
echo -n "Hello World" > test.txt
sha256sum test.txt | cut -f 1 -d " " > hash
openssl pkeyutl -sign -in hash -inkey privkeyv1.pem -out test_sig_meth1
openssl dgst -sha256 -binary -sign privkeyv1.pem -out test_sig_meth2 test.txt
The issue: Here is the output of xxd -p -c 256 test_sig_meth1
:
3045022000a86fb146d5f8f6c15b962640bc2d1d928f5e0f96a5924e4db2853ec8b66fb002210085431613d0a235db1adabc090cc1062a246a78941972e298423f4b3d081b48c8
xxd -p -c 256 test_sig_meth2
:
30450220693732cd53d9f2ba3deae213d74cdf69a00e7325a10ddc6a4445ff2b33f95e62022100b6d2561e3afba10f95247ed05f0c59620dc0913f0d798b4148e05c4116b6384e
30450220
, maybe longer), but I am not sure what they are for or how to remove them. For reference, here is a a signature of the same method generated on the crypto chip. If you remove the null byte padding at the end, it's 64 bytes. 4677AD09F2AF49D7445ED5D6AC7253ADC863EC6D5DB6D3CFBF9C6D3E221D0A7BA2561942524F46B590AEE749D827FBF80A961E884E3A7D85EC75FE48ADBC0BD00000000000000000000000
r
and s
as a byte array or octet string, where each r
and s
is the same as the field size (i.e. key size) in octets. Another approach is to output r
and s
as a sequence of numbers, because in the end, that is what r
and s
are. Using ASN.1 this becomes a SEQUENCE of INTEGER values.