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



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

关于素数,我指出这可能无关紧要。但重要的是在将1024个随机位转换为整数时,必须考虑哪种方法是正确的;将其视为已签名(像您一样)还是未签名?

例如,在8位中,如果我随机生成11010011,当被视为素数的无符号整数时,它就是211

如果我把相同的比特11010011当作一个有符号整数,我得到的-45不是素数,即使你接受负素数。

如果弄错了这一点,您的代码将错误地排除有效密钥,并错误地接受无效密钥。如果为了安全起见,你排除了所有的负片,那么你只会得到1023位素数(两个补码负片的最高有效位总是有一个1)。

因此,处理从位到整数的转换的方法能够避免负数,并避免整个负素数问题,而RSA对所选数字只有一个正确的解释作为密钥。我的猜测是解释是无符号的。

对于"为什么"这个问题,我们无法给您一个明确的答案。为此,您需要与设计API的人员交谈。

我倾向于同意@weston的猜想,即"这无关紧要";请参阅此链接。该链接的另一个结论是,它取决于素数的哪个定义被用于素数是否为负数。(根据最广泛使用的定义,它们不是,但…)

但是,我可以告诉您,实现行为是经过深思熟虑的。该方法的实现如下:

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的行为是否正确,务实的解决方案都是在测试之前添加一个测试,看看你的候选人是否呈阴性。

相关内容

  • 没有找到相关文章

最新更新