SHA256.pas 2.7 KB

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