<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=75580&amp;view=findpost&amp;p=538542</guid>
        <pubDate>Fri, 10 Dec 2004 07:33:11 +0000</pubDate>
        <title>Алгоритм шифования TEA</title>
        <link>https://forum.sources.ru/index.php?showtopic=75580&amp;view=findpost&amp;p=538542</link>
        <description><![CDATA[Rouse_: <div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">////////////////////////////////////////////////////////////////////////////////</div><div class="code_line">//</div><div class="code_line">// &nbsp;****************************************************************************</div><div class="code_line">// &nbsp;* Unit Name : TEA</div><div class="code_line">// &nbsp;* Purpose &nbsp; : Модуль шифрования по алгоритму TEA</div><div class="code_line">// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(Tiny Encryption Algorithm)</div><div class="code_line">// &nbsp;* Author &nbsp; &nbsp;: Александр (Rouse_) Багель</div><div class="code_line">// &nbsp;* Version &nbsp; : 1.04</div><div class="code_line">// &nbsp;* Home Page : http://rouse.drkb.ru</div><div class="code_line">// &nbsp;****************************************************************************</div><div class="code_line">//</div><div class="code_line">&nbsp;</div><div class="code_line">// Схема действия</div><div class="code_line">// В функцию передается массив данных</div><div class="code_line">// Генерируется уникальный 128 битный ключ для кодирования на основе GUID</div><div class="code_line">// Вычисляется размер данных, они должны быть кратны четному</div><div class="code_line">// кол-ву 32 битных блоков, недостающий обьем заполняется мусором</div><div class="code_line">// Первые три байта занимает заголовок ETA</div><div class="code_line">// В четвертую позицию данных добавляется значение указывающее объем мусора</div><div class="code_line">// Производится кодирование ранее сгенерированным ключем</div><div class="code_line">// Сам ключ кодируется внутренним ключем, делится на четыре части</div><div class="code_line">// 128 битный ключ разделяется на четыре 32 битных блока</div><div class="code_line">// Ключ добавляется в данные со сдвигом в любое место</div><div class="code_line">// в следующем порядке 4-ый, 3-ий, 1-ый, 2-ой блоки</div><div class="code_line">// На 14 ую позицию данных вставляется со сдвигом указатель на начало ключа</div><div class="code_line">// Итого в закодированном буффере находится помимо основной</div><div class="code_line">// еще и 21 байт служебной информации</div><div class="code_line">// Для раскодирования все действи производится в обратном порядке</div><div class="code_line">&nbsp;</div><div class="code_line">unit TEA;</div><div class="code_line">&nbsp;</div><div class="code_line">{$Q-} // Отключаем INTEGER OVERFLOW</div><div class="code_line">&nbsp;</div><div class="code_line">interface</div><div class="code_line">&nbsp;</div><div class="code_line">uses</div><div class="code_line">&nbsp;&nbsp;Windows,</div><div class="code_line">&nbsp;&nbsp;SysUtils,</div><div class="code_line">&nbsp;&nbsp;Classes;</div><div class="code_line">&nbsp;</div><div class="code_line">const</div><div class="code_line">&nbsp;&nbsp;Delta = E3779B9; &nbsp;// Смещение контрольной суммы ~ 32 бит</div><div class="code_line">&nbsp;&nbsp;Header = &#39;ETA&#39;; // Enhanced TEA</div><div class="code_line">&nbsp;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;_k0: DWORD = 0; &nbsp; &nbsp;// Главный 128 битный ключ (4 части по 32 бита)</div><div class="code_line">&nbsp;&nbsp;_k1: DWORD = 0; &nbsp; &nbsp;// Его нужно изменить на свой аналог...</div><div class="code_line">&nbsp;&nbsp;_k2: DWORD = 0;</div><div class="code_line">&nbsp;&nbsp;_k3: DWORD = 0;</div><div class="code_line">&nbsp;</div><div class="code_line">type</div><div class="code_line">&nbsp;&nbsp;PHash = ^THash;</div><div class="code_line">&nbsp;&nbsp;THash = array of Byte;</div><div class="code_line">&nbsp;&nbsp;Int256 = array [0..31] of Byte;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;procedure EnCript(var S: THash);</div><div class="code_line">&nbsp;&nbsp;procedure EnCryptStream(Stream: TStream);</div><div class="code_line">&nbsp;&nbsp;function DeCript(var S: THash): Boolean;</div><div class="code_line">&nbsp;&nbsp;function DeCriptStream(Stream: TStream): Boolean;</div><div class="code_line">&nbsp;&nbsp;procedure SetDefaultKey;</div><div class="code_line">&nbsp;&nbsp;procedure SetKey(Value: Int256);</div><div class="code_line">&nbsp;</div><div class="code_line">implementation</div><div class="code_line">&nbsp;</div><div class="code_line">// &nbsp;Установка ключа по умолчанию (DEMO - ключ)</div><div class="code_line">// =============================================================================</div><div class="code_line">procedure SetDefaultKey;</div><div class="code_line">begin &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp;_k0 := 2C98C1; &nbsp; &nbsp;// Главный 128 битный ключ (4 части по 32 бита)</div><div class="code_line">&nbsp;&nbsp;_k1 := F8F4D4B; &nbsp; &nbsp;// Его нужно изменить на свой аналог...</div><div class="code_line">&nbsp;&nbsp;_k2 := $BCAE3151;</div><div class="code_line">&nbsp;&nbsp;_k3 := 1BC789;</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// &nbsp;Установка рабочего ключа</div><div class="code_line">// =============================================================================</div><div class="code_line">procedure SetKey(Value: Int256);</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;XorKey: DWORD;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;// Ну например вот так :)</div><div class="code_line">&nbsp;&nbsp;Move(Value[0], _k0, 4);</div><div class="code_line">&nbsp;&nbsp;Move(Value[4], XorKey, 4);</div><div class="code_line">&nbsp;&nbsp;_k0 := _k0 xor XorKey;</div><div class="code_line">&nbsp;&nbsp;Move(Value[4], _k1, 4);</div><div class="code_line">&nbsp;&nbsp;Move(Value[12], XorKey, 4);</div><div class="code_line">&nbsp;&nbsp;_k1 := _k1 xor XorKey;</div><div class="code_line">&nbsp;&nbsp;Move(Value[24], _k2, 4);</div><div class="code_line">&nbsp;&nbsp;Move(Value[20], XorKey, 4);</div><div class="code_line">&nbsp;&nbsp;_k2 := _k2 xor XorKey;</div><div class="code_line">&nbsp;&nbsp;Move(Value[16], _k3, 4);</div><div class="code_line">&nbsp;&nbsp;Move(Value[28], XorKey, 4);</div><div class="code_line">&nbsp;&nbsp;_k3 := _k3 xor XorKey;</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">////////////////////////////////////////////////////////////////////////////////</div><div class="code_line">//</div><div class="code_line">// ЧАСТЬ ПЕРВАЯ * * * КОДИРОВАНИЕ * * *</div><div class="code_line">&nbsp;</div><div class="code_line">procedure EnCript(var S: THash);</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;InBuf,</div><div class="code_line">&nbsp;&nbsp;OutBuf,</div><div class="code_line">&nbsp;&nbsp;ResultBuf: THash; &nbsp; // Входной, выходной и результирующий буфера</div><div class="code_line">&nbsp;&nbsp;Y, Z, Sum: LongWord; &nbsp; &nbsp; &nbsp; &nbsp;// Временные переменные для кодируемых блоков данных</div><div class="code_line">&nbsp;&nbsp;k0, k1, k2 , k3: LongWord; &nbsp;// Текущий ключ для шифрования</div><div class="code_line">&nbsp;&nbsp;I, A, Len: Integer; &nbsp; &nbsp; &nbsp; &nbsp; // Переменные для циклов</div><div class="code_line">&nbsp;&nbsp;C: Byte; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Счетчик кол-ва мусора</div><div class="code_line">&nbsp;&nbsp;Guid, Key: String;</div><div class="code_line">&nbsp;&nbsp;G: TGUID;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;// Проверка заданного ключа</div><div class="code_line">&nbsp;&nbsp;if _k0 = 0 then SetDefaultKey;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Проверка размера данных</div><div class="code_line">&nbsp;&nbsp;if Length(S) = 0 then Exit;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;Randomize;</div><div class="code_line">&nbsp;&nbsp;</div><div class="code_line">&nbsp;&nbsp;CreateGUID(G); // Генерируем ключик на основе GUID - а :)</div><div class="code_line">&nbsp;&nbsp;Guid := GUIDToString(G);</div><div class="code_line">&nbsp;&nbsp;for I := 1 to Length(Guid) do</div><div class="code_line">&nbsp;&nbsp; &nbsp;if Guid[I] in [&#39;0&#39;..&#39;9&#39;, &#39;A&#39;..&#39;F&#39;] then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Key := Key + Guid[I]; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;k0 := StrToInt64(&#39;$&#39; + Copy(Key, 1, 8));</div><div class="code_line">&nbsp;&nbsp;k1 := StrToInt64(&#39;$&#39; + Copy(Key, 9, 8));</div><div class="code_line">&nbsp;&nbsp;k2 := StrToInt64(&#39;$&#39; + Copy(Key, 17, 8));</div><div class="code_line">&nbsp;&nbsp;k3 := StrToInt64(&#39;$&#39; + Copy(Key, 25, 8));</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;C := 0; // Инициализируем счетчик дозаполнений</div><div class="code_line">&nbsp;&nbsp;// Дозаполняем данные чтобы последний блок данных был равен 64 битам</div><div class="code_line">&nbsp;&nbsp;while (Length(S) div 8) * 8 &#60;&#62; Length(S) do // 64 бита = 8 байтам :)</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;Len := Length(S);</div><div class="code_line">&nbsp;&nbsp; &nbsp;Inc(Len);</div><div class="code_line">&nbsp;&nbsp; &nbsp;SetLength(S, Len);</div><div class="code_line">&nbsp;&nbsp; &nbsp;S[Len - 1] := Random(255); // Заполняем случайными данными</div><div class="code_line">&nbsp;&nbsp; &nbsp;Inc(C);</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;Len := Length(S); // Вычисляем размер кодируемого блока</div><div class="code_line">&nbsp;&nbsp;SetLength(InBuf, Len); &nbsp;// Устанавливаем размер буферов</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Размер выходного буфера увеличен на 21 байт из-за</div><div class="code_line">&nbsp;&nbsp;// 3 байта - заголовок ETA</div><div class="code_line">&nbsp;&nbsp;// 1 байт - счетчик кол-ва мусора в конце буфера</div><div class="code_line">&nbsp;&nbsp;// 16 байт - кодированный ключ - 4 Cardinal </div><div class="code_line">&nbsp;&nbsp;// 1 байт - метка расположения кодированного ключа</div><div class="code_line">&nbsp;&nbsp;Inc(Len, 21);</div><div class="code_line">&nbsp;&nbsp;SetLength(OutBuf, Len);</div><div class="code_line">&nbsp;&nbsp;SetLength(ResultBuf, Len);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;Inc(C);// Увеличим кол-во мусора для удаления самого поля счетчика</div><div class="code_line">&nbsp;&nbsp;OutBuf[0] := Ord(Header[1]); // добавляем идентификатор</div><div class="code_line">&nbsp;&nbsp;OutBuf[1] := Ord(Header[2]);</div><div class="code_line">&nbsp;&nbsp;OutBuf[2] := Ord(Header[3]);</div><div class="code_line">&nbsp;&nbsp;OutBuf[3] := C; // Добавляем счетчик мусора</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;Move(S[0], InBuf[0], Length(S));// Заполняем входной буфер данными</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;I := 0;</div><div class="code_line">&nbsp;&nbsp;while I &#60; Len - 21 do // Непосредственно кодировка</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;Move(InBuf[I], Y, 4); &nbsp; &nbsp; // Берем первые 32 бита</div><div class="code_line">&nbsp;&nbsp; &nbsp;Move(InBuf[I + 4], Z, 4); // Берем вторые 32 бита</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Кодируем</div><div class="code_line">&nbsp;&nbsp; &nbsp;Sum := 0;</div><div class="code_line">&nbsp;&nbsp; &nbsp;for A := 0 to 31 do &nbsp;// 64 битный кодируемый блок (2 части по 32 бита)</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Inc(Sum, Delta);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Inc(Y, ((Z shl 4) + k0) xor (Z + Sum) xor ((Z shr 5) + k1));</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Inc(Z, ((Y shl 4) + k2) xor (Y + Sum) xor ((Y shr 5) + k3));</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Move (Y, OutBuf[I + 4], 4); // Помещаем кодированные блоки в выходном буфер</div><div class="code_line">&nbsp;&nbsp; &nbsp;Move (Z, OutBuf[I + 8], 4);</div><div class="code_line">&nbsp;&nbsp; &nbsp;Inc(I, 8); // Пропускаем обработанный блок, переходим к следующему</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;Sum := 0;</div><div class="code_line">&nbsp;&nbsp;for A := 0 to 31 do &nbsp;// Кодируем первые 2 части ключа внутренним ключем</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;Inc(sum,Delta);</div><div class="code_line">&nbsp;&nbsp; &nbsp;Inc(k0, ((k1 shl 4) + _k0) xor (k1 + Sum) xor ((k1 shr 5) + _k1));</div><div class="code_line">&nbsp;&nbsp; &nbsp;Inc(k1, ((k0 shl 4) + _k2) xor (k0 + Sum) xor ((k0 shr 5) + _k3));</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;Sum := 0;</div><div class="code_line">&nbsp;&nbsp;for A := 0 to 31 do &nbsp;// Кодируем вторые 2 части ключа внутренним ключем</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;Inc(Sum, Delta);</div><div class="code_line">&nbsp;&nbsp; &nbsp;Inc(k2, ((k3 shl 4) + _k0) xor (k3 + Sum) xor ((k3 shr 5) + _k1));</div><div class="code_line">&nbsp;&nbsp; &nbsp;Inc(k3, ((k2 shl 4) + _k2) xor (k2 + Sum) xor ((k2 shr 5) + _k3));</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Определяем позицию размещения ключа в блоке данных</div><div class="code_line">&nbsp;&nbsp;Randomize;</div><div class="code_line">&nbsp;&nbsp;if Len &#60; 255 then</div><div class="code_line">&nbsp;&nbsp; &nbsp;I := Len</div><div class="code_line">&nbsp;&nbsp;else</div><div class="code_line">&nbsp;&nbsp; &nbsp;I := 255;</div><div class="code_line">&nbsp;&nbsp;repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp;I := Random(I);</div><div class="code_line">&nbsp;&nbsp; &nbsp;if I &#60; 4 then I := 4;</div><div class="code_line">&nbsp;&nbsp;until I &#60; Len - 16; // &#60;- исправление глюка с шифрованием маленьких блоков данных</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Смещаем данные освобождая место для четырех</div><div class="code_line">&nbsp;&nbsp;// частей ключа</div><div class="code_line">&nbsp;&nbsp;Move(OutBuf[0], ResultBuf[0], I);</div><div class="code_line">&nbsp;&nbsp;Move(OutBuf[I], ResultBuf[I + 16], Len - I - 17);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Разбиваем четвертую четверть ключа на 4 восьмибитных части</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I] &nbsp; &nbsp;:= Byte(k3 shr 24);</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I + 1] &nbsp;:= Byte(k3 shr 16);</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I + 2] &nbsp;:= Byte(k3 shr 8);</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I + 3] &nbsp;:= Byte(k3);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Разбиваем третью четверть ключа на 4 восьмибитных части</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I + 4] &nbsp;:= Byte(k2 shr 24);</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I + 5] &nbsp;:= Byte(k2 shr 16);</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I + 6] &nbsp;:= Byte(k2 shr 8);</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I + 7] &nbsp;:= Byte(k2);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Разбиваем первую четверть ключа на 4 восьмибитных части</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I + 8] &nbsp;:= Byte(k0 shr 24);</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I + 9] &nbsp;:= Byte(k0 shr 16);</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I + 10] := Byte(k0 shr 8);</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I + 11] := Byte(k0);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Разбиваем вторую четверть ключа на 4 восьмибитных части</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I + 12] := Byte(k1 shr 24);</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I + 13] := Byte(k1 shr 16);</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I + 14] := Byte(k1 shr 8);</div><div class="code_line">&nbsp;&nbsp;ResultBuf[I + 15] := Byte(k1);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Сдвигаем данные с 14 позиции на одну вправо для метки</div><div class="code_line">&nbsp;&nbsp;// (буфер начинается с нуля)</div><div class="code_line">&nbsp;&nbsp;for A := Len - 1 downto 14 do</div><div class="code_line">&nbsp;&nbsp; &nbsp;ResultBuf[A] := ResultBuf[A - 1];</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Помещаем метку начала ключа (14-й байт)</div><div class="code_line">&nbsp;&nbsp;ResultBuf[13] := I;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;S := ResultBuf;</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// &nbsp;Функция кодирует стрим с текущей позиции и до конца.</div><div class="code_line">// &nbsp;Результат помещается в текущую позицию. Размеры стрима корректируются</div><div class="code_line">// =============================================================================</div><div class="code_line">procedure EnCryptStream(Stream: TStream);</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;Template: THash;</div><div class="code_line">&nbsp;&nbsp;Position: Int64;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;if Stream = nil then</div><div class="code_line">&nbsp;&nbsp; &nbsp;raise Exception.Create(&#39;Empty stream.&#39;);</div><div class="code_line">&nbsp;&nbsp;Position := Stream.Position;</div><div class="code_line">&nbsp;&nbsp;SetLength(Template, Stream.Size - Position);</div><div class="code_line">&nbsp;&nbsp;Stream.Read(Template[0], Length(Template));</div><div class="code_line">&nbsp;&nbsp;EnCript(Template);</div><div class="code_line">&nbsp;&nbsp;Stream.Size := Position + Length(Template);</div><div class="code_line">&nbsp;&nbsp;Stream.Position := Position;</div><div class="code_line">&nbsp;&nbsp;Stream.Write(Template[0], Length(Template));</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">////////////////////////////////////////////////////////////////////////////////</div><div class="code_line">//</div><div class="code_line">// ЧАСТЬ ВТОРАЯ * * * ДЕКОДИРОВАНИЕ * * *</div><div class="code_line">&nbsp;</div><div class="code_line">function DeCript (var S: THash): Boolean;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;InBuf,</div><div class="code_line">&nbsp;&nbsp;OutBuf,</div><div class="code_line">&nbsp;&nbsp;ResultBuf: THash; // Входной, выходной и результирующий буфера</div><div class="code_line">&nbsp;&nbsp;Y , Z, Sum: LongWord; &nbsp; &nbsp; // Временные переменные для кодируемых блоков данных</div><div class="code_line">&nbsp;&nbsp;k0, k1, k2, k3: LongWord; // Текущий ключ для шифрования</div><div class="code_line">&nbsp;&nbsp;I, A, Len: Integer; &nbsp; &nbsp; &nbsp; // Переменные для циклов</div><div class="code_line">&nbsp;&nbsp;AHeader: String;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;Result := False;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Проверка заданного ключа</div><div class="code_line">&nbsp;&nbsp;if _k0 = 0 then SetDefaultKey;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;Len := Length(S); // Вычисляем размер декодируемого блока</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Проверка размера</div><div class="code_line">&nbsp;&nbsp;if Len &#60; 27 then Exit;</div><div class="code_line">&nbsp;&nbsp;if Len &#60;&#62; (((Len - 21) div 8) * 8) + 21 then Exit;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Проверка заголовка</div><div class="code_line">&nbsp;&nbsp;AHeader := Char(S[0]) + Char(S[1]) + Char(S[2]);</div><div class="code_line">&nbsp;&nbsp;if AHeader &#60;&#62; Header then Exit;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Проверка позиции ключа</div><div class="code_line">&nbsp;&nbsp;if not(S[13] in [4..255]) then Exit;</div><div class="code_line">&nbsp;&nbsp;if S[13] + 16 &#62; Len then Exit;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Проверка счетчика мусора</div><div class="code_line">&nbsp;&nbsp;if S[3] &#62; 8 then Exit;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;SetLength(InBuf, Len); &nbsp;// Устанавливаем размер буферов</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;Move(S[0], InBuf[0], Len);// Заполняем входной буфер данными</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;I := InBuf[13]; // Узнаем начальную позицию ключа</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Удаляем метку на начало ключа</div><div class="code_line">&nbsp;&nbsp;for A := 13 to Len - 2 do</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;InBuf[A] := InBuf[A + 1];</div><div class="code_line">&nbsp;&nbsp; &nbsp;InBuf[A + 1] := 0;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;&nbsp;Dec(Len);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Извлекаем ключ</div><div class="code_line">&nbsp;&nbsp;k3 :=(InBuf[I + 3] or (InBuf[I + 2] shl 8) or (InBuf[I + 1] shl 16) or (InBuf[I] shl 24));</div><div class="code_line">&nbsp;&nbsp;k2 :=(InBuf[I + 7] or (InBuf[I + 6] shl 8) or (InBuf[I + 5] shl 16) or (InBuf[I + 4] shl 24));</div><div class="code_line">&nbsp;&nbsp;k0 :=(InBuf[I + 11] or (InBuf[I + 10] shl 8) or (InBuf[I + 9] shl 16) or (InBuf[I + 8] shl 24));</div><div class="code_line">&nbsp;&nbsp;k1 :=(InBuf[I + 15] or (InBuf[I + 14] shl 8) or (InBuf[I + 13] shl 16) or (InBuf[I + 12] shl 24));</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Удаляем ключ из блока данных</div><div class="code_line">&nbsp;&nbsp;for A := I + 16 to Len do</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;InBuf[A - 16] := InBuf[A];</div><div class="code_line">&nbsp;&nbsp; &nbsp;InBuf[A] := 0;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;&nbsp;SetLength(OutBuf, Len);</div><div class="code_line">&nbsp;&nbsp;ZeroMemory(OutBuf, Len);</div><div class="code_line">&nbsp;&nbsp;Dec(Len, 16); // Удаляем размер ключа</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Декодируем первые две части ключа</div><div class="code_line">&nbsp;&nbsp;Sum := Delta shl 5;</div><div class="code_line">&nbsp;&nbsp;for A := 0 to 31 do</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dec(k1, ((k0 shl 4) + _k2) xor (k0 + Sum) xor ((k0 shr 5) + _k3));</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dec(k0, ((k1 shl 4) + _k0) xor (k1 + Sum) xor ((k1 shr 5) + _k1));</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dec(Sum, Delta);</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Декодируем вторые две части ключа</div><div class="code_line">&nbsp;&nbsp;Sum := Delta shl 5;</div><div class="code_line">&nbsp;&nbsp;for A := 0 to 31 do</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dec(k3, ((k2 shl 4) + _k2) xor (k2 + Sum) xor ((k2 shr 5) + _k3));</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dec(k2, ((k3 shl 4) + _k0) xor (k3 + Sum) xor ((k3 shr 5) + _k1));</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dec(Sum, Delta);</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;I := 0;</div><div class="code_line">&nbsp;&nbsp;Dec(Len); // Удяляем из размера место счетчика мусора</div><div class="code_line">&nbsp;&nbsp;Dec(Len, 3); // Удаляем из размера заголовок ETA</div><div class="code_line">&nbsp;&nbsp;while I &#60; Len do // Непосредственно декодировка</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;Move(InBuf[I + 4], Y, 4); &nbsp;// Берем первые 32 бита</div><div class="code_line">&nbsp;&nbsp; &nbsp;Move(InBuf[I + 8], Z, 4); &nbsp;// Берем вторые 32 бита</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Декодируем</div><div class="code_line">&nbsp;&nbsp; &nbsp;Sum := Delta shl 5;</div><div class="code_line">&nbsp;&nbsp; &nbsp;for A := 0 to 31 do &nbsp;// 64 битный кодируемый блок (2 части по 32 бита)</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Dec(Z, ((Y shl 4) + k2) xor (Y + Sum) xor ((Y shr 5) + k3));</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Dec(Y, ((Z shl 4) + k0) xor (Z + Sum) xor ((Z shr 5) + k1));</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Dec(Sum, Delta);</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Move(Y, OutBuf[I], 4); &nbsp;// Запоминаем кодированные блоки в выходном буфере</div><div class="code_line">&nbsp;&nbsp; &nbsp;Move(Z, OutBuf[I + 4], 4);</div><div class="code_line">&nbsp;&nbsp; &nbsp;Inc(I, 8); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Пропускаем обработанный блок, переходим к следующему</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Отрезаем мусор (-1 потому что место для счетчика уже удалено из Len)</div><div class="code_line">&nbsp;&nbsp;Len := Len - (InBuf[3] - 1);</div><div class="code_line">&nbsp;&nbsp;SetLength(ResultBuf, Len);</div><div class="code_line">&nbsp;&nbsp;Move(OutBuf[0], ResultBuf[0], Len);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Выводим текст из выходного буфера</div><div class="code_line">&nbsp;&nbsp;S := ResultBuf;</div><div class="code_line">&nbsp;&nbsp;Result := True;</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// &nbsp;Функция декодирует стрим с текущей позиции и до конца.</div><div class="code_line">// &nbsp;Результат помещается в текущую позицию. Размеры стрима корректируются</div><div class="code_line">// =============================================================================</div><div class="code_line">function DeCriptStream(Stream: TStream): Boolean;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;Template: THash;</div><div class="code_line">&nbsp;&nbsp;Position: Int64;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;if Stream = nil then</div><div class="code_line">&nbsp;&nbsp; &nbsp;raise Exception.Create(&#39;Empty stream.&#39;);</div><div class="code_line">&nbsp;&nbsp;Position := Stream.Position;</div><div class="code_line">&nbsp;&nbsp;SetLength(Template, Stream.Size - Position);</div><div class="code_line">&nbsp;&nbsp;Stream.Read(Template[0], Length(Template));</div><div class="code_line">&nbsp;&nbsp;Result := DeCript(Template);</div><div class="code_line">&nbsp;&nbsp;Stream.Size := Position + Length(Template);</div><div class="code_line">&nbsp;&nbsp;Stream.Position := Position;</div><div class="code_line">&nbsp;&nbsp;Stream.Write(Template[0], Length(Template));</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">end.</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script>]]></description>
        <author>Rouse_</author>
        <category>Алгоритмы</category>
      </item>
	
      </channel>
      </rss>
	