Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 03.05.2011, 00:16   #1
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,285
По умолчанию SHA1-хеширование (проблемы с русскими буквами)

Мне понадобилось хешировать некоторый текст методом SHA1 (не будем вдаваться в подробности). Для этого я стал искать примеры реализации на Delphi. И нашел... Код я, как смог, доработал (заработал в Delphi 2010, правильный хеш пустой строки), но программа выдает неправильный хеш русского текста, т.е.
Текст:В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!
Википедия:9e32295f8225803bb6d5fdfcc 0674616a4413c1b
Online HASH генератор:9e32295f8225803bb6d5fdfcc0674616a4 413c1b
Моя программа:B2C19A50D47B89F9896AEF70F D6FB0F383F5E6BB
HashTab:B2C19A50D47B89F9896AEF70FD6 FB0F383F5E6BB
Кто прав?
Код:
unit sha1hash;

interface

uses sysutils;

const
  HC0 = $67452301;
  HC1 = $EFCDAB89;
  HC2 = $98BADCFE;
  HC3 = $10325476;
  HC4 = $C3D2E1F0;

  K1 = $5A827999;
  K2 = $6ED9EBA1;
  K3 = $8F1BBCDC;
  K4 = $CA62C1D6;

var
  H0, H1, H2, H3, H4: integer;

function sha1(z: RawByteString): string;

implementation

function rol(const x: integer; const y: byte): integer;
// сдвиг числа x на y бит влево
begin
  asm
    mov  eax,x
    mov  cl, y
    rol  eax,cl
    mov  x, eax
  end;
  Result := x;
end;

procedure INIT; // Инициализация - присвоить переменным значения констант
begin
  H0 := HC0; // $67452301;
  H1 := HC1; // $EFCDAB89;
  H2 := HC2; // $98BADCFE;
  H3 := HC3; // $10325476;
  H4 := HC4; // $C3D2E1F0;
end;

function PADDING(S: RawByteString; FS: integer): RawByteString; // добавление одного бита (1000000=128) и добавление нулей до кратности 64 байтам
var
  size, i: integer;
begin
  size := Length(S) * 8; // size -входной размер в битах
  S := S + #$80; // добавление одного бита  (1000000=128)

  while (Length(S) mod 64) <> 0 do
    S := S + #0; // добавление нулей до кратности 64  байтам

  IF ((size mod 512) >= 448) then // если хвост превышает 48 байт то добавить пустой блок из 64 нулей
  begin
    S := S + #0; // добавление нулей до кратности 64
    while (Length(S) mod 64) <> 0 do
      S := S + #0;
  end;

  i := Length(S);
  size := FS * 8;
  while size > 0 do // запись в конец строки её размер
  begin
    S[i] := ansichar(byte(size)); // получение младшего байта
    size := size shr 8; // сдвиг вправо на 8 бит - перенос старшего байта на место младшего
    i := i - 1;
  end;
  Result := S;
end;

Procedure START(const S_IN: RawByteString);
var
  A, B, C, D, E, TEMP: integer;
  t, i: byte;
  W: array [0 .. 79] of integer;
begin

  t := 1;
  for i := 1 to ((Length(S_IN)) div 4) do
  begin
    W[i - 1] := (ord(S_IN[t]) shl 24) + (ord(S_IN[t + 1]) shl 16) +
      (ord(S_IN[t + 2]) shl 8) + ord(S_IN[t + 3]);
    t := t + 4;
  end;

  For t := 16 to 79 do
    W[t] := rol(W[t - 3] XOR W[t - 8] XOR W[t - 14] XOR W[t - 16], 1);

  A := H0;
  B := H1;
  C := H2;
  D := H3;
  E := H4;

  for t := 0 to 19 do
  begin
    TEMP := rol(A, 5) + ((B AND C) OR ((NOT B) AND D)) + E + K1 + W[t];
    E := D;
    D := C;
    C := rol(B, 30);
    B := A;
    A := TEMP;
  end;
  for t := 20 to 39 do
  begin
    TEMP := rol(A, 5) + (B XOR C XOR D) + E + K2 + W[t];
    E := D;
    D := C;
    C := rol(B, 30);
    B := A;
    A := TEMP;
  end;
  for t := 40 to 59 do
  begin
    TEMP := rol(A, 5) + ((B AND C) OR (B AND D) OR (C AND D)) + E + K3 + W[t];
    E := D;
    D := C;
    C := rol(B, 30);
    B := A;
    A := TEMP;
  end;
  for t := 60 to 79 do
  begin
    TEMP := rol(A, 5) + (B XOR C XOR D) + E + K4 + W[t];
    E := D;
    D := C;
    C := rol(B, 30);
    B := A;
    A := TEMP;
  end;

  H0 := A + H0;
  H1 := B + H1;
  H2 := C + H2;
  H3 := D + H3;
  H4 := E + H4;
end;

function min(A, B: integer): integer;
begin
  Result := (-abs(A - B) + A + B) div 2;
end;

function sha1(z: RawByteString): string;
var
  S, s1: RawByteString;
  i, L, FS: integer;
begin
  S := '';
  FS := Length(z);
  INIT;
  repeat
    L := min(65536, Length(z));
    S := copy(z, 1, L);
    delete(z, 1, L);
    IF ((L < 65536) and (L > 0)) then
    begin
      s1 := PADDING(S, FS);
      i := 1;
      L := Length(s1);
      while i < L do
      begin
        START(copy(s1, i, 64));
        i := i + 64;
      end;
    end;
    if L = 0 then
    begin
      s1 := PADDING(S, FS);
      START(copy(s1, 1, 64));
    end;
    IF L = 65536 then
    begin
      i := 1;
      L := Length(s1);
      while i < L do
      begin
        START(copy(s1, i, 64));
        i := i + 64;
      end;
    end;
  until Length(z) = 0;
  Result := IntToHex(H0, 8) + IntToHex(H1, 8) + IntToHex(H2, 8) + IntToHex(H3,
    8) + IntToHex(H4, 8);
end;

end.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA на форуме Ответить с цитированием
Старый 03.05.2011, 08:55   #2
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,238
По умолчанию

100% дело в исходной кодировке!

для русского текста она может быть (из широкораспространнённых)
866 (она же DOS, она же OEM)
1251 (она же Windows, она же ANSI)
KOI8-R
UNICODE (и тоже разные варианты и форматы)..

p.s. берите хэш для текста, заданного в виде БАЙТ!

ДОБАВЛЕНО
У Вас подсчёт правильный, для строки, заданной в кодировке 1251:
Цитата:
Сообщение от DAMN Hash Calculator v1.5.1
Calculating hash of 54 bytes string `В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!`...

SHA-160 : B2C19A50D47B89F9896AEF70FD6FB0F383F 5E6BB
....

Последний раз редактировалось Serge_Bliznykov; 03.05.2011 в 09:03.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 03.05.2011, 10:10   #3
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Распечатайте бумажку с надписью НЕ СУЩЕСТВУЕТ ТАКОЙ ВЕЩИ КАК "ПРОСТО ТЕКСТ" и повесьте себе на монитор

Пока вы не говорите о том, в какой кодировке у вас находится строка, вы не сможете даже определить, где она заканчивается.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 03.05.2011, 11:10   #4
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,238
По умолчанию

GunSmoker, +1

а вот и ссылочка на статью
(обычно эту ссылку сам GunSmoker публикует, но он, видимо, устал )

Абсолютный Минимум, который Каждый Разработчик Программного Обеспечения Обязательно Должен Знать о Unicode и Наборах Символов

Это раз.

второе.
я провел исследование.
и выяснил, что и википедия и ваш онлайт калькулятор вычисляют SHA для русского текста, заданного в формате UTF-8 (БЕЗ ЗАГОЛОВКА)
поэтому, если есть желание получать идентичные результаты,
задавайте исходную строку (или переводите её) в формат UTF-8
Serge_Bliznykov вне форума Ответить с цитированием
Старый 03.05.2011, 18:39   #5
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,285
По умолчанию

GunSmoker, да, насчет не указания кодировки я "ступил".
Serge_Bliznykov, спасибо за исследование) Я попробовал в OEM 866 переводить ту строчку, а про UTF-8 не догадался. Хотя именно в этой кодировке будет текст для хешинга (пытаюсь сделать генерацию Magnet URI по torrent файлу).
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA на форуме Ответить с цитированием
Старый 08.09.2017, 17:50   #6
dwa_e
 
Регистрация: 06.01.2008
Сообщений: 8
По умолчанию

Пробую использовать unit sha1hash для получения hash из HEX строки, и просто на пролом ничего не получается

Код:
Memo1.Lines.Add(sha1hash(Edit1.Text)); // в edit1.text - 12345678 	
//результат 	7c222fb2927d828af22f592134e8932480637c0d
а если делать так

Код:
Memo1.Lines.Add(sha1hash(#$12#$34#$56#$78));
//результат       9bce73d0c8b9eca4f24154f3bd3b8aa473b1c3a9
помогите получить второй вариант через Edit, StrToHex не помогает.
У меня похожая проблема как и у BDA ?
ps использую Embarcadero® Delphi 10.2
dwa_e вне форума Ответить с цитированием
Старый 11.09.2017, 10:12   #7
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,238
По умолчанию

Цитата:
Сообщение от dwa_e Посмотреть сообщение
Edit1.Text)); // в edit1.text - 12345678
так, а Вы знаете, что такое кодировка? Погуглите, например, ASCII.

Вы бред передаёте в #$12#$34#$56#$78

в Edit у Вас СТРОКА символов. каждый символ имеет свой код.
для 1 этот код равен 49 ( в шестнадцатеричном виде это 0x31 == $31)
для 2 этот код равен 40 ( в шестнадцатеричном виде это 0x32 == $32)
и т.д.
т.е ваша строка "12345678" в шестнадцатеричном виде будет
31 32 33 34 35 36 37 38
Serge_Bliznykov вне форума Ответить с цитированием
Старый 15.09.2017, 09:15   #8
dwa_e
 
Регистрация: 06.01.2008
Сообщений: 8
По умолчанию

проблема решилась через такую функцию
Код:
function HexToStr(const source: string): string;
var
  i, idx:Cardinal;
  StrAsBytes:TBytes;
begin
  SetLength(StrAsBytes, length(source) div 2);
  i:=1;
  idx:=0;
  while i<=length(source) do
  begin
    StrAsBytes[idx]:=StrToInt('$'+source[i]+source[i+1]);
    i:=i+2;
    idx:=idx+1;
  end;
  result:=TEncoding.Default.GetString(StrAsBytes);
end;
при таком вводе получаю то что нужно
Код:
Memo1.Lines.Add(sha1hash(HexToStr(Edit1.Text)));
вся соль в этой строке
TEncoding.Default.GetString(StrAsBy tes), в оригинале там было UTF-8.
я и сам осознавал что проблема в кодировке
dwa_e вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Паскаль. Файлы - Создать подпрограмму для заполнения файла латинскими и русскими буквами Антон Лысенко Помощь студентам 2 15.12.2010 22:44
Фильтр ячеек с маленькими буквами и несколько большими буквами Clockgen Microsoft Office Excel 8 24.11.2010 21:13
Дан файл, содержащий текст, записанный строчными русскими буквами. Получить в др.файле тот же текст, develish151 Microsoft Office Word 4 05.05.2010 13:20
Пути с русскими буквами в Lazarus. Alex Cones Lazarus, Free Pascal, CodeTyphon 4 30.03.2010 18:31
SMS русскими буквами nimf Общие вопросы Delphi 10 13.02.2010 22:23