OpenSSL ECDSA签名比预期更长 [英] OpenSSL ECDSA signatures longer than expected

查看:203
本文介绍了OpenSSL ECDSA签名比预期更长的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试生成原始"未编码的ECDSA签名以与加密芯片一起使用.目的是在主机PC上签名,然后将其发送到芯片进行验证.但是,我遇到了一个小问题.我的理解是ECDSA签名应为64字节(对于secp256v1).而且,当我使用芯片生成签名时,它的确确实是64个字节的长度.但是,当我使用openssl时,签名的长度为71个字节.签名的开头似乎是某种前缀,但我找不到有关该前缀的任何数据.

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:

生成密钥:

openssl ecparam -genkey -name secp256r1 -noout -out privkeyv1.pem

生成要签名的消息":

echo -n "Hello World" > test.txt

我尝试了两种方法来对邮件签名.两者都导致相同的意外输出.

I have tried two methods for signing the message. Both lead to the same, unexpected output.

第一种方法-生成测试文件的sha256哈希,然后对其签名:

First method - generate sha256 hash of test file, then sign it:

sha256sum test.txt | cut -f 1 -d " " > hash

用pkutil签名

openssl pkeyutl -sign -in hash -inkey privkeyv1.pem -out test_sig_meth1

方法2:使用openssl dgst登录

Method 2: Sign with openssl dgst

openssl dgst -sha256 -binary -sign privkeyv1.pem -out test_sig_meth2 test.txt 问题:这是xxd -p -c 256 test_sig_meth1的输出: 3045022000a86fb146d5f8f6c15b962640bc2d1d928f5e0f96a5924e4db2853ec8b66fb002210085431613d0a235db1adabc090cc1062a246a78941972e298423f4b3d081b48c8

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,可能更长),但是我不确定它们的用途或如何删除它们.作为参考,这是在加密芯片上生成的相同方法的签名.如果在最后删除空字节填充,则为64个字节. 4677AD09F2AF49D7445ED5D6AC7253ADC863EC6D5DB6D3CFBF9C6D3E221D0A7BA2561942524F46B590AEE749D827FBF80A961E884E3A7D85EC75FE48ADBC0BD00000000000000000000000

As you can see, both of these methods generate some bytes at the beginning that look like header bytes (the 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

问题:如何使用openssl生成可用于此方案的64字节原始(未编码,无标头)ECDSA签名?

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?

推荐答案

出于效率原因,大多数芯片只会将rs输出为字节数组或八位字节串,其中每个rs与八位字节中的字段大小(即密钥大小)相同.另一种方法是将rs作为数字序列输出,因为最后,这就是rs的含义.使用ASN.1,它将成为INTEGER值的序列.

Most chips will, for efficiency reasons, just output the 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.

要从这样的序列进行转换,您可以先使用BER解析器进行BER解码以检索整数.然后实现一个I2OSP算法(整数到八位字节流原语),该算法需要以字节/八位字节为单位的值和密钥大小作为参数.该数字应采用大整数形式,但这很好,因为ASN.1 BER编码的整数也是大整数.基本上,如果数字太小,则必须保留零字节填充.然后将数字连接起来.

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.

我不会进入将字节数组转换为整数的OS2IP.请注意,如果您以BER形式对其进行编码,则整数不应填充零字节.因此仍然需要一些技巧.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆