/Source/ThirdParty/Poco/Foundation/src/SHA1Engine.cpp

https://gitlab.com/Teo-Mirror/AtomicGameEngine · C++ · 285 lines · 194 code · 53 blank · 38 comment · 8 complexity · 06a7f34d5677769d0d72f26174be94e1 MD5 · raw file

  1. //
  2. // SHA1Engine.cpp
  3. //
  4. // $Id: //poco/1.4/Foundation/src/SHA1Engine.cpp#1 $
  5. //
  6. // Library: Foundation
  7. // Package: Crypt
  8. // Module: SHA1Engine
  9. //
  10. // Based on the public domain implementation by Peter C. Gutmann
  11. // on 2 Sep 1992, modified by Carl Ellison to be SHA-1.
  12. //
  13. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
  14. // and Contributors.
  15. //
  16. // SPDX-License-Identifier: BSL-1.0
  17. //
  18. #include "Poco/SHA1Engine.h"
  19. #include <cstring>
  20. #ifdef POCO_ARCH_LITTLE_ENDIAN
  21. #define SHA1_BYTE_REVERSE(x, y) byteReverse(x, y)
  22. #else
  23. #define SHA1_BYTE_REVERSE(x, y)
  24. #endif
  25. namespace Poco {
  26. SHA1Engine::SHA1Engine()
  27. {
  28. _digest.reserve(16);
  29. reset();
  30. }
  31. SHA1Engine::~SHA1Engine()
  32. {
  33. reset();
  34. }
  35. inline void SHA1Engine::byteReverse(UInt32* buffer, int byteCount)
  36. {
  37. #ifdef POCO_ARCH_LITTLE_ENDIAN
  38. byteCount /= sizeof(UInt32);
  39. for(int count = 0; count < byteCount; count++)
  40. {
  41. UInt32 value = (buffer[ count ] << 16) | (buffer[ count ] >> 16);
  42. buffer[count] = ((value & 0xFF00FF00L) >> 8) | ((value & 0x00FF00FFL) << 8);
  43. }
  44. #endif // POCO_ARCH_LITTLE_ENDIAN
  45. }
  46. void SHA1Engine::updateImpl(const void* buffer_, std::size_t count)
  47. {
  48. const BYTE* buffer = (const BYTE*) buffer_;
  49. BYTE* db = (BYTE*) &_context.data[0];
  50. /* Update bitcount */
  51. if ((_context.countLo + ((UInt32) count << 3)) < _context.countLo)
  52. _context.countHi++; /* Carry from low to high bitCount */
  53. _context.countLo += ((UInt32) count << 3);
  54. _context.countHi += ((UInt32 ) count >> 29);
  55. /* Process data in BLOCK_SIZE chunks */
  56. while (count-- > 0)
  57. {
  58. db[_context.slop++] = *(buffer++);
  59. if (_context.slop == BLOCK_SIZE)
  60. {
  61. /* transform this one block */
  62. SHA1_BYTE_REVERSE(_context.data, BLOCK_SIZE);
  63. transform();
  64. _context.slop = 0 ; /* no slop left */
  65. }
  66. }
  67. }
  68. std::size_t SHA1Engine::digestLength() const
  69. {
  70. return DIGEST_SIZE;
  71. }
  72. void SHA1Engine::reset()
  73. {
  74. _context.digest[0] = 0x67452301L;
  75. _context.digest[1] = 0xEFCDAB89L;
  76. _context.digest[2] = 0x98BADCFEL;
  77. _context.digest[3] = 0x10325476L;
  78. _context.digest[4] = 0xC3D2E1F0L;
  79. _context.countLo = 0;
  80. _context.countHi = 0;
  81. _context.slop = 0;
  82. std::memset(_context.data, 0, sizeof(_context.data));
  83. }
  84. const DigestEngine::Digest& SHA1Engine::digest()
  85. {
  86. int count;
  87. UInt32 lowBitcount = _context.countLo;
  88. UInt32 highBitcount = _context.countHi;
  89. /* Compute number of bytes mod 64 */
  90. count = (int) ((_context.countLo >> 3) & 0x3F);
  91. /* Set the first char of padding to 0x80. This is safe since there is
  92. always at least one byte free */
  93. ((BYTE*) _context.data)[count++] = 0x80;
  94. /* Pad out to 56 mod 64 */
  95. if (count > 56)
  96. {
  97. /* Two lots of padding: Pad the first block to 64 bytes */
  98. std::memset((BYTE*) &_context.data + count, 0, 64 - count);
  99. SHA1_BYTE_REVERSE(_context.data, BLOCK_SIZE);
  100. transform();
  101. /* Now fill the next block with 56 bytes */
  102. std::memset(&_context.data, 0, 56);
  103. }
  104. else
  105. {
  106. /* Pad block to 56 bytes */
  107. std::memset((BYTE*) &_context.data + count, 0, 56 - count);
  108. }
  109. SHA1_BYTE_REVERSE(_context.data, BLOCK_SIZE);
  110. /* Append length in bits and transform */
  111. _context.data[14] = highBitcount;
  112. _context.data[15] = lowBitcount;
  113. transform();
  114. SHA1_BYTE_REVERSE(_context.data, DIGEST_SIZE);
  115. unsigned char hash[DIGEST_SIZE];
  116. for (count = 0; count < DIGEST_SIZE; count++)
  117. hash[count] = (BYTE) ((_context.digest[count>>2]) >> (8*(3-(count & 0x3)))) & 0xff;
  118. _digest.clear();
  119. _digest.insert(_digest.begin(), hash, hash + DIGEST_SIZE);
  120. reset();
  121. return _digest;
  122. }
  123. /* The SHA f()-functions */
  124. #define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) /* Rounds 0-19 */
  125. #define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */
  126. #define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) /* Rounds 40-59 */
  127. #define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */
  128. /* The SHA Mysterious Constants */
  129. #define K1 0x5A827999L /* Rounds 0-19 */
  130. #define K2 0x6ED9EBA1L /* Rounds 20-39 */
  131. #define K3 0x8F1BBCDCL /* Rounds 40-59 */
  132. #define K4 0xCA62C1D6L /* Rounds 60-79 */
  133. /* 32-bit rotate - kludged with shifts */
  134. typedef UInt32 UL; /* to save space */
  135. #define S(n,X) ( ( ((UL)X) << n ) | ( ((UL)X) >> ( 32 - n ) ) )
  136. /* The initial expanding function */
  137. #define expand(count) W[ count ] = S(1,(W[ count - 3 ] ^ W[ count - 8 ] ^ W[ count - 14 ] ^ W[ count - 16 ])) /* to make this SHA-1 */
  138. /* The four SHA sub-rounds */
  139. #define subRound1(count) \
  140. { \
  141. temp = S( 5, A ) + f1( B, C, D ) + E + W[ count ] + K1; \
  142. E = D; \
  143. D = C; \
  144. C = S( 30, B ); \
  145. B = A; \
  146. A = temp; \
  147. }
  148. #define subRound2(count) \
  149. { \
  150. temp = S( 5, A ) + f2( B, C, D ) + E + W[ count ] + K2; \
  151. E = D; \
  152. D = C; \
  153. C = S( 30, B ); \
  154. B = A; \
  155. A = temp; \
  156. }
  157. #define subRound3(count) \
  158. { \
  159. temp = S( 5, A ) + f3( B, C, D ) + E + W[ count ] + K3; \
  160. E = D; \
  161. D = C; \
  162. C = S( 30, B ); \
  163. B = A; \
  164. A = temp; \
  165. }
  166. #define subRound4(count) \
  167. { \
  168. temp = S( 5, A ) + f4( B, C, D ) + E + W[ count ] + K4; \
  169. E = D; \
  170. D = C; \
  171. C = S( 30, B ); \
  172. B = A; \
  173. A = temp; \
  174. }
  175. void SHA1Engine::transform()
  176. {
  177. UInt32 W[80];
  178. UInt32 temp;
  179. UInt32 A, B, C, D, E;
  180. int i;
  181. /* Step A. Copy the data buffer into the local work buffer */
  182. for( i = 0; i < 16; i++ )
  183. W[ i ] = _context.data[ i ];
  184. /* Step B. Expand the 16 words into 64 temporary data words */
  185. expand( 16 ); expand( 17 ); expand( 18 ); expand( 19 ); expand( 20 );
  186. expand( 21 ); expand( 22 ); expand( 23 ); expand( 24 ); expand( 25 );
  187. expand( 26 ); expand( 27 ); expand( 28 ); expand( 29 ); expand( 30 );
  188. expand( 31 ); expand( 32 ); expand( 33 ); expand( 34 ); expand( 35 );
  189. expand( 36 ); expand( 37 ); expand( 38 ); expand( 39 ); expand( 40 );
  190. expand( 41 ); expand( 42 ); expand( 43 ); expand( 44 ); expand( 45 );
  191. expand( 46 ); expand( 47 ); expand( 48 ); expand( 49 ); expand( 50 );
  192. expand( 51 ); expand( 52 ); expand( 53 ); expand( 54 ); expand( 55 );
  193. expand( 56 ); expand( 57 ); expand( 58 ); expand( 59 ); expand( 60 );
  194. expand( 61 ); expand( 62 ); expand( 63 ); expand( 64 ); expand( 65 );
  195. expand( 66 ); expand( 67 ); expand( 68 ); expand( 69 ); expand( 70 );
  196. expand( 71 ); expand( 72 ); expand( 73 ); expand( 74 ); expand( 75 );
  197. expand( 76 ); expand( 77 ); expand( 78 ); expand( 79 );
  198. /* Step C. Set up first buffer */
  199. A = _context.digest[ 0 ];
  200. B = _context.digest[ 1 ];
  201. C = _context.digest[ 2 ];
  202. D = _context.digest[ 3 ];
  203. E = _context.digest[ 4 ];
  204. /* Step D. Serious mangling, divided into four sub-rounds */
  205. subRound1( 0 ); subRound1( 1 ); subRound1( 2 ); subRound1( 3 );
  206. subRound1( 4 ); subRound1( 5 ); subRound1( 6 ); subRound1( 7 );
  207. subRound1( 8 ); subRound1( 9 ); subRound1( 10 ); subRound1( 11 );
  208. subRound1( 12 ); subRound1( 13 ); subRound1( 14 ); subRound1( 15 );
  209. subRound1( 16 ); subRound1( 17 ); subRound1( 18 ); subRound1( 19 );
  210. subRound2( 20 ); subRound2( 21 ); subRound2( 22 ); subRound2( 23 );
  211. subRound2( 24 ); subRound2( 25 ); subRound2( 26 ); subRound2( 27 );
  212. subRound2( 28 ); subRound2( 29 ); subRound2( 30 ); subRound2( 31 );
  213. subRound2( 32 ); subRound2( 33 ); subRound2( 34 ); subRound2( 35 );
  214. subRound2( 36 ); subRound2( 37 ); subRound2( 38 ); subRound2( 39 );
  215. subRound3( 40 ); subRound3( 41 ); subRound3( 42 ); subRound3( 43 );
  216. subRound3( 44 ); subRound3( 45 ); subRound3( 46 ); subRound3( 47 );
  217. subRound3( 48 ); subRound3( 49 ); subRound3( 50 ); subRound3( 51 );
  218. subRound3( 52 ); subRound3( 53 ); subRound3( 54 ); subRound3( 55 );
  219. subRound3( 56 ); subRound3( 57 ); subRound3( 58 ); subRound3( 59 );
  220. subRound4( 60 ); subRound4( 61 ); subRound4( 62 ); subRound4( 63 );
  221. subRound4( 64 ); subRound4( 65 ); subRound4( 66 ); subRound4( 67 );
  222. subRound4( 68 ); subRound4( 69 ); subRound4( 70 ); subRound4( 71 );
  223. subRound4( 72 ); subRound4( 73 ); subRound4( 74 ); subRound4( 75 );
  224. subRound4( 76 ); subRound4( 77 ); subRound4( 78 ); subRound4( 79 );
  225. /* Step E. Build message digest */
  226. _context.digest[ 0 ] += A;
  227. _context.digest[ 1 ] += B;
  228. _context.digest[ 2 ] += C;
  229. _context.digest[ 3 ] += D;
  230. _context.digest[ 4 ] += E;
  231. }
  232. } // namespace Poco