Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

RC6

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

Как я уже говорил, 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.
 
 

https://delphiworld.narod.ru/

DelphiWorld 6.0