Шифрование в DELPHI
Материал из DRKB
Шифрование в DELPHI
Данные надо беречь. Сам посуди, обидно, если открытие ценой в сто миллионов енотов или рецепт безалкогольной водки, над которым ты корпел три вечера в мрачном подвале нелегального компьютерного клуба, уплывет к злостному ленивому конкуренту, который, пользуясь твоим похмельем, наложил грязную лапу на приватные дискеты с ценнейшей инфой?! Дальше можно не продолжать. Шифруем, шифруем, шифруем!..
Добрый дядюшка borland предоставил нам несколько занятных функций для работы со строками, о которых не все знают. Сосредоточены они в модуле strutils.pas.
Такие функции, как RightStr(), LeftStr() совмещают стандартные команды Copy() и Delete(): так, LeftStr() возвращает значение левой части строки до указанной вами позиции (что вытворяет RightStr(), догадайся сам), а функция ReverseString() и вовсе делает зеркальное отображение данной строки: 321 вместо 123. Используем ее в особенности, чтобы осложнить жизнь хитрому дешифровщику.
Алгоритм шифрования будет прост, как win 3.1. С каждым символом кодируемого документа проделаем следующее:
- 1. Преобразуем символ в число командой Ord.
- 2. Преобразуем каждый символ пользовательского пароля в число и сумму этих чисел прибавим к полученному в пункте 1.
- 3. От результата отнимаем число, равное позиции данного символа. То есть буковки будут шифроваться по-разному в зависимости от их позиции в строке :).
- 4. То, что получилось, запишем обратно из чисел в символы командой Chr. Как видишь, после всех наших манипуляций этот символ уже будет другим.
- 5. Запишем всю строку навыворот командой ReverseString.
Дешифровка, как ты догадываешься, будет производиться в обратном порядке.
Теперь, когда алгоритм намертво засел в голове, реализуем соответствующую программу.
Внимание! Не исключено, что это будет первая твоя программа с настоящим синтаксисом команд:
<команда> <путь> <пароль>
- так будет выглядеть он в консоли нашего приложения (да, оно будет консольным!). Команд всего две: crypt и decrypt соответственно зашифровать и дешифровать файл, путь к которому указывается после пробела, а затем - твой пароль. НЕ ЗАБУДЬ ЕГО! Предупреждаю совершенно серьезно. Запомнил? В бой!
crypt c:\file.txt linuxmustsurvive
- закодируем file.txt.
Результат (зашифрованный текст) сохраниться в той же директории, что и исполняемый файл нашего приложения под именем translated_file.txt.
decrypt c:\translated_file.txt linuxmustsurvive
- дешифровка.
Реализовывается это вот как:
program crypter;
{$apptype console}
uses
sysutils,
strutils; //!!
var
f, // входящий файл
f1: TextFile; // результат (файл с переводом)
todo, Filename, passw, line, TranslatedFile: string;
Position, IsCrypt: Integer;
// находим сумму числовых значений символов пароля
function Password(psw: string): Integer;
var
i: Integer;
begin
Result := 0;
for i:=1 to Length(psw) do
Result := Result + Ord(psw[i]);
end;
function Crypt(CryptStr: string): string;
var
s: string;
i: Integer;
begin
Result := '';
if CryptStr = EmptyStr then Exit;
for i := 1 to Length(CryptStr) do
begin
s := LeftStr(CryptStr, 1);
CryptStr := RightStr(CryptStr, Length(CryptStr)-1);
// ШИФРОВКА:
s := Chr(Ord(s[1]) + Password(passw)-i);
Result := Result + s;
end;
Result := ReverseString(Result);
end;
function Decrypt(DecryptStr: string): string;
var
i: Integer;
s: string;
begin
Result := '';
DecryptStr := ReverseString(DecryptStr);
if DecryptStr = EmptyStr then Exit;
for i := 1 to Length(DecryptStr) do
begin
s := LeftStr(DecryptStr, 1);
DecryptStr := RightStr(DecryptStr, Length(DecryptStr)-1);
// ДЕШИФРОВКА:
Result := Result + Chr(Ord(s[1]) - Password(passw)+i);
end;
end;
begin
while True do
begin
IsCrypt := 0;
WriteLn(#10 + 'crypter >' + #10);
// Какую команду ввел юзер?
ReadLn(todo);
if LowerCase(todo) = 'exit' then exit;
if AnsiContainsText(todo, 'decrypt') then
IsCrypt := 1
else if AnsiContainsText(todo, 'crypt') then
IsCrypt := 2;
// прочитав команду, удаляем ее из строки и читаем дальше
Position := Pos(' ', todo);
if Position > 0 then
todo := RightStr(todo, Length(todo) - Position);
// Читаем путь к файлу
Position := Pos(' ', todo);
if Position > 0 then
FileName := LeftStr(todo, Position-1);
// Читаем пароль
passw := RightStr(todo, Length(todo) - Position);
// Всё правильно? Начинаем!
if (IsCrypt <= 0) or (passw = EmptyStr)
or (not FileExists(FileName)) then
WriteLn('wrong command')
else
begin
TranslatedFile := ExtractFilePath(ParamStr(0)) +
'translated_' + ExtractFileName(FileName);
// соединяемся с файлами
AssignFile(f, FileName);
AssignFile(f1, TranslatedFile);
// переходим в начало файла
Rewrite(f1);
Reset(f);
// читаем строки, пока не дойдем до конца файла
while not Eof(f) do
begin
// читаем из переводимого файла
ReadLn(f, line);
if IsCrypt = 1 then line := Decrypt(line);
if IsCrypt = 2 then line := Crypt(line);
// записываем в файл с переводом
WriteLn(f1, line);
end;
// отсоединяемся от файлов
CloseFile(f);
CloseFile(f1);
end;
end;
end.
Вот, собственно, и всё. Еще раз напоминаю, что результат (файл с переводом) сохранится В ТОЙ ЖЕ ДИРЕКТОРИИ, что и наше приложение, а не в той, где лежит исходный файл. В заключение процитирую отрывок из статьи «Криптография в c++» в номере 3.03 журнала «Хакер»:
//(с) Николай «gorlum» Андреев
Но я хочу тебя предупредить: в нашей стране, согласно указу № 334 от 1995 года, производить и распространять любые шифрующие средства можно, только имея лицензию ФАПСИ. Соответственно, шифровать нельзя :). Поэтому пиши программы только для личного пользования и только в познавательных целях.
Author: Трофим Роцкий
ID: 03983