RC5

Автор: Матвеев Игорь Прежде всего немного о самом алгоритме: алгоритм был разработан Рональдом Ривестом (Ronald L. Rivest) для компании RSA Data Security. На основе в свое время был создан алгоритм шифрования RC6, который участвовал в конкурсе на звание AES (Advanced Encryption Standard - "Продвинутый" алгоритм шифрования). объявленном национальным институтом стандартизации и технологий для замены уже устаревшего алгоритма DES. Тогда RC6 не выиграл только из-за низкой производительности аппаратных реализаций алгоритма. А программные реализации и RC6 являются, пожалуй, самыми быстрыми среди всех алгоритмов шифрования, обеспечивающих достаточную стойкость перед атаками. Например, по некоторым данным скорость грамотно построенной аппаратной реализации алгоритма на компьютере с скоростью процессора 200 МГц может достигать 10..11 Мбайт/сек, а алгоритма RC6 - 11..12 Мбайт/сек. Для сравнения - скорость работы алгоритма Rijndael (победитель конкурса на звание AES) при вышеозначенных характеристиках процессора может достигать максимум 7 Мбайт/сек. Если вам срочно нужно внедрить алгоритмы шифрования в свои коммерческие проекты - на мой взгляд лучший выбор это или RC6. И не только потому, что они значительно проще в реализации, чем, например, IDEA, но и потому, что и RC6 (насколько я знаю - ручаться не могу) свободные алгоритмы и вы не должны отчислять часть прибыли при коммерческом использовании алгоритма. Итак, работает с блоками по восемь байт - два 32 битных слова. В отличии от IDEA и Rijndael в после развертывания ключа вычисляется один подключ, который используется и при шифровании, и при дешифровании. , как и большинство алгоритмов - раундовый алгоритм, другими словами, при шифрации блока над ним производятся одни и те же операции несколько раз, в таких раундов 12. Вот пожалуй и все, что вам нужно знать о теории алгоритма , все остальное видно из модуля. Модуль похож на модуль IDEA из моей предыдущей статьи. Если вы уже используете модуль IDEA в своих программах - для использования вам достаточно просто уброть из uses модуль IDEA и включить туда модуль (все имена методов сохраняются).

{ *********************************************************************** }
{ }
{ Delphi Еncryption Library }
{ Еncryption / Decryption stream -  }
{ }
{ Copyright (c) 2004 by Matveev Igor Vladimirovich }
{ With offers and wishes write: <a href="mailto:teap_leap@mail.ru">teap_leap@mail.ru</a> }
{ }
{ *********************************************************************** }
unit ;
interface
uses
 SysUtils, Classes;
type
 TBlock = array[1..2] of LongWord;
const
 Rounds = 12;
 BlockSize = 8;
 BufferSize = 2048;
 KeySize = 64;
 KeyLength = 2 * (Rounds + 1);
 P32 = $b7e15163;
 Q32 = $9e3779b9;
var
 Key : string;
 KeyPtr : PChar;
 S : array[0..KeyLength-1] of LongWord;
////////////////////////////////////////////////////////////////////////////////
// Дополнительные функции
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;
////////////////////////////////////////////////////////////////////////////////
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
 // Разворачивание ключа до длинны 64 символа
 TempKey := Key;
 i := 1;
 while ((Length(TempKey) mod KeySize) <> 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((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 Initialize(AKey: string);
begin
 Key := AKey;
 GetMem(KeyPtr, KeySize);
 FillChar(KeyPtr^, KeySize, #0);
 InvolveKey;
end;
////////////////////////////////////////////////////////////////////////////////
{$R-,Q-}
procedure CalculateSubKeys;
var
 i, j, k : Integer;
 L : array[0..15] of LongWord;
 A, B : LongWord;
begin
 // Copy the key into L
 Move(KeyPtr^, L, KeySize);
 // Now initialize the S table
 S[0] := P32;
 for i := 1 to KeyLength-1 do
  S[i] := S[i-1] + Q32;
 // Now scramble the S table with the key
 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;
////////////////////////////////////////////////////////////////////////////////

function EncipherBlock(var Block): Boolean;
var
 Block : TBlock absolute Block;
 i : Integer;
begin
 Inc(Block[1], S[0]);
 Inc(Block[2], S[1]);
 for i := 1 to Rounds do
  begin
  Block[1] := ROL((Block[1] xor Block[2]), Block[2]) + S[2*i];
  Block[2] := ROL((Block[2] xor Block[1]), Block[1]) + S[2*i+1];
  end;
 Result := TRUE;
end;
////////////////////////////////////////////////////////////////////////////////
function DecipherBlock(var Block): Boolean;
var
 Block : TBlock absolute Block;
 i : Integer;
begin
 for i := Rounds downto 1 do
  begin
  Block[2] := ROR((Block[2]-S[2*i+1]), Block[1]) xor Block[1];
  Block[1] := ROR((Block[1]-S[2*i]), Block[2]) xor Block[2];
  end;
 Dec(Block[2], S[1]);
 Dec(Block[1], S[0]);
 Result := TRUE;
end;
////////////////////////////////////////////////////////////////////////////////
// Реализация главных функций
function EncryptCopy(DestStream, SourseStream : TStream; Count: Int64;
 Key : string): Boolean;
var
 Buffer : TBlock;
 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, BlockSize);
  EncipherBlock(Buffer);
  DestStream.Write(Buffer, BlockSize);
  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 : TBlock;
 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, BlockSize);
  DecipherBlock(Buffer);
  DestStream.Write(Buffer, BlockSize);
  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 : TBlock;
 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, BlockSize);
  EncipherBlock(Buffer);
  DataStream.Seek(-BlockSize, soFromCurrent);
  DataStream.Write(Buffer, BlockSize);
  Inc(PrCount, 8);
  end;
 except
  Result := False;
 end;
end;
////////////////////////////////////////////////////////////////////////////////
function DecryptStream(DataStream: TStream; Count: Int64; Key: string): Boolean;
var
 Buffer : TBlock;
 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, BlockSize);
  DecipherBlock(Buffer);
  DataStream.Seek(-BlockSize, soFromCurrent);
  DataStream.Write(Buffer, BlockSize);
  Inc(PrCount, 8);
  end;
 except
  Result := False;
 end;
end;
// Завершение главных функций ...
////////////////////////////////////////////////////////////////////////////////
{$R+,Q+}
end.

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


DelphiWorld 6.0

Отправить комментарий

Проверка
Антиспам проверка
Image CAPTCHA
...