Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Класс THashMd5 (вычисляет хэш md5), реализовал класс,не уверен что правильно 
:(
    Опции темы
Чoо
Дата 23.12.2010, 19:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 22.9.2009

Репутация: нет
Всего: 4



Здравствуйте. Реализовал класс, протестировав его с разными входными  данными получаю правильный результат. Однако не вполне уверен в "нормальности" реализации, хоть "косяков" и не выявил. Буду благодарен, за указания на ошибки, грубые ошибки, технологические неправильности и прочее:
Код

unit HashMd5;

{$mode objfpc}{$H+}

interface

uses
    SysUtils; //<-- от сюда понадобится только IntToHex
type
    Thashmd5 = class
    private
      digest:array[0..3] of DWord; //4 ячейки по 32 бит. Для вычисления хэша
      buf:array[0..63] of byte;    //буфер для помещения данных, для которых рассчитывается хэш. 512 бит.
      T:array[1..64] of DWord;     //массив, в котором хранятся значения 2^32*|sin(i)|
      bytescount:DWord;            //если размер блока будет < 448 по модулю 512, то
                                   //будет указывать на смещение, с которого надо
                                   //начинать дополнение. В противном случае равно нулю
    procedure get_sin_values();    //заполняет массив Т целой частью от 2^32*|sin(i)|
    procedure init();              //осуществляет инициализацию при каждом вычислении хэша
    function lcs(a,b:DWord):DWord; //lcs - left cyclic shift (возвращает результат
                                   //циклического сдвига влево а на b разрядов
    {элементарные функции(одноименно с названиями в алгоритме получения хэша}
    function Ff(v1,v2,v3:DWord):DWord;
    function Fg(v1,v2,v3:DWord):DWord;
    function Fh(v1,v2,v3:DWord):DWord;
    function Fi(v1,v2,v3:DWord):DWord;

    {4 раунда вычислений}
    procedure first_round(var A,B,C,D:DWord; var X:array of DWord);
    procedure second_round(var A,B,C,D:dWORD; var X:array of DWord);
    procedure third_round(var A,B,C,D:dWORD; var X:array of DWord);
    procedure fourth_round(var A,B,C,D:dWORD; var X:array of DWord);

    {процедура, выполняющая вычисления для каждого блока по 512 байт}
    procedure hmd5();
  public
    constructor create;            //конструктор, выполняющий начальную инициализацию объекта}
    function get_md5(const source; _size:int64):string; //принимает нетипизированный блок байтов
                                   //и размер этого блока, возвращает хэш в виде строки
  end;

implementation

constructor Thashmd5.create;
begin
  get_sin_values;
end;

procedure THashmd5.get_sin_values;
var
  i:integer;
begin
  for i:=1 to 64 do
    T[i] := trunc(4294967296*abs(sin(i))); //2^32 = 4294967296. берем только целую часть
end;

procedure Thashmd5.init;
begin
  FillChar(digest,sizeof(digest),0); //заполняем дайджест нулями
  FillChar(buf,sizeof(buf),0); //заполняем буфер нулями
  bytescount:=0;
  //далее инициализация дайджеста начальными значениями
  digest[0]:=$67452301;
  digest[1]:=$efcdab89;
  digest[2]:=$98badcfe;
  digest[3]:=$10325476;
end;

function Thashmd5.lcs(a,b:DWord):DWord;
begin
     result := (a shl b) or (a shr (32-b)); //32 - размер DWord
end;

function Thashmd5.Ff(v1,v2,v3:DWord):DWord;
begin
    Ff:= (v1 and v2) or ((not v1) and v3);
end;

function THashmd5.Fg(v1,v2,v3:DWord):DWord;
begin
    Fg := (v1 and v3) or (v2 and (not v3));
end;

function THashmd5.Fh(v1,v2,v3:DWord):DWord;
begin
    Fh := v1 xor v2 xor v3;
end;

function THashmd5.Fi(v1,v2,v3:DWord):DWord;
begin
    Fi := v2 xor (v1 or (not v3));
end;

procedure Thashmd5.first_round(var A,B,C,D:DWord; var X:array of DWord);
    //вспомогательые процедуры, для вычислений в цикле
    procedure ABCD(k,s,i:integer);
    begin
      A := B+lcs((A+Ff(B,C,D)+X[k]+T[i]),s);
    end;
    procedure DABC(k,s,i:integer);
    begin
      D := A+lcs((D+Ff(A,B,C)+X[k]+T[i]),s);
    end;
    procedure CDAB(k,s,i:integer);
    begin
      C := D+lcs((C+Ff(D,A,B)+X[k]+T[i]),s);
    end;
    procedure BCDA(k,s,i:integer);
    begin
      B := C+lcs((B+Ff(C,D,A)+X[k]+T[i]),s);
    end;
begin
  { первый раунд
  [abcd k s i] a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s)
  где, k — номер 32-битного слова из n-го 512-битного блока сообщения
       s — циклический сдвиг влево на s бит полученого 32-битного аргумента.
       i - индекс 32-битного слова в матрице Т.

  [ABCD  0 7  1][DABC  1 12  2][CDAB  2 17  3][BCDA  3 22  4]
  [ABCD  4 7  5][DABC  5 12  6][CDAB  6 17  7][BCDA  7 22  8]
  [ABCD  8 7  9][DABC  9 12 10][CDAB 10 17 11][BCDA 11 22 12]
  [ABCD 12 7 13][DABC 13 12 14][CDAB 14 17 15][BCDA 15 22 16]}
  ABCD(0,7,1);  DABC(1,12,2);  CDAB(2,17,3);  BCDA(3,22,4);
  ABCD(4,7,5);  DABC(5,12,6);  CDAB(6,17,7);  BCDA(7,22,8);
  ABCD(8,7,9);  DABC(9,12,10); CDAB(10,17,11);BCDA(11,22,12);
  ABCD(12,7,13);DABC(13,12,14);CDAB(14,17,15);BCDA(15,22,16);
end;

procedure THashmd5.second_round(var A,B,C,D:DWord; var X:array of DWord);
    procedure ABCD(k,s,i:integer);
    begin
      A := B+lcs((A+Fg(B,C,D)+X[k]+T[i]),s);
    end;
    procedure DABC(k,s,i:integer);
    begin
      D := A+lcs((D+Fg(A,B,C)+X[k]+T[i]),s);
    end;
    procedure CDAB(k,s,i:integer);
    begin
      C := D+lcs((C+Fg(D,A,B)+X[k]+T[i]),s);
    end;
    procedure BCDA(k,s,i:integer);
    begin
      B := C+lcs((B+Fg(C,D,A)+X[k]+T[i]),s);
    end;
begin
  {  второй раунд
  [abcd k s i] a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s)
  [ABCD  1 5 17][DABC  6 9 18][CDAB 11 14 19][BCDA  0 20 20]
  [ABCD  5 5 21][DABC 10 9 22][CDAB 15 14 23][BCDA  4 20 24]
  [ABCD  9 5 25][DABC 14 9 26][CDAB  3 14 27][BCDA  8 20 28]
  [ABCD 13 5 29][DABC  2 9 30][CDAB  7 14 31][BCDA 12 20 32] }
  ABCD(1,5,17); DABC(6,9,18); CDAB(11,14,19);BCDA(0,20,20);
  ABCD(5,5,21); DABC(10,9,22);CDAB(15,14,23);BCDA(4,20,24);
  ABCD(9,5,25); DABC(14,9,26);CDAB(3,14,27); BCDA(8,20,28);
  ABCD(13,5,29);DABC(2,9,30); CDAB(7,14,31); BCDA(12,20,32);
end;

procedure THashmd5.third_round(var A,B,C,D:DWord; var X:array of DWord);
    procedure ABCD(k,s,i:integer);
    begin
      A := B+lcs((A+Fh(B,C,D)+X[k]+T[i]),s);
    end;
    procedure DABC(k,s,i:integer);
    begin
      D := A+lcs((D+Fh(A,B,C)+X[k]+T[i]),s);
    end;
    procedure CDAB(k,s,i:integer);
    begin
      C := D+lcs((C+Fh(D,A,B)+X[k]+T[i]),s);
    end;
    procedure BCDA(k,s,i:integer);
    begin
      B := C+lcs((B+Fh(C,D,A)+X[k]+T[i]),s);
    end;
begin
  {третий раунд
  [abcd k s i] a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s)
  [ABCD  5 4 33][DABC  8 11 34][CDAB 11 16 35][BCDA 14 23 36]
  [ABCD  1 4 37][DABC  4 11 38][CDAB  7 16 39][BCDA 10 23 40]
  [ABCD 13 4 41][DABC  0 11 42][CDAB  3 16 43][BCDA  6 23 44]
  [ABCD  9 4 45][DABC 12 11 46][CDAB 15 16 47][BCDA  2 23 48]}
  ABCD(5,4,33); DABC(8,11,34); CDAB(11,16,35);BCDA(14,23,36);
  ABCD(1,4,37); DABC(4,11,38); CDAB(7,16,39); BCDA(10,23,40);
  ABCD(13,4,41);DABC(0,11,42); CDAB(3,16,43); BCDA(6,23,44);
  ABCD(9,4,45); DABC(12,11,46);CDAB(15,16,47);BCDA(2,23,48);
end;

procedure THashmd5.fourth_round(var A,B,C,D:DWord; var X:array of DWord);
    procedure ABCD(k,s,i:integer);
    begin
      A := B+lcs((A+Fi(B,C,D)+X[k]+T[i]),s);
    end;
    procedure DABC(k,s,i:integer);
    begin
      D := A+lcs((D+Fi(A,B,C)+X[k]+T[i]),s);
    end;
    procedure CDAB(k,s,i:integer);
    begin
      C := D+lcs((C+Fi(D,A,B)+X[k]+T[i]),s);
    end;
    procedure BCDA(k,s,i:integer);
    begin
      B := C+lcs((B+Fi(C,D,A)+X[k]+T[i]),s);
    end;
begin
  { четвертый раунд
  [abcd k s i] a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s)
  [ABCD  0 6 49][0DABC  7 10 50][CDAB 14 15 51][BCDA  5 21 52]
  [ABCD 12 6 53][DABC  3 10 54][CDAB 10 15 55][BCDA  1 21 56]
  [ABCD  8 6 57][DABC 15 10 58][CDAB  6 15 59][BCDA 13 21 60]
  [ABCD  4 6 61][DABC 11 10 62][CDAB  2 15 63][BCDA  9 21 64]}
  ABCD(0,6,49); DABC(7,10,50); CDAB(14,15,51); BCDA(5,21,52);
  ABCD(12,6,53);DABC(3,10,54); CDAB(10,15,55); BCDA(1,21,56);
  ABCD(8,6,57); DABC(15,10,58);CDAB(6,15,59);  BCDA(13,21,60);
  ABCD(4,6,61); DABC(11,10,62);CDAB(2,15,63);  BCDA(9,21,64);
end;

procedure Thashmd5.hmd5;
var
  TMP:array[0..15] of DWord; //промежуточное "хранилище" для блока в 512 бит
                             //удобно хранить в таком формате, что бы прибавлять
                             //значения к вычислениям по индексу
  A, B, C, D:DWord;
begin
  move(buf,tmp,sizeof(tmp));
  A:=digest[0];
  B:=digest[1];
  C:=digest[2];
  D:=digest[3];

  first_round(A,B,C,D,TMP);
  second_round(A,B,C,D,TMP);
  third_round(A,B,C,D,TMP);
  fourth_round(A,B,C,D,TMP);

  inc(digest[0],A);
  inc(digest[1],B);
  inc(digest[2],C);
  inc(digest[3],D);

  fillchar(buf,sizeof(buf),0);
end;

function Thashmd5.get_md5(const source; _size:int64):string;
var
  psource:^byte; //указатель на источник. Для более удобного получения блоков по 512 бит
  hash:array [0..15] of byte; //сюда будет скопирован дайджест, что бы иметь
                              //возможность вывести побайтово представление
                              //хэша в виде hex
  size:int64;
  sizeinbits:int64; //размер в битах (в процедуру move можно передать только переменную)
  i:integer;
begin
  init;
  size := _size;
  sizeinbits:=_size*8;
  psource := @source;
  while(size > 0) do begin
    if(size >= 64) then begin
      move(psource^,buf[bytescount],sizeof(buf)-bytescount); //помещаем в буфер 64байта
                                                             //из истточника
      dec(size,sizeof(buf)-bytescount);
      inc(psource,sizeof(buf)-bytescount); //перемещаем указатель вперед на 64 байта
      hmd5;
    end
    else begin
      move(psource^,buf[bytescount],size);
      inc(bytescount,size);
      size := 0;
    end;
  end;
  {последняя фаза обработки. Здесь осуществляется выравнивание данных.
   выравнивание состояит в дополнении исходного буфера таким образом,
   что бы его длина стала равной 448 по модулю 512. Добовление состоит из
   единицы, за которой следует необходимое количество нулей.
   в случае, если оставшейся незаполненой длины буфера будет
   не достаточно, что бы разместить int64+1 байт, через hmd5 будет пропущено
   еще 2 пакета. Иначе 1}
  buf[bytescount] := $80; //80hex = 1000 0000bin
  if bytescount>= 56 then hmd5;
  move(sizeinbits,buf[56],8);   //int64 = 8 байт
  hmd5; //обработка последнего пакета
  move(digest,hash,sizeof(digest));  //полученный Хэш находится в массиве digest, копируем его в
                                     //hash для более удобного вывода
  result:='';
  for i:=0 to 15 do
    result:=result+inttohex(hash[i],2);
end;

end.

на всякий случай все подробно откомментировал. В процессе написания опирался на http://base.vingrad.ru/view/1154-Algoritm-shifrovaniya-MD5
потому код выглядит похожим smile. Конечно, можно было бы функции и процедуры целиком скопипастить в методы, но я решил сделать немного по-своему, что бы разобраться в том, как происходит вычисление.

пример использования:
Код

procedure TForm1.Button1Click(Sender: TObject);
var
  h:THashmd5;
begin
  try
    h:=THashmd5.create;
    edit1.text := h.get_md5(Memo1.lines.Text[1],length(memo1.Lines.text));
  finally
    h.free;
  end;
end;


Это сообщение отредактировал(а) Чoо - 23.12.2010, 21:16


--------------------
user posted image

OS: Debian Squeeze (kernel 3.8.2)
IDE: qtCreator 1.3.1; Eclipse SDK 3.5.2
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.2017 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.