md4.lua 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. -- require("lockbox").insecure();
  2. local Bit = require("lockbox.util.bit");
  3. local String = require("string");
  4. local Math = require("math");
  5. local Queue = require("lockbox.util.queue");
  6. local AND = Bit.band;
  7. local OR = Bit.bor;
  8. local NOT = Bit.bnot;
  9. local XOR = Bit.bxor;
  10. local LROT = Bit.lrotate;
  11. local LSHIFT = Bit.lshift;
  12. local RSHIFT = Bit.rshift;
  13. --MD4 is little-endian
  14. local bytes2word = function(b0, b1, b2, b3)
  15. local i = b3; i = LSHIFT(i, 8);
  16. i = OR(i, b2); i = LSHIFT(i, 8);
  17. i = OR(i, b1); i = LSHIFT(i, 8);
  18. i = OR(i, b0);
  19. return i;
  20. end
  21. local word2bytes = function(word)
  22. local b0, b1, b2, b3;
  23. b0 = AND(word, 0xFF); word = RSHIFT(word, 8);
  24. b1 = AND(word, 0xFF); word = RSHIFT(word, 8);
  25. b2 = AND(word, 0xFF); word = RSHIFT(word, 8);
  26. b3 = AND(word, 0xFF);
  27. return b0, b1, b2, b3;
  28. end
  29. local dword2bytes = function(i)
  30. local b4, b5, b6, b7 = word2bytes(Math.floor(i / 0x100000000));
  31. local b0, b1, b2, b3 = word2bytes(i);
  32. return b0, b1, b2, b3, b4, b5, b6, b7;
  33. end
  34. local F = function(x, y, z) return OR(AND(x, y), AND(NOT(x), z)); end
  35. local G = function(x, y, z) return OR(AND(x, y), OR(AND(x, z), AND(y, z))); end
  36. local H = function(x, y, z) return XOR(x, XOR(y, z)); end
  37. local MD4 = function()
  38. local queue = Queue();
  39. local A = 0x67452301;
  40. local B = 0xefcdab89;
  41. local C = 0x98badcfe;
  42. local D = 0x10325476;
  43. local public = {};
  44. local processBlock = function()
  45. local a = A;
  46. local b = B;
  47. local c = C;
  48. local d = D;
  49. local X = {};
  50. for i = 0, 15 do
  51. X[i] = bytes2word(queue.pop(), queue.pop(), queue.pop(), queue.pop());
  52. end
  53. a = LROT(a + F(b, c, d) + X[ 0], 3);
  54. d = LROT(d + F(a, b, c) + X[ 1], 7);
  55. c = LROT(c + F(d, a, b) + X[ 2], 11);
  56. b = LROT(b + F(c, d, a) + X[ 3], 19);
  57. a = LROT(a + F(b, c, d) + X[ 4], 3);
  58. d = LROT(d + F(a, b, c) + X[ 5], 7);
  59. c = LROT(c + F(d, a, b) + X[ 6], 11);
  60. b = LROT(b + F(c, d, a) + X[ 7], 19);
  61. a = LROT(a + F(b, c, d) + X[ 8], 3);
  62. d = LROT(d + F(a, b, c) + X[ 9], 7);
  63. c = LROT(c + F(d, a, b) + X[10], 11);
  64. b = LROT(b + F(c, d, a) + X[11], 19);
  65. a = LROT(a + F(b, c, d) + X[12], 3);
  66. d = LROT(d + F(a, b, c) + X[13], 7);
  67. c = LROT(c + F(d, a, b) + X[14], 11);
  68. b = LROT(b + F(c, d, a) + X[15], 19);
  69. a = LROT(a + G(b, c, d) + X[ 0] + 0x5A827999, 3);
  70. d = LROT(d + G(a, b, c) + X[ 4] + 0x5A827999, 5);
  71. c = LROT(c + G(d, a, b) + X[ 8] + 0x5A827999, 9);
  72. b = LROT(b + G(c, d, a) + X[12] + 0x5A827999, 13);
  73. a = LROT(a + G(b, c, d) + X[ 1] + 0x5A827999, 3);
  74. d = LROT(d + G(a, b, c) + X[ 5] + 0x5A827999, 5);
  75. c = LROT(c + G(d, a, b) + X[ 9] + 0x5A827999, 9);
  76. b = LROT(b + G(c, d, a) + X[13] + 0x5A827999, 13);
  77. a = LROT(a + G(b, c, d) + X[ 2] + 0x5A827999, 3);
  78. d = LROT(d + G(a, b, c) + X[ 6] + 0x5A827999, 5);
  79. c = LROT(c + G(d, a, b) + X[10] + 0x5A827999, 9);
  80. b = LROT(b + G(c, d, a) + X[14] + 0x5A827999, 13);
  81. a = LROT(a + G(b, c, d) + X[ 3] + 0x5A827999, 3);
  82. d = LROT(d + G(a, b, c) + X[ 7] + 0x5A827999, 5);
  83. c = LROT(c + G(d, a, b) + X[11] + 0x5A827999, 9);
  84. b = LROT(b + G(c, d, a) + X[15] + 0x5A827999, 13);
  85. a = LROT(a + H(b, c, d) + X[ 0] + 0x6ED9EBA1, 3);
  86. d = LROT(d + H(a, b, c) + X[ 8] + 0x6ED9EBA1, 9);
  87. c = LROT(c + H(d, a, b) + X[ 4] + 0x6ED9EBA1, 11);
  88. b = LROT(b + H(c, d, a) + X[12] + 0x6ED9EBA1, 15);
  89. a = LROT(a + H(b, c, d) + X[ 2] + 0x6ED9EBA1, 3);
  90. d = LROT(d + H(a, b, c) + X[10] + 0x6ED9EBA1, 9);
  91. c = LROT(c + H(d, a, b) + X[ 6] + 0x6ED9EBA1, 11);
  92. b = LROT(b + H(c, d, a) + X[14] + 0x6ED9EBA1, 15);
  93. a = LROT(a + H(b, c, d) + X[ 1] + 0x6ED9EBA1, 3);
  94. d = LROT(d + H(a, b, c) + X[ 9] + 0x6ED9EBA1, 9);
  95. c = LROT(c + H(d, a, b) + X[ 5] + 0x6ED9EBA1, 11);
  96. b = LROT(b + H(c, d, a) + X[13] + 0x6ED9EBA1, 15);
  97. a = LROT(a + H(b, c, d) + X[ 3] + 0x6ED9EBA1, 3);
  98. d = LROT(d + H(a, b, c) + X[11] + 0x6ED9EBA1, 9);
  99. c = LROT(c + H(d, a, b) + X[ 7] + 0x6ED9EBA1, 11);
  100. b = LROT(b + H(c, d, a) + X[15] + 0x6ED9EBA1, 15);
  101. A = AND(A + a, 0xFFFFFFFF);
  102. B = AND(B + b, 0xFFFFFFFF);
  103. C = AND(C + c, 0xFFFFFFFF);
  104. D = AND(D + d, 0xFFFFFFFF);
  105. end
  106. public.init = function()
  107. queue.reset();
  108. A = 0x67452301;
  109. B = 0xefcdab89;
  110. C = 0x98badcfe;
  111. D = 0x10325476;
  112. return public;
  113. end
  114. public.update = function(bytes)
  115. for b in bytes do
  116. queue.push(b);
  117. if(queue.size() >= 64) then processBlock(); end
  118. end
  119. return public;
  120. end
  121. public.finish = function()
  122. local bits = queue.getHead() * 8;
  123. queue.push(0x80);
  124. while ((queue.size() + 7) % 64) < 63 do
  125. queue.push(0x00);
  126. end
  127. local b0, b1, b2, b3, b4, b5, b6, b7 = dword2bytes(bits);
  128. queue.push(b0);
  129. queue.push(b1);
  130. queue.push(b2);
  131. queue.push(b3);
  132. queue.push(b4);
  133. queue.push(b5);
  134. queue.push(b6);
  135. queue.push(b7);
  136. while queue.size() > 0 do
  137. processBlock();
  138. end
  139. return public;
  140. end
  141. public.asBytes = function()
  142. local b0, b1, b2, b3 = word2bytes(A);
  143. local b4, b5, b6, b7 = word2bytes(B);
  144. local b8, b9, b10, b11 = word2bytes(C);
  145. local b12, b13, b14, b15 = word2bytes(D);
  146. return {b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15};
  147. end
  148. public.asHex = function()
  149. local b0, b1, b2, b3 = word2bytes(A);
  150. local b4, b5, b6, b7 = word2bytes(B);
  151. local b8, b9, b10, b11 = word2bytes(C);
  152. local b12, b13, b14, b15 = word2bytes(D);
  153. return String.format("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
  154. b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15);
  155. end
  156. public.asString = function()
  157. local b0, b1, b2, b3 = word2bytes(A);
  158. local b4, b5, b6, b7 = word2bytes(B);
  159. local b8, b9, b10, b11 = word2bytes(C);
  160. local b12, b13, b14, b15 = word2bytes(D);
  161. return string.pack(string.rep('B', 16),
  162. b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15);
  163. end
  164. return public;
  165. end
  166. return MD4;