public static bool MillerRabinAlgorithm(BigNum n, BigNum t, BigNum u) { bool isPrimeNumber = true; BigNum randomNumber = GenerateNumberFromOneToGivenTop(n); BigNum x0 = Power(randomNumber, u, n); BigNum x1 = new BigNum(); BigNum iterationNumber = new BigNum(GlobalVariables.one); while (iterationNumber <= t) // Iterates t times. { x1 = Power(x0, GlobalVariables.two, n); x0.Set(x1); if ((x1.CompNumWithoutPrint(GlobalVariables.one)) && (!x0.CompNumWithoutPrint(GlobalVariables.one)) && (!x0.CompNumWithoutPrint(GlobalVariables.minusOne))) { isPrimeNumber = false; break; } iterationNumber.AddNum(GlobalVariables.one); } if (isPrimeNumber) { if (!x1.CompNumWithoutPrint(GlobalVariables.one)) { isPrimeNumber = false; } } return(isPrimeNumber); }
/// <summary> /// Gets BigNum <paramref name="b"/>. /// Generates p and q, prime numbers. /// While b is not inverse number to p-1 and q-1, p and q re-generates. /// After finding good p and q, calculate a that is inverse of b mod ((p-1)(q-1)). /// n is calculated as p * q. /// Returns by reference the BigNum a, p, q, and n. /// </summary> /// <param name="b"></param> /// <param name="a"></param> /// <param name="q"></param> /// <param name="p"></param> /// <param name="nByRef"></param> public static void GenRSA(BigNum b, BigNum a, BigNum q, BigNum p, BigNum nByRef) { bool isBInverseOfPMinus1AndQMinus1 = false; BigNum n = new BigNum(); while (!isBInverseOfPMinus1AndQMinus1) { p.Set(GenPrime()); q.Set(GenPrime()); BigNum pMinus1 = new BigNum(p); pMinus1.SubNum(GlobalVariables.one); BigNum qMinus1 = new BigNum(q); qMinus1.SubNum(GlobalVariables.one); BigNum fiOfN = new BigNum(pMinus1); fiOfN.MultNum(qMinus1); BigNum gcd = new BigNum(); ExtendedGCD(b, fiOfN, new BigNum(), new BigNum(), gcd); if (gcd.CompNumWithoutPrint(GlobalVariables.one)) { isBInverseOfPMinus1AndQMinus1 = true; a.Set(Inverse(b, fiOfN)); if (a.IsNegative) { a.AddNum(fiOfN); } n = new BigNum(p); n.MultNum(q); } } nByRef.Set(n); }
/// <summary> /// M. /// Computes x to the power of y at mod z. /// </summary> /// <returns></returns> public static BigNum Power(BigNum x, BigNum y, BigNum z) { BigNum result = new BigNum(); if (y.CompNumWithoutPrint(GlobalVariables.zero)) { result = new BigNum(GlobalVariables.one); } else { if (y.IsEven()) { // x^y = [x^(y/2)]^2 mod z. BigNum yDividedBy2 = new BigNum(); DivNum(y, GlobalVariables.two, yDividedBy2, result); // y = y/2. result = Power(x, yDividedBy2, z); result.MultNum(new BigNum(result)); DivNum(result, z, new BigNum(), result); } else { BigNum yMinus1DividedBy2 = new BigNum(y); yMinus1DividedBy2.SubNum(GlobalVariables.one); // y = y-1. DivNum(y, GlobalVariables.two, yMinus1DividedBy2, result); // y = y-1/2. result = Power(x, yMinus1DividedBy2, z); result.MultNum(new BigNum(result)); DivNum(result, z, new BigNum(), result); result.MultNum(x); DivNum(result, z, new BigNum(), result); } } return(result); }
/// <summary> /// Gets BigNum number. /// Finds the index of the MSB 1 digit, run from it to the LSB. /// It has boolean variable <isSmaller> that set to true when the first 1's digits is cleared /// (set to 0). /// Unless <isSmaller> = true, this method cannot set any bit. /// Use random (IsGeneratedToSet() method) to set or clear that bit. /// </summary> /// <param name="top"></param> /// <returns></returns> private static BigNum GenerateNumberFromOneToGivenTop(BigNum top) { BigNum generatedNumber = new BigNum(); if (top.MSB1Location.HasValue) { do { bool isSmaller = false; List <int> PositionsOf1sList = new List <int>(); for (int i = top.MSB1Location.Value; i < GlobalVariables.MAX_NUM; ++i) { if (top[i] == 1) { if (GenerateOneOrZero() == 0) { isSmaller = true; } else { PositionsOf1sList.Add(i); } } else { if ((GenerateOneOrZero() == 1) && (isSmaller)) { PositionsOf1sList.Add(i); } } } generatedNumber.ReadNum(PositionsOf1sList); } while ((generatedNumber.CompNumWithoutPrint(GlobalVariables.zero)) || (generatedNumber.CompNumWithoutPrint(top))); } return(generatedNumber); }
/// <summary> /// L. /// Gets two BigNums, calculates the opposite number of a in mod m. ([a^-1][mod m]). /// Returns null if the a does not have an inverse mode m. (i.e: gcd(a, m) != 1). /// </summary> /// <param name="a"></param> /// <param name="m"></param> public static BigNum Inverse(BigNum a, BigNum m) { BigNum inverse = null; BigNum x = new BigNum(); BigNum y = new BigNum(); BigNum d = new BigNum(); // d will be gcd(a, m). ExtendedGCD(a, m, x, y, d); if (d.CompNumWithoutPrint(GlobalVariables.one)) { inverse = y; } return(inverse); }
/// <summary> /// K. /// Gets two BigNum type numbers a and m and returns by reference (d, x, y), also BigNum type numbers. /// d represents GCD(m,a). (Greatest common divider). /// Note: If d = 1, it means that x is the opposite number of m(mod a) and /// y is the opposite number of a(mod m). /// Proofe for Note: 1 = [m*x + a*y](mod m) ==> 1 = a*y. /// </summary> /// <param name="a"></param> /// <param name="m"></param> /// <param name="x"></param> /// <param name="y"></param> /// <param name="d"></param> public static void ExtendedGCD(BigNum a, BigNum m, BigNum x, BigNum y, BigNum d) { BigNum r0 = new BigNum(m); BigNum x0 = new BigNum(GlobalVariables.one); BigNum y0 = new BigNum(GlobalVariables.zero); BigNum r1 = new BigNum(a); BigNum x1 = new BigNum(GlobalVariables.zero); BigNum y1 = new BigNum(GlobalVariables.one); BigNum r = new BigNum(GlobalVariables.one); // Just to be able to enter the while loop. BigNum q = new BigNum(); DivNum(r0, r1, q, r); while (!r.CompNumWithoutPrint(GlobalVariables.zero)) { // x = x0 - qx1. BigNum qx1 = new BigNum(q); qx1.MultNum(x1); x.Set(x0); x.SubNum(qx1); // y = y0 - qy1. BigNum qy1 = new BigNum(q); qy1.MultNum(y1); y.Set(y0); y.SubNum(qy1); r0.Set(r1); x0.Set(x1); y0.Set(y1); r1.Set(r); x1.Set(x); y1.Set(y); DivNum(r0, r1, q, r); } d.Set(r1); x.Set(x1); y.Set(y1); }