Пример #1
0
        internal static BigInteger oddModPow(BigInteger _base, BigInteger exponent,
                                             BigInteger modulus)
        {
            // PRE: (base > 0), (exponent > 0), (modulus > 0) and (odd modulus)
            int k = (modulus.numberLength << 5); // r = 2^k
            // n-residue of base [base * r (mod modulus)]
            BigInteger a2 = _base.shiftLeft(k).mod(modulus);
            // n-residue of base [1 * r (mod modulus)]
            BigInteger x2 = BigInteger.getPowerOfTwo(k).mod(modulus);
            BigInteger res;
            // Compute (modulus[0]^(-1)) (mod 2^32) for odd modulus

            int n2 = calcN(modulus);

            if (modulus.numberLength == 1)
            {
                res = squareAndMultiply(x2, a2, exponent, modulus, n2);
            }
            else
            {
                res = slidingWindow(x2, a2, exponent, modulus, n2);
            }

            return(monPro(res, BigInteger.ONE, modulus, n2));
        }
Пример #2
0
        internal static BigInteger evenModPow(BigInteger _base, BigInteger exponent,
                                              BigInteger modulus)
        {
            // PRE: (base > 0), (exponent > 0), (modulus > 0) and (modulus even)
            // STEP 1: Obtain the factorization 'modulus'= q * 2^j.
            int        j = modulus.getLowestSetBit();
            BigInteger q = modulus.shiftRight(j);

            // STEP 2: Compute x1 := base^exponent (mod q).
            BigInteger x1 = oddModPow(_base, exponent, q);

            // STEP 3: Compute x2 := base^exponent (mod 2^j).
            BigInteger x2 = pow2ModPow(_base, exponent, j);

            // STEP 4: Compute q^(-1) (mod 2^j) and y := (x2-x1) * q^(-1) (mod 2^j)
            BigInteger qInv = modPow2Inverse(q, j);
            BigInteger y    = (x2.subtract(x1)).multiply(qInv);

            inplaceModPow2(y, j);
            if (y.sign < 0)
            {
                y = y.add(BigInteger.getPowerOfTwo(j));
            }
            // STEP 5: Compute and return: x1 + q * y
            return(x1.add(q.multiply(y)));
        }
Пример #3
0
        internal static BigInteger modInverseMontgomery(BigInteger a, BigInteger p)
        {
            if (a.sign == 0)
            {
                // ZERO hasn't inverse
                throw new ArithmeticException("BigInteger not invertible");
            }


            if (!p.testBit(0))
            {
                // montgomery inverse require even modulo
                return(modInverseLorencz(a, p));
            }

            int m = p.numberLength * 32;
            // PRE: a \in [1, p - 1]
            BigInteger u, v, r, s;

            u = p.copy();  // make copy to use inplace method
            v = a.copy();
            int max = Math.Max(v.numberLength, u.numberLength);

            r           = new BigInteger(1, 1, new int[max + 1]);
            s           = new BigInteger(1, 1, new int[max + 1]);
            s.digits[0] = 1;
            // s == 1 && v == 0

            int k = 0;

            int lsbu = u.getLowestSetBit();
            int lsbv = v.getLowestSetBit();
            int toShift;

            if (lsbu > lsbv)
            {
                BitLevel.inplaceShiftRight(u, lsbu);
                BitLevel.inplaceShiftRight(v, lsbv);
                BitLevel.inplaceShiftLeft(r, lsbv);
                k += lsbu - lsbv;
            }
            else
            {
                BitLevel.inplaceShiftRight(u, lsbu);
                BitLevel.inplaceShiftRight(v, lsbv);
                BitLevel.inplaceShiftLeft(s, lsbu);
                k += lsbv - lsbu;
            }

            r.sign = 1;
            while (v.signum() > 0)
            {
                // INV v >= 0, u >= 0, v odd, u odd (except last iteration when v is even (0))

                while (u.compareTo(v) > BigInteger.EQUALS)
                {
                    Elementary.inplaceSubtract(u, v);
                    toShift = u.getLowestSetBit();
                    BitLevel.inplaceShiftRight(u, toShift);
                    Elementary.inplaceAdd(r, s);
                    BitLevel.inplaceShiftLeft(s, toShift);
                    k += toShift;
                }

                while (u.compareTo(v) <= BigInteger.EQUALS)
                {
                    Elementary.inplaceSubtract(v, u);
                    if (v.signum() == 0)
                    {
                        break;
                    }
                    toShift = v.getLowestSetBit();
                    BitLevel.inplaceShiftRight(v, toShift);
                    Elementary.inplaceAdd(s, r);
                    BitLevel.inplaceShiftLeft(r, toShift);
                    k += toShift;
                }
            }
            if (!u.isOne())
            {
                // in u is stored the gcd
                throw new ArithmeticException("BigInteger not invertible.");
            }
            if (r.compareTo(p) >= BigInteger.EQUALS)
            {
                Elementary.inplaceSubtract(r, p);
            }

            r = p.subtract(r);

            // Have pair: ((BigInteger)r, (Integer)k) where r == a^(-1) * 2^k mod (module)
            int n1 = calcN(p);

            if (k > m)
            {
                r = monPro(r, BigInteger.ONE, p, n1);
                k = k - m;
            }

            r = monPro(r, BigInteger.getPowerOfTwo(m - k), p, n1);
            return(r);
        }