为什么Java中的BigInteger.isProbablePrime()函数对负数返回true?

时间:2017-01-07 23:21:47

标签: java rsa biginteger secure-random

我正在用Java实现RSA公钥加密算法。它需要生成两个随机素数。我一直在使用SecureRandom类生成两个1024位数来创建一个2048位密钥。我使用BigInteger类处理数字。我使用isProbablePrime()函数来确定它是否为素数,确定性为100.但是,我注意到此函数对于负数返回了true,即使根据定义,素数也不能为负数。

2 个答案:

答案 0 :(得分:2)

我们无法给出对“为什么”问题的确切答案。为此,您需要与设计API的人员交谈。

我倾向于同意@Weston的猜想“这无关紧要”;见official link。另一个来自链接的内容是它取决于使用素数的定义来判断素数是否为负数。 (根据最广泛使用的定义,它们不是,但......)

但是,我可以告诉你,实现行为是故意的。该方法的实现如下:

public boolean isProbablePrime(int certainty) {
    if (certainty <= 0)
        return true;
    BigInteger w = this.abs();
    if (w.equals(TWO))
        return true;
    if (!w.testBit(0) || w.equals(ONE))
        return false;
    return w.primeToCertainty(certainty, null);
}

注意测试前候选人的绝对值是多少。

这种行为已经存在了很长时间(从我可以看到)ZERO记录了有关它的Java Bug报告。这支持@Weston的推测。

无论isProbablePrime的行为是否正确,实用的解决方案是在测试之前添加测试以确定您的候选人是否为负。

答案 1 :(得分:2)

关于素数,我指出它可能not matter。但是重要是什么时候将1024个随机位转换为整数,你必须考虑哪个是正确的方法;把它视为已签名(就像你一样)或将其视为未签名?

例如,在8位中,如果我将11010011作为无效符号整数(即素数)时随机生成211

如果我将相同的位11010011视为有符号整数,即使您接受负素数,我也会得到不是素数的-45

出错并且您的代码将错误地排除有效密钥并错误地接受无效密钥。如果你排除所有负面只是为了安全起见,那么你只会得到1023位素数(二进制补码负数总是在最高位有1)。

因此,处理从位到整数的转换的方式能够避免负数并避免负素数的整个问题,并且RSA只能对选择的数字作为关键字进行正确解释。我的猜测是解释是无符号的。