http://www.tnmanning.com

智能合约中的签名重放裂痕

此类实现中的常见裂痕是签名重放进攻。在 Cryptonics 对一个重要项目标智能合约审计中,我们碰着了这个问题的一个有趣例子。在本文中,我们将利用此示例来说明智能合约中签名验证是如何堕落的。
    require(_isValidator(recAddr));
让我们来看一下我们在最近的合约审计中发明的裂痕:
可是,这段代码并不完美。它并没有遵循签名验证的最佳实践。原因是它没有查抄可塑性签名,我们应查抄作为已接管签名一部门的 s 值是否在较低范畴内。利用 ecrecover 函数的推荐流程可以在 Open Zeppelin 的 excellent ECDSA 库中找到。事实上,在社区审计过的代码,好比 Open Zeppelin 长举办开拓,老是一个好主意。
很多在以太坊上陈设的智能合约也有直接验证数字签名的成果,以使得一个或多个验证者可以通过提交离线建设的签名(甚至是由另一个智能合约生成的签名)来授权操纵。这项验证凡是被用于多重签名冷钱包可能投票条约,以便一起提交各类签名或委托授权。
上述例子只是个中一个示例,演示了不能担保独一型的签名如何被重放。在大部门情景中,确保签名可以或许与每一次挪用形成独一的匹配对防范重放进攻长短常重要的。
)
  require(_v.length >= 5);
签名重放裂痕
原文链接: 

智能合约中的签名重放裂缝

固然这些长短常强大的属性,可是需要重点留意的是签过名的数据自己不提供特另外保障。签名不能担保一条动静的独一性,也不能担保签名流就是发信人自己。虽然,加密签名可以被用于确认相关事实,可是应用措施也须执行须要的查抄。我们可以在以太坊智能合约中观测以上事实。

https://medium.com/cryptronics/signature-replay-vulnerabilities-in-smart-contracts-3b6f7596df57 
与签名验证相关的裂痕凡是是由于误解了底层的暗码学道理和签名的目标而引起的。因此,在具体相识此特定裂痕之前,我们先快速相识一下暗码学签名的事情道理。
  require(_v.length >= 5);
以太坊中的签名验证
}
    require(_isValidator(recAddr));


这段代码此刻要求每一个乐成的解锁挪用都包括一个序列号。因为动静中得包括一个唯一无二的数字,所以每次乐成挪用所要求的签名都是唯一无二的。这暗示之前视察到的动静对进攻者来说没用了,因为重放会失败。
  require(_nonce == nonce++);
public uint256 nonce;
· Bob 可以或许反复这个进程直到智能合约中的以太坊被耗尽。
  }
进攻情景
  bytes32 hashData = keccak256(_to, _amount, _nonce);

· Bob 在与以太坊毗连的另一条链上有等价于 10ETH 的资产被他通过桥接器传回了以太坊链上。

大大都的暗码学签名体系都基于公私钥对。私钥可以或许对数据举办签名,并且此签名可以或许被对应的公钥所验证。就像它的名字所体现的一样,一个用户的公钥是果真的,而私钥则必然要保密。
· 包括一系列签名值的生意业务可以或许在大发3d上果真读取。
address signer = ecrecover(msgHash, v, r, s);

  external
  uint8[] _v,
要害词:   


  bytes32[] _r,
· 数据签名者可识别性,这是通过规复签名者的公钥来实现的。



· Bob 此刻可以复制这个签名值的序列而且本身提交一个一模一样的解锁函数挪用请求。这个解锁的操纵可以或许再一次乐成,导致又一个 10ETH 被发送给Bob。
  external
  bytes32[] _s

{
  to.transfer(_amount);
  uint256 _nonce,
作者: Stefan Beyer 

    address recAddr = ecrecover(hashData, _v[i], _r[i], _s[i]);
以上代码的问题在于被验证者用 ECDSA 算法签过名的动静中。这个动静只包括吸收者的地点以及需要解锁的数量。在这个动静中,并没有什么内容能防备沟通的签名被多次反复利用。想象如下的情景:
  address _to,
function unlock(
  uint256 _amount,
这个要领的输入参数是签名值 v,r 和 s,以及签名数据的 keccak256 哈希值。它可以校验数据的完整性,即确认数字签名与数据的哈希值相对应,而且可以从签名中规复签名者的以太坊地点(以太坊地点乃是从公钥中推导出来的)。
常常有人误解了 ecrecover 的成果,然后搞出了安详裂痕。

以太坊和一分PK10一样,回收椭圆曲线数字签名算法(ECDSA)和 secp256k1 曲线。智能合约可以通过系统要领 ecrecover 会见内置的 ECDSA 签名验证算法。以下示例展示了这个函数的用法:
代码示例


  to.transfer(_amount);
)
翻译&校对: TrumanW & 阿剑
  }



  bytes32[] _r,


  uint8[] _v,
一个防备此类进攻的简朴要领是在被签名数据中包括一个动静序列号可能 nonce。以上代码的批改版如下:

暗码学签名是大发3d系统中的根基模块。利用对应的私钥对生意业务举办签名可以或许将生意业务提倡人与特定帐户接洽起来。假如没有此成果,大发3d的记帐事情将无法正常举办。
被审计的合约是跨链桥接器的一部门,它能让数字资产从一个大发3d转移到另一个上。以太币在以太坊智能合约中被锁定之时,另一条链上会建设出对应的资产。当资产在另一条链上被锁定或销毁时, unlock 函数可以释放先前被锁定的以太币。要实现这个结果时,跨链中继者可以提交一系列的验证者签名、一个解锁的数额以及一个方针地点。这个函数要求至少五个签名来解锁需要的数额并将资金传给吸收方。而内部的 _isValidator 函数(为了简化,省略掉了详细实现)会查抄一个地点具不具备验证者身份。
  bytes32[] _s
  for (uint i = 0; i < _v.length; i++) {
签名验证的最佳模式
    address recAddr = ecrecover(hashData, _v[i], _r[i], _s[i]);
暗码学签名
function unlock(

· 数据完整的可验证性,意思是签名可以用于证明自签名以来数据未被修改。

  address _to,
对数据举办加密签名可实现两个重要属性:
  uint256 _amount, 


改造手段
· Alice 是一个处理惩罚跨链生意业务的中继者。她收集了必须的验证者签名,在所毗连的链上锁定了相对应的资产数量,而且挪用 unlock 函数将 10ETH 从合约中释放给 Bob。
  for (uint i = 0; i < _v.length; i++) {



以上景象被称为签名重放进攻。这种进攻能乐成是由于我们无法验证所签名动静的独一性,也不知道它之前是否被用过。

任何特另外查抄,岂论是查抄签名地点是否为正确地点,照旧查抄被签名的动静是否独一,都必需被手动添加进智能合约中。
{

以上代码是我们所审计的代码的简化版本,为使代码变得简短易懂,它只保存了最基本的信息。可是个中的裂痕被完整地保存了下来。
}
  bytes32 hashData = keccak256(_to, _amount);

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。