我一直在研究计算大整数的模逆的问题,即^ -1 mod n。并一直使用BigInteger的内置函数modInverse来检查我的工作。
我已经按照Menezes等人的“应用密码学手册”中所示对算法进行了编码。对我来说不幸的是,我没有得到所有整数的正确结果。
我的想法是q = a.divide(b)这一行是我的问题,因为除法函数没有很好地记录(IMO)(我的代码也遭受类似的影响)。 BigInteger.divide(val)是圆形还是截断?我的假设是截断,因为文档说它模仿int的行为。任何其他见解都表示赞赏。
这是我一直在使用的代码:
private static BigInteger modInverse(BigInteger a, BigInteger b) throws ArithmeticException {
//trivial case: b = 0 => a^-1 = 1
if (b.equals(BigInteger.ZERO)) {
return BigInteger.ONE;
}
//all other cases
BigInteger x2 = BigInteger.ONE;
BigInteger x1 = BigInteger.ZERO;
BigInteger y2 = BigInteger.ZERO;
BigInteger y1 = BigInteger.ONE;
BigInteger x, y, q, r;
while (b.compareTo(BigInteger.ZERO) == 1) {
q = a.divide(b);
r = a.subtract(q.multiply(b));
x = x2.subtract(q.multiply(x1));
y = y2.subtract(q.multiply(y1));
a = b;
b = r;
x2 = x1;
x1 = x;
y2 = y1;
y1 = y;
}
if (!a.equals(BigInteger.ONE))
throw new ArithmeticException("a and n are not coprime");
return x2;
}
输出错误输入的示例是:
a:123456789
b:2 ^ 809 - 1
产生预期结果的输入示例是:
a:123456789
b:2 ^ 807 - 1
答案 0 :(得分:5)
以下是Java语言规范中指定整数除法的方法:
JLS 15.17.2 Division Operator
整数除法向0舍入。也就是说,为二进制数字提升后的整数操作数
n
和d
生成的商是一个整数值{{1}在满足q
的同时,其幅度尽可能大;此外,当|d·q|<=|n|
和q
和|n|>=|d|
具有相同的符号时,n
为正,但d
和{{1}时q
为否定}和|n|>=|d|
有相反的符号。
答案 1 :(得分:0)
将return x2;
更改为return y2;
,您的例行程序将给出正确答案。
编辑,此答案不再有效,因为顶级海报更改了他的代码。
答案 2 :(得分:0)
要使代码工作,您需要保存模数的原始值,您可以在开头创建:BigInteger m = b; 然后当你在x2中获得最终结果时,为了避免可能由欧几里德算法产生的负值,计算:x2.add(m),它将是BigInteger a,mod(b)的乘法逆,根据你的代码。