Описание работы программы Vizhener.

Теоретическая часть.

Шифр Виженера (Chiffre de Vigenère) — метод полиалфавитного шифрования буквенного текста с использованием ключевого слова.

Этот метод является простой формой многоалфавитной замены. Шифр Виженера изобретался многократно. Впервые этот метод описал Джован Баттиста Беллазо (итал. Giovan Battista Bellaso) в книге La cifra del. Sig. Giovan Battista Bellasо в 1553 году, однако в XIX веке получил имя Блеза Виженера, французского дипломата. Метод прост для понимания и реализации, он является недоступным для простых методов криптоанализа.

В шифре Цезаря каждая буква алфавита сдвигается на несколько строк; например в шифре Цезаря при сдвиге +3, A стало бы D, B стало бы E и так далее. Шифр Виженера состоит из последовательности нескольких шифров Цезаря с различными значениями сдвига. Для зашифровывания может использоваться таблица алфавитов, называемая tabula recta или квадрат (таблица) Виженера. Применительно к латинскому алфавиту таблица Виженера составляется из строк по 26 символов, причём каждая следующая строка сдвигается на несколько позиций. Таким образом, в таблице получается 26 различных шифров Цезаря. На разных этапах кодировки шифр Виженера использует различные алфавиты из этой таблицы. На каждом этапе шифрования используются различные алфавиты, выбираемые в зависимости от символа ключевого слова. Например, предположим, что исходный текст имеет вид:

ATTACKATDAWN

Человек, посылающий сообщение, записывает ключевое слово («LEMON») циклически до тех пор, пока его длина не будет соответствовать длине исходного текста:

LEMONLEMONLE

Первый символ исходного текста A зашифрован последовательностью L, которая является первым символом ключа. Первый символ L шифрованного текста находится на пересечении строки L и столбца A в таблице Виженера. Точно так же для второго символа исходного текста используется второй символ ключа; то есть второй символ шифрованного текста X получается на пересечении строки E и столбца T. Остальная часть исходного текста шифруется подобным способом.

Исходный текст: ATTACKATDAWNКлюч: LEMONLEMONLEЗашифрованный текст: LXFOPVEFRNHR

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

Если буквы A-Z соответствуют числам 0-25, то шифрование Виженера можно записать в виде формулы:

Описание работы программы Vizhener. - student2.ru

Расшифровка:

Описание работы программы Vizhener. - student2.ru

Квадрат Виженера, или таблица Виженера, также известная как tabula recta, может быть использована для шифрования и расшифрования.

Описание работы программы Vizhener. - student2.ru

Описание работы программы Vizhener.

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

Интерфейс программы:

Готовность к вводу данных или их загрузке:

Описание работы программы Vizhener. - student2.ru

Введенные данные для шифрования и пароль(активна кнопка «Зашифровать»):

Описание работы программы Vizhener. - student2.ru

Результат нажатия кнопки «Зашифровать»:

Описание работы программы Vizhener. - student2.ru

Введенные данные для дешифрования и пароль(активна кнопка «Расшифровать»):

Описание работы программы Vizhener. - student2.ru

Таблица Виженера с возможностью редактирования алфавита:

Описание работы программы Vizhener. - student2.ru

Листинг программы:

program Vizhener;

uses

Forms,

TablVin in 'TablVin.pas' {Form1};

{$R *.res}

begin

Application.Initialize;

Application.Title := 'ВИЖЕНЕР';

Application.CreateForm(TForm1, Form1);

Application.Run;

end.

unit TablVin;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, Grids, ComCtrls, ExtCtrls, StdCtrls, Buttons, Menus;

type

TForm1 = class(TForm)

PC1: TPageControl;

TabSheet1: TTabSheet;

TabSheet2: TTabSheet;

SG1: TStringGrid;

Panel1: TPanel;

SB1: TSpeedButton;

SB2: TSpeedButton;

SG2: TStringGrid;

PopupMenu1: TPopupMenu;

N1: TMenuItem;

Edit1: TEdit;

Label1: TLabel;

REd1: TMemo;

REd2: TMemo;

SB3: TSpeedButton;

SB4: TSpeedButton;

SB5: TSpeedButton;

SB6: TSpeedButton;

SBar1: TStatusBar;

OD1: TOpenDialog;

SD1: TSaveDialog;

SB7: TSpeedButton;

MainMenu1: TMainMenu;

N2: TMenuItem;

N3: TMenuItem;

Timer1: TTimer;

SpeedButton1: TSpeedButton;

SpeedButton2: TSpeedButton;

procedure FormCreate(Sender: TObject);

procedure N1Click(Sender: TObject);

procedure FormClose(Sender: TObject; var Action: TCloseAction);

procedure Edit1KeyPress(Sender: TObject; var Key: Char);

procedure REd1KeyPress(Sender: TObject; var Key: Char);

procedure SG2KeyPress(Sender: TObject; var Key: Char);

procedure SB1Click(Sender: TObject);

procedure SB2Click(Sender: TObject);

procedure REd2KeyPress(Sender: TObject; var Key: Char);

procedure SB7Click(Sender: TObject);

procedure SB3Click(Sender: TObject);

procedure SB5Click(Sender: TObject);

procedure N3Click(Sender: TObject);

procedure SB4Click(Sender: TObject);

procedure SB6Click(Sender: TObject);

procedure LokBut(Sender: TObject);

procedure SpeedButton1Click(Sender: TObject);

procedure SpeedButton2Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

Const

DopChr = ['a'..'z', '0'..'9'];

var Rez :TStrings; Old1, Old2 :String;

Cont :Set of Char; // Допустимые символы

Form1: TForm1;

Function Det0(Tb :TStringGrid):Boolean;

Function Invert(S :String; N :LongInt):String;

Function KeyR(Tb :TStringGrid; Zn :Char; N :Integer=0):Integer;

Function KeyS(Tb :TStringGrid; Zn :Char; N :Integer=0):Integer;

Function Znak(Tb :TStringGrid; C, R :LongInt):Char;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);

Var ColL :LongInt; Lst :TStrings;

begin

Cont := [];

ColL := 0; // Ноль строк

Lst:=TStringList.Create;

Try

Lst.Clear;

IF FileExists( ExtractFilePath(ParamStr(0))+'Grid.cfg' ) Then

Lst.LoadFromFile( ExtractFilePath(ParamStr(0))+'Grid.cfg' );

ColL := Lst.Count;

Finally

SG2.RowCount := ColL;

Lst.Free;

End;

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

SG1.Visible:=False;

PC1.ActivePage:=TabSheet2;

IF FileExists(ExtractFilePath(ParamStr(0))+'Grid.cfg') Then

SG2.Cols[0].LoadFromFile(ExtractFilePath(ParamStr(0))+'Grid.cfg');

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Sg1.ColCount := ColL;

Sg1.RowCount := Sg1.ColCount;

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

N1.Click;

IF(REd1.Lines.Count>0)OR(REd2.Lines.Count>0)Then SB7.Enabled:=True ELSE

SB7.Enabled:=False;

end;

Function Det0(Tb :TStringGrid):Boolean;

VAR R :LongInt; //Заполненость таблицы

begin

Det0:=True;

For R:=0 To Tb.RowCount-1 Do

IF Tb.Cells[0, R]='' Then

begin

Det0:=True;

ShowMessage('ЗАПОЛНИТЕ ВСЁ!'); Break;

end ELSE Det0:=False;

end;

procedure TForm1.N1Click(Sender: TObject);

Var R,I :LongInt; Ms, Sd :String;

begin

IF Det0(SG2) Then Exit;

//=============================================== Фильтр символов

Cont := [];

For I:=0 To Sg2.RowCount - 1 Do

begin

Cont := Cont + [ Znak(Sg2, 0, I) ];

end;

//===============================================

PC1.Enabled:=False;

Ms:='';

For I:=0 To Sg2.RowCount-1 Do

MS:=MS+SG2.Cells[0, I];

For R:=0 To SG1.RowCount-1 Do

begin

SG1.Rows[R].Clear;

Sd:=Invert(MS, R);

For I:=1 to Length(Sd) Do

SG1.Rows[R].Add( Sd[I] );

end;

PC1.Enabled:=True;

end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

begin

IF Det0( Sg2 ) = False Then

SG2.Cols[0].SaveToFile(ExtractFilePath(ParamStr(0))+'Grid.cfg');

end;

Function Invert(S :String; N :LongInt):String;

Var S1,S2, Sum :String;

begin

IF(S='')OR(N>Length(S))Then Exit;

///////////////////////////

Try

IF N>0 Then

begin

S1:=''; S2:='';

S1:=Copy(S, 1, N);

S2:=Copy(S, N+1, Length(S)-N);

Sum:=S2+S1;

Invert:=Sum;

end ELSE

IF N<=0 Then

Begin

Invert:=S;

End;

Except

ShowMessage('ВНУТРЕНЯЯ ОШИБКА!'); Exit;

End;

end;

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);

begin

CASE Key OF

'А'..'Я',#8,#9: ;

'а'..'я', 'a'..'z': Key:=Chr(Ord(Key)-32);

'ё','Ё': Key:='Ё';

// ELSE Key:=#0;

End;

IF Not (Key in Cont) Then Key:=#0;

end;

procedure TForm1.REd1KeyPress(Sender: TObject; var Key: Char);

begin

CASE Key OF

'А'..'Я',#8,#9,#13,#10,' ': ;

'а'..'я', 'a'..'z': Key:=Chr(Ord(Key)-32);

'ё','Ё': Key:='Ё';

'0'..'9': ;

End;

end;

procedure TForm1.REd2KeyPress(Sender: TObject; var Key: Char);

begin

CASE Key OF

'А'..'Я',#8,#9,#13,#10,' ': ;

'а'..'я', 'a'..'z': Key:=Chr(Ord(Key)-32);

'ё','Ё': Key:='Ё';

'0'..'9': ;

// ELSE Key:=#0;

End;

end;

procedure TForm1.SG2KeyPress(Sender: TObject; var Key: Char);

begin

CASE Key OF

'А'..'Я',#8,#9,#13,#10,' ': ;

'а'..'я', 'a'..'z': Key:=Chr(Ord(Key)-32);

'ё','Ё': Key:='Ё';

'0'..'9': ;

// ELSE Key:=#0;

End;

end;

Function KeyR(Tb :TStringGrid; Zn :Char; N :Integer=0):Integer;

Var R :LongInt; // ОБЩЕЕ: сканер столбцов

begin // Определение номера строки ключа " 1-ый столбец "

Result:=0;

For R:=0 To Tb.RowCount-1 Do

begin

Application.ProcessMessages();

IF Tb.Cells[N, R]=Zn Then Begin Result:=R; Break; End;

end;

end;

Function KeyS(Tb :TStringGrid; Zn :Char; N :Integer=0):Integer;

Var C :LongInt; // ОБЩЕЕ: сканер строк

begin // Определение номера столбца

Result:=0;

For C:=0 To Tb.ColCount-1 Do

begin

Application.ProcessMessages();

IF Tb.Cells[C, N]=Zn Then Begin Result:=C; Break; End;

end;

end;

Function Znak(Tb :TStringGrid; C, R :LongInt):Char;

begin //

Result:=Tb.Cells[C, R][1];

end;

procedure TForm1.SB1Click(Sender: TObject);

Var I,J,K :LongInt; Key,Txt, Oyt :String; Ch :Char; A,B :Longint;

begin // ШИФРУЕТ

IF Edit1.Text='' Then Exit;

Timer1.Enabled:=False;

SB1.Enabled:=False;

SB2.Enabled:=False;

Edit1.Enabled:=False;

REd2.Enabled:=False;

REd1.Enabled:=False;

Key:=Edit1.Text;

J:=1;

REd2.Lines.Clear; //Чистка

FOR K:=0 To REd1.Lines.Count-1 Do

Begin Oyt:='';

Txt:=REd1.Lines.Strings[ K ]; //Грузим строку

For I:=1 To Length(Txt{REd1.Lines.Text})Do

begin

Application.ProcessMessages(); //

///////////////////////////////

IF {REd1.Lines.Text[I]}Txt[I] in Cont{['А'..'Я','Ё']} Then

Begin

Ch:=Key[J];

A:=KeyR(SG1, Ch, 0) ; // Ищем номер символа ключа в столбце

Ch:=Txt[I]; //REd1.text[I];

B:=KeyS(SG1, Ch, 0) ; // Ищем номер символа текста в строке

//REd2.Text:=REd2.Text+Znak(SG1, B, A);

Oyt:=Oyt+Znak(SG1, B, A);

IF J<=Length(Key)-1 Then J:=J+1 ELSE J:=1; //Перебор Ключа

End ELSE

Begin //

Ch:=Txt[ I ];

//REd2.Text:=REd2.Text+Ch;

Oyt:=Oyt+Ch;

End;

///////////////////////////////

end;

REd2.Lines.Add(Oyt);

End;

SB1.Enabled:=True;

SB2.Enabled:=True;

Edit1.Enabled:=True;

Timer1.Enabled:=True;

REd2.Enabled:=True;

REd1.Enabled:=True;

end;

procedure TForm1.SB2Click(Sender: TObject);

Var I,J,K :LongInt; Key,Txt, Oyt :String; Ch :Char; A,B :Longint;

begin // РАСШИФРОВЫВАЕМ

IF Edit1.Text='' Then Exit;

Timer1.Enabled:=False;

SB1.Enabled:=False;

Edit1.Enabled:=False;

REd2.Enabled:=False;

REd1.Enabled:=False;

REd1.Clear; //Чистим

Key:=Edit1.Text;

J:=1;

For K:=0 To REd2.Lines.Count-1 Do

Begin Oyt:='';

Txt:=REd2.Lines.Strings[K];

Application.ProcessMessages(); //

For I:=1 To Length( Txt ) DO

Begin

Application.ProcessMessages();

//////////////////////////////

IF Txt[I] IN Cont{['А'..'Я','Ё']} Then

Begin

Ch:=Key[J];

A:=KeyR(SG1, Ch, 0) ; // Ищем номер символа ключа в столбце

Ch:=Txt[I]; //REd2.text[I];

B:=KeyS(SG1, Ch, A) ; // Ищем номер символа текста в строке " Main "

//REd1.Text:=REd1.Text+Znak(SG1, B, 0);

Oyt:=Oyt+Znak(SG1, B, 0);

IF J<=Length(Key)-1 Then J:=J+1 ELSE J:=1; //Перебор Ключа

End ELSE

Begin

Ch:=Txt[ I ];

//REd1.Text:=REd1.Text+Ch;

Oyt:=Oyt+Ch;

End;

//////////////////////////////

End;

REd1.Lines.Add(Oyt);

End;

SB1.Enabled:=True;

SB2.Enabled:=True;

Edit1.Enabled:=True;

Timer1.Enabled:=True;

REd2.Enabled:=True;

REd1.Enabled:=True;

end;

procedure TForm1.SB7Click(Sender: TObject);

begin // Удалить всё

IF REd1.Lines.Count>0 Then REd1.Clear;

IF REd2.Lines.Count>0 Then REd2.Clear;

SB7.Enabled:=False; SB1.Enabled:=False;

SB2.Enabled:=False; SB4.Enabled:=False;

SB6.Enabled:=False;

SBar1.Panels[0].Text:='';

SBar1.Panels[1].Text:='';

end;

procedure TForm1.SB3Click(Sender: TObject);

begin

OD1.Title:='Открыть исходный текст ...';

IF OD1.Execute Then

Begin

SBar1.Panels[0].Text:=ExtractFileName( OD1.FileName );

Old1:=OD1.FileName;

Application.ProcessMessages(); //

Try

SD1.FileName:=Old1;

REd1.Lines.LoadFromFile( Old1 );

Except

BEEP; ShowMessage('Нет доступа к: '+Old1);

SBar1.Panels[0].Text:=''; SD1.FileName:='';

End;

OD1.FileName:='';

End;

end;

procedure TForm1.SB5Click(Sender: TObject);

begin

OD1.Title:='Открыть шифрованный текст ...';

IF OD1.Execute Then

Begin

SBar1.Panels[1].Text:=ExtractFileName( OD1.FileName );

Old2:=OD1.FileName;

Application.ProcessMessages(); //

Try

REd2.Lines.LoadFromFile( Old2 );

Except

BEEP; ShowMessage('Нет доступа к: '+Old2);

SBar1.Panels[1].Text:='';

End;

OD1.FileName:='';

End;

end;

procedure TForm1.N3Click(Sender: TObject);

begin

SG1.Visible:=Not SG1.Visible;

end;

procedure TForm1.SB4Click(Sender: TObject);

Label 0;

begin

SD1.Title:='Сохранить Исходный текст как ...';

IF SBar1.Panels[0].Text='' Then

Begin

0 : IF SD1.Execute Then

begin

Old1:=SD1.FileName;

Application.ProcessMessages();

REd1.Lines.SaveToFile( Old1 );

SBar1.Panels[0].Text:=ExtractFileName( Old1 );

end;

End ELSE

IF MessageBox(Handle, PChar( 'Если хотите использовать имеющийся путь'+

#13+'"'+Old1+'"'+

#13' Нажмите " Да ".' ), 'Сохранение',

MB_YESNO+MB_ICONINFORMATION)=MrYes Then

REd1.Lines.SaveToFile(Old1) ELSE GoTo 0;

//SBar1.Panels[0].Text

SD1.FileName:='';

end;

procedure TForm1.SB6Click(Sender: TObject);

Label 1;

begin

SD1.Title:='Сохранить Зашифрованный текст как ...';

IF SBar1.Panels[1].Text='' Then

Begin

1: IF SD1.Execute Then

begin

Old2:=SD1.FileName;

Application.ProcessMessages();

REd2.Lines.SaveToFile( Old2 );

SBar1.Panels[1].Text:=ExtractFileName( Old2 );

end;

End ELSE

IF MessageBox(Handle, PChar( 'Если хотите использовать имеющийся путь'+

#13+'"'+Old2+'"'+

#13' Нажмите " Да ".' ), 'Сохранение',

MB_YESNO+MB_ICONINFORMATION)=MrYes Then

REd2.Lines.SaveToFile( Old2 ) ELSE GoTo 1;

//SBar1.Panels[0].Text

SD1.FileName:='';

end;

procedure TForm1.LokBut(Sender: TObject);

begin // Проверка текстовых полей

IF REd1.Lines.Count>0 Then

begin

SB1.Enabled:=True;

SB4.Enabled:=True;

end ELSE

IF REd1.Lines.Count<=0 Then

begin

SB1.Enabled:=False;

SB4.Enabled:=False;

end;

IF REd2.Lines.Count>0 Then

begin

SB2.Enabled:=True;

SB6.Enabled:=True;

end ELSE

IF REd2.Lines.Count<=0 Then

begin

SB2.Enabled:=False;

SB6.Enabled:=False;

end;

IF(REd1.Lines.Count>0)OR(REd2.Lines.Count>0)Then SB7.Enabled:=True ELSE

SB7.Enabled:=False;

TabSheet1.Caption:=Format('Таблица - [R=%d, C=%d]',

[SG1.RowCount, SG1.ColCount])

end;

// МЕТОДЫ ДЛЯ " STRINGGRID "

procedure DelCol(SG: TStringGrid);

Var I, J :LongInt;

begin // Удалить колонку

with SG do

begin

J := ColCount - 1;

Cols[ J ].Clear;

for I:=J to ColCount - 2 do

Cols[ I ].Assign( Cols[ I+1 ] );

ColCount := ColCount - 1;

end;

end;

procedure DelRow(SG: TStringGrid);

Var I, J :LongInt;

begin // Удалить строку

with SG do

begin

J := RowCount - 1; // Последняя строка

Rows[ J ].Clear;

for I:=J to RowCount - 2 do

Rows[I].Assign( Rows[ I+1 ] );

RowCount := RowCount - 1;

end;

end;

procedure InsRow(SG: TStringGrid);

begin // Вставка строки

With SG do

RowCount := RowCount + 1;

end;

procedure InsCol(StrGrid: TStringGrid);

begin // Вставка колонок

StrGrid.ColCount := StrGrid.ColCount + 1;

end;

procedure TForm1.SpeedButton1Click(Sender: TObject);

begin // Добавить Строку для символов

IF SG2.RowCount<256 Then

begin

InsRow( Sg2 );

InsRow( Sg1 );

InsCol( SG1 );

end ELSE Beep;

end;

procedure TForm1.SpeedButton2Click(Sender: TObject);

begin // Удалить Строку для символов

IF Sg2.RowCount>33 Then

Begin

DelRow( Sg2 );

DelRow( Sg1 );

DelCol( SG1 );

End ELSE Beep;

end;

end.

Наши рекомендации