Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #65, МАЙ 2004 г.

Шифруйся сам!

Alek Silverstone

Xakep, номер #065, стр. 065-110-1


(AlekSi@pisem.net)

Шифруем и хешируем без чужих компонентов

Сейчас модно говорить о криптографии: таинственные слова "IDEA", "BlowFish", "MD5" можно слышать достаточно часто. Однако большая часть людей знает только, что это такое, и не знает, как это сделано. Поэтому все начинающие кодеры, столкнувшиеся с проблемой защиты информации, начинают либо изобретать колесо (xor с ключом, битовый сдвиг и т.п. - все это вызывает у профессионалов лишь кривую ухмылку), либо использовать чужие компоненты.

В этой статье мы разберем два простых алгоритма, необходимых в любой программе защиты информации. Первый - алгоритм шифрования, второй - функция хеширования (о том, что это такое, прочитай в статье «Надери задницу хацкерам» этого же номера).

Шифруемся!

Рассмотрим алгоритм шифрования RC4 (Ron's Code 4 или Rivest's Cipher 4, если интересно). Я взял его, во-первых, из-за крайне простой реализации, а во-вторых, из-за высокой стойкости к атакам. Он был разработан Роном Ривестом (Ron Rivest, один из самых известных людей в мире криптографии - буква "R" в аббревиатуре RSA принадлежит именно ему) в 1987 году, и с тех пор не известно ни одного случая успешной атаки на него. Есть и третья причина - этот алгоритм является поточным шифром. Что это значит? Опять рассмотрим пример. Допустим, нам необходимо шифровать поток информации. Как работают блочные шифры, такие как DES, IDEA и BlowFish? Им на вход подается текст фиксированного размера (в случае DES - 64 байта), на выходе получается тот же объем. То есть в нашем примере нам придется ждать получения 64 байт, потом шифровать их и выплевывать. Но ведь поток надо шифровать в режиме реального времени! А если блоки идут по нескольку байт? Вот и выходит облом... Потоковые же шифры обрабатывают текст по одному биту (в данной реализации RC4 - по одному байту).

RC4 входит в спецификацию стандарта CDPD (сотовая пакетная передача данных), а также в "туннельный" протокол "точка-точка" PPTP (защищенный PPP). Такие солидные стандарты не выбрали бы что-то плохое :).

Для алгоритма нам понадобятся три глобальные переменные - rc4i и rc4j типа byte и массив rc4s:array[0..255] of byte. Сначала надо заполнить массив:

Заполняем массив

procedure RC4Init(key:shortstring);

var

k: array[0..255] of byte;

i, j, t : byte;

begin

rc4i:=0;

rc4j:=0;

for i:=0 to 255 do rc4s[i]:=i;

j:=0;

t:=length(key);

for i:=0 to 255 do begin

inc(j);

k[i]:=Byte(key[j]);

if j=t then j:=0;

end;

j:=0;

for i:=0 to 255 do begin

j:=(j+k[i]+rc4s[i]) mod 256;

t:=rc4s[i];

rc4s[i]:=rc4s[j];

rc4s[j]:=t;

end;

end;

Вот и все! Сложно? Да ладно! Все остальные алгоритмы намного сложнее! :) Теперь напишем функцию для получения шифрованного байта:

Шифранем байты

function RC4GetCryptoByte(ch:byte):byte;

var t:byte;

begin

rc4i:=(rc4i+1) mod 256;

rc4j:=(rc4j+rc4s[rc4i]) mod 256;

t:=rc4s[rc4i];

rc4s[rc4i]:=rc4s[rc4j];

rc4s[rc4j]:=t;

t:=(rc4s[rc4i]+rc4s[rc4j]) mod 256;

RC4GetCryptoByte:=rc4s[t] xor ch;

end;

В первой строчке мы циклически увеличиваем значение rc4i на 1. Если значение стало равным 255, то оно обнуляется. Второй строчкой мы изменяем значение счетчика rc4j в зависимости от массива rc4s (который, в свою очередь, зависит от ключа). Потом мы меняем местами элементы с порядковыми номерами rc4i и rc4j в этом массиве. Далее мы определяем номер элемента, который складывается по модулю 2 (это такое хитрое название xor'а) с байтом исходного текста. Этот шифр является симметричным, поэтому дешифрование выполняется аналогично шифрованию - на вход подаем зашифрованный байт и получаем дешифрованный. Скорость его примерно в 11 раз выше, чем у известного DES’а (проверенно мной).

Содержание  Вперед на стр. 065-110-2
<<< НАЗАД ||| ГЛАВНАЯ