首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >比特币ECDSA通过加密进行签名。签名/4正在产生错误的签名(不兼容RFC6979 )

比特币ECDSA通过加密进行签名。签名/4正在产生错误的签名(不兼容RFC6979 )
EN

Stack Overflow用户
提问于 2015-08-12 01:16:50
回答 2查看 1.1K关注 0票数 1

我试图签署一个比特币交易,其中的一部分过程是签署它与sha256和私钥。

下面是我使用的Elixir/Erlang代码:

代码语言:javascript
复制
signed_data = :crypto.sign(:ecdsa, :sha256, data, [prk, :secp256k1]) |> Base.encode16

它生成以下字符串:

代码语言:javascript
复制
3046022100AFF0CCC46F08C1A2D304483C0D9B97348EEEB7D415E394A512B87A73CB69AA660221009DB8FD52692FD0ADF16F0BB8EA870C9424F1BCD22EB6755388883DE62FBC01BD

问题是,此签名对我针对BlockCypher使用的引用实现失败。

它们在示例中提供的签名如下:

代码语言:javascript
复制
3044022045734b7593ed805dd95d3dfb86658afdb647b6693a740ffc9b2aa3d37cc6c06e0220324e5024acc51550e287564c308e280b8978305198d49cb2df8d07e7822b2563

因此,对于相同的数据/私有键输入参数,我的签名要长2个字节。K部分的I字节长,S部分的1字节。

我怀疑Erlang密码库没有遵循比特币预期的RFC6979。

下面是一个可以工作的签名者的实现链接:https://github.com/blockcypher/btcutils/tree/master/signer

问题是:是否有一种使Erlang密码工作的方法,或者我应该使用的另一个Erlang/Elixir库.

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-13 05:00:50

我能找到的最接近的东西是:https://github.com/trustatom-oss/erlang-secp256k1

它不是一个本地的Erlang代码,它使用的是NIF和普通C,但它总比没有好。

把它留在这里,以防有人做本机Erlang/Elixir实现。如果你这么做了,请把我打平。

票数 0
EN

Stack Overflow用户

发布于 2016-04-20 16:08:13

ECDSA签名描述椭圆曲线内的一个点。在比特币的例子中,曲线是secp256k1。对于实数,这样的曲线看起来或多或少是这样的:

曲线内的点是由两个值或“坐标”明确指定的:对于单个R值,有两个可能的有效S值。

2015年10月,有人开始利用这种两重性,一次又一次地操纵已经被广播的交易,以淹没比特币网络并导致其失灵。

由于这种可延展性的潜在风险,Blockcypher和其他著名的比特币场景成员立刻决定拥抱到BIP-0062。

BIP 0062强制执行“低S值”。这意味着包含S组件大于某个值的签名的事务必须被丢弃。这种最高价值是:

代码语言:javascript
复制
0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0

如果要确保事务包含始终有效的S值,则需要检查得到的S值是否大于顶值。如果是这样,只需将当前的S值移至以下值:

代码语言:javascript
复制
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141

这是一个函数在Elixir中执行这种转换的例子。

代码语言:javascript
复制
def enforce_low_s sig do
  len  = sig |> :binary.at(1)
  rlen = sig |> :binary.at(3)
  r    = sig |> :binary.part(4, rlen)
  slen = sig |> :binary.at(rlen + 5)
  s    = sig |> :binary.part(rlen + 6, slen)
  sint = s   |> :binary.decode_unsigned
  if sint > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 do
    s = (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - sint) |> :binary.encode_unsigned
    slen = s |> :binary.bin_to_list |> Enum.count
    len = rlen + slen + 4
  end
  <<48, len, 2>> <> <<rlen>> <> r <> <<2, slen>> <> s
end

因此,完整的签名过程如下所示:

代码语言:javascript
复制
priv_key = "yourhexprivatekey"
    |> Base.decode16!
msg = "Lorem Ipsum dolor sit amet..."
sig = :crypto.sign(:sha256, msg, [priv_key, :secp256k1])
    |> enforce_low_s
    |> Base.encode16
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31954520

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档