|
2 | 2 |
|
3 | 3 | #include <array> // std::array |
4 | 4 | #include <cstdint> // std::uint32_t, std::uint64_t |
| 5 | + |
| 6 | +#ifdef SOURCEMETA_CORE_CRYPTO_USE_SYSTEM_OPENSSL |
| 7 | +#include <openssl/evp.h> // EVP_MD_CTX_new, EVP_DigestInit_ex, EVP_sha256, EVP_DigestUpdate, EVP_DigestFinal_ex, EVP_MD_CTX_free |
| 8 | +#include <stdexcept> // std::runtime_error |
| 9 | +#else |
5 | 10 | #include <cstring> // std::memcpy |
| 11 | +#endif |
| 12 | + |
| 13 | +namespace { |
| 14 | +constexpr std::array<char, 17> HEX_DIGITS{{'0', '1', '2', '3', '4', '5', '6', |
| 15 | + '7', '8', '9', 'a', 'b', 'c', 'd', |
| 16 | + 'e', 'f', '\0'}}; |
| 17 | +} // namespace |
| 18 | + |
| 19 | +#ifdef SOURCEMETA_CORE_CRYPTO_USE_SYSTEM_OPENSSL |
| 20 | + |
| 21 | +namespace sourcemeta::core { |
| 22 | + |
| 23 | +auto sha256(const std::string_view input, std::ostream &output) -> void { |
| 24 | + auto *context = EVP_MD_CTX_new(); |
| 25 | + if (context == nullptr) { |
| 26 | + throw std::runtime_error("Could not allocate OpenSSL digest context"); |
| 27 | + } |
| 28 | + |
| 29 | + if (EVP_DigestInit_ex(context, EVP_sha256(), nullptr) != 1 || |
| 30 | + EVP_DigestUpdate(context, input.data(), input.size()) != 1) { |
| 31 | + EVP_MD_CTX_free(context); |
| 32 | + throw std::runtime_error("Could not compute SHA-256 digest"); |
| 33 | + } |
| 34 | + |
| 35 | + std::array<unsigned char, 32> digest{}; |
| 36 | + unsigned int length = 0; |
| 37 | + if (EVP_DigestFinal_ex(context, digest.data(), &length) != 1) { |
| 38 | + EVP_MD_CTX_free(context); |
| 39 | + throw std::runtime_error("Could not finalize SHA-256 digest"); |
| 40 | + } |
| 41 | + |
| 42 | + EVP_MD_CTX_free(context); |
| 43 | + |
| 44 | + for (std::uint64_t index = 0; index < 32u; ++index) { |
| 45 | + output.put(HEX_DIGITS[(digest[index] >> 4u) & 0x0fu]); |
| 46 | + output.put(HEX_DIGITS[digest[index] & 0x0fu]); |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +} // namespace sourcemeta::core |
| 51 | + |
| 52 | +#else |
6 | 53 |
|
7 | 54 | namespace { |
8 | 55 |
|
@@ -169,17 +216,15 @@ auto sha256(const std::string_view input, std::ostream &output) -> void { |
169 | 216 | sha256_process_block(final_block.data() + 64u, state); |
170 | 217 | } |
171 | 218 |
|
172 | | - // Produce the final hex digest directly from state words (big-endian) |
173 | | - static constexpr std::array<char, 17> hex_digits{ |
174 | | - {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', |
175 | | - 'e', 'f', '\0'}}; |
176 | 219 | for (std::uint64_t state_index = 0u; state_index < 8u; ++state_index) { |
177 | 220 | const auto value = state[state_index]; |
178 | 221 | for (std::uint64_t nibble = 0u; nibble < 8u; ++nibble) { |
179 | 222 | const auto shift = 28u - nibble * 4u; |
180 | | - output.put(hex_digits[(value >> shift) & 0x0fu]); |
| 223 | + output.put(HEX_DIGITS[(value >> shift) & 0x0fu]); |
181 | 224 | } |
182 | 225 | } |
183 | 226 | } |
184 | 227 |
|
185 | 228 | } // namespace sourcemeta::core |
| 229 | + |
| 230 | +#endif |
0 commit comments