Алгоритм RC6
От: PVOID http://www.pvoid.h11.ru/
Дата: 13.10.03 05:31
Оценка:
Plz, помогите кто-нть. Никак не могу найти алгоритм шифрования RC6. Очень нужен...
Как можно доверять чутью челоека мозг которого работает на лимонах?
Re: Алгоритм RC6
От: Alex Fedotov США  
Дата: 14.10.03 07:28
Оценка:
Здравствуйте, PVOID, Вы писали:

PVO>Plz, помогите кто-нть. Никак не могу найти алгоритм шифрования RC6. Очень нужен...


http://www.google.com/search?q=rc6+source
-- Alex Fedotov
Re[2]: Алгоритм RC6
От: bv77  
Дата: 13.10.08 18:18
Оценка:
Проблема шифрования алгоритмом RC6. Алгоритм работает на ура, есть только одна проблема, если остается кусок информации меньше 64 бит, то программа просто дописывает её без применения кодирования. Как решить эту проблему. Вот кусок кода отвечающий за шифрование:
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 PrCount <> Count 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;


Вот собственно весь код реализующий шифрование алгоритмом RC6:
unit RC6;

interface

uses
  SysUtils, Classes;

const
  Rounds    = 20; //количество раундов(проходов)
  KeyLength = 2 * (Rounds + 2);    //фрагменты расширенного ключа

  BlockSize = 16;   //размер блока байт
  KeySize   = 16 * 4;      //размер ключа 64байта

  P32       = $b7e15163;   //P32 и Q32 - псевдослучайные константы, образованные путем умножения на 2 в 32 степени дробной части
  Q32       = $9e3779b9;   //и последующего округления до ближайшего нечетного целого двух математических констант (e и ф соответственно)
  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 PrCount <> Count 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.
Re[3]: Алгоритм RC6
От: quodum  
Дата: 14.10.08 09:52
Оценка:
Здравствуйте, bv77, Вы писали:

B>Проблема шифрования алгоритмом RC6. Алгоритм работает на ура, есть только одна проблема, если остается кусок информации меньше 64 бит, то программа просто дописывает её без применения кодирования. Как решить эту проблему.


Ciphertext stealing
Re[3]: Алгоритм RC6
От: Кодт Россия  
Дата: 14.10.08 10:35
Оценка:
Здравствуйте, bv77, Вы писали:

B>Проблема шифрования алгоритмом RC6. Алгоритм работает на ура, есть только одна проблема, если остается кусок информации меньше 64 бит, то программа просто дописывает её без применения кодирования. Как решить эту проблему. Вот кусок кода отвечающий за шифрование:


Шифр блочный, поэтому в конец текста придётся напихать мусор.

Наша задача — научиться определять, где кончился текст и начался концевой мусор.
Для этого есть следующие способы:
1) записать незашифрованную длину текста в выходной поток
— либо в самом начале
— либо после последнего блока
2) подмешать длину текста во входной поток
— либо в самом начале
— либо в каждом блоке
— либо дописать маркер конца (символ EOF, например); естественно, что придётся выполнить кодирование, эскейпящее вхождения маркера в исходный текст

Вариант 1.1 самый простой в реализации, хотя и наименее затаённый.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Перекуём баги на фичи!
Re[4]: Алгоритм RC6
От: WolfHound  
Дата: 14.10.08 15:53
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Вариант 1.1 самый простой в реализации, хотя и наименее затаённый.

А самый простой вариант выкинуть блочный алгоритм и взять поточный. Чтонибудь из этих http://www.ecrypt.eu.org/stream/finallist.html
Еще один вариант еще раз зашифровать последний целый блок и проксорить результатом хвост.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: Алгоритм RC6
От: CreatorCray  
Дата: 15.10.08 07:53
Оценка: 1 (1)
Здравствуйте, Кодт, Вы писали:

B>>Проблема шифрования алгоритмом RC6. Алгоритм работает на ура, есть только одна проблема, если остается кусок информации меньше 64 бит, то программа просто дописывает её без применения кодирования. Как решить эту проблему. Вот кусок кода отвечающий за шифрование:


К>Шифр блочный, поэтому в конец текста придётся напихать мусор.

Есть еще вариант:
* Использовать OFB или CTR режим шифрования.

На пальцах — тута
Эти режимы по сути превращают блочный шифр в потоковый.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.