用智能合约来实现保险柜

张亚宁   |     |   1869 次阅读

原文:https://www.reddit.com/r/ethereum/comments/484lm0/new_proposal_for_secure_bitcoin_vaults_with_a_new/


如何实现安全的比特币保险柜

你是如何保存比特币的?当然,比特币登记在区块链上,但是你是如何保存你的私钥来保证你的资金安全的?如果你现在还没有比特币,你会如何保存你的私钥,这个小小的文件有着直接的货币价值,如何防止丢失和黑客?保持密钥的安全是大众接受密码货币的阻碍之一,每一次货币的丢失事件都给整个加密货币社区带来不好的名声,这些问题有各种不同的答案。

如果问任何一个加密货币老手,他们都会告诉你一个事实,你必须使用非常成熟的软件和真正的随机数来生成你的私钥。并且他们会告诉你使用多重签名来拆分开你的私钥,这样黑客必须破解不是一个,而是多个机器来获得你的资金。这种保护是很复杂的。经典的保存私钥安全的方法是遵循37步操作安全准则 ,这里涉及到物理隔离,专用笔记本和断开网络接口。但是“互联网”类的货币也需要物理隔离,专用笔记本和隐藏在使用假墓室的金塔里?所以,不足为奇的是,凡人常常选择比较大的交易所来保存他们的币。当然,这只是将安全问题外包为交易所的安全,但是面临完全相同的问题,只不过有更高的赌注。

在可用性(需要更多的备份)和安全性(更多的备份意味着更大的风险)的权衡中,一般的使用者会难以抉择。极端情况下,要么将私钥保存在多个设备上,这样就容易被盗,或者只保存一份编码私钥在物理隔离的保险库,如果用户需要访问,需要临时地重新连接网络,并且需要一段密码来还原私钥。

结果,加密货币的的历史里记载了很多起丢失货币的悲剧,要么因为自己的错误丢失货币,要么黑客偷走了私钥而盗走多部分金额。这样的事情同样发生在聪明人身上。一个计算机系毕业的大学生,是早期的比特币矿工,丢失了差不多10,000个比特币。另外一个朋友选择了一个非常非常好的密码,好的以至于在一些年后他不能回忆起这个密码,甚至使用催眠和根据他的密码选择习惯的暴力破解也无济于事。

总的来讲,我们的计算机设施在安全保存高价值的资产方面遥遥无期。比特币已经变成一种普遍的黑客的“福利”,因为他们可以侵入你的电脑盗走你的财富。我们需要一种方式去锁定我们的比特币,让黑客和小偷不为所动。

比特币保险柜

在巴巴多斯的比特币工作室里,Malte Möser 展示了我们的比特币私钥解决方案。特别的是,我们的论文描述了一种方式来新建“保险库“,它是一种特殊的帐户,一旦私钥落入攻击者手里,这些私钥达成的交易也可以被抵消。保险柜是比特币的一种去中心化的方式,让你可以申请银行丢失信用卡来撤销攻击者的交易。这里有一些有趣的地方:这样的话,保险柜在根本上是使私钥盗窃行为失去动机。攻击者知道如果他们不能拿走比特币的话,首先就会很少去攻击,对比当前情况,比特币攻击者可以保证他们的攻击行为能够获得可观的回报。

在操作上,思路也很简单。你发送你的资金到你自己创建的保险柜地址。每一个保险柜地址有一个开锁密钥和恢复密钥。当你使用开锁密钥从保险柜花费时,你必须等待预先设置的时间(非保险期),它是你创建保险柜时创建的,比如说24小时。当一切顺利的话,在不保险期之后,你保险柜里的资金是未锁定状态,你可以将它们转移到其他地址,然后像往常一样去花费它们。现在,假使Harry一个黑客掌握了你的开锁密钥,你也有24小时的时间使用恢复密钥撤销Harry发起的交易。这次偷盗行为本质上讲是失败的,资金会转移到正确的拥有者那里。它有点像现代银行依靠的“撤销”功能,但是是在比特币世界。

现在,精明的读者会问,如果Harry是非常非常聪明,他不仅偷走了开锁密钥也偷走了恢复密钥,会怎样。那样的话,他已经完全攻陷你,就网络而言,他和你已经没有区别。即便如此,保险柜依然可以保护你。恢复密钥同样有一个类似的锁定期,允许你永久性的撤销Harry所有的交易行为。不幸的是,在这种情况下,Harry也可以做同样的事,撤销你做的所有交易。为了避免反复的僵局,恢复密钥也可以烧掉资金,这样就你没有人能得到这笔钱。结局是Harry从他的偷盗行为中不能够得到任何回报。这样实际上意味者Harry首先就不会把保险柜列为目标,因为如果这样做他不会有任何收入。

在比特币契约之上构建保险柜

在比特币中实现这样的保险柜机制是遥不可及的。一种可行的方案是,为保险柜专门设计的工具,使用专门的地址为保险柜,更多的操作代码。但是我们相信架构的变更,应该是最小并且通用。因此,我们提出对比特币进行一个小的变更,称之为“比特币契约“。就像法律契约,比特币契约会检查交易花费的条件是否成立。本质上讲,契约是未来交易形式的一种约束。因为契约可以递归,可以保持自我永存,或者可以某段时间进行限制,它应当允许一个人实现一系列丰富的语义自定义。

扩展脚本语言的想法并不是新近提起。事实上,我们命名为契约源于一篇Greg Maxwell发表过的文章随便说说的文章,他建议了一个不大可能的机制并且提到一些奇怪的案例。这篇文章很值得一读。

不可逆转性不会被影响

很重要的要指出,保险柜不会影响比特币交易的不可逆转性。保险柜是个人资金的保护机制:你可以将你希望安全保存的资金放到你自己创建的保险柜地址。这样做的话,你放弃了迅速消费它们的能力换来防盗。当你想使用这些币时,你可以将它们从保险柜转移到你的热钱包,你用你的钱包进行支付。只有你自己拥有的钱可以被保存到保险柜,它们也只能转回到你的所有权下。你不能欺骗某人接受一笔来自保险柜的交易,然后再将这些币收回。整个的设计关系到个人资产的保护,这将影响到他们选择哪种币来保存个人资产,保证比特币上的资产不会让人产生任何不安。

总的来讲,我们的建议是一种简单而强大的对脚本语言的扩展,这很容易推断出,它将开启更加丰富的设想的大门。

保险柜是契约的第一个用例,它解决一个自比特币系统第发布以来就一直困扰每一个比特币用户的问题。我们希望保险柜可以使人们可以安全的保存它们的线上资金,知道他们总是远离被盗,更重要的是它从根本上断除了偷窃的想法。


原文:http://hackingdistributed.com/2016/02/26/how-to-implement-secure-bitcoin-vaults/
译者:@rubyu2


以太坊可以使用智能合约来实现

基本思路:创建一个合约来保存以太币,并保存一个开锁密钥和一个恢复密钥。开锁秘钥可以将以太币返还到你的热钱包账户中,并有24小时延迟。恢复密钥可以重置开锁密钥的操作,将合约恢复为长期保存状态。

因为开锁密钥和恢复密钥为折中关系,它们可以互相撤销对方的操作。尽管如此,恢复密钥还可以销毁以太币。所以,根据这三点的折中,你依然会可能失去以太币,但是你至少可以避免以太币被攻击者获得,减少了被攻击的动机。

完全未经过测试的,刚刚仓促完成的代码:

contract Vault {
    address public hotwallet;
    address public vaultkey;
    address public recoverykey;
    uint public unvaultedAmount;
    uint public redeemblock;
    bool public destroyed;

    modifier only_vaultkey() { 
        if (msg.sender != vaultkey) throw;
        _
    }

    modifier only_recoverykey() { 
        if (msg.sender != recoverykey) throw;
        _
    }

    event Unvault(uint _amount);
    event Redeem();
    event Recover(address _newwallet);
    event Destroy();

    function Vault(address vault, address recovery) {
        hotwallet = msg.sender;
        vaultkey = vault;
        recoverykey = recovery;
        destroyed = false;
    }

    function unvault(uint amount) only_vaultkey {
        if (amount + unvaultedAmount > this.balance) return;
        unvaultedAmount += amount;
        redeemblock = block.timestamp + 24 hours;
        Unvault(amount);
    }

    function redeem() only_vaultkey {
        if (destroyed || block.timestamp < redeemblock) return;
        hotwallet.call.value(unvaultedAmount)();
        unvaultedAmount = 0;
        Redeem();
    }

    function recover(address newHotwallet) only_recoverykey {
        unvaultedAmount = 0;
        hotwallet = newHotwallet;
        Recover(newHotwallet);
    }

    function destroy() only_recoverykey {
        destroyed = true;
        Destroy();
    }
}

译者:@rubyu2

 
1 人喜欢