Одним из ранних вариантов шифра перестановки был разработан
стандартами в 475 году до нашей эры. Он использовал устройство в
виде длинной узкой ленты, которая накручивалась на цилиндр и на
которой сообщение писалось поперек. Лента затем разматывалась и
поставлялась получателю, который имел точно такой же цилиндр. Те-
оретически возможно прочитать ленту без цилиндра, так как буквы
все-таки сохраняют порядок следования. Однако, на практике данный
метод остается только возможным, так как необходимо перепробовать
большое количество различных размеров цилиндров прежде, чем сооб-
щение начинает вырисовываться.
Вы можете создать машинную версию такого шифра, поместив
исходное текстовое сообщение в матрицу одним способом и выведя
его другим способом. Для того, чтобы сделать это, для хранения
кодируемого сообщения используется одновременная строка, но сооб-
щение записывается в дисковый файл в виде матрицы. В нашем вари-
анте исходный текст, представляющий собой строку длиной 100 байт,
записывается на диск, как матрица 5х20. Однако, вы могли бы
использовать матрицу любой другой размерности. Так как сообщение
помещается в матрицу фиксированного размера, то существует веро-
ятность того, что не все элементы матрицы будут использованы. Это
делает необходимым инициализацию матрицы перед помещением в нее
исходного текста. На практике лучше инициализировать матрицу про-
извольными символами, однако, для простоты используется символ
"#".
Если вы поместите сообщение
meet me at sunset
в матрицу, она будет выглядеть следующим образом
¦ m ¦ e ¦ e ¦ t ¦ ¦
+---+---+---+---+---¦
¦ m ¦ e ¦ ¦ a ¦ t ¦
+---+---+---+---+---¦
¦ ¦ s ¦ u ¦ n ¦ s ¦
+---+---+---+---+---¦
¦ e ¦ t ¦ # ¦ # ¦ # ¦
+---+---+---+---+---¦
¦ # ¦ # ¦ # ¦ # ¦ # ¦
Если вы затем осуществите запись матрицы по столбцам, то
сообщение будет выглядеть следующим образом:
mm e...eest...e u...tan... ts
где точки обозначают соответствующее количество символов "#". Для
декодирования сообщения заполняются столбцы матрицы. Затем матри-
ца может быть отображена в нормальном порядке. Программа Skytale
использует данный метод для кодирования и декодирования сообще-
ний:
{шифр skytale}
{ примечание: наибольшее сообщение, которое может быть за-
кодировано, состоит из 100 байт }
program skytale;
type
str100 = string[100];
str80 = string[80];
var
inf, outf:str80;
sky: str100;
t: integer;
ch: char;
procedure code(inf, outf: str80);
var
infile, outfile: file of char;
ch: char;
t, t2: integer;
begin
assign(infile, inf);
reset(infile);
assign(outfile, outf);
rewrite(outfile);
t := 1;
{ считывание текстового файла, как одномерной матрицы }
while (not eof(infile)) and (t<=100) do
begin
Read(infile, sky[t]);
t := t+1;
end;
{ запись в матрицу размера 5х20 }
for t := 1 to 5 do
for t2 := 0 to 19 do
Write(outfile, sky[t+(t2*5)]);
WriteLn('файл закодирован');
close(infile); close(outfile);
end; {code}
procedure decode(inf, outf: str80);
var
infile, outfile: file of char;
ch: char;
t, t2: integer;
begin
assign(infile, inf);
reset(infile);
assign(outfile, outf);
rewrite(outfile);
{ считывание матрицы размером 5х20 }
for t := 1 to 5 do
for t2 := 0 to 19 do
Read(infile, sky[t+(t2*5)]);
{ вывод в качестве строки }
for t := 1 to 100 do Write(outfile, sky[t]);
WriteLn('файл декодирован');
close(infile); close(outfile);
end; {decode}
begin
{ заполнение символов "#" }
for t := 1 to 100 do sky[t] := '#';
Write('введите имя входного файла: ');
ReadLn(inf);
Write('введите имя выходного файла: ');
ReadLn(outf);
Write('кодировать или декодировать (C or D): ');
ReadLn(ch);
if upcase(ch)='C' then code(inf, outf)
else if upcase(ch)='D' then decode(inf, outf);
end.
Существуют другие методы получения перемешанных сообщений.
Один метод, особенно подходящий для компьютера, использует пе-
рестановку букв внутри сообщения с некоторым алгоритмом. Следую-
щая программа перемешивает буквы:
{шифр перемешивания. Длина сообщения не должна превышать
100 символов
program transpose;
type
str100 = string[100];
str80 = string[80];
var
inf, outf: str80;
message: str100;
ch: char;
t: integer;
procedure code(inf, outf: str80);
var
infile, outfile: file of char;
temp: char;
t, t2: integer;
begin
assign(infile, inf);
reset(infile);
assign(outfile, outf);
rewrite(outfile);
t := 1;
while (not eof(infile)) and (t<=100) do begin
Read(infile, message[t]);
t := t+1;
end;
message[t-1] := {удаление знака конца файла }
{ теперь перемешиваются символы }
for t2 := 0 to 4 do
for t := 1 to 4 do
begin
temp := message[t+t2*20];
message[t+t2*20] := message[t+10+t2*20];
message[t+10+t2*20] := temp;
end;
{now write it out}
for t := 1 to 100 do Write(outfile, message[t]);
WriteLn('файл закодирован');
close(infile); close(outfile);
end; {code}
procedure decode(inf, outf: str80);
var
infile, outfile: file of char;
temp: char;
t, t2: integer;
begin
assign(infile, inf);
reset(infile);
assign(outfile, outf);
rewrite(outfile);
t := 1;
while (not eof(infile)) and (t<=100) do
begin
Read(infile, message[t]);
t := t+1;
end;
message[t-1] := '#'; {удаление знака конца файла }
{теперь перемешиваются символы }
for t2 := 0 to 4 do
for t := 1 to 4 do
begin
temp := message[t+t2*20];
message[t+t2*20] := message[t+10+t2*20];
message[t+10+t2*20] := temp;
end;
{ теперь осуществляем вывод }
for t := 1 to 100 do Write(outfile, message[t]);
WriteLn('файл декодирован');
close(infile); close(outfile);
end; {decoded}
begin
for t := 1 to 100 do message[t] := '#';
Write('введите имя входного файла : ');
ReadLn(inf);
Write('введите имя выходного файла : ');
ReadLn(outf);
Write('кодировать или декодировать (C or D): ');
ReadLn(ch);
if upcase(ch)='C' then code(inf, outf)
else if upcase(ch)='D' then decode(inf, outf);
end.
Хотя коды перестановки могут быть эффективными, алгоритмы,
если требуется высокий уровень секретности, становятся очень
сложными.