SHA256.pas 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. unit SHA256;
  2. {
  3. SHA256.pas: System.Hash.pas wrapper in the style of MD5.pas and SHA1.pas
  4. Author: Martijn Laan
  5. License for SHA256.pas: Public domain, no copyright claimed
  6. }
  7. interface
  8. uses
  9. SysUtils, System.Hash;
  10. type
  11. TSHA256Context = record
  12. hash: THashSHA2;
  13. end;
  14. TSHA256Digest = array[0..31] of Byte;
  15. procedure SHA256Init(var ctx: TSHA256Context);
  16. procedure SHA256Update(var ctx: TSHA256Context; const buffer; len: Cardinal);
  17. function SHA256Final(var ctx: TSHA256Context): TSHA256Digest;
  18. function SHA256Buf(const Buffer; Len: Cardinal): TSHA256Digest;
  19. function SHA256DigestsEqual(const A, B: TSHA256Digest): Boolean;
  20. function SHA256DigestToString(const D: TSHA256Digest): String;
  21. function SHA256DigestFromString(const S: String): TSHA256Digest;
  22. implementation
  23. procedure SHA256Init(var ctx: TSHA256Context);
  24. begin
  25. ctx.hash := THashSHA2.Create(THashSHA2.TSHA2Version.SHA256);
  26. end;
  27. procedure SHA256Update(var ctx: TSHA256Context; const buffer; len: Cardinal);
  28. begin
  29. ctx.hash.Update(buffer, len);
  30. end;
  31. function SHA256Final(var ctx: TSHA256Context): TSHA256Digest;
  32. begin
  33. var HashAsBytes := ctx.hash.HashAsBytes;
  34. Move(HashAsBytes[0], Result[0], SizeOf(Result));
  35. end;
  36. function SHA256Buf(const Buffer; Len: Cardinal): TSHA256Digest;
  37. var
  38. Context: TSHA256Context;
  39. begin
  40. SHA256Init(Context);
  41. SHA256Update(Context, Buffer, Len);
  42. Result := SHA256Final(Context);
  43. end;
  44. function SHA256DigestsEqual(const A, B: TSHA256Digest): Boolean;
  45. var
  46. I: Integer;
  47. begin
  48. for I := Low(TSHA256Digest) to High(TSHA256Digest) do
  49. if A[I] <> B[I] then begin
  50. Result := False;
  51. Exit;
  52. end;
  53. Result := True;
  54. end;
  55. function SHA256DigestToString(const D: TSHA256Digest): String;
  56. const
  57. Digits: array[0..15] of Char = '0123456789abcdef';
  58. var
  59. Buf: array[0..63] of Char;
  60. P: PChar;
  61. I: Integer;
  62. begin
  63. P := @Buf;
  64. for I := 0 to 31 do begin
  65. P^ := Digits[D[I] shr 4];
  66. Inc(P);
  67. P^ := Digits[D[I] and 15];
  68. Inc(P);
  69. end;
  70. SetString(Result, Buf, 64);
  71. end;
  72. function SHA256DigestFromString(const S: String): TSHA256Digest;
  73. begin
  74. if Length(S) <> 64 then
  75. raise EConvertError.Create('Invalid string length');
  76. for var I := 0 to 63 do begin
  77. var B: Byte;
  78. const C = UpCase(S.Chars[I]);
  79. case C of
  80. '0'..'9': B := Byte(Ord(C) - Ord('0'));
  81. 'A'..'F': B := Byte(Ord(C) - (Ord('A') - 10));
  82. else
  83. raise EConvertError.Create('Invalid digit character');
  84. end;
  85. const ResultIndex = I shr 1;
  86. if not Odd(I) then
  87. Result[ResultIndex] := Byte(B shl 4)
  88. else
  89. Result[ResultIndex] := Result[ResultIndex] or B;
  90. end;
  91. end;
  92. end.