Для кращого розуміння, в таблиці я не буду вказувати цифрові коди букв пароля, я просто вкажу самі літери. Зрозуміло, під літерами розуміється їх цифровий код.
З алгоритмом начебто розібралися, тепер треба подумати про функції, яка буде шифрувати байт за допомогою збільшення. Найпростіший спосіб це КСОР xn і 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_ * опишу пізніше.
Тут я поясню докладніше. Константа CF_Dest_NOT_CREATE каже функції, що шифрувати треба в шуканий файл, тобто шуканий файл, і файл призначення збігаються. Але проміжний файл потрібен в будь-якому випадку, тому ми його створюємо на диску С. потім ми замінимо шуканий файл з цими проміжними, і проміжний потім видалимо.
all_mass: = 0; // ця змінна потрібна для прогресу
SourceHFile: = CreateFile (pchar (SourceFile), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0,0);
if SourceHFile = INVALID_HANDLE_VALUE then
Exit;
DestHFile: = CreateFile (pchar (DestFile), GENERIC_WRITE, FILE_SHARE_READ, nil, CREATE_ALWAYS, 0,0);
if DestHFile = INVALID_HANDLE_VALUE then
Exit;
FSize: = GetFileSize (SourceHFile, nil);
if ACF_ShowProgress then
if aGauge = nil then
ACF_ShowProgress: = false
Else
<всё правильно: гаугэ указали, получаем вес одного байта в прогрессе гаугэ>
one_byte_mass: = (TGauge (aGauge ^). MaxValue-TGauge (aGauge ^). MinValue) / FSize;
Далі йде алгоритм відмінний від того, який я вказував на початку, але він виконує те ж саме тільки швидше. Він швидше, тому що він не обчислює номер букви, яку треба брати з пароля, вона береться сама по собі, згідно з номером повтору у внутрішньому циклі.
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:
Ось константи, які я використовував в цій функції (змінювати їх не рекомендується):
const
CF_AutoRename = $ 00000001;
CF_DeleteSource = $ 00000002;
CF_Dest_NOT_CREATE = $ 00000008;
CF_ShowProgress = $ 00000010;
var
ACF_AutoRename: boolean;
ACF_DeleteSource: boolean;
ACF_Dest_NOT_CREATE: boolean;
ACF_ShowProgress: boolean;
Їх треба описувати саме так: константи до implementation, а змінні після.
Функції. DeCriptFile я не буду описувати, тому що вона точно така ж, всього лише за двома відмінностями:
і зрозуміло:
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 і користуєтеся їм на здоров'я.
Файли для завантаження