Чтение онлайн

на главную - закладки

Жанры

Шрифт:
...

Листинг 12.14.

Функция получения ключа

function TfmCryptography.GetKey: Integer;

var

key, code: Integer;

begin

Result := –1;

//получаем текст элемента управления текстовая строка

Val(edKey.Text, key, code);

//ошибка во время преобразования к целому числу?

//или ключ имеет отрицательное значение?

if (code = 0) and (0 < key) then

Result := key;

end;

Процедура RecalcAlphabet имеет один параметр nKey, который принимает любое целое значение. Он показывает, на сколько требуется сдвинуть алфавит циклически вперед, то есть если имеется алфавит АБВГД, а пКеу=3, то результатом будет ВГДАБ. Первым делом алфавит соответствия заполняется один к одному, то есть каждый символ соответствует сам себе.

После этого циклом проходимся по строке, содержащей весь необходимый алфавит, подлежащий сдвигу, и переназначаем соответствие этих букв смещенным. Как это делается, можно посмотреть в листинге 12.15.

...

Листинг 12.15.

Функция пересчета алфавита преобразования

procedure TfmCryptography.RecalcAlphabet(nKey: Integer);

var

Ch: Char;

i: Integer;

LetCnt: Integer;

begin

//предварительно все символы в алфавите шифрования

//соответствуют символам из незашифрованного алфавита

for Ch := Low(RusDstAlphabet) to High(RusDstAlphabet) do

RusDstAlphabet[Ch] := Ch;

//количество символов в алфавите

LetCnt := SizeOf(TRusSrcAlphabet);

//смещаем эталонный алфавит циклически влево на значение,

//заданное ключом nKey

for i := 0 to LetCnt – 1 do

RusDstAlphabet[RusSrcAlphabet[(i – nKey + LetCnt)

mod LetCnt]] := RusSrcAlphabet[i];

end;

Процедура RecalcAlphabet производит необходимую подготовку перед шифрованием или дешифрованием. Результаты процедуры используются в функции EncryptDecryptString, где каждая буква открытого текста заменяется соответствующей ей буквой из смещенного алфавита. Это преобразование осуществляется простым проходом по всей строке и выполнением операции замены символа соответствующим ему. Стоит заметить, что для дешифровки сообщения по заданному ключу вычисляется симметричный ему ключ. В результате процесс дешифровки текста сообщения ничем не отличается от процесса его шифровки (листинг 12.16).

...

Листинг 12.16.

Шифрование/дешифрование строки

function TfmCryptography.EncryptDecryptString(strMsg: String;

nKey: Integer): String;

var

i: Integer;

begin

//каждый символ строки заменяется соответствующим символом

//алфавита шифрования

for i := 1 to Length(strMsg) do

strMsg[i] := RusDstAlphabet[strMsg[i]];

Result := strMsg;

end;

Теперь у нас есть все, чтобы перейти к решению основной задачи. Процесс шифрования аналогичен процессу дешифрования текста сообщения. Для начала нужно попытаться получить ключ, который ввел пользователь, что мы и делаем. После проверяем значение ключа. Если он равен -1, то это значит, что ключ введен неверно и преобразование текста невозможно. Когда все отлично, перед преобразованием текста мы вызываем метод подготовки алфавита с полученным ключом. Стоит отметить, что, когда происходит процесс дешифрования, вычисляется обратный ключ. С его помощью можно получить алфавит, используя который аналогично процессу шифрования получаем открытый текст сообщения. Далее просто: для каждой строки текста сообщения вызывается функцияпреобразования. На этом каждый метод заканчивает свою работу. Исходный код, соответствующий приведенному выше описанию, показан в листинге 12.17.

...

Листинг 12.17.

Шифрование/дешифрование текста сообщения

procedure TfmCryptography.btnEncryptMessageClick(Sender: TObject);

var

i: Integer;

nKey: Integer;

begin

//получаем ключ, с помощью которого будет

//шифроваться сообщение

nKey := GetKey;

//ключ задан верно?

if nKey = –1 then

Begin

MessageDlg(\'Ошибка: ключ задан неверно\', mtError, [mbOk], 0);

Exit;

End;

//получаем алфавит, с помощью которого будет

//происходить шифрование

RecalcAlphabet(nKey);

//предотвращаем перерисовку компонента до тех пор, пока не

//зашифруем все строки сообщения

mmEncryptMessage.Lines.BeginUpdate;

//освобождаем список от любых старых значений

mmEncryptMessage.Clear;

//шифруем сообщение построчно

for i := 0 to mmDecryptMessage.Lines.Count – 1 do

mmEncryptMessage.Lines.Add(

EncryptDecryptString(mmDecryptMessage.Lines[i], nKey));

//заново разрешаем перерисовку компонента

mmEncryptMessage.Lines.EndUpdate;

end;

procedure TfmCryptography.btnDecpyptMessageClick(Sender: TObject);

var

i: Integer;

nKey: Integer;

begin

nKey := GetKey;

if nKey = –1 then

Begin

MessageDlg(\'Ошибка:

ключ задан неверно\', mtError, [mbOk], 0);

Exit;

End;

//получаем алфавит, с помощью которого будет происходить

//дешифрование

RecalcAlphabet(SizeOf(TRusSrcAlphabet) – nKey

mod SizeOf(TRusSrcAlphabet));

mmDecryptMessage.Lines.BeginUpdate;

mmDecryptMessage.Clear;

for i := 0 to mmEncryptMessage.Lines.Count – 1 do

mmDecryptMessage.Lines.Add(

EncryptDecryptString(mmEncryptMessage.Lines[i], nKey));

mmDecryptMessage.Lines.EndUpdate;

end;

Первое, что бросается в глаза при рассмотрении всего текста приложения, это практически полная идентичность интерфейса и основной части исходного кода. На самом деле это совсем не случайно. Достаточно часто программы пишутся универсально (даже более универсально, чем здесь!). Это основывается на очень простом предположении, что код должен быть многоразовым, то есть его можно повторно использовать в других приложениях. В результате у вас получается некий шаблон, который позволяет решать целый класс задач. Для этого нужно выполнить несколько маленьких изменений и потом просто можно забыть об этом. Результат выполнения итогового приложения можно увидеть на рис. 12.6.

Рис. 12.6. Результат работы приложения «Шифр Цезаря»

12.5. Шифр с автоключом

Шифр, основывающийся на шифре Виженера, в котором или само сообщение, или результирующая криптограмма используются в качестве ключа, называется шифром с автоключом. Шифрование начинается с помощью «первичного ключа» (который является настоящим ключом в нашем смысле) и продолжается с помощью сообщения или криптограммы, смещенной на длину первичного ключа. Рассмотрим пример, в котором первичным ключом является набор букв ЗЕБРА. В табл. 12.2 приведено шифрование, когда в качестве ключа используется сообщение.

Таблица 12.2.

Шифр с автоключом (ключ – сообщение)

Если же в качестве ключа использовать криптограмму, то получится шифрование, как в табл. 12.3.

Таблица 12.3.

Шифр с автоключом (ключ – криптограмма)

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

Как обычно, сначала приведем код с объявлением необходимых типов, констант и переменных, а также объявление класса нашей формы. Все это содержится в листинге 12.18.

...

Листинг 12.18.

Объявление типов и класса нашей формы

type

TRusLetters = set of Char;

TfmEncryptingAutoKey = class(TForm)

mmDecryptMessage: TMemo;

mmEncryptMessage: TMemo;

lbDecryptMessage: TLabel;

lbEncryptMessage: TLabel;

btnEncryptMessage: TButton;

btnDecpyptMessage: TButton;

edKey: TEdit;

lbKey: TLabel;

procedure btnEncryptMessageClick(Sender: TObject);

procedure btnDecpyptMessageClick(Sender: TObject);

private

{ Private declarations }

function GetKey: String;

function EncryptString(strEncryptMsg: String;

var strKey: String): String;

function DecryptString(strDecryptMsg: String;

var strKey: String): String;

procedure EncryptDecrypt(SrcLines, DstLines: TStrings;

bEncrypt: Boolean);

public

{ Public declarations }

end;

const

RusLetters: TRusLetters = [\'А\'..’я’];

var

fmEncryptingAutoKey: TfmEncryptingAutoKey;

Поделиться:
Популярные книги

Батальоны тьмы. Трилогия

Болл Брайан Н.
18. Фантастический боевик
Фантастика:
боевая фантастика
5.00
рейтинг книги
Батальоны тьмы. Трилогия

Дженни Герхардт

Драйзер Теодор
Проза:
классическая проза
9.44
рейтинг книги
Дженни Герхардт

Тютчев

Кожинов Вадим Валерьянович
687. Жизнь замечательных людей
Документальная литература:
биографии и мемуары
8.12
рейтинг книги
Тютчев

Апокалипсис

Мартин Джордж Р.Р.
Антология
Фантастика:
социально-философская фантастика
героическая фантастика
боевая фантастика
киберпанк
6.00
рейтинг книги
Апокалипсис

- Да они как две капли воды! - Нет, она хуже

Адский жнец
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
- Да они как две капли воды! - Нет, она хуже

Сицилианская защита

Васильев Андрей Александрович
5. Акула пера в Мире Файролла
Фантастика:
фэнтези
киберпанк
рпг
9.27
рейтинг книги
Сицилианская защита

Гримуар темного лорда III

Грехов Тимофей
3. Гримуар темного лорда
Фантастика:
фэнтези
попаданцы
аниме
5.25
рейтинг книги
Гримуар темного лорда III

Игра Эндера

Кард Орсон Скотт
1. История Эндера
Фантастика:
космическая фантастика
9.39
рейтинг книги
Игра Эндера

Бояръ-Аниме. Газлайтер. Том 34

Володин Григорий Григорьевич
34. История Телепата
Фантастика:
фэнтези
боевая фантастика
аниме
7.17
рейтинг книги
Бояръ-Аниме. Газлайтер. Том 34

Я еще князь. Книга XX

Дрейк Сириус
20. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я еще князь. Книга XX

Осажденная крепость. Нерассказанная история первой холодной войны

Млечин Леонид Михайлович
Научно-образовательная:
история
5.00
рейтинг книги
Осажденная крепость. Нерассказанная история первой холодной войны

Откройте Америку!

Яцкарь Григорий Семенович
Проза:
современная проза
роман
6.25
рейтинг книги
Откройте Америку!

Я уже царь. Книга XXIX

Дрейк Сириус
29. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я уже царь. Книга XXIX

Рассвет русского царства 3

Грехов Тимофей
3. Новая Русь
Фантастика:
историческое фэнтези
альтернативная история
5.00
рейтинг книги
Рассвет русского царства 3