delphi DCPcrypt散列德语变音

lskq00tm  于 2022-11-23  发布在  其他
关注(0)|答案(1)|浏览(163)

我使用DCPcrypt和SHA512来散列字符串。
我使用的版本由沃伦Postma https://bitbucket.org/wpostma/dcpcrypt2010
它工作得很好。但是它在德语变音如ä,ö,ü和可能其他unicode上失败了。
我是这样使用库的:

function TForm1.genhash(str: string): string;
var
  Hash  : TDCP_sha512;
  Digest: array[0..63] of byte;
  i: integer;
  s: string;
begin
  s:= '';
  hash  := TDCP_sha512.Create(nil);
  if hash<>nil then
  begin
    try
      Hash.Init;
      Hash.UpdateStr(str);
      Hash.Final(Digest);

      for i:= 0 to length(Digest)-1 do
        s:= s + IntToHex(Digest[i],2);

    finally
      hash.free;
    end;

  end;
  Result := s;
end;

当我输入字母ä时,我期望输出为:
2004年12月18日,中国人民银行发布《中国人民银行股份有限公司关于进一步深化改革的通知》,明确了改革的方向。
我查过那些网站:http://hashgenerator.de/http://passwordsgenerator.net/sha512-hash-generator/
然而我得到:
1998年,在美国的一家公司中,有一个名为“美国”的公司。
所以我的问题是:如何使用DCPcrypt库生成德语变音的哈希值?谢谢

lf3rwulv

lf3rwulv1#

这一定是人们在使用哈希和加密时最常犯的错误。这些算法对二进制数据进行操作,但你传递的是文本。某处必须有某种东西将文本编码为二进制。应该使用什么编码。你怎么知道你的图书馆使用的是和在线工具相同的编码?你不知道。
所以,这里有一条规则要遵循。永远不要哈希文本。就是不要这样做。使用一个定义良好的、明确选择的编码将文本编码为二进制。然后哈希它。我建议你编码为UTF-8并哈希它。所以,TEncoding.UTF8.GetBytes(...)是你的朋友。
现在,查看此处的实际详细信息,您将调用此方法:

procedure UpdateStr(const Str: RawByteString);

参数RawByteString意味着你的Unicode文本将被转换成ANSI字符串,使用默认的系统代码页。我敢肯定这不是你想要发生的。实际上编译器是这样说的:
[dcc 32警告] W1058从'string'到'RawByteString'的隐含字串转换可能会遗失数据
所以编译器告诉你你做错了什么。你真的必须注意编译器的消息。
现在,您可以调用UpdateUnicodeStr而不是UpdateStr。但是,您又如何知道使用了什么编码呢?它恰好是本机内部编码UTF-16 LE。
但是,让我们遵循我的规则,永远不要对文本进行编码。

{$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.

输出

2004年12月18日,中国人民银行发布《中国人民银行股份有限公司关于进一步深化改革的通知》,明确了改革的方向。
注意,我在其他方面简化了代码。我删除了本地字符串变量,直接使用Result。我使用Classes单元中的BinToHex将摘要转换为十六进制。我还修改了以下代码:

hash := TDCP_sha512.Create(nil);
if hash<>nil then
  ....

移除不需要的if陈述式。如果建构函式失败,就会引发例外状况。
请遵守我的规则,永远不要哈希文本。它会为你服务得很好!

相关问题