SHA256.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #pragma once
  2. #include <cstdint>
  3. #include <cstring>
  4. #include <string>
  5. #include <vector>
  6. #include <iomanip>
  7. #include <sstream>
  8. namespace sha256_detail {
  9. static inline uint32_t rotr(uint32_t x, uint32_t n) {
  10. return (x >> n) | (x << (32 - n));
  11. }
  12. static inline uint32_t Ch(uint32_t x, uint32_t y, uint32_t z) { return (x & y) ^ (~x & z); }
  13. static inline uint32_t Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) ^ (x & z) ^ (y & z); }
  14. static inline uint32_t bigSigma0(uint32_t x) { return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); }
  15. static inline uint32_t bigSigma1(uint32_t x) { return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); }
  16. static inline uint32_t smallSigma0(uint32_t x) { return rotr(x, 7) ^ rotr(x, 18) ^ (x >> 3); }
  17. static inline uint32_t smallSigma1(uint32_t x) { return rotr(x, 17) ^ rotr(x, 19) ^ (x >> 10); }
  18. static const uint32_t K[64] = {
  19. 0x428a2f98ul,0x71374491ul,0xb5c0fbcful,0xe9b5dba5ul,0x3956c25bul,0x59f111f1ul,0x923f82a4ul,0xab1c5ed5ul,
  20. 0xd807aa98ul,0x12835b01ul,0x243185beul,0x550c7dc3ul,0x72be5d74ul,0x80deb1feul,0x9bdc06a7ul,0xc19bf174ul,
  21. 0xe49b69c1ul,0xefbe4786ul,0x0fc19dc6ul,0x240ca1ccul,0x2de92c6ful,0x4a7484aaul,0x5cb0a9dcul,0x76f988daul,
  22. 0x983e5152ul,0xa831c66dul,0xb00327c8ul,0xbf597fc7ul,0xc6e00bf3ul,0xd5a79147ul,0x06ca6351ul,0x14292967ul,
  23. 0x27b70a85ul,0x2e1b2138ul,0x4d2c6dfcul,0x53380d13ul,0x650a7354ul,0x766a0abbul,0x81c2c92eul,0x92722c85ul,
  24. 0xa2bfe8a1ul,0xa81a664bul,0xc24b8b70ul,0xc76c51a3ul,0xd192e819ul,0xd6990624ul,0xf40e3585ul,0x106aa070ul,
  25. 0x19a4c116ul,0x1e376c08ul,0x2748774cul,0x34b0bcb5ul,0x391c0cb3ul,0x4ed8aa4aul,0x5b9cca4ful,0x682e6ff3ul,
  26. 0x748f82eeul,0x78a5636ful,0x84c87814ul,0x8cc70208ul,0x90befffaul,0xa4506cebul,0xbef9a3f7ul,0xc67178f2ul
  27. };
  28. struct State {
  29. uint32_t h[8] = {
  30. 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul,
  31. 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul
  32. };
  33. void transform(const uint8_t block[64]) {
  34. uint32_t w[64];
  35. // 以大端解析前 16 个 32 位字
  36. for (int i = 0; i < 16; ++i) {
  37. w[i] = (uint32_t(block[i * 4 + 0]) << 24) |
  38. (uint32_t(block[i * 4 + 1]) << 16) |
  39. (uint32_t(block[i * 4 + 2]) << 8) |
  40. (uint32_t(block[i * 4 + 3]) << 0);
  41. }
  42. // 扩展到 64 个字
  43. for (int i = 16; i < 64; ++i) {
  44. w[i] = smallSigma1(w[i - 2]) + w[i - 7] + smallSigma0(w[i - 15]) + w[i - 16];
  45. }
  46. 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];
  47. for (int i = 0; i < 64; ++i) {
  48. uint32_t T1 = h0 + bigSigma1(e) + Ch(e, f, g) + K[i] + w[i];
  49. uint32_t T2 = bigSigma0(a) + Maj(a, b, c);
  50. h0 = g;
  51. g = f;
  52. f = e;
  53. e = d + T1;
  54. d = c;
  55. c = b;
  56. b = a;
  57. a = T1 + T2;
  58. }
  59. h[0] += a; h[1] += b; h[2] += c; h[3] += d;
  60. h[4] += e; h[5] += f; h[6] += g; h[7] += h0;
  61. }
  62. };
  63. inline std::string to_hex_lower(const uint8_t* bytes, size_t len) {
  64. static const char* digits = "0123456789abcdef";
  65. std::string out;
  66. out.resize(len * 2);
  67. for (size_t i = 0; i < len; ++i) {
  68. out[2 * i + 0] = digits[(bytes[i] >> 4) & 0xF];
  69. out[2 * i + 1] = digits[(bytes[i] >> 0) & 0xF];
  70. }
  71. return out;
  72. }
  73. } // namespace sha256_detail
  74. // 一次性计算:输入任意二进制数据,返回 64 字节 hex 小写字符串
  75. inline std::string sha256_hex(const void* data, size_t len) {
  76. using namespace sha256_detail;
  77. const uint8_t* p = static_cast<const uint8_t*>(data);
  78. State st;
  79. // 处理完整的 64 字节块
  80. size_t full = len / 64;
  81. for (size_t i = 0; i < full; ++i) {
  82. st.transform(p + i * 64);
  83. }
  84. // 处理尾块与填充
  85. uint8_t block[128]; // 最多需要两个块
  86. size_t rem = len % 64;
  87. std::memcpy(block, p + full * 64, rem);
  88. // 附加 0x80
  89. block[rem++] = 0x80;
  90. // 若剩余空间不足以放 64-bit 长度(需要 8 字节),则补 0 到 64,再 transform,再在下一块补长度
  91. if (rem > 56) {
  92. std::memset(block + rem, 0, 64 - rem);
  93. st.transform(block);
  94. rem = 0;
  95. }
  96. // 填 0,直到最后 8 字节留给长度(比特数,按大端)
  97. std::memset(block + rem, 0, 56 - rem);
  98. // 附加 64bit 原始长度(比特)
  99. uint64_t bitlen = static_cast<uint64_t>(len) * 8ull;
  100. for (int i = 7; i >= 0; --i) {
  101. block[56 + (7 - i)] = static_cast<uint8_t>((bitlen >> (i * 8)) & 0xFF);
  102. }
  103. // 最后一块
  104. st.transform(block);
  105. // 输出大端 32-bit * 8 = 32 字节
  106. uint8_t digest[32];
  107. for (int i = 0; i < 8; ++i) {
  108. digest[i * 4 + 0] = static_cast<uint8_t>((st.h[i] >> 24) & 0xFF);
  109. digest[i * 4 + 1] = static_cast<uint8_t>((st.h[i] >> 16) & 0xFF);
  110. digest[i * 4 + 2] = static_cast<uint8_t>((st.h[i] >> 8) & 0xFF);
  111. digest[i * 4 + 3] = static_cast<uint8_t>((st.h[i] >> 0) & 0xFF);
  112. }
  113. return to_hex_lower(digest, 32);
  114. }
  115. // 便捷重载:字符串输入
  116. inline std::string sha256_hex(const std::string& s) {
  117. return sha256_hex(s.data(), s.size());
  118. }