Java 中的模幂运算

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4066952/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:38:40  来源:igfitidea点击:

Modular Exponentiation in Java

javamathmodulusdsaexponentiation

提问by Carl Hagen

I need a way to calculate:

我需要一种计算方法:

(g^u * y^v) mod p

in Java.

在爪哇。

I've found this algorithm for calculating (g^u) mod p:

我找到了这个计算 (g^u) mod p 的算法:

int modulo(int a,int b,int c) {
    long x=1
    long y=a;
    while(b > 0){
        if(b%2 == 1){
            x=(x*y)%c;
        }
        y = (y*y)%c; // squaring the base
        b /= 2;
    }
    return (int) x%c;
}

and it works great, but I can't seem to find a way to do this for

而且效果很好,但我似乎找不到办法做到这一点

(g^u * y^v) mod p

as my math skills are lackluster.

因为我的数学能力很差。

To put it in context, it's for a java implementation of a "reduced" DSA - the verifying part requires this to be solved.

把它放在上下文中,它是一个“简化的”DSA 的 Java 实现——验证部分需要解决这个问题。

回答by Christian Mann

Assuming that the two factors will not overflow, I believe you can simplify an expression like that in this way:

假设这两个因素不会溢出,我相信你可以这样简化这样的表达式:

(x * y) mod p = ( (x mod p)*(y mod p) ) mod p. I'm sure you can figure it out from there.

(x * y) mod p = ( (x mod p)*(y mod p) ) mod p. 我相信你可以从那里弄清楚。

回答by wnoise

That fragment of code implements the well known "fast exponentiation" algorithm, also known as Exponentiation by squaring.

该代码片段实现了众所周知的“快速取幂”算法,也称为平方

It also uses the fact that (a * b) mod p = ((a mod p) * (b mod p)) mod p. (Both addition and multiplications are preserved structures under taking a prime modulus -- it is a homomorphism). This way at every point in the algorithm it reduces to numbers smaller than p.

它还使用了 (a * b) mod p = ((a mod p) * (b mod p)) mod p 的事实。(加法和乘法都是采用质数模数的保留结构——它是同态的)。这样,在算法中的每一点,它都会减少到小于 p 的数字。

While you could try to calculate these in an interleaved fashion in a loop, there's no real benefit to doing so. Just calculate them separately, multiply them together, and take the mod one last time.

虽然您可以尝试在循环中以交错方式计算这些,但这样做并没有真正的好处。只需分别计算它们,将它们相乘,最后一次取模数即可。

Be warned that you will get overflow if p^2 is greater than the largest representable int, and that this will cause you to have the wrong answer. For Java, switching to big integer might be prudent, or at least doing a runtime check on the size of p and throwing an exception.

请注意,如果 p^2 大于可表示的最大整数,则会出现溢出,这将导致您得到错误的答案。对于 Java,切换到大整数可能是谨慎的,或者至少对 p 的大小进行运行时检查并抛出异常。

Finally, if this is for cryptographic purposes, you should probably be using a library to do this, rather than implementing it yourself. It's very easy to do something slightly wrong that appears to work, but provides minimal to no security.

最后,如果这是出于加密目的,您可能应该使用库来执行此操作,而不是自己实现。很容易做一些看似可行的小错误,但提供的安全性极低甚至没有。

回答by Rogach

Try

尝试

(Math.pow(q, u) * Math.pow(y, v)) % p

(Math.pow(q, u) * Math.pow(y, v)) % p