2017-04-18 11 views
7

Data.Cloud.CloudAPI.pas पर एक गलत SHA256 लौटाता हैहै जो कुछ फ़ाइल पर गलत SHA 256 लौटाता है।डेल्फी THashSHA2 बड़ी फ़ाइल

class function TCloudSHA256Authentication.GetStreamToHashSHA256Hex(const Content: TStream): string; 
var 
    LBytes : TBytes; 
    Hash: THashSHA2; 
begin 
    LBytes := TBytesStream(Content).Bytes; 
    //Hash bytes 
    Hash := THashSHA2.Create; 
    Hash.Update(LBytes); 
    Result := Hash.HashAsString; 
end; 

एडब्ल्यूएस S3 वापसी त्रुटि: कुछ परीक्षण

<ClientComputedContentSHA256>f43ee89e2b7758057bb1f33eb8546d4c2c118f2ab932de89dbd74aabc0651053</ClientComputedContentSHA256> 
<S3ComputedContentSHA256>3bbf5f864cc139cf6392b4623bd782a69d16929db713bffaa68035f8a5c3c0ce</S3ComputedContentSHA256> 

मैं बना दिया है एक myfile.zip (600 एमबी) बुद्धि:

The provided x-amz-content-sha256 header does not match what was computed

GetStreamToHashSHA256Hex अमेज़न से एक अलग SHA256 उत्पादन लगता है। ..

TIdHashSHA256 इंडी से एक विकल्प सही SHA256 (aws s3 के समान) लौटाता है, उदाहरण के लिए ।:

var 
    aFileStream: TFileStream; 
    aHash:  TIdHashSHA256; 
begin 
    aFileStream := TFileStream.Create('C:\myfile.zip', fmOpenRead or fmShareDenyWrite); 
    aHash  := TIdHashSHA256.Create; 

    try 
    Result := aHash.HashStreamAsHex(aFileStream).ToLower; 
    finally 
    aFileStream.Free; 
    aHash.Free; 
    end; 
end; 

PHP से hash_file() सही SHA256, जैसे .:

hash_file('sha256', 'C:\myfile.zip'); 

(एडब्ल्यूएस S3 का एक ही) लौट लेकिन THashSHA2 एक गलत SHA256 वापसी, जैसे .:

var 
    LBytes : TBytes; 
    Hash: THashSHA2; 
begin 
    LBytes := TFile.ReadAllBytes('C:\myfile.zip'); 
    Hash := THashSHA2.Create; 
    Hash.Update(LBytes); 
    Result := Hash.HashAsString; 
end; 

क्यूं कर?

अद्यतन

यह मेरा बग समाधान है। परियोजना में आयात Data.Cloud.CloudAPI.pas और पुनर्लेखन इन समारोह:

uses IdHash, IdHashSHA, IdSSLOpenSSL; 

class function TCloudSHA256Authentication.GetHashSHA256Hex(HashString: string): string; 
var 
    aHash: TIdHashSHA256; 
begin 
    LoadOpenSSLLibrary; 
    try 
    if not(TIdHashSHA256.IsAvailable) then 
     raise Exception.Create('HashSHA256 Isn''t available!'); 

    aHash := TIdHashSHA256.Create; 
    try 
     Result := aHash.HashStringAsHex(HashString).ToLower; 
    finally 
     aHash.Free; 
    end; 
    finally 
    UnLoadOpenSSLLibrary; 
    end; 
end; 

class function TCloudSHA256Authentication.GetStreamToHashSHA256Hex(const Content: TStream): string; 
var 
    aHash: TIdHashSHA256; 
begin 
    LoadOpenSSLLibrary; 
    try 
    if not(TIdHashSHA256.IsAvailable) then 
     raise Exception.Create('HashSHA256 Isn''t available!'); 

    aHash := TIdHashSHA256.Create; 
    try 
     Result := aHash.HashStreamAsHex(Content).ToLower; 
    finally 
     aHash.Free; 
    end; 
    finally 
    UnLoadOpenSSLLibrary; 
    end; 
end; 

अद्यतन 2

मैं है भी Freds सुझाव को लागू करने की कोशिश करते हैं, यह काम करता है:

class function TCloudSHA256Authentication.GetHashSHA256Hex(HashString: string): string; 
var 
    Content: TStringStream; 
    Hash: THashSHA2; 
    LBytes: TArray<Byte>; 
    Buffer: PByte; 
    BufLen: Integer; 
    Readed: Integer; 
begin 
    BufLen := 16 * 1024; 

    Buffer := AllocMem(BufLen); 
    Hash := THashSHA2.Create; 
    Content := TStringStream.Create(HashString); 
    try 
    while Content.Position < Content.Size do 
    begin 
     Readed := Content.Read(Buffer^, BufLen); 
     if Readed > 0 then 
     Hash.update(Buffer^, Readed); 
    end; 
    finally 
    Content.Free; 
    FreeMem(Buffer); 
    end; 

    Result := Hash.HashAsString; 
end; 

class function TCloudSHA256Authentication.GetStreamToHashSHA256Hex(const Content: TStream): string; 
var 
    LBytes : TBytes; 
    Hash: THashSHA2; 
    Buffer: PByte; 
    BufLen: Integer; 
    Readed: Integer; 
begin 
    BufLen := 16 * 1024; 

    Buffer := AllocMem(BufLen); 
    Hash := THashSHA2.Create; 
    try 
     Content.Seek(0, soFromBeginning); 

     while Content.Position < Content.Size do 
     begin 
     Readed := Content.Read(Buffer^, BufLen); 
     if Readed > 0 then 
      Hash.update(Buffer^, Readed); 
     end; 

     Content.Seek(0, soFromBeginning); 
    finally 
     FreeMem(Buffer); 
    end; 

    Result := Hash.HashAsString; 
end; 
+0

जाहिर 'THashSHA2' गाड़ी तो है। Embarcadero के साथ कृपया [एक बग रिपोर्ट दर्ज करें] (http://quality.embarcadero.com)। –

+0

@RemyLebeau THashSHA2 छोटी गाड़ी है, क्या आप इसे ठीक करने के लिए कोई कामकाज जानते हैं? – ar099968

+0

कई सही कार्यान्वयन हैं जिनका आप उपयोग कर सकते हैं। ढूँढो एक। इसका इस्तेमाल करें। –

उत्तर

4

मैंने अभी बर्लिन पर एमएस साइप्रो और थैश एसएच 2 का उपयोग करके +1.5 जीबी फ़ाइल का परीक्षण किया है, वे दोनों एक ही हैश लौटाए हैं लेकिन एमएस क्रिप्टो ओपनएसएसएल की तरह बहुत तेज है।

समस्या यह है कि फ़ाइल एक हिस्से में टीबीइट्स में पकड़ने के लिए बहुत बड़ी है। मेरे रिकॉर्ड हेल्पर में TBytes.MaxLen = $F000; {61440} है इसलिए आपको एक TFileStream का उपयोग करने और HashSHA2 में फ़ाइलों में फ़ाइल को पढ़ने की आवश्यकता है। इसके बजाय अद्यतन करें।

अद्यतन: प्रति डेविड हेफेरनान की टिप्पणी के रूप में मैं TBytes.MaxLen पुनर्परीक्षण और यह केवल उपलब्ध स्मृति द्वारा सीमित प्रतीत होता है। एमएस क्रिप्टो और डेल्फी HashSha2

नोट के बीच


व्यावहारिक उदाहरण और स्पीड तुलना: आवश्यक जेडी एपीआई

program SHA2SpeedTest; 

    {$APPTYPE CONSOLE} 
    {$R *.res} 

    uses 
    JwaWindows, Winapi.Windows, System.SysUtils, System.Classes, System.Diagnostics, System.Hash; 

    const 
    SHA256_LEN = 256 div 8; 
    ChunkSize  = $F000; 

    type 
    TBytesHelper = record helper for TBytes 
    public 
     function BinToHex: string; 
    end; 

    function TBytesHelper.BinToHex: string; 
    var 
    Len : Integer; 
    begin 
    Len := Length(Self); 
    SetLength(Result, Len * 2)); 
    System.Classes.BinToHex(Self, PChar(Result), Len); 
    end; 

    procedure DelphiHash256(const AStream: TStream; out Bytes: TBytes); 
    var 
    HashSHA2: THashSHA2; 
    BytesRead: Integer; 
    begin 
    HashSHA2 := THashSHA2.create; 
    SetLength(Bytes, ChunkSize); 
    AStream.Position := 0; 
    repeat 
     BytesRead := AStream.Read(Bytes, ChunkSize); 
     if (BytesRead = 0) then Break; // Done 
     HashSHA2.Update(Bytes, BytesRead); 
    until False; 
    Bytes := HashSHA2.HashAsBytes; 
    end; 


    function CryptoHash256(const AStream: TStream; out Bytes: TBytes): Boolean; 
    var 
    SigLen : Cardinal; 
    hHash : HCRYPTHASH; 
    hProv : HCRYPTPROV; 
    BytesRead: Integer; 
    begin 
    hProv := 0; hHash := 0; 
    Result := False; 

    If not CryptAcquireContext(hProv, nil, nil, PROV_RSA_AES, CRYPT_VERIFYCONTEXT) then Exit; 
    try 
     if not CryptCreateHash(hProv, CALG_SHA_256, 0, 0, hHash) then Exit; 
     try 
     SetLength(Bytes, ChunkSize); 
     AStream.Position := 0; 
     repeat 
      BytesRead := AStream.Read(Bytes, ChunkSize); 
      if (BytesRead = 0) then Break; // Done 
      if not CryptHashData(hHash, @Bytes[0], BytesRead, 0) then Exit; 
     until False; 

     SigLen := SHA256_LEN; 
     SetLength(Bytes, SigLen); 
     Result := CryptGetHashParam(hHash, HP_HASHVAL, @Bytes[0], SigLen, 0); 
     finally 
     CryptDestroyHash(hHash); 
     end; 
    finally 
     CryptReleaseContext(hProv, 0); 
    end; 
    end; 

    var 
    Stream: TStream; 
    Bytes : TBytes; 
    sw : TStopwatch; 
    CryptoTicks : int64; 
    FileName : string; 

    {* CheckFileName *} 
    function CheckFileName: boolean; 
    begin 
     if (FileName='') then FileName := ParamStr(0); 
     Result := FileExists(FileName); 
     if not Result then Writeln('Invalid File name'); 
    end; 
    begin 
    repeat 
     Writeln('Please Enter a valid File name, empty for this Executable'); 
     Readln(FileName); 
    until CheckFileName; 

    try 
     Stream := TFileStream.Create(FileName, fmOpenRead + fmShareDenyNone); 
     try 
     WriteLn('Crypto - Calculating Checksum'); 
     sw.Start; 
     if not CryptoHash256(Stream, Bytes) then raise Exception.Create('Something Happened :)'); 
     sw.Stop; 
     Writeln(Bytes.BinToHex); 
     WriteLn('Elapsed: ' + sw.Elapsed.ToString); 
     CryptoTicks := sw.ElapsedTicks; 

     WriteLn('Delphi - Calculating Checksum'); 
     sw.Reset; sw.Start; 
     DelphiHash256(Stream, Bytes); 
     sw.Stop; 
     Writeln(Bytes.BinToHex); 
     WriteLn('Elapsed: ' + sw.Elapsed.ToString); 

     Writeln(Format('MS Crypto is %d%% faster', [(sw.ElapsedTicks-CryptoTicks) * 100 div CryptoTicks])); 
     finally 
     Stream.Free; 
     end; 
     Writeln('Hit <Enter> to exit'); 
     Readln; 
    except 
     on E: Exception do Writeln(E.ClassName, ': ', E.Message); 
    end; 

    end. 
+5

उस कोड के साथ अन्य समस्याओं में टीबीइट्सस्ट्रीम को कोड का एक उद्धरण बोगलिंग टुकड़ा हार्ड कस्ट शामिल है। एम्बा के कहने के लिए कि उनके लिए गुणवत्ता मायने रखती है मेरे दिमाग को उड़ाती है। –

+0

क्या आप एक व्यावहारिक उदाहरण प्रदान कर सकते हैं? मुझे एक और फिक्स मिला है (मेरा प्रश्न अपडेट देखें) – ar099968

+0

मेरा अद्यतन 2 देखें, क्या मैंने आपके सुझाव को सही तरीके से कार्यान्वित किया है? – ar099968

संबंधित मुद्दे