Необходимо реализовать алгоритм DES. Вопрос к этапу "Начальная перестановка"?

Есть массив байтов длины 64, в начале согласно "Wikipedia" необходимо выполнить начальную перестановку. Можно ли сделать это каким-то простым способом а не в лоб как это:

IP[1] = InputData[58];
IP[2] = InputData[50];           
IP[3] = InputData[42];

И так далее...


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

Автор решения: aepot

Начните с того, что это массив из 64 бит, а не байт, то есть 8 байт.

Из Википедии:

Исходный текст T (блок 64 бит) преобразуется c помощью начальной перестановки IP которая определяется таблицей 1

Поэтому исходный массив байт придется выровнять до размера, кратного 8, и только потом выполнить побитовую перестановку.

Так же следует учесть, что в IP массиве значения базируются на единице, то есть с 1 до 64, а в C# нумерация элементов массива или коллекции начинается с 0. Я не стал вычитать из каждого элемента массива единицу, а сделал это прямо в алгоритме перестановки. Но в идеале, нужно просто поправить массив IP.

Простой пример, как это можно сделать:

public class Program
{
    private static readonly int[] IP =
    {
        58, 50, 42, 34, 26, 18, 10, 2,
        60, 52, 44, 36, 28, 20, 12, 4,
        62, 54, 46, 38, 30, 22, 14, 6,
        64, 56, 48, 40, 32, 24, 16, 8,
        57, 49, 41, 33, 25, 17,  9, 1,
        59, 51, 43, 35, 27, 19, 11, 3,
        61, 53, 45, 37, 29, 21, 13, 5,
        63, 55, 47, 39, 31, 23, 15, 7
    };

    public static void Main()
    {
        string text = "Hello World!";
        Console.WriteLine("Исходная строка: {0}", text);
        byte[] bytes = Encoding.UTF8.GetBytes(text);
        int padding = bytes.Length % 8;
        if (padding > 0)
        {
            padding = 8 - padding;
            Array.Resize(ref bytes, bytes.Length + padding);
            Console.WriteLine("Выравнивание: {0} => {1}", bytes.Length - padding, bytes.Length);
        }
        Console.WriteLine("Исходные байты: {0}", string.Join(", ", bytes));
        byte[] encoded = InitialPermutation(bytes); // IP
        Console.WriteLine("Перестановка  : {0}", string.Join(", ", encoded));
        byte[] decoded = InitialPermutation(encoded, true); // FP
        Console.WriteLine("Восстановлено : {0}", string.Join(", ", decoded));
        if (padding > 0)
            Array.Resize(ref decoded, decoded.Length - padding);
        Console.WriteLine("Восстановленная строка: {0}", Encoding.UTF8.GetString(decoded));
        Console.ReadKey();
    }

    private static byte[] InitialPermutation(byte[] bytes, bool reverse = false)
    {
        byte[] result = new byte[bytes.Length];
        byte[] buffer = new byte[8];
        for (int i = 0; i < bytes.Length; i += 8)
        {
            Array.Copy(bytes, i, buffer, 0, 8);
            BitArray bits = new BitArray(buffer);
            BitArray outBits = new BitArray(64);
            for (int j = 0; j < bits.Length; j++)
            {
                if (reverse)
                    outBits[IP[j] - 1] = bits[j];
                else
                    outBits[j] = bits[IP[j] - 1];
            }
            outBits.CopyTo(result, i);
        }
        return result;
    }
}

Вывод в консоль

Исходная строка: Hello World!
Выравнивание: 12 => 16
Исходные байты: 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 0, 0, 0, 0
Перестановка  : 11, 185, 125, 0, 75, 123, 2, 251, 128, 64, 240, 0, 16, 96, 128, 224
Восстановлено : 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 0, 0, 0, 0
Восстановленная строка: Hello World!

А вообще готовую реализацию для такого старого алгоритма можно легко найти, вот например, но я не проверял, насколько там вменяемый код.

→ Ссылка