- 1.前言
- 2.为什么是区块链编程而不是比特币编程?
- 3.为什么是 C#?
- 4.预备条件
- 5.本书众筹
- 6.补充阅读
- 7.图标
- 8.许可: CC (ASA 3U)
- 9.项目设置
- 1.比特币地址
- 2.交易
- 3.区块链
- 4. 区块链不仅仅是比特币
- 5.支付比特币
- 6.作为真实性验证方法的所有权证明
- 1.足够随机了吗?
- 2.秘钥加密
- 3.秘钥的生成
- 1.P2PK[H] (向公钥付款 [Hash])
- 2.多重签名
- 3.P2SH ( 向脚本哈希付款)
- 4.灵活机动性
- 5.使用 TransactionBuilder
- 1.颜色币
- 2.发行一项资产
- 3.传输资产
- 4.单元测试
- 5.李嘉图合约
- 6.流动的民主
- 7.烧钱和声誉证明
- 8.存在性证明
- 1.比特币发展的挑战
- 2.如何证明一个币存在于区块链上
- 3.如何证明一个颜色币存在于区块链上
- 4.断开与第三方 API 的信任关系
- 5.防止延展性攻击
- 6.保护你的私钥
1.足够随机了吗?
当你调用 new Key() 时,实际上是在用 PRNG(伪随机数生成器)来产生私钥。在 windows 平台上,就是用系统提供的 RNGCryptoServiceProvider。.
在安卓上,我使用 SecureRandom,实际上你可以自己实现 RandomUtils.Random 然后使用它。
在 IOS 上,我还没用实现,你需要自己实现 IRandom。
对一台电脑来说,随机是很难的。但是最大的问题是,几乎不可能知道一串数字是否真的是随机的。
如果有个恶意软件修改了你的 PRNG(当然可以预测你将产生的随机数),当你发现时已经太迟了。
这就意味着跨平台的 PRNG 实现(就好像使用电脑时钟加上 CPU 速度)是危险的,但是当你发现时已经太迟了。
出于效率的考虑,大多数 PRNG 工作方法都是一样的:选择一个随机数,称为种子,然后每次你需要的时候,一个可预测的规则就会为你产生下一个数字。
种子的随机程度由熵的测量来定义,但是熵的大小同时取决于观察者。
假设你从时钟时间产生一个种子,并且你的时钟分辨率可能是 1ms。(实际上是更多,大约 15ms)
如果黑客知道上星期你产生了 key,那么你的种子有 1000 60 60 24 7 = 604800000 种可能性。
对这个黑客来说,熵就是 LOG(604800000;2) = 29.17 bits。
在我的家用电脑上遍历这样的数字用不了 2 秒钟,我们把这种遍历叫 暴力攻击 。
然而,如果你使用时钟时间 + 进程 ID 来产生种子, 并且假设有 1024 个不同的进程 ID。
那么,现在黑客就需要遍历 604800000 * 1024 种可能性,大概需要耗时 2000 秒。
然后,如果再加上我打开电脑的时间,就算黑客知道我是在今天打开的话,那也有 86400000 种可能性。
这样的话,黑客需要遍历 604800000 1024 86400000 = 5,35088E+19 种可能性。
可是,注意如果黑客攻击了我的电脑,他就可以获得最后的信息片段,减少数字的可能性,从而减少熵。
熵按照 LOG(possibilities;2) 来测量,所以 LOG(5,35088E+19; 2) = 65 bits。
足够了吗?也许,如果你面临的黑客不知道可能世界里的更多信息的话。
但是既然公钥的哈希是 20bytes = 160bits,比所有地址空间要小,所以你可以做得更好。
注意:增加熵的难度是线性递增的,攻击熵的难度是指数递增的。
一种可以快速产生熵的有趣方法就是人类的干预。(比如移动鼠标)
如果你不完全信任 PRNG 平台(并不奇怪),你可以给 NBitcoin 使用的 PRNG 输出增加熵。
RandomUtils.AddEntropy("hello");
RandomUtils.AddEntropy(new byte[] { 1, 2, 3 });
var nsaProofKey = new Key();
调用 AddEntropy(data) 时 NBitcoin 做的事情如下:
additionalEntropy = SHA(SHA(data) ^ additionalEntropy)
当你产生一个新数字的时候:
result = SHA(PRNG() ^ additionalEntropy)
c. 主要的派生函数
然而,数字的可能性并不是最重要的。最重要的是黑客成功打开你秘钥的时间。这样 KDF 就来了。
KDF, Key Derivation Function 的简称,是一种取得更加坚固秘钥的方法,即便你的熵比较低。
想象一下,你需要产生一个种子,并且黑客知道它存在 10,000,000 种可能性。这样的种子一般情况下很容就被破解了。
但是如果你可以让遍历工作慢一些呢?
一个 KDF 就是一个旨在耗费计算资源的哈希函数,下面是一个例子:
var derived = SCrypt.BitcoinComputeDerivedKey("hello", new byte[] { 1, 2, 3 });
RandomUtils.AddEntropy(derived);
即使你面临的黑客知道熵源就是 5 个字母,他仍然需要运行 Scrypt 以检测可能性,在我的电脑上这需要耗费 5 秒钟。
最后:不信任 PRNG 并不是固执己见,你可以通过增加熵和使用 KDF 来降低攻击的破坏性。
时刻记在心头,黑客可以收集你或者你的系统信息来降低熵。
如果你使用时间戳作为熵源,他就会知道你是上周生成秘钥的,并且你只在上午 9 点到下午 6 点之间使用电脑,这样就可以降低熵。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论