您的位置:首页 > 互联网 >

签名重放攻击是常见漏洞 能够被对应公钥验证

2019-06-12 15:33:27 来源: 以太坊爱好者

密码学签名是区块链系统中的基本模块。使用对应的私钥对交易进行签名能够将交易发起人与特定帐户联系起来。如果没有此功能,区块链的记帐工

密码学签名是区块链系统中的基本模块。使用对应的私钥对交易进行签名能够将交易发起人与特定帐户联系起来。如果没有此功能,区块链的记帐工作将无法正常进行。

许多在以太坊上部署的智能合约也有直接验证数字签名的功能,以使得一个或多个验证者可以通过提交离线创建的签名(甚至是由另一个智能合约生成的签名)来授权操作。这项验证通常被用于多重签名冷钱包或者投票合同,以便一起提交各种签名或委托授权。

此类实现中的常见漏洞是签名重放攻击。在 Cryptonics 对一个重要项目的智能合约审计中,我们遇到了这个问题的一个有趣例子。在本文中,我们将使用此示例来说明智能合约中签名验证是如何出错的。

与签名验证相关的漏洞通常是由于误解了底层的密码学原理和签名的目的而引起的。因此,在详细了解此特定漏洞之前,我们先快速了解一下密码学签名的工作原理。

密码学签名

大多数的密码学签名体系都基于公私钥对。私钥能够对数据进行签名,而且此签名能够被对应的公钥所验证。就像它的名字所暗示的一样,一个用户的公钥是公开的,而私钥则一定要保密。

对数据进行加密签名可实现两个重要属性:

· 数据签名者可识别性,这是通过恢复签名者的公钥来实现的。

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

虽然这些是非常强大的属性,但是需要重点注意的是签过名的数据本身不提供额外的保障。签名不能保证一条消息的唯一性,也不能保证签名人就是发信人本身。当然,加密签名可以被用于确认相关事实,但是应用程序也须执行必要的检查。我们可以在以太坊智能合约中调查以上事实。

以太坊中的签名验证

以太坊和比特币一样,采用椭圆曲线数字签名算法(ECDSA)和 secp256k1 曲线。智能合约可以通过系统方法 ecrecover 访问内置的 ECDSA 签名验证算法。以下示例展示了这个函数的用法:

address signer = ecrecover(msgHash, v, r, s);

这个方法的输入参数是签名值 v,r 和 s,以及签名数据的 keccak256 哈希值。它可以校验数据的完整性,即确认数字签名与数据的哈希值相对应,并且可以从签名中恢复签名者的以太坊地址(以太坊地址乃是从公钥中推导出来的)。

任何额外的检查,不论是检查签名地址是否为正确地址,还是检查被签名的消息是否唯一,都必须被手动添加进智能合约中。

经常有人误解了 ecrecover 的功能,然后搞出了安全漏洞。

签名重放漏洞

代码示例

让我们来看一下我们在最近的合约审计中发现的漏洞:

function unlock(

address _to,

uint256 _amount,

uint8[] _v,

bytes32[] _r,

bytes32[] _s

)

external

{

require(_v.length >= 5);

bytes32 hashData = keccak256(_to, _amount);

for (uint i = 0; i < _v.length; i++) {

address recAddr = ecrecover(hashData, _v[i], _r[i], _s[i]);

require(_isValidator(recAddr));

}

to.transfer(_amount);

}

以上代码是我们所审计的代码的简化版本,为使代码变得简短易懂,它只保留了最基础的信息。但是其中的漏洞被完整地保留了下来。

被审计的合约是跨链桥接器的一部分,它能让数字资产从一个区块链转移到另一个上。以太币在以太坊智能合约中被锁定之时,另一条链上会创建出对应的资产。当资产在另一条链上被锁定或销毁时, unlock 函数可以释放先前被锁定的以太币。

要实现这个效果时,跨链中继者可以提交一系列的验证者签名、一个解锁的数额以及一个目标地址。这个函数要求至少五个签名来解锁需要的数额并将资金传给接收方。而内部的 _isValidator 函数(为了简化,省略掉了具体实现)会检查一个地址具不具备验证者身份。

攻击情景

以上代码的问题在于被验证者用 ECDSA 算法签过名的消息中。这个消息只包含接收者的地址以及需要解锁的数量。在这个消息中,并没有什么内容能防止相同的签名被多次重复使用。想象如下的情景:

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

· Alice 是一个处理跨链交易的中继者。她收集了必需的验证者签名,在所连接的链上锁定了相对应的资产数量,并且调用 unlock 函数将 10ETH 从合约中释放给 Bob。

· 包含一系列签名值的交易能够在区块链上公开读取。

· Bob 现在可以复制这个签名值的序列并且自己提交一个一模一样的解锁函数调用请求。这个解锁的操作能够再一次成功,导致又一个 10ETH 被发送给Bob。

· Bob 能够重复这个过程直到智能合约中的以太坊被耗尽。

改进手段

以上情形被称为签名重放攻击。这种攻击能成功是由于我们无法验证所签名消息的唯一性,也不知道它之前是否被用过。

一个防止此类攻击的简单方法是在被签名数据中包含一个消息序列号或者 nonce。以上代码的修正版如下:

public uint256 nonce;

function unlock(

address _to,

uint256 _amount,

uint256 _nonce,

uint8[] _v,

bytes32[] _r,

bytes32[] _s

)

external

{

require(_v.length >= 5);

require(_nonce == nonce++);

bytes32 hashData = keccak256(_to, _amount, _nonce);

for (uint i = 0; i < _v.length; i++) {

address recAddr = ecrecover(hashData, _v[i], _r[i], _s[i]);

require(_isValidator(recAddr));

}

to.transfer(_amount);

}

这段代码现在要求每一个成功的解锁调用都包含一个序列号。因为消息中得包含一个独一无二的数字,所以每次成功调用所要求的签名都是独一无二的。这表示之前观测到的消息对攻击者来说没用了,因为重放会失败。

签名验证的最佳模式

上述例子只是其中一个示例,演示了不能保证唯一型的签名如何被重放。在大部分情景中,确保签名能够与每一次调用形成唯一的匹配对预防重放攻击是非常重要的。

但是,这段代码并不完美。它并没有遵循签名验证的最佳实践。原因是它没有检查可塑性签名,我们应检查作为已接受签名一部分的 s 值是否在较低范围内。使用 ecrecover 函数的推荐流程可以在 Open Zeppelin 的 excellent ECDSA 库中找到。事实上,在社区审计过的代码,比如 Open Zeppelin 上进行开发,总是一个好主意。(作者: Stefan Beyer)

关键词: 签名重放攻击 公钥验证

精选 导读

募资55亿港元万物云启动招股 预计9月29日登陆港交所主板

万科9月19日早间公告,万物云当日启动招股,预计发行价介乎每股47 1港元至52 7港元,预计9月29日登陆港交所主板。按发行1 167亿股计算,万

发布时间: 2022-09-20 10:39
管理   2022-09-20

公募基金二季度持股情况曝光 隐形重仓股多为高端制造业

随着半年报披露收官,公募基金二季度持股情况曝光。截至今年二季度末,公募基金全市场基金总数为9794只,资产净值为269454 75亿元,同比上

发布时间: 2022-09-02 10:45
资讯   2022-09-02

又有上市公司宣布变卖房产 上市公司粉饰财报动作不断

再有上市公司宣布变卖房产。四川长虹25日称,拟以1 66亿元的转让底价挂牌出售31套房产。今年以来,A股公司出售房产不断。根据记者不完全统

发布时间: 2022-08-26 09:44
资讯   2022-08-26

16天12连板大港股份回复深交所关注函 股份继续冲高

回复交易所关注函后,大港股份继续冲高。8月11日大港股份高开,随后震荡走高,接近收盘时触及涨停,报20 2元 股。值得一提的是,在7月21日

发布时间: 2022-08-12 09:56
资讯   2022-08-12

万家基金再添第二大股东 中泰证券拟受让11%基金股权

7月13日,中泰证券发布公告,拟受让齐河众鑫投资有限公司(以下简称齐河众鑫)所持有的万家基金11%的股权,交易双方共同确定本次交易的标的资

发布时间: 2022-07-14 09:39
管理   2022-07-14

央行连续7日每天30亿元逆回购 对债市影响如何?

央行12日再次开展了30亿元逆回购操作,中标利率2 10%。这已是央行连续7日每天仅进行30亿元的逆回购缩量投放,创下去年1月以来的最低操作规

发布时间: 2022-07-13 09:38
资讯   2022-07-13

美元指数创近20年新高 黄金期货创出逾9个月新低

由于对美联储激进加息的担忧,美元指数11日大涨近1%创出近20年新高。受此影响,欧美股市、大宗商品均走弱,而黄金期货创出逾9个月新低。美

发布时间: 2022-07-13 09:36
资讯   2022-07-13

美股三大股指全线下跌 纳斯达克跌幅创下记录以来最大跌幅

今年上半年,美股持续回落。数据显示,道琼斯指数上半年下跌15 3%,纳斯达克综合指数下跌29 5%,标普500指数下跌20 6%。其中,纳斯达克连续

发布时间: 2022-07-04 09:51
推荐   2022-07-04

融资客热情回升 两市融资余额月内增加超344亿元

近期A股走强,沪指6月以来上涨4%,融资客热情明显回升。数据显示,截至6月16日,两市融资余额1 479万亿元,月内增加344 67亿元,最近一个半

发布时间: 2022-06-20 09:41
资讯   2022-06-20

4个交易日净买入超百亿元 北向资金持续流入A股市场

北向资金净流入态势延续。继6月15日净买入133 59亿元后,北向资金6月16日净买入44 52亿元。自5月27日至今,除6月13日以外,北向资金累计净

发布时间: 2022-06-17 09:37
推荐   2022-06-17