浅析区块链DApp安全随机源机制的设计与实现
摘要: 近期区块链DApp游戏的应用数量和用户数量都得到了一定增长,但令人担忧的是多款竞猜类DApp频频爆出被黑客进行了针对随机数缺陷的攻击。
近期,区块链DApp游戏的应用数量和用户数量都得到了一定增长,这对公链的应用探索和推广有积极的促进。令人担忧的是,多款竞猜类DApp频频爆出被黑客进行了针对随机数缺陷的攻击。攻击成功后,黑客就能够预知竞猜结果,来获得下一次竞猜的奖励。
在中心化的竞猜类应用里,竞猜结果都是由中心提供的,参与竞猜的客户端向中心服务提交竞猜订单,中心收集竞猜订单并生成竞猜结果返回给客户端。在这个过程中,客户端只负责收集竞猜订单和通知结果,并不参与竞猜结果的计算。竞猜结果都是由中心产生竞猜用随机数,根据游戏规则将随机数的随机性体现在竞猜结果上。通过这样的随机数转化来保证竞猜结果的随机性和公平性。因此竞猜应用是否公平、中奖机率是否随机,完全取决于随机数的生成、使用过程是否完全实现了的随机性的传递。
在区块链的DApp应用里,随机数或由第三方随机数服务接口利用Oracle机制,由硬件HSM生成后提供给区块链参与者,或由智能合约提供生成规则后DApp自行生成。大多数DApp使用的都是由智能合约进行共识来生成伪随机数。
目前,ETH和EOS等公链并未提供可靠的伪随机数接口。一些热门的DApp游戏尤其是竞猜类游戏如Luckyos、EOS.WIN、EOSDice等先后因伪随机数生成的缺陷而遭到黑客攻击。我们以EOSDice举例来说明攻击的原理。
---------------https://github.com/loveblockchain/eosdice/blob/v3.0/eosbocai2222.hpp---------------
uint8_t random(account_name name, uint64_t game_id)
{
auto mixd = tapos_block_prefix() * tapos_block_num() + name + game_id - current_time();
const char *mixedChar = reinterpret_cast(&mixd);
checksum256 result;
sha256((char *)mixedChar, sizeof(mixedChar), &result);
uint64_t random_num = *(uint64_t *)(&result.hash[0]) + *(uint64_t *)(&result.hash[8]) + *(uint64_t *)(&result.hash[16]) + *(uint64_t *)(&result.hash[24]);
return (uint8_t)(random_num % 100 + 1);
}
----------------------------------------------------------------------------------------------------------------------------
从最新修复后的代码可以看到,该随机函数中使用的随机因子(seed)主要是:
tapos_block_prefix() * tapos_block_num() --参照区块信息
name --账户名
game_id --账户名
current_time() -- 当前时间
在该版本中,下注账户余额(pool_ol_eos.amount) 已经不参与随机因子(seed)。项目方解决被攻击的思路是避免黑客通过可控制的账户余额(pool_ol_eos.amount)来计算随机因子(seed)。但该修复只是减少可控因素的成本,随机因子中的账户名(name)还是可以被操纵的。当下注金额较大时,黑客依然有十足动力来进行攻击。
从安全本质上来说,能够被黑客轻易攻击是因为这个随机数算法不具备工业级别。表现为:
1. 作为随机因子的(seed)的熵源(Entropy Input)不是可靠。
2. 随机因子Seed的安全强度不足。
3. 算法简单和重置随机因子机制缺失,随机数结果可回溯且具备可预测性。
如何设计和运用具备工业级别的伪随机数方案,笔者建议参考2015年 的NIST 800-90A《确定性随机比特生成器的随机数生成方法建议》(‘Recommendation for Random Number Generation Using Deterministic Random Bit Generators’),它给出了实践和参考的一些实现方法。但结合DApp的业务流程时,也需要进行针对性的调整。NIST的800-90A 2016年版本也曾造成了重大的安全事故:建议中包含了4种随机数生成方法,其中一种Dual_EC_DRBG算法为美国安全局进行全球的通讯窃听提供了有力的助攻。
该建议书中的DRBG(Deterministic Random Bit Generators)机制有五个独立的功能:
1. 实例化功能(instantiate function)获取熵源(entropy input)或者附加 随机数Nonce和个性化字符串(personalization string)创建初始内部状态的随机因子(seed)。
2. 随机比特位生成功能根据请求使用当前内部状态(current internal state)和可能的附加输入(Additional Input)生成伪随机比特位; 并生成下一个请求的新内部状态(new internal state)。
3. 重设随机因子功能(Reseed Function)获取新的熵源,并将其与当前内部状态(current internal state)和可能的附加输入(Additional Input)结合创建新的随机因子(new seed)和新内部状态(new internal state)。
4. 注销实例化功能将内部状态清零擦除。
5. 自检功能确定DRBG机制能继续正常运行。
图片来源:NIST 800-90A《确定性随机比特生成器的随机数生成方法建议》
在开源世界里,已经有很多满足NIST要求800-90的DRBG的实现,笔者建议在不具备密码学基础的Developer不要轻易的编写自定义的伪随机数生成器。
即使采用满足标准的伪随机数生成器,但由于伪随机数生成算法跟设备上物理状态或执行过程中状态相关,在区块链分布式系统的各个Node无法得到一致的随机数。 在区块链世界里某些应用场景尤其是有奖竞猜等,各个Node所需要的随机数(不管是真随机还是伪随机)应该是可共识的,可信赖的,可验证且可审计的。
(作者:ChainShell,内容来自链得得内容开放平台“得得号”;本文仅代表作者观点,不代表链得得官方立场)
评论(0)
Oh! no
您是否确认要删除该条评论吗?