/// <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); }
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 a number m. /// Finds p >= 0 and k (k is odd), where m = 2^p * k. /// Return p and k by ref. /// /// p = 0; /// if (!IsEven(m)) /// { /// k = m; /// } /// else // m is even. /// { /// while(IsEven(m)) /// { /// m /= 2; /// p++; /// } /// k = m; /// } /// </summary> /// <param name=""></param> /// <param name=""></param> public static void FindExpressionOfGivenNumberByPowerOfTwoTimesOddNumber(BigNum m, BigNum p, BigNum k) { if (!m.IsEven()) { k.Set(m); } else { while (m.IsEven()) { DivNum(m, GlobalVariables.two, m, new BigNum()); p.AddNum(GlobalVariables.one); } k.Set(m); } }
/// <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); }
/// <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"); } }