Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Модуль для RC6 шифрования

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

Переквалифицировался хакер в священника и однажды приходит на проповедь после большого перепоя. Заплетающимся языком:
- И да поможет тебе F1, и сохранит тебя F2! Во имя Controla, Alta и святого Dela, да будет так - Reset!

 Данная статья является логическим завершением темы шифрования данных, которой я посвятил три статьи (Модуль для IDEA шифрования, Модуль для RC5 шифрования и данная). Данная статья посвящена алгоритму шифрования RC6.

 Как я уже говорил, RC6 Очень похож на RC5, во всяком случае расчет подключа производится тем же способом, что и в RC5. RC6 участвовал в конкурсе на звание AES и, по некоторым данным, не выиграл только из-за медленной работы аппаратных реализаций. Программные же реализации RC6, пожалуй, являются самыми быстрыми среди алгоритмов шифрования, при обеспечении достаточной стойкости шифра.

 Нижепредставленный модуль построен по тому же принципу, что и предыдущие - имена функций совпадают и если вы хотите заменить в своей программе шифрование с IDEA или RC5 на RC6 - просто добавьте модуль RC6, а IDEA или RC5 - удалите из списка uses.

 Шифр RC6, в отличии от RC5, оперирует блоками по 16 байт, а модуль построен так, что если при шифрации методами: EncryptCopy, DecryptCopy, EncryptStream, DecryptStream размер данных не будет кратен 16 - последний блок длинной 1..15 байт не шифруется и в "чистом" виде добавляется к зашифрованным. Также и при дешифровании - если последний блок размером 1..15 байт он не дешифруется а добавляется к расшифрованным данным. Такой подход обеспечивает в полной мере "симметричное" шифрование так как размеры входных и выходных данных полностью совпадают. Однако такой подход приводит к некоторым сложностям, если последний блок также нуждается в шифровании. На мой взгляд лучший выход - добавить при шифровании к исходным данным строку определенной длинны и после дешифрования отсечь с конца строку той же длинны.

 Также в заключении цыкла статей, посвященных шифрованию я подготовил примеры по всем представленным алгоритмам (IDEA, RC5, RC6).

Загрузить демо примеры

А вот последний модуль:

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

unit RC6;

interface

uses
  SysUtils, Classes;

const
  Rounds    = 20;
  KeyLength = 2 * (Rounds + 2);

  BlockSize = 16;
  KeySize   = 16 * 4;

  P32       = $b7e15163;
  Q32       = $9e3779b9;
  lgw       = 5;

type
  TRC6Block = array[1..4] of LongWord;

var
  S      : array[0..KeyLength-1] of LongWord;
  Key    : string;
  KeyPtr : PChar;

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

procedure Initialize(AKey: string);          // Инициализация
procedure CalculateSubKeys;                  // Подготовка подключей
function EncipherBlock(var Block): Boolean;  // Шифрация блока (16 байт)
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;

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

function ROR(a, s: LongWord): LongWord;
asm
  mov    ecx, s
  ror    eax, cl
end;

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

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

 i := 1;
 j := 0;
 while (i < Length(TempKey)) do
   begin
     Move((KeyPtr+j)^, K1, 4);
     Move(TempKey[i], K2, 4);
     K1 := ROL(K1, K2) xor K2;
     Move(K1, (KeyPtr+j)^, 4);
     j := (j + 4) mod KeySize;
     Inc(i, 4);
   end;
end;

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

procedure CalculateSubKeys;
var
  i, j, k : Integer;
  L       : array[0..15] of LongWord;
  A, B	 : LongWord;
begin
 // Копирование ключа в L
 Move(KeyPtr^, L, KeySize);

 // Инициализация подключа S
 S[0] := P32;
 for i := 1 to KeyLength-1 do
   S[i] := S[i-1] + Q32;

 // Смешивание S с ключом
 i := 0;
 j := 0;
 A := 0;
 B := 0;
 for k := 1 to 3*KeyLength do
   begin
     A := ROL((S[i] + A + B), 3);
     S[i] := A;
     B := ROL((L[j] + A + B), (A + B));
     L[j] := B;
     i := (i + 1) mod KeyLength;
     j := (j + 1) mod 16;
   end;
end;

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

procedure Initialize(AKey: string);
begin
 GetMem(KeyPtr, KeySize);
 FillChar(KeyPtr^, KeySize, #0);
 Key := AKey;

 InvolveKey;
end;

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

function EncipherBlock(var Block): Boolean;
var
  RC6Block : TRC6Block absolute Block;
  i	   : Integer;
  t, u	   : LongWord;
  Temp	   : LongWord;
begin
 // Инициализация блока
 Inc(RC6Block[2], S[0]);
 Inc(RC6Block[4], S[1]);

 for i := 1 to Rounds do
   begin
     t := ROL((RC6Block[2] * (2*RC6Block[2] + 1)), lgw);
     u := ROL((RC6Block[4] * (2*RC6Block[4] + 1)), lgw);
     RC6Block[1] := ROL((RC6Block[1] xor t), u) + S[2*i];
     RC6Block[3] := ROL((RC6Block[3] xor u), t) + S[2*i+1];

     Temp := RC6Block[1];
     RC6Block[1] := RC6Block[2];
     RC6Block[2] := RC6Block[3];
     RC6Block[3] := RC6Block[4];
     RC6Block[4] := Temp;
   end;

 RC6Block[1] := RC6Block[1] + S[2*Rounds+2];
 RC6Block[3] := RC6Block[3] + S[2*Rounds+3];

 Result := TRUE;
end;

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

function DecipherBlock(var Block): Boolean;
var
  RC6Block : TRC6Block absolute Block;
  i	   : Integer;
  t, u	   : LongWord;
  Temp	   : LongWord;
begin
 // Инициализация блока
 RC6Block[3] := RC6Block[3] - S[2*Rounds+3];
 RC6Block[1] := RC6Block[1] - S[2*Rounds+2];

 for i := Rounds downto 1 do
   begin
     Temp := RC6Block[4];
     RC6Block[4] := RC6Block[3];
     RC6Block[3] := RC6Block[2];
     RC6Block[2] := RC6Block[1];
     RC6Block[1] := Temp;

     u := ROL((RC6Block[4] * (2*RC6Block[4] + 1)),lgw);
     t := ROL((RC6Block[2] * (2*RC6Block[2] + 1)),lgw);
     RC6Block[3] := ROR((RC6Block[3]-S[2*i+1]), t) xor u;
     RC6Block[1] := ROR((RC6Block[1]-S[2*i]), u) xor t;
   end;

 Dec(RC6Block[4], S[1]);
 Dec(RC6Block[2], S[0]);

 Result := TRUE;
end;

////////////////////////////////////////////////////////////////////////////////
// Реализация главных функций

function EncryptCopy(DestStream, SourseStream : TStream; Count: Int64;
  Key : string): Boolean;
var
  Buffer   : TRC6Block;
  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 >= BlockSize do
     begin
       SourseStream.Read(Buffer, BlockSize);
       EncipherBlock(Buffer);
       DestStream.Write(Buffer, BlockSize);
       Inc(PrCount, BlockSize);
     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   : TRC6Block;
  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 >= BlockSize do
     begin
       SourseStream.Read(Buffer, BlockSize);
       DecipherBlock(Buffer);
       DestStream.Write(Buffer, BlockSize);
       Inc(PrCount, BlockSize);
     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   : TRC6Block;
  PrCount  : Int64;
begin
 Result := True;
 try
   if Key = '' then
     begin
       DataStream.Seek(Count, soFromCurrent);
       Exit;
     end;
   Initialize(Key);
   CalculateSubKeys;
   PrCount := 0;
   while Count - PrCount >= BlockSize do
     begin
       DataStream.Read(Buffer, BlockSize);
       EncipherBlock(Buffer);
       DataStream.Seek(-BlockSize, soFromCurrent);
       DataStream.Write(Buffer, BlockSize);
       Inc(PrCount, BlockSize);
     end;
 except
   Result := False;
 end;
end;

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

function DecryptStream(DataStream: TStream; Count: Int64; Key: string): Boolean;
var
  Buffer   : TRC6Block;
  PrCount  : Int64;
begin
 Result := True;
 try
   if Key = '' then
     begin
       DataStream.Seek(Count, soFromCurrent);
       Exit;
     end;
   Initialize(Key);
   CalculateSubKeys;
   PrCount := 0;
   while Count - PrCount >= BlockSize do
     begin
       DataStream.Read(Buffer, BlockSize);
       DecipherBlock(Buffer);
       DataStream.Seek(-BlockSize, soFromCurrent);
       DataStream.Write(Buffer, BlockSize);
       Inc(PrCount, BlockSize);
     end;
 except
   Result := False;
 end;
end;

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

end.

Проект Delphi World © Выпуск 2002 - 2004
Автор проекта: ___Nikolay