Ответ 1
Это должна быть самая распространенная ошибка, которую люди делают с хэшированием и шифрованием. Эти algos работают на двоичных данных, но вы передаете текст. Что-то где-то есть, чтобы закодировать этот текст как двоичный. И какую кодировку следует использовать. Откуда вы знаете, что ваша библиотека использует то же самое, что и онлайн-инструмент? Вы этого не сделаете.
Итак, вот правило для вас следовать. Никогда не хэш-текст. Только не делай этого. Кодирование текста в виде двоичного кода с использованием четко определенной, явно выбранной кодировки. И хэш это. Я предлагаю вам кодировать как UTF-8 и хэш. Итак, TEncoding.UTF8.GetBytes(...)
- ваш друг здесь.
Теперь, глядя на настоящую деталь, вы вызываете этот метод:
procedure UpdateStr(const Str: RawByteString);
Параметр RawByteString
означает, что ваш текст Юникода преобразуется в строку ANSI со страницей системного кода по умолчанию. Я уверен, что не то, что вы намереваетесь произойти. В самом деле, компилятор говорит следующее:
[dcc32 Warning] W1058 Неявная строка с потенциальной потерей данных от 'string' до 'RawByteString'
Итак, компилятор говорит вам, что вы делаете что-то неправильно. Вы действительно должны внимательно относиться к сообщениям компилятора.
Теперь вы можете вызвать UpdateUnicodeStr
вместо UpdateStr
. Но опять же, откуда вы знаете, какая кодировка используется? Это обычная внутренняя кодировка, UTF-16LE.
Но пусть последует мое правило никогда не кодировать текст.
{$APPTYPE CONSOLE}
uses
SysUtils, Classes, DCPsha512;
function genhash(str: string): string;
var
Bytes: TBytes;
Hash: TDCP_sha512;
Digest: array[0..63] of byte;
begin
Bytes := TEncoding.UTF8.GetBytes(str); // encode text as UTF-8 bytes
hash := TDCP_sha512.Create(nil);
try
Hash.Init;
Hash.Update(Pointer(Bytes)^, Length(Bytes));
Hash.Final(Digest);
finally
hash.Free;
end;
// convert the digest to a hex hash string
SetLength(Result, Length(Digest)*2);
BinToHex(Digest, PChar(Result), Length(Digest));
end;
begin
Writeln(genhash('ä'));
Readln;
end.
Выход
64868C5784A6004E675BCF405F549369BF607CD3269C0CAC1711E21BA9F40A5ABBF0C7535856E7CF77EA55A072DD04AA89EEA361E95F497AA965309B50587157
Обратите внимание, что я упростил код другими способами. Я удалил локальную строковую переменную и работал непосредственно с Result
. Я использовал BinToHex
из блока Classes
, чтобы преобразовать дайджест в шестнадцатеричное преобразование. Я также изменил этот код:
hash := TDCP_sha512.Create(nil);
if hash<>nil then
....
чтобы удалить инструкцию if
, которая не нужна. Если конструктор не работает, возникает исключение.
Пожалуйста, следуйте моему правилу, никогда не добавляя хэш-текст. Это будет вам хорошо!