Защита данных в .NET - Стандарт шифрования данных

ОГЛАВЛЕНИЕ

3. Стандарт шифрования данных

DES является наиболее широко используемым шифром с закрытым ключом. Он имеет классическую структуру Фейстеля, состоящую из некоторого количества идентичных циклов обработки. DES использует 64-битный блок и 54-битный размер ключа. Ключ используется и в шифровании, и в расшифровке. Операция шифрования в DES выполняет циклы на рисунке.

Блок-схема шифрования DES

Рисунок изображает операцию шифрования. Инвертирование порядка применения ключей дает операцию расшифровки. Перед применением этого рисунка 16 ключей генерируются из секретного ключа. Эти фазы объяснены далее.

3.a Шифрование

Ниже приведен алгоритм операции шифрования, также изображенный на рисунке выше. Три фазы являются основой этого алгоритма: начальная перестановка, функция F() и конечная перестановка.

//Алгоритм шифрование DES
private Bit[] Encrypt64Bit(Bit[] block)
{
    InitialPermutation(block);

    Bit[] Left = block[0 - 31];
    Bit[] Right = block[31 - 63];
   
    for (int i = 1; i <= 16; i++)
    {
        Temp = Left;
        Left = Right;
        Right = (Temp) Xor (F(Right, Keys[i - 1]));
    }
    block[0 - 31] = Right;
    block[32 - 63] = Left;

    RevInitialPermutation(block);

    return block;
}

3.a.1 Начальная перестановка

Эта операция принимает 64- битные входные данные и переставляет другой блок в порядке таблицы IP. Например, первый элемент таблицы IP равен 58, тогда первый элемент нового блока содержит 58-й элемент входного блока. Следовательно, второй элемент нового блока содержит 50-й элемент входного блока, а последний элемент нового блока содержит 7-й элемент входного блока.

IP = new byte[8 * 8] {   58,    50,   42 ..... 15,    7 }; 

3.a.2 Функция F()

Этот метод принимает два параметра: правый блок (32 бита) и текущий ключ (48 бита). Сначала он увеличивает правый блок в порядке таблицы выбора E, что дает 48-битный блок. Затем применяет операцию “Исключающее или“ к новому блоку и текущему ключу. Потом разделяет подвергнутый операции “Исключающее или“ блок на 8 частей (первые 6 битов становятся первой частью, вторые 6 битов становятся второй частью и т. д.). Теперь есть 8 блоков, каждый содержит 6 битов. Далее из каждого 6-битового блока генерируется 4-битовый блок по следующему правилу:

(Есть восемь таблиц S, а именно S1, S2, S3... S8. Максимальный элемент в этих таблицах - 15, то есть число битов максимального элемента - 4). Пусть первые 6 битов равны abcdef, тогда вычисляется B1 = S1[2*a+f, 8*b+4*c+2*d+e]. Пусть вторые 6 битов равны asdfgh, тогда вычисляется B2 = S2[2*a+h, 8*s+4*d+2*f+g]. Пусть восьмые 6 битов равны zxcvbn, тогда вычисляется B8 = S8[2*z+n, 8*x+4*c+2*v+b].

Каждый из 8 блоков содержит 4 бита. Это дает 4*8=32 битный блок (B1 B2 B3 B4 B5 B6 B7 B8), в итоге переставляемый в порядке таблицы P, как показано в следующем фрагменте кода:

private BitArray F(BitArray R, BitArray K)
{
    R = Table(E, R);
    BitArray B = R.Xor(K);
    BitArray S = new BitArray(8 * 4);

    int x, y;
    BitArray Temp;
    for (int i = 0; i < 8; i++)
    {
        x = (B[i * 6 + 0] ? 2 : 0) + (B[i * 6 + 5] ? 1 : 0);
        y = (B[i * 6 + 1] ? 8 : 0) + (B[i * 6 + 2] ? 4 : 0) +
            (B[i * 6 + 3] ? 2 : 0) + (B[i * 6 + 4] ? 1 : 0);

        Temp = new BitArray(new byte[] { Ss[i, 16 * x + y] });
        Copy(Temp, 0, S, i * 4, 4);
    }

    S = Table(P, S);
    return S;
}

Блок-схема функции F

3.a.3 Операция XOR

Этот метод принимает два битовых массива и применяет операцию “Исключающее или“ к каждому биту входного массива. Затем он сохраняет подвергнутые операции “Исключающее или“ биты в новый битовый массив. Реализация данного метода выглядит так:

Bit[] Xor(Bit[] Left, Bit[] Right)
{
    Bit[] Result = new Bit[Right.Length];
    for (int i = 0; i < Right.Length; i++)
        Result[i] = Left[i] ^ Right[i];
    return Result;
}

3.a.4 Инвертирование начальной перестановки

Этот метод аналогичен методу начальной перестановки, не считая того, что входные данные переставляются в порядке таблицы IP-1.

3.b Расшифровка

Алгоритм расшифровки в DES аналогичен алгоритму шифрования, не считая того что он применяет обратный порядок ключей, как показано ниже:

//алгоритм расшифровки DES
private Bit[] Decrypt64Bit(Bit[] block)
{
    InitialPermutation(block);

    Bit[] Left = block[0 - 31];
    Bit[] Right = block[31 - 63];

    for (int i = 1; i <= 16; i++)
    {
        Temp = Left;
        Left = Right;
        Right = (Temp)Xor(F(Right, Keys[16 - i]));
    }
    block[0 - 31] = Right;
    block[32 - 63] = Left;

    RevInitialPermutation(block);

    return block;
}

3.c Генерация ключей

Эта операция принимает 56-битный ключ и генерирует 16 разных 48-битных ключей. Сначала входной ключ переставляется в порядке таблицы PC1, что дает 56-битный блок. Потом этот новый блок делится на две части, давая два 28-битных блока, а именно C0 и D0. Затем следуют 16 циклов. В каждом цикле C(n+1) и D(n+1) переставляются путем применения сдвига влево к C(n) и D(n). Наконец, перестановка (Cn)(Dn) в порядке таблицы PC-2 дает nй ключ (C0 D0 в порядке таблицы PC-2 дает первый ключ, C1 D1 в порядке таблицы PC-2 дает второй ключ ... C15 D15 в порядке таблицы PC-2 дает пятнадцатый ключ). Количество сдвигов влево отличается в каждом цикле. C1 D1 получается из C0 D0 путем одного сдвига влево, C2 D2 получается из C1 D1 путем одного сдвига влево, C3 D3 получается из C2 D2 путем двух сдвигов влево, и так далее. Один сдвиг влево означает перемещение битов на одну позицию влево, поэтому после одного сдвига влево биты в 28 позициях являются битами, ранее бывшими в позициях 2, 3,..., 28, 1.

//количество сдвигов влево в каждом цикле
LeftShifts = new byte[16] { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };

Блок-схема генерации ключа DES