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

на главную

Жанры

Шрифт:
...

Листинг 12.8.

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

procedure TfmSubstitution.btnEncryptMessageClick(Sender:

TObject);

var

i: Integer;

begin

//проверяем корректность ввода перестановки

if ValidateRearrangement then

begin

//создаем алфавит преобразования открытого текста

RecalcAlphabet(0);

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

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

mmEncryptMessage.Lines.BeginUpdate;

//очищаем текстовый редактор

mmEncryptMessage.Clear;

//шифруем открытый текст построчно

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

mmEncryptMessage.Lines.Add(EncryptDecryptString

(mmDecryptMessage.Lines[i]));

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

mmEncryptMessage.Lines.EndUpdate;

end

else

MessageDlg(\'Ошибка: символы подстановки заданы неверно\',

mtError, [mbOk], 0);

end;

procedure TfmSubstitution.btnDecpyptMessageClick(Sender:

TObject);

var

i: Integer;

begin

//проверяем

корректность ввода перестановки

if ValidateRearrangement then

begin

//создаем алфавит преобразования шифрованного текста

RecalcAlphabet(1);

mmDecryptMessage.Lines.BeginUpdate;

mmDecryptMessage.Clear;

//дешифруем шифрованный текст построчно

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

mmDecryptMessage.Lines.Add(EncryptDecryptString

(mmEncryptMessage.Lines[i]));

mmDecryptMessage.Lines.EndUpdate;

end

else

MessageDlg(\'Ошибка: символы подстановки заданы неверно\',

mtError, [mbOk], 0);

end;

В итоге мы получили вполне рабочий вариант приложения, способного без особого труда шифровать и дешифровать сообщения. На рис. 12.2 представлен результат работы данного приложения.

Рис. 12.2. Результат работы приложения «Шифр простой подстановки»

12.3. Транспозиция

Следующий шифр, который мы будем рассматривать, называется транспозицией с фиксированным периодом d. В этом случае сообщение делится на группы символов длины d и к каждой группе применяется одна и та же перестановка. Эта перестановка является ключом и может быть задана некоторой перестановкой первых d целых чисел.

Таким образом, для d = 5 в качестве перестановки можно взять 23154. Это будет означать, что т1т2 тЗт4т5т6т7т8т9 тЮ… переходит в т2 тЗт1т5т4т7т8т6т10т9… Последовательное применение двух или более транспозиций будет называться составной транспозицией. Если периоды этих транспозиций d1…., ds, то, очевидно, в результате получится транспозиция периода d, где d – наименьшее общее кратное d1…., ds.

Теперь, зная определение данного шифра, можно перейти к примеру одной из возможных его реализаций. Для этого, как и в предыдущем случае, создадим новое приложение, а на форму поместим те же самые компоненты, за исключением редактора значений и кнопки для генерации перестановки. Вместо них используем следующие компоненты: текстовое поле класса TEdit и еще один компонент класса TLabel с соответствующими HMeHaMHedRearrangement и IbRearrangement. Когда вы закончите, то в результате должно получиться нечто подобное изображенному на рис. 12.3.

Рис. 12.3. Интерфейс программы «Транспозиция с фиксированным периодом»

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

Стоит отметить одну неприятную особенность данного шифра. Поскольку период фиксирован, то на текст накладывается определенное ограничение. Оно заключается в том, что длина текста должна быть кратна периоду. Существует несколько вариантов решения данной проблемы. Можно дополнять открытый текст какими-либо символами. И тогда зашифровать сообщение не составит труда. Если эти символы заранее определены, то это облегчит задачу противника по вскрытию шифра. Другой вариант – переписать сообщение, используя, например, синонимы, либо удалив часть сообщения, которую легко восстановить из контекста, таким образом, чтобы длина текста стала кратной периоду.

Теперь перейдем к рассмотрению исходного кода нашего приложения. Как и в прошлый раз, начнем с объявления класса необходимых нам типов, а также класса формы. Соответствующий программный код показан в листинге 12.9. Здесь мы ввели целочисленную константу, ограничивающую длину задаваемого периода. В данном случае она равна 100. Нам понадобится помнить саму перестановку, при помощи которой будет осуществляться транспозиция сообщения, поэтому вводится соответствующий тип.

...

Листинг 12.9.

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

const

MaxTerm = 100;

type

TRearrangement = array [0..MaxTerm] of Integer;

TfmTransposition = class(TForm)

mmDecryptMessage: TMemo;

mmEncryptMessage: TMemo;

lbDecryptMessage: TLabel;

lbEncryptMessage: TLabel;

lbRearrangement: TLabel;

edRearrangement: TEdit;

btnEncryptMessage: TButton;

btnDecpyptMessage: TButton;

procedure btnEncryptMessageClick(Sender: TObject);

procedure btnDecpyptMessageClick(Sender: TObject);

private

{ Private declarations }

Rear: TRearrangement;

function RecalcRearrangement(nKey: Integer): Boolean;

function GetLine(Lines: TStrings;

nRow, nInd: Integer): String;

procedure EncryptDecrypt(SrcLines, DstLines: TStrings;

nKey: Integer);

public

{ Public declarations }

end;

Теперь

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

Функция RecalcRearrangement подготавливает перестановку требуемым образом для шифрования либо дешифрования в зависимости от параметра пКеу, который принимает два значения: 0 и 1. Значение 0 указывает на то, что будет производиться шифрование сообщения и дополнительных действий по подготовке перестановки не требуется, за исключением проверки ее корректности. Значение 1, напротив, указывает на то, что будет производиться дешифрование сообщения и требуется еще дополнительно преобразовать перестановку так, чтобы она была симметрична исходной, в этом случае процесс дешифрования ничем не будет отличаться от процесса шифрования.

Чтобы введенная перестановка считалась корректной, необходимо и достаточно выполнить три следующих требования:

• введены только числа через пробел;

• все числа не повторяются;

• числа находятся в диапазоне от 1 до их общего количества.

Проверка первого условия осуществляется следующим образом. Изначально считается, что в строке идут пробелы. Как только пробелы заканчиваются, предполагается, что началось число, и до тех пор, пока мы опять не встретим пробел, выделяем это число. Как только встретили пробел, пытаемся преобразовать выделенную часть из строкового представления в численное. После этого добавляем полученное число к итоговой перестановке. Когда фрагмент кода, в котором находится первый цикл с условием после него, отработает, в массиве Rear будет храниться введенная перестановка (в Rear [0] хранится количество чисел в полученной перестановке). Сразу за первой проверкой осуществляется совместно вторая и третья, то есть проверяется допустимость самих введенных чисел, а также их уникальность. После всех проверок при необходимости осуществляется преобразование исходной перестановки к симметричной.

Для получения симметричной перестановки стоит выполнить нехитрое действие по обмену местами индексов чисел и сами х чисел, то есть если имеется перестановка 3 1 2, то она преобразуется в 2 3 1, так как 1 стоит на втором месте, 2 – на 3,3 – на 1.

Исходный код данной функции приведен в листинге 12.10.

...

Листинг 12.10.

Функция разбора строки и проверки допустимости перестановки

function TfmTransposition.RecalcRearrangement(nKey: Integer):

Boolean;

var

i: Integer;

s: String;

Space: Boolean;

Used: array [1..MaxTerm] of Boolean;

ExRear: TRearrangement;

begin

Result := False;

Rear[0] := 0;

Space := True;

//выделяем каждое слово, разделенное пробелом,

//и преобразуем его к числу

for i := 1 to Length(edRearrangement.Text) do

if (edRearrangement.Text[i] = \' \') and (not Space) then

begin

Inc(Rear[0]);

Rear[Rear[0]] := StrToInt(s);

Space := True;

end

else

if (edRearrangement.Text[i] <> \' \') then

begin

if Space then

begin

Space := False;

s := \'\

end;

s := s + edRearrangement.Text[i];

end;

if not Space then

begin

Inc(Rear[0]);

Rear[Rear[0]] := StrToInt(s);

end;

//проверяем допустимость полученных чисел

FillChar(Used, SizeOf(Used), False);

for i := 1 to Rear[0] do

if (0 < Rear[i]) and (Rear[i] <= Rear[0])

and not Used[Rear[i]] then

Used[Rear[i]] := True

else

Exit;

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

//для симметричности процесса дешифровки

if nKey = 1 then

begin

ExRear[0] := Rear[0];

for i := 1 to Rear[0] do

ExRear[Rear[i]] := i;

Rear := ExRear;

end;

Result := Rear[0] > 1;

end;

Еще для упрощения алгоритма шифрования необходимо уметь получать часть текста заданной длины, начиная с указанной позиции, в виде одной строки, пропуская все переводы строк. Это действие выполняет следующая описываемая функция. Алгоритм ее работы довольно прост. Изначально в результирующей строке нет ни единого символа. Далее осуществляется двойной вложенный цикл. Цикл верхнего уровня осуществляет изменение значения переменной, начиная с указанной строки до самой последней. Вложенный цикл, в свою очередь, изменяет значение переменной, первый раз начиная с указанной позиции в строке, а в остальных случаях всегда с 1, до длины текущей обрабатываемой строки. Каждый очередной символ добавляется к результирующей строке до тех пор, пока не будет достигнута заданная длина строки, равная периоду транспозиции. Соответствующий код приведен в листинге 12.11.

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

Лорд Системы 8

Токсик Саша
8. Лорд Системы
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Лорд Системы 8

Осознание. Пятый пояс

Игнатов Михаил Павлович
14. Путь
Фантастика:
героическая фантастика
5.00
рейтинг книги
Осознание. Пятый пояс

Академия

Кондакова Анна
2. Клан Волка
Фантастика:
боевая фантастика
5.40
рейтинг книги
Академия

Князь Мещерский

Дроздов Анатолий Федорович
3. Зауряд-врач
Фантастика:
альтернативная история
8.35
рейтинг книги
Князь Мещерский

Огненный князь 5

Машуков Тимур
5. Багряный восход
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Огненный князь 5

Новый Рал 4

Северный Лис
4. Рал!
Фантастика:
попаданцы
5.00
рейтинг книги
Новый Рал 4

Варлорд

Астахов Евгений Евгеньевич
3. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Варлорд

Пропала, или Как влюбить в себя жену

Юнина Наталья
2. Исцели меня
Любовные романы:
современные любовные романы
6.70
рейтинг книги
Пропала, или Как влюбить в себя жену

Инкарнатор

Прокофьев Роман Юрьевич
1. Стеллар
Фантастика:
боевая фантастика
рпг
7.30
рейтинг книги
Инкарнатор

Жена на пробу, или Хозяйка проклятого замка

Васина Илана
Фантастика:
попаданцы
фэнтези
5.00
рейтинг книги
Жена на пробу, или Хозяйка проклятого замка

Холодный ветер перемен

Иванов Дмитрий
7. Девяностые
Фантастика:
попаданцы
альтернативная история
6.80
рейтинг книги
Холодный ветер перемен

Корпулентные достоинства, или Знатный переполох. Дилогия

Цвик Катерина Александровна
Фантастика:
юмористическая фантастика
7.53
рейтинг книги
Корпулентные достоинства, или Знатный переполох. Дилогия

Приручитель женщин-монстров. Том 5

Дорничев Дмитрий
5. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 5

Довлатов. Сонный лекарь

Голд Джон
1. Не вывожу
Фантастика:
альтернативная история
аниме
5.00
рейтинг книги
Довлатов. Сонный лекарь