123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- #pragma once
- #include <cstdint>
- #include <cstring>
- #include <string>
- #include <vector>
- #include <iomanip>
- #include <sstream>
- 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<const uint8_t*>(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<uint64_t>(len) * 8ull;
- for (int i = 7; i >= 0; --i) {
- block[56 + (7 - i)] = static_cast<uint8_t>((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<uint8_t>((st.h[i] >> 24) & 0xFF);
- digest[i * 4 + 1] = static_cast<uint8_t>((st.h[i] >> 16) & 0xFF);
- digest[i * 4 + 2] = static_cast<uint8_t>((st.h[i] >> 8) & 0xFF);
- digest[i * 4 + 3] = static_cast<uint8_t>((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());
- }
|