Главная » Статьи » Delphi » Статьи Delphi

Скачивать материалы с сайта, могут только зарегистрированные пользователи.
Для регистрации заполните два поля ниже!

Через минуту Вы получите "Гостевой доступ"




Модуль для IDEA шифрования
Модуль для IDEA шифрования

Автор: Матвеев Игорь

 Часто в свои проекты необходимо включать шифрование данных. Самый простой способ - xor шифрование, но он подходит только когда необходимо обеспечить малый уровень защиты. Но иногда необходимы более серьезные алгоритмы.

 Работая над архиватором файлов (вроде WinRar), у меня встал вопрос о шифровании, в таких программах как архиватор это просто необходимо.

 Итак, существует ряд алгоритмов симметричного шифрования - когда один и тот же ключ используется для шифрования и дешифрования. Эти алгоритмы, как правило, очень хорошо изучены и их стойкость к различного рода атакам подтверждена результатами математических исследований.

 Кроме того, 2 октября 2000 года NIST (Национальный институт стандартов и технологий, правопреемник прежнего НБС), утвердил алгоритм Rijndael Джоана Димена и Винсента Риджмена как AES (Усовершенствованный алгоритм шифрования, который должен стать заменой прежнего стандарта - DES). Алгоритм Rijndael свободен как для коммерческого, так и для некоммерческого использования и, по видимому, является наилучшим выбором если необходима достаточная стойкость шифра наряду с высокой скоростью работы и относительной простотой реализации.

 Но я выбрал для своего архиватора алгоритм IDEA (International Data Encryption Algorithm). Этот алгоритм был разработан для простого воплощения как программно, так и аппаратно. Стойкость IDEA основывается на использовании трех несовместимых типов арифметических операций над 16-битными словами. IDEA очень распространен в Европе и используется в популярной программе шифрования электронных писем PGP (Pretty Good Privacy).

 Нижепредставленный модуль полностью реализует в себе метода IDEA шифрования. Главными функциями являются:

function EncryptCopy(DestStream, SourseStream : TStream; Count: Int64;
  Key : string): Boolean; // Зашифровать данные из одного потока в другой

function DecryptCopy(DestStream, SourseStream : TStream; Count: Int64;
  Key : string): Boolean; // Расшифровать данные из одного потока в другой

function EncryptStream(DataStream: TStream; Count: Int64;
  Key : string): Boolean; // Зашифровать содержимое потока

function DecryptStream(DataStream: TStream; Count: Int64;
  Key : string): Boolean; // Расшифровать содержимое потока

 А теперь сам модуль:

{ *********************************************************************** }
{ }
{ Delphi Еncryption Library }
{ Еncryption / Decryption stream - IDEA }
{ }
{ Copyright (c) 2004 by Matveev Igor Vladimirovich }
{ With offers and wishes write: teap_leap@mail.ru }
{ }
{ *********************************************************************** }


unit IDEA;

interface

uses
SysUtils, Classes, Math;

const
Rounds = 8;
KeyLength = (Rounds * 6) + 4;
Maxim = 65537;

type
TIDEAKey = array[0..KeyLength-1] of Word;
TIDEABlock = array[1..4] of Word;

var
Z : TIDEAKey;
K : TIDEAKey;

FBlockSize : Integer;
FKey : string;
FBufferSize : Integer;
FKeySize : Integer;
FKeyPtr : PChar;

////////////////////////////////////////////////////////////////////////////////
// Дополнительные функции


procedure Initialize(AKey: string); // Инициализация
procedure CalculateSubKeys; // Подготовка подключей
function EncipherBlock(var Block): Boolean; // Шифрация блока (8 байт)
function DecipherBlock(var Block): Boolean; // Дешифрация блока

////////////////////////////////////////////////////////////////////////////////
// Основные функции


function EncryptCopy(DestStream, SourseStream : TStream; Count: Int64;
Key : string): Boolean; // Зашифровать данные из одного потока в другой
function DecryptCopy(DestStream, SourseStream : TStream; Count: Int64;
Key : string): Boolean; // Расшифровать данные из одного потока в другой

function EncryptStream(DataStream: TStream; Count: Int64;
Key: string): Boolean; // Зашифровать содержимое потока

function DecryptStream(DataStream: TStream; Count: Int64;
Key: string): Boolean; // Расшифровать содержимое потока

implementation

////////////////////////////////////////////////////////////////////////////////

function ROL(a, s: LongWord): LongWord;
asm
mov ecx, s
rol eax, cl
end;

////////////////////////////////////////////////////////////////////////////////

procedure InvolveKey;
var
TempKey : string;
i, j : Integer;
K1, K2 : LongWord;
begin
// Разворачивание ключа до длинны 51 символ
TempKey := FKey;
i := 1;
while ((Length(TempKey) mod FKeySize) <> 0) do
begin
TempKey := TempKey + TempKey[i];
Inc(i);
end;

// Now shorten the key down to one KeySize block by combining the bytes
i := 1;
j := 0;
while (i < Length(TempKey)) do
begin
Move((FKeyPtr+j)^, K1, 4);
Move(TempKey[i], K2, 4);
K1 := ROL(K1, K2) xor K2;
Move(K1, (FKeyPtr+j)^, 4);
j := (j + 4) mod FKeySize;
Inc(i, 4);
end;
end;

////////////////////////////////////////////////////////////////////////////////

{$R-,Q-}

procedure ExpandKeys;
var
i : Integer;
begin
// Копирование ключа в Z
Move(FKeyPtr^, Z, FKeySize);

// Генерация подключа зашифрование
for i := 8 to KeyLength-1 do
begin
if (((i+2) mod 8) = 0) then Z[i] := (Z[i- 7] shl 9) xor (Z[i-14] shr 7)
else if (((i+1) mod 8) = 0) then Z[i] := (Z[i-15] shl 9) xor (Z[i-14] shr 7)
else Z[i] := (Z[i- 7] shl 9) xor (Z[i- 6] shr 7);
end;
end;

////////////////////////////////////////////////////////////////////////////////

procedure InvertKeys;
type
PWord = ^Word;
var
j : Integer;
pz, pp : PWord;
t1, t2, t3 : Word;

////////////////////////////////////////

function Inv(I: Integer): Integer;
var
n1, n2, q, r, b1, b2, t : Integer;
begin
if (I = 0) then
Result := 0 else
begin
n1 := Maxim;
n2 := I;
b2 := 1;
b1 := 0;
repeat
r := (n1 mod n2);
q := (n1-r) div n2;
if (r = 0) then
begin
if (b2 < 0) then b2 := Maxim + b2;
end else
begin
n1 := n2;
n2 := r;
t := b2;
b2 := b1 - q * b2;
b1 := t;
end;
until (r = 0);
Result := b2;
end;
Result := (Result and $ffff);
end;

////////////////////////////////////////

begin
pz := @Z;
pp := @K;
Inc(pp, KeyLength);

// t1 = inv(*Z++);
t1 := Inv(pz^);
Inc(pz);

// t2 = -*Z++;
t2 := -pz^;
Inc(pz);

// t3 = -*Z++;
t3 := -pz^;
Inc(pz);

// *--p = inv(*Z++);
Dec(pp);
pp^ := Inv(pz^);
Inc(pz);

// *--p = t3;
Dec(pp);
pp^ := t3;

// *--p = t2;
Dec(pp);
pp^ := t2;

// *--p = t1;
Dec(pp);
pp^ := t1;

for j := 1 to Rounds-1 do
begin
// t1 = *Z++;
t1 := pz^;
Inc(pz);

// *--p = *Z++;
Dec(pp);
pp^ := pz^;
Inc(pz);

// *--p = t1;
Dec(pp);
pp^ := t1;

// t1 = inv(*Z++);
t1 := Inv(pz^);
Inc(pz);

// t2 = -*Z++;
t2 := -pz^;
Inc(pz);

// t3 = -*Z++;
t3 := -pz^;
Inc(pz);

// *--p = inv(*Z++);
Dec(pp);
pp^ := Inv(pz^);
Inc(pz);

// *--p = t2;
Dec(pp);
pp^ := t2;

// *--p = t3;
Dec(pp);
pp^ := t3;

// *--p = t1;
Dec(pp);
pp^ := t1;
end;

// t1 = *Z++;
t1 := pz^;
Inc(pz);

// *--p = *Z++;
Dec(pp);
pp^ := pz^;
Inc(pz);

// *--p = t1;
Dec(pp);
pp^ := t1;

// t1 = inv(*Z++);
t1 := Inv(pz^);
Inc(pz);

// t2 = -*Z++;
t2 := -pz^;
Inc(pz);

// t3 = -*Z++;
t3 := -pz^;
Inc(pz);

// *--p = inv(*Z++);
Dec(pp);
pp^ := Inv(pz^);

// *--p = t3;
Dec(pp);
pp^ := t3;

// *--p = t2;
Dec(pp);
pp^ := t2;

// *--p = t1;
Dec(pp);
pp^ := t1;
end;
{$R+,Q+}

////////////////////////////////////////////////////////////////////////////////


procedure CalculateSubKeys;
begin
ExpandKeys;
InvertKeys;
end;

////////////////////////////////////////////////////////////////////////////////

procedure Initialize(AKey: string);
begin
FBlockSize := 8;
FBufferSize := 2048;
FKey := AKey;
FKeySize := 32;

FillChar(Z, SizeOf(Z), 0);
FillChar(K, SizeOf(K), 0);

GetMem(FKeyPtr, FKeySize);
FillChar(FKeyPtr^, FKeySize, #0);

InvolveKey;
end;

////////////////////////////////////////////////////////////////////////////////

{$R-,Q-}

procedure Cipher(var Block: TIDEABlock; const Keys: TIDEAKey);
var
x1, x2, x3, x4 : Word;
t1, t2 : Word;
pz : ^Word;
r : Integer;

////////////////////////////////////////

function Mul(a,b: Word): Word;
var
p : LongWord;
begin
if (a > 0) then
begin
if (b > 0) then
begin
p := LongWord(a)*b;
b := p and $ffff;
a := p shr 16;
Result := ((b - a) + Ord(b < a));
end else Result := 1 - a;
end else Result := 1 - b;
end;

////////////////////////////////////////

begin
// x1 = *in++; x2 = *in++;
x1 := Block[1];
x2 := Block[2];
// x3 = *in++; x4 = *in;
x3 := Block[3];
x4 := Block[4];

pz := @Keys;
for r := 1 to Rounds do
begin
// MUL(x1,*Z++);
x1 := Mul(x1, pz^);
Inc(pz);

// x2 += *Z++;
x2 := x2 + pz^;
Inc(pz);

// x3 += *Z++;
x3 := x3 + pz^;
Inc(pz);

// MUL(x4, *Z++);
x4 := Mul(x4, pz^);
Inc(pz);

// t2 = x1^x3;
t2 := x1 xor x3;

// MUL(t2, *Z++);
t2 := Mul(t2, pz^);
Inc(pz);

// t1 = t2 + (x2^x4);
t1 := t2 + (x2 xor x4);

// MUL(t1, *Z++);
t1 := Mul(t1, pz^);
Inc(pz);

// t2 = t1+t2;
t2 := (t1 + t2);

// x1 ^= t1;
x1 := x1 xor t1;

// x4 ^= t2;
x4 := x4 xor t2;

// t2 ^= x2;
t2 := t2 xor x2;

// x2 = x3^t1;
x2 := x3 xor t1;

// x3 = t2;
x3 := t2;
end;

// MUL(x1, *Z++);
x1 := Mul(x1, pz^);
Inc(pz);

// *out++ = x1;
Block[1] := x1;

// *out++ = x3 + *Z++;
Block[2] := x3 + pz^;
Inc(pz);

// *out++ = x2 + *Z++;
Block[3] := x2 + pz^;
Inc(pz);

// MUL(x4, *Z);
x4 := Mul(x4, pz^);

// *out = x4;
Block[4] := x4;
end;
{$R+,Q+}

////////////////////////////////////////////////////////////////////////////////


function EncipherBlock(var Block): Boolean;
begin
Cipher(TIDEABlock(Block), Z);
Result := TRUE;
end;

////////////////////////////////////////////////////////////////////////////////

function DecipherBlock(var Block): Boolean;
begin
Cipher(TIDEABlock(Block), K);
Result := TRUE;
end;

////////////////////////////////////////////////////////////////////////////////
// Главные функции ...


function EncryptCopy(DestStream, SourseStream : TStream; Count: Int64;
Key : string): Boolean;
var
Buffer : TIDEABlock;
PrCount : Int64;
AddCount : Byte;
begin
Result := True;
try
if Key = '' then
begin
DestStream.CopyFrom(SourseStream, Count);
Exit;
end;
Initialize(Key);
CalculateSubKeys;
PrCount := 0;
while Count - PrCount >= 8 do
begin
SourseStream.Read(Buffer, SizeOf(TIDEABlock));
EncipherBlock(Buffer);
DestStream.Write(Buffer, SizeOf(TIDEABlock));
Inc(PrCount, 8);
end;

AddCount := Count - PrCount;
if Count - PrCount <> 0 then
begin
SourseStream.Read(Buffer, AddCount);
DestStream.Write(Buffer, AddCount);
end;
except
Result := False;
end;
end;


////////////////////////////////////////////////////////////////////////////////

function DecryptCopy(DestStream, SourseStream : TStream; Count: Int64;
Key : string): Boolean;
var
Buffer : TIDEABlock;
PrCount : Int64;
AddCount : Byte;
begin
Result := True;
try
if Key = '' then
begin
DestStream.CopyFrom(SourseStream, Count);
Exit;
end;
Initialize(Key);
CalculateSubKeys;
PrCount := 0;
while Count - PrCount >= 8 do
begin

SourseStream.Read(Buffer, SizeOf(TIDEABlock));
DecipherBlock(Buffer);
DestStream.Write(Buffer, SizeOf(TIDEABlock));
Inc(PrCount, 8);
end;

AddCount := Count - PrCount;
if Count - PrCount <> 0 then
begin
SourseStream.Read(Buffer, AddCount);
DestStream.Write(Buffer, AddCount);
end;
except

Result := False;
end;
end;


////////////////////////////////////////////////////////////////////////////////

function EncryptStream(DataStream: TStream; Count: Int64; Key: string): Boolean;
var
Buffer : TIDEABlock;
PrCount : Int64;
AddCount : Byte;
begin
Result := True;
try
if Key = '' then
begin

DataStream.Seek(Count, soFromCurrent);
Exit;
end;
Initialize(Key);
CalculateSubKeys;
PrCount := 0;
while Count - PrCount >= 8 do
begin
DataStream.Read(Buffer, SizeOf(TIDEABlock));
EncipherBlock(Buffer);
DataStream.Seek(-SizeOf(TIDEABlock), soFromCurrent);
DataStream.Write(Buffer, SizeOf(TIDEABlock));
Inc(PrCount, 8);
end;
except

Result := False;
end;
end;


////////////////////////////////////////////////////////////////////////////////

function DecryptStream(DataStream: TStream; Count: Int64; Key: string): Boolean;
var
Buffer : TIDEABlock;
PrCount : Int64;
begin
Result := True;
try
if Key = '' then
begin

DataStream.Seek(Count, soFromCurrent);
Exit;
end;
Initialize(Key);
CalculateSubKeys;
PrCount := 0;
while Count - PrCount >= 8 do
begin
DataStream.Read(Buffer, SizeOf(TIDEABlock));
DecipherBlock(Buffer);
DataStream.Seek(-SizeOf(TIDEABlock), soFromCurrent);
DataStream.Write(Buffer, SizeOf(TIDEABlock));
Inc(PrCount, 8);
end;
except

Result := False;
end;
end;


// Завершение главных функций ...
////////////////////////////////////////////////////////////////////////////////


end.

 А пользоваться этим модулем можно так. Нижеприведенный пример демонстрирует шифрование / дешифрование файла с использованием функций EncryptStream / DecryptStream:

procedure TForm1.Button1Click(Sender: TObject);
var
SourseStream : TFileStream;
begin
SourseStream := TFileStream.Create(Edit1.Text, fmOpenReadWrite );
EncryptStream(SourseStream, SourseStream.Size, Edit2.Text);
SourseStream.Free;
end;

procedure
TForm1.Button2Click(Sender: TObject);
var
SourseStream : TFileStream;
begin
SourseStream := TFileStream.Create(Edit1.Text, fmOpenReadWrite );
DecryptStream(SourseStream, SourseStream.Size, Edit2.Text);
SourseStream.Free;
end;

 ПРИМЕЧАНИЕ: Так как алгоритм шифрует данные блоками по 8 байт, а размер шифруемых данных не всегда кратен 8, поэтому в данном модуле последний блок, если он размером больше нодя и меньше восьми, не шифруется. Поэтому, если функцию шифрования обозначить e(x), а Srt1 и Str2 - шифруемые данные, то e(Str1) + e(Str2) не всегда равно e(Str1 + Str2).


Категория: Статьи Delphi | Добавил: c1 (2009 Июль 10)
Просмотров: 821 | Теги: Модуль для IDEA шифрования | Рейтинг: 0.0/0

Выразить благодарность - Поделиться с друзьями!

 

Здесь все о технической стороне 1С!

 

Узнай, как правильно администрировать 1С Предприятие
Регистрируйся на бесплатный 7-ми дневный курс сейчас:

Ваш E-Mail в безопасности



Всего комментариев: 0
avatar