Zgragselus

Sha256.cpp

Jun 22nd, 2026
24
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.93 KB | None | 0 0
  1. ///////////////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Sha256.h
  4. //
  5. ///////////////////////////////////////////////////////////////////////////////////////////////////
  6.  
  7. ///////////////////////////////////////////////////////////////////////////////////////////////////
  8. // Header section
  9.  
  10. #include "Sha256.h"
  11. #include <sstream>
  12. #include <iomanip>
  13.  
  14. ///////////////////////////////////////////////////////////////////////////////////////////////////
  15. // Declaration section
  16.  
  17. using namespace Engine;
  18.  
  19. ///////////////////////////////////////////////////////////////////////////////////////////////////
  20. // Definition section
  21.  
  22. /// <summary>Hashing key</summary>
  23. constexpr std::array<uint32_t, 64> Sha256::mKey;
  24.  
  25. /// <summary>
  26. /// Default constructor
  27. /// </summary>
  28. Sha256::Sha256() : mBlockLength(0), mBitLength(0)
  29. {
  30.     memset(mData, 0, sizeof(mData));
  31.  
  32.     mState[0] = 0x6a09e667;
  33.     mState[1] = 0xbb67ae85;
  34.     mState[2] = 0x3c6ef372;
  35.     mState[3] = 0xa54ff53a;
  36.     mState[4] = 0x510e527f;
  37.     mState[5] = 0x9b05688c;
  38.     mState[6] = 0x1f83d9ab;
  39.     mState[7] = 0x5be0cd19;
  40. }
  41.  
  42. /// <summary>
  43. /// Add data to hash (and re-calculate hash)
  44. /// </summary>
  45. /// <param name="data">Inpute data</param>
  46. /// <param name="length">Length of data in bytes</param>
  47. void Sha256::Update(const uint8_t* data, size_t length)
  48. {
  49.     for (size_t i = 0; i < length; i++)
  50.     {
  51.         mData[mBlockLength++] = data[i];
  52.  
  53.         if (mBlockLength == 64)
  54.         {
  55.             Transform();
  56.  
  57.             // End of block
  58.             mBitLength += 512;
  59.             mBlockLength = 0;
  60.         }
  61.     }
  62. }
  63.  
  64. /// <summary>
  65. /// Add data to hash (and re-calculate hash) - C string variant
  66. /// </summary>
  67. /// <param name="data">Inpute data</param>
  68. /// <param name="length">Length of data in bytes</param>
  69. void Sha256::Update(const char* data, size_t length)
  70. {
  71.     Update(reinterpret_cast<const uint8_t*>(data), length);
  72. }
  73.  
  74. /// <summary>
  75. /// Add data to hash (and re-calculate hash) - C++ String variant
  76. /// </summary>
  77. /// <param name="data">Inpute data</param>
  78. void Sha256::Update(const std::string& data)
  79. {
  80.     Update(reinterpret_cast<const uint8_t*>(data.c_str()), data.size());
  81. }
  82.  
  83. /// <summary>
  84. /// Get SHA-256 hash
  85. /// </summary>
  86. /// <returns>SHA-256 hash</returns>
  87. std::array<uint8_t, 32> Sha256::Digest()
  88. {
  89.     std::array<uint8_t, 32> hash;
  90.  
  91.     Pad();
  92.     Revert(hash);
  93.  
  94.     return hash;
  95. }
  96.  
  97. /// <summary>
  98. /// Get string representing SHA-256 hash (hexadecimal)
  99. /// </summary>
  100. /// <param name="digest">SHA-256 to get string of</param>
  101. /// <returns>String representation of SHA-256 hash (hexadecimal)</returns>
  102. std::string Sha256::ToString(const std::array<uint8_t, 32>& digest)
  103. {
  104.     std::stringstream ss;
  105.     ss << std::setfill('0') << std::hex;
  106.  
  107.     for (uint8_t i = 0; i < 32; i++)
  108.     {
  109.         ss << std::setw(2) << (unsigned int)digest[i];
  110.     }
  111.  
  112.     return ss.str();
  113. }
  114.  
  115. /// <summary>
  116. /// Rotate bits right
  117. /// </summary>
  118. /// <param name="value">Input value</param>
  119. /// <param name="count">No. of bits to rotate right</param>
  120. /// <returns>Value rotated right by count bits</returns>
  121. uint32_t Sha256::RotateRight(uint32_t value, uint32_t count)
  122. {
  123.     return (value >> count) | (value << (32 - count));
  124. }
  125.  
  126. /// <summary>
  127. /// Choose function - select input F or G based on mask
  128. /// </summary>
  129. /// <param name="e">Mask</param>
  130. /// <param name="f">Input F</param>
  131. /// <param name="g">Input G</param>
  132. /// <returns>Combination of Input F and G based on mask</returns>
  133. uint32_t Sha256::Choose(uint32_t e, uint32_t f, uint32_t g)
  134. {
  135.     return (e & f) ^ (~e & g);
  136. }
  137.  
  138. /// <summary>
  139. /// Bit majority function - median bit operator (n-th bit is 1 when majority of inputs is 1, otherwise 0)
  140. /// </summary>
  141. /// <param name="a">Input A</param>
  142. /// <param name="b">Input B</param>
  143. /// <param name="c">Input C</param>
  144. /// <returns>Bit majority of A, B and C</returns>
  145. uint32_t Sha256::Majority(uint32_t a, uint32_t b, uint32_t c)
  146. {
  147.     return (a & (b | c)) | (b & c);
  148. }
  149.  
  150. /// <summary>
  151. /// Sigma-0 function for SHA
  152. /// </summary>
  153. /// <param name="value">Input value</param>
  154. /// <returns>Sigma-0 of input value</returns>
  155. uint32_t Sha256::Sigma0(uint32_t value)
  156. {
  157.     return RotateRight(value, 7) ^ RotateRight(value, 18) ^ (value >> 3);
  158. }
  159.  
  160. /// <summary>
  161. /// Sigma-1 function for SHA
  162. /// </summary>
  163. /// <param name="value">Input value</param>
  164. /// <returns>Sigma-1 of input value</returns>
  165. uint32_t Sha256::Sigma1(uint32_t value)
  166. {
  167.     return RotateRight(value, 17) ^ RotateRight(value, 19) ^ (value >> 10);
  168. }
  169.  
  170. /// <summary>
  171. /// Transformation function
  172. /// </summary>
  173. void Sha256::Transform()
  174. {
  175.     uint32_t m[64] = { 0 };
  176.  
  177.     // Split data with 32-bits into first 16 blocks
  178.     for (uint8_t i = 0, j = 0; i < 16; i++, j += 4)
  179.     {
  180.         m[i] = (mData[j] << 24) | (mData[j + 1] << 16) | (mData[j + 2] << 8) | mData[j + 3];
  181.     }
  182.  
  183.     // Remaining 48 blocks
  184.     for (uint8_t i = 16; i < 64; i++)
  185.     {
  186.         m[i] = Sigma1(m[i - 2]) + m[i - 7] + Sigma0(m[i - 15]) + m[i - 16];
  187.     }
  188.  
  189.     // Store state to local
  190.     uint32_t state[8] = { 0 };
  191.     for (uint8_t i = 0; i < 8; i++)
  192.     {
  193.         state[i] = mState[i];
  194.     }
  195.  
  196.     for (uint8_t i = 0; i < 64; i++)
  197.     {
  198.         uint32_t majority = Majority(state[0], state[1], state[2]);
  199.         uint32_t xora = RotateRight(state[0], 2) ^ RotateRight(state[0], 13) ^ RotateRight(state[0], 22);
  200.         uint32_t ch = Choose(state[4], state[5], state[6]);
  201.         uint32_t xore = RotateRight(state[4], 6) ^ RotateRight(state[4], 11) ^ RotateRight(state[4], 25);
  202.  
  203.         uint32_t sum = m[i] + mKey[i] + state[7] + ch + xore;
  204.         uint32_t newa = xora + majority + sum;
  205.         uint32_t newe = state[3] + sum;
  206.  
  207.         state[7] = state[6];
  208.         state[6] = state[5];
  209.         state[5] = state[4];
  210.         state[4] = newe;
  211.         state[3] = state[2];
  212.         state[2] = state[1];
  213.         state[1] = state[0];
  214.         state[0] = newa;
  215.     }
  216.  
  217.     for (uint8_t i = 0; i < 8; i++)
  218.     {
  219.         mState[i] += state[i];
  220.     }
  221. }
  222.  
  223. /// <summary>
  224. /// Padding function
  225. /// </summary>
  226. void Sha256::Pad()
  227. {
  228.     uint64_t i = mBlockLength;
  229.     uint8_t end = mBlockLength < 56 ? 56 : 64;
  230.  
  231.     // Append bit 1
  232.     mData[i++] = 0x80;
  233.     // Pad with 0
  234.     while (i < end)
  235.     {
  236.         mData[i++] = 0x00;
  237.     }
  238.  
  239.     if (mBlockLength >= 56)
  240.     {
  241.         Transform();
  242.         memset(mData, 0, 56);
  243.     }
  244.  
  245.     // Append padding to the total messages length in bits and transform
  246.     mBitLength += mBlockLength * 8;
  247.     mData[63] = (uint8_t)mBitLength;
  248.     mData[62] = (uint8_t)(mBitLength >> 8);
  249.     mData[61] = (uint8_t)(mBitLength >> 16);
  250.     mData[60] = (uint8_t)(mBitLength >> 24);
  251.     mData[59] = (uint8_t)(mBitLength >> 32);
  252.     mData[58] = (uint8_t)(mBitLength >> 40);
  253.     mData[57] = (uint8_t)(mBitLength >> 48);
  254.     mData[56] = (uint8_t)(mBitLength >> 56);
  255.     Transform();
  256. }
  257.  
  258. /// <summary>
  259. /// Revert hash
  260. ///
  261. /// SHA generally uses big-endian ordering, revert all the bytes
  262. /// </summary>
  263. /// <param name="hash">Hash array to revert</param>
  264. void Sha256::Revert(std::array<uint8_t, 32>& hash)
  265. {
  266.     // SHA generally uses big-endian ordering, revert all the bytes
  267.     for (uint8_t i = 0; i < 4; i++)
  268.     {
  269.         for (uint8_t j = 0; j < 8; j++)
  270.         {
  271.             hash[i + (j * 4)] = (mState[j] >> (24 - i * 8)) & 0xFF;
  272.         }
  273.     }
  274. }
Advertisement
Add Comment
Please, Sign In to add comment