谈谈区块链(19):比特币钱包蕴含的安全隐患

2017-02-14 10:54 来源:巴比特资讯 阅读:5347
大家目前正在热衷炒比特币,却很少去关注比特币技术本身的安全问题。你可能并不知道你目前正在使用的比特币钱包蕴含着巨大的危险,所以决定写此文以做警醒,否则你可能会在未来丢失几个、几十个,甚至更多的比特币。

大家目前正在热衷炒比特币,却很少去关注比特币技术本身的安全问题。你可能并不知道你目前正在使用的比特币钱包蕴含着巨大的危险,所以决定写此文以做警醒,否则你可能会在未来丢失几个、几十个,甚至更多的比特币。

我们知道比特币是基于UTXO的。假设你是Alice,有个比特币钱包,该钱包内含有一个比特币地址,该地址含有一个UTXO,该UTXO内含有10BTC余额。现在你要转帐10个BTC给Bob(不考虑手续费),那么产生的Transaction很简单(用你的UTXO作为input,用Bob的地址作为output),如下图:

p1

现在,情况变得稍复杂一点,你只需要转5个BTC给Bob,这时Transaction就会变得复杂一点(1个input还是引用你的UTXO,2个output,1个是给Bob的地址5BTC,另一个给自己的地址5BTC)。

这时问题就来了。转给自己的那5个BTC是用原来的地址,还是新创建的地址?这就是比特币里的一个标准政策,称为:Change Address(改变地址)。我们现在看一下比特币为什么要设定这样的政策?在没有change address政策之前,我们转账的模式是这样的:

p2

所有剩余的BTC都转回到发送的地址中。因为比特币的blockchain都是公开可查询的,这种方式你很容易追踪到A的付款行为和他的财富状态,没有任何隐私性可言。于是比特币推出了change address的政策(不是强制的),在新模式下工作方式是这样的:

p3

为每次转账的余额创建新的地址。实际上上图中的C是A用户的另一个地址。

在一个Transaction的output中,output是有顺序的(index),总是把目标地址放在第一个(index为0)会导致交易行为泄露。为了进一步增强隐私性,会在此基础上增加shuffleOutputs(洗牌)的功能,该功能会让Transaction中的output顺序打乱,随机排列。经过几次这样的转帐,你就无法追踪A的交易行为了。

这是一个完美的方案,已经被广泛使用。但是,这却为钱包的安全引进了巨大风险,这也是我们今天文章主要的阐述的观点。

现在我们大家绝大多数使用比特币钱包的标准步骤是(不研究在线钱包和交易所,他们会有另外的安全问题):

  1. 下载一个比特币钱包(PC或者手机端)

  2. 备份钱包(钱包里的密钥)

  3. 各种转入、转出

我们以为这样是安全的,因为我已经备份了钱包,即使电脑报废、手机丢失,我还可以用备份进行恢复。是的,没错!但是那只是你不进行转出操作的情况下!一旦你进行转出操作,你的钱包就有可能会为你产生新的地址,而这个新的地址可能不包含你在的备份中!

设想你的钱包里有100BTC,你进行了多次的转出操作,一共转出了50BTC。突然有一天你的手机丢了(钱包在你手机里),你赶紧买了新手机,装了新钱包,拿出备份进行恢复,却发现钱包的余额变成了0。因为你的剩余的50BTC所在的地址你没有备份,这是在转帐过程中产生的新地址!

下面是笔者通过用手机钱包转帐,红框部分的地址是新产生的地址,不在笔者的上次备份之中。

p4

我们这里说是可能,是因为现在不同钱包采取了不同模式。当前大致的模式分为下面几种:

  1. 单地址钱包,该种类型就是最原始,没有应用change address方案的钱包;

  2. 随机地址池钱包,这种类型的钱包一开始为你随机生成一个地址池,比如含有100个地址(有的可以通过-keypool参数设置池的大小)。在100次转帐范围内,是不需要产生新地址的。但是随着次数增多,还是会有同样的问题;

  3. 层级指定地址池钱包(HD钱包),通过密码生成主私钥,再通过主私钥生成若干子私钥;

  4. 可自定义,支持多种模式的钱包;

如何解决?

如果你不关心隐私问题(因为大部分人不关心交易行为的泄露,因为地址本身就是匿名的,他们更关注币的安全性),可以采用单地址钱包。对于在线钱包也是类似。笔者就将其运营的比特币支付平台(bitbill.com)改回了单地址模式(稍有扩展),笔者使用的是bitcoinj,在其核心代码里做了如下修改:

log.info("selection.gathered length:"+selection.gathered.size());
for (TransactionOutput output : selection.gathered){
//added by Tom @2017/2/9 for change address issue.
if(req.changeAddress==null){
try{
req.changeAddress=output.getAddressFromP2PKHScript(org.bitcoinj.params.MainNetParams.get());
}catch(Exception ex){}//in case not P2PKH
log.info("Tom's fix for req.changeAddress:"+req.changeAddress);
}else{
log.info("req.changeAddress is not empty:"+req.changeAddress);
}
}

对于使用比特币钱包的用户,要看钱包类型(尤其是非HD钱包,大多目前使用的是非HD钱包)。一般需要更多次的备份。一定记住,要么你不转帐,转帐完你可能需要立即备份!

声明:此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。本网站所提供的信息,只供参考之用。

点击阅读全文