Форум   Статьи   Новости   Файлы   Bugtraq   Сниффер   Друзья   О Клубе
  , 08:54   #1
;)
 
Аватар для pwcode
 
Локация: hpc.name
Регистрация: 04.06.2013
Сообщений: 283

Репутация: 110 / 2
Smile Пишем шифратор файлов

Выражаю огромную благодарность XaVis'у за помощь и разъяснение многих вещей. Если ты это читаешь, то спасибо ещё раз

Поехали!
Первым делом прикинем в голове общий план будущей программы: первое - это возможность шифровать файл с помощью 2-х методов: 1) по ключу; 2) с помощью ключевого файла. На выбор пользователя.

Теперь внимание на форму программы:

IMAGE http://www.pwcode.net/uploads/posts/2013-08/1377188152_bezymyannyy.png
3 edit'a, 4 button'a, 1 richedit и 2 radiobutton'а.

Надо понимать, что XOR (а именно он и шифрует) использует ключ (что и есть пароль) и шифрует файл непосредственно с помощью него. Для первого варианта шифровки ключ обязателен, ведь шифрование идёт напрямую связанное с паролем.

Скелет в шкафу номер 1.
Дело в том, что считывая байты программы, которую собираемся шифровать, мы получаем огромное количество символов и букв, заключённых в массив. Сначала я , использую публичную функцию криптовки XOR'ом, задавал огромный ключ и радовался тому, что программа ничерта не работала. Но потом мне объяснили, что т.к. каждый байт состоит из 2-х символов, его нельзя шифровать ключём более 2-х символов! Но какая-же это тогда шифровка? Тогда и ключ будет вычислить несложно, скажешь ты. И будешь прав, поэтому единственный целесообразный способ зашифровать массив длинным ключём - это разграничить каждый байт массива (помним, что это 2 символа) и каждые 2 символа ключа, и зашифровать их друг с другом:

IMAGE http://www.pwcode.net/uploads/posts/2013-08/1377107437_bezymyannyy.png

Т.е. каждые 2 символа массива шифруются попарно с каждыми двумя символами ключа. Вот и весь процесс. Тогда и ключ можно будет задать длинный (32, 64, 128 бит) и достать его будет сложней. Но что же будет, если ключ неожиданно закончится, а массив ещё продолжается? Не шифровать же половину массива? Конечно нет. Если ключ закончится - его мы начнём с начала. Что бы всё это реализовать - достаточно несколько строчек кода и несколько переменных:

Delphi highlight
var

    CryptFilePath : string; // переменная пути файла который шифруется
    KeyFilePath : string;  //переменная пути ключевого файла


    USerKey : string; // ключ, генерированный программой
    fCrypt, fKey: file; // переменный файла который шифруется и ключевого файла
    arr, arrKeyFile: array of Byte; // переменный массивов, куда считываются байты из файлов.
    Size, pos1, pos2, _key, sizekeyFile, t: longint; 
    _StrKey : string  ;

// Сразу приведу функцию, которая будет сохранять массив байтов в файл:
function SaveBinArrayToFile(AFileName:string; ABuf:array of byte):boolean;
var
  fs:TFileStream;
  n:integer;
begin

  fs:=TFileStream.Create(AFileName, fmCreate);
  try
    fs.Position := 0;
    n := Length(ABuf);
    fs.Write(ABuf, n);
  finally
    fs.Free;
  end;
end;

// Процедура генерации 32-х битного ключа:

procedure TForm1.Button2Click(Sender: TObject); // тут всё понятно
var
i: integer;
begin
randomize;
txtKey.Clear;
for i := 1 to 32 do
 txtKey.Text:=txtKey.Text+IntToStr(random(9));
end;

// Открытие файла, который будем шифровать:
AssignFile(fCrypt,CryptFilePath); // привязка переменной к пути и имени файла
Reset(fCrypt,1); // разрешаем файл для чтения и редактирования с блоком чтения в 1 байт
size:= FileSize(fCrypt); // в переменную size ложится размер файла (кол-во байт)
SetLength(arr,size); // присваивание массиву ARR данного размера
BlockRead(fCrypt,arr[0],size); // читаем байты из файла FCrypt, ложим в массив ARR, начиная с [0]-ого элемента, читаем количество байт равное SIZE
CloseFile(fCrypt); // закрываем файл после чтения

Процедура Шифрования файла по ключу:
procedure TForm1.EncryptedKey;
var i: integer;
  begin
  UserKey:= txtKey.Text;  // Userkey - переменная типа String, куда ложится ключ генерированный программой
    Pos1:=1;  // Переменная позиции (будет определять позицию символа в ключе)

         //Шифрование файла по ключу
         for i := 1 to length(arr) do  // перебираем байты файла который будет зашифрован
          begin
             if pos1>= length(UserKey) then  pos1:=1; // если позиция символа в ключе меньше или равна длине ключе (т.е. достигла конца ключа, то позиция равна 1, т.е. начинается с начала) 

            _StrKey:= UserKey[pos1]+UserKey[pos1+1]  ; // _StrKey = символу ключа pos1 и следующему символу (pos1+1)
            _key:=StrToInt(_StrKey); // _key = 2-м символам взятым выше
            arr[i]:=arr[i] xor _key; // шифруется i-товый байт массива (2 символа) и 2 символа ключа
            pos1:=pos1+2; // позиция перескакивает на 2 следующих символа.
           end;

          if not SaveDialog1.Execute then exit; // если диалог1 не открыт, то выходим
          SaveBinArrayToFile(SaveDialog1.FileName, arr); // процедура сохранения массива байт в файл
  end;

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

procedure TForm1.EncryptedKeyFile; // всё аналогично, не комментирую. только тут открываем уже ключевой файл
var I: integer;
v: TSaveDialog;
begin
          v:= TSaveDialog.Create(SaveDialog2);
           //Открытие ключевого файла
          AssignFile(fKey,OpenDialog2.FileName); 
          Reset(fKey,1);
          sizekeyFile:= FileSize(fKey);
          SetLength(arrKeyFile,sizekeyFile);
          BlockRead(fKey,arrKeyFile[0],sizekeyFile);
          CloseFile(fKey);

          // Шифрование по ключевому файлу
          pos2:=0;
          for i := 1 to length(arr) do
          begin
          if pos2 >= length(arrkeyFile) then pos2:=1;
          arr[i]:= arr[i] xor arrkeyFile[pos2];
          pos2:= pos2+1;
          end;

          if not v.Execute then exit;
          SaveBinArrayToFile(v.FileName, arr);


  end;

//Что бы вызвать процедуры, на событие onclick у кнопки Crypt пишем такой код:
if form1.RadioButton1.Checked=true then  EncryptedKey else
if form1.RadioButton2.Checked=true then  EncryptedKeyFile;

//Так же при открытии файла желательно создать бэкап, что делается одной строчкой:

CopyFile (PChar(Opendialog1.FileName), PChar(OpenDialog1.FileName + '.bak'), true);
Всё, шифратор файлов готов. Соответственно можно прикрутить лог событий и прочие ненужные вещи

Весь код проекта:
Скрытый текст
code:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.StdCtrls, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    txtOpenFilePath: TEdit;
    GroupBox1: TGroupBox;
    txtKey: TEdit;
    RichEdit1: TRichEdit;
    Crypt: TButton;
    StatusBar1: TStatusBar;
    OpenDialog1: TOpenDialog;
    SaveDialog1: TSaveDialog;
    Button2: TButton;
    Label1: TLabel;
    txtKeyFile: TEdit;
    Button3: TButton;
    Label2: TLabel;
    Label3: TLabel;
    OpenDialog2: TOpenDialog;
    SaveDialog2: TSaveDialog;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    procedure Button1Click(Sender: TObject);
    procedure CryptClick(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure RadioButton1Click(Sender: TObject);
    procedure RadioButton2Click(Sender: TObject);
    procedure GroupBox1Click(Sender: TObject);
  private
    var

    CryptFilePath : string;
    KeyFilePath : string;


    USerKey : string;
    fCrypt, fKey: file;
    arr, arrKeyFile: array of Byte;
    Size, pos1, pos2, _key, sizekeyFile, t: longint;
    _StrKey : string  ;

  public
    { Public declarations }
    Procedure EncryptedKey;
    Procedure EncryptedKeyFile;

  end;

var
  Form1: TForm1;
  CrKey: integer;
implementation

{$R *.dfm}

function SaveBinArrayToFile(AFileName:string; ABuf:array of byte):boolean;
var
  fs:TFileStream;
  n:integer;
begin

  fs:=TFileStream.Create(AFileName, fmCreate);
  try
    fs.Position := 0;
    n := Length(ABuf);
    fs.Write(ABuf, n);
  finally
    fs.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
if OpenDialog1.Execute = true then

begin
form1.txtOpenFilePath.Text:= Opendialog1.FileName;
form1.RichEdit1.Lines.Add('Файл '+ExtractFIleName(OpenDialog1.FileName)+' был открыт в '+ timetostr(time)+'.');
form1.RichEdit1.Lines.Add('');
CryptFilePath:=OpenDialog1.FileName;

// Open the file to encr
ShowMessage(CryptFilePath);
AssignFile(fCrypt,CryptFilePath);
Reset(fCrypt,1);
size:= FileSize(fCrypt);
SetLength(arr,size);
BlockRead(fCrypt,arr[0],size);
CloseFile(fCrypt);

end;

CopyFile (PChar(Opendialog1.FileName), PChar(OpenDialog1.FileName + '.bak'), true);
if FileExists(OpenDIalog1.FileName) then  begin form1.RichEdit1.Lines.Add('Бэкап файла создан в '+ timetostr(time));
form1.RichEdit1.Lines.Add('');
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
i: integer;
begin
randomize;
txtKey.Clear;
for i := 1 to 32 do
 txtKey.Text:=txtKey.Text+IntToStr(random(9));
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
if OpenDialog2.Execute then
form1.txtKeyFile.Text:= form1.OpenDialog2.FileName;
end;


procedure TForm1.CryptClick(Sender: TObject);
begin
if form1.RadioButton1.Checked=true then  EncryptedKey else
if form1.RadioButton2.Checked=true then  EncryptedKeyFile;
end;



procedure TForm1.EncryptedKey;
var i: integer;
  begin
  UserKey:= txtKey.Text;
    Pos1:=1;
         //Шифрование файла по ключу
         for i := 1 to length(arr) do
          begin
             if pos1>= length(UserKey) then  pos1:=1;
            _StrKey:= UserKey[pos1]+UserKey[pos1+1]  ;
            _key:=StrToInt(_StrKey);
            arr[i]:=arr[i] xor _key;
            pos1:=pos1+2;
           end;
          //Шифрование файла по ключу
          if not SaveDialog1.Execute then exit;
          SaveBinArrayToFile(SaveDialog1.FileName, arr);
  end;

procedure TForm1.EncryptedKeyFile;
var I: integer;
v: TSaveDialog;
begin
          v:= TSaveDialog.Create(SaveDialog2);
           //Открытие ключевого файла
          AssignFile(fKey,OpenDialog2.FileName);
          Reset(fKey,1);
          sizekeyFile:= FileSize(fKey);
          SetLength(arrKeyFile,sizekeyFile);
          BlockRead(fKey,arrKeyFile[0],sizekeyFile);
          CloseFile(fKey);

          // Шифрование по ключевому файлу
          pos2:=0;
          for i := 1 to length(arr) do
          begin
          if pos2 >= length(arrkeyFile) then pos2:=1;
          arr[i]:= arr[i] xor arrkeyFile[pos2];
          pos2:= pos2+1;
          end;
          // Шифрование по ключевому файлу
          if not v.Execute then exit;
          SaveBinArrayToFile(v.FileName, arr);


  end;

procedure TForm1.GroupBox1Click(Sender: TObject);
begin

end;

procedure TForm1.RadioButton1Click(Sender: TObject);
begin
label3.Enabled:= true;
txtKey.Enabled:= true;
Button2.Enabled:= true;
end;

procedure TForm1.RadioButton2Click(Sender: TObject);
begin
label2.Enabled:= true;
txtkeyFile.Enabled:= true;
Button3.Enabled:= true;
end;

end.

Спасибо за внимание.
 
Пользователь вне форума    
Наши Спонсоры
  , 09:12   #2
;)
 
Аватар для pwcode
 
Локация: hpc.name
Регистрация: 04.06.2013
Сообщений: 283

Репутация: 110 / 2
По умолчанию

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

Метки
crypt, delphi, encrypt, pwcode

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[FAQ] Пишем WinLock, delphi 7 beknazar Delphi 157 15.10.2015 13:54
Пишем трояна megapupsik C++ Builder 19 08.05.2013 12:22
Команды которые используются для написания *.bat файлов chechenman Windows 6 27.05.2012 15:15
Пишем простейший джойнер файлов becensed Assembler 0 07.03.2011 17:15
CMD-что это?Команды CMD Badak Новичкам 0 11.11.2009 11:22



Часовой пояс GMT +2
Powered by vBulletin® 3.x.x Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.

Copyright © 2008 - 2013 «HPC» Реклама на сайте Правила Форума Пользовательское соглашение Работа на сайте
При копировании материалов ставьте ссылку на источник
Все материалы представлены только в ознакомительных целях, администрация за их использование ответственности не несет.