有没有什么好的方法可以在 Javascript 中生成加密强的伪随机(或真正的随机)数?
关键要求:如果 a.com 的 Javascript 生成一些随机数,其他人应该无法预测这些随机数。例如,evil.com 上的 Javascript 应该无法预测 a.com 获得的随机数。
总结我对这个主题的了解。 这是我在自己的研究中能够找到的:
所有浏览器都提供
Math.random()
作为库调用来生成伪随机数。不幸的是,它不提供加密质量的随机数并且不符合上述要求。在我见过的浏览器上,Math.random()
使用非加密 PRNG,其内部状态在多个站点之间共享。所以 evil.com 可以调用Math.random()
一堆,恢复 PRNG 的内部状态,然后推断 a.com 调用时得到了哪些随机数Math.random()
。此外,它使用非加密质量的 PRNG,因此如果 a.com 使用Math.random()
然后发布 IV 生成随机密钥和随机 IV,则有可能推断 PRNG 的内部状态(从 IV)然后恢复钥匙。所以,Math.random()
就出来了。我发现一篇研究论文着眼于用 Javascript 进行密码学。他们的代码,Stanford Javascript Crypto Library,是公开的。它确实包括一个加密强度的伪随机数。
但是,它似乎有一个很大的限制:如果我正确地阅读了论文,那么在伪随机数得到充分播种之前,用户与您的站点进行交互需要 10-40 秒。此外,每个站点都必须从头开始:如果 a.com 包含 SJCL 库,那么看起来 a.com 的脚本必须等待用户与 a.com 站点交互 10-40 秒(通常)在 a.com 可以生成加密质量的随机数之前。这是一个非常重要的限制。
这是他们的论文:
- 艾米莉·史塔克、迈克尔·汉堡、丹·博内。 Javascript 中的快速对称加密。2009 年美国国家癌症研究中心。
经典文章Javascript Cryptography Considered Harmful提到,缺乏任何在 Javascript 中获取加密强度随机数的好方法是在 Javascript 中进行安全加密的主要障碍。本文考虑了几种明显的方法,并解释了它们存在缺陷的原因。
底线是我不知道任何合理的解决方案;我发现的选项似乎都很有问题。然而,这些论文和论文写完已经好几年了,我知道网络技术可以迅速改变。有谁知道这个问题的任何好的解决方案?