Exemplo n.º 1
0
            /// <summary>
            ///     Осуществляет процесс восстановления ключа из его частей при помощи многочлена Лагранжа
            /// </summary>
            /// <param name="Fragments">Набор частей ключа</param>
            /// <param name="module">Модуль, по которому необходимо производить вычисления</param>
            /// <returns>Значение ключа</returns>
            public static BigInteger RestoreByLagrangePolynomial(KeyValuePair <int, BigInteger>[] Fragments,
                                                                 BigInteger module)
            {
                Comparison.LinearComparison Result = new Comparison.LinearComparison(0, module);
                Comparison.LinearComparison buffer = new Comparison.LinearComparison(1, module);

                foreach (KeyValuePair <int, BigInteger> fragment1 in Fragments)
                {
                    buffer.A = 1;
                    foreach (KeyValuePair <int, BigInteger> fragment2 in Fragments)
                    {
                        Comparison.LinearComparison fract = new Comparison.LinearComparison(fragment2.Key - fragment1.Key,
                                                                                            module);
                        if (fract.A == 0)
                        {
                            continue;
                        }
                        buffer.A *= fragment2.Key * Comparison.MultiplicativeInverse.Solve(fract.A, module);
                    }

                    Result.A += buffer.A * fragment1.Value;
                }

                return(Result.A);
            }
Exemplo n.º 2
0
        /// <summary>
        ///     Возвращает символ, полученный в результате дешифрования символа текста символом ключа.
        /// </summary>
        /// <param name="EncryptedShar"></param>
        /// <param name="KeyChar"></param>
        /// <returns></returns>
        public static char GetDecryptedChar(char EncryptedShar, char KeyChar)
        {
            int SourceIndex = Languages.CurrentLanguage.Alphabet.IndexOf(EncryptedShar);
            int KeyIndex    = Languages.CurrentLanguage.Alphabet.IndexOf(KeyChar);

            Comparison.LinearComparison ResultIndex =
                new Comparison.LinearComparison(SourceIndex - KeyIndex, Languages.CurrentLanguage.Alphabet.Length);
            return(Languages.CurrentLanguage.Alphabet[(int)ResultIndex.A]);
        }
Exemplo n.º 3
0
 /// <summary>
 ///     Возвращает результат восстановления секрета по имеющимся частям и пороговому значению.
 /// </summary>
 /// <param name="Parts"></param>
 /// <param name="Limit"></param>
 /// <returns></returns>
 public static BigInteger Restore(List <CRTPart> Parts, int Limit)
 {
     if (Parts.Count < Limit)
     {
         throw new InvalidOperationException(
                   "Невозможно восстановить секрет: число долей меньше порогового значения");
     }
     Comparison.LinearComparison NewM = Maths.CRT.Solve(Parts.Select(part => part.Comparison));
     return(new Comparison.LinearComparison(NewM.A, Parts.First().P).A);
 }
Exemplo n.º 4
0
            private static BigInteger SolveByGaussianMethod(KeyValuePair <int, BigInteger>[] Fragments,
                                                            BigInteger module)
            {
                int polynomdegree = Fragments.Length;

                Comparison.LinearComparison[][] Matrix = new Comparison.LinearComparison[polynomdegree][];
                for (int i = 0; i < polynomdegree; i++)
                {
                    Matrix[i] = new Comparison.LinearComparison[polynomdegree + 1].Select(_ => new Comparison.LinearComparison(0, module))
                                .ToArray();
                    Matrix[i][polynomdegree - 1].A = 1;
                    for (int j = polynomdegree - 2; j >= 0; j--)
                    {
                        Matrix[i][j].A = Matrix[i][j + 1].A * Fragments[i].Key;
                    }
                    Matrix[i][Matrix[i].Length - 1].A = Fragments[i].Value;
                }
                //Матрица проинициализирована

                //Фиксируем i-ую строку и начинаем у всех остальных создавать нули в столбце i
                for (int i = 0; i < polynomdegree - 1; i++)
                {
                    if (Matrix.Any(row =>
                                   row.Skip(row.Length - 1).All(element => element.A != 0) &&
                                   row.Take(row.Length - 1).All(element => element.A == 0)))
                    {
                        Comparison.LinearComparison[] target = Matrix.First(row =>
                                                                            row.Skip(row.Length - 2).All(element => element.A != 0) &&
                                                                            row.Take(row.Length - 2).All(element => element.A == 0)).ToArray();
                        Solve(target[target.Length - 2].A,
                              target[target.Length - 1].A,
                              module, out Comparison.LinearComparison result);
                        return(result.A);
                    }

                    int FirstNonZeroIndex = i;
                    while (FirstNonZeroIndex < Matrix.Length && Matrix[FirstNonZeroIndex][i].A == 0)
                    {
                        FirstNonZeroIndex++;
                    }
                    if (FirstNonZeroIndex == Matrix.Length)
                    {
                        continue;
                    }
                    SwapLines(Matrix, i, FirstNonZeroIndex);
                    //перебираем все остальные j-ые строки и производим вычитание
                    for (int j = i + 1; j < polynomdegree; j++)
                    {
                        if (Matrix[j][i].A == 0)
                        {
                            continue;
                        }

                        //высчитываем НОД и коэффициенты
                        BigInteger firstmultiplier = AdvancedEuclidsalgorithm.LCM(Matrix[i][i].A, Matrix[j][i].A) /
                                                     Matrix[i][i].A;
                        BigInteger secondmultiplier = firstmultiplier * Matrix[i][i].A / Matrix[j][i].A;
                        Matrix[j][i].A = 0;
                        //пробегаем по всей строке и задаем значения после вычитания
                        for (int k = i + 1; k < polynomdegree + 1; k++)
                        {
                            Matrix[j][k].A = Matrix[j][k].A * secondmultiplier - Matrix[i][k].A * firstmultiplier;
                        }
                    }
                }

                //получили выражение вида ak=b(mod m)

                return(Solve(Matrix[polynomdegree - 1][polynomdegree - 1].A,
                             Matrix[polynomdegree - 1][polynomdegree].A,
                             module, out Comparison.LinearComparison Result)
                    ? Result.A
                    : int.MaxValue);
            }
Exemplo n.º 5
0
            /// <summary>
            ///     Осуществляет генерацию кодов, подходящим заданным частотам так, чтобы добиться наименьшей средней длины сообщения.
            /// </summary>
            /// <param name="Probabilities">Массив - частотный анализ исходного алфавита.</param>
            /// <param name="k">Система счисления, в которой будет произведено кодирование.</param>
            /// <param name="AverageLength">Вычисленная в процессе генерации кодов средняя длина сообщения.</param>
            /// <returns>
            ///     Массив <see cref="ByteSet" />[], содержащий в себе коды, расположенные в соответствии введенным частотам в
            ///     порядке убывания.
            /// </returns>
            public static ByteSet[] GetCodes(double[] Probabilities, int k, out double AverageLength)
            {
                AverageLength = 0;
                if (k >= Probabilities.Length)
                {
                    ByteSet[] answer = new ByteSet[Probabilities.Length];
                    for (int i = 0; i < Probabilities.Length; i++)
                    {
                        answer[i] = new ByteSet {
                            Value = new[] { (byte)i }
                        };
                        AverageLength += Probabilities[i];
                    }

                    return(answer);
                }

                //k - это число частей, на которые нам необходимо разбивать вероятности
                double[] ProbCop = new double[Probabilities.Length];
                Probabilities.CopyTo(ProbCop, 0);
                Array.Sort(ProbCop, (d, d1) => Math.Sign((d1 - d)));
                //отсортировали свою копию массива в порядке убывания вероятностей

                Stack <int> Insertions = new Stack <int>();
                //n - мощность исходного алфавита (кол-во вероятностей, которое на вход дали)
                //k - мощность конечного алфавита (система счисления)
                //ПЕРВАЯ СВЕРТКА
                int FirstConvolutionLength;

                if (k == 2)
                {
                    FirstConvolutionLength = 2;
                }
                else
                {
                    Comparison.LinearComparison k0 = new Comparison.LinearComparison(ProbCop.Length, k - 1);
                    if (k0.A == 0)
                    {
                        FirstConvolutionLength = k - 1;
                    }
                    else if (k0.A == 1)
                    {
                        FirstConvolutionLength = k;
                    }
                    else
                    {
                        FirstConvolutionLength = (int)k0.A;
                    }
                }

                double Sum = ProbCop.Skip(ProbCop.Length - FirstConvolutionLength).Sum();

                Sum = Math.Round(Sum, 3);
                int Index        = 0;
                int ResultLength = ProbCop.Length - FirstConvolutionLength + 1;

                while (ProbCop[Index] >= Sum && Index < ResultLength)
                {
                    Index++;
                }
                Insertions.Push(Index);
                List <double> bufferProb = new List <double>(ProbCop);

                bufferProb.Insert(Index, Sum);
                ProbCop = bufferProb.Take(ResultLength).ToArray();
                //Последующие свертки
                while (ProbCop.Length != k)
                {
                    Sum = ProbCop.Skip(ProbCop.Length - k).Sum();
                    Sum = Math.Round(Sum, 3);
                    //вычислили сумму последних k элементов

                    //надо определить, на какой индекс будем вставлять
                    Index        = 0;
                    ResultLength = ProbCop.Length - k + 1;
                    while (ProbCop[Index] >= Sum && Index < ResultLength)
                    {
                        Index++;
                    }
                    //нашли индекс, на который необходимо вставить полученную сумму

                    Insertions.Push(Index);
                    bufferProb = new List <double>(ProbCop);
                    bufferProb.Insert(Index, Sum);
                    ProbCop = bufferProb.Take(ResultLength).ToArray();
                }

                List <ByteSet> Answer = new List <ByteSet>();

                for (int i = 0; i < ProbCop.Length; i++)
                {
                    Answer.Add(new ByteSet {
                        Value = new[] { (byte)i }
                    });
                }

                int            Moving;
                List <ByteSet> buffer;

                //Все восстановления, кроме последнего
                while (Insertions.Count != 1)
                {
                    Moving = Insertions.Pop();
                    //узнали о перестановке
                    buffer = new List <ByteSet>(Answer);
                    buffer.RemoveAt(Moving);
                    for (int i = 0; i < k; i++)
                    {
                        buffer.Add(new ByteSet(Answer[Moving]));
                        buffer.Last().Append((byte)i);
                    }

                    Answer = buffer;
                }

                //ВОССТАНОВЛЕНИЕ ПОСЛЕДНЕЙ СВЕРТКИ
                Moving = Insertions.Pop();
                //узнали о перестановке
                buffer = new List <ByteSet>(Answer);
                buffer.RemoveAt(Moving);
                for (int i = 0; i < FirstConvolutionLength; i++)
                {
                    buffer.Add(new ByteSet(Answer[Moving]));
                    buffer.Last().Append((byte)i);
                }

                Answer = buffer;

                AverageLength += Probabilities.Select((t, i) => t * Answer[i].Length).Sum();
                return(Answer.ToArray());
            }