Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

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

Delphi , Синтаксис , Шифрование

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

 

 Часто в свои проекты необходимо включать шифрование данных. Самый простой способ - 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 для шифрования IDEA!

Это nice piece кода, который реализует алгоритм симметричной блоковой шифровки IDEA (International Data Encryption Algorithm). Модуль предоставляет функции для шифрования и дешифрования потоков данных, а также копирования зашифрованных или расшифрованных данных из одного потока в другой.

Некоторые наблюдения и предложения:

  1. Процедура Initialize настраивает ключ шифрования и вычисляет подключи. Хорошая практика - проверять длину входного ключа и убедиться, что она соответствует ожидаемой длине.
  2. Процедура Cipher является ядром процесса шифрования/дешифрования. Она принимает блок данных в качестве входных данных, применяет алгоритм IDEA и возвращает зашифрованный или расшифрованный блок.
  3. Процедуры EncryptStream и DecryptStream предназначены для работы с потоками файлов. Они читают блоки из потока, шифруют или дешифруют их с помощью процедуры Cipher, и записывают результаты обратно в поток.
  4. Процедуры EncryptCopy и DecryptCopy аналогичны предыдущим двум, но они работают с копией входных данных вместо потока.
  5. Код использует inline-ассемблер в процедуре InvertKeys. Хотя это эффективный способ реализации шага инверсии ключей, он может сделать код более сложным для разработчиков, не знакомых с ассемблером.

В целом, модуль appears to be well-structured and easy to use. Некоторые предложения по улучшению:

  1. Рассмотрите добавление обработки ошибок в случаях, когда входные данные являются недопустимыми (например, неправильная длина ключа).
  2. Вам может потребоваться добавить поддержку больших блоков или переменной длины шифрования.
  3. Процедура Cipher могла бы получить дополнительные комментарии, объясняющие ее реализацию и связь с алгоритмом IDEA.
  4. Если вы планируете использовать этот модуль в производственной среде, рассмотрите добавление поддержки padding (например, PKCS#7) для обеспечения правильного обработки данных разной длины.

Хорошая работа по реализации алгоритма шифрования IDEA!

Модуль для IDEA шифрования - это программный код, который реализует алгоритм IDEA (International Data Encryption Algorithm) для шифрования и дешифрования данных в памяти.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




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


:: Главная :: Шифрование ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-01-28 06:01:55/0.0048658847808838/0