diff --git a/src/core/operations/XOR.mjs b/src/core/operations/XOR.mjs index aa228842..7f6f8e50 100644 --- a/src/core/operations/XOR.mjs +++ b/src/core/operations/XOR.mjs @@ -6,7 +6,7 @@ import Operation from "../Operation.mjs"; import Utils from "../Utils.mjs"; -import { bitOp, xor, BITWISE_OP_DELIMS } from "../lib/BitwiseOp.mjs"; +import { bitOp, xor, add, BITWISE_OP_DELIMS } from "../lib/BitwiseOp.mjs"; /** * XOR operation @@ -21,7 +21,7 @@ class XOR extends Operation { 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.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"; @@ -35,7 +35,7 @@ class XOR extends Operation { { "name": "Scheme", "type": "option", - "value": ["Standard", "Input differential", "Output differential", "Cascade"] + "value": ["Standard", "Input differential", "Output differential", "Cascade", "Rolling", "Rolling cumulative", "Rolling cumulative (self)"] }, { "name": "Null preserving", @@ -55,6 +55,31 @@ class XOR extends Operation { 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) { + case "Rolling": // key = key + index + return result.concat(bitOp(current, key.map(x => add(x, index)), xor, nullPreserving, scheme)); + case "Rolling cumulative": // key = key + index + previous + return result.concat(bitOp(current, key.map(x => add(x, runningIndex)), xor, nullPreserving, scheme)); + case "Rolling cumulative (self)": // key = key XOR previous chunk + // 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("")); + } + return bitOp(input, key, xor, nullPreserving, scheme); }