20 static constexpr size_t DigestSize = 32;
21 static constexpr size_t BlockSize = 64;
30 _state[0] = 0x6a09e667;
31 _state[1] = 0xbb67ae85;
32 _state[2] = 0x3c6ef372;
33 _state[3] = 0xa54ff53a;
34 _state[4] = 0x510e527f;
35 _state[5] = 0x9b05688c;
36 _state[6] = 0x1f83d9ab;
37 _state[7] = 0x5be0cd19;
42 void Update(
void const* data,
size_t len)
44 auto const* bytes =
static_cast<uint8_t const*
>(data);
49 size_t const toCopy = std::min(BlockSize - _bufferLen, len);
50 std::memcpy(_buffer.data() + _bufferLen, bytes, toCopy);
55 if (_bufferLen == BlockSize)
57 ProcessBlock(_buffer.data());
62 while (len >= BlockSize)
71 std::memcpy(_buffer.data(), bytes, len);
76 void Update(std::span<uint8_t const> data)
78 Update(data.data(), data.size());
81 void Update(std::string_view data)
83 Update(data.data(), data.size());
86 std::array<uint8_t, DigestSize> Finalize()
88 uint64_t
const bitCount = _count * 8;
91 uint8_t
const pad = 0x80;
94 while (_bufferLen != 56)
96 uint8_t
const zero = 0;
101 std::array<uint8_t, 8> countBytes {};
102 for (
size_t i = 0; i < 8; ++i)
103 countBytes[i] =
static_cast<uint8_t
>(bitCount >> (56 - i * 8));
104 Update(countBytes.data(), 8);
107 std::array<uint8_t, DigestSize> digest {};
108 for (
size_t i = 0; i < 8; ++i)
110 digest[(i * 4) + 0] =
static_cast<uint8_t
>(_state[i] >> 24);
111 digest[(i * 4) + 1] =
static_cast<uint8_t
>(_state[i] >> 16);
112 digest[(i * 4) + 2] =
static_cast<uint8_t
>(_state[i] >> 8);
113 digest[(i * 4) + 3] =
static_cast<uint8_t
>(_state[i]);
118 static std::string ToHex(std::array<uint8_t, DigestSize>
const& digest)
120 std::ostringstream oss;
122 oss << std::hex << std::setfill(
'0') << std::setw(2) <<
static_cast<int>(b);
126 static std::string Hash(
void const* data,
size_t len)
129 hasher.Update(data, len);
130 return ToHex(hasher.Finalize());
133 static std::string Hash(std::string_view data)
135 return Hash(data.data(), data.size());
139 static constexpr std::array<uint32_t, 64> K = {
140 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
141 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
142 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
143 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
144 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
145 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
146 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
147 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
150 static uint32_t RotateRight(uint32_t x,
int n)
152 return (x >> n) | (x << (32 - n));
155 static uint32_t Ch(uint32_t x, uint32_t y, uint32_t z)
157 return (x & y) ^ (~x & z);
160 static uint32_t Maj(uint32_t x, uint32_t y, uint32_t z)
162 return (x & y) ^ (x & z) ^ (y & z);
165 static uint32_t Sigma0(uint32_t x)
167 return RotateRight(x, 2) ^ RotateRight(x, 13) ^ RotateRight(x, 22);
170 static uint32_t Sigma1(uint32_t x)
172 return RotateRight(x, 6) ^ RotateRight(x, 11) ^ RotateRight(x, 25);
175 static uint32_t LowerSigma0(uint32_t x)
177 return RotateRight(x, 7) ^ RotateRight(x, 18) ^ (x >> 3);
180 static uint32_t LowerSigma1(uint32_t x)
182 return RotateRight(x, 17) ^ RotateRight(x, 19) ^ (x >> 10);
185 void ProcessBlock(uint8_t
const* block)
187 std::array<uint32_t, 64> W {};
190 for (
size_t i = 0; i < 16; ++i)
192 W[i] = (
static_cast<uint32_t
>(block[i * 4]) << 24) | (
static_cast<uint32_t
>(block[(i * 4) + 1]) << 16)
193 | (
static_cast<uint32_t
>(block[(i * 4) + 2]) << 8) |
static_cast<uint32_t
>(block[(i * 4) + 3]);
195 for (
size_t i = 16; i < 64; ++i)
196 W[i] = LowerSigma1(W[i - 2]) + W[i - 7] + LowerSigma0(W[i - 15]) + W[i - 16];
199 uint32_t a = _state[0];
200 uint32_t b = _state[1];
201 uint32_t c = _state[2];
202 uint32_t d = _state[3];
203 uint32_t e = _state[4];
204 uint32_t f = _state[5];
205 uint32_t g = _state[6];
206 uint32_t h = _state[7];
209 for (
size_t i = 0; i < 64; ++i)
211 uint32_t
const T1 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];
212 uint32_t
const T2 = Sigma0(a) + Maj(a, b, c);
233 std::array<uint32_t, 8> _state {};
234 std::array<uint8_t, BlockSize> _buffer {};
235 size_t _bufferLen = 0;