【问题标题】:ECDSA signing/verifiying appears to be only considering the first 32 bytes of the dataECDSA 签名/验证似乎只考虑数据的前 32 个字节
【发布时间】:2021-08-05 04:05:19
【问题描述】:
ec = OpenSSL::PKey::EC.new('secp256k1')
ec.generate_key
signature = ec.dsa_sign_asn1("A" * 64)
refute ec.dsa_verify_asn1("A" * 32, signature) # Fails here

鉴于上面的测试代码,为什么dsa_sign_asn1dsa_verify_asn1只考虑提供数据的前32个字节?

环境:

Ruby 3.0、Ubuntu 21.04 在 Windows 10 上运行多通道。OpenSSL::VERSION 是 2.2.0

【问题讨论】:

    标签: ruby openssl cryptography ecdsa


    【解决方案1】:

    签名时,签名的不是数据本身,而是数据的哈希值。这一方面是为了能够签署更长的消息,另一方面是出于安全原因(s.here)。

    对于 secp256k1,通常使用输出大小为 256 位的摘要(s.here),例如SHA256。

    如果您采用具有较大输出大小的摘要,则根据 NIST FIPS 186-4(s.here,其中 n 是密钥大小,即生成器的位大小)考虑哈希的最左边 n 位顺序,secp256k1 为 256 位)。

    这就是贴出的示例中验证成功的原因:只考虑前 32 个字节,它们是相同的。

    如果改用数据的哈希值,验证如预期失败:

    signature = ec.dsa_sign_asn1(OpenSSL::Digest::SHA256.digest("A" * 64))
    verified = ec.dsa_verify_asn1(OpenSSL::Digest::SHA256.digest("A" * 32), signature) # false
    

    【讨论】:

    • 感谢您提供更多参考资料。在问这个问题之前,我确实阅读了一些背景知识。我了解到,在签名的第一步,数据是由一个散列函数散列的,即 ECDSA 背后的数学。但是我不确定我是否应该为我做散列或实现散列。我还阅读了ruby方法dsa_sign_asn1的C代码,发现它既没有散列也没有切割要签名的消息。
    • 最后我尝试使用 C 代码,做类似的事情。从中,我发现 openssl 的 ECDSA_sign 确实将要签名的消息截断,只保留前 32 个字节。根据您提供的参考资料,它按预期工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 2020-06-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多