2016-03-03 65 views
11

我使用DCPcrypt和SHA512散列串。DCPcrypt散列德国变音

我使用的版本由沃伦波斯特马https://bitbucket.org/wpostma/dcpcrypt2010

这是工作的罚款。然而,它与德国的变音符号就好了,ö,ü,可能其他统一码failes。

我使用这样的库:

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库来产生对德国变音哈希?感谢

回答

18

这一定是一个最常见的错误,人们作出与散列和加密。这些算法对二进制数据进行操作,但是您正在传递文本。某处需要将该文本编码为二进制文件。并且应该使用什么编码。你怎么知道你的图书馆和在线工具一样?你没有。

所以,这里有一个规则,你跟着。从不哈希文本。只是不要这样做。使用明确定义的明确选择的编码将文本编码为二进制。并散列。我建议你编码为UTF-8并散列。所以,TEncoding.UTF8.GetBytes(...)是你的朋友在这里。

现在,在实际的细节在这里看,你调用这个方法:

procedure UpdateStr(const Str: RawByteString); 

RawByteString参数,意味着你的Unicode文本被转换为ANSI字符串,用默认的系统代码页。我相信这不是你打算发生的事情。事实上,编译器这样说:

[dcc32警告] W1058隐串变成与“串”到潜在的数据丢失“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声明,这是不需要的。如果构造函数失败,则会引发异常。

请按照我的规则永远不要哈希文本。它会为你服务!

+1

感谢大卫这个伟大的答案。欣赏解释并肯定学到了一些东西! – Tommy

+2

太好了。并感谢您的问题。很高兴能够清楚地说明问题所在,并有机会最终写下一段时间以来唠叨我的事情。我希望我们可以使用这个Q&A通过散列和加密来传播关于二进制和文本的信息! –