33 _state[0] = 0x6a09e667;
34 _state[1] = 0xbb67ae85;
35 _state[2] = 0x3c6ef372;
36 _state[3] = 0xa54ff53a;
37 _state[4] = 0x510e527f;
38 _state[5] = 0x9b05688c;
39 _state[6] = 0x1f83d9ab;
40 _state[7] = 0x5be0cd19;
46 void Update(
void const* data,
size_t len)
48 auto const* bytes =
static_cast<uint8_t const*
>(data);
53 size_t const toCopy = std::min(
BlockSize - _bufferLen, len);
54 std::memcpy(_buffer.data() + _bufferLen, bytes, toCopy);
61 ProcessBlock(_buffer.data());
75 std::memcpy(_buffer.data(), bytes, len);
81 void Update(std::span<uint8_t const> data)
83 Update(data.data(), data.size());
89 Update(data.data(), data.size());
95 uint64_t
const bitCount = _count * 8;
98 uint8_t
const pad = 0x80;
101 while (_bufferLen != 56)
103 uint8_t
const zero = 0;
108 std::array<uint8_t, 8> countBytes {};
109 for (
size_t i = 0; i < 8; ++i)
110 countBytes[i] =
static_cast<uint8_t
>(bitCount >> (56 - i * 8));
111 Update(countBytes.data(), 8);
114 std::array<uint8_t, DigestSize> digest {};
115 for (
size_t i = 0; i < 8; ++i)
117 digest[(i * 4) + 0] =
static_cast<uint8_t
>(_state[i] >> 24);
118 digest[(i * 4) + 1] =
static_cast<uint8_t
>(_state[i] >> 16);
119 digest[(i * 4) + 2] =
static_cast<uint8_t
>(_state[i] >> 8);
120 digest[(i * 4) + 3] =
static_cast<uint8_t
>(_state[i]);
126 static std::string
ToHex(std::array<uint8_t, DigestSize>
const& digest)
128 std::ostringstream oss;
130 oss << std::hex << std::setfill(
'0') << std::setw(2) <<
static_cast<int>(b);
135 static std::string
Hash(
void const* data,
size_t len)
143 static std::string
Hash(std::string_view data)
145 return Hash(data.data(), data.size());
149 static constexpr std::array<uint32_t, 64> K = {
150 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
151 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
152 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
153 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
154 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
155 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
156 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
157 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
160 static uint32_t RotateRight(uint32_t x,
int n)
162 return (x >> n) | (x << (32 - n));
165 static uint32_t Ch(uint32_t x, uint32_t y, uint32_t z)
167 return (x & y) ^ (~x & z);
170 static uint32_t Maj(uint32_t x, uint32_t y, uint32_t z)
172 return (x & y) ^ (x & z) ^ (y & z);
175 static uint32_t Sigma0(uint32_t x)
177 return RotateRight(x, 2) ^ RotateRight(x, 13) ^ RotateRight(x, 22);
180 static uint32_t Sigma1(uint32_t x)
182 return RotateRight(x, 6) ^ RotateRight(x, 11) ^ RotateRight(x, 25);
185 static uint32_t LowerSigma0(uint32_t x)
187 return RotateRight(x, 7) ^ RotateRight(x, 18) ^ (x >> 3);
190 static uint32_t LowerSigma1(uint32_t x)
192 return RotateRight(x, 17) ^ RotateRight(x, 19) ^ (x >> 10);
195 void ProcessBlock(uint8_t
const* block)
197 std::array<uint32_t, 64> W {};
200 for (
size_t i = 0; i < 16; ++i)
202 W[i] = (
static_cast<uint32_t
>(block[i * 4]) << 24) | (
static_cast<uint32_t
>(block[(i * 4) + 1]) << 16)
203 | (
static_cast<uint32_t
>(block[(i * 4) + 2]) << 8) |
static_cast<uint32_t
>(block[(i * 4) + 3]);
205 for (
size_t i = 16; i < 64; ++i)
206 W[i] = LowerSigma1(W[i - 2]) + W[i - 7] + LowerSigma0(W[i - 15]) + W[i - 16];
209 uint32_t a = _state[0];
210 uint32_t b = _state[1];
211 uint32_t c = _state[2];
212 uint32_t d = _state[3];
213 uint32_t e = _state[4];
214 uint32_t f = _state[5];
215 uint32_t g = _state[6];
216 uint32_t h = _state[7];
219 for (
size_t i = 0; i < 64; ++i)
221 uint32_t
const T1 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];
222 uint32_t
const T2 = Sigma0(a) + Maj(a, b, c);
243 std::array<uint32_t, 8> _state {};
244 std::array<uint8_t, BlockSize> _buffer {};
245 size_t _bufferLen = 0;