【问题标题】:What is a possible use case of BigInteger's .isProbablePrime()?BigInteger 的 .isProbablePrime() 的可能用例是什么?
【发布时间】:2015-02-10 08:44:37
【问题描述】:

The method BigInteger.isProbablePrime() 很奇怪;从文档中,这将判断一个数字是否为素数,概率为1 - 1 / 2^arg,其中arg 是整数参数。

它在JDK中已经存在很长时间了,所以它意味着它必须有用途。我在计算机科学和算法(以及数学)方面的有限知识告诉我,知道一个数字是否“可能”是素数但不完全是素数是没有意义的。

那么,想使用这种方法的可能场景是什么?密码学?

【问题讨论】:

  • 另外,Miller-Rabin primality test。主要优点是速度。例如。当您想检查因子时,您可以进行此类测试以加快因子分解过程。您可以将其中的“可能”部分保持在很低的水平,这在实践中很有用。但我同意它有点不稳定和奇怪,就像花车一样。
  • @maxx777 这是给定的——我要求一个实际的用例
  • 我真的很希望投反对票的人解释一下投反对票背后的原因
  • "它在JDK中已经存在很长时间了,所以它意味着它必须有用途。" - 或者它是出于无用的原因添加的,然后没有被删除,因为没有任何内容被删除。

标签: java primes


【解决方案1】:

是的,这种方法可以用于密码学。 RSA encryption 涉及寻找巨大的素数,有时大约为 1024 位(约 300 位)。 RSA 的安全性取决于这样一个事实,即对由 2 个质数相乘组成的数字进行因式分解是非常困难且耗时的。但要使其发挥作用,它们必须是素数。

事实证明,证明这些素数也很困难。但是Miller-Rabin primality testisProbablePrime 使用的素数测试之一,要么检测到一个数字是复合的,要么不给出结论。运行此测试n 次,您可以得出结论,有 2n 的几率是这个数字确实是复合的。运行它100 次会产生可接受的风险,即该数字是复合数字的 2100 分之一。

【讨论】:

  • @Mr.777 我见过拉宾-米勒一两次,但米勒-拉宾见过几十次。不过我不确定是否有正式名称。
  • @Mr.777 我在上面链接的 Wikipedia 页面首先声明了“Miller-Rabin”,但同时承认了这两个名称:“The Miller-Rabin primality test or Rabin-Miller primality test”。
  • isProbablyPrime 的实现(据我所知)是完全确定的。运行测试n 次如何提高正确结果的几率? (即使它是随机性的一个元素,也需要使多个调用的随机性独立,才能以您描述的方式影响风险。)
  • @TedHopp 该实现使用了一个随机生成器,每一轮都有一个新的随机数,有 3/4 的机会检测到复合物。默认生成器是 SecureRandom,具有很强的随机性保证。
  • 这可能很困难,但请记住,PRIMES 在 P 中。AKS 测试可能比 Miller-Rabin 慢,但它们之间没有指数差异或多项式。您可以使用 Miller-Rabin 找到一堆可能的素数,并使用 AKS 确定它们是素数。
【解决方案2】:

如果测试告诉你一个整数不是素数,你当然可以相信 100%。

这只是问题的另一面,如果测试告诉您整数是“可能的素数”,您可能会怀疑。使用不同的“碱基”重复测试可以使错误地成功“模仿”一个素数(对于多个碱基来说是一个强伪素数)的概率尽可能小。

测试的用处在于它的速度和简单性。人们不一定会对“可能的素数”作为最终答案的状态感到满意,但通过在引入素数测试的大炮之前使用此例程,肯定会避免在几乎所有合数上浪费时间.

与因式分解整数的难度进行比较有点像红鲱鱼。众所周知,整数的素数可以在多项式时间内确定,并且确实有证据证明米勒拉宾检验扩展到足够多的基是确定的(在检测素数时,与可能的素数相反),但这假设广义黎曼假设,所以它不像(更昂贵的)AKS primality test 那样确定。

【讨论】:

  • 值得注意的是,AKS 是在 2002 年 8 月才发现的,而这种方法从 2002 年 2 月就已经在 J​​DK 中了
  • 不,等等,自 1997 年 2 月以来它一直在 JDK 中(我查看的是 probablePrime 方法,而不是 isProbablePrime 方法)
  • 事实上,Agrawal、Kayal 和 Saxena 2002 年论文“PRIMES is in P”的标题标志着多项式的第一个无条件证明(位长为n) 确定性(一般整数)素数测试的复杂性。 Miller (1975) 表明,assuming GRH,整数的素数可以按照与位长的四次方成比例的步长进行确定性测试,比目前已知的 AKS 或其变体的指数要好得多。
  • 虽然 AKS 渐近地更快,但像 ECPP 这样的方法对于“加密”或“工业”质数来说会更有效。
  • AKS 非常慢,对于任何可计算的地质尺度时间的数字,AKS 都不会比 APR-CL 快,更不用说人类尺度了。 APR-CL 和 ECPP 早在 1997 年就出现了。正如 Brett 提到的,如果我们想要证明,ECPP 是一个不错的选择。与可能的素数方法(例如 M-R、BPSW、Frobenius)相比,所有这些方法都很慢。
【解决方案3】:

BigInteger.isProbablePrime(int) 的标准用例是密码学。具体来说,某些密码算法,例如RSA,需要随机选择的大素数。然而,重要的是,这些算法并不真正要求这些数字保证为素数——它们只需要以非常高概率为素数。

非常高有多高?好吧,在加密应用程序中,通常会调用 .isProbablePrime(),参数介于 128 和 256 之间。因此,非质数通过此类测试的概率小于 2128 或 2256.

让我们换个角度来看:如果您有 100 亿台计算机,每台计算机每秒生成 100 亿个可能的素数(这意味着在任何现代 CPU 上每个数字都少于一个时钟周期),并且这些数字的素数已经过测试使用.isProbablePrime(128),您平均会期望每 1000 亿年出现一次有一个非质数。

也就是说,如果这 100 亿台计算机能够以某种方式运行数千亿年而不会发生任何硬件故障,情况就会如此。但在实践中,随机宇宙射线更有可能在正确的时间和地点撞击您的计算机,从而将 .isProbablePrime(128) 的返回值从 false 翻转为 true,而不会导致任何其他可检测的影响,而不是非素数在该确定性水平上实际通过概率素性检验。

当然,随机宇宙射线和其他硬件故障的风险同样适用于确定性素性测试,如AKS。因此,在实践中,由于随机硬件故障(更不用说所有其他可能的错误来源,例如实现错误),即使是这些测试也具有(非常小的)基线误报率。

由于很容易将.isProbablePrime() 使用的Miller–Rabin primality test 的内在误报率推到远低于这个基线率,只需重复足够多次测试,因为即使重复了这么多次,Miller-在实践中,Rabin 测试仍然比最知名的确定性素性测试(如 AKS)快得多,它仍然是加密应用程序的标准素性测试。

(此外,即使您不小心选择了一个强伪素数作为 RSA 模数的因素之一,它通常也不会导致灾难性的失败。通常,这样的伪素数将是两个(或很少更多)的乘积大约一半长度的素数,这意味着你最终会得到一个multi-prime RSA key。只要没有一个因素小(如果是,素数测试应该抓住了它们),RSA算法仍然可以正常工作,虽然密钥对某些类型的攻击比相同长度的普通RSA密钥要弱一些,但如果你没有不必要地节省密钥长度,它应该仍然是相当安全的.)

【讨论】:

  • 故障问题是实际不使用 AKS 的一个原因(另一个是速度慢得惊人),ECPP 更为常见。正如您所注意到的,算法中的实现错误很可能发生,因此使用独立代码验证证书会很有帮助。
【解决方案4】:

一个可能的用例是测试给定数字的素数(测试本身有很多用途)。 isProbablePrime 算法的运行速度将比精确算法快得多,因此如果数字失败 isProbablePrime,则无需花费运行成本更高的算法。

【讨论】:

  • 那么,那是出于实用目的吗?由于素数分解是一个 NP 问题?
  • @fge - 是的,我提出的用例是为了实用。我不知道这有助于素数分解,这比测试素数要困难得多。对于后者,有一个多项式时间算法:AKS primality test
  • @fge:分解确实在 NP 中,但我怀疑您的意思是“NP-complete”,而分解是已知的。相反,强烈怀疑 不是 是 NP 难的。
【解决方案5】:

找到可能的素数是密码学中的一个重要问题。事实证明,寻找可能的 k 位素数的合理策略是重复选择一个随机的 k 位数,并使用类似isProbablePrime() 的方法测试它的可能素数。

如需进一步讨论,请参阅section 4.4.1 of the Handbook of Applied Cryptography

另请参阅 Brandt 和 Damgård 的 On generation of probable primes by incremental search

【讨论】:

    【解决方案6】:

    RSA 密钥生成等算法依赖于能够确定一个数字是否为素数。

    但是,在将 isProbablePrime 方法添加到 JDK 时(1997 年 2 月),还没有经过验证的方法可以在合理的时间内确定性地确定一个数是否为素数。当时最著名的方法是Miller-Rabin algorithm - 一种概率算法,有时会给出误报(即,会将非素数报告为素数),但可以进行调整以减少误报的可能性,但代价是运行时间适度增加。

    从那时起,已经发现了可以相当快地确定性地确定一个数是否为素数的算法,例如 2002 年 8 月发现的AKS algorithm。然而,应该注意的是,这些算法仍然没有那么快米勒-拉宾。

    也许更好的问题是为什么自 2002 年以来 JDK 没有添加 isPrime 方法。

    【讨论】:

    • 感谢历史视角!看起来@immibis 对“在 JDK 中但从未删除”的评论走在正确的轨道上,然后呢? :)
    • 我知道 Java 从不从标准库中删除东西是出了名的,但我不确定他们是否会删除它,即使他们可以。对于某些应用程序,99.999999999% 确定某物的质数就足够了,而且比 100% 确定要快得多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-03
    相关资源
    最近更新 更多