mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
212 lines
6.8 KiB
ObjectPascal
212 lines
6.8 KiB
ObjectPascal
{
|
|
Double Commander
|
|
-------------------------------------------------------------------------
|
|
General Hash Unit: This unit defines the common types, functions,
|
|
and procedures
|
|
|
|
Copyright (C) 2009-2024 Alexander Koblov (alexx2000@mail.ru)
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
}
|
|
|
|
unit uHash;
|
|
|
|
{$mode delphi}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, DCPcrypt2, crc;
|
|
|
|
type
|
|
THashContext = TDCP_hash;
|
|
THashAlgorithm = (HASH_BLAKE2S, HASH_BLAKE2SP, HASH_BLAKE2B, HASH_BLAKE2BP, HASH_BLAKE3,
|
|
HASH_CHECKSUM32, HASH_CRC32, HASH_HAVAL, HASH_MD4, HASH_MD5, HASH_RIPEMD128, HASH_RIPEMD160,
|
|
HASH_SFV, HASH_SHA1, HASH_SHA224, HASH_SHA256, HASH_SHA384, HASH_SHA512,
|
|
HASH_SHA3_224, HASH_SHA3_256, HASH_SHA3_384, HASH_SHA3_512, HASH_TIGER, HASH_XXH3_128,
|
|
HASH_BEST
|
|
);
|
|
|
|
var
|
|
HashFileExt: array[Low(THashAlgorithm)..Pred(High(THashAlgorithm))] of String = (
|
|
'blake2s', 'blake2sp', 'blake2b', 'blake2bp', 'blake3', 'checksum32', 'crc32', 'haval',
|
|
'md4', 'md5', 'ripemd128', 'ripemd160', 'sfv', 'sha', 'sha224', 'sha256',
|
|
'sha384', 'sha512', 'sha3', 'sha3', 'sha3', 'sha3', 'tiger', 'xxh128'
|
|
);
|
|
|
|
var
|
|
HashName: array[Low(THashAlgorithm)..Pred(High(THashAlgorithm))] of String = (
|
|
'blake2s', 'blake2sp', 'blake2b', 'blake2bp', 'blake3', 'checksum32', 'crc32', 'haval',
|
|
'md4', 'md5', 'ripemd128', 'ripemd160', 'sfv', 'sha1_160', 'sha2_224',
|
|
'sha2_256', 'sha2_384', 'sha2_512', 'sha3_224', 'sha3_256',
|
|
'sha3_384', 'sha3_512', 'tiger', 'xxh3_128'
|
|
);
|
|
|
|
HashFirst: array[0..11] of THashAlgorithm = (
|
|
HASH_SFV, HASH_SHA224, HASH_SHA3_224,
|
|
HASH_BLAKE3, HASH_SHA256, HASH_SHA3_256,
|
|
HASH_XXH3_128, HASH_SHA384, HASH_SHA3_384,
|
|
HASH_SHA1, HASH_SHA512, HASH_SHA3_512
|
|
);
|
|
|
|
procedure HashInit(out Context: THashContext; Algorithm: THashAlgorithm);
|
|
procedure HashUpdate(var Context: THashContext; const Buffer; BufLen: LongWord);
|
|
procedure HashFinal(var Context: THashContext; out Hash: String);
|
|
|
|
function HashString(const Line: String; IgnoreCase, IgnoreWhiteSpace: Boolean): LongWord;
|
|
|
|
{ Helper functions }
|
|
function TrimHash(const AHash: String): String;
|
|
function FileExtIsHash(const FileExt: String): Boolean;
|
|
function FileExtToHashAlg(const FileExt: String): THashAlgorithm;
|
|
|
|
implementation
|
|
|
|
uses
|
|
LazUTF8, DCPhaval, DCPmd4, DCPmd5, DCPripemd128, DCPripemd160, DCPChecksum32, DCPcrc32,
|
|
DCPsha1, DCPsha256, DCPsha512, DCPtiger, DCPblake2, DCPblake3, DCPsha3, DCPxxh3;
|
|
|
|
procedure HashInit(out Context: THashContext; Algorithm: THashAlgorithm);
|
|
begin
|
|
if (Algorithm = HASH_BEST) then
|
|
begin
|
|
{$IF DEFINED(CPUX86_64)}
|
|
Algorithm:= HASH_BLAKE3;
|
|
{$ELSEIF DEFINED(CPUAARCH64)}
|
|
Algorithm:= HASH_BLAKE3;
|
|
{$ELSEIF DEFINED(CPU64)}
|
|
Algorithm:= HASH_BLAKE2B;
|
|
{$ELSE}
|
|
Algorithm:= HASH_BLAKE2S;
|
|
{$ENDIF}
|
|
end;
|
|
case Algorithm of
|
|
HASH_BLAKE2S: Context:= TDCP_blake2s.Create(nil);
|
|
HASH_BLAKE2SP: Context:= TDCP_blake2sp.Create(nil);
|
|
HASH_BLAKE2B: Context:= TDCP_blake2b.Create(nil);
|
|
HASH_BLAKE2BP: Context:= TDCP_blake2bp.Create(nil);
|
|
HASH_BLAKE3: Context:= TDCP_blake3.Create(nil);
|
|
HASH_CHECKSUM32: Context:= TDCP_checksum32.Create(nil);
|
|
HASH_CRC32: Context:= TDCP_crc32.Create(nil);
|
|
HASH_HAVAL: Context:= TDCP_haval.Create(nil);
|
|
HASH_MD4: Context:= TDCP_md4.Create(nil);
|
|
HASH_MD5: Context:= TDCP_md5.Create(nil);
|
|
HASH_RIPEMD128: Context:= TDCP_ripemd128.Create(nil);
|
|
HASH_RIPEMD160: Context:= TDCP_ripemd160.Create(nil);
|
|
HASH_SFV: Context:= TDCP_crc32.Create(nil);
|
|
HASH_SHA1: Context:= TDCP_sha1.Create(nil);
|
|
HASH_SHA224: Context:= TDCP_sha224.Create(nil);
|
|
HASH_SHA256: Context:= TDCP_sha256.Create(nil);
|
|
HASH_SHA384: Context:= TDCP_sha384.Create(nil);
|
|
HASH_SHA512: Context:= TDCP_sha512.Create(nil);
|
|
HASH_SHA3_224: Context:= TDCP_sha3_224.Create(nil);
|
|
HASH_SHA3_256: Context:= TDCP_sha3_256.Create(nil);
|
|
HASH_SHA3_384: Context:= TDCP_sha3_384.Create(nil);
|
|
HASH_SHA3_512: Context:= TDCP_sha3_512.Create(nil);
|
|
HASH_TIGER: Context:= TDCP_tiger.Create(nil);
|
|
HASH_XXH3_128: Context:= TDCP_xxh3_128.Create(nil);
|
|
end;
|
|
|
|
Context.Init;
|
|
end;
|
|
|
|
procedure HashUpdate(var Context: THashContext; const Buffer; BufLen: LongWord);
|
|
begin
|
|
Context.Update(Buffer, BufLen);
|
|
end;
|
|
|
|
procedure HashFinal(var Context: THashContext; out Hash: String);
|
|
var
|
|
I, HashSize: LongWord;
|
|
Digest: array of Byte;
|
|
begin
|
|
Hash:= EmptyStr;
|
|
HashSize:= Context.HashSize div 8;
|
|
SetLength(Digest, HashSize);
|
|
Context.Final(Pointer(Digest)^);
|
|
for I := 0 to HashSize - 1 do
|
|
Hash := Hash + HexStr(Digest[I], 2);
|
|
Hash := LowerCase(Hash);
|
|
FreeAndNil(Context);
|
|
end;
|
|
|
|
function HashString(const Line: String; IgnoreCase, IgnoreWhiteSpace: Boolean): LongWord;
|
|
var
|
|
S: String;
|
|
I, J, L: Integer;
|
|
begin
|
|
S := Line;
|
|
if IgnoreWhiteSpace then
|
|
begin
|
|
J := 1;
|
|
L := Length(Line);
|
|
for I:= 1 to L do
|
|
begin
|
|
// Skip white spaces
|
|
if not (Line[I] in [#9, #32]) then
|
|
begin
|
|
S[J] := Line[I];
|
|
Inc(J);
|
|
end;
|
|
end;
|
|
SetLength(S, J - 1);
|
|
end;
|
|
if IgnoreCase then S := UTF8LowerCase(S);
|
|
|
|
Result := crc32(0, nil, 0);
|
|
Result := crc32(Result, PByte(S), Length(S));
|
|
end;
|
|
|
|
function TrimHash(const AHash: String): String;
|
|
var
|
|
I, J: Integer;
|
|
begin
|
|
J:= 0;
|
|
Result:= EmptyStr;
|
|
SetLength(Result, Length(AHash));
|
|
for I:= 1 to Length(AHash) do
|
|
begin
|
|
if (AHash[I] in ['0'..'9', 'A'..'F', 'a'..'f']) then
|
|
begin
|
|
Inc(J);
|
|
Result[J]:= AHash[I];
|
|
end;
|
|
end;
|
|
SetLength(Result, J);
|
|
end;
|
|
|
|
function FileExtIsHash(const FileExt: String): Boolean;
|
|
var
|
|
I: THashAlgorithm;
|
|
begin
|
|
Result:= False;
|
|
for I:= Low(HashFileExt) to High(HashFileExt) do
|
|
begin
|
|
if SameText(FileExt, HashFileExt[I]) then Exit(True);
|
|
end;
|
|
end;
|
|
|
|
function FileExtToHashAlg(const FileExt: String): THashAlgorithm;
|
|
var
|
|
I: THashAlgorithm;
|
|
begin
|
|
for I:= Low(HashFileExt) to High(HashFileExt) do
|
|
begin
|
|
if SameText(FileExt, HashFileExt[I]) then Exit(I);
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|