计算乘以两个长数的余数?

时间:2014-11-09 15:12:42

标签: java cryptography repeat

我正在编写一个加密方法的代码,用于使用重复平方来计算x ^ d模数

public static long repeatedSquaring(long x, long d, long n){
        x = x%n;
        boolean dj = d % 2 == 1;
        long c = dj ? x : 1;

        d = d / 2;
        while (d > 0){
            dj = d % 2 == 1;
            x = x * x % n; //Here
            if (dj)
                c = c * x % n; //and here..
            d = d / 2;
        }
        return c;
    }

n很小时,此代码可以正常工作。但是使用n > sqrt(Long.MAX_VALUE)会产生意外结果。 由于使用x ≈ n,我们可以x*x > Long.MAX_VALUE,然后模数运算符会将不正确的值分配给x(或c)。
所以,我的问题是,我们如何只使用数学相关的方法计算(A * B)%N(都是long类型)。
我不想使用BigInteger(BigA.multiply(BigB).remainder(BigN)或我们可以直接使用BigX.modPow(BigD, BigN)来解决这个大问题。) 我认为普通计算会比String计算运行得更快吗?除了我的问题,所有的临时值都是long类型'足够的'。
我想知道解决方案在最坏的情况下可以正常工作:A, B, N <≈ Long.MAX_VALUE

2 个答案:

答案 0 :(得分:1)

乘法可以在log(B)时间内与指数相似

if(b为奇数)a +乘(2 * a,(b-1)/ 2)mod N
否则乘以(2 * a,b / 2)mod N

这可以工作到longvalue / 2

http://en.wikipedia.org/wiki/Montgomery_reduction可能更合理

答案 1 :(得分:1)

真的,简短的回答是你需要使用BigInteger,即使你不想这样做。正如您所发现的那样,您目前采用的方法将超出long的范围;即使您改进算法,使用long仍然无法在答案中获得超过64位。

你说你用它来加密;但64位公钥加密是如此之弱,以至于比没有它更糟糕(因为它给出了一种错误的安全感)。对于公钥来说,即使1024位也不够,64位可能会或多或少地瞬间破解。

请注意,这与对称加密不同,其中密钥可以小得多。 (但即便如此,64位还不足以阻止业余黑客。)

请参阅this question,其中指出64位RSA可以在几分之一秒内破解......那是四年前的事了!