Java 的 probablePrime 是否在生产中使用?

信息安全 加密 公钥基础设施 爪哇 RSA 伪随机数发生器
2021-08-30 14:09:53

质数是安全的核心。
我看到这个关于Java 的probablePrime的问题 ,并且想知道该 API/方法是否确实用于真正的生产就绪安全代码或其他方法是首选的,以确保使用非素数的可能性为 0

2个回答

重要的部分是“此方法返回的 BigInteger 是复合的概率不超过 2e-100”

硬件并不完全可靠:https ://community.hiveeyes.org/t/soft-errors-caused-by-single-event-upsets-seus/1891

让我们做一些假设:

  • 来自宇宙射线的机器每天翻转 1 位
    • 如果您愿意,您可以假设每台机器每年翻转 1 位 - 这是答案中的 2^8 倍。
  • 机器中的 2^38 位 (16GiB) 内存
  • 2^10 位翻转会使“绝对素数功能”无效
    • 结果本身(1 位,但如果在字节中返回布尔值,则可能为 8 位,如果在 int32_t 中返回布尔值,则可能为 32 位) - 运行测试后,可能会有一个循环尝试另一个数字是结果是复合的——但是如果函数返回“复合”,但宇宙射线将其翻转为“素数”怎么办?
    • 内存中的数字(2^10 == 1024 == 用于 2048 位 RSA 密钥的素数大小)
      • 我假设绝对素数函数需要一个数字的副本(到寄存器中),所以在启动之后,主存储器中的原始数字可以通过一点翻转来改变。如果发生这种情况,函数的结果将与内存中的数字不同 - 由于素数在 2^1024 范围内很少见,因此新数字可能是复合数。
    • 在结果上分支的代码——在函数之后运行后有一个分支指令(决定是否重试)——但是如果分支如果假被更改为分支如果真怎么办?还是一个分支 - 从不?还是改看不同的地址或寄存器?
  • 一天 86400 秒 ~ 2^16 秒/天

= 每天有 2^-38 次翻转的机会

= 2^-54 机会每秒翻转一点(2^-38 除以 2^16)

= 2^-44 每秒翻转有趣位的机会(将 2^-54 乘以有趣位的数量)

因此,绝对素数算法需要在 2^-54 秒内运行(比 probablePrime 长)才能与 probablePrime 函数一样确定。这比一条指令要少得多(2^-20 秒?)。否则 P(error(probablePrime)) < P(error(definitePrime + 位翻转))

我们使用 probablePrime 是因为它比绝对Prime 函数快得多,这使得它在真实计算机上更可靠。

这些数字相距甚远,即使我们在 2^25 秒(大约一年)内说 1 位翻转,在位翻转的风险超过不确定性之前,它仍然远少于我们可以允许的 1 条指令来自 probablePrime。

Java 8的BitInteger 类

  • probablePrime 来电
    • largePrime如果请求的素数有多个SMALL_PRIME_THRESHOLD = 95调用的位
      • searchSieve.retrieve,其中在昂贵的调用之前执行 BitSieve ( Sieving )
        • primeToCertainty(Rabin-Miller Test with 50rounds),Rabin Miller 的概率计算由 4 -k给出,因此概率为 4 -50 =2 -100换句话说,一个合数以 2 -100的概率通过测试。

这个概率是非常微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小微小

如果你想得到一个 100% 的素数

  1. 您可以假设它是素数,并在 RSA 或类似的加密系统中使用它,这样如果结果不正确,则可能表明存在问题。实际上,这仍然不是 100%,请参阅如果素数之一是 RSA 中的伪素数,是否存在将正确加密和解​​密的伪消息更好的一个;
  2. 使用AKS 素性测试,它是一种确定性素性证明算法。随着时间的推移有改进,但是,它仍然与拉宾米勒相比。

如果需要 100%,AKS 及其变体是唯一的选择。