ECDSA的OpenSSL签名是否在签名之前对哈希应用ASN1编码



这个SO问题ECDSA使用OpenSSL进行签名,而不使用ASN1编码哈希,说明OpenSSL在签名之前对哈希执行ASN1编码。

换句话说,它规定OpenSSL在调用椭圆曲线密钥符号时执行以下步骤:a.计算H=哈希(M)b.将H编码为ASN1标准-H'c.标志H’

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

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

有人能谈谈这个话题吗?我在OpenSSL文档中找不到文档。

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

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

  1. 计算e = HASH (m),其中HASH是一个加密散列函数,例如SHA-2。

  2. zeLn最左边的比特,其中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)

问题是ECDSA算法以数学结束,而不是以字节结束。关于如何将这对数字转换为字节,出现了两种不同的约定。(与RSA相反,RSA的最后一步说明了如何将数学值转换回字节,并声明该字节序列为签名)。

让我们断言,我们使用r = 67432751043532511959904657272700966685609390316545000351652696368910338707793s = 15800012655857962601029927988066555130680701005265153794330961生成了一个签名(针对secp256r1)。

ASN.1 DER

由X.509/PKIX和OpenSSL使用。第一次声明(我可以找到,无论如何)由RFC 3279,第2.2.3节:

签名时,ECDSA算法生成两个值。这些值通常被称为r和s。为了方便地转移这两个值作为一个签名,它们必须使用ASN.1编码以下ASN.1结构:

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

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

r是一个整数,67432751043532511959904657272700966685609390316545000351652696368910338707793是十进制数,或者951595A548D156D51655159654ADA548D156D5165195159654ADA54D156D5151是十六进制数。ITU-T-REC-X.690-201508表示,整数被编码为带符号的big-endian值。由于最高有效字节(0x95)具有高位集,这是一个负数,因此我们需要插入一个额外的0x00来保持数字为正。所以r取32+1=33字节:

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相比,它太小了。

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字节:

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使用。

在这种格式中,rs被取为与n具有相同字节大小的大整数,然后被级联。由于r使用了全部32个字节,因此可以继续使用。s仅使用26个字节,因此需要6个前导0x00字节。

// 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个字节);但可能(1/2^32次机会中有1次)最终大小相同,或(1/2^40次机会中的1次)更小。

此外,如果你发现自己是一个设计新签名方案的委员会成员,记得添加声明有线表示的步骤。

相关内容

最新更新