#pragma once #include #include #include #include #include #include namespace sha256_detail { static inline uint32_t rotr(uint32_t x, uint32_t n) { return (x >> n) | (x << (32 - n)); } static inline uint32_t Ch(uint32_t x, uint32_t y, uint32_t z) { return (x & y) ^ (~x & z); } static inline uint32_t Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) ^ (x & z) ^ (y & z); } static inline uint32_t bigSigma0(uint32_t x) { return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); } static inline uint32_t bigSigma1(uint32_t x) { return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); } static inline uint32_t smallSigma0(uint32_t x) { return rotr(x, 7) ^ rotr(x, 18) ^ (x >> 3); } static inline uint32_t smallSigma1(uint32_t x) { return rotr(x, 17) ^ rotr(x, 19) ^ (x >> 10); } static const uint32_t K[64] = { 0x428a2f98ul,0x71374491ul,0xb5c0fbcful,0xe9b5dba5ul,0x3956c25bul,0x59f111f1ul,0x923f82a4ul,0xab1c5ed5ul, 0xd807aa98ul,0x12835b01ul,0x243185beul,0x550c7dc3ul,0x72be5d74ul,0x80deb1feul,0x9bdc06a7ul,0xc19bf174ul, 0xe49b69c1ul,0xefbe4786ul,0x0fc19dc6ul,0x240ca1ccul,0x2de92c6ful,0x4a7484aaul,0x5cb0a9dcul,0x76f988daul, 0x983e5152ul,0xa831c66dul,0xb00327c8ul,0xbf597fc7ul,0xc6e00bf3ul,0xd5a79147ul,0x06ca6351ul,0x14292967ul, 0x27b70a85ul,0x2e1b2138ul,0x4d2c6dfcul,0x53380d13ul,0x650a7354ul,0x766a0abbul,0x81c2c92eul,0x92722c85ul, 0xa2bfe8a1ul,0xa81a664bul,0xc24b8b70ul,0xc76c51a3ul,0xd192e819ul,0xd6990624ul,0xf40e3585ul,0x106aa070ul, 0x19a4c116ul,0x1e376c08ul,0x2748774cul,0x34b0bcb5ul,0x391c0cb3ul,0x4ed8aa4aul,0x5b9cca4ful,0x682e6ff3ul, 0x748f82eeul,0x78a5636ful,0x84c87814ul,0x8cc70208ul,0x90befffaul,0xa4506cebul,0xbef9a3f7ul,0xc67178f2ul }; struct State { uint32_t h[8] = { 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul }; void transform(const uint8_t block[64]) { uint32_t w[64]; // 以大端解析前 16 个 32 位字 for (int i = 0; i < 16; ++i) { w[i] = (uint32_t(block[i * 4 + 0]) << 24) | (uint32_t(block[i * 4 + 1]) << 16) | (uint32_t(block[i * 4 + 2]) << 8) | (uint32_t(block[i * 4 + 3]) << 0); } // 扩展到 64 个字 for (int i = 16; i < 64; ++i) { w[i] = smallSigma1(w[i - 2]) + w[i - 7] + smallSigma0(w[i - 15]) + w[i - 16]; } uint32_t a = h[0], b = h[1], c = h[2], d = h[3], e = h[4], f = h[5], g = h[6], h0 = h[7]; for (int i = 0; i < 64; ++i) { uint32_t T1 = h0 + bigSigma1(e) + Ch(e, f, g) + K[i] + w[i]; uint32_t T2 = bigSigma0(a) + Maj(a, b, c); h0 = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; } h[0] += a; h[1] += b; h[2] += c; h[3] += d; h[4] += e; h[5] += f; h[6] += g; h[7] += h0; } }; inline std::string to_hex_lower(const uint8_t* bytes, size_t len) { static const char* digits = "0123456789abcdef"; std::string out; out.resize(len * 2); for (size_t i = 0; i < len; ++i) { out[2 * i + 0] = digits[(bytes[i] >> 4) & 0xF]; out[2 * i + 1] = digits[(bytes[i] >> 0) & 0xF]; } return out; } } // namespace sha256_detail // 一次性计算:输入任意二进制数据,返回 64 字节 hex 小写字符串 inline std::string sha256_hex(const void* data, size_t len) { using namespace sha256_detail; const uint8_t* p = static_cast(data); State st; // 处理完整的 64 字节块 size_t full = len / 64; for (size_t i = 0; i < full; ++i) { st.transform(p + i * 64); } // 处理尾块与填充 uint8_t block[128]; // 最多需要两个块 size_t rem = len % 64; std::memcpy(block, p + full * 64, rem); // 附加 0x80 block[rem++] = 0x80; // 若剩余空间不足以放 64-bit 长度(需要 8 字节),则补 0 到 64,再 transform,再在下一块补长度 if (rem > 56) { std::memset(block + rem, 0, 64 - rem); st.transform(block); rem = 0; } // 填 0,直到最后 8 字节留给长度(比特数,按大端) std::memset(block + rem, 0, 56 - rem); // 附加 64bit 原始长度(比特) uint64_t bitlen = static_cast(len) * 8ull; for (int i = 7; i >= 0; --i) { block[56 + (7 - i)] = static_cast((bitlen >> (i * 8)) & 0xFF); } // 最后一块 st.transform(block); // 输出大端 32-bit * 8 = 32 字节 uint8_t digest[32]; for (int i = 0; i < 8; ++i) { digest[i * 4 + 0] = static_cast((st.h[i] >> 24) & 0xFF); digest[i * 4 + 1] = static_cast((st.h[i] >> 16) & 0xFF); digest[i * 4 + 2] = static_cast((st.h[i] >> 8) & 0xFF); digest[i * 4 + 3] = static_cast((st.h[i] >> 0) & 0xFF); } return to_hex_lower(digest, 32); } // 便捷重载:字符串输入 inline std::string sha256_hex(const std::string& s) { return sha256_hex(s.data(), s.size()); }