SecureRandom 的 Android 实现是不是会产生真正的随机数?

Posted

技术标签:

【中文标题】SecureRandom 的 Android 实现是不是会产生真正的随机数?【英文标题】:Does the Android implementation of SecureRandom produce true random numbers?SecureRandom 的 Android 实现是否会产生真正的随机数? 【发布时间】:2014-11-07 03:43:06 【问题描述】:

我已经读过,一般来说,some implementations of SecureRandom may produce true random numbers。

特别是android docs 说

此类的实例将使用内部熵源生成初始种子,例如/dev/urandom

但这是否意味着它会产生真正的随机数(即,而不是伪随机数)?

如果我以这种方式在 Android 中使用SecureRandom...

SecureRandom sr = new SecureRandom();

...当我调用sr.nextBoolean() 时,我会得到真正随机的输出吗?

或者,如果我每次都通过这样做来获得输出,那么输出是否可能更多(或更少?)随机: new SecureRandom().nextBoolean()?

【问题讨论】:

这不是必须正确的,因为某些Android设备没有硬件来生成正确的随机数。至于带有该硬件的设备是否会使用它,我不这么认为,尽管 Linux 内核可能会加载一个从此类硬件获取真正随机数的模块。 AFAIK 所有的实现都使用不同的形式或算法散列。虽然具有良好的数学特性,但它们并不是真正随机的。 来自Android Developer's Blog:“我们现在已经确定,使用 Java 密码体系结构 (JCA) 进行密钥生成、签名或随机数生成的应用程序可能无法在 Android 上接收加密强值由于底层 PRNG 初始化不当导致的设备..."。之后,我相信 AOSP 会切换到 OpenSSL 的生成器。更改发生在Jelly Bean。 @ban-geoengineering - 我有代码使用 JNI 读取 Android 的传感器,然后播种随机数生成器(如 OpenSSL 或 Crypto++)。您可以使用它来做同样的事情,或者使用它来播种 Java HMAC/SHA-1 生成器。 “肉和土豆”源文件位于 Android/Crypto++ PRNG auto-seeded from sensors (by JWW) 的 Pastebin 上。我希望尽快将Eclipse项目上传到Crypto++ wiki(由于配置更改,wiki目前遇到问题)。 等一下。 /dev/urandom 仅用于生成初始种子。在那之后,一切都是算法。 SecureRandom 需要“提供加密强随机数生成器 (RNG)”。 【参考方案1】:

根据Android Developer Docs:

(SecureRandom) 符合 FIPS 140-2,加密模块的安全要求,第 4.9.1 节中指定的统计随机数生成器测试

但是,同样的警告适用于 Android 和 Java:

许多 SecureRandom 实现采用伪随机数生成器 (PRNG) 的形式,这意味着它们使用确定性算法从真正的随机种子生成伪随机序列。其他实现可能会产生真正的随机数,而其他实现可能会使用这两种技术的组合。

所以,简短的回答是:这取决于实施,但如果您对 FIPS 140-2 没问题,那么 SecureRandom 在法律上就足以满足您的目的。

【讨论】:

【参考方案2】:

关键的答案是/dev/urandom和defined by the linux kernel一样,保证不会阻塞。重点是在生成足够的熵的同时不让用户停滞不前。如果 android 文档说他们正在使用 /dev/urandom 进行初始化,并且内核中没有足够的熵来提供随机数,那么内核将退回到伪随机算法。

根据内核文档,/dev/urandom 被认为足以满足几乎所有目的,除了“长寿命 [加密] 密钥”。鉴于您对预期用途的描述,我怀疑 android SecureRandom 将被证明是随机的,足以满足您的目的。

【讨论】:

Android 是一种独特的野兽。它有/dev/urandom,但我不相信Android 的SecureRandomSecureRandomSpi 正在使用它。相反,种子真的很弱——它本质上是系统属性(如序列号、基带版本)、时间(毫秒和纳秒)和字符串 “All Your Ra​​ndomness Are Belong To Us”。查看EntropyService.java。【参考方案3】:

“真”和“伪随机”随机数对不同的人意味着很多不同的东西。最好避免这些。

/dev/urandom 的名声不好,因为人们不了解它和 /dev/random 之间的区别(比你想象的要小得多)。

如果您问/dev/urandom 播种是否会损害SecureRandom 将其用于加密目的的适用性,答案是响亮的“不”。

如果您有时间,您可能想阅读my essay 以了解整个问题。

【讨论】:

嗨,Thomas,我想你打错字了 - 一个 urandom 的。 (而且,不,这不是用于加密目的。)

以上是关于SecureRandom 的 Android 实现是不是会产生真正的随机数?的主要内容,如果未能解决你的问题,请参考以下文章

SecureRandom 数中的算法

Android AES加密工具类实现(基础回顾)

随机数SecureRandom在Linux下阻塞

Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [271] milliseconds

SecureRandom 线程安全吗?

jdk java.security.SecureRandom 性能问题