ctr.lua 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. local Array = require("lockbox.util.array");
  2. local Stream = require("lockbox.util.stream");
  3. local Queue = require("lockbox.util.queue");
  4. local Bit = require("lockbox.util.bit");
  5. local AND = Bit.band;
  6. local CTR = {};
  7. CTR.Cipher = function()
  8. local public = {};
  9. local key;
  10. local blockCipher;
  11. local padding;
  12. local inputQueue;
  13. local outputQueue;
  14. local iv;
  15. public.setKey = function(keyBytes)
  16. key = keyBytes;
  17. return public;
  18. end
  19. public.setBlockCipher = function(cipher)
  20. blockCipher = cipher;
  21. return public;
  22. end
  23. public.setPadding = function(paddingMode)
  24. padding = paddingMode;
  25. return public;
  26. end
  27. public.init = function()
  28. inputQueue = Queue();
  29. outputQueue = Queue();
  30. iv = nil;
  31. return public;
  32. end
  33. local updateIV = function()
  34. iv[16] = iv[16] + 1;
  35. if iv[16] <= 0xFF then return; end
  36. iv[16] = AND(iv[16], 0xFF);
  37. iv[15] = iv[15] + 1;
  38. if iv[15] <= 0xFF then return; end
  39. iv[15] = AND(iv[15], 0xFF);
  40. iv[14] = iv[14] + 1;
  41. if iv[14] <= 0xFF then return; end
  42. iv[14] = AND(iv[14], 0xFF);
  43. iv[13] = iv[13] + 1;
  44. if iv[13] <= 0xFF then return; end
  45. iv[13] = AND(iv[13], 0xFF);
  46. iv[12] = iv[12] + 1;
  47. if iv[12] <= 0xFF then return; end
  48. iv[12] = AND(iv[12], 0xFF);
  49. iv[11] = iv[11] + 1;
  50. if iv[11] <= 0xFF then return; end
  51. iv[11] = AND(iv[11], 0xFF);
  52. iv[10] = iv[10] + 1;
  53. if iv[10] <= 0xFF then return; end
  54. iv[10] = AND(iv[10], 0xFF);
  55. iv[9] = iv[9] + 1;
  56. if iv[9] <= 0xFF then return; end
  57. iv[9] = AND(iv[9], 0xFF);
  58. return;
  59. end
  60. public.update = function(messageStream)
  61. local byte = messageStream();
  62. while (byte ~= nil) do
  63. inputQueue.push(byte);
  64. if(inputQueue.size() >= blockCipher.blockSize) then
  65. local block = Array.readFromQueue(inputQueue, blockCipher.blockSize);
  66. if(iv == nil) then
  67. iv = block;
  68. else
  69. local out = iv;
  70. out = blockCipher.encrypt(key, out);
  71. out = Array.XOR(out, block);
  72. Array.writeToQueue(outputQueue, out);
  73. updateIV();
  74. end
  75. end
  76. byte = messageStream();
  77. end
  78. return public;
  79. end
  80. public.finish = function()
  81. local paddingStream = padding(blockCipher.blockSize, inputQueue.getHead());
  82. public.update(paddingStream);
  83. return public;
  84. end
  85. public.getOutputQueue = function()
  86. return outputQueue;
  87. end
  88. public.asHex = function()
  89. return Stream.toHex(outputQueue.pop);
  90. end
  91. public.asBytes = function()
  92. return Stream.toArray(outputQueue.pop);
  93. end
  94. public.asString = function()
  95. return Stream.toString(outputQueue.pop);
  96. end
  97. return public;
  98. end
  99. CTR.Decipher = function()
  100. local public = {};
  101. local key;
  102. local blockCipher;
  103. local padding;
  104. local inputQueue;
  105. local outputQueue;
  106. local iv;
  107. public.setKey = function(keyBytes)
  108. key = keyBytes;
  109. return public;
  110. end
  111. public.setBlockCipher = function(cipher)
  112. blockCipher = cipher;
  113. return public;
  114. end
  115. public.setPadding = function(paddingMode)
  116. padding = paddingMode;
  117. return public;
  118. end
  119. public.init = function()
  120. inputQueue = Queue();
  121. outputQueue = Queue();
  122. iv = nil;
  123. return public;
  124. end
  125. local updateIV = function()
  126. iv[16] = iv[16] + 1;
  127. if iv[16] <= 0xFF then return; end
  128. iv[16] = AND(iv[16], 0xFF);
  129. iv[15] = iv[15] + 1;
  130. if iv[15] <= 0xFF then return; end
  131. iv[15] = AND(iv[15], 0xFF);
  132. iv[14] = iv[14] + 1;
  133. if iv[14] <= 0xFF then return; end
  134. iv[14] = AND(iv[14], 0xFF);
  135. iv[13] = iv[13] + 1;
  136. if iv[13] <= 0xFF then return; end
  137. iv[13] = AND(iv[13], 0xFF);
  138. iv[12] = iv[12] + 1;
  139. if iv[12] <= 0xFF then return; end
  140. iv[12] = AND(iv[12], 0xFF);
  141. iv[11] = iv[11] + 1;
  142. if iv[11] <= 0xFF then return; end
  143. iv[11] = AND(iv[11], 0xFF);
  144. iv[10] = iv[10] + 1;
  145. if iv[10] <= 0xFF then return; end
  146. iv[10] = AND(iv[10], 0xFF);
  147. iv[9] = iv[9] + 1;
  148. if iv[9] <= 0xFF then return; end
  149. iv[9] = AND(iv[9], 0xFF);
  150. return;
  151. end
  152. public.update = function(messageStream)
  153. local byte = messageStream();
  154. while (byte ~= nil) do
  155. inputQueue.push(byte);
  156. if(inputQueue.size() >= blockCipher.blockSize) then
  157. local block = Array.readFromQueue(inputQueue, blockCipher.blockSize);
  158. if(iv == nil) then
  159. iv = block;
  160. else
  161. local out = iv;
  162. out = blockCipher.encrypt(key, out);
  163. out = Array.XOR(out, block);
  164. Array.writeToQueue(outputQueue, out);
  165. updateIV();
  166. end
  167. end
  168. byte = messageStream();
  169. end
  170. return public;
  171. end
  172. public.finish = function()
  173. local paddingStream = padding(blockCipher.blockSize, inputQueue.getHead());
  174. public.update(paddingStream);
  175. return public;
  176. end
  177. public.getOutputQueue = function()
  178. return outputQueue;
  179. end
  180. public.asHex = function()
  181. return Stream.toHex(outputQueue.pop);
  182. end
  183. public.asBytes = function()
  184. return Stream.toArray(outputQueue.pop);
  185. end
  186. public.asString = function()
  187. return Stream.toString(outputQueue.pop);
  188. end
  189. return public;
  190. end
  191. return CTR;