RC6

Автор: Матвеев Игорь Как я уже говорил, Очень похож на RC5, во всяком случае расчет подключа производится тем же способом, что и в RC5. участвовал в конкурсе на звание AES и, по некоторым данным, не выиграл только из-за медленной работы аппаратных реализаций. Программные же реализации , пожалуй, являются самыми быстрыми среди алгоритмов шифрования, при обеспечении достаточной стойкости шифра. Нижепредставленный модуль построен по тому же принципу, что и предыдущие - имена функций совпадают и если вы хотите заменить в своей программе шифрование с IDEA или RC5 на - просто добавьте модуль , а IDEA или RC5 - удалите из списка uses. Шифр , в отличии от RC5, оперирует блоками по 16 байт, а модуль построен так, что если при шифрации методами: EncryptCopy, DecryptCopy, EncryptStream, DecryptStream размер данных не будет кратен 16 - последний блок длинной 1..15 байт не шифруется и в "чистом" виде добавляется к зашифрованным. Также и при дешифровании - если последний блок размером 1..15 байт он не дешифруется а добавляется к расшифрованным данным. Такой подход обеспечивает в полной мере "симметричное" шифрование так как размеры входных и выходных данных полностью совпадают. Однако такой подход приводит к некоторым сложностям, если последний блок также нуждается в шифровании. На мой взгляд лучший выход - добавить при шифровании к исходным данным строку определенной длинны и после дешифрования отсечь с конца строку той же длинны. Также в заключении цыкла статей, посвященных шифрованию я подготовил примеры по всем представленным алгоритмам (IDEA, RC5, ).

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

{ *********************************************************************** }

{ }

{ 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;

const

 Rounds = 20;

 KeyLength = 2 * (Rounds + 2);

 BlockSize = 16;

 KeySize = 16 * 4;

 P32 = $b7e15163;

 Q32 = $9e3779b9;

 lgw = 5;

type

 TBlock = 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

 Block : TBlock absolute Block;

 i      : Integer;

 t, u      : LongWord;

 Temp      : LongWord;

begin

 // Инициализация блока

 Inc(Block[2], S[0]);

 Inc(Block[4], S[1]);

 for i := 1 to Rounds do

  begin

  t := ROL((Block[2] * (2*Block[2] + 1)), lgw);

  u := ROL((Block[4] * (2*Block[4] + 1)), lgw);

  Block[1] := ROL((Block[1] xor t), u) + S[2*i];

  Block[3] := ROL((Block[3] xor u), t) + S[2*i+1];

  Temp := Block[1];

  Block[1] := Block[2];

  Block[2] := Block[3];

  Block[3] := Block[4];

  Block[4] := Temp;

  end;

 Block[1] := Block[1] + S[2*Rounds+2];

 Block[3] := Block[3] + S[2*Rounds+3];

 Result := TRUE;

end;

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

function DecipherBlock(var Block): Boolean;

var

 Block : TBlock absolute Block;

 i      : Integer;

 t, u      : LongWord;

 Temp      : LongWord;

begin

 // Инициализация блока

 Block[3] := Block[3] - S[2*Rounds+3];

 Block[1] := Block[1] - S[2*Rounds+2];

 for i := Rounds downto 1 do

  begin

  Temp := Block[4];

  Block[4] := Block[3];

  Block[3] := Block[2];

  Block[2] := Block[1];

  Block[1] := Temp;

  u := ROL((Block[4] * (2*Block[4] + 1)),lgw);

  t := ROL((Block[2] * (2*Block[2] + 1)),lgw);

  Block[3] := ROR((Block[3]-S[2*i+1]), t) xor u;

  Block[1] := ROR((Block[1]-S[2*i]), u) xor t;

  end;

 Dec(Block[4], S[1]);

 Dec(Block[2], 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 >= 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 : 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 >= 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 : 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 >= 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 : 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 >= 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.


DelphiWorld 6.0

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

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