在签名之前,用于ECDSA的OpenSSL -sign是否将ASN1编码应用于哈希? [英] Does OpenSSL -sign for ECDSA apply ASN1 encoding to the hash before signing?

查看:144
本文介绍了在签名之前,用于ECDSA的OpenSSL -sign是否将ASN1编码应用于哈希?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此SO问题使用OpenSSL而不使用ASN1编码的ECDSA标志hash 在对散列进行签名之前将OpenSSL perfoms ASN1编码声明为散列.

This SO question ECDSA sign using OpenSSL without ASN1 encoding the hash states the OpenSSL perfoms ASN1 encoding to the hash before signing it.

换句话说,当椭圆曲线键-sign被调用时,它指出OpenSSL执行以下步骤: 一种.计算H =哈希(M) b.将H编码为ASN1标准-H’ C.签名H’

In other words it states that OpenSSL performs the following steps when for an Elliptic curve key -sign is called: a. Calculate H = Hash(M) b. Encode H into ASN1 standard- H’ c. Sign H’

因此,为避免应用步骤b,有必要先计算摘要,然后使用原始签名-椭圆曲线键的pkeyutl对摘要进行签名

And thus to avoid applyting step b it's neccessary to first calculate the digest, and then sign the digest using raw signing - pkeyutl for elliptic curver keys

但是,当我同时运行-sign和-dgst + -pkeyutl时,在两种情况下我都可以使用-verify来验证签名.这意味着未将ASN1编码应用于哈希.

However when I run BOTH -sign and -dgst+ -pkeyutl I am able to verify the signature using -verify in both cases. This implies that ASN1 encoding is NOT being applied to the hash.

任何人都可以在这个话题上有所启发吗?我无法在OpenSSL文档中找到文档.

Can anyone throw some light on this topic? I was not able to find documentation in the OpenSSL documentation.

推荐答案

OpenSSL将ASN.1 DER编码应用于签名的输出.

OpenSSL applies ASN.1 DER encoding to the output of the signature.

https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Signature_generation_algorithm

https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Signature_generation_algorithm

  1. 计算e = HASH (m),其中HASH是加密哈希函数,例如SHA-2.
  2. ze的最左侧Ln位,其中Ln是组顺序n的位长.
  3. [1, n - 1]中选择一个加密安全的随机整数k.
  4. 计算曲线点(x1, y1) = k x G.
  5. 计算r = x1 mod n.如果是r = 0,请返回步骤3.
  6. 计算s = (k − 1) x (z + r * dA) mod n.如果是s = 0,请返回步骤3.
  7. 签名是对(r, s).
  1. Calculate e = HASH (m), where HASH is a cryptographic hash function, such as SHA-2.
  2. Let z be the Ln leftmost bits of e , where Ln is the bit length of the group order n.
  3. Select a cryptographically secure random integer k from [1, n - 1].
  4. Calculate the curve point (x1, y1) = k x G.
  5. Calculate r = x1 mod n. If r = 0, go back to step 3.
  6. Calculate s = (k − 1) x (z + r * dA) mod n. If s = 0, go back to step 3.
  7. The signature is the pair (r, s).

问题在于ECDSA算法以数学结尾,而不是以字节结尾.对于如何将那对数字转换为字节,已经出现了两种不同的约定. (与RSA相反,后者的最后一步是如何将数学值转换为字节并声明该字节序列为签名).

The problem is that the ECDSA algorithm ends with math, not with bytes. Two different conventions have arisen for how to turn that pair of numbers into bytes. (Contrast with RSA, whose last step says how to turn the mathematical value back into bytes and declares that byte sequence to be the signature).

我们断言我们针对r = 67432751043532511959904657272700966685609390316545000351652696368910338707793s = 15800012655857962601029927988066555130680701005265153794330961生成了一个签名(针对secp256r1).

Let's assert that we produced a signature (against secp256r1) with r = 67432751043532511959904657272700966685609390316545000351652696368910338707793 and s = 15800012655857962601029927988066555130680701005265153794330961.

由X.509/PKIX和OpenSSL使用.首先由 RFC 3279,秒2.2.3声明(无论如何,我仍然可以找到) :

Used by X.509/PKIX and OpenSSL. First declared (that I can find, anyways) by RFC 3279, sec 2.2.3:

签名时,ECDSA算法生成两个值.这些值 通常称为r和s.轻松转移这两个 值作为一个签名,它们必须使用ASN.1编码 遵循ASN.1结构:

When signing, the ECDSA algorithm generates two values. These values are commonly referred to as r and s. To easily transfer these two values as one signature, they MUST be ASN.1 encoded using the following ASN.1 structure:

Ecdsa-Sig-Value  ::=  SEQUENCE  {
     r     INTEGER,
     s     INTEGER  }

如果我们从内到外构建DER,效果最好,所以让我们对r进行编码.

DER works best if we build it inside out, so let's encode r.

r是整数,十进制的67432751043532511959904657272700966685609390316545000351652696368910338707793或十六进制的951595A548D156D51655159654ADA548D156D5165195159654ADA54D156D5151.

r is an integer, 67432751043532511959904657272700966685609390316545000351652696368910338707793 in decimal, or 951595A548D156D51655159654ADA548D156D5165195159654ADA54D156D5151 hex. ITU-T-REC-X.690-201508 says that the integer gets encoded as a signed big endian value. Since the most significant byte (0x95) has the high bit set this is a negative number, so we need to insert an extra 0x00 to keep the number positive. So r takes 32+1 = 33 bytes:

02 21 (INTEGER, 33 bytes)
   00 (padding byte)
   95 15 95 A5 48 D1 56 D5 16 55 15 96 54 AD A5 48
   D1 56 D5 16 51 95 15 96 54 AD A5 4D 15 6D 51 51

s具有十进制值15800012655857962601029927988066555130680701005265153794330961或十六进制值9D51655159654ADA548D156D5165195159654ADA54D156D5151.虽然它以十六进制9开头,但实际上是0x09,因此不需要填充字节. s仅占用27个字节的内容,因为与r相比,它是如此之小.

s has decimal value 15800012655857962601029927988066555130680701005265153794330961, or hexadecimal value 9D51655159654ADA548D156D5165195159654ADA54D156D5151. While it starts with hex 9 it's actually 0x09, so no padding byte is required. s only takes 27 bytes of content, because it's so small compared to r.

02 1A (INTEGER, 26 bytes)
   09 D5 16 55 15 96 54 AD A5 48 D1 56 D5 16 51 95
   15 96 54 AD A5 4D 15 6D 51 51

现在我们可以计算出包含SEQUENCE的大小为63个字节:

And now we can calculate the size of the containing SEQUENCE to be 63 bytes:

30 3F (CONSTRUCTED SEQUENCE, 64 bytes)
   02 21 (INTEGER, 33 bytes)
      00 (padding byte)
      95 15 95 A5 48 D1 56 D5 16 55 15 96 54 AD A5 48
      D1 56 D5 16 51 95 15 96 54 AD A5 4D 15 6D 51 51
   02 1A (INTEGER, 26 bytes)
      09 D5 16 55 15 96 54 AD A5 48 D1 56 D5 16 51 95
      15 96 54 AD A5 4D 15 6D 51 51

或者线性化:

30 3F 02 21 00 95 15 95 A5 48 D1 56 D5 16 55 15 
96 54 AD A5 48 D1 56 D5 16 51 95 15 96 54 AD A5 
4D 15 6D 51 51 02 1A 09 51 D5 16 55 15 96 54 AD 
A5 48 D1 56 D5 16 51 95 15 96 54 AD A5 4D 15 6D 
51 51 

IEEE P1363

由Windows使用.

IEEE P1363

Used by Windows.

以这种格式将rs视为与n相同字节大小的大整数,然后进行级联.由于r使用所有32个字节,因此可以使用. s仅使用26个字节,因此它需要6个前导0x00字节.

In this format r and s are taken to be big integers of the same byte size as n, then concatenated. Since r uses all 32 bytes it's good to go. s only uses 26 bytes, so it needs 6 leading 0x00 bytes.

// r
95 15 95 A5 48 D1 56 D5 16 55 15 96 54 AD A5 48
D1 56 D5 16 51 95 15 96 54 AD A5 4D 15 6D 51 51
// s
00 00 00 00 00 00 09 D5 16 55 15 96 54 AD A5 48
D1 56 D5 16 51 95 15 96 54 AD A5 4D 15 6D 51 51

结论

因此,OpenSSL将ASN.1编码应用于签名 ,而不是哈希. ASN.1编码是更常见的"(因为这是ECC证书中使用的编码). Windows/IEEE方式更容易. ASN.1方式通常以大约6个字节结尾(或者secp521r1平均平均大7个字节).但可以(2 ^ 32几分之一的机会)的大小相同,或者(2 ^ 40几分之一的机会)的大小缩小.

Conclusion

So, OpenSSL applies an ASN.1 encoding to the signature, not the hash. The ASN.1 encoding is "more common" (in that it's what's used in ECC certificates). The Windows/IEEE way is easier. The ASN.1 way usually ends up about 6 bytes larger (or 7 bytes larger on average for secp521r1); but could (1 in 2^32 chance) end up the same size, or (1 in 2^40 chance) smaller.

此外,如果您发现自己在设计新的签名方案的委员会中,请记住添加声明接线图代表的步骤.

Also, if you ever find yourself on a committee designing a new signature scheme, remember to add the step declaring the wire representation.

这篇关于在签名之前,用于ECDSA的OpenSSL -sign是否将ASN1编码应用于哈希?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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