/// <summary> /// Осуществляет разделение ключа на несколько частей /// </summary> /// <param name="Key">Ключ, который необходимо разделить</param> /// <param name="CountOfFragments">Число фрагментов, на которые необходимо разделить ключ</param> /// <param name="module">Модуль, который будет определен исходя из ключа</param> /// <param name="Limit">Порог количества фрагментов, начиная с которого можно будет восстановить ключ</param> /// <returns>Массив наборов (x,y). x можно публиковать. y должен находиться в секрете.</returns> public static KeyValuePair <int, BigInteger>[] Share(BigInteger Key, int CountOfFragments, out BigInteger module, int Limit = -1) { if (Limit == -1) { Limit = CountOfFragments; } module = GetBiggerRandomPrime(Key); //Вычислили модуль многочлена и знаем порог - пора генерировать многочлен. int[] coefs = new int[Limit]; for (int i = 0; i < coefs.Length - 1; i++) { coefs[i] = (int)RD.UniformDistribution(1, module - 1, 1)[0]; } coefs[coefs.Length - 1] = (int)Key; Polynoms.ModularPolynom sharepolynom = new Polynoms.ModularPolynom(coefs, (int)module); KeyValuePair <int, BigInteger>[] Keys = new KeyValuePair <int, BigInteger> [CountOfFragments]; for (int i = 1; i <= CountOfFragments; i++) { Keys[i - 1] = new KeyValuePair <int, BigInteger>(i, (BigInteger)sharepolynom.GetValue(i)); } return(Keys); }
/// <summary> /// Тест Соловея-Штрассена. Имеет числа КарлМайкла /// </summary> /// <param name="source">Число, которое необходмио протестировать</param> /// <param name="count">Число прогонов теста</param> /// <returns></returns> public static PrimalityTestResult SSPT(BigInteger source, BigInteger count) { if (count >= source) { throw new InvalidOperationException("Число прогонов теста не должно быть меньше тестируемого числа."); } if (source == 0) { return(PrimalityTestResult.Composite); } if (source == 1) { return(PrimalityTestResult.Unknown); } if (source < 0 || count <= 0) { throw new InvalidOperationException( "Тестируемое число и число его прогонов должны быть положительными числами!"); } //нам необходимо, чтобы число было нечетным, поэтому мы отсеиваем все четные числа. if (source % 2 == 0) { return(PrimalityTestResult.Composite); } BigInteger[] RestVariants = RD.UniformDistribution(2, source - 1, count); //отрезок [2,n-1] for (int i = 0; i < count; i++) { BigInteger CurrentValue = RestVariants[i]; if (AdvancedEuclidsalgorithm.GCDResult(CurrentValue, source) != 1) { return(PrimalityTestResult.Composite); } //значение символа якоби BigInteger jacobi = JacobiSymbol.Get(CurrentValue, source); Comparison.LinearComparison comparison = new Comparison.LinearComparison(CurrentValue, source); if (Comparison.MultiplicativeInverse.BinaryPowLinearComparison(comparison, (source - 1) / 2).LeastModulo != jacobi) { return(PrimalityTestResult.Composite); } } return(PrimalityTestResult.Unknown); }
/// <summary> /// Fermat Primality Test - тест на основе теоремы Ферма. Имеет псевдопростые числа /// </summary> /// <param name="source">Число, которое необходимо проверить на простотоу</param> /// /// /// <param name="count">Число прогонов теста. Чем больше, тем точнее ответ.</param> /// <returns></returns> /// <exception cref="InvalidOperationException"></exception> public static PrimalityTestResult FPT(int source, int count) { if (count >= source) { throw new InvalidOperationException("Число прогонов теста должно быть меньше тестируемого числа."); } switch (source) { case 0: return(PrimalityTestResult.Composite); case 1: throw new InvalidOperationException("Единица не является ни простым, ни составным числом."); } if (source < 0 || count <= 0) { throw new InvalidOperationException( "Тестируемое число и количество прогонов должны быть положительными числами!"); } BigInteger[] RestVariants = RD.UniformDistribution(2, source - 1, count); //отрезок [2,n-1] for (int i = 1; i <= count; i++) { BigInteger CurrentValue = RestVariants[i - 1]; if (AdvancedEuclidsalgorithm.GCDResult(CurrentValue, source) != 1) { return(PrimalityTestResult.Composite); } Comparison.LinearComparison comparison = new Comparison.LinearComparison(CurrentValue, source); if (Comparison.MultiplicativeInverse.BinaryPowLinearComparison(comparison, source - 1).A != 1) { return(PrimalityTestResult.Composite); } } return(PrimalityTestResult.Unknown); }
/// <summary> /// Тест Рабина Миллера. Имеет сильно псевдопростые числа /// </summary> /// <param name="source"></param> /// <param name="count"></param> /// <returns></returns> public static PrimalityTestResult MRPT(int source, int count) { if (count >= source) { throw new InvalidOperationException("Число прогонов теста не должно быть меньше тестируемого числа."); } switch (source) { case 0: return(PrimalityTestResult.Composite); case 1: throw new InvalidOperationException("Единица не является ни простым, ни составным числом."); } if (source < 0 || count <= 0) { throw new InvalidOperationException( "Тестируемое число и число его прогонов должны быть положительными числами!"); } //нам необходимо, чтобы число было нечетным, поэтому мы отсеиваем все четные числа. if (source % 2 == 0) { return(PrimalityTestResult.Composite); } int t = source - 1; int s = 0; while (t % 2 == 0) { t /= 2; s++; } //n-1 = (2^s) * t BigInteger[] RestVariants = RD.UniformDistribution(2, source - 1, count); //отрезок [2,n-1] for (int i = 0; i < count; i++) { BigInteger CurrentValue = RestVariants[i]; if (AdvancedEuclidsalgorithm.GCDResult(CurrentValue, source) != 1) { return(PrimalityTestResult.Composite); } //значение символа якоби Comparison.LinearComparison comparison = new Comparison.LinearComparison(CurrentValue, source); if (BigInteger.Abs((comparison = Comparison.MultiplicativeInverse.BinaryPowLinearComparison(comparison, t)) .LeastModulo) == 1) { continue; } while (s != 1) { comparison = Comparison.MultiplicativeInverse.BinaryPowLinearComparison(comparison, 2); if (comparison.LeastModulo == -1) { break; } if (--s == 0) { return(PrimalityTestResult.Composite); } } } return(PrimalityTestResult.Unknown); }