Сегодня нас ждет написание собственной крипто-проги, умеющей шифровать текст
по принципу открытого ключа. Если ты уже напуган размерами исходников PGP
(которые лень читать даже пробитым юниксоидам), я тебя успокою. Дело в том, что
добрые капиталисты из TSM inc написали для нас совершенно бесплатный компонент,
реализующий функции RSA алгоритма, который, собственно, сейчас и является
стандартом асимметричного шифрования. Так что за размер кода можешь не
беспокоиться, он будет неприлично маленьким и вместе с тем полноценным. Т.е.
наша с тобой прога будет уметь все, как и ее старшие братья. А именно - генерить
ключи, шифровать и расшифровывать :).
Вспомнить все
Прежде чем взяться за кодинг, нам придется припомнить пару теоретических
моментов:
1) Шифрование информации производится при помощи public key, а расшифровка -
private key. Первый может находиться у кого угодно (поскольку способен только
шифровать), второй - только у того, кому пишут. Его надо беречь как
девственность :).
Длина ключа может быть 512, 1024 и 2048 бит. В нашем примере я буду
использовать 1024-битный ключ, поскольку меньшая длина уже давно считается
отстоем, а 2048 слишком долго вычисляется моим 566 целероном.
2) Математической основой алгоритма являются 2 больших простых числа - p и q.
Они настолько большие, что разработчики компонента (который мы сегодня будем
использовать) ввели тип BigNum. Подробнее я расскажу о нем ниже.
Следовательно, автоматическая генерация ключа для нас будет заключаться
именно в нахождении p и q. Остальное компонент сделает сам. И это правильно. Как
говорил мой преподаватель труда, "пусть работают механизмы". Правда, он еще
считал, что ананасы растут на деревьях, но рабочему человеку это простительно.
Реквизит
Срочно беги на
http://www.crypto-central.com/software/freeware/RSA_free.zip и качай
компонент. Если при появлении надписи "download complete" твои руки (как это
обычно происходит со мной) приходят в сильное возбуждение и запускают
инсталляцию загруженного, то уйми их. Потому что этого мало, надо еще зайти на
http://www.crypto-central.com/cgi-bin/freeform.exe. Там, после заполнения
простенькой формы (размер лифчика и годовой доход там не спрашивают, достаточно
электронного адреса, имени и источника, откуда ты о них узнал) тебе на e-mail
сваливается индивидуальный код для инсталляции. Можно, правда, ничего не
заполнять, потому что я уже это сделал до тебя и получил вот что:
hjkDL9l3s0s[39s3fm3. Это код для бесплатной версии.
Ладно, теперь можно дать волю рукам и запустить инсталляцию - она сама найдет
твой дельфи и положит в компоненты новую закладку - "crypto", содержащую
компонент "RSA". Поэтому срочно кидай его на форму, и займемся
программированием.
Кодинг
Нам понадобится следующее: 2 Edit, 2 кнопки, 2 RadioButton (тоже лежит в
закладке standard), 1 ProgressBar, 2 Memo или RichEdit - кому что нравится.
Расположи их примерно так:
Совсем не обязательно делать такую здоровую кнопку "START", просто у меня
развилась гигантомания, и я стараюсь делать так, чтобы в любую кнопку можно было
попасть не целясь. Кстати, в будущем я не упущу возможности рассказать о
какой-нибудь консольной программе, и тут уж тебе вообще не придется баловаться
скринами :).
Переменные
Давай объявим следующее переменные:
pQ, pP: BigNum;
nado: boolean;
i, length: integer;
FromT, ToT: String;
Тут pQ и pP - это p и q, о которых я говорил в начале, nado - определяет,
надо ли создавать ключ, i и length - нужны для генерации ключа, FromT - исходная
строка (для шифровки или расшифровки), ToT - конечный текст.
Ключики
С переменными все ясно, давай разберемся с генерацией ключа. Дело в том, что
p и q, о которых я говорю уже в третий раз :), в сущности представляют собой
массивы из 32-битных чисел (следовательно, каждый элемент может принимать
значение до $FFFFFFFF), а длина самого массива будет зависеть от длины ключа и
определяться переменной length.
Поэтому все, что нам надо, это присвоить значение каждому элементу p и q, а
затем вычислить ключи командой MakeKeyPair. Можно, конечно, присвоить просто
случайные значения, используя генератор псевдослучайных чисел от дельфи, как нас
и учили в школе :), но тут тебя может ждать облом. Числа, которые он выдает,
очень предсказуемы, а потому делают наш ключ слишком уязвимым. Из-за этого,
кстати, многие компоненты содержат свой генератор чисел, эффективность которых
тоже вызывает сомнение :). Потому мы и пойдем путем PGP - будем использовать
координаты мышки (в случайности которых сомневаться не приходится) - т.е. для
генерации ключа мы попросим юзера покрутить мышкой, вызывая таким образом
событие MouseMove, и будем использовать постоянно меняющиеся координаты как
основу. Итак, начнем с соответствующей кнопки, которая называется "Сгенерировать
ключ". Вот что представляет собой ее онклик:
nado:= true; I:=0;
length:= RSA1.GetPrecision;
Progressbar1.Min:=0;
Progressbar1.Max:=length-1;
Тут я засвидетельствую надобность и инициализируюсь, плюс расставлю
минимальное и максимальное значения прогрессбара. Теперь самое интересное -
создай для формы событие TForm1.FormMouseMove и выжги в нем следующее:
Теперь уже там все предельно ясно, с каждым изменением координаты мы
присваиваем очередному элементу массива случайное значение, в зависимости от
координат мышки. Эту систему тебе предстоит круто усложнить, например,
использовать не каждую координату, а каждую 15-ю. Случайным образом :).
Шифруемся!
С этого момента можно отключать свои мозги от сети, они уже не понадобятся,
т.к. все остальное компонент сделает сам. Нам останется только сказать ему,
откуда брать ключи и что делать (шифровать или расшифровывать, что определяется
RadioButton’ами). Да что тут говорить, посмотри сам на кнопку Start (она же пуск
:)).
Вот так. Объясняю дальше. Бери строчку из Memo1 и шифруй ее ключом из Edit2.
И наоборот :). При таком упрощении юзеров на планете вообще скоро не останется -
все ринутся кодить. Посмотри на результат шифрования:
Заметил, что он намного больше оригинала? Это не глюк, а суровая реальность
асимметричных алгоритмов. Размер шифрованного текста больше оригинала, причем
зависит это от длины ключа.
End Of The World
Ну все, с этого момента можешь считать, что свой PGP у тебя уже есть. Ключи
его полностью совместимы с другими реализациями RSA алгоритма, а в исходник я
еще включил функцию сохранения и загрузки открытого ключа из файла. Поэтому не
забудь скачать его с
www.cydsoft.com/vr-online или взять на диске. Да, еще глянь на
директорию с компонентом, там есть хелп-файл и его неплохо бы почитать (правда,
он на английском). Там понаписано много интересного, в том числе и про цифровую
подпись (да, она тоже поддерживается RSA алгоритмом). Вещь это нужная, потому
что без нее MS IE никогда бы не выдавал нечто вроде: "Подлинность The
Super-Porno-Viewer удостоверена компанией Майкрософт. Всегда ли доверять
компании Майкрософт?" :)
На этой торжественной ноте ваш непокорный спешит откланяться и сообщить, что
на все вопросы (жалобы, предложения, тупой флейм, etc) он с удовольствием
ответит по электронной почте :).
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
IF nado= true then //Поехали
begin
IF i= length-1 then //Да ведь мы все заполнили...
begin
RSA1.MakeKeyPair(pP, pQ); //Образуем ключ
nado:= false; //И уже ничего не надо
Edit1.Text:= RSA1.PrivateKey; //Отобразим найденное
Edit2.Text:= RSA1.PublicKey;
end else //Ах, не заполнили? Исправим
begin
pP.Contents[i]:= X*Y*random($FFFF); //Координаты умножаем на случайность
pQ.Contents[i]:= X*Y*Y*random($FFFF);
Progressbar1.Position:=i; //Увеличим прогресс :)
inc(i); //Перейдем к следующему элементу, увеличим i
end;
end;
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
IF RadioButton1.Checked then //Надо шифровать?
begin
FromT:= Memo1.text; //Исходная строка
RSA1.PublicKey:= Edit2.Text; //Ключ
RSA1.EncryptString(FromT, ToT); //Зашифровали
Memo2.text:= ToT; //Вывели конечный текст
end else //Ах, не шифровать? Тогда наоборот :)
begin
RSA1.PrivateKey:= EDit1.Text;
FromT:= memo2.Text;
RSA1.DecryptString(FromT, ToT);
MEmo1.Text:= ToT;
end;
end;
|