37 const std::array<std::uint32_t, 8> state = digest(message);
39 std::string hexadecimal;
40 hexadecimal.reserve(64);
41 for (std::uint32_t word : state) {
43 std::snprintf(buffer,
sizeof(buffer),
"%08x", word);
44 hexadecimal += buffer;
64 std::FILE* file = std::fopen(path.c_str(),
"rb");
65 if (file ==
nullptr) {
66 throw std::runtime_error(
"SHA256: cannot open '" + path +
"'");
73 while ((read = std::fread(buffer, 1,
sizeof(buffer), file)) > 0) {
74 contents.append(buffer, read);
80 const bool read_failed = std::ferror(file) != 0;
83 throw std::runtime_error(
"SHA256: error reading '" + path +
"'");
89 [[nodiscard]]
static std::uint32_t rotate_right(std::uint32_t value,
int places) {
90 return (value >> places) | (value << (32 - places));
94 [[nodiscard]]
static std::array<std::uint32_t, 8> digest(
const std::string& message) {
95 std::array<std::uint32_t, 8> state = {0x6a09e667u,
108 std::vector<unsigned char> padded(message.begin(), message.end());
109 const std::uint64_t length_in_bits =
static_cast<std::uint64_t
>(message.size()) * 8;
110 padded.push_back(0x80);
111 while (padded.size() % 64 != 56) {
112 padded.push_back(0x00);
114 for (
int shift = 56; shift >= 0; shift -= 8) {
115 padded.push_back(
static_cast<unsigned char>((length_in_bits >> shift) & 0xffu));
118 std::array<std::uint32_t, 64> schedule{};
119 for (std::size_t block = 0; block < padded.size(); block += 64) {
120 for (
int index = 0; index < 16; index++) {
121 const std::size_t offset = block +
static_cast<std::size_t
>(index) * 4;
122 schedule[index] = (
static_cast<std::uint32_t
>(padded[offset]) << 24) |
123 (
static_cast<std::uint32_t
>(padded[offset + 1]) << 16) |
124 (
static_cast<std::uint32_t
>(padded[offset + 2]) << 8) |
125 static_cast<std::uint32_t
>(padded[offset + 3]);
127 for (
int index = 16; index < 64; index++) {
128 const std::uint32_t previous = schedule[index - 15];
129 const std::uint32_t recent = schedule[index - 2];
130 const std::uint32_t sigma_zero =
131 rotate_right(previous, 7) ^ rotate_right(previous, 18) ^ (previous >> 3);
132 const std::uint32_t sigma_one =
133 rotate_right(recent, 17) ^ rotate_right(recent, 19) ^ (recent >> 10);
135 schedule[index - 16] + sigma_zero + schedule[index - 7] + sigma_one;
138 std::array<std::uint32_t, 8> working = state;
139 for (
int index = 0; index < 64; index++) {
140 const std::uint32_t capital_sigma_one = rotate_right(working[4], 6) ^
141 rotate_right(working[4], 11) ^
142 rotate_right(working[4], 25);
143 const std::uint32_t choice = (working[4] & working[5]) ^ (~working[4] & working[6]);
144 const std::uint32_t first = working[7] + capital_sigma_one + choice +
145 round_constants()[index] + schedule[index];
146 const std::uint32_t capital_sigma_zero = rotate_right(working[0], 2) ^
147 rotate_right(working[0], 13) ^
148 rotate_right(working[0], 22);
149 const std::uint32_t majority = (working[0] & working[1]) ^
150 (working[0] & working[2]) ^
151 (working[1] & working[2]);
152 const std::uint32_t second = capital_sigma_zero + majority;
154 working[7] = working[6];
155 working[6] = working[5];
156 working[5] = working[4];
157 working[4] = working[3] + first;
158 working[3] = working[2];
159 working[2] = working[1];
160 working[1] = working[0];
161 working[0] = first + second;
163 for (
int index = 0; index < 8; index++) {
164 state[index] += working[index];
171 [[nodiscard]]
static const std::array<std::uint32_t, 64>& round_constants() {
172 static const std::array<std::uint32_t, 64> constants = {
173 0x428a2f98u, 0x71374491u, 0xb5c0fbcfu, 0xe9b5dba5u, 0x3956c25bu, 0x59f111f1u,
174 0x923f82a4u, 0xab1c5ed5u, 0xd807aa98u, 0x12835b01u, 0x243185beu, 0x550c7dc3u,
175 0x72be5d74u, 0x80deb1feu, 0x9bdc06a7u, 0xc19bf174u, 0xe49b69c1u, 0xefbe4786u,
176 0x0fc19dc6u, 0x240ca1ccu, 0x2de92c6fu, 0x4a7484aau, 0x5cb0a9dcu, 0x76f988dau,
177 0x983e5152u, 0xa831c66du, 0xb00327c8u, 0xbf597fc7u, 0xc6e00bf3u, 0xd5a79147u,
178 0x06ca6351u, 0x14292967u, 0x27b70a85u, 0x2e1b2138u, 0x4d2c6dfcu, 0x53380d13u,
179 0x650a7354u, 0x766a0abbu, 0x81c2c92eu, 0x92722c85u, 0xa2bfe8a1u, 0xa81a664bu,
180 0xc24b8b70u, 0xc76c51a3u, 0xd192e819u, 0xd6990624u, 0xf40e3585u, 0x106aa070u,
181 0x19a4c116u, 0x1e376c08u, 0x2748774cu, 0x34b0bcb5u, 0x391c0cb3u, 0x4ed8aa4au,
182 0x5b9cca4fu, 0x682e6ff3u, 0x748f82eeu, 0x78a5636fu, 0x84c87814u, 0x8cc70208u,
183 0x90befffau, 0xa4506cebu, 0xbef9a3f7u, 0xc67178f2u};