MD5.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. * Copyright (c) 2020, Ali Mohammad Pur <ali.mpfard@gmail.com>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <AK/Types.h>
  27. #include <LibCrypto/Hash/MD5.h>
  28. static constexpr u32 F(u32 x, u32 y, u32 z) { return (x & y) | ((~x) & z); };
  29. static constexpr u32 G(u32 x, u32 y, u32 z) { return (x & z) | ((~z) & y); };
  30. static constexpr u32 H(u32 x, u32 y, u32 z) { return x ^ y ^ z; };
  31. static constexpr u32 I(u32 x, u32 y, u32 z) { return y ^ (x | ~z); };
  32. static constexpr u32 ROTATE_LEFT(u32 x, size_t n)
  33. {
  34. return (x << n) | (x >> (32 - n));
  35. }
  36. static constexpr void round_1(u32& a, u32 b, u32 c, u32 d, u32 x, u32 s, u32 ac)
  37. {
  38. a += F(b, c, d) + x + ac;
  39. a = ROTATE_LEFT(a, s);
  40. a += b;
  41. }
  42. static constexpr void round_2(u32& a, u32 b, u32 c, u32 d, u32 x, u32 s, u32 ac)
  43. {
  44. a += G(b, c, d) + x + ac;
  45. a = ROTATE_LEFT(a, s);
  46. a += b;
  47. }
  48. static constexpr void round_3(u32& a, u32 b, u32 c, u32 d, u32 x, u32 s, u32 ac)
  49. {
  50. a += H(b, c, d) + x + ac;
  51. a = ROTATE_LEFT(a, s);
  52. a += b;
  53. }
  54. static constexpr void round_4(u32& a, u32 b, u32 c, u32 d, u32 x, u32 s, u32 ac)
  55. {
  56. a += I(b, c, d) + x + ac;
  57. a = ROTATE_LEFT(a, s);
  58. a += b;
  59. }
  60. namespace Crypto {
  61. namespace Hash {
  62. void MD5::update(const u8* input, size_t length)
  63. {
  64. auto index = (u32)(m_count[0] >> 3) & 0x3f;
  65. size_t offset { 0 };
  66. m_count[0] += (u32)length << 3;
  67. if (m_count[0] < ((u32)length << 3)) {
  68. ++m_count[1];
  69. }
  70. m_count[1] += (u32)length >> 29;
  71. auto part_length = 64 - index;
  72. if (length >= part_length) {
  73. m_buffer.overwrite(index, input, part_length);
  74. transform(m_buffer.data());
  75. for (offset = part_length; offset + 63 < length; offset += 64)
  76. transform(&input[offset]);
  77. index = 0;
  78. }
  79. ASSERT(length < part_length || length - offset <= 64);
  80. m_buffer.overwrite(index, &input[offset], length - offset);
  81. }
  82. MD5::DigestType MD5::digest()
  83. {
  84. auto digest = peek();
  85. reset();
  86. return digest;
  87. }
  88. MD5::DigestType MD5::peek()
  89. {
  90. DigestType digest;
  91. u8 bits[8];
  92. encode(m_count, bits, 8);
  93. // pad the data to 56%64
  94. u32 index = (u32)((m_count[0] >> 3) & 0x3f);
  95. u32 pad_length = index < 56 ? 56 - index : 120 - index;
  96. update(MD5Constants::PADDING, pad_length);
  97. // append length
  98. update(bits, 8);
  99. // store state (4 registers ABCD)
  100. encode(&m_A, digest.data, 4 * sizeof(m_A));
  101. return digest;
  102. }
  103. void MD5::encode(const u32* from, u8* to, size_t length)
  104. {
  105. for (size_t i = 0, j = 0; j < length; ++i, j += 4) {
  106. to[j] = (u8)(from[i] & 0xff);
  107. to[j + 1] = (u8)((from[i] >> 8) & 0xff);
  108. to[j + 2] = (u8)((from[i] >> 16) & 0xff);
  109. to[j + 3] = (u8)((from[i] >> 24) & 0xff);
  110. }
  111. }
  112. void MD5::decode(const u8* from, u32* to, size_t length)
  113. {
  114. for (size_t i = 0, j = 0; j < length; ++i, j += 4)
  115. to[i] = (((u32)from[j]) | (((u32)from[j + 1]) << 8) | (((u32)from[j + 2]) << 16) | (((u32)from[j + 3]) << 24));
  116. }
  117. void MD5::transform(const u8* block)
  118. {
  119. auto a = m_A;
  120. auto b = m_B;
  121. auto c = m_C;
  122. auto d = m_D;
  123. u32 x[16];
  124. decode(block, x, 64);
  125. round_1(a, b, c, d, x[0], MD5Constants::S11, 0xd76aa478); // 1
  126. round_1(d, a, b, c, x[1], MD5Constants::S12, 0xe8c7b756); // 2
  127. round_1(c, d, a, b, x[2], MD5Constants::S13, 0x242070db); // 3
  128. round_1(b, c, d, a, x[3], MD5Constants::S14, 0xc1bdceee); // 4
  129. round_1(a, b, c, d, x[4], MD5Constants::S11, 0xf57c0faf); // 5
  130. round_1(d, a, b, c, x[5], MD5Constants::S12, 0x4787c62a); // 6
  131. round_1(c, d, a, b, x[6], MD5Constants::S13, 0xa8304613); // 7
  132. round_1(b, c, d, a, x[7], MD5Constants::S14, 0xfd469501); // 8
  133. round_1(a, b, c, d, x[8], MD5Constants::S11, 0x698098d8); // 9
  134. round_1(d, a, b, c, x[9], MD5Constants::S12, 0x8b44f7af); // 10
  135. round_1(c, d, a, b, x[10], MD5Constants::S13, 0xffff5bb1); // 11
  136. round_1(b, c, d, a, x[11], MD5Constants::S14, 0x895cd7be); // 12
  137. round_1(a, b, c, d, x[12], MD5Constants::S11, 0x6b901122); // 13
  138. round_1(d, a, b, c, x[13], MD5Constants::S12, 0xfd987193); // 14
  139. round_1(c, d, a, b, x[14], MD5Constants::S13, 0xa679438e); // 15
  140. round_1(b, c, d, a, x[15], MD5Constants::S14, 0x49b40821); // 16
  141. round_2(a, b, c, d, x[1], MD5Constants::S21, 0xf61e2562); // 17
  142. round_2(d, a, b, c, x[6], MD5Constants::S22, 0xc040b340); // 18
  143. round_2(c, d, a, b, x[11], MD5Constants::S23, 0x265e5a51); // 19
  144. round_2(b, c, d, a, x[0], MD5Constants::S24, 0xe9b6c7aa); // 20
  145. round_2(a, b, c, d, x[5], MD5Constants::S21, 0xd62f105d); // 21
  146. round_2(d, a, b, c, x[10], MD5Constants::S22, 0x2441453); // 22
  147. round_2(c, d, a, b, x[15], MD5Constants::S23, 0xd8a1e681); // 23
  148. round_2(b, c, d, a, x[4], MD5Constants::S24, 0xe7d3fbc8); // 24
  149. round_2(a, b, c, d, x[9], MD5Constants::S21, 0x21e1cde6); // 25
  150. round_2(d, a, b, c, x[14], MD5Constants::S22, 0xc33707d6); // 26
  151. round_2(c, d, a, b, x[3], MD5Constants::S23, 0xf4d50d87); // 27
  152. round_2(b, c, d, a, x[8], MD5Constants::S24, 0x455a14ed); // 28
  153. round_2(a, b, c, d, x[13], MD5Constants::S21, 0xa9e3e905); // 29
  154. round_2(d, a, b, c, x[2], MD5Constants::S22, 0xfcefa3f8); // 30
  155. round_2(c, d, a, b, x[7], MD5Constants::S23, 0x676f02d9); // 31
  156. round_2(b, c, d, a, x[12], MD5Constants::S24, 0x8d2a4c8a); // 32
  157. round_3(a, b, c, d, x[5], MD5Constants::S31, 0xfffa3942); // 33
  158. round_3(d, a, b, c, x[8], MD5Constants::S32, 0x8771f681); // 34
  159. round_3(c, d, a, b, x[11], MD5Constants::S33, 0x6d9d6122); // 35
  160. round_3(b, c, d, a, x[14], MD5Constants::S34, 0xfde5380c); // 36
  161. round_3(a, b, c, d, x[1], MD5Constants::S31, 0xa4beea44); // 37
  162. round_3(d, a, b, c, x[4], MD5Constants::S32, 0x4bdecfa9); // 38
  163. round_3(c, d, a, b, x[7], MD5Constants::S33, 0xf6bb4b60); // 39
  164. round_3(b, c, d, a, x[10], MD5Constants::S34, 0xbebfbc70); // 40
  165. round_3(a, b, c, d, x[13], MD5Constants::S31, 0x289b7ec6); // 41
  166. round_3(d, a, b, c, x[0], MD5Constants::S32, 0xeaa127fa); // 42
  167. round_3(c, d, a, b, x[3], MD5Constants::S33, 0xd4ef3085); // 43
  168. round_3(b, c, d, a, x[6], MD5Constants::S34, 0x4881d05); // 44
  169. round_3(a, b, c, d, x[9], MD5Constants::S31, 0xd9d4d039); // 45
  170. round_3(d, a, b, c, x[12], MD5Constants::S32, 0xe6db99e5); // 46
  171. round_3(c, d, a, b, x[15], MD5Constants::S33, 0x1fa27cf8); // 47
  172. round_3(b, c, d, a, x[2], MD5Constants::S34, 0xc4ac5665); // 48
  173. round_4(a, b, c, d, x[0], MD5Constants::S41, 0xf4292244); // 49
  174. round_4(d, a, b, c, x[7], MD5Constants::S42, 0x432aff97); // 50
  175. round_4(c, d, a, b, x[14], MD5Constants::S43, 0xab9423a7); // 51
  176. round_4(b, c, d, a, x[5], MD5Constants::S44, 0xfc93a039); // 52
  177. round_4(a, b, c, d, x[12], MD5Constants::S41, 0x655b59c3); // 53
  178. round_4(d, a, b, c, x[3], MD5Constants::S42, 0x8f0ccc92); // 54
  179. round_4(c, d, a, b, x[10], MD5Constants::S43, 0xffeff47d); // 55
  180. round_4(b, c, d, a, x[1], MD5Constants::S44, 0x85845dd1); // 56
  181. round_4(a, b, c, d, x[8], MD5Constants::S41, 0x6fa87e4f); // 57
  182. round_4(d, a, b, c, x[15], MD5Constants::S42, 0xfe2ce6e0); // 58
  183. round_4(c, d, a, b, x[6], MD5Constants::S43, 0xa3014314); // 59
  184. round_4(b, c, d, a, x[13], MD5Constants::S44, 0x4e0811a1); // 60
  185. round_4(a, b, c, d, x[4], MD5Constants::S41, 0xf7537e82); // 61
  186. round_4(d, a, b, c, x[11], MD5Constants::S42, 0xbd3af235); // 62
  187. round_4(c, d, a, b, x[2], MD5Constants::S43, 0x2ad7d2bb); // 63
  188. round_4(b, c, d, a, x[9], MD5Constants::S44, 0xeb86d391); // 64
  189. m_A += a;
  190. m_B += b;
  191. m_C += c;
  192. m_D += d;
  193. __builtin_memset(x, 0, sizeof(x));
  194. }
  195. }
  196. }