简体   繁体   English

Java 中的模幂运算

[英]Modular Exponentiation in Java

I need a way to calculate:我需要一种方法来计算:

(g^u * y^v) mod p

in Java.在 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 实现 - 验证部分需要解决这个问题。

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 . (x * y) mod p = ( (x mod p)*(y mod p) ) mod p I'm sure you can figure it out from there. 我相信你可以从那里弄明白。

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. 它还使用(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. 这种方式在算法的每个点上都减少到小于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. 只需单独计算它们,将它们相乘,最后一次取mod。

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. 请注意,如果p ^ 2大于最大可表示的int,您将会溢出,这将导致您得到错误的答案。 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. 对于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. 做一些看起来有效的错误很容易,但提供的安全性很小甚至没有。

Try 尝试

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

Here's some sample code that inputs the variables in the original question and follows on from Christian Mann's answer.下面是一些示例代码,它在原始问题中输入变量,并遵循 Christian Mann 的回答。 BigInteger gets around the overflow issues. BigInteger 解决了溢出问题。 The return statement is a BigInteger.返回语句是一个 BigInteger。

    public static BigInteger ModularExponent(BigInteger G, BigInteger U, BigInteger Y, BigInteger V, BigInteger P) {
      
      return ((G.modPow(U,P)).multiply(Y.modPow(V,P))).mod(P);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM