/// <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 <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> /// Overloading the ">=" operator. /// If num1 >= num2, num1-num2 should be positive => subResult.IsNegative = false. /// It should return true, therefore !subResult.IsNegative. /// </summary> /// <param name="num1"></param> /// <param name="num2"></param> /// <returns></returns> public static bool operator >=(BigNum num1, BigNum num2) { BigNum subResult = new BigNum(num1); subResult.SubNum(num2); return(!subResult.IsNegative); }
/// <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); }
public static void I() { Console.WriteLine("(I) Using SubNum method."); Console.WriteLine("18 - 5 = 13"); BigNum bigNumI1 = new BigNum(18L); BigNum bigNumI2 = new BigNum(5L); bigNumI1.SubNum(bigNumI2); Console.WriteLine(bigNumI1.WriteNum()); Console.WriteLine("375683 - 12345 = 363338 (1011000101101001010 in binary.)"); BigNum bigNumI3 = new BigNum(375683L); BigNum bigNumI4 = new BigNum(12345L); bigNumI3.SubNum(bigNumI4); Console.WriteLine(bigNumI3.WriteNum()); Console.WriteLine(); }
/// <summary> /// N. /// Runs Miller-Rabin algorithm k times. /// </summary> /// <param name="n"></param> /// <param name="k"></param> /// <returns></returns> public static bool IsPrime(BigNum n, int k) { bool isPrimeNumber = true; BigNum t = new BigNum(); BigNum u = new BigNum(); BigNum nMinusOne = new BigNum(n); nMinusOne.SubNum(GlobalVariables.one); FindExpressionOfGivenNumberByPowerOfTwoTimesOddNumber(nMinusOne, t, u); for (int i = 0; i < k; ++i) { if (!MillerRabinAlgorithm(n, new BigNum(t), u)) { isPrimeNumber = false; break; } } return(isPrimeNumber); }
/// <summary> /// J. /// Gets two BigNum type numbers, divided and divider. /// Returns by reference the result - quotient and reminder. /// </summary> /// <param name="divider"></param> public static void DivNum(BigNum divided, BigNum divider, BigNum quotientRetrunByRef, BigNum reminderReturnByRef) { List <int> positionsOf1s = new List <int>(); if (divided.MSB1Location.HasValue) { int indexPos = divided.MSB1Location.Value + divider.Length - 1; BigNum subResult = new BigNum(divided); while (indexPos < GlobalVariables.MAX_NUM) { BigNum numberFromLeftToIndex = GetSubBigNumFromLeftToIndex(subResult, indexPos); if (numberFromLeftToIndex >= divider) { // Saving quotient's info. positionsOf1s.Add(indexPos); // Subtract. int numberOfShifts = GlobalVariables.MAX_NUM - indexPos - 1; BigNum numberToSubtract = new BigNum(divider); numberToSubtract.ShiftLeft(numberOfShifts); subResult.SubNum(numberToSubtract); } indexPos++; } quotientRetrunByRef.ReadNum(positionsOf1s); reminderReturnByRef.Set(subResult); } else { Console.WriteLine("Cannot divide by zero"); } }