-
-
Notifications
You must be signed in to change notification settings - Fork 973
/
Copy pathSHA256.pas
108 lines (92 loc) · 2.65 KB
/
SHA256.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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.