Шифрование DES - теория и практика
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ
ГОУ ВПО ИЖЕВСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
КАФЕДРА ”ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ”
Отчёт по курсу «МИСЗИ»
студента 5 курса специальности 230105
(заочное отделение)
Задание « Шифрование DES »
Группа 10-19-4з
Выполнил Стерхов Д. В.
Принял Старыгин А. В.
Ижевск 2007
Теоретические сведения о DES
Процесс шифрования
DES представляет собой блочный шифр, он шифрует 64 - битовыми блоками. С одного конца алгоритма вводится 64 - битовый блок открытого текста, а с другого конца выходит 64 - битовый блок шифротекста. DES является симметричным алгоритмом: для шифрования и дешифрования используется одинаковые алгоритмы и ключ(за исключением различий в использовании ключа).
Длина ключа равна 56 битам. Ключ обычно представляется 64 - битовым числом, но каждый восьмой бит используется для проверки чётности и игнорируется. Биты чётности являются наименьшими значащими битами байтов ключа. Ключ, который может быть любым 56 - битовым числом, можно изменить в любой момент времени. Ряд чисел считаются слабыми ключами, но их можно легко избежать. Безопасность полностью определяется ключом.
На простейшем уровне алгоритм не представляет ничего большего, чем комбинация двух основных методов шифрования: смещения и диффузии. Фундаментальным строительным блоком DES является применение к тексту единичной комбинации этих методов(подстановка, а за ней перестановка), зависящей от ключа. Такой блок называется этапом. DES состоит из 16 этапов, одинаковая комбинация методов применяется к открытому тексту 16 раз.
Процесс шифрования данных поясняется рисунком 1. Сначала 64 бита входной последовательности перестанавливаются в соответствии с таблицей 1. Таким образом, бит 58 входной последовательности становится битом 1, бит 50 – 2 и т.д.
Таблица 1. "Начальная перестановка"
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 |
Полученная последовательность бит разделяется на две последовательности: L(0) (биты 58, 50, 42, ..., 8) и R(0) (биты 57, 49, 41, ..., 7), каждая из которых содержит 32 бита. Затем выполняется итеративный процесс шифрования, который описывается следующими формулами:
L(i)=R(i-1), i=1,2,...,16.
R(i)=L(i-1) + F(R(i-1),K(i)), i=1,2,...,16.
Функция F называется функцией шифрования. Ее аргументами являются последовательность R, полученная на предыдущем шаге, и 48-битовый ключ K(i), который является результатом функции преобразования 64-битового ключа шифра. Подробно функция шифрования и алгоритм получения ключей K(i) описаны ниже.
На последнем шаге итерации будут получены последовательности L(16) и R(16), которые конкатенируются в 64-х битовую последовательность R(16)L(16). Видно, что в полученной последовательности 64 бита, перестанавливаются в соответствии с таблицей 2. Как легко видеть данная перестановка является обратной по отношению к начальной (см. таблицу 1).
Таблица 2. "Конечная перестановка"
40 |
8 |
48 |
16 |
56 |
24 |
64 |
32 |
39 |
7 |
47 |
15 |
55 |
23 |
63 |
31 |
38 |
6 |
46 |
14 |
54 |
22 |
62 |
30 |
37 |
5 |
45 |
13 |
53 |
21 |
61 |
29 |
36 |
4 |
44 |
12 |
52 |
20 |
60 |
28 |
35 |
3 |
43 |
11 |
51 |
19 |
59 |
27 |
34 |
2 |
42 |
10 |
50 |
18 |
58 |
26 |
33 |
1 |
41 |
9 |
49 |
17 |
57 |
25 |
Полученная последовательность из 64 бит и будет являться зашифрованной последовательностью.
Рисунок 1
Процесс расшифрования
Процесс расшифрования данных является инверсным по отношению к процессу шифрования. Все действия должны быть выполнены в обратном порядке. Это означает, что расшифровываемые данные сначала переставляются в соответствии с таблицей 1, а затем над последовательностью бит R(16)L(16) выполняется те же действия, что и в процессе зашифрования, но в обратном порядке. Итеративный процесс расшифрования описан следующими формулами:
R(i-1)=L(i), i =16, 15, ..., 1
L(i-1)=R(i)+F(L(i),K(i)), i=16, 15, ..., 1.
На последнем шаге итерации будут получены последовательности L(0) и R(0), которые конкатенируются в 64 битовую последовательность L(0)R(0). В полученной последовательности 64 бита перестанавливаются в соответствии с таблицей 2. Результат преобразования - исходная последовательность бит (расшифрованное 64-битовое значение).
Функция шифрования
Функция шифрования F(R,K) схематически показана на рисунке 2. Для вычисления значения функции F используется функция E (расширение 32 бит до 48), функции S(1), S(2),...,S(8) преобразование 6-битового числа в 4-битовое) и функция P (перестановка бит в 32-битовой последовательности). Приведем определения этих функций. Аргументами функции шифрования являются R (32 бита) и K (48 бит). Результат функции E(R) есть 48-битовое число, которое складывается по модулю 2 с числом K. Таким образом, получается 48-битовая последовательность, которая рассматривается, как конкатенация 8 строк длиной по 6 бит (т.е. B(1)B(2)B(3)B(4)B(5)B(6)B(7)B(8)). Результат функции S(i)B(i) - 4 битовая последовательность, которую будем обозначать L(i). В результате конкатенации всех 8 полученных последовательностей L(i) имеем 32-битовую последовательность L=L(1)L(2)L(3)L(4)L(5)L(6)L(7)L(8). Наконец, для получения результат функции шифрования надо переставить биты последовательности L. Для этого применяется функция перестановки P(L).
Рисунок 2.
Функция расширения Е, выполняющая расширение 32 бит до 48, определяется таблицей. В соответствии с этой таблицей первые три бита Е(R) - это биты 32,1 и 2, а последние - 31,32,1.
"
Функция расширения Е"(перестановка с расширением)
32 |
1 |
2 |
3 |
4 |
5 |
4 |
5 |
6 |
7 |
8 |
9 |
8 |
9 |
10 |
11 |
12 |
13 |
12 |
13 |
14 |
15 |
16 |
17 |
13 |
17 |
18 |
19 |
20 |
21 |
20 |
21 |
22 |
23 |
24 |
25 |
24 |
25 |
26 |
27 |
28 |
29 |
28 |
29 |
30 |
31 |
32 |
1 |
Функция S(i), которая преобразует 6-битовые числа в 4-битовые. Эта операция расширяет правую половину данных, R>(>>i>>)> от 32 до 48 битов. Так как при этом не просто повторяются определённые биты, но и изменяется их порядок, эта операция называется перестановкой с расширением. У неё две задачи: привести размер правой половины в соответствии с ключом для операции XOR и получить более длинный результат, который можно будет сжать в ходе операции подстановки. Однако главный криптографический смысл совсем в другом. За счёт влияния одного бита на две подстановки быстрее возрастает зависимость битов результата от битов исходных данных. Это называется лавинным эффектом. DES спроектирован так, чтобы как можно быстрее добиться зависимости каждого бита шифротекста от каждого бита открытого текста и каждого бита ключа.
"Функции преобразования S(i)"
S(1)
14 |
4 |
13 |
1 |
2 |
15 |
11 |
8 |
3 |
10 |
6 |
12 |
5 |
9 |
0 |
7 |
0 |
15 |
7 |
4 |
14 |
2 |
13 |
1 |
10 |
6 |
12 |
11 |
9 |
5 |
3 |
8 |
4 |
1 |
14 |
8 |
13 |
6 |
2 |
11 |
15 |
12 |
9 |
7 |
3 |
10 |
5 |
0 |
15 |
12 |
8 |
2 |
4 |
9 |
1 |
7 |
5 |
11 |
3 |
14 |
10 |
0 |
6 |
13 |
S(2)
15 |
1 |
8 |
14 |
6 |
11 |
3 |
4 |
9 |
7 |
2 |
13 |
12 |
0 |
5 |
10 |
3 |
13 |
4 |
7 |
15 |
2 |
8 |
14 |
12 |
0 |
1 |
10 |
6 |
9 |
11 |
5 |
0 |
14 |
7 |
11 |
10 |
4 |
13 |
1 |
5 |
8 |
12 |
6 |
9 |
3 |
2 |
15 |
13 |
8 |
10 |
1 |
3 |
15 |
4 |
2 |
11 |
6 |
7 |
12 |
0 |
5 |
14 |
9 |
S(3)
10 |
0 |
9 |
14 |
6 |
3 |
15 |
5 |
1 |
13 |
12 |
7 |
11 |
4 |
2 |
8 |
13 |
7 |
0 |
9 |
3 |
4 |
6 |
10 |
2 |
8 |
5 |
14 |
12 |
11 |
15 |
1 |
13 |
6 |
4 |
9 |
8 |
15 |
3 |
0 |
11 |
1 |
2 |
12 |
5 |
10 |
14 |
7 |
1 |
10 |
13 |
0 |
6 |
9 |
8 |
7 |
4 |
15 |
14 |
3 |
11 |
5 |
2 |
12 |
S(4)
7 |
13 |
14 |
3 |
0 |
6 |
9 |
10 |
1 |
2 |
8 |
5 |
11 |
12 |
4 |
15 |
13 |
8 |
11 |
5 |
6 |
15 |
0 |
3 |
4 |
7 |
2 |
12 |
1 |
10 |
14 |
9 |
10 |
6 |
9 |
0 |
12 |
11 |
7 |
13 |
15 |
1 |
3 |
14 |
5 |
2 |
8 |
4 |
3 |
15 |
0 |
6 |
10 |
1 |
13 |
8 |
9 |
4 |
5 |
11 |
12 |
7 |
2 |
14 |
S(5)
2 |
12 |
4 |
1 |
7 |
10 |
11 |
6 |
8 |
5 |
3 |
15 |
13 |
0 |
14 |
9 |
14 |
11 |
2 |
12 |
4 |
7 |
13 |
1 |
5 |
0 |
15 |
10 |
3 |
9 |
8 |
6 |
4 |
2 |
1 |
11 |
10 |
13 |
7 |
8 |
15 |
9 |
12 |
5 |
6 |
3 |
0 |
14 |
11 |
8 |
12 |
7 |
1 |
14 |
2 |
13 |
6 |
15 |
0 |
9 |
10 |
4 |
5 |
3 |
S(6)
12 |
1 |
10 |
15 |
9 |
2 |
6 |
8 |
0 |
13 |
3 |
4 |
14 |
7 |
5 |
11 |
10 |
15 |
4 |
2 |
7 |
12 |
9 |
5 |
6 |
1 |
13 |
14 |
0 |
11 |
3 |
8 |
9 |
14 |
15 |
5 |
2 |
8 |
12 |
3 |
7 |
0 |
4 |
10 |
1 |
13 |
11 |
6 |
4 |
3 |
2 |
12 |
9 |
5 |
15 |
10 |
11 |
14 |
1 |
7 |
6 |
0 |
8 |
13 |
S(7)
4 |
11 |
2 |
14 |
15 |
0 |
8 |
13 |
3 |
12 |
9 |
7 |
5 |
10 |
6 |
1 |
13 |
0 |
11 |
7 |
4 |
9 |
1 |
10 |
14 |
3 |
5 |
12 |
2 |
15 |
8 |
6 |
1 |
4 |
11 |
13 |
12 |
3 |
7 |
14 |
10 |
15 |
6 |
8 |
0 |
5 |
9 |
2 |
6 |
11 |
13 |
8 |
1 |
4 |
10 |
7 |
9 |
5 |
0 |
15 |
14 |
2 |
3 |
12 |
S(8)
13 |
2 |
8 |
4 |
6 |
15 |
11 |
1 |
10 |
9 |
3 |
14 |
5 |
0 |
12 |
7 |
1 |
15 |
13 |
8 |
10 |
3 |
7 |
4 |
12 |
5 |
6 |
11 |
0 |
14 |
9 |
2 |
7 |
11 |
4 |
1 |
9 |
12 |
14 |
2 |
0 |
6 |
10 |
13 |
15 |
3 |
5 |
8 |
2 |
1 |
14 |
7 |
4 |
10 |
8 |
13 |
15 |
12 |
9 |
0 |
3 |
5 |
6 |
11 |
К таблице 4 требуются дополнительные пояснения. Каждая из функций S(i)B(i) преобразовывает 6-битовый код в 4-битовый выход по следующему алгоритму:
· первый и последний биты входной последовательности B, определяют номер строки k.
· второй, третий, четвертый и пятый биты последовательности B задают номер колонки l
· результат преобразования выбирается из строки k и колонки l.
Предположим, что B=011011. Тогда S(1)(B)=0101. Действительно, k=1, l=13. В колонке 13 строки 1 задано значение 5, которое и является значением функции S(1)(011011).
Функция перестановки бит P(L), также используемая для определения функции шифрования, задается значениями, приведенными в таблице 5. В последовательности L 32 перестанавливается так, чтобы бит 16 стал первым битом, бит 7 - вторым и т.д.
"Функция перестановки P"
16 |
7 |
20 |
21 |
29 |
12 |
28 |
17 |
1 |
15 |
23 |
26 |
5 |
18 |
31 |
10 |
2 |
8 |
24 |
14 |
32 |
27 |
3 |
9 |
19 |
13 |
30 |
6 |
22 |
11 |
4 |
25 |
Чтобы завершить описание алгоритма шифрования данных, осталось привести алгоритм получение ключей K(i), i=1,2,...,16, размерностью в 48 бит. Ключи K(i) определяются по 64-битовому ключу шифра как это показано.
В начале над ключом шифра выполняется операция B, которая сводится к выбору определенных бит и их перестановке, как это показано выше. Причем, первые четыре строки определяют, как выбираются биты последовательности C(0) (первым битом C(0) будет бит 57 бит ключа шифра, затем бит 49 и т.д., а последними битами биты 44 и 36 ключа шифра), а следующие четыре строки - как выбираются биты последовательности D(0) (т.е. последовательность D(0) будем стоять из битов 63,55,...,12, 4 ключа шифра).
"Функция перестановки и выбора последовательности B"(ключа)
57 |
49 |
41 |
33 |
25 |
17 |
9 |
1 |
58 |
50 |
42 |
34 |
26 |
18 |
10 |
2 |
59 |
51 |
43 |
35 |
27 |
19 |
11 |
3 |
60 |
52 |
44 |
36 |
63 |
55 |
47 |
39 |
31 |
23 |
15 |
7 |
62 |
54 |
46 |
38 |
30 |
22 |
14 |
6 |
61 |
53 |
45 |
37 |
29 |
21 |
13 |
5 |
28 |
20 |
12 |
4 |
Как видно из таблицы, для генерации последовательностей C(0) и D(0) не используются биты 8,16,25,32,40,48,56 и 64 ключа шифра. Эти биты не влияют на шифрование и могут служить для других целей (например, для контроля по четности). Таким образом, в действительности ключ шифра является 56-битовым. После определения C(0) и D(0) рекурсивно определяются C(i) и D(i), i=1,2,...,16. Для этого применяются операции сдвига влево на один или два бита в зависимости от номера шага итерации, как это показано в таблицей 7. Операции сдвига выполняются для последовательностей C(i) и D(i) независимо. Например, последовательность C(3) получается, посредством сдвига влево на две позиции последовательности C(2), а последовательность D(3) - посредством сдвига влево на две позиции последовательности D(2). Следует иметь в виду, что выполняется циклический сдвиг влево. Например, единичный сдвиг влево последовательности C(i) приведет к тому, что первый бит C(i) станет последним и последовательность бит будет следующая: 2,3,..., 28,1.
"Функция сдвига Si"
Этап |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
Число |
1 |
1 |
2 |
2 |
2 |
2 |
2 |
2 |
1 |
2 |
2 |
2 |
2 |
2 |
2 |
1 |
Ключ K(i), определяемый на каждом шаге итерации, есть результат выбора определенных бит из 56-битовой последовательности C(i)D(i) и их перестановки. Другими словами, K(i) = K(C(i)D(i)), где функция K определяется данными, приведенными в таблице.
"Функция перестановки и выбора K"(перестановка со сжатием)
После сдвига выбирается 48 из 56. Так как при этом не только выбирается подмножество битов, но и изменяется их порядок, эта операция называется перестановка со сжатием. Её результатом является набор из 48 битов.
14 |
17 |
11 |
24 |
1 |
5 |
3 |
28 |
15 |
6 |
21 |
10 |
23 |
19 |
12 |
4 |
26 |
8 |
16 |
7 |
27 |
20 |
13 |
2 |
41 |
52 |
31 |
37 |
47 |
55 |
30 |
40 |
51 |
45 |
33 |
48 |
44 |
49 |
39 |
56 |
34 |
53 |
46 |
42 |
50 |
36 |
29 |
32 |
Как следует из таблицы первый бит K(i) - это бит 14 последовательности C(i)D(i), второй - бит 17, последний - бит 32.
Пример
Шифруемое сообщение – шифровка = 11111000 11101000 11110100 11110000 11101110 11100010 11101010 11100000
Ключ шифрования 12345678 = 00110001 00110010 00110011 00110100 00110101 00110110 00110111 00111000
Шаг 1 Начальная перестановка
Входная последовательность
1111100011101000111101001111000011101110111000101110101011100000 - согласно таблице начальной перестановки перестанавливаем биты в сообщении.
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 |
Полученная последовательность 1111111100001101000101000000000011111111111111110101001101110000
Шаг 2 Получение последовательности L(0) и R(0)
Делим полученную последовательность согласно таблицам.
Последовательности получаются путём деления блока в 64 бита на 2 равных части.
L(0) перестановка
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
L(0) последовательность полученная 11111111000011010001010000000000
R(0) перестановка
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
R(0) последовательность полученная 11111111111111110101001101110000
Шаг 3 Функция выбора и перестановки последовательности В (преобразование ключа шифрования)
Входная последовательность
0011000100110010001100110011010000110101001101100011011100111000
57 |
49 |
41 |
33 |
25 |
17 |
9 |
1 |
58 |
50 |
42 |
34 |
26 |
18 |
10 |
2 |
59 |
51 |
43 |
35 |
27 |
19 |
11 |
3 |
60 |
52 |
44 |
36 |
63 |
55 |
47 |
39 |
31 |
23 |
15 |
7 |
62 |
54 |
46 |
38 |
30 |
22 |
14 |
6 |
61 |
53 |
45 |
37 |
29 |
21 |
13 |
5 |
28 |
20 |
12 |
4 |
Полученная последовательность 00000000000000001111111111110110011001111000100000001111
Шаг 4 Получение последовательностей C(0) D(0)
Полученную последовательность(ключа) делим на две согласно таблицам.
C(0)
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
Последовательность C(0) = 0000000000000000111111111111
D(0)
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
Последовательность D(0) = 0110011001111000100000001111
Шаг 5 получение последовательности C(i)
По таблице сдвигаем биты в последовательностях
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
1 |
1 |
2 |
2 |
2 |
2 |
2 |
2 |
1 |
2 |
2 |
2 |
2 |
2 |
2 |
1 |
C(0) = 0000000000000000111111111111
C(1) |
0000000000000001111111111110 |
C(2) |
0000000000000011111111111100 |
C(3) |
0000000000001111111111110000 |
C(4) |
0000000000111111111111000000 |
C(5) |
0000000011111111111100000000 |
C(6) |
0000001111111111110000000000 |
C(7) |
0000111111111111000000000000 |
C(8) |
0011111111111100000000000000 |
C(9) |
0111111111111000000000000000 |
C(10) |
1111111111100000000000000001 |
C(11) |
1111111110000000000000000111 |
C(12) |
1111111000000000000000011111 |
C(13) |
1111100000000000000001111111 |
C(14) |
1110000000000000000111111111 |
C(15) |
1000000000000000011111111111 |
C(16) |
0000000000000000111111111111 |
Шаг 6 получение последовательности D(i)
По той же таблице сдвигаем биты в последовательностях
D(0) = 0110011001111000100000001111
D(1) |
1100110011110001000000011110 |
D(2) |
1001100111100010000000111101 |
D(3) |
0110011110001000000011110110 |
D(4) |
1001111000100000001111011001 |
D(5) |
0111100010000000111101100110 |
D(6) |
1110001000000011110110011001 |
D(7) |
1000100000001111011001100111 |
D(8) |
0010000000111101100110011110 |
D(9) |
0100000001111011001100111100 |
D(10) |
0000000111101100110011110001 |
D(11) |
0000011110110011001111000100 |
D(12) |
0001111011001100111100010000 |
D(13) |
0111101100110011110001000000 |
D(14) |
1110110011001111000100000001 |
D(15) |
1011001100111100010000000111 |
D(16) |
0110011001111000100000001111 |
Шаг 7 получение последовательностей K(i)
14 |
17 |
11 |
24 |
1 |
5 |
3 |
28 |
15 |
6 |
21 |
10 |
23 |
19 |
12 |
4 |
26 |
8 |
16 |
7 |
27 |
20 |
13 |
2 |
41 |
52 |
31 |
37 |
47 |
55 |
30 |
40 |
51 |
45 |
33 |
48 |
44 |
49 |
39 |
56 |
34 |
53 |
46 |
42 |
50 |
36 |
29 |
32 |
Для получения последовательности K(i) произведём конкатенацию последовательностей C(i) и D(i). В полученной последовательности C(i)D(i) переставим биты согласно таблице.
K(0) = 010100010010110010001100101001110100001111000000
K(1) |
010100000010110010101100010101110010101011000010 |
K(2) |
010100001010110010100100010100001010001101000111 |
K(3) |
110100001010110000100110111101101000010010001100 |
K(4) |
111000001010011000100110010010000011011111001011 |
K(5) |
111000001001011000100110001111101111000000101001 |
K(6) |
111000001001001001110010011000100101110101100010 |
K(7) |
101001001101001001110010100011001010100100111010 |
K(8) |
101001100101001101010010111001010101111001010000 |
K(9) |
001001100101001101010011110010111001101001000000 |
K(10) |
001011110101000101010001110100001100011100111100 |
K(11) |
000011110100000111011001000110010001111010001100 |
K(12) |
000111110100000110011001110110000111000010110001 |
K(13) |
000111110000100110001001001000110110101000101101 |
K(14) |
000110110010100010001101101100100011100110010010 |
K(15) |
000110010010110010001100101001010000001100110111 |
K(16) |
010100010010110010001100101001110100001111000000 |
Шаг 8 функция Е(шифрование, перестановка с расширением)
По таблице преобразовать последовательности R(i)
32 |
1 |
2 |
3 |
4 |
5 |
4 |
5 |
6 |
7 |
8 |
9 |
8 |
9 |
10 |
11 |
12 |
13 |
12 |
13 |
14 |
15 |
16 |
17 |
13 |
17 |
18 |
19 |
20 |
21 |
20 |
21 |
22 |
23 |
24 |
25 |
24 |
25 |
26 |
27 |
28 |
29 |
28 |
29 |
30 |
31 |
32 |
1 |
R(0) = 11111111111111110101001101110000
E(R(0)) = 011111111111111111111110101010100110101110100001
Объединение R(i)K(i+1) XOR
R(0)K(1) xor = 001011111101001101010010111111010100000101100011
Подстановка через S блоки(вход 6 бит выход 4 бита)
S(1) = 2 = 0010 S(2) = 14 = 1110 S(3) = 9 = 1001 S(4) = 2 = 0010
S(5) = 3 = 0011 S(6) = 3 = 0011 S(7) = 11 = 1011 S(8) = 1 = 0001
Выходная (S1..S8) = 00101110100100100011001110110001
Прямая перестановка с помощью P блоков
16 |
7 |
20 |
21 |
29 |
12 |
28 |
17 |
1 |
15 |
23 |
26 |
5 |
18 |
31 |
10 |
2 |
8 |
24 |
14 |
32 |
27 |
3 |
9 |
19 |
13 |
30 |
6 |
22 |
11 |
4 |
25 |
Результат = 01100110011010000010111110010001
L(i)R(i+1) XOR
L(0) = 11111111000011010001010000000000
R(0) = 01100110011010000010111110010001
XOR R(1)=10011001011001010011101110010001
L(1) = R(0)
В итоге этих действий появляется новая правая половина, а старая правая половина становится новой левой. Эти действия повторяются 16 раз, образуя 16 этапов DES.
L(1) = 11111111111111110101001101110000
R(1) = 10011001011001010011101110010001
E(R1) = 110011110010101100001010100111110111110010100011
R(1) XOR K(2) = 100111111000011110101110110011111101111111100100
S(1..8) = 00101001100011011111100011000100
P = 10110001000111000101001111100001
R(1) XOR L(1) = 01001110111000110000000010010001 = R(2)
L(2) = R(1) = 10011001011001010011101110010001
E(R2) = 101001011101011100000110100000000001010010100010
R(2) XOR K(3) = 011101010111101100100000011101101001000000101110
S(1..8) = 00111010001110101000100101000010
P = 01010101010110100010001001000110
R(2) XOR L(2) = 11001100001111110001100111010111 = R(3)
L(3) = R(2) = 01001110111000110000000010010001
E(R3) = 111001011000000111111110100011110011111010101111
R(3) XOR K(4) = 000001010010011111011000110001110000100101100100
S(1..8) = 00000111000110110110011111010100
P = 11000110011101000110000011111001
R(3) XOR L(3) = 10001000100101110110000001101000 = R(4)
L(4) = R(3) = 11001100001111110001100111010111
E(R4) = 010001010001010010101110101100000000001101010001
R(4) XOR K(5) = 101001011000001010001000100011101111001101111000
S(1..8) = 01001100001100001000101000011100
P = 00011111001010001000000000110100
R(4) XOR L(4) = 11010011000101111001100111100011 = R(5)
L(5) = R(4) = 10001000100101110110000001101000
E(R5) = 111010100110100010101111110011110011111100000111
R(5) XOR K(6) = 000010101111101011011101101011010110001001100101
S(1..8) = 01000010100111101110010001001110
P = 01001101010101101001000111101000
R(5) XOR L(5) = 11000101110000011111000110000000 = R(6)
L(6) = R(5) = 11010011000101111001100111100011
E(R6) = 011000001011111000000011111110100011110000000001
R(6) XOR K(7) = 110001000110110001110001011101101001010100111011
S(1..8) = 01011110010010011000100110010101
P = 11010011000010011010100001110011
R(6) XOR L(6) = 00000000000111100011000110010000 = R(7)
L(7) = R(6) = 11000101110000011111000110000000
E(R7) = 000000000000000011111100000110100011110010100000
R(7) XOR K(8) = 101001100101001110101110111111110110001011110000
S(1..8) = 01001010010111110011101010010000
P = 11110110011010011001000011000001
R(7) XOR L(7) = 00110011101010000110000101000001 = R(8)
L(8) = R(7) = 00000000000111100011000110010000
E(R8) = 100110100111110101010000001100000010101000000010
R(8) XOR K(9) = 101111000010111000000011111110111011000001000010
S(1..8) = 01110001010110001110000010110010
P = 00000111000001111100011011000011
R(8) XOR L(8) = 00000111000110011111011101010011 = R(9)
L(9) = R(8) = 00110011101010000110000101000001
E(R9) = 100000001110100011110011111110101110101010100110
R(9) XOR K(10) = 101011111011100110100010001010100010110110011010
S(1..8) = 10010101100101101010111010000000
P = 00010101111000000101000110011011
R(9) XOR L(9) = 00100110010010000011000011011010 = R(10)
L(10) = R(9) = 00000111000110011111011101010011
E(R10) = 000100001100001001010000000110100001011011110100
R(10) XOR K(11) = 000111111000001110001001000000110000100001111000
S(1..8) = 01001001010101100010011101101111
P = 00001100011110111111110010101000
R(10) XOR L(10) = 00001011011000100000101111111011 = R(11)
L(11) = R(10) = 00100110010010000011000011011010
E(R11) = 100001010110101100000100000001010111111111110110
R(11) XOR K(12) = 100110100010101010011101110111010000111101000111
S(1..8) = 10001110111111101001000000111000
P = 01101111110010010001010101010100
R(11) XOR L(11) = 01001001100000010010010110001110 = R(12)
L(12) = R(11) = 00001011011000100000101111111011
E(R12) = 001001010011110000000010100100001011110001011100
R(12) XOR K(13) = 001110100011010110001011101100111101011001110001
S(1..8) = 10001000011111110111100000101111
P = 10111100110011110001110011100100
R(12) XOR L(12) = 10110111101011010001011100011111 = R(13)
L(13) = R(12) = 01001001100000010010010110001110
E(R13) = 110110101111110101011010100010101110100011111111
R(13) XOR K(14) = 110000011101010111010111001110001101000101101101
S(1..8) = 11111011111011000110100110111000
P = 01011010100011011111011111000111
R(13) XOR L(13) = 00010011000011001101001001001001 = R(14)
L(14) = R(13) = 10110111101011010001011100011111
E(R14) = 100010100110100001011001011010100100001001010010
R(14) XOR K(15) = 100100110100010011010101110011110100000101100101
S(1..8) = 11101100100000101111010010111110
P = 00101011110011101000011110111001
R(14) XOR L(14) = 10011100011000111001000010100110 = R(15)
L(15) = R(14) = 00010011000011001101001001001001
E(R15) = 010011111000001100000111110010100001010100001101
R(15) XOR K(16) = 000111101010111110001011011011010101011011001101
S(1..8) = 01000100011111111001110111110111
P = 10110111010100111011110001111101
R(15) XOR L(15) = 10100100010111110110111000110100 = R(16)
L(16) = R(15) = 10011100011000111001000010100110
Шаг 9 заключительная перестановка(обратная)
40 |
8 |
48 |
16 |
56 |
24 |
64 |
32 |
39 |
7 |
47 |
15 |
55 |
23 |
63 |
31 |
38 |
6 |
46 |
14 |
54 |
22 |
62 |
30 |
37 |
5 |
45 |
13 |
53 |
21 |
61 |
29 |
36 |
4 |
44 |
12 |
52 |
20 |
60 |
28 |
35 |
3 |
43 |
11 |
51 |
19 |
59 |
27 |
34 |
2 |
42 |
10 |
50 |
18 |
58 |
26 |
33 |
1 |
41 |
9 |
49 |
17 |
57 |
25 |
Вход (L16R16) = 1001110001100011100100001010011010100100010111110110111000110100
Полученная = 00110000 00111001 11101011 01101000 01100110 10011011 00111000 11000101 =
48 57 235 104 102 155 56 197 = 0 9 л h f > 8 Е
Программа
Шифрование
Расшифровка
Текст программы
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Memo2: TMemo;
Label1: TLabel;
Label2: TLabel;
Button1: TButton;
Button2: TButton;
Memo3: TMemo;
Label3: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
c, d, k: array [0..16] of AnsiString;
r, l, rez, z: AnsiString;
w, desK, desR: byte;
implementation
{$R *.dfm}
procedure DecToBin(input: string; var output: ansistring);
var
a, b: double;
ost, q, w: byte;
st: AnsiString;
str: string[8];
begin
str:= ' ';
for w:= 1 to 8 do
begin
q:= Ord(input[w]);
b:= q;
While b <> 1 do
begin
a:= q / 2;
b:= Int(a);
if a = b then
ost:= 0
else ost:= 1;
q:= Round(b);
st:= st + IntToStr(ost);
if b = 1 then st:= st + '1';
end;
ost:= 1;
for q:= Length(st) downto 1 do // ïåðåâîðîò ñòðîêè
begin
str[ost]:= st[q];
Inc(ost);
end;
case Length(st) of
1: Insert('0000000', str, 1); // äîáàâëåíèå íåäîñòàþùèõ íîëåé
2: Insert('000000', str, 1);
3: Insert('00000', str, 1);
4: Insert('0000', str, 1);
5: Insert('000', str, 1);
6: Insert('00', str, 1);
7: Insert('0', str, 1);
end;
output:= output + str;// + ' ';
str:= ' ';
st:= '';
end;
end;
procedure BeginPerestanovka(input: ansistring; var output: ansistring);
begin
output:=
input[58] + input[50] + input[42] + input[34] + input[26] + input[18]
+ input[10] + input[2]
+ input[60] + input[52] + input[44] + input[36] + input[28] + input[20]
+ input[12] + input[4]
+ input[62] + input[54] + input[46] + input[38] + input[30] + input[22]
+ input[14] + input[6]
+ input[64] + input[56] + input[48] + input[40] + input[32] + input[24]
+ input[16] + input[8]
+ input[57] + input[49] + input[41] + input[33] + input[25] + input[17]
+ input[9] + input[1]
+ input[59] + input[51] + input[43] + input[35] + input[27] + input[19]
+ input[11] + input[3]
+ input[61] + input[53] + input[45] + input[37] + input[29] + input[21]
+ input[13] + input[5]
+ input[63] + input[55] + input[47] + input[39] + input[31] + input[23]
+ input[15] + input[7];
end;
procedure PerestanovkaKeyB(input: AnsiString; var output: AnsiString);
begin
output:= '';
output:=
input[57]+input[49]+input[41]+input[33]+input[25]+input[17]+input[9]
+input[1]+input[58]+input[50]+input[42]+input[34]+input[26]+input[18]
+input[10]+input[2]+input[59]+input[51]+input[43]+input[35]+input[27]
+input[19]+input[11]+input[3]+input[60]+input[52]+input[44]+input[36]
+input[63]+input[55]+input[47]+input[39]+input[31]+input[23]+input[15]
+input[7]+input[62]+input[54]+input[46]+input[38]+input[30]+input[22]
+input[14]+input[6]+input[61]+input[53]+input[45]+input[37]+input[29]
+input[21]+input[13]+input[5]+input[28]+input[20]+input[12]+input[4];
end;
procedure pocledovatelnostiK;
var
w: byte;
bufer: AnsiString;
begin
for w:= 0 to 16 do
begin
bufer:= Concat(c[w], d[w]);
k[w]:=
Concat(bufer[14], bufer[17], bufer[11], bufer[24], bufer[1], bufer[5],
bufer[3], bufer[28], bufer[15], bufer[6], bufer[21], bufer[10],
bufer[23], bufer[19], bufer[12], bufer[4], bufer[26], bufer[8],
bufer[16], bufer[7], bufer[27], bufer[20], bufer[13], bufer[2],
bufer[41], bufer[52], bufer[31], bufer[37], bufer[47], bufer[55],
bufer[30], bufer[40], bufer[51], bufer[45], bufer[33], bufer[48],
bufer[44], bufer[49], bufer[39], bufer[56], bufer[34], bufer[53],
bufer[46], bufer[42], bufer[50], bufer[36], bufer[29], bufer[32]);
end;
end;
procedure FuncE;
const
s1 : array[0..3, 0..15] of string[4] =
(('1110','0100','1101','0001','0010','1111','1011','1000','0011','1010','0110','1100','0101','1001','0000','0111'),
('0000','1111','0111','0100','1110','0010','1101','0001','1010','0110','1100','1011','1001','0101','0011','1000'),
('0100','0001','1110','1000','1001','0110','0010','1011','1111','1100','1001','0111','0011','1010','0101','0000'),
('1111','1100','1000','0010','0100','1001','0001','0111','0101','1011','0011','1110','1010','0000','1001','1101'));
s2 : array[0..3, 0..15] of string[4] =
(('1111','0001','1000','1110','0110','1011','0011','0100','1001','0111','0010','1101','1100','0000','0101','1010'),
('0011','1101','0100','0111','1111','0010','1000','1110','1100','0000','0001','1010','0110','1001','1011','0101'),
('0000','1110','0111','1011','1010','0100','1101','0001','0101','1000','1100','0110','1001','0011','0010','1111'),
('1101','1000','1010','0001','0011','1111','0100','0010','1011','0110','0111','1100','0000','0101','1110','1001'));
s3 : array [0..3, 0..15] of string[4] =
(('1010','0000','1001','1110','0110','0011','1111','0101','0001','1101','1100','0111','1011','0100','0010','1000'),
('1101','0111','0000','1001','0011','0100','0110','1010','0010','1000','0101','1110','1100','1011','1111','0001'),
('1101','0110','0100','1001','1000','1111','0011','0000','1011','0001','0010','1100','0101','1010','1110','0111'),
('0001','1010','1101','0000','0110','1001','1000','0111','0100','1111','1110','0011','1011','0101','0010','1100'));
s4 : array [0..3, 0..15] of string[4] =
(('0111','1101','1110','0011','0000','0110','1001','1010','0001','0010','1000','0101','1011','1100','0100','1111'),
('1101','1000','1011','0101','0110','1111','0000','0011','0100','0111','0010','1100','0001','1010','1110','1001'),
('1010','0110','1001','0000','1100','1011','0111','1101','1111','0001','0011','1110','0101','0010','1000','0100'),
('0011','1111','0000','0110','1010','0001','1101','1000','1001','0100','0101','1011','1100','0111','0010','1110'));
s5 : array [0..3, 0..15] of string[4] =
(('0010','1100','0100','0001','0111','1010','1011','0110','1000','0101','0011','1111','1101','0000','1110','1001'),
('1110','1011','0010','1100','0100','0111','1101','0001','0101','0000','1111','1010','0011','1001','1000','0110'),
('0100','0010','0001','1011','1010','1101','0111','1000','1111','1001','1100','0101','0110','0011','0000','1110'),
('1011','1000','1100','0111','0001','1110','0010','1101','0110','1111','0000','1001','1010','0100','0101','0011'));
s6 : array [0..3, 0..15] of string[4] =
(('1100','0001','1010','1111','1001','0010','0110','1000','0000','1101','0011','0100','1110','0111','0101','1011'),
('1010','1111','0100','0010','0111','1100','1001','0101','0110','0001','1101','1110','0000','1011','0011','1000'),
('1001','1110','1111','0101','0010','1000','1100','0011','0111','0000','0100','1010','0001','1101','1011','0110'),
('0100','0011','0010','1100','1001','0101','1111','1010','1011','1110','0001','0111','0110','0000','1000','1101'));
s7 : array [0..3, 0..15] of string[4] =
(('0100','1011','0010','1110','1111','0000','1000','1101','0011','1100','1001','0111','0101','1010','0110','0001'),
('1101','0000','1011','0111','0100','1001','0001','1010','1110','0011','0101','1100','0011','1111','1000','0110'),
('0001','0100','1011','1101','1100','0011','0111','1110','1010','1111','0110','1000','0000','0101','1001','0010'),
('0110','1011','1101','1000','0001','0100','1010','0111','1001','0101','0000','1111','1110','0010','0011','1100'));
s8 : array [0..3, 0..15] of string[4] =
(('1101','0010','1000','0100','0110','1111','1011','0001','1010','1001','0011','1110','0101','0000','1100','0111'),
('0001','1111','1101','1000','1010','0011','0111','0100','1100','0101','0110','1011','0000','1110','1001','0011'),
('0111','1011','0100','0001','1001','1100','1110','0010','0000','0110','1010','1101','1111','0011','0101','1000'),
('0010','0001','1110','0111','0100','1010','1000','1101','1111','1100','1001','0000','0011','0101','0110','1011'));
var
_1, _2: AnsiString;
p: string[6];
v, b, x, a, j: byte;
u: string[2];
o: string[4];
function s(var a, b: byte): byte;
begin
if u = '00' then a:= 0
else if u = '01' then a:= 1
else if u = '10' then a:= 2
else if u = '11' then a:= 3;
if o = '0000' then b:= 0
else if o = '0001' then b:= 1
else if o = '0010' then b:= 2
else if o = '0011' then b:= 3
else if o = '0100' then b:= 4
else if o = '0101' then b:= 5
else if o = '0110' then b:= 6
else if o = '0111' then b:= 7
else if o = '1000' then b:= 8
else if o = '1001' then b:= 9
else if o = '1010' then b:= 10
else if o = '1011' then b:= 11
else if o = '1100' then b:= 12
else if o = '1101' then b:= 13
else if o = '1110' then b:= 14
else if o = '1111' then b:= 15;
end;
begin
for a:= 1 to 16 do
begin
z:= Concat(r[32],r[1],r[2],r[3],r[4],r[5],r[4],r[5],r[6],r[7],r[8],r[9],
r[8],r[9],r[10],r[11],r[12],r[13],r[12],r[13],r[14],r[15],r[16],r[17],
r[16],r[17],r[18],r[19],r[20],r[21],r[20],r[21],r[21],r[23],r[24],r[25],
r[24],r[25],r[26],r[27],r[28],r[29],r[28],r[29],r[30],r[31],r[32],r[1]);
_1:= k[a];
r:= z;
for j:= 1 to 48 do // xor
begin
v:= StrToInt(r[j]);
b:= StrToInt(_1[j]);
x:= v xor b;
_2:= Concat(_2, IntToStr(x));
end;
p:= Copy(_2, 1, 6); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s1[v, b];
p:= Copy(_2, 7, 12); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s2[v, b];
p:= Copy(_2, 13, 18); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s3[v, b];
p:= Copy(_2, 19, 24); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s4[v, b];
p:= Copy(_2, 25, 30); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s5[v, b];
p:= Copy(_2, 31, 36); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s6[v, b];
p:= Copy(_2, 37, 42); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s7[v, b];
p:= Copy(_2, 43, 48); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s8[v, b];
// Ð ïåðåñòàíîâêà
_2:= rez;
rez:= Concat(_2[16], _2[7], _2[20], _2[21], _2[29], _2[12], _2[28], _2[17],
_2[1], _2[15], _2[23], _2[26], _2[5], _2[18], _2[31], _2[10],
_2[2], _2[8], _2[24], _2[14], _2[32], _2[27], _2[3], _2[9],
_2[19], _2[13], _2[30], _2[6], _2[22], _2[11], _2[4], _2[25]);
for w:= 1 to 32 do
begin
v:= StrToInt(r[w]);
b:= StrToInt(l[w]);
x:= v xor b;
_2:= Concat(_2, IntToStr(x));
end;
l:= r;
r:= _2;
end;
_2:= Concat(l, r);
rez:= Concat(
_2[40], _2[8], _2[48], _2[16], _2[56], _2[24], _2[64], _2[32],
_2[39], _2[7], _2[47], _2[15], _2[55], _2[23], _2[63], _2[31],
_2[38], _2[6], _2[46], _2[14], _2[54], _2[22], _2[62], _2[30],
_2[37], _2[5], _2[45], _2[13], _2[53], _2[21], _2[61], _2[29],
_2[36], _2[4], _2[44], _2[12], _2[52], _2[20], _2[60], _2[28],
_2[35], _2[3], _2[43], _2[11], _2[51], _2[19], _2[59], _2[27],
_2[34], _2[2], _2[42], _2[10], _2[50], _2[18], _2[58], _2[26],
_2[33], _2[1], _2[41], _2[9], _2[49], _2[17], _2[57], _2[25]);
end;
procedure FuncER;
const
s1 : array[0..3, 0..15] of string[4] =
(('1110','0100','1101','0001','0010','1111','1011','1000','0011','1010','0110','1100','0101','1001','0000','0111'),
('0000','1111','0111','0100','1110','0010','1101','0001','1010','0110','1100','1011','1001','0101','0011','1000'),
('0100','0001','1110','1000','1001','0110','0010','1011','1111','1100','1001','0111','0011','1010','0101','0000'),
('1111','1100','1000','0010','0100','1001','0001','0111','0101','1011','0011','1110','1010','0000','1001','1101'));
s2 : array[0..3, 0..15] of string[4] =
(('1111','0001','1000','1110','0110','1011','0011','0100','1001','0111','0010','1101','1100','0000','0101','1010'),
('0011','1101','0100','0111','1111','0010','1000','1110','1100','0000','0001','1010','0110','1001','1011','0101'),
('0000','1110','0111','1011','1010','0100','1101','0001','0101','1000','1100','0110','1001','0011','0010','1111'),
('1101','1000','1010','0001','0011','1111','0100','0010','1011','0110','0111','1100','0000','0101','1110','1001'));
s3 : array [0..3, 0..15] of string[4] =
(('1010','0000','1001','1110','0110','0011','1111','0101','0001','1101','1100','0111','1011','0100','0010','1000'),
('1101','0111','0000','1001','0011','0100','0110','1010','0010','1000','0101','1110','1100','1011','1111','0001'),
('1101','0110','0100','1001','1000','1111','0011','0000','1011','0001','0010','1100','0101','1010','1110','0111'),
('0001','1010','1101','0000','0110','1001','1000','0111','0100','1111','1110','0011','1011','0101','0010','1100'));
s4 : array [0..3, 0..15] of string[4] =
(('0111','1101','1110','0011','0000','0110','1001','1010','0001','0010','1000','0101','1011','1100','0100','1111'),
('1101','1000','1011','0101','0110','1111','0000','0011','0100','0111','0010','1100','0001','1010','1110','1001'),
('1010','0110','1001','0000','1100','1011','0111','1101','1111','0001','0011','1110','0101','0010','1000','0100'),
('0011','1111','0000','0110','1010','0001','1101','1000','1001','0100','0101','1011','1100','0111','0010','1110'));
s5 : array [0..3, 0..15] of string[4] =
(('0010','1100','0100','0001','0111','1010','1011','0110','1000','0101','0011','1111','1101','0000','1110','1001'),
('1110','1011','0010','1100','0100','0111','1101','0001','0101','0000','1111','1010','0011','1001','1000','0110'),
('0100','0010','0001','1011','1010','1101','0111','1000','1111','1001','1100','0101','0110','0011','0000','1110'),
('1011','1000','1100','0111','0001','1110','0010','1101','0110','1111','0000','1001','1010','0100','0101','0011'));
s6 : array [0..3, 0..15] of string[4] =
(('1100','0001','1010','1111','1001','0010','0110','1000','0000','1101','0011','0100','1110','0111','0101','1011'),
('1010','1111','0100','0010','0111','1100','1001','0101','0110','0001','1101','1110','0000','1011','0011','1000'),
('1001','1110','1111','0101','0010','1000','1100','0011','0111','0000','0100','1010','0001','1101','1011','0110'),
('0100','0011','0010','1100','1001','0101','1111','1010','1011','1110','0001','0111','0110','0000','1000','1101'));
s7 : array [0..3, 0..15] of string[4] =
(('0100','1011','0010','1110','1111','0000','1000','1101','0011','1100','1001','0111','0101','1010','0110','0001'),
('1101','0000','1011','0111','0100','1001','0001','1010','1110','0011','0101','1100','0011','1111','1000','0110'),
('0001','0100','1011','1101','1100','0011','0111','1110','1010','1111','0110','1000','0000','0101','1001','0010'),
('0110','1011','1101','1000','0001','0100','1010','0111','1001','0101','0000','1111','1110','0010','0011','1100'));
s8 : array [0..3, 0..15] of string[4] =
(('1101','0010','1000','0100','0110','1111','1011','0001','1010','1001','0011','1110','0101','0000','1100','0111'),
('0001','1111','1101','1000','1010','0011','0111','0100','1100','0101','0110','1011','0000','1110','1001','0011'),
('0111','1011','0100','0001','1001','1100','1110','0010','0000','0110','1010','1101','1111','0011','0101','1000'),
('0010','0001','1110','0111','0100','1010','1000','1101','1111','1100','1001','0000','0011','0101','0110','1011'));
var
_1, _2: AnsiString;
p: string[6];
v, b, x, a, j: byte;
u: string[2];
o: string[4];
function s(var a, b: byte): byte;
begin
if u = '00' then a:= 0
else if u = '01' then a:= 1
else if u = '10' then a:= 2
else if u = '11' then a:= 3;
if o = '0000' then b:= 0
else if o = '0001' then b:= 1
else if o = '0010' then b:= 2
else if o = '0011' then b:= 3
else if o = '0100' then b:= 4
else if o = '0101' then b:= 5
else if o = '0110' then b:= 6
else if o = '0111' then b:= 7
else if o = '1000' then b:= 8
else if o = '1001' then b:= 9
else if o = '1010' then b:= 10
else if o = '1011' then b:= 11
else if o = '1100' then b:= 12
else if o = '1101' then b:= 13
else if o = '1110' then b:= 14
else if o = '1111' then b:= 15;
end;
begin
for a:= 16 downto 1 do
begin
z:= Concat(r[32],r[1],r[2],r[3],r[4],r[5],r[4],r[5],r[6],r[7],r[8],r[9],
r[8],r[9],r[10],r[11],r[12],r[13],r[12],r[13],r[14],r[15],r[16],r[17],
r[16],r[17],r[18],r[19],r[20],r[21],r[20],r[21],r[21],r[23],r[24],r[25],
r[24],r[25],r[26],r[27],r[28],r[29],r[28],r[29],r[30],r[31],r[32],r[1]);
_1:= k[a];
r:= z;
for j:= 1 to 48 do // xor
begin
v:= StrToInt(r[j]);
b:= StrToInt(_1[j]);
x:= v xor b;
_2:= Concat(_2, IntToStr(x));
end;
p:= Copy(_2, 1, 6); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s1[v, b];
p:= Copy(_2, 7, 12); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s2[v, b];
p:= Copy(_2, 13, 18); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s3[v, b];
p:= Copy(_2, 19, 24); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s4[v, b];
p:= Copy(_2, 25, 30); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s5[v, b];
p:= Copy(_2, 31, 36); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s6[v, b];
p:= Copy(_2, 37, 42); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s7[v, b];
p:= Copy(_2, 43, 48); u:= p[1] + p[6]; o:= Copy(p, 2, 5); s(v, b);
rez:= rez + s8[v, b];
// Ð ïåðåñòàíîâêà
_2:= rez;
rez:= Concat(_2[16], _2[7], _2[20], _2[21], _2[29], _2[12], _2[28], _2[17],
_2[1], _2[15], _2[23], _2[26], _2[5], _2[18], _2[31], _2[10],
_2[2], _2[8], _2[24], _2[14], _2[32], _2[27], _2[3], _2[9],
_2[19], _2[13], _2[30], _2[6], _2[22], _2[11], _2[4], _2[25]);
for w:= 1 to 32 do
begin
v:= StrToInt(r[w]);
b:= StrToInt(l[w]);
x:= v xor b;
_2:= Concat(_2, IntToStr(x));
end;
l:= r;
r:= _2;
end;
_2:= Concat(l, r);
rez:= Concat(
_2[40], _2[8], _2[48], _2[16], _2[56], _2[24], _2[64], _2[32],
_2[39], _2[7], _2[47], _2[15], _2[55], _2[23], _2[63], _2[31],
_2[38], _2[6], _2[46], _2[14], _2[54], _2[22], _2[62], _2[30],
_2[37], _2[5], _2[45], _2[13], _2[53], _2[21], _2[61], _2[29],
_2[36], _2[4], _2[44], _2[12], _2[52], _2[20], _2[60], _2[28],
_2[35], _2[3], _2[43], _2[11], _2[51], _2[19], _2[59], _2[27],
_2[34], _2[2], _2[42], _2[10], _2[50], _2[18], _2[58], _2[26],
_2[33], _2[1], _2[41], _2[9], _2[49], _2[17], _2[57], _2[25]);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
output, put, key, c0, d0, k0: AnsiString;
e1: string[1];
e2: string[2];
begin
DecToBin(Form1.Memo1.Text, output);
BeginPerestanovka(output, put);
l:= Copy(put, 1, 32);
r:= Copy(put, 33, 64);
DecToBin(Form1.Memo3.Text, key);
PerestanovkaKeyB(key, key);
c0:= Copy(key, 1, 28);
d0:= Copy(key, 29, 56);
c[0]:= c0;
d[0]:= d0;
for w:= 1 to 2 do
begin
e1:= c[w-1];
c[w]:= Copy(c[w-1], 2, 28) + e1;
e1:= d[w-1];
d[w]:= Copy(d[w-1], 2, 28) + e1;
end;
for w:= 3 to 8 do
begin
e2:= c[w-1];
c[w]:= Copy(c[w-1], 3, 28) + e2;
e2:= d[w-1];
d[w]:= Copy(d[w-1], 3, 28) + e2;
end;
e1:= c[8];
c[9]:= Copy(c[8], 2, 28) + e1;
e1:= d[8];
d[w]:= Copy(d[8], 2, 28) + e1;
for w:= 10 to 15 do
begin
e2:= c[w-1];
c[w]:= Copy(c[w-1], 3, 28) + e2;
e2:= d[w-1];
d[w]:= Copy(d[w-1], 3, 28) + e2;
end;
e1:= c[15];
c[16]:= Copy(c[15], 2, 28) + e1;
e1:= d[15];
d[16]:= Copy(d[15], 2, 28) + e1;
pocledovatelnostiK;
FuncE;
Form1.Memo2.Text:= rez;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
output, put, key, c0, d0, k0: AnsiString;
e1: string[1];
e2: string[2];
begin
DecToBin(Form1.Memo2.Text, output);
BeginPerestanovka(output, put);
l:= Copy(put, 1, 32);
r:= Copy(put, 33, 64);
DecToBin(Form1.Memo3.Text, key);
PerestanovkaKeyB(key, key);
c0:= Copy(key, 1, 28);
d0:= Copy(key, 29, 56);
c[0]:= c0;
d[0]:= d0;
for w:= 1 to 2 do
begin
e1:= c[w-1];
c[w]:= Copy(c[w-1], 2, 28) + e1;
e1:= d[w-1];
d[w]:= Copy(d[w-1], 2, 28) + e1;
end;
for w:= 3 to 8 do
begin
e2:= c[w-1];
c[w]:= Copy(c[w-1], 3, 28) + e2;
e2:= d[w-1];
d[w]:= Copy(d[w-1], 3, 28) + e2;
end;
e1:= c[8];
c[9]:= Copy(c[8], 2, 28) + e1;
e1:= d[8];
d[w]:= Copy(d[8], 2, 28) + e1;
for w:= 10 to 15 do
begin
e2:= c[w-1];
c[w]:= Copy(c[w-1], 3, 28) + e2;
e2:= d[w-1];
d[w]:= Copy(d[w-1], 3, 28) + e2;
end;
e1:= c[15];
c[16]:= Copy(c[15], 2, 28) + e1;
e1:= d[15];
d[16]:= Copy(d[15], 2, 28) + e1;
pocledovatelnostiK;
FuncER;
Form1.Memo1.Text:= rez;
end;
end.