diff --git a/src/core/lib/BitwiseOp.mjs b/src/core/lib/BitwiseOp.mjs
new file mode 100644
index 00000000..b7cf7c97
--- /dev/null
+++ b/src/core/lib/BitwiseOp.mjs
@@ -0,0 +1,117 @@
+/**
+ * Bitwise operation resources.
+ *
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ */
+
+/**
+ * Runs bitwise operations across the input data.
+ *
+ * @param {byteArray} input
+ * @param {byteArray} key
+ * @param {function} func - The bitwise calculation to carry out
+ * @param {boolean} nullPreserving
+ * @param {string} scheme
+ * @returns {byteArray}
+ */
+export function bitOp (input, key, func, nullPreserving, scheme) {
+ if (!key || !key.length) key = [0];
+ const result = [];
+ let x = null,
+ k = null,
+ o = null;
+
+ for (let i = 0; i < input.length; i++) {
+ k = key[i % key.length];
+ o = input[i];
+ x = nullPreserving && (o === 0 || o === k) ? o : func(o, k);
+ result.push(x);
+ if (scheme &&
+ scheme !== "Standard" &&
+ !(nullPreserving && (o === 0 || o === k))) {
+ switch (scheme) {
+ case "Input differential":
+ key[i % key.length] = x;
+ break;
+ case "Output differential":
+ key[i % key.length] = o;
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+/**
+ * XOR bitwise calculation.
+ *
+ * @param {number} operand
+ * @param {number} key
+ * @returns {number}
+ */
+export function xor(operand, key) {
+ return operand ^ key;
+}
+
+
+/**
+ * NOT bitwise calculation.
+ *
+ * @param {number} operand
+ * @returns {number}
+ */
+export function not(operand, _) {
+ return ~operand & 0xff;
+}
+
+
+/**
+ * AND bitwise calculation.
+ *
+ * @param {number} operand
+ * @param {number} key
+ * @returns {number}
+ */
+export function and(operand, key) {
+ return operand & key;
+}
+
+
+/**
+ * OR bitwise calculation.
+ *
+ * @param {number} operand
+ * @param {number} key
+ * @returns {number}
+ */
+export function or(operand, key) {
+ return operand | key;
+}
+
+
+/**
+ * ADD bitwise calculation.
+ *
+ * @param {number} operand
+ * @param {number} key
+ * @returns {number}
+ */
+export function add(operand, key) {
+ return (operand + key) % 256;
+}
+
+
+/**
+ * SUB bitwise calculation.
+ *
+ * @param {number} operand
+ * @param {number} key
+ * @returns {number}
+ */
+export function sub(operand, key) {
+ const result = operand - key;
+ return (result < 0) ? 256 + result : result;
+}
diff --git a/src/core/operations/ADD.mjs b/src/core/operations/ADD.mjs
new file mode 100644
index 00000000..7e6ad9d5
--- /dev/null
+++ b/src/core/operations/ADD.mjs
@@ -0,0 +1,76 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import Utils from "../Utils";
+import { bitOp, add } from "../lib/BitwiseOp";
+
+/**
+ * ADD operation
+ */
+class ADD extends Operation {
+
+ /**
+ * ADD constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "ADD";
+ this.module = "Default";
+ this.description = "ADD the input with the given key (e.g. fe023da5
), MOD 255";
+ this.inputType = "byteArray";
+ this.outputType = "byteArray";
+ this.args = [
+ {
+ "name": "Key",
+ "type": "toggleString",
+ "value": "",
+ "toggleValues": ["Hex", "Base64", "UTF8", "Latin1"]
+ }
+ ];
+ }
+
+ /**
+ * @param {byteArray} input
+ * @param {Object[]} args
+ * @returns {byteArray}
+ */
+ run(input, args) {
+ const key = Utils.convertToByteArray(args[0].string || "", args[0].option);
+
+ return bitOp(input, key, add);
+ }
+
+ /**
+ * Highlight ADD
+ *
+ * @param {Object[]} pos
+ * @param {number} pos[].start
+ * @param {number} pos[].end
+ * @param {Object[]} args
+ * @returns {Object[]} pos
+ */
+ highlight(pos, args) {
+ return pos;
+ }
+
+ /**
+ * Highlight ADD in reverse
+ *
+ * @param {Object[]} pos
+ * @param {number} pos[].start
+ * @param {number} pos[].end
+ * @param {Object[]} args
+ * @returns {Object[]} pos
+ */
+ highlightReverse(pos, args) {
+ return pos;
+ }
+
+}
+
+export default ADD;
diff --git a/src/core/operations/AND.mjs b/src/core/operations/AND.mjs
new file mode 100644
index 00000000..4a062725
--- /dev/null
+++ b/src/core/operations/AND.mjs
@@ -0,0 +1,76 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import Utils from "../Utils";
+import { bitOp, and } from "../lib/BitwiseOp";
+
+/**
+ * AND operation
+ */
+class AND extends Operation {
+
+ /**
+ * AND constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "AND";
+ this.module = "Default";
+ this.description = "AND the input with the given key.
e.g. fe023da5
";
+ this.inputType = "byteArray";
+ this.outputType = "byteArray";
+ this.args = [
+ {
+ "name": "Key",
+ "type": "toggleString",
+ "value": "",
+ "toggleValues": ["Hex", "Base64", "UTF8", "Latin1"]
+ }
+ ];
+ }
+
+ /**
+ * @param {byteArray} input
+ * @param {Object[]} args
+ * @returns {byteArray}
+ */
+ run(input, args) {
+ const key = Utils.convertToByteArray(args[0].string || "", args[0].option);
+
+ return bitOp(input, key, and);
+ }
+
+ /**
+ * Highlight AND
+ *
+ * @param {Object[]} pos
+ * @param {number} pos[].start
+ * @param {number} pos[].end
+ * @param {Object[]} args
+ * @returns {Object[]} pos
+ */
+ highlight(pos, args) {
+ return pos;
+ }
+
+ /**
+ * Highlight AND in reverse
+ *
+ * @param {Object[]} pos
+ * @param {number} pos[].start
+ * @param {number} pos[].end
+ * @param {Object[]} args
+ * @returns {Object[]} pos
+ */
+ highlightReverse(pos, args) {
+ return pos;
+ }
+
+}
+
+export default AND;
diff --git a/src/core/operations/NOT.mjs b/src/core/operations/NOT.mjs
new file mode 100644
index 00000000..e0352dd0
--- /dev/null
+++ b/src/core/operations/NOT.mjs
@@ -0,0 +1,66 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import { bitOp, not } from "../lib/BitwiseOp";
+
+/**
+ * NOT operation
+ */
+class NOT extends Operation {
+
+ /**
+ * NOT constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "NOT";
+ this.module = "Default";
+ this.description = "Returns the inverse of each byte.";
+ this.inputType = "byteArray";
+ this.outputType = "byteArray";
+ this.args = [];
+ }
+
+ /**
+ * @param {byteArray} input
+ * @param {Object[]} args
+ * @returns {byteArray}
+ */
+ run(input, args) {
+ return bitOp(input, null, not);
+ }
+
+ /**
+ * Highlight NOT
+ *
+ * @param {Object[]} pos
+ * @param {number} pos[].start
+ * @param {number} pos[].end
+ * @param {Object[]} args
+ * @returns {Object[]} pos
+ */
+ highlight(pos, args) {
+ return pos;
+ }
+
+ /**
+ * Highlight NOT in reverse
+ *
+ * @param {Object[]} pos
+ * @param {number} pos[].start
+ * @param {number} pos[].end
+ * @param {Object[]} args
+ * @returns {Object[]} pos
+ */
+ highlightReverse(pos, args) {
+ return pos;
+ }
+
+}
+
+export default NOT;
diff --git a/src/core/operations/OR.mjs b/src/core/operations/OR.mjs
new file mode 100644
index 00000000..33bb2f63
--- /dev/null
+++ b/src/core/operations/OR.mjs
@@ -0,0 +1,76 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import Utils from "../Utils";
+import { bitOp, or } from "../lib/BitwiseOp";
+
+/**
+ * OR operation
+ */
+class OR extends Operation {
+
+ /**
+ * OR constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "OR";
+ this.module = "Default";
+ this.description = "OR the input with the given key.
e.g. fe023da5
";
+ this.inputType = "byteArray";
+ this.outputType = "byteArray";
+ this.args = [
+ {
+ "name": "Key",
+ "type": "toggleString",
+ "value": "",
+ "toggleValues": ["Hex", "Base64", "UTF8", "Latin1"]
+ }
+ ];
+ }
+
+ /**
+ * @param {byteArray} input
+ * @param {Object[]} args
+ * @returns {byteArray}
+ */
+ run(input, args) {
+ const key = Utils.convertToByteArray(args[0].string || "", args[0].option);
+
+ return bitOp(input, key, or);
+ }
+
+ /**
+ * Highlight OR
+ *
+ * @param {Object[]} pos
+ * @param {number} pos[].start
+ * @param {number} pos[].end
+ * @param {Object[]} args
+ * @returns {Object[]} pos
+ */
+ highlight(pos, args) {
+ return pos;
+ }
+
+ /**
+ * Highlight OR in reverse
+ *
+ * @param {Object[]} pos
+ * @param {number} pos[].start
+ * @param {number} pos[].end
+ * @param {Object[]} args
+ * @returns {Object[]} pos
+ */
+ highlightReverse(pos, args) {
+ return pos;
+ }
+
+}
+
+export default OR;
diff --git a/src/core/operations/SUB.mjs b/src/core/operations/SUB.mjs
new file mode 100644
index 00000000..79ce95d0
--- /dev/null
+++ b/src/core/operations/SUB.mjs
@@ -0,0 +1,76 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import Utils from "../Utils";
+import { bitOp, sub } from "../lib/BitwiseOp";
+
+/**
+ * SUB operation
+ */
+class SUB extends Operation {
+
+ /**
+ * SUB constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "SUB";
+ this.module = "Default";
+ this.description = "SUB the input with the given key (e.g. fe023da5
), MOD 255";
+ this.inputType = "byteArray";
+ this.outputType = "byteArray";
+ this.args = [
+ {
+ "name": "Key",
+ "type": "toggleString",
+ "value": "",
+ "toggleValues": ["Hex", "Base64", "UTF8", "Latin1"]
+ }
+ ];
+ }
+
+ /**
+ * @param {byteArray} input
+ * @param {Object[]} args
+ * @returns {byteArray}
+ */
+ run(input, args) {
+ const key = Utils.convertToByteArray(args[0].string || "", args[0].option);
+
+ return bitOp(input, key, sub);
+ }
+
+ /**
+ * Highlight SUB
+ *
+ * @param {Object[]} pos
+ * @param {number} pos[].start
+ * @param {number} pos[].end
+ * @param {Object[]} args
+ * @returns {Object[]} pos
+ */
+ highlight(pos, args) {
+ return pos;
+ }
+
+ /**
+ * Highlight SUB in reverse
+ *
+ * @param {Object[]} pos
+ * @param {number} pos[].start
+ * @param {number} pos[].end
+ * @param {Object[]} args
+ * @returns {Object[]} pos
+ */
+ highlightReverse(pos, args) {
+ return pos;
+ }
+
+}
+
+export default SUB;
diff --git a/src/core/operations/XOR.mjs b/src/core/operations/XOR.mjs
new file mode 100644
index 00000000..ae35eab7
--- /dev/null
+++ b/src/core/operations/XOR.mjs
@@ -0,0 +1,87 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import Utils from "../Utils";
+import { bitOp, xor } from "../lib/BitwiseOp";
+
+/**
+ * XOR operation
+ */
+class XOR extends Operation {
+
+ /**
+ * XOR constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "XOR";
+ this.module = "Default";
+ this.description = "XOR the input with the given key.
e.g. fe023da5
Options
Null preserving: If the current byte is 0x00 or the same as the key, skip it.
Scheme: