/tmp/beast/boost/beast/core/detail/sha1.hpp

https://gitlab.com/amyasnikov/xgame · C++ Header · 313 lines · 266 code · 28 blank · 19 comment · 8 complexity · fd2b50d73e0038a3ee09e9c11840c2a7 MD5 · raw file

  1. //
  2. // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/beast
  8. //
  9. #ifndef BOOST_BEAST_DETAIL_SHA1_HPP
  10. #define BOOST_BEAST_DETAIL_SHA1_HPP
  11. #include <algorithm>
  12. #include <cstdint>
  13. #include <cstring>
  14. // Based on https://github.com/vog/sha1
  15. /*
  16. Original authors:
  17. Steve Reid (Original C Code)
  18. Bruce Guenter (Small changes to fit into bglibs)
  19. Volker Grabsch (Translation to simpler C++ Code)
  20. Eugene Hopkinson (Safety improvements)
  21. Vincent Falco (beast adaptation)
  22. */
  23. namespace boost {
  24. namespace beast {
  25. namespace detail {
  26. namespace sha1 {
  27. static std::size_t constexpr BLOCK_INTS = 16;
  28. static std::size_t constexpr BLOCK_BYTES = 64;
  29. static std::size_t constexpr DIGEST_BYTES = 20;
  30. inline
  31. std::uint32_t
  32. rol(std::uint32_t value, std::size_t bits)
  33. {
  34. return (value << bits) | (value >> (32 - bits));
  35. }
  36. inline
  37. std::uint32_t
  38. blk(std::uint32_t block[BLOCK_INTS], std::size_t i)
  39. {
  40. return rol(
  41. block[(i+13)&15] ^ block[(i+8)&15] ^
  42. block[(i+2)&15] ^ block[i], 1);
  43. }
  44. inline
  45. void
  46. R0(std::uint32_t block[BLOCK_INTS], std::uint32_t v,
  47. std::uint32_t &w, std::uint32_t x, std::uint32_t y,
  48. std::uint32_t &z, std::size_t i)
  49. {
  50. z += ((w&(x^y))^y) + block[i] + 0x5a827999 + rol(v, 5);
  51. w = rol(w, 30);
  52. }
  53. inline
  54. void
  55. R1(std::uint32_t block[BLOCK_INTS], std::uint32_t v,
  56. std::uint32_t &w, std::uint32_t x, std::uint32_t y,
  57. std::uint32_t &z, std::size_t i)
  58. {
  59. block[i] = blk(block, i);
  60. z += ((w&(x^y))^y) + block[i] + 0x5a827999 + rol(v, 5);
  61. w = rol(w, 30);
  62. }
  63. inline
  64. void
  65. R2(std::uint32_t block[BLOCK_INTS], std::uint32_t v,
  66. std::uint32_t &w, std::uint32_t x, std::uint32_t y,
  67. std::uint32_t &z, std::size_t i)
  68. {
  69. block[i] = blk(block, i);
  70. z += (w^x^y) + block[i] + 0x6ed9eba1 + rol(v, 5);
  71. w = rol(w, 30);
  72. }
  73. inline
  74. void
  75. R3(std::uint32_t block[BLOCK_INTS], std::uint32_t v,
  76. std::uint32_t &w, std::uint32_t x, std::uint32_t y,
  77. std::uint32_t &z, std::size_t i)
  78. {
  79. block[i] = blk(block, i);
  80. z += (((w|x)&y)|(w&x)) + block[i] + 0x8f1bbcdc + rol(v, 5);
  81. w = rol(w, 30);
  82. }
  83. inline
  84. void
  85. R4(std::uint32_t block[BLOCK_INTS], std::uint32_t v,
  86. std::uint32_t &w, std::uint32_t x, std::uint32_t y,
  87. std::uint32_t &z, std::size_t i)
  88. {
  89. block[i] = blk(block, i);
  90. z += (w^x^y) + block[i] + 0xca62c1d6 + rol(v, 5);
  91. w = rol(w, 30);
  92. }
  93. inline
  94. void
  95. make_block(std::uint8_t const* p,
  96. std::uint32_t block[BLOCK_INTS])
  97. {
  98. for(std::size_t i = 0; i < BLOCK_INTS; i++)
  99. block[i] =
  100. (static_cast<std::uint32_t>(p[4*i+3])) |
  101. (static_cast<std::uint32_t>(p[4*i+2]))<< 8 |
  102. (static_cast<std::uint32_t>(p[4*i+1]))<<16 |
  103. (static_cast<std::uint32_t>(p[4*i+0]))<<24;
  104. }
  105. template<class = void>
  106. void
  107. transform(
  108. std::uint32_t digest[], std::uint32_t block[BLOCK_INTS])
  109. {
  110. std::uint32_t a = digest[0];
  111. std::uint32_t b = digest[1];
  112. std::uint32_t c = digest[2];
  113. std::uint32_t d = digest[3];
  114. std::uint32_t e = digest[4];
  115. R0(block, a, b, c, d, e, 0);
  116. R0(block, e, a, b, c, d, 1);
  117. R0(block, d, e, a, b, c, 2);
  118. R0(block, c, d, e, a, b, 3);
  119. R0(block, b, c, d, e, a, 4);
  120. R0(block, a, b, c, d, e, 5);
  121. R0(block, e, a, b, c, d, 6);
  122. R0(block, d, e, a, b, c, 7);
  123. R0(block, c, d, e, a, b, 8);
  124. R0(block, b, c, d, e, a, 9);
  125. R0(block, a, b, c, d, e, 10);
  126. R0(block, e, a, b, c, d, 11);
  127. R0(block, d, e, a, b, c, 12);
  128. R0(block, c, d, e, a, b, 13);
  129. R0(block, b, c, d, e, a, 14);
  130. R0(block, a, b, c, d, e, 15);
  131. R1(block, e, a, b, c, d, 0);
  132. R1(block, d, e, a, b, c, 1);
  133. R1(block, c, d, e, a, b, 2);
  134. R1(block, b, c, d, e, a, 3);
  135. R2(block, a, b, c, d, e, 4);
  136. R2(block, e, a, b, c, d, 5);
  137. R2(block, d, e, a, b, c, 6);
  138. R2(block, c, d, e, a, b, 7);
  139. R2(block, b, c, d, e, a, 8);
  140. R2(block, a, b, c, d, e, 9);
  141. R2(block, e, a, b, c, d, 10);
  142. R2(block, d, e, a, b, c, 11);
  143. R2(block, c, d, e, a, b, 12);
  144. R2(block, b, c, d, e, a, 13);
  145. R2(block, a, b, c, d, e, 14);
  146. R2(block, e, a, b, c, d, 15);
  147. R2(block, d, e, a, b, c, 0);
  148. R2(block, c, d, e, a, b, 1);
  149. R2(block, b, c, d, e, a, 2);
  150. R2(block, a, b, c, d, e, 3);
  151. R2(block, e, a, b, c, d, 4);
  152. R2(block, d, e, a, b, c, 5);
  153. R2(block, c, d, e, a, b, 6);
  154. R2(block, b, c, d, e, a, 7);
  155. R3(block, a, b, c, d, e, 8);
  156. R3(block, e, a, b, c, d, 9);
  157. R3(block, d, e, a, b, c, 10);
  158. R3(block, c, d, e, a, b, 11);
  159. R3(block, b, c, d, e, a, 12);
  160. R3(block, a, b, c, d, e, 13);
  161. R3(block, e, a, b, c, d, 14);
  162. R3(block, d, e, a, b, c, 15);
  163. R3(block, c, d, e, a, b, 0);
  164. R3(block, b, c, d, e, a, 1);
  165. R3(block, a, b, c, d, e, 2);
  166. R3(block, e, a, b, c, d, 3);
  167. R3(block, d, e, a, b, c, 4);
  168. R3(block, c, d, e, a, b, 5);
  169. R3(block, b, c, d, e, a, 6);
  170. R3(block, a, b, c, d, e, 7);
  171. R3(block, e, a, b, c, d, 8);
  172. R3(block, d, e, a, b, c, 9);
  173. R3(block, c, d, e, a, b, 10);
  174. R3(block, b, c, d, e, a, 11);
  175. R4(block, a, b, c, d, e, 12);
  176. R4(block, e, a, b, c, d, 13);
  177. R4(block, d, e, a, b, c, 14);
  178. R4(block, c, d, e, a, b, 15);
  179. R4(block, b, c, d, e, a, 0);
  180. R4(block, a, b, c, d, e, 1);
  181. R4(block, e, a, b, c, d, 2);
  182. R4(block, d, e, a, b, c, 3);
  183. R4(block, c, d, e, a, b, 4);
  184. R4(block, b, c, d, e, a, 5);
  185. R4(block, a, b, c, d, e, 6);
  186. R4(block, e, a, b, c, d, 7);
  187. R4(block, d, e, a, b, c, 8);
  188. R4(block, c, d, e, a, b, 9);
  189. R4(block, b, c, d, e, a, 10);
  190. R4(block, a, b, c, d, e, 11);
  191. R4(block, e, a, b, c, d, 12);
  192. R4(block, d, e, a, b, c, 13);
  193. R4(block, c, d, e, a, b, 14);
  194. R4(block, b, c, d, e, a, 15);
  195. digest[0] += a;
  196. digest[1] += b;
  197. digest[2] += c;
  198. digest[3] += d;
  199. digest[4] += e;
  200. }
  201. } // sha1
  202. struct sha1_context
  203. {
  204. static unsigned int constexpr block_size = sha1::BLOCK_BYTES;
  205. static unsigned int constexpr digest_size = 20;
  206. std::size_t buflen;
  207. std::size_t blocks;
  208. std::uint32_t digest[5];
  209. std::uint8_t buf[block_size];
  210. };
  211. template<class = void>
  212. void
  213. init(sha1_context& ctx) noexcept
  214. {
  215. ctx.buflen = 0;
  216. ctx.blocks = 0;
  217. ctx.digest[0] = 0x67452301;
  218. ctx.digest[1] = 0xefcdab89;
  219. ctx.digest[2] = 0x98badcfe;
  220. ctx.digest[3] = 0x10325476;
  221. ctx.digest[4] = 0xc3d2e1f0;
  222. }
  223. template<class = void>
  224. void
  225. update(sha1_context& ctx,
  226. void const* message, std::size_t size) noexcept
  227. {
  228. auto p = reinterpret_cast<
  229. std::uint8_t const*>(message);
  230. for(;;)
  231. {
  232. auto const n = (std::min)(
  233. size, sizeof(ctx.buf) - ctx.buflen);
  234. std::memcpy(ctx.buf + ctx.buflen, p, n);
  235. ctx.buflen += n;
  236. if(ctx.buflen != 64)
  237. return;
  238. p += n;
  239. size -= n;
  240. ctx.buflen = 0;
  241. std::uint32_t block[sha1::BLOCK_INTS];
  242. sha1::make_block(ctx.buf, block);
  243. sha1::transform(ctx.digest, block);
  244. ++ctx.blocks;
  245. }
  246. }
  247. template<class = void>
  248. void
  249. finish(sha1_context& ctx, void* digest) noexcept
  250. {
  251. using sha1::BLOCK_INTS;
  252. using sha1::BLOCK_BYTES;
  253. std::uint64_t total_bits =
  254. (ctx.blocks*64 + ctx.buflen) * 8;
  255. // pad
  256. ctx.buf[ctx.buflen++] = 0x80;
  257. auto const buflen = ctx.buflen;
  258. while(ctx.buflen < 64)
  259. ctx.buf[ctx.buflen++] = 0x00;
  260. std::uint32_t block[BLOCK_INTS];
  261. sha1::make_block(ctx.buf, block);
  262. if(buflen > BLOCK_BYTES - 8)
  263. {
  264. sha1::transform(ctx.digest, block);
  265. for(size_t i = 0; i < BLOCK_INTS - 2; i++)
  266. block[i] = 0;
  267. }
  268. /* Append total_bits, split this uint64_t into two uint32_t */
  269. block[BLOCK_INTS - 1] = total_bits & 0xffffffff;
  270. block[BLOCK_INTS - 2] = (total_bits >> 32);
  271. sha1::transform(ctx.digest, block);
  272. for(std::size_t i = 0; i < sha1::DIGEST_BYTES/4; i++)
  273. {
  274. std::uint8_t* d =
  275. reinterpret_cast<std::uint8_t*>(digest) + 4 * i;
  276. d[3] = ctx.digest[i] & 0xff;
  277. d[2] = (ctx.digest[i] >> 8) & 0xff;
  278. d[1] = (ctx.digest[i] >> 16) & 0xff;
  279. d[0] = (ctx.digest[i] >> 24) & 0xff;
  280. }
  281. }
  282. } // detail
  283. } // beast
  284. } // boost
  285. #endif