Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Шифруем файл с помощью пароля

Автор: Руслан Аблязов
6 октября 2006 года

Скачать исходник (.PAS)

Здравствуйте, уважаемые delphi'сты и не только. Сегодня я вам расскажу, как можно зашифровать файл с помощью пароля. Я напишу 2 функции, которые всё это делают (разумеется, одна функция будет зашифровывать, а другая расшифровывать) и засуну их в отдельный модуль, чтобы ими было проще пользоваться.

Итак, приступим.

Сначала немного теории. Какой же алгоритм шифровки я буду использовать? Алгоритм очень прост.

  1. Открываем файл источник
  2. Создаём файл назначение
  3. дальше число n будет изменяться от 1 до
  4. Читаем n-байт файла в некую переменную xn
  5. Вычисляем параметр изменения этой переменной - dx, которое будет вычисляться по формуле dx=ord(пароль[index]), где index= n mod "длина пароля".
  6. Зашифровываем переменную xn с помощью некой функции xk=cript(xn,dx)
  7. Записываем в n-байт файла назначения переменную xk.
  8. Закрываем оба файла. И если надо, удаляем искомый файл.

Согласно этому алгоритму не трудно понять, каким будет алгоритм расшифровки. Он будет точно таким же только с тем отличием, что вместо некоторой функции cript будет применяться функция ей обратная. Поясню данный алгоритм на таблице, допустим, что пароль будет равен "qwerty", схема шифровки будет такая (напомню, что функция ord возвращает цифровой код буквы в кодировке ANSI):

Буква пароляЦифровой код
'q'113
'w'119
'e'101
'r'114
't'116
'y'121

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

значение dxqwertyqwertyqw
Значение байтаxxxxxxxxxxxxxx
Номер байта1234567891011121314
значение dxertyqw:пароль[n mod ]
Значение байтаxxxxxxxx
Номер байта151617181920:n

С алгоритмом вроде разобрались, теперь надо подумать о функции, которая будет шифровать байт с помощью приращения. Самый простой способ это ксорить xn и dx. Вот так:

xk:=xn xor dx;

этот способ примечателен тем, что для него не нужно создавать способа дешифровки, потому что декриптор ксора - это тот же ксор.

xk:=xn xor dx;
xdk:=xk xor dx;

После всех этих манипуляций xdk будет равно xn. Следовательно, для расшифровки нам не надо создавать декриптор.

Шифровать с помощью ксора примитивно и просто. Есть более лучший метод. Можно просто к начальному значению байта прибавлять значение dx, а при расшифровке вычитать. По-моему этот метод лучше и оригинальнее. НО здесь тоже есть загвоздка. Проблема в том, что максимальное значение байта 28 это 256, но у нас есть ещё и ноль, значит диапазон значений байта [0..255]. Следовательно, если начальное значение байта было равно 245, а приращение равно 45, и если их сложить то получается 290, и присваивании такого значения переменной размером с байт, произойдёт переполнение и просто-напросто ей присвоится 0. Есть выход: можно просто брать остаток от 256. При расшифровке смотреть если dx больше чем xn, то просто сначала из xn вычесть dx, а потом прибавить 256. Вот эти 2 функции:

function plus(xn,dx:byte):byte;
begin
 result:=(xn+dx) mod 256;
end;

function minus(xn,dx:byte):byte;
begin
  if xn>=dx then
   result:=xn-dx
           else
   result:=xn-dx+256;
end;

Вот и у нас есть криптор и декриптор. Теперь приступим к написанию самих функции шифровки и расшифровки.

Сначала напишем криптор.

Function CriptFile(
                   SourceFile:string; //наверное 
                   DestFile:string;  // это понятно
                   Password:string;  //пароль шифровки
                   Flags:DWORD;       //флаги операции
                   aGauge:pointer  //указатель на прогресс
                   ):boolean;
label
 1; //пригодится
var
 DestHFile,SourceHFile:THandle;
 FSize,i,j,kl,n:DWORD;
 CurrentByte:byte;
 one_byte_mass,all_mass:real;
begin
 Result:=false; 
 kl:=length(Password);

 ACF_AutoRename          :=(Flags and  CF_AutoRename) = CF_AutoRename;
 ACF_DeleteSource        :=(Flags and  CF_DeleteSource) = CF_DeleteSource;
 ACF_Dest_NOT_CREATE     :=(Flags and  CF_Dest_NOT_CREATE) = CF_Dest_NOT_CREATE;
 ACF_ShowProgress        :=(Flags and  CF_ShowProgress) = CF_ShowProgress;

Обрабатывает флаги которые мы приняли и потом их обрабатываем. Константы CF_* и переменные ACF_* опишу позже.

 if ACF_AutoRename then
  begin 
{если автоматическое переименование то добаляем ещё одно расширение}
   DestFile:=SourceFile+'.cript';
{если автоматически переименовывать, то файл нащначение надо создавать в любом случае}
   ACF_Dest_NOT_CREATE:=false;
  end;
 if ACF_Dest_NOT_CREATE then
  begin
   DestFile:='c:\3D9D8F57C3274EF3A6E7C5D5B27ADCF0.dat';
   ACF_DeleteSource:=false;
  end;

Дальше идёт алгоритм отличный от того, который я указывал в начале, но он выполняет тоже самое только быстрее. Он быстрее, потому что он не вычисляет номер буквы, которую надо брать из пароля, она берётся сама по себе, согласно номеру повтора во внутреннем цикле.

 for i:=1 to (FSize div kl)+1 do
  for j:=1 to kl do
   begin
    ReadFile(SourceHFile,CurrentByte,1,n,0);
{если ничего не считалось, то значит это конец файла}
    if n=0 then goto 1;
    CurrentByte:=plus(CurrentByte,ord(password[j]));
    WriteFile(DestHFile,Currentbyte,1,n,0);
    if ACF_ShowProgress then
     begin
      all_mass:=all_mass+one_byte_mass;
      TGauge(aGauge^).Progress:=round(all_mass);
     end; 
   end;
 1:

 CloseHandle(SourceHFile);
 CloseHandle(DestHFile);
{если надо удалить источник, то удаляем, если надо не надо создавать
 назначение, то производим необходимые манипуляции}
 if ACF_DeleteSource then
  DeleteFile(pchar(SourceFile));
 if ACF_Dest_NOT_CREATE then
  begin
   if not DeleteFile(pchar(SourceFile))then exit;
   CopyFile(pchar(DestFile),pchar(SourceFile),false);
   if not DeleteFile(pchar(DestFile)) then exit;
  end;
 Result:=true;//всё завершилось хорошо
end;

Вот константы, которые я использовал в этой функции (изменять их нерекомендуется):

const
 CF_AutoRename             =  $00000001;
 CF_DeleteSource           =  $00000002;
 CF_Dest_NOT_CREATE        =  $00000008;
 CF_ShowProgress           =  $00000010;

implementation

uses ::::;

var
 ACF_AutoRename:boolean;
 ACF_DeleteSource:boolean;
 ACF_Dest_NOT_CREATE:boolean;
 ACF_ShowProgress:boolean;

Их надо описывать именно так: константы до implementation, а переменные после.

Функции. DeCriptFile я не буду описывать, потому что она точно такая же, всего лишь за двумя отличиями:

if ACF_AutoRename then
  begin
   DestFile:=copy(SourceFile,1,length(SourceFile)-6);
   ACF_Dest_NOT_CREATE:=false;
  end;

и разумеется:

CurrentByte:=minus(CurrentByte,ord(password[j]));

Кстати о флагах. Их можно комбинировать с помощью оператора or.

Вот пример использования этих функций:

procedure TForm1.Button1Click(Sender: TObject);
begin
 CriptFile(Edit1.Text,'','123',CF_AutoRename or CF_ShowProgress or CF_DeleteSource,@Gauge1);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 DeCriptFile(Edit2.Text,'','123',CF_AutoRename or CF_ShowProgress,@Gauge1);
end;

Короче всё смотрите в исходниках. Там всё есть. Копируете этот модель в расшаренную для дельфи папку, добавляете в выражение uses модуль FileCript и пользуетесь им на здоровье.

Вот и конец моей очередной статьи. Пожалуйста, оцениваем её на форуме этого сайта.

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
33K
26 октября 2007 года
5C0A0
4 / / 26.10.2007
Мне нравитсяМне не нравится
10 ноября 2007, 18:02:49
и декрипт XOR BYTE,тоже_число
2.
33K
26 октября 2007 года
5C0A0
4 / / 26.10.2007
Мне нравитсяМне не нравится
10 ноября 2007, 18:01:38
всё так запутано...
я бы использовал всего лишь WriteFile ,ReadFile и CloseHandle
и криптовал XOR BYTE,any_number
good luck!!1
3.
261
03 ноября 2005 года
ahilles
1.5K / / 03.11.2005
Мне нравитсяМне не нравится
24 октября 2006, 21:00:57
нет не идиотизм
улучшаешь функции plus и minus - улучшаешь метод шифрования
4.
8.4K
24 августа 2004 года
kolya7k
5 / / 24.08.2004
+1 / -0
Мне нравитсяМне не нравится
22 октября 2006, 15:53:23
Идиотизм.

CryptAcquireContext
CryptCreateHash
CryptHashData
CryptDeriveKey

И всё что надо чтобы зашифровать файл.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог