Сеть Фейстеля на C# работает некорректно

Сеть Фейстеля при расшифровке неверно расшифровывает некоторые буквы. В чём у меня может быть ошибка?

Сама сеть:

        /// <summary>
        /// Шифрование строки
        /// </summary>
        /// <param name="input">Введённая строка</param>
        /// <param name="key">Ключ для шифра</param>
        /// <returns>Зашифрованная строка</returns>
        public string Encrypt(string input, string key)
        {
            //Проверяем строку и ключ на четность количества символов и, если нужно, дописываем в конце пробелы
            if (input.Length % 2 != 0)
                input += " ";
            if (key.Length % 2 != 0)
                key += " ";
            //Делим строку и ключ пополам
            string l = input.Substring(0, input.Length / 2);
            string r = input.Substring(input.Length / 2, input.Length - input.Length / 2);
            string K1 = key.Substring(0, key.Length / 2);
            string K2 = key.Substring(key.Length / 2, key.Length - key.Length / 2);
            //Создаём ещё два ключа, инвертировав предыдущие и "упаковываем" все ключи в массив
            char[] KeyArray = K1.ToCharArray();
            Array.Reverse(KeyArray);
            string K3 = new string(KeyArray);
            KeyArray = K2.ToCharArray();
            Array.Reverse(KeyArray);
            string K4 = new string(KeyArray);
            string[] Keys = {K1, K2, K3, K4};
            //Шифруем обе половины строки сетью Фейстеля
            XOR XOR_Algorithm = new XOR();
            foreach (string K in Keys)
            {
                string F = XOR_Algorithm.XOR_Algorithm(l, K);
                string l1 = XOR_Algorithm.XOR_Algorithm(F, r);
                if (K != K4)
                {
                    r = l;
                    l = l1;
                }
                else
                    r = l1;                                                           
            }
            return l + r;           
        }

        /// <summary>
        /// Расшифровка строки
        /// </summary>
        /// <param name="input">Введённая строка</param>
        /// <param name="key">Ключ для шифра</param>
        /// <returns>Расшифрованная строка</returns>
        public string Decrypt(string input, string key)
        {
            //Проверяем строку и ключ на четность количества символов и, если нужно, дописываем в конце пробелы
            if (input.Length % 2 != 0)
                input += " ";
            if (key.Length % 2 != 0)
                key += " ";
            //Делим строку и ключ пополам
            string l = input.Substring(0, input.Length / 2);
            string r = input.Substring(input.Length / 2, input.Length - input.Length / 2);
            string K1 = key.Substring(0, key.Length / 2);
            string K2 = key.Substring(key.Length / 2, key.Length - key.Length / 2);
            //Создаём ещё два ключа, инвертировав предыдущие и "упаковываем" все ключи в массив
            char[] KeyArray = K1.ToCharArray();
            Array.Reverse(KeyArray);
            string K3 = new string(KeyArray);
            KeyArray = K2.ToCharArray();
            Array.Reverse(KeyArray);
            string K4 = new string(KeyArray);
            string[] Keys = {K4, K3, K2, K1};
            //Расшифровываем обе половины строки сетью Фейстеля
            XOR XOR_Algorithm = new XOR();
            foreach (string K in Keys)
            {
                string F = XOR_Algorithm.XOR_Algorithm(l, K);
                string l1 = XOR_Algorithm.XOR_Algorithm(F, r);                
                if (K != K1)
                {
                    r = l;
                    l = l1;
                }
                else
                    r = l1;
            }
            return l + r;
        }

Алгоритм гаммирования, использующийся в сети:

        /// <summary>
        /// Массив с цифрами и латинскими буквами. Будет применяться в качестве алфавита.
        /// </summary>
        char[] letters = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
                                       'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
                                        ' ', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };

        /// <summary>
        /// Алгоритм шифрования и дешифровки методом гаммирования
        /// </summary>
        /// <param name="input">Введённая строка</param>
        /// <param name="key">Ключ для шифра</param>
        /// <returns>Зашифрованная или расшифрованная строка</returns>
        public string XOR_Algorithm(string input, string key)
        {
            //Переводим строку и ключ в верхний регистр
            input = input.ToUpper();
            key = key.ToUpper();          
            //Создаём переменную для записи результата
            string result = "";
            //Объявляем переменную для хранения индексов букв ключа
            int key_index = 0;
            //Сам процесс побуквенного шифрования
            foreach (char symbol in input)
            {
                //Ищем номер символа в алфавите по формуле гаммирования
                int c = Array.IndexOf(letters, symbol) ^ Array.IndexOf(letters, key[key_index]);
                if (c > 36)
                    c = 0;
                //Прибавление к зашифрованному слову очередной буквы
                result += letters[c];
                //Сдвиг на одну букву в ключе
                key_index++;
                //Перезапуск ключа, если исчерпаны все буквы в нём
                if ((key_index + 1) == key.Length) key_index = 0;
            }
            //Вывод зашифрованной или расшифрованной строки
            return result;
        }

Алгоритм гаммирования отдельно от сети функционирует нормально.

UPD. Единственная моя задача - создать сеть Фейстеля, где в качестве шифрующей функции используется алгоритм гаммирования. Делаю я в точности, как мне объяснили - разбиваю сообщение пополам, беру 4 ключа (исходный ключ делю пополам и обе половины инвертирую), затем сперва ключом шифрую левую половину, а потом получившуюся последовательность шифрую правой половиной сообщения, после чего новой правой половиной становится то, что изначально было левой половиной, а новой левой половиной будет полученный шифр, и так делаю по очереди для каждого ключа, только в четвёртой итерации шифр "отдаю" правой половине, а левую оставляю такой же, как после прошлой итерации, ну и затем вывожу обе половины сообщения. В расшифровке сообщения всё то же самое, только ключи идут в обратной последовательности. Вся загвоздка состоит в том, что большая часть сообщения шифруется и расшифровывается верно, но одна или две буквы (последняя и иногда ещё какая-нибудь) после расшифровки получаются не такими, как должны быть, причём там бывают буквы, которых ни в сообщении, ни в ключе вообще нет.


Ответы (0 шт):