DCPcrypt 散列德语变音符号
DCPcrypt Hashing German Umlauts
我正在使用 DCPcrypt 和 SHA512 对字符串进行哈希处理。
我使用的是 Warren 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;
当我输入字母 ä
时,我希望输出为:
64868C5784A6004E675BCF405F549369BF607CD3269C0CAC1711E21BA9F40A5ABBF0C7535856E7CF77EA55A072DD04AA89EEA361E95F497AA965309B50587157
我在这些网站上查过:
http://hashgenerator.de/
http://passwordsgenerator.net/sha512-hash-generator/
但是我得到:
1A7F725BD18E062020A646D4639F264891368863160A74DF2BFC069C4DADE04E6FA854A2474166EED0914B922A9D8BE0C89858D437DDD7FBCA5C9C89FC07323A
所以我的问题是:
我如何使用 DCPcrypt 库为德语变音符号生成哈希值?谢谢
这一定是人们在散列和加密方面最常犯的一个错误。这些算法对二进制数据进行操作,但您传递的是文本。某个地方必须将该文本编码为二进制。以及应该使用什么编码。您怎么知道您的图书馆使用与在线工具相同的工具?你不知道。
所以,这是您要遵守的规则。永远不要散列文本。只是不要这样做。使用明确定义的明确选择的编码将文本编码为二进制。并散列它。我建议您编码为 UTF-8 并对其进行哈希处理。所以,TEncoding.UTF8.GetBytes(...)
是你的朋友。
现在,看看这里的实际细节,您正在调用此方法:
procedure UpdateStr(const Str: RawByteString);
RawByteString
参数表示您的 Unicode 文本正在转换为 ANSI 字符串,使用默认的系统代码页。我敢肯定那不是你想要发生的。事实上,编译器是这样说的:
[dcc32 Warning] W1058 Implicit string cast with potential data loss from 'string' to '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
。我使用 Classes
单元中的 BinToHex
进行摘要到十六进制的转换。我还更改了这段代码:
hash := TDCP_sha512.Create(nil);
if hash<>nil then
....
删除不需要的 if
语句。如果构造函数失败,则会引发异常。
请遵循我的规则,永远不要散列文本。它将为您服务!
我正在使用 DCPcrypt 和 SHA512 对字符串进行哈希处理。
我使用的是 Warren 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;
当我输入字母 ä
时,我希望输出为:
64868C5784A6004E675BCF405F549369BF607CD3269C0CAC1711E21BA9F40A5ABBF0C7535856E7CF77EA55A072DD04AA89EEA361E95F497AA965309B50587157
我在这些网站上查过: http://hashgenerator.de/ http://passwordsgenerator.net/sha512-hash-generator/
但是我得到:
1A7F725BD18E062020A646D4639F264891368863160A74DF2BFC069C4DADE04E6FA854A2474166EED0914B922A9D8BE0C89858D437DDD7FBCA5C9C89FC07323A
所以我的问题是: 我如何使用 DCPcrypt 库为德语变音符号生成哈希值?谢谢
这一定是人们在散列和加密方面最常犯的一个错误。这些算法对二进制数据进行操作,但您传递的是文本。某个地方必须将该文本编码为二进制。以及应该使用什么编码。您怎么知道您的图书馆使用与在线工具相同的工具?你不知道。
所以,这是您要遵守的规则。永远不要散列文本。只是不要这样做。使用明确定义的明确选择的编码将文本编码为二进制。并散列它。我建议您编码为 UTF-8 并对其进行哈希处理。所以,TEncoding.UTF8.GetBytes(...)
是你的朋友。
现在,看看这里的实际细节,您正在调用此方法:
procedure UpdateStr(const Str: RawByteString);
RawByteString
参数表示您的 Unicode 文本正在转换为 ANSI 字符串,使用默认的系统代码页。我敢肯定那不是你想要发生的。事实上,编译器是这样说的:
[dcc32 Warning] W1058 Implicit string cast with potential data loss from 'string' to '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
。我使用 Classes
单元中的 BinToHex
进行摘要到十六进制的转换。我还更改了这段代码:
hash := TDCP_sha512.Create(nil);
if hash<>nil then
....
删除不需要的 if
语句。如果构造函数失败,则会引发异常。
请遵循我的规则,永远不要散列文本。它将为您服务!