【问题标题】:What's the proper way to get a fixed-length bytes representation of an ECDSA Signature?获取 ECDSA 签名的固定长度字节表示的正确方法是什么?
【发布时间】:2018-07-21 10:51:22
【问题描述】:

我正在使用 python 和 cryptography.io 来签署和验证消息。我可以通过以下方式获得签名的 DER 编码字节表示:

cryptography_priv_key.sign(message, hash_function)

...根据本文档:https://cryptography.io/en/latest/hazmat/primitives/asymmetric/ec/

来自 256 位曲线的 DER 编码 ECDSA 签名最多为 72 个字节;见:ECDSA signature length

但是,根据 r 和 s 的值,它也可以是 70 或 71 字节。事实上,如果我检查这个函数的输出长度,它会在 70-72 之间变化。到目前为止我有这个权利吗?

我可以将签名解码为整数 r 和 s。这些显然都是 32 字节,但我不清楚这是否会总是如此。

将这两个整数转换为字节并通过网络发送它们是否安全,以便在另一端再次对其进行编码?

【问题讨论】:

  • 对于 ASN.1/DER 编码,rsINTEGER,这是一个二进制补码整数。如果设置了高位,则在前面添加一个前导 0 字节以保持整数为正。知道您是否需要rs 的额外八位字节的唯一方法是签署消息。处理它的正确方法是让签名函数返回一个大小合适的缓冲区。
  • 为什么不直接发送sign() 给你的正确的DER编码序列?
  • @JamesKPolk:DER 编码的序列不是固定长度的。
  • 发送可变字节数并不是一个难题。如果可能,最好避免在 DER 编码中间解析 ASN.1 INTEGER 组件。我宁愿遇到发送和接收可变字节数的问题,也不愿遇到 ASN.1 解析问题。
  • @JamesKPolk:为什么最好避免?您是否有描述“ASN.1 解析问题”的链接?

标签: cryptography ecdsa python-cryptography


【解决方案1】:

简单的答案是,是的,它们总是 32 字节。

更完整的答案是它取决于曲线。例如,256 位曲线的阶数为 256 位。同理,128位的曲线只有128位的阶。

您可以将此数字除以 8 以找到 rs 的大小。

当曲线不能被 8 整除时,情况会变得更加复杂,例如 secp521r1,其中阶数是 521 位数字。

在这种情况下,我们四舍五入。 521 / 8 是 65.125,因此它需要我们释放 66 字节的内存来适应这个数字。

只要您知道rs 是哪一个,就可以安全地通过网络发送它们并再次对其进行编码。

【讨论】:

  • 我仍然持怀疑态度,伙计(注意:@Tux 和我一直在亲自讨论这个问题)。这可能表明我对某些密码学函数的理解存在局限性,但在我的脑海中:如果整数是 32 字节,它仍然可能由曲线上的两个不同点表示——一个在 X 轴上方,一个在 X 轴下方。如果我假设它是一个正值,我会失败大约一半的时间,不是吗?
  • 好的,所以有两件事:1)您如何回应@JamesKPolk 的上述cmets? 2)然后我是否正确理解您只是说 DER 编码在这里基本上是浪费的? (即,没有很好的理由认为 DER 不能是固定长度的,而且它的可变长度的原因也不能令人信服?)
  • @jMyles:EC 公钥 是一个点,具有 X 坐标,有时是 Y 坐标,但 ECDSA 签名是两个整数,而不是一个点。一个数字 (r) 从 X 坐标派生但经过修改,而另一个 (s) 与任何点都不相关。注意 NIST/SECG Fp 曲线(不是 F2m)具有辅因子 1,因此曲线阶数接近但不等于基础场模量 p;谷歌哈斯定理。
猜你喜欢
  • 2020-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-27
  • 2019-10-27
相关资源
最近更新 更多