Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Практическая криптография алгоритмы и их программирование

.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
Глава 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
, kk3вместе. Для того чтобы зашиф-
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.
-
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]