BitwiseOp.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. import Utils from "../Utils.js";
  2. /**
  3. * Bitwise operations.
  4. *
  5. * @author n1474335 [n1474335@gmail.com]
  6. * @copyright Crown Copyright 2016
  7. * @license Apache-2.0
  8. *
  9. * @namespace
  10. */
  11. const BitwiseOp = {
  12. /**
  13. * Runs bitwise operations across the input data.
  14. *
  15. * @private
  16. * @param {byteArray} input
  17. * @param {byteArray} key
  18. * @param {function} func - The bitwise calculation to carry out
  19. * @param {boolean} nullPreserving
  20. * @param {string} scheme
  21. * @returns {byteArray}
  22. */
  23. _bitOp: function (input, key, func, nullPreserving, scheme) {
  24. if (!key || !key.length) key = [0];
  25. let result = [],
  26. x = null,
  27. k = null,
  28. o = null;
  29. for (let i = 0; i < input.length; i++) {
  30. k = key[i % key.length];
  31. o = input[i];
  32. x = nullPreserving && (o === 0 || o === k) ? o : func(o, k);
  33. result.push(x);
  34. if (scheme &&
  35. scheme !== "Standard" &&
  36. !(nullPreserving && (o === 0 || o === k))) {
  37. switch (scheme) {
  38. case "Input differential":
  39. key[i % key.length] = x;
  40. break;
  41. case "Output differential":
  42. key[i % key.length] = o;
  43. break;
  44. }
  45. }
  46. }
  47. return result;
  48. },
  49. /**
  50. * @constant
  51. * @default
  52. */
  53. XOR_PRESERVE_NULLS: false,
  54. /**
  55. * @constant
  56. * @default
  57. */
  58. XOR_SCHEME: ["Standard", "Input differential", "Output differential"],
  59. /**
  60. * @constant
  61. * @default
  62. */
  63. KEY_FORMAT: ["Hex", "Base64", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1"],
  64. /**
  65. * XOR operation.
  66. *
  67. * @param {byteArray} input
  68. * @param {Object[]} args
  69. * @returns {byteArray}
  70. */
  71. runXor: function (input, args) {
  72. let key = Utils.format[args[0].option].parse(args[0].string || ""),
  73. scheme = args[1],
  74. nullPreserving = args[2];
  75. key = Utils.wordArrayToByteArray(key);
  76. return BitwiseOp._bitOp(input, key, BitwiseOp._xor, nullPreserving, scheme);
  77. },
  78. /**
  79. * @constant
  80. * @default
  81. */
  82. XOR_BRUTE_KEY_LENGTH: 1,
  83. /**
  84. * @constant
  85. * @default
  86. */
  87. XOR_BRUTE_SAMPLE_LENGTH: 100,
  88. /**
  89. * @constant
  90. * @default
  91. */
  92. XOR_BRUTE_SAMPLE_OFFSET: 0,
  93. /**
  94. * @constant
  95. * @default
  96. */
  97. XOR_BRUTE_PRINT_KEY: true,
  98. /**
  99. * @constant
  100. * @default
  101. */
  102. XOR_BRUTE_OUTPUT_HEX: false,
  103. /**
  104. * XOR Brute Force operation.
  105. *
  106. * @param {byteArray} input
  107. * @param {Object[]} args
  108. * @returns {string}
  109. */
  110. runXorBrute: function (input, args) {
  111. const keyLength = args[0],
  112. sampleLength = args[1],
  113. sampleOffset = args[2],
  114. scheme = args[3],
  115. nullPreserving = args[4],
  116. printKey = args[5],
  117. outputHex = args[6],
  118. crib = args[7].toLowerCase();
  119. let output = [],
  120. result,
  121. resultUtf8,
  122. record = "";
  123. input = input.slice(sampleOffset, sampleOffset + sampleLength);
  124. if (ENVIRONMENT_IS_WORKER())
  125. self.sendStatusMessage("Calculating " + Math.pow(256, keyLength) + " values...");
  126. /**
  127. * Converts an integer to an array of bytes expressing that number.
  128. *
  129. * @param {number} int
  130. * @param {number} len - Length of the resulting array
  131. * @returns {array}
  132. */
  133. const intToByteArray = (int, len) => {
  134. let res = Array(len).fill(0);
  135. for (let i = len - 1; i >= 0; i--) {
  136. res[i] = int & 0xff;
  137. int = int >>> 8;
  138. }
  139. return res;
  140. };
  141. for (let key = 1, l = Math.pow(256, keyLength); key < l; key++) {
  142. if (key % 10000 === 0 && ENVIRONMENT_IS_WORKER()) {
  143. self.sendStatusMessage("Calculating " + l + " values... " + Math.floor(key / l * 100) + "%");
  144. }
  145. result = BitwiseOp._bitOp(input, intToByteArray(key, keyLength), BitwiseOp._xor, nullPreserving, scheme);
  146. resultUtf8 = Utils.byteArrayToUtf8(result);
  147. record = "";
  148. if (crib && resultUtf8.toLowerCase().indexOf(crib) < 0) continue;
  149. if (printKey) record += "Key = " + Utils.hex(key, (2*keyLength)) + ": ";
  150. if (outputHex) {
  151. record += Utils.toHex(result);
  152. } else {
  153. record += Utils.printable(resultUtf8, false);
  154. }
  155. output.push(record);
  156. }
  157. return output.join("\n");
  158. },
  159. /**
  160. * NOT operation.
  161. *
  162. * @param {byteArray} input
  163. * @param {Object[]} args
  164. * @returns {byteArray}
  165. */
  166. runNot: function (input, args) {
  167. return BitwiseOp._bitOp(input, null, BitwiseOp._not);
  168. },
  169. /**
  170. * AND operation.
  171. *
  172. * @param {byteArray} input
  173. * @param {Object[]} args
  174. * @returns {byteArray}
  175. */
  176. runAnd: function (input, args) {
  177. let key = Utils.format[args[0].option].parse(args[0].string || "");
  178. key = Utils.wordArrayToByteArray(key);
  179. return BitwiseOp._bitOp(input, key, BitwiseOp._and);
  180. },
  181. /**
  182. * OR operation.
  183. *
  184. * @param {byteArray} input
  185. * @param {Object[]} args
  186. * @returns {byteArray}
  187. */
  188. runOr: function (input, args) {
  189. let key = Utils.format[args[0].option].parse(args[0].string || "");
  190. key = Utils.wordArrayToByteArray(key);
  191. return BitwiseOp._bitOp(input, key, BitwiseOp._or);
  192. },
  193. /**
  194. * ADD operation.
  195. *
  196. * @param {byteArray} input
  197. * @param {Object[]} args
  198. * @returns {byteArray}
  199. */
  200. runAdd: function (input, args) {
  201. let key = Utils.format[args[0].option].parse(args[0].string || "");
  202. key = Utils.wordArrayToByteArray(key);
  203. return BitwiseOp._bitOp(input, key, BitwiseOp._add);
  204. },
  205. /**
  206. * SUB operation.
  207. *
  208. * @param {byteArray} input
  209. * @param {Object[]} args
  210. * @returns {byteArray}
  211. */
  212. runSub: function (input, args) {
  213. let key = Utils.format[args[0].option].parse(args[0].string || "");
  214. key = Utils.wordArrayToByteArray(key);
  215. return BitwiseOp._bitOp(input, key, BitwiseOp._sub);
  216. },
  217. /**
  218. * Bit shift left operation.
  219. *
  220. * @param {byteArray} input
  221. * @param {Object[]} args
  222. * @returns {byteArray}
  223. */
  224. runBitShiftLeft: function(input, args) {
  225. const amount = args[0];
  226. return input.map(b => {
  227. return (b << amount) & 0xff;
  228. });
  229. },
  230. /**
  231. * @constant
  232. * @default
  233. */
  234. BIT_SHIFT_TYPE: ["Logical shift", "Arithmetic shift"],
  235. /**
  236. * Bit shift right operation.
  237. *
  238. * @param {byteArray} input
  239. * @param {Object[]} args
  240. * @returns {byteArray}
  241. */
  242. runBitShiftRight: function(input, args) {
  243. const amount = args[0],
  244. type = args[1],
  245. mask = type === "Logical shift" ? 0 : 0x80;
  246. return input.map(b => {
  247. return (b >>> amount) ^ (b & mask);
  248. });
  249. },
  250. /**
  251. * XOR bitwise calculation.
  252. *
  253. * @private
  254. * @param {number} operand
  255. * @param {number} key
  256. * @returns {number}
  257. */
  258. _xor: function (operand, key) {
  259. return operand ^ key;
  260. },
  261. /**
  262. * NOT bitwise calculation.
  263. *
  264. * @private
  265. * @param {number} operand
  266. * @returns {number}
  267. */
  268. _not: function (operand, _) {
  269. return ~operand & 0xff;
  270. },
  271. /**
  272. * AND bitwise calculation.
  273. *
  274. * @private
  275. * @param {number} operand
  276. * @param {number} key
  277. * @returns {number}
  278. */
  279. _and: function (operand, key) {
  280. return operand & key;
  281. },
  282. /**
  283. * OR bitwise calculation.
  284. *
  285. * @private
  286. * @param {number} operand
  287. * @param {number} key
  288. * @returns {number}
  289. */
  290. _or: function (operand, key) {
  291. return operand | key;
  292. },
  293. /**
  294. * ADD bitwise calculation.
  295. *
  296. * @private
  297. * @param {number} operand
  298. * @param {number} key
  299. * @returns {number}
  300. */
  301. _add: function (operand, key) {
  302. return (operand + key) % 256;
  303. },
  304. /**
  305. * SUB bitwise calculation.
  306. *
  307. * @private
  308. * @param {number} operand
  309. * @param {number} key
  310. * @returns {number}
  311. */
  312. _sub: function (operand, key) {
  313. const result = operand - key;
  314. return (result < 0) ? 256 + result : result;
  315. },
  316. };
  317. export default BitwiseOp;