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

ECDSA的OpenSSL-sign在签名之前是否对哈希应用ASN1编码?,openssl,cryptography,digital-signature,elliptic-curve,ecdsa,Openssl,Cryptography,Digital Signature,Elliptic Curve,Ecdsa,这个问题说明了在签名之前OpenSSL对哈希进行ASN1编码 换句话说,当调用椭圆曲线密钥符号时,OpenSSL将执行以下步骤: A.计算H=散列(M) B将H编码为ASN1标准-H' C符号H' 因此,为了避免应用步骤b,有必要首先计算摘要,然后使用原始签名-pkeyutl为椭圆曲线密钥对摘要进行签名 但是,当我同时运行-sign和-dgst+-pkeyutl时,我可以在这两种情况下使用-verify来验证签名。这意味着ASN1编码未应用于哈希 有人能解释一下这个话题吗?我无法在OpenSSL

这个问题说明了在签名之前OpenSSL对哈希进行ASN1编码

换句话说,当调用椭圆曲线密钥符号时,OpenSSL将执行以下步骤: A.计算H=散列(M) B将H编码为ASN1标准-H' C符号H'

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

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


有人能解释一下这个话题吗?我无法在OpenSSL文档中找到文档。

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

  • 计算
    e=HASH(m)
    ,其中HASH是加密HASH函数,如SHA-2
  • 假设
    z
    e
    Ln
    最左边的位,其中
    Ln
    是组顺序
    n
    的位长度
  • [1,n-1]
    中选择一个加密安全的随机整数
    k
  • 计算曲线点
    (x1,y1)=k x G
  • 计算
    r=x1模n
    。如果
    r=0
    ,则返回步骤3
  • 计算
    s=(k− 1) x(z+r*dA)模块n
    。如果
    s=0
    ,则返回步骤3
  • 签名是一对
    (r,s)
  • 问题是ECDSA算法以数学而不是字节结束。对于如何将这对数字转换成字节,出现了两种不同的约定。(与RSA相反,RSA的最后一步说明了如何将数学值转换回字节,并将字节序列声明为签名)

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

    第1条 由X.509/PKIX和OpenSSL使用。首先声明(无论如何,我可以找到)是:

    签名时,ECDSA算法生成两个值。这些价值观 通常称为r和s。要轻松转移这两个 值作为一个签名,必须使用 以下ASN.1结构:

    如果我们从内到外构建DER,它的工作效果最好,所以让我们编码
    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
    
    r
    是一个整数,
    67432751043532511959904657272700966685609390316545000351652696368910338707793
    是十进制,或者
    951595A548D156D5165515954ADA548D156D5165195159654ADA5548D156D5165195159654ADA554D156D5151
    十六进制。表示整数被编码为有符号的大端值。由于最高有效字节(
    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
    具有十进制值
    15800126558579626010299279880665555130680701005265153794330961
    ,或十六进制值
    9D516551599654ADA548D156D5165195159654ADA54D156D5151
    。虽然它以十六进制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
    
    现在我们可以计算包含序列的大小为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使用

    在这种格式中,
    r
    s
    被视为与
    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/2^40的概率)更小


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

    Stack Overflow是一个用于编程和开发问题的网站。这个问题似乎离题了,因为它与编程或开发无关。请参见帮助中心中的。也许或者会是一个更好的提问的地方。这是一个影响如何使用OpenSSL和PyOpenSSL使用Python编程的问题,因为我不知道OpenSSL API执行什么操作。这是对这里出现的另一个问题“使用OpenSSL进行ECDSA签名,而不使用ASN1编码哈希”的跟进。不过,我可以尝试在CryptoStackExchange上发布;它误解了#9951599。