/// <summary> /// Calculates a public exponent on the basis of /// a pair of primes which form the RSA secret key and /// the number chosen as public exponent. /// </summary> /// <typeparam name="B">An implementation of <c>IBase</c> interface which specifies the digit base of <c>LongInt<<typeparamref name="B"/>></c> numbers.</typeparam> /// <param name="secretKey">A pair of primes which form the RSA secret key.</param> /// <returns>The secret exponent of the RSA algorithm.</returns> public static LongInt <B> GetSecretExponent <B>(Point <LongInt <B> > secretKey, LongInt <B> publicExponent) where B : IBase, new() { Contract.Requires <ArgumentNullException>(publicExponent != null, "publicExponent"); Contract.Requires <ArgumentNullException>(secretKey.X != null, "secretKey.X"); Contract.Requires <ArgumentNullException>(secretKey.Y != null, "secretKey.Y"); LongInt <B> totient = LongInt <B> .Helper.MultiplyFFTComplex(secretKey.X - 1, secretKey.Y - 1); return (WhiteMath <LongInt <B>, CalcLongInt <B> > .MultiplicativeInverse(publicExponent, totient)); }
/// <summary> /// Returns the first half of the [rootDegree]th roots of unity series in the BigInteger field. /// Used in the recursive FFT algorithm in LongInt.Helper class. /// /// Root degree should be an exact power of two. /// </summary> /// <param name="rootDegree"></param> /// <returns></returns> public static BigInteger[] rootsOfUnityHalfGalois(int rootDegree, bool inverted) { Contract.Requires <ArgumentOutOfRangeException>(rootDegree > 0, "The degree of the root should be a positive power of two."); Contract.Ensures( Contract.ForAll( Contract.Result <BigInteger[]>(), (x => WhiteMath <BigInteger, CalcBigInteger> .PowerIntegerModular(x, (ulong)rootDegree, NTT_MODULUS) == 1))); BigInteger[] result = new BigInteger[rootDegree / 2]; // The first root of unity is obviously one. // - result[0] = 1; // Now we will learn what k it is in rootDegree == 2^k // - int rootDegreeCopy = rootDegree; int rootDegreeExponent = 0; while (rootDegreeCopy > 1) { rootDegreeCopy /= 2; ++rootDegreeExponent; } // Now we obtain the principal 2^rootDegreeExponent-th root of unity. // - BigInteger principalRoot = WhiteMath <BigInteger, CalcBigInteger> .PowerIntegerModular( NTT_MAX_ROOT_OF_UNITY_2_30, WhiteMath <ulong, CalcULong> .PowerInteger(2, NTT_MAX_ROOT_OF_UNITY_DEGREE_EXPONENT - rootDegreeExponent), NTT_MODULUS); // Calculate the desired roots of unity. // - for (int i = 1; i < rootDegree / 2; i++) { // All the desired roots of unity are obtained as powers of the principal root. // - result[i] = result[i - 1] * principalRoot % NTT_MODULUS; } // If performing the inverse NTT, we should invert the roots. // - if (inverted) { for (int i = 0; i < rootDegree / 2; ++i) { result[i] = WhiteMath <BigInteger, CalcBigInteger> .MultiplicativeInverse(result[i], NTT_MODULUS); } } return(result); }
/// <summary> /// BACK FFT /// </summary> /// <param name="coefficients"></param> /// <returns></returns> internal static BigInteger[] Recursive_NTT_Inverse(IList <BigInteger> coefficients) { int n = coefficients.Count; BigInteger[] rootsHalf = rootsOfUnityHalfGalois(n, true); BigInteger[] result = Recursive_NTT_Skeleton(coefficients, rootsHalf, 1, 0); // We should multiply the result by the multiplicative inverse of length. // - BigInteger lengthMultiplicativeInverse = WhiteMath <BigInteger, CalcBigInteger> .MultiplicativeInverse(n, NTT_MODULUS); for (int i = 0; i < result.Length; i++) { result[i] = (result[i] * lengthMultiplicativeInverse) % NTT_MODULUS; } return(result); }
/// <summary> /// BACK FFT /// </summary> /// <param name="coefficients"></param> /// <returns></returns> internal static BigInteger[] Recursive_NTT_Inverse( IList <BigInteger> coefficients, NTTFiniteFieldInfo finiteFieldInfo) { int n = coefficients.Count; BigInteger[] rootsHalf = rootsOfUnityHalfGalois(finiteFieldInfo, n, true); BigInteger[] result = Recursive_NTT_Skeleton(coefficients, rootsHalf, finiteFieldInfo, 1, 0); // We should multiply the result by the multiplicative inverse of length // in contrast to the forward-NTT. // - BigInteger lengthMultiplicativeInverse = WhiteMath <BigInteger, CalcBigInteger> .MultiplicativeInverse(n, finiteFieldInfo.primeModulus); for (int i = 0; i < result.Length; i++) { result[i] = (result[i] * lengthMultiplicativeInverse) % finiteFieldInfo.primeModulus; } return(result); }
/// <summary> /// For debug purposes. Performs the NTT in a straightforward (quadratic) manner. /// </summary> internal static BigInteger[] __DB_Quadratic_NTT(IList <BigInteger> coefficients, bool back = false) { BigInteger[] rootsOfUnity = __DB__rootsOfUnityGalois(coefficients.Count, back); BigInteger[] result = new BigInteger[coefficients.Count]; for (int i = 0; i < rootsOfUnity.Length; ++i) { BigInteger currentRoot = rootsOfUnity[i]; BigInteger hornerResult = 0; for (int j = coefficients.Count - 1; j >= 0; --j) { hornerResult = (hornerResult * currentRoot + coefficients[j]) % NTT_MODULUS; } result[i] = hornerResult * (back ? WhiteMath <BigInteger, CalcBigInteger> .MultiplicativeInverse(coefficients.Count, NTT_MODULUS) : 1) % NTT_MODULUS; } return(result); }