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))); }
public static BigInteger karatsuba(BigInteger op1, BigInteger op2) { BigInteger temp; if (op2.numberLength > op1.numberLength) { temp = op1; op1 = op2; op2 = temp; } if (op2.numberLength < whenUseKaratsuba) { return multiplyPAP(op1, op2); } /* Karatsuba: u = u1*B + u0 * v = v1*B + v0 * u*v = (u1*v1)*B^2 + ((u1-u0)*(v0-v1) + u1*v1 + u0*v0)*B + u0*v0 */ // ndiv2 = (op1.numberLength / 2) * 32 int ndiv2 = (int)(op1.numberLength & 0xFFFFFFFE) << 4; BigInteger upperOp1 = op1.shiftRight(ndiv2); BigInteger upperOp2 = op2.shiftRight(ndiv2); BigInteger lowerOp1 = op1.subtract(upperOp1.shiftLeft(ndiv2)); BigInteger lowerOp2 = op2.subtract(upperOp2.shiftLeft(ndiv2)); BigInteger upper = karatsuba(upperOp1, upperOp2); BigInteger lower = karatsuba(lowerOp1, lowerOp2); BigInteger middle = karatsuba( upperOp1.subtract(lowerOp1), lowerOp2.subtract(upperOp2)); middle = middle.add(upper).add(lower); middle = middle.shiftLeft(ndiv2); upper = upper.shiftLeft(ndiv2 << 1); return upper.add(middle).add(lower); }
private static bool millerRabin(BigInteger n, int t) { // PRE: n >= 0, t >= 0 BigInteger x; // x := UNIFORM{2...n-1} BigInteger y; // y := x^(q * 2^j) mod n BigInteger n_minus_1 = n.subtract(BigInteger.ONE); // n-1 int bitLength = n_minus_1.bitLength(); // ~ log2(n-1) // (q,k) such that: n-1 = q * 2^k and q is odd int k = n_minus_1.getLowestSetBit(); BigInteger q = n_minus_1.shiftRight(k); Random rnd = new Random(); for (int i = 0; i < t; i++) { // To generate a witness 'x', first it use the primes of table if (i < primes.Length) { x = BIprimes[i]; } else /* * It generates random witness only if it's necesssary. Note * that all methods would call Miller-Rabin with t <= 50 so * this part is only to do more robust the algorithm */ { do { x = new BigInteger(bitLength, rnd); } while ((x.compareTo(n) >= BigInteger.EQUALS) || (x.sign == 0) || x.isOne()); } y = x.modPow(q, n); if (y.isOne() || y.Equals(n_minus_1)) { continue; } for (int j = 1; j < k; j++) { if (y.Equals(n_minus_1)) { continue; } y = y.multiply(y).mod(n); if (y.isOne()) { return(false); } } if (!y.Equals(n_minus_1)) { return(false); } } return(true); }
public static BigInteger karatsuba(BigInteger op1, BigInteger op2) { BigInteger temp; if (op2.numberLength > op1.numberLength) { temp = op1; op1 = op2; op2 = temp; } if (op2.numberLength < whenUseKaratsuba) { return(multiplyPAP(op1, op2)); } /* Karatsuba: u = u1*B + u0 * v = v1*B + v0 * u*v = (u1*v1)*B^2 + ((u1-u0)*(v0-v1) + u1*v1 + u0*v0)*B + u0*v0 */ // ndiv2 = (op1.numberLength / 2) * 32 int ndiv2 = (int)(op1.numberLength & 0xFFFFFFFE) << 4; BigInteger upperOp1 = op1.shiftRight(ndiv2); BigInteger upperOp2 = op2.shiftRight(ndiv2); BigInteger lowerOp1 = op1.subtract(upperOp1.shiftLeft(ndiv2)); BigInteger lowerOp2 = op2.subtract(upperOp2.shiftLeft(ndiv2)); BigInteger upper = karatsuba(upperOp1, upperOp2); BigInteger lower = karatsuba(lowerOp1, lowerOp2); BigInteger middle = karatsuba(upperOp1.subtract(lowerOp1), lowerOp2.subtract(upperOp2)); middle = middle.add(upper).add(lower); middle = middle.shiftLeft(ndiv2); upper = upper.shiftLeft(ndiv2 << 1); return(upper.add(middle).add(lower)); }
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)); }