Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Практическая криптография алгоритмы и их программирование
.pdf
Глава 4. Как устроены современные шифры 101
temp=r^key[1];
l ^= SP_box[7][temp & 0x3F];
l ^= SP_box[5][(temp >> 8) & 0x3F];
l ^= SP_box[3][(temp >> 16) & 0x3F];
l ^= SP_box[1][(temp >> 24) & 0x3F];
else
next operators
Проверив условие, он выполнит операцию, выделенную жирным шрифтом, а
остальные будет выполнять всегда (!). При этом совершенно ошибочным выглядит появление конструкции «else next operators» в конце. Чтобы этого не произошло, макрос приходится обрамлять кавычками {} или, что значительно лучше,
конструкцией do {} while (0).
Листинг 4.15
#define F(l, r, key) do { \
temp = ((r >> 4) | (r << 28)) ^ key[0]; \
l ^= SP_box[6][temp & 0x3F]; \
l ^= SP_box[4][(temp >> 8) & 0x3F]; \
l ^= SP_box[2][(temp >> 16) & 0x3F]; \
l ^= SP_box[0][(temp >> 24) & 0x3F]; \
temp=r^key[1]; \
l ^= SP_box[7][temp & 0x3F]; \
l ^= SP_box[5][(temp >> 8) & 0x3F]; \
l ^= SP_box[3][(temp >> 16) & 0x3F]; \
l ^= SP_box[1][(temp >> 24) & 0x3F]; \
} while (0)
Функция гаммирования в DES достаточно проста. Правая половина r преобразуется циклическим сдвигом и наложением гаммы-значения текущего подключа key. Подключ key состоит на самом деле из восьми байтов, представляющих
собой шестибитовые значения используемых ключевых элементов. В исходном
тексте из листинга 4.13 видно, что для их представления используются не восьмибитовые типы данных, а 32-битовые — как для длинных целых. Это сделано опять
же в целях повышения эффективности генерируемого современными компиляторами кода.
На вход функции гаммирования F поступает 32-битовая половина шифруемого блока и подключ. С помощью специальной таблицы эти 32 бита разворачиваются до 48 битов дублированием некоторых из них. Затем полученный развернутый блок побитно суммируется по модулю 2 с соответствующим битом ключа.
Полученный в результате блок данных снова разделяется на восемь шестибитовых частей.
Они, в свою очередь, используются в качестве входных аргументов для получения значений соответствующих узлов замен. После этого полученные восемь
уже 4-битовых значений объединяются обратно в 32-битовый блок данных. С его
элементами проводится специальная перестановка битов, показанная на
рис. 4.12. Результат этой последней операции и является выходным значением
функции шифрования.

102 Глава 4. Как устроены современные шифры
Как видно из описания, почти все операции алгоритма являются линейными — в действительности все, кроме операции замены, проводимой с помощью заранее заданных узлов замен. Они единственные представляют собой нелинейную
и самую сложную часть алгоритма, от которой зависит стойкость всего алгоритма. Связь между узлами замен S1...S8, таблицей расширения E и таблицей перестановок P показана на рис. 4.12.
Ðèñ. 4.12
Для их эффективной реализации вполне достаточно массива констант, используя который мы вычисляем значение замены путем подстановки блока битов в
качестве индекса этого массива, например: S = S_box[data]. С побитовой перестановкой гораздо сложнее. В предыдущем разделе (см. раздел «Криптосистема
Lucifer») нами уже был описан способ осуществить обе эти операции с максимальной эффективностью. Точно так же можно поступить и при реализации алгоритма DES.
Для вычисления SP-узлов замен и перестановки можно воспользоваться программой из листинга 4.16. В ней по всем возможным входным данным и соответствующим проводятся вычисления возможных результатов, которые затем в массиве констант в файле описания на языке Си вносятся в основной программный
модуль.
Листинг 4.16
void make_spboxes() {
uint8_t pbox[32];
int p, i, s, j, rowcol;
FILE *f = fopen("des_sp.h", "wt");
// небольшая инверсия для таблицы перестановки
for (p = 0; p < 32; p++)
for(i = 0; i < 32; i++)
if (p32i[i] == p+1) {
pbox[p] = i;
break;
}

Глава 4. Как устроены современные шифры 103
// заполняем SP_box // uint32_t SP_box[8][64];
for(s=0;s<8;s++)
for (i = 0; i < 64; i++) {
SP_box[s][i] = 0;
rowcol = (i & 32) | ((i & 1) ? 16 : 0) | ((i >> 1) & 0xf);
for(j=0;j<4;j++)
if (S_box[s][rowcol] & (8 >> j)){
SP_box[s][i] |= 1L << (31 - pbox[4*s + j]);
}
}
s=0;
p=1;
fprintf(f, "uint32_t SP_box[8][64] = {\n\t");
for(i=0;i<8;i++) // по всем узлам
for (j = 0; j < 64; j++) { // по всем возможным входам
// сдвигаем циклически для алгоритма
SP_box[i][j] = (SP_box[i][j] << p)
| (SP_box[i][j] >> (32-p));
// и выводим в файл описаний
fprintf(f, "0x%08lx, ", SP_box[i][j]);
if (++s == 4) {
fprintf(f, "\n");
if (i != 7 || j != 63) fprintf(f, "\t");
s=0;
}
}
fprintf(f, "};\n");
fclose(f);
}
Теперь снова посмотрим на весь алгоритм. На последнем раунде шифрования
не происходит обмена половин данных. Вместо этого они объединяются в полный
64-битовый блок и над ним выполняется финальная битовая перестановка, обратная начальной. Собственно, результат последней операции и является результатом зашифрования блока с помощью алгоритма DES.
При этом процедура расшифрования блока аналогична процедуре зашифрования, с той только разницей, что для расшифрования необходимо переставить все
операции преобразования блока в обратном порядке (см. листинг 4.17).
Листинг 4.17
// проводим 16 раундов шифрования
if (encrypt) {
F(left, right, key->subkey[0]);
F(right, left, key->subkey[1]);
F(left, right, key->subkey[2]);
F(right, left, key->subkey[3]);
F(left, right, key->subkey[4]);
F(right, left, key->subkey[5]);
F(left, right, key->subkey[6]);
F(right, left, key->subkey[7]);
F(left, right, key->subkey[8]);

104 Глава 4. Как устроены современные шифры
F(right, left, key->subkey[9]);
F(left, right, key->subkey[10]);
F(right, left, key->subkey[11]);
F(left, right, key->subkey[12]);
F(right, left, key->subkey[13]);
F(left, right, key->subkey[14]);
F(right, left, key->subkey[15]);
}
else {
F(right, left, key->subkey[15]);
F(left, right, key->subkey[14]);
F(right, left, key->subkey[13]);
F(left, right, key->subkey[12]);
F(right, left, key->subkey[11]);
F(left, right, key->subkey[10]);
F(right, left, key->subkey[9]);
F(left, right, key->subkey[8]);
F(right, left, key->subkey[7]);
F(left, right, key->subkey[6]);
F(right, left, key->subkey[5]);
F(left, right, key->subkey[4]);
F(right, left, key->subkey[3]);
F(left, right, key->subkey[2]);
F(right, left, key->subkey[1]);
F(left, right, key->subkey[0]);
}
Постоянная проверка очевидного значения и необходимость держать два варианта исполнения, по сути, одного и того же кода явно не является эффективной
реализацией. Чтобы избежать этого в программе, мы можем просто переставлять
биты ключа надлежащим образом, не переставляя функции в исходном коде. Проделав это, получим полный текст программы алгоритма зашифрования данных в
соответствии со стандартом DES (см. листинг 4.18).
Листинг 4.18
// зашифровываем один блок данных
void enc_DES(uint32_t *block, DES_KEY *key, bool encrypt) {
uint32_t left, right, temp;
// переставляем байты для совместимости с big-endian
reorder_bytes(*block, 2, left, temp);
left = block[0];
right = block[1];
temp = ((left >> 4) ^ right) & 0x0f0f0f0fL;
right ^= temp;
left ^= (temp << 4);
temp = ((left >> 16) ^ right) & 0x0000ffffL;
right ^= temp;
left ^= (temp << 16);
temp = ((right >> 2) ^ left) & 0x33333333L;
left ^= temp;

Глава 4. Как устроены современные шифры 105
right ^= (temp << 2);
temp = ((right >> 8) ^ left) & 0x00ff00ffL;
left ^= temp;
right ^= (temp << 8);
right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
temp = (left ^ right) & 0xaaaaaaaaL;
left ^= temp;
right ^= temp;
left = ((left << 1) | ((left >> 31) & 1L)) & 0xffffffffL;
// проводим 16 раундов шифрования
F(left, right, key->subkey[0]);
F(right, left, key->subkey[1]);
F(left, right, key->subkey[2]);
F(right, left, key->subkey[3]);
F(left, right, key->subkey[4]);
F(right, left, key->subkey[5]);
F(left, right, key->subkey[6]);
F(right, left, key->subkey[7]);
F(right, left, key->subkey[9]);
F(left, right, key->subkey[10]);
F(right, left, key->subkey[11]);
F(left, right, key->subkey[12]);
F(right, left, key->subkey[13]);
F(left, right, key->subkey[14]);
F(right, left, key->subkey[15]);
right = (right << 31) | (right >> 1);
temp = (left ^ right) & 0xaaaaaaaaL;
left ^= temp;
right ^= temp;
left = (left << 31) | (left >> 1);
temp = ((left >> 8) ^ right) & 0x00ff00ffL;
right ^= temp;
left ^= (temp << 8);
temp = ((left >> 2) ^ right) & 0x33333333L;
right ^= temp;
left ^= (temp << 2);
temp = ((right >> 16) ^ left) & 0x0000ffffL;
left ^= temp;
right ^= (temp << 16);
temp = ((right >> 4) ^ left) & 0x0f0f0f0fL;
left ^= temp;
right ^= (temp << 4);
// снова меняем байты местами для совместимости
block[0] = right;
block[1] = left;
reorder_bytes(*block, 2, left, temp);
}
Надо сказать, что все табличные значения несколько отличаются от соответ-
ствующих значений, опубликованных в классическом варианте — в самом стан
-

106 Глава 4. Как устроены современные шифры
дарте DES. Это связано с принципами строения архитектуры процессоров Intel
как little-endian и соответственно с принципами обработки данных, которые размещаются в памяти. Вследствие этого исходные таблицы приходится дорабатывать. По этой же причине байты данных перед зашифрованием необходимо переставить в соответствии с big-endian архитектурой, а после зашифрования переставить их в обратном порядке.
На самом деле последняя операция могла быть излишней, если бы твердо
были уверены в том, что никакой сетевой драйвер или драйвер жесткого диска не
вздумает переставить их по собственной воле «для совместимости с компьютерами других платформ». К сожалению, такой уверенности нет, и приходится каждый раз проделывать эту в общем-то бессмысленную операцию.
К тому же недавно было показано, что и от примитивных атак ключ размером
56 битов не предоставляет значительной защиты, — ключ DES был найден путем
тотального опробования с помощью специализированного программно-аппаратного комплекса (см. раздел «Дешифрование DES»).
Правда, на проблему недостаточного размера ключа указывали сразу же после принятия DES как стандарта шифрования. Поэтому для обеспечения большей
надежности, исходя из того, что сам DES потенциально не мог ее обеспечить,
были построены несколько вариантов нового стандарта: Triple-DES (3-DES) и его
обобщенные варианты nDES, New-DES, DES-X, Generalized-DES (GDES). Они
появлялись в разное время, но все были основаны на существующей DES-архитектуре. Таким же образом появился и DEAL, затем DEA, а затем и IDEA.
Все они в первую очередь устраняли недостаток, связанный с малой длиной
ключа в алгоритме DES. Triple-DES (3-DES) или Тройной-DES представляет собой весьма простое усовершенствование алгоритма, увеличивающее длину 56-битового ключа вдвое (или втрое, в зависимости от вариантов исполнения) с помощью следующего нехитрого преобразования:
1
3
DES x DES DES DES x
12 1 1
kk k k k+
=() ( ( ()))
−
для двойной длины ключа
1
èëè
3
DES x DES DES DES x
12 3 1 2 3
kkk k k k++
DES
(x) — обозначает зашифрование с помощью алгоритма, а
k
=() ( ( ()))
для тройной длины ключа.
DES x
−1
k
()
—
обозначает расшифрование.
В алгоритме Тройной-DES в качестве основной криптографической функции
используется весь алгоритм DES без изменения. Ключ 3-DES формируют путем
конкатенации трех различных ключей — k
, k2è k3вместе. Для того чтобы зашиф-
1
ровать блок данных, его сначала преобразуют с помощью алгоритма DES и ключа
, затем получившийся выход дополнительно преобразуют еще раз с помощью
k
1
DES, но ключ выбирают уже k
используя ключ k
.
3
и в третий раз поступают аналогичным образом,
2
Вариант, где используется только лишь двукратное увеличение, называют
также «двухключевым Тройным-DES». В нем открытый текст сперва шифруется
ключом k
. К сожалению, криптоанализ этих схем показал, что длина блока в 64 бита де-
k
1
, затем расшифровывается ключом k2и снова зашифровывается ключом
1
лает эти схемы уязвимыми к атаке по подобранному шифротексту. К тому же

Глава 4. Как устроены современные шифры 107
3-DES с тремя независимыми ключами оказался уязвим к атаке по зависимому
ключу (см. раздел «Дешифрование DES»), причем время ее исполнения приблизительно равно времени исчерпывающего поиска в простом DES. Кроме того, нерешенным до сих пор является вопрос, не образует ли DES сам по себе алгебраическое кольцо. Если так, то зашифрование на двух разных ключах k
равносильно зашифрованию на некотором третьем ключе k
, который возможно
3
è k2будет
1
будет описать формально.
Еще одним вариантом исполнения нового стандарта был шифр DES-X, увеличивающий длину ключа обычного DES до 120 битов. Учитывая, что сам по себе
DES не может обеспечить должной стойкости, его можно попытаться усилить посредством применения дополнительных криптографических преобразований.
В алгоритме DES-X, предложенном компанией RSA Data Security, используется
именно такой подход. Входные данные (блок размером 64 бита) суммируются по
модулю 2 с некоторым битовым набором (в английских источниках эта операция
названа «отбеливанием» или whitening — дело в том, что с помощью этой операции входные данные должны выглядеть более случайно, более похожими на так
называемый «белый шум», то есть совершенно случайные данные). После этого
блок зашифровывается с помощью DES, а затем уже результат проходит еще
одно отбеливание, но уже с помощью другого набора битов.
По этой причине ключ DES-X состоит на самом деле из двух ключей — ключа для настоящего DES длиной 56 битов и еще 64-битовый ключ для «отбеливания». При этом «отбеливающая» часть ключа используется в основном на этапе
работы функции разворачивания ключа. Для ее работы необходима таблица замен, основанная на значениях цифр числа π (см. листинг 4.19).
Листинг 4.19
DESX_S_box[256] = {
189, 86,234,242,162,241,172, 42,176,147,209,156, 27, 51,253,208,
48, 4,182,220,125,223, 50, 75,247,203, 69,155, 49,187, 33, 90,
65,159,225,217, 74, 77,158,218,160,104, 44,195, 39, 95,128, 54,
62,238,251,149, 26,254,206,168, 52,169, 19,240,166, 63,216, 12,
120, 36,175, 35, 82,193,103, 23,245,102,144,231,232, 7,184, 96,
72,230, 30, 83,243,146,164,114,140, 8, 21,110,134, 0,132,250,
244,127,138, 66, 25,246,219,205, 20,141, 80, 18,186, 60, 6, 78,
236,179, 53, 17,161,136,142, 43,148,153,183,113,116,211,228,191,
58,222,150, 14,188, 10,237,119,252, 55,107, 3,121,137, 98,198,
215,192,210,124,106,139, 34,163, 91, 5, 93, 2,117,213, 97,227,
24,143, 85, 81,173, 31, 11, 94,133,229,194, 87, 99,202, 61,108,
180,197,204,112,178,145, 89, 13, 71, 32,200, 79, 88,224, 1,226,
22, 56,196,111, 59, 15,101, 70,190,126, 45,123,130,249, 64,181,
29,115,248,235, 38,199,135,151, 37, 84,177, 40,170,152,157,165,
100,109,122,212, 16,129, 68,239, 73,214,174, 46,221,118, 92, 47,
167, 28,201, 9,105,154,131,207, 41, 57,185,233, 76,255, 67,171
}
Для начала обычным способом с помощью ключа для DES вычисляется 16
подключей DES. Затем для вычисления отбеливающих наборов битов использует
-

108 Глава 4. Как устроены современные шифры
ся алгоритм, приведенный в листинге 4.20. Там же описан способ применения отбеливающих наборов битов — функции DESX_encrypt и DESX_decrypt.
Листинг 4.20
pre_whitening = whitening_key;
post_whitening = 0;
hash_it_with(DES_key);
hash_it_with(whitening_key);
...
hash_it_with(uint8_t *key) {
for(inti=0;i<8;i++) {
int index = post_whitening[0] ^ post_whitening[1];
for(intj=0;j<7;j--)
post_whitening[i] = post_whitening[i+1];
post_whitening[0] = post_whitening[0] ^ DESX_S_box[index];
}
...
DESX_encrypt(uint8_t *data, DESX_key *key) {
int i;
for(i=0;i<7;i++) data[i] = data[i] ^ key->pre_whitening[i];
DES_enc(data, key, true);
for(i=0;i<7;i++) data[i] = data[i] ^ key->post_whitening[i];
}
DESX_decrypt(uint8_t *data, DESX_key *key) {
int i;
for(i=0;i<7;i++) data[i] = data[i] ^ key->pre_whitening[i];
DES_enc(data, key, false);
for(i=0;i<7;i++) data[i] = data[i] ^ key->post_whitening[i];
}
Шифр nDES является обобщением 3-DES, связанным с n-кратным применением в связи с неэффективностью алгоритма при больших значениях n,онне
стал сколь-нибудь значительным вкладом в развитие криптографии блочных
шифров.
Его созвучный аналог представляет собой уже 17-раундовый шифр со 120-битовым ключом. Процедура разворачивания ключа проста. Каждые два раунда используют одну 56-битовую часть ключа, которая для каждой следующей пары получается из первых 56 битов ключа, который преобразуется с помощью циклического сдвига на те же 56 битов.
Обобщенный GDES (Generalized-DES) является не чем иным, как простым
обобщением опубликованного стандарта DES (что следует из названия). Сохраняя структуру DES, шифр GDES позволяет использовать произвольные узлы замен, начальные/конечные перестановки и таблицу для разворачивания ключа.
При этом 16 подключей длиной в 48 битов также могут выбираться пользователем вручную, а не вычисляться системой из одного основного 56-битового ключа.

Глава 4. Как устроены современные шифры 109
Авторы GDES добивались на самом деле решения двух проблем — увеличения
длины ключа и устранения возможной «недобросовестности» составителей известных узлов замен, поскольку они являются не менее ключевым местом в шифре,
чем все остальное.
Надо сказать, что в отечественном стандарте «Системы обработки информации. Защита криптографическая. Алгоритм криптографического преобразования»
в соответствии c ГОСТ 28147—89, принятом в 1989 году, поступили приблизительно так же. Отечественный стандарт шифрования копирует структуру DES, за
исключением некоторых существенных модификаций. Первой модификацией является отсутствие начальной и финальной перестановок, характерных для всех
вариантов DES. Кроме того, в ГОСТ увеличено количество раундов до 32 штук.
Отсутствует схема разворачивания ключа из 32 в 48 битов. Подключи на каждом
32
раунде суммируются по модулю 2
бенностью сложения является то, что оно выполняется с переносом.
, а не по модулю 2, как в DES. При этом осо-
18
Вместо
подстановок, переводящих 6 битов в 4 бита, используются взаимооднозначные,
переводящие 4 бита в 4 бита.
Значения 512-битовых узлов замен не были опубликованы вместе со стандартом. При этом не было (и до сих пор не стандартизовано) даже упоминания о возможных критериях по их созданию (да что уж говорить, если даже тестовые векторы, записанные в стандарте, к сожалению, не учитывают ряд битов выхода
шифра). Как говаривал известный советский критик: «Что поделать, издержки
производства». Говоря другим языком, узлы замен в ГОСТ нужно считать секретной компонентой шифра.
Дополнительно ко всем вышеперечисленным пунктам перестановка осуществляется циклическим сдвигом на 11 битов влево вместо сложной побитовой перестановки DES. Процедура разворачивания ключа представляется простым расположением исходных ключевых данных в следующем порядке:
0,1,2,3,4,5,6,7, 0,1,2,3,4,5,6,7, 0,1,2,3,4,5,6,7, 7,6,5,4,3,2,1,0 —
для зашифрования и
0,1,2,3,4,5,6,7, 7,6,5,4,3,2,1,0 7,6,5,4,3,2,1,0 7,6,5,4,3,2,1,0 —
для расшифрования данных.
Вкупе с 512-битовыми узлами замены 256-битовый ключ составляет приблизительно 610 битов действительно ключевой информации (со скидкой на структуру алгоритма). Узлы замен на самом деле можно считать группой перестановок,
которые по требованиям к памяти превосходят узлы замен DES в два раза. А 610
битов ключевой информации получаются следующим образом. Первые 256 исходного ключа включены в шесть результирующих сотен полностью. Следующей
ключевой компонентой являются узлы замен. Каждый узел замены представляет
собой перестановку целых от 0 до 15. Всевозможных таких перестановок 16! =
= 20922789888000, или приблизительно 2 ⋅ 10
44,25014047
2
вание по модулю 2
. Последнее же означает (см. главу «Теория секретных систем»), что узел
18
На самом деле в алгоритме в соответствии с ГОСТ 28147—89 используется как суммиро
32
с переносом, так и суммирование по модулю 232соответственно без оного.
13
вариантов, или что равно
-

110 Глава 4. Как устроены современные шифры
замены можно определить с помощью не более чем 44,2 бита информации. Умножаем 44,2 на 8 (количество узлов замены) и получаем 354 бита, которые в сумме
с 256 битами исходного ключа дают ровно 610 искомых битов.
Основной частью алгоритма, так же как и в DES в ГОСТ 28147—89, являются функции гаммирования, используемые для выработки накладываемой на данные гамма-последовательности. И здесь проявляется основная особенность отечественного стандарта. Дело в том, что функция F определяет группы перестановок
для различных семейств ключей и по этой причине образует не что иное, как простую перестановку c произвольным фиксированным ключом.
В описании ГОСТ определены четыре режима работы, совпадающие с аналогичными режимами работы его западного аналога (см. раздел «Режимы шифрования»).
Попробуем реализовать алгоритм шифрования в соответствии с ГОСТ на языке Perl (см. листинг 4.21).
Листинг 4.21
#!/usr/bin/perl -w
# узлы замен (последовательно)
@SBOX = (
[ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 ],
[ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 ],
[ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 ],
[ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 ],
[ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 ],
[ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 ],
[ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 ],
[ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 ]
);
19
sub f($) {
local $_;
my $x = shift;
my $result = 0;
grep {
$result = $result
| (${$SBOX[$_]}[($x >> ($_ * 4)) & 15] << ($_ * 4));
} reverse (0..7);
return $result;
}
sub gostcrypt($$$) {
my ($data, $key, $decrypt) = @_;
my ($swap, $left, $right, $j);
19
Поскольку ГОСТ в действительности имеет тот же каркас, что и DES, авторы сочли до
вольно скучным представлять реализацию алгоритма в соответствии с ГОСТ 28147-89 на языке
Си, так же как и DES. Поэтому было решено сделать это на другом языке — им сразу стал Perl.
-
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
