/** * @author n1474335 [n1474335@gmail.com] * @copyright Crown Copyright 2016 * @license Apache-2.0 */ import Operation from "../Operation.mjs"; import Utils from "../Utils.mjs"; import { bitOp, xor, add, BITWISE_OP_DELIMS } from "../lib/BitwiseOp.mjs"; /** * 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:"; this.infoURL = "https://wikipedia.org/wiki/XOR"; this.inputType = "ArrayBuffer"; this.outputType = "byteArray"; this.args = [ { name: "Key", type: "toggleString", value: "", toggleValues: BITWISE_OP_DELIMS, }, { name: "Scheme", type: "option", value: [ "Standard", "Input differential", "Output differential", "Cascade", "Rolling", "Rolling cumulative", "Rolling cumulative (self)", ], }, { name: "Null preserving", type: "boolean", value: false, }, ]; } /** * @param {ArrayBuffer} input * @param {Object[]} args * @returns {byteArray} */ run(input, args) { input = new Uint8Array(input); const key = Utils.convertToByteArray( args[0].string || "", args[0].option ), [, scheme, nullPreserving] = args; if (scheme.startsWith("Rolling") && key.length) { const inputChunks = Utils.chunked(input, key.length); let runningIndex = 0; let runningKey = key; let xorred = null; return inputChunks.reduce((result, current, index) => { runningIndex += index; switch (scheme) { // key = key + index case "Rolling": return result.concat( bitOp( current, key.map((x) => add(x, index)), xor, nullPreserving, scheme ) ); // key = key + index + previous case "Rolling cumulative": return result.concat( bitOp( current, key.map((x) => add(x, runningIndex)), xor, nullPreserving, scheme ) ); // key = key XOR previous chunk case "Rolling cumulative (self)": // Xor this chunk xorred = bitOp( current, runningKey, xor, nullPreserving, scheme ); // Update the running key for next part of loop runningKey = bitOp( runningKey, current, xor, nullPreserving, scheme ); // Return the result with the newest xor'd chunk return result.concat(xorred); } }, Utils.strToByteArray("")); // Start our reduction with an empty byte array } return bitOp(input, key, xor, nullPreserving, scheme); } /** * Highlight XOR * * @param {Object[]} pos * @param {number} pos[].start * @param {number} pos[].end * @param {Object[]} args * @returns {Object[]} pos */ highlight(pos, args) { return pos; } /** * Highlight XOR 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 XOR;