Сеть Фейстеля на 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 ключа (исходный ключ делю пополам и обе половины инвертирую), затем сперва ключом шифрую левую половину, а потом получившуюся последовательность шифрую правой половиной сообщения, после чего новой правой половиной становится то, что изначально было левой половиной, а новой левой половиной будет полученный шифр, и так делаю по очереди для каждого ключа, только в четвёртой итерации шифр "отдаю" правой половине, а левую оставляю такой же, как после прошлой итерации, ну и затем вывожу обе половины сообщения. В расшифровке сообщения всё то же самое, только ключи идут в обратной последовательности. Вся загвоздка состоит в том, что большая часть сообщения шифруется и расшифровывается верно, но одна или две буквы (последняя и иногда ещё какая-нибудь) после расшифровки получаются не такими, как должны быть, причём там бывают буквы, которых ни в сообщении, ни в ключе вообще нет.