sha2_256.lua 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. local Bit = require("lockbox.util.bit");
  2. local String = require("string");
  3. local Math = require("math");
  4. local Queue = require("lockbox.util.queue");
  5. local CONSTANTS = {
  6. 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  7. 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  8. 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  9. 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  10. 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  11. 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  12. 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  13. 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
  14. local fmt = "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" ..
  15. "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
  16. local AND = Bit.band;
  17. local OR = Bit.bor;
  18. local NOT = Bit.bnot;
  19. local XOR = Bit.bxor;
  20. local RROT = Bit.rrotate;
  21. local LSHIFT = Bit.lshift;
  22. local RSHIFT = Bit.rshift;
  23. --SHA2 is big-endian
  24. local bytes2word = function(b0, b1, b2, b3)
  25. local i = b0; i = LSHIFT(i, 8);
  26. i = OR(i, b1); i = LSHIFT(i, 8);
  27. i = OR(i, b2); i = LSHIFT(i, 8);
  28. i = OR(i, b3);
  29. return i;
  30. end
  31. local word2bytes = function(word)
  32. local b0, b1, b2, b3;
  33. b3 = AND(word, 0xFF); word = RSHIFT(word, 8);
  34. b2 = AND(word, 0xFF); word = RSHIFT(word, 8);
  35. b1 = AND(word, 0xFF); word = RSHIFT(word, 8);
  36. b0 = AND(word, 0xFF);
  37. return b0, b1, b2, b3;
  38. end
  39. local dword2bytes = function(i)
  40. local b4, b5, b6, b7 = word2bytes(i);
  41. local b0, b1, b2, b3 = word2bytes(Math.floor(i / 0x100000000));
  42. return b0, b1, b2, b3, b4, b5, b6, b7;
  43. end
  44. local SHA2_256 = function()
  45. local queue = Queue();
  46. local h0 = 0x6a09e667;
  47. local h1 = 0xbb67ae85;
  48. local h2 = 0x3c6ef372;
  49. local h3 = 0xa54ff53a;
  50. local h4 = 0x510e527f;
  51. local h5 = 0x9b05688c;
  52. local h6 = 0x1f83d9ab;
  53. local h7 = 0x5be0cd19;
  54. local public = {};
  55. local processBlock = function()
  56. local a = h0;
  57. local b = h1;
  58. local c = h2;
  59. local d = h3;
  60. local e = h4;
  61. local f = h5;
  62. local g = h6;
  63. local h = h7;
  64. local w = {};
  65. for i = 0, 15 do
  66. w[i] = bytes2word(queue.pop(), queue.pop(), queue.pop(), queue.pop());
  67. end
  68. for i = 16, 63 do
  69. local s0 = XOR(RROT(w[i - 15], 7), XOR(RROT(w[i - 15], 18), RSHIFT(w[i - 15], 3)));
  70. local s1 = XOR(RROT(w[i - 2], 17), XOR(RROT(w[i - 2], 19), RSHIFT(w[i - 2], 10)));
  71. w[i] = AND(w[i - 16] + s0 + w[i - 7] + s1, 0xFFFFFFFF);
  72. end
  73. for i = 0, 63 do
  74. local s1 = XOR(RROT(e, 6), XOR(RROT(e, 11), RROT(e, 25)));
  75. local ch = XOR(AND(e, f), AND(NOT(e), g));
  76. local temp1 = h + s1 + ch + CONSTANTS[i + 1] + w[i];
  77. local s0 = XOR(RROT(a, 2), XOR(RROT(a, 13), RROT(a, 22)));
  78. local maj = XOR(AND(a, b), XOR(AND(a, c), AND(b, c)));
  79. local temp2 = s0 + maj;
  80. h = g;
  81. g = f;
  82. f = e;
  83. e = d + temp1;
  84. d = c;
  85. c = b;
  86. b = a;
  87. a = temp1 + temp2;
  88. end
  89. h0 = AND(h0 + a, 0xFFFFFFFF);
  90. h1 = AND(h1 + b, 0xFFFFFFFF);
  91. h2 = AND(h2 + c, 0xFFFFFFFF);
  92. h3 = AND(h3 + d, 0xFFFFFFFF);
  93. h4 = AND(h4 + e, 0xFFFFFFFF);
  94. h5 = AND(h5 + f, 0xFFFFFFFF);
  95. h6 = AND(h6 + g, 0xFFFFFFFF);
  96. h7 = AND(h7 + h, 0xFFFFFFFF);
  97. end
  98. public.init = function()
  99. queue.reset();
  100. h0 = 0x6a09e667;
  101. h1 = 0xbb67ae85;
  102. h2 = 0x3c6ef372;
  103. h3 = 0xa54ff53a;
  104. h4 = 0x510e527f;
  105. h5 = 0x9b05688c;
  106. h6 = 0x1f83d9ab;
  107. h7 = 0x5be0cd19;
  108. return public;
  109. end
  110. public.update = function(bytes)
  111. for b in bytes do
  112. queue.push(b);
  113. if queue.size() >= 64 then processBlock(); end
  114. end
  115. return public;
  116. end
  117. public.finish = function()
  118. local bits = queue.getHead() * 8;
  119. queue.push(0x80);
  120. while ((queue.size() + 7) % 64) < 63 do
  121. queue.push(0x00);
  122. end
  123. local b0, b1, b2, b3, b4, b5, b6, b7 = dword2bytes(bits);
  124. queue.push(b0);
  125. queue.push(b1);
  126. queue.push(b2);
  127. queue.push(b3);
  128. queue.push(b4);
  129. queue.push(b5);
  130. queue.push(b6);
  131. queue.push(b7);
  132. while queue.size() > 0 do
  133. processBlock();
  134. end
  135. return public;
  136. end
  137. public.asBytes = function()
  138. local b0, b1, b2, b3 = word2bytes(h0);
  139. local b4, b5, b6, b7 = word2bytes(h1);
  140. local b8, b9, b10, b11 = word2bytes(h2);
  141. local b12, b13, b14, b15 = word2bytes(h3);
  142. local b16, b17, b18, b19 = word2bytes(h4);
  143. local b20, b21, b22, b23 = word2bytes(h5);
  144. local b24, b25, b26, b27 = word2bytes(h6);
  145. local b28, b29, b30, b31 = word2bytes(h7);
  146. return { b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15
  147. , b16, b17, b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31};
  148. end
  149. public.asHex = function()
  150. local b0, b1, b2, b3 = word2bytes(h0);
  151. local b4, b5, b6, b7 = word2bytes(h1);
  152. local b8, b9, b10, b11 = word2bytes(h2);
  153. local b12, b13, b14, b15 = word2bytes(h3);
  154. local b16, b17, b18, b19 = word2bytes(h4);
  155. local b20, b21, b22, b23 = word2bytes(h5);
  156. local b24, b25, b26, b27 = word2bytes(h6);
  157. local b28, b29, b30, b31 = word2bytes(h7);
  158. return String.format(fmt, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15
  159. , b16, b17, b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31);
  160. end
  161. public.asString = function()
  162. local b0, b1, b2, b3 = word2bytes(h0);
  163. local b4, b5, b6, b7 = word2bytes(h1);
  164. local b8, b9, b10, b11 = word2bytes(h2);
  165. local b12, b13, b14, b15 = word2bytes(h3);
  166. local b16, b17, b18, b19 = word2bytes(h4);
  167. local b20, b21, b22, b23 = word2bytes(h5);
  168. local b24, b25, b26, b27 = word2bytes(h6);
  169. local b28, b29, b30, b31 = word2bytes(h7);
  170. return string.pack(string.rep('B', 32),
  171. b0, b1, b2, b3, b4, b5, b6, b7, b8,
  172. b9, b10, b11, b12, b13, b14, b15,
  173. b16, b17, b18, b19, b20, b21, b22, b23, b24,
  174. b25, b26, b27, b28, b29, b30, b31);
  175. end
  176. return public;
  177. end
  178. return SHA2_256;