| как пройти тест 9 |
Блокнот - шифратор
Откройте любой редактор текстов, хотя бы тот же стандартный Блокнот Windows. Скопируйте в него нижеследующий листинг, строки
//------ Начало модуля ---------
//------- Конец модуля ---------
копировать в модуль не нужно они только обозначают границы листинга этого кода:
//------ Начало модуля ---------
{ **** UBPFD *********** by delphibase.endimus.com ****
>> Шифрование и дешифрование текстов по принципу S-Coder со скрытым ключом
После подключения модуля ключевое слово (фраза) будут в MyCript.MyPassword;
Шифровать примерно так:
Memo1.Text:= MyCript.Write(MyCript.Encrypt(Memo1.Text));
Дешифровать примерно так:
Memo1.Text:= MyCript.Decrypt(MyCript.Read(Memo1.Text));
Copyright: EFD Systems http://www.mindspring.com/~efd
Дата: 23 мая 2002 г.
***************************************************** }
unit MyCript;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils;
//Это просто интерфейс функций EnCipher и Crypt для шифрования строки текста:
function Encrypt(text: Ansistring): Ansistring;
//Это просто интерфейс функций EnCipher и Crypt для дешифрования строки текста:
function Decrypt(text: Ansistring): Ansistring;
function Write(text: Ansistring): Ansistring;
function Read(text: Ansistring): Ansistring;
var
MyPassword: AnsiString; //здесь будет пароль
implementation
procedure EnCipher(var Source: AnsiString);
{Low order, 7-bit ASCII (char. 32-127) encryption designed for database use.
Control and high order (8 bit) characters are passed through unchanged.
Uses a hybrid method...random table substitution with bit-mangled output.
No passwords to worry with (the built-in table is the password). Not industrial
strength but enough to deter the casual hacker or snoop. Even repeating char.
sequences have little discernable pattern once encrypted.
NOTE: When displaying encrypted strings, remember that some characters
within the output range are interpreted by VCL components; for
example, '&'.}
begin
{$asmmode intel}
asm
Push ESI //Save the good stuff
Push EDI
Or EAX,EAX
Jz @Done
Push EAX
Call UniqueString
Pop EAX
Mov ESI,[EAX] //String address into ESI
Or ESI,ESI
Jz @Done
Mov ECX,[ESI-4] //String Length into ECX
Jecxz @Done //Abort on null string
Mov EDX,ECX //initialize EDX with length
Lea EDI,@ECTbl //Table address into EDI
Cld //make sure we go forward
@L1:
Xor EAX,EAX
Lodsb //Load a byte from string
Sub AX,32 //Adjust to zero base
Js @Next //Ignore if control char.
Cmp AX,95
Jg @Next //Ignore if high order char.
Mov AL,[EDI+EAX] //get the table value
Test CX,3 //screw it up some
Jz @L2
Rol EDX,3
@L2:
And DL,31
Xor AL,DL
Add EDX,ECX
Add EDX,EAX
Add AL,32 //adjust to output range
Mov [ESI-1],AL //write it back into string
@Next:
Dec ECX
Jnz @L1
// Loop @L1 //do it again if necessary
@Done:
Pop EDI
Pop ESI
Jmp @Exit
// Ret //this does not work with Delphi 3 - EFD 971022
@ECTbl: //The encipher table
DB 75,85,86,92,93,95,74,76,84,87,91,94
DB 63,73,77,83,88,90,62,64,72,78,82,89
DB 51,61,65,71,79,81,50,52,60,66,70,80
DB 39,49,53,59,67,69,38,40,48,54,58,68
DB 27,37,41,47,55,57,26,28,36,42,46,56
DB 15,25,29,35,43,45,14,16,24,30,34,44
DB 06,13,17,23,31,33,05,07,12,18,22,32
DB 01,04,08,11,19,21,00,02,03,09,10,20
@Exit:
end;//asm
end;
procedure DeCipher(var Source: AnsiString);
{Decrypts a string previously encrypted with EnCipher.}
begin
{$asmmode intel}
asm
Push ESI //Save the good stuff
Push EDI
Push EBX
Or EAX,EAX
Jz @Done
Push EAX
Call UniqueString
Pop EAX
Mov ESI,[EAX] //String address into ESI
Or ESI,ESI
Jz @Done
Mov ECX,[ESI-4] //String Length into ECX
Jecxz @Done //Abort on null string
Mov EDX,ECX //Initialize EDX with length
Lea EDI,@DCTbl //Table address into EDI
Cld //make sure we go forward
@L1:
Xor EAX,EAX
Lodsb //Load a byte from string
Sub AX,32 //Adjust to zero base
Js @Next //Ignore if control char.
Cmp AX,95
Jg @Next //Ignore if high order char.
Mov EBX,EAX //save to accumulate below
Test CX,3 //unscrew it
Jz @L2
Rol EDX,3
@L2:
And DL,31
Xor AL,DL
Add EDX,ECX
Add EDX,EBX
Mov AL,[EDI+EAX] //get the table value
Add AL,32 //adjust to output range
Mov [ESI-1],AL //store it back in string
@Next:
Dec ECX
Jnz @L1
// Loop @L1 //do it again if necessary
@Done:
Pop EBX
Pop EDI
Pop ESI
Jmp @Exit
// Ret Does not work with Delphi3 - EFD 971022
@DCTbl: //The decryption table
DB 90,84,91,92,85,78,72,79,86,93,94,87
DB 80,73,66,60,67,74,81,88,95,89,82,75
DB 68,61,54,48,55,62,69,76,83,77,70,63
DB 56,49,42,36,43,50,57,64,71,65,58,51
DB 44,37,30,24,31,38,45,52,59,53,46,39
DB 32,25,18,12,19,26,33,40,47,41,34,27
DB 20,13,06,00,07,14,21,28,35,29,22,15
DB 08,01,02,09,16,23,17,10,03,04,11,05
@Exit:
end;//asm
end;
procedure Crypt(var Source: Ansistring; const Key: AnsiString);
{Encrypt AND decrypt strings using an enhanced XOR technique similar to
S-Coder (DDJ, Jan. 1990). To decrypt, simply re-apply the procedure
using the same password key. This algorithm is reasonably secure on
it's own; however,there are steps you can take to make it even more
secure.
1) Use a long key that is not easily guessed.
2) Double or triple encrypt the string using different keys.
To decrypt, re-apply the passwords in reverse order.
3) Use EnCipher before using Crypt. To decrypt, re-apply Crypt
first then use DeCipher.
4) Some unique combination of the above
NOTE: The resultant string may contain any character, 0..255.}
begin
{$asmmode intel}
asm
Push ESI //Save the good stuff
Push EDI
Push EBX
Or EAX,EAX
Jz @Done
Push EAX
Push EDX
Call UniqueString
Pop EDX
Pop EAX
Mov EDI,[EAX] //String address into EDI
Or EDI,EDI
Jz @Done
Mov ECX,[EDI-4] //String Length into ECX
Jecxz @Done //Abort on null string
Mov ESI,EDX //Key address into ESI
Or ESI,ESI
Jz @Done
Mov EDX,[ESI-4] //Key Length into EDX
Dec EDX //make zero based
Js @Done //abort if zero key length
Mov EBX,EDX //use EBX for rotation offset
Mov AH,DL //seed with key length
Cld //make sure we go forward
@L1:
Test AH,8 //build stream char.
Jnz @L3
Xor AH,1
@L3:
Not AH
Ror AH,1
Mov AL,[ESI+EBX] //Get next char. from Key
Xor AL,AH //XOR key with stream to make pseudo-key
Xor AL,[EDI] //XOR pseudo-key with Source
Stosb //store it back
Dec EBX //less than zero ?
Jns @L2 //no, then skip
Mov EBX,EDX //re-initialize Key offset
@L2:
Dec ECX
Jnz @L1
@Done:
Pop EBX //restore the world
Pop EDI
Pop ESI
end;//asm
end;
function Encrypt(text: Ansistring): Ansistring;
//Это просто интерфейс функций EnCipher и Crypt для шифрования строки текста
begin
{шифруем текст}
EnCipher(Text);
{зашифровываем ключом}
Crypt(Text, MyPassword);
Result := Text;
end;
function Decrypt(text: Ansistring): Ansistring;
//Это просто интерфейс функций EnCipher и Crypt для дешифрования строки текста
begin
{расшифровываем ключом}
Crypt(Text, MyPassword);
{расшифровываем результат}
DeCipher(Text);
Result := Text;
end;
function Write(text: Ansistring): Ansistring;
var
i: integer;
begin
Result := '';
for i := 1 to Length(text) do
{получаем hex код из текста}
Result := Result + InttoHex(ord(text[i]), 2);
end;
function Read(text: Ansistring): Ansistring;
var
i: integer;
begin
Result := '';
for I := 1 to Length(text) do
if odd(i) then
{получаем текст из hex кода}
Result := Result + Chr(StrtoInt('$' + text[i] + text[i + 1]));
end;
end.
//------- Конец модуля ---------
Листинг
.
Сохраните модуль в файл MyCript.pas туда, куда вы решили собирать свою коллекцию модулей. Не забудьте скопировать этот файл в папку с нашим текущим проектом.
Также в Редакторе кода нашей программы добавьте модуль MyCript в раздел uses, в конец списка подключаемых модулей.
Теперь можем приступить непосредственно к кодированию команд. Вы помните, что чтобы сгенерировать команду OnClick пункта меню, достаточно выбрать эту команду? Тогда начнем с более простых пунктов меню. Самым первым обработаем пункт "Формат->Перенос по словам":
procedure TfMain.FormatWordWrapClick(Sender: TObject);
begin
//изменяем меню:
FormatWordWrap.Checked:= not FormatWordWrap.Checked;
//присваиваем настройку Memo1:
Memo1.WordWrap:= FormatWordWrap.Checked;
//если перенос по словам включен, нужна только вертикальная
//линейка прокрутки, иначе нужны обе линейки:
if Memo1.WordWrap then Memo1.ScrollBars:= ssVertical
else Memo1.ScrollBars:= ssBoth;
end;
Мы с вами установили по умолчанию, что текст в Memo1 переносится по словам, а данный пункт меню отмечен флажком. При выборе этой команды происходит обратное действие: состояние Checked пункта меню меняется на противоположное, состояние WordWrap компонента Memo1 становится таким же. То есть, если флажок установлен, то и перенос будет работать, и наоборот. В заключение мы устанавливаем нужное состояние полос прокрутки. Если перенос работает, то горизонтальная полоса не нужна, только вертикальная. Если же переноса нет, то строка может получиться очень длинной, тут понадобятся обе полосы прокрутки.