Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Практическая криптография алгоритмы и их программирование
.pdf
Глава 4. Как устроены современные шифры 81
возможно представить в виде суммы произведений некоторых постоянных коэф-
.
, x1, ..., xn:
0
фициентов со слагаемыми аргументами ни для какого из наборов x
( , , ,..., ) ...
Fx x x x a x ax a x
012 00 11
=+++
nnn
Почему это плохо? Простое линейное преобразование, которое возможно
дало бы нужный результат, не может быть использовано по той причине, что в
этом случае криптоаналитик просто вычислит его с помощью статистического
оценивания, используя, например, метод нахождения линейной регрессии, и найдет формулы всех использованных линейных преобразований данных.
16
Если все же используем такую функцию F, которая обладает указанным
свойством, то есть является линейной, мы можем представить себе следующую
ситуацию. Имея пары {участок открытого текста} и {соответствующий ему закрытый текст}, криптоаналитик сможет составить алгебраическую систему вида (*) и
решить ее, найдя все необходимые ему компоненты для вскрытия шифра каким-нибудь не очень сложным и не очень медленным методом решения систем линейных алгебраических уравнений, которые в вузах изучают студенты начальных
курсов.
1
i
В (*) функции
представляют собой i-е по счету линейное преобразование,
f
k
зависящее от ключа k,àP
fP C
fP C
(*)
...,
fP C
è Cnпредставляют собой участки (биты, байты или би-
n
=
() ,
k
11
2
=
() ,
22
k
=
() .
knnn
товые строки) соответственно открытого и шифротекста. На многие современные
блочные шифры были реализованы подобные атаки. Дополнительный анализ иногда приводит еще и к тому, что удается найти функции зависимости не только для
конкретных пар открытого и шифротекста, но и для устройства непосредственно
шифра, что вдобавок позволяет все найденные функции отделить друг от друга.
То есть создать модель шифра, в которой четко прослеживались последствия изменения бита исходного текста всего на двух-трех битах выхода.
Шифр Люцифер строился под руководством Файстеля в конце 60-х годов с
учетом подобных возможностей и сообразительности криптоаналитика. Позже
эти работы стали финансироваться Национальным институтом стандартов и технологий США (National Institute of Standards and Technology), поскольку их результатом должно было стать формирование нового национального стандарта шифрования, позволившего бы шифровать данные для создания защищенных каналов
передачи данных.
16
Здесь нужно четко представлять себе тонкое различие между открытостью алгоритма в
соответствии правилами Керкхоффа и закрытостью алгоритма, измененного на время шифрова
ния с помощью ключа. Функция F, о которой идет речь в данном конкретном случае, уже изме
нена в зависимости от заданного пользователем ключа и скрыта от глаз криптоаналитика. Поэ
тому поиск формулы, преставляющей функцию F, то же самое, что и поиск ключа, только в ме
нее очевидном виде.
-
-
-
-

82 Глава 4. Как устроены современные шифры
Файстель в своей статье представил способ организации шифра по Шеннону.
Этот шифр обладал хорошими свойствами перемешивания и рассеивания. Для достижения вышеозначенного эффекта предлагалось использовать блоки подстановок и перестановок. Архитектура подобных шифров носит название SP-ñåòè,от
двух названий используемых в ней компонентов: S-box è P-box.
Данные представлялись в виде подблоков небольшого размера, например, в 3
или 4 бита. Затем использовалась заранее подготовленная таблица подстановки
(например, рис. 4.4), названная Файстелем S-Box (от substitution — в английском
языке обозначающего подстановку или замену) и окрещенная в русской терминологии S-блоком и узлом (иногда еще говорят, блоком) замены.
x1x2x3x
00001101
00011011
00100100
00110101
01000000
01011001
01101010
01110111
10000010
10010011
10100001
10110110
11001110
11011100
11101000
11111111
Ðèñ. 4.4. Пример таблицы замен для n = 4
4
S(x)
Подставляя значение входных данных в левую колонку таблицы, получаем
соответствующее значение подстановки в правой колонке. Как в левой, так и в
правой колонках все значения должны быть различны, иначе, заменив однажды
данные в соответствии с таблицей, мы не сможем однозначно их восстановить
позже.
В варианте для компьютерного исполнения небольшая таблица замен обычно
организуется как обычный массив (см. листинг 4.5).
Листинг 4.5
int S_Box[16] = {
13, 11, 4, 5, 0, 9, 10, 7, 2, 3, 1, 6, 14, 15, 12, 8
}

Глава 4. Как устроены современные шифры 83
for(inti=0;i<size_of_data; i++) {
int data_l, data_h;
data_l = (data[i] >> 4) & 0xF; // берем младший полубайт
// его размер как раз равен 4 битам
data_l = S_Box[data_l];
data_h = data[i] & 0xF; // берем старший полубайт
// и поступаем с ним та кже, как с младшим
data_h = S_Box[data_h];
data[i] = data_h || (data_l << 4); // возвращаем половинки назад
}
Читатель, ознакомившийся со второй главой книги, возможно, сразу предложит способ взлома шифра, использующего таблицу замен, — это простой частотный анализ. В роли букв латинского алфавита из классических примеров здесь
выступят всевозможные двоичные последовательности — комбинации из четырех битов. Чтобы сделать схему с таблицей замен стойкой к анализу, требуется
значительно увеличить размер обрабатываемых двоичных последовательностей,
чтобы во много раз усложнить частотный анализ. Для этого надо будет использовать например 128-битовую таблицу замен, а следовательно, хранить все 128 значений 128-битовых векторов. Для этого понадобится 16 kb памяти только для одной таблицы. Кроме того, возникает вопрос об использовании такой таблицы в качестве ключа — она все-таки слишком громоздка. Это означает, что необходимо
придумать способ расширить небольшой по размеру ключ до необходимого размера и модифицировать постоянную таблицу в соответствии с ним. В силу явных
трудностей с реализацией метода сотрудники Bell Laboratories обратили внимание еще и на таблицы перестановок (рис. 4.5).
Ðèñ. 4.5. Пример таблицы перестановок для n = 8

84 Глава 4. Как устроены современные шифры
Таблица перестановок была названа P-Box (от permutation — перемешивание) или узел (блок) перестановки по аналогии с узлом (блоком) замены. С ее помощью в блоке данных биты переставляются так, чтобы затруднить частотный
анализ. При этом даже для сравнительно небольших блоков мы получаем очень
большое пространство возможных ключей, равное по мощности N! Например, для
16-битового блока 16! = 20922789888000). Впечатляющее число, не правда ли?
Однако для блока перестановки легко придумать криптографическую атаку,
которая позволит быстро (всего за N−1 операций, если блок перестановки состоит из N элементов) раскрыть структуру его содержимого. Немного присмотревшись к рис. 4.5, читатель может увидеть, что для этого достаточно подать на вход
строки битов, содержащие одну единицу и остальные нули: то есть последовательность
(1, 0, 0, 0, ..., 0, 0),
(0, 1, 0, 0, ..., 0, 0),
(0, 0, 1, 0, ..., 0, 0),
(0, 0, 0, 1, ..., 0, 0)
èò.ä.
После этого единица на выходе будет соответствовать тому элементу, на место которого переставляется исходный единичный бит.
Если криптоаналитик получит доступ к шифровальной машине (или программе), то, просто подставив все векторы, легко получит формулу преобразования
данных и сможет раскрывать все тексты, зашифрованные с ее помощью.
Таким образом, у нас есть два различных способа преобразования данных,
каждый из которых уязвим к определенному виду криптоатак. При этом мы знаем, что с точки зрения формального подхода наиболее эффективным шифром из
всех возможных блочных шифров является тот, который может преобразовать
любой возможный блок открытого текста в любой возможный блок шифрованного текста. И естественно, это преобразование должно быть обратимым. Такой
шифр можно отнести к шифрам на основе простой подстановки, который в упрощенном варианте был описан S-блоком.
Теперь вернемся к реальности и проведем простой расчет. Если блок шифра
имеет длину n битов, то имеется 2
n
различных двоичных блоков и (2n)! способов, с
помощью которых можно зашифровать один блок текста. Количество битов ключа, необходимых для выбора одного из этих способов, огромно — оно равно
{2n)!}. Это неприемлемо большое число даже при небольших значениях n.Íà-
log
2
пример, при n, равным 8, нам потребуется хранить ключ длиной почти в 2000 битов. Плюс ко всему простые подстановки на малых алфавитах можно эффективно
раскрывать посредством составления частотных таблиц для знаков шифрованного текста. Мы оказываемся перед дилеммой — нам нужны блоки больших размеров, но мы не сможем эффективно их использовать из-за слишком большой длины
ключа.
Разрешить ее можно, пойдя по стопам сотрудников лаборатории IBM. Почти
все первые криптосистемы IBM базируются на работе Шеннона и его композиционных шифрах. Для построения сильной системы из слабых по отдельности ком
-

Глава 4. Как устроены современные шифры 85
понент используется произведение шифров, а точнее, их многократное последовательное применение над данными. Понятно, что последовательное применение,
например, двух блоков замены равносильно применению одного третьего блока
замены. Поэтому применение замен и перестановок необходимо чередовать между собой. Именно так и поступили в IBM.
Несмотря на незначительные различия в реализациях, почти во всех системах фирмы IBM в основном использовалась перестановка внутри блока для некоторого фиксированного перемешивающего преобразования и подстановка для
4-битовых подблоков (рис. 4.6). Кстати, название «узел замены» появилось именно отсюда, поскольку оно наглядно демонстрирует позицию блока замены в архитектуре шифра как некоторую узловую операцию, в которой своего рода узлом
сходятся линии, обозначающие поступление данных.
Файстелем была описана такая схема в качестве примера эффективной криптосистемы. В ней блок из 128 битов открытого текста разбивается на 32 4-битных
подблока, каждый из которых подвергается действию различных S-блоков, которые управляются частью заданного пользователем ключа. Затем полученные 128
битов перемешиваются с помощью фиксированной перестановки, и процесс повторяется. Перестановка перемешивает биты различных S-блоков и необходима
для того, чтобы предотвратить вырождение всего преобразования в подстановку
4-битовых блоков. Расшифрование происходит аналогично, за исключением того,
что в качестве S-блоков используются их обратные подстановки.
К сожалению, в данной схеме есть существенные недостатки. Дело в том, что
в данном случае S-блоки являются секретной частью алгоритма шифрования. Все
они должны быть различными, следовательно, для их хранения понадобится це-
ëûõ (4!)
128
= 768 битов.
4
Ðèñ. 4.6. Композиционный шифр из перестановок и подстановок

86 Глава 4. Как устроены современные шифры
Чтобы преодолеть данные трудности, Файстель использовал только два различных S-блока (S0 и S1), структура которых известна вместе с алгоритмом. Тогда каждый из S-блоков на рис. 4.6 будет заменен либо S0, либо S1, в зависимости
от значения одного бита ключа. Это снижает требования к памяти для S-блоков
до 128 битов и к длине ключа до 512 битов. Дальнейшее уменьшение размера
ключа до 128 битов было достигнуто за счет использования алгоритма разворачивания ключа (key shedule), который просто повторяет каждый бит ключа четыре
раза.
Каждый 4-битовый S-блок можно реализовать в виде массива в памяти объемом в шестнадцать 4-битовых слов. Поскольку S-блок должен быть обратимым,
все слова должны быть разными. Следовательно, простейшая реализация одного
4-битового S-блока потребует от нас наличия 64 битов памяти, для 8-битового
S-блока потребуется уже 2048 битов памяти, а 16-битовый S-блок «отъест» приличный кусок в один мегабайт. В IBM выбрала размер в 4 бита, выдержав своего
рода компромисс между стоимостью и надежностью.
Если бы был выбран 2-битовый вариант, то вся система могла быть раскрыта
за несколько секунд работ персонального компьютера. Это произошло бы потому,
что все 4! = 24 обратимых отображения 2 битов в 2 бита являются линейными
(или, если быть точным — аффинными) и могут быть представлены в виде линейного уравнения, в котором вся арифметика выполняется по модулю 2. Факт того,
что перестановка является линейной операцией, а композиция аффинных отображений дает аффинное отображение, показывает, что использование S-блоков в
этом случае было бы равносильно одному линейному преобразованию. В этом
случае, даже не пытаясь найти ключ, можно было бы получить открытый текст из
решения системы линейных уравнений методом, описанным в начале раздела.
Следовательно, при создании S-блоков аффинных отображений следует избегать. Отображений, «близких» к аффинным, тоже следует избегать, что, по-видимому, и отразилось в решении не использовать 3-битовые узлы замены, хотя в
данном случае аффинными будут всего лишь 3% обратимых отображений 3 битов
в 3 бита. Вместо этого были созданы и использованы 4-битовые S-блоки.
Криптосистема Lucifer
However, this does not mean that the LUCIFER algorithm is
useless. If a reasonably good stream cipher is used both before
and after LUCIFER, its weaknesses essentially become irrelevant, and its strengths are still present. It might indeed be argued that this kind of precaution ought to be used with DES as
well.
J. Savard. A Cryptographic Compendium
Шифр Люцифер стал логическим продолжением начатого исследования по
созданию алгоритма криптографического преобразования данных. В отличие от
предложенного ранее способа шифрования, реализованного в лабораториях IBM
впервые, Люцифер организован уже в соответствии с принципами сети Файстеля.

Глава 4. Как устроены современные шифры 87
Однако он унаследовал наработанные принципы создания и использования блоков подстановки и перемешивания.
Свои изобретения Файстель защитил с помощью нескольких патентов, ключевым из которых стал «Способ блочного криптографического преобразования» — он же Люцифер, одобренный патентной комиссией в 1974 году. Алгоритм
работы Люцифера был отображен также в одной из статей в «Журнале криптологии», однако настоящая его реализация была несколько сложнее, чем приведенная в опубликованной статье.
Шифр изначально имел размер блока шифрования, равный 128 битам. Такого
же размера использовался и ключ к шифру. Функция зашифрования своей структурой точь-в-точь повторяет описанную разделом выше сбалансированную сеть
Файстеля.
Процедура зашифрования состоит из шестнадцати последовательно выполняемых над блоком данных раундов, в каждом из которых результат выполнения
функции гаммирования F от левой половины блока входных данных складывается по модулю 2 с правой половиной блока. После выполнения каждого раунда левая и правая половины меняются местами, в соответствии с принципом сети
Файстеля.
Понятно, что выполнять обмен половинок после выполнения последнего раунда бессмысленно — это лишняя операция, которая не модифицирует данные
существенным образом, никак не затрудняя криптоанализ, и в то же время будет явно замедлять процесс зашифрования данных очень больших объемов. Поэтому обычно обмен полублоков после последнего раунда можно опустить как
излишний.
Каждый раунд шифра использует свой уникальный ключ раунда, представленный 72-битовым подключом. Данный подключ для первого раунда состоит из
первого байта основного ключа, который просто повторяется дважды (почему это
так, станет ясно чуть позже), а затем дополняется следующими 7 байтами ключа
(ведь 72-битный ключ раунда состоит ровно из 9 байтов). Подключ для каждого
следующего раунда получается циклическим сдвигом ключа предыдущей итерации шифра влево на 7 байтов (56 битов).
Понятно, что критической частью алгоритма является функция гаммирования, на которую возлагается задача генерации блока гаммы с как можно более
случайным поведением. Роль функции F в алгоритме играет следующая конструкция:
1. Правая половина блока складывается по модулю 2 с последними 8 байтами
подключа.
2. Полученный результат преобразуется в зависимости от ключа. В соответствии с первым байтом подключа раунда меняются местами полубайты получившейся гаммы. Если соответствующий бит ключа равен 1, обмен происходит, иначе байт остается неизменным.
3. Затем с помощью двух блоков замены меняется весь 8-байтовый блок гаммы. Для старших полубайтов используется узел замены S0, для младших — S1.
Таким образом, их влияние на гамму косвенно зависит от ключа. Значения S-блоков приведены на рис. 4.7.

88 Глава 4. Как устроены современные шифры
4. После этого 64 бита результата перемешиваются с помощью таблицы перестановки, заданной от младшего бита к старшему (рис. 4.8).
x1x2x3x
000011000111
000111110010
001001111110
001110101001
010011100011
010111011010
011010110000
011100000100
100000101100
100101101101
101000110001
101100011010
110010010110
110101001111
111001011000
111110000101
Ðèñ. 4.7. Узлы замены шифра Люцифер
4
S0(x) S1(x)
Áèò Номер результирующего бита для перестановки Áèò
0
16
32
48
10 21 52 56 27 1 47 38 18 29 60 0 35 9 55 46
26 37 4 8 43 17 63 54 34 45 12 16 51 25 7 62
42 53 20 24 59 33 15 6 50 61 28 32 3 41 23 14
58 5 36 40 11 49 31 22 2 13 44 48 19 57 39 30
Ðèñ. 4.8. Блок фиксированной перестановки шифра Люцифер
15
31
47
63
К сожалению, несмотря на то что шифр Люцифер обладает довольно большим размером блока и достаточной длины ключом, он оказался весьма уязвим к
криптографическим атакам. Это действительно имеет место в силу двух причин,
одна из которых заключается в слабости алгоритма разворачивания ключа, а вторая находится в слабых узлах замены.
Попробуем реализовать на практике предложенный шифр. Как использовать
таблицы замен уже было показано в одном из предыдущих листингов. Осталось
запрограммировать таблицу перестановки и использовать остов шифра с архитектурой сети Файстеля. Результат должен быть приблизительно похож на демонстрируемый в листинге 4.6.

Глава 4. Как устроены современные шифры 89
Листинг 4.6
#include <stdio.h>
#include <mem.h>
// узлы замен
uint8_t S0_box = {
12, 15, 7, 10, 14, 13, 11, 0,
2, 6, 3, 1, 9, 4, 5, 8
}
uint8_t S1_box[16] = {
7, 2, 14, 9, 3, 11, 0, 4,
12, 13, 1, 10, 6, 15, 8, 5
}
// блок перестановки
uint8_t P_box[64] = {
10, 21, 52, 56, 27, 1, 47, 38, 18, 29, 60, 0, 35, 9, 55, 46,
26, 37, 4, 8, 43, 17, 63, 54, 34, 45, 12, 16, 51, 25, 7, 62,
42, 53, 20, 24, 59, 33, 15, 6, 50, 61, 28, 32, 3, 41, 23, 14,
58, 5, 36, 40, 11, 49, 31, 22, 2, 13, 44, 48, 19, 57, 39, 30
}
#define NUM_OF_ROUNDS 16
// data = указатель на 128-битовый блок открытого текста
// key = 128-битный ключ
void enc_Lucifer(uint8_t *data, uint8_t *key) {
int i, b, j;
uint8_t subkey[16][9]; // 72-битовые подключи
uint8_t *swap, p[8];
uint8_t *left = data, *right = data+8; // технический прием,
// позволяющий избежать лишних операций копирования данных
// ---------------------------------------------// разворачиваем 128-битовый ключ
// первый байт основного ключа повторяется дважды
subkey[0][0] = key[0];
subkey[0][1] = key[0];
// затем подключ дополняется остальными байтами ключа
for (i = 2; i < 16; i++) subkey[0][2] = key[1];
// генерируем остальные подключи циклическим сдвигом на 7 байтов
for (i = 1; i < 16; i++) {
subkey[i][0] = subkey[i-1][2];
subkey[i][1] = subkey[i-1][3];
subkey[i][2] = subkey[i-1][4];
subkey[i][3] = subkey[i-1][5];
subkey[i][4] = subkey[i-1][6];
subkey[i][5] = subkey[i-1][7];
subkey[i][6] = subkey[i-1][8];
subkey[i][7] = subkey[i-1][0];
subkey[i][8] = subkey[i-1][1];
}

90 Глава 4. Как устроены современные шифры
// ---------------------------------------------// циклы шифрования
for (i = 0; i < NUM_OF_ROUNDS; i++) {
// вычисляем гамму: правая половина блока складывается
//помодулю2споследними восемью байтами подключа
subkey[i][1] ^= right[0];
subkey[i][2] ^= right[1];
subkey[i][3] ^= right[2];
subkey[i][4] ^= right[3];
subkey[i][5] ^= right[4];
subkey[i][6] ^= right[5];
subkey[i][7] ^= right[6];
subkey[i][8] ^= right[7];
// в соответствии с первым байтом подключа
// меняем местами полубайты получившейся гаммы
for(b=0;b<8;b++)
// если соответствующий бит ключа равен 1
if ((subkey[i][0] >> b)&1!=0){
// меняем местами старший и младший полубайты
subkey[i][b+1] =
(subkey[i][b+1] << 4) | (subkey[i][b+1] >> 4);
}
// с помощью двух блоков замены меняем весь блок гаммы
for(b=1;b<9;b++) {
subkey[i][b] = (S0_box[subkey[i][b] >> 4] << 4) |
(S1_box[subkey[i][b] & 0xF];
}
// переставляем биты в p
memset(p, 0, 8);
for(j=0;j<8;j++) {
for(b=0;b<8;b++) {
s = P_box[j*8 + b];
p[s / 8] ^= ((subkey[i][j] >> b) & 1) << (s % 8);
}
}
// в соответствии с принципом сети Файстеля
// левая половина блока ксорится с гаммой
for(b=0;b<8;b++) left[b] ^= p[b];
// очень быстро меняем местами половинки
swap = right;
right = left;
left = swap;
}
}
Приглядевшись к алгоритму, сразу становится ясно, зачем в каждом подключе был продублирован первый байт исходного ключа в самом начале алгоритма.
В самом алгоритме шифрования в каждом цикле левая половина блока складывается со значением старших восьми байтов подключа. Вместо того чтобы заводить
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
