109 lines
2.7 KiB
ObjectPascal
109 lines
2.7 KiB
ObjectPascal
unit SHA256;
|
|
|
|
{
|
|
SHA256.pas: System.Hash.pas wrapper in the style of MD5.pas and SHA1.pas
|
|
Author: Martijn Laan
|
|
License for SHA256.pas: Public domain, no copyright claimed
|
|
}
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils, System.Hash;
|
|
|
|
type
|
|
TSHA256Context = record
|
|
hash: THashSHA2;
|
|
end;
|
|
TSHA256Digest = array[0..31] of Byte;
|
|
|
|
procedure SHA256Init(var ctx: TSHA256Context);
|
|
procedure SHA256Update(var ctx: TSHA256Context; const buffer; len: Cardinal);
|
|
function SHA256Final(var ctx: TSHA256Context): TSHA256Digest;
|
|
|
|
function SHA256Buf(const Buffer; Len: Cardinal): TSHA256Digest;
|
|
function SHA256DigestsEqual(const A, B: TSHA256Digest): Boolean;
|
|
function SHA256DigestToString(const D: TSHA256Digest): String;
|
|
function SHA256DigestFromString(const S: String): TSHA256Digest;
|
|
|
|
implementation
|
|
|
|
procedure SHA256Init(var ctx: TSHA256Context);
|
|
begin
|
|
ctx.hash := THashSHA2.Create(THashSHA2.TSHA2Version.SHA256);
|
|
end;
|
|
|
|
procedure SHA256Update(var ctx: TSHA256Context; const buffer; len: Cardinal);
|
|
begin
|
|
ctx.hash.Update(buffer, len);
|
|
end;
|
|
|
|
function SHA256Final(var ctx: TSHA256Context): TSHA256Digest;
|
|
begin
|
|
var HashAsBytes := ctx.hash.HashAsBytes;
|
|
Move(HashAsBytes[0], Result[0], SizeOf(Result));
|
|
end;
|
|
|
|
function SHA256Buf(const Buffer; Len: Cardinal): TSHA256Digest;
|
|
var
|
|
Context: TSHA256Context;
|
|
begin
|
|
SHA256Init(Context);
|
|
SHA256Update(Context, Buffer, Len);
|
|
Result := SHA256Final(Context);
|
|
end;
|
|
|
|
function SHA256DigestsEqual(const A, B: TSHA256Digest): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := Low(TSHA256Digest) to High(TSHA256Digest) do
|
|
if A[I] <> B[I] then begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
Result := True;
|
|
end;
|
|
|
|
function SHA256DigestToString(const D: TSHA256Digest): String;
|
|
const
|
|
Digits: array[0..15] of Char = '0123456789abcdef';
|
|
var
|
|
Buf: array[0..63] of Char;
|
|
P: PChar;
|
|
I: Integer;
|
|
begin
|
|
P := @Buf;
|
|
for I := 0 to 31 do begin
|
|
P^ := Digits[D[I] shr 4];
|
|
Inc(P);
|
|
P^ := Digits[D[I] and 15];
|
|
Inc(P);
|
|
end;
|
|
SetString(Result, Buf, 64);
|
|
end;
|
|
|
|
function SHA256DigestFromString(const S: String): TSHA256Digest;
|
|
begin
|
|
if Length(S) <> 64 then
|
|
raise EConvertError.Create('Invalid string length');
|
|
|
|
for var I := 0 to 63 do begin
|
|
var B: Byte;
|
|
const C = UpCase(S.Chars[I]);
|
|
case C of
|
|
'0'..'9': B := Byte(Ord(C) - Ord('0'));
|
|
'A'..'F': B := Byte(Ord(C) - (Ord('A') - 10));
|
|
else
|
|
raise EConvertError.Create('Invalid digit character');
|
|
end;
|
|
const ResultIndex = I shr 1;
|
|
if not Odd(I) then
|
|
Result[ResultIndex] := Byte(B shl 4)
|
|
else
|
|
Result[ResultIndex] := Result[ResultIndex] or B;
|
|
end;
|
|
end;
|
|
|
|
end.
|