Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cryptography 通过crypto.sign/4进行的比特币ECDSA签名产生错误的签名(与RFC6979不兼容)_Cryptography_Erlang_Bitcoin - Fatal编程技术网

Cryptography 通过crypto.sign/4进行的比特币ECDSA签名产生错误的签名(与RFC6979不兼容)

Cryptography 通过crypto.sign/4进行的比特币ECDSA签名产生错误的签名(与RFC6979不兼容),cryptography,erlang,bitcoin,Cryptography,Erlang,Bitcoin,我正在尝试对比特币交易进行签名,其中一部分过程是使用sha256和私钥对其进行签名 以下是我使用的Elixir/Erlang代码: signed_data = :crypto.sign(:ecdsa, :sha256, data, [prk, :secp256k1]) |> Base.encode16 将生成以下字符串: 3046022100AFF0CCC46F08C1A2D304483C0D9B97348EEEB7D415E394A512B87A73CB69AA660221009DB8

我正在尝试对比特币交易进行签名,其中一部分过程是使用sha256和私钥对其进行签名

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

signed_data = :crypto.sign(:ecdsa, :sha256, data, [prk, :secp256k1]) |> Base.encode16
将生成以下字符串:

3046022100AFF0CCC46F08C1A2D304483C0D9B97348EEEB7D415E394A512B87A73CB69AA660221009DB8FD52692FD0ADF16F0BB8EA870C9424F1BCD22EB6755388883DE62FBC01BD
问题是,这个签名在我针对BlockCypher使用的引用实现中失败

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

3044022045734b7593ed805dd95d3dfb86658afdb647b6693a740ffc9b2aa3d37cc6c06e0220324e5024acc51550e287564c308e280b8978305198d49cb2df8d07e7822b2563
priv_key = "yourhexprivatekey"
    |> Base.decode16!
msg = "Lorem Ipsum dolor sit amet..."
sig = :crypto.sign(:sha256, msg, [priv_key, :secp256k1])
    |> enforce_low_s
    |> Base.encode16
因此,对于相同的数据/私钥输入参数,我的签名长2字节。K部分的I字节长,S部分的1字节长。

我怀疑Erlang加密库没有遵循比特币所期望的RFC6979

下面是一个有效的签名者实施链接:


问题是:有没有办法让Erlang crypto实现这一点,或者我应该使用另一种Erlang/Elixir库。我能找到的最接近的东西是:

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


将其留在这里,以防有人执行本机Erlang/Elixir实现。如果有,请打电话给我。

ECDSA签名描述椭圆曲线内的一个点。在比特币的例子中,曲线是。对于实数,这样的曲线大致如下所示:

3044022045734b7593ed805dd95d3dfb86658afdb647b6693a740ffc9b2aa3d37cc6c06e0220324e5024acc51550e287564c308e280b8978305198d49cb2df8d07e7822b2563
priv_key = "yourhexprivatekey"
    |> Base.decode16!
msg = "Lorem Ipsum dolor sit amet..."
sig = :crypto.sign(:sha256, msg, [priv_key, :secp256k1])
    |> enforce_low_s
    |> Base.encode16

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

2015年10月,有人开始利用这种双重性,一次又一次地操纵已经播出的交易,以泛滥比特币网络并导致其故障

由于这种可塑性的潜在风险,Blockcypher和比特币领域的其他著名成员将BIP-0062升级

BIP-0062强制执行“低S值”。这意味着必须丢弃包含签名的事务,该签名的分量大于某个值。该最高值为:

0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0
如果要确保事务始终包含有效的S值,则需要检查生成的S值是否大于最大值。如果是,只需将当前的S值删除为以下值:

0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
这是一个函数在Elixir中进行这种转换的示例

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

所以有一点是,在这种情况下,你的签名会更长,但它是一个有效的长度。文件格式需要30(签名从这里开始)44 | 45 | 46(它有这么多字节长)02(第一部分从这里开始)20 | 21 | 22(它有这么多字节长),然后是这么多字节,然后是02,然后是20 | 21 | 22。因此,示例中的签名是44个字节,或者0220(然后是20个字节)0220(然后是20个字节),而您的签名是46-0221(然后是21个字节)0221(然后是20个字节)。据我所知,这是意料之中的,并不意味着rfc6979出现了问题。阿丹,你能提供一个完整的工作原理吗?它仍然会产生与官方btc代码不同的哈希值