mirror of
https://github.com/gchq/CyberChef.git
synced 2024-11-02 14:11:02 +01:00
Ported Bitwise operations
also enabled bitshift tests
This commit is contained in:
parent
9ffab374db
commit
95f81ad740
117
src/core/lib/BitwiseOp.mjs
Normal file
117
src/core/lib/BitwiseOp.mjs
Normal file
@ -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;
|
||||
}
|
76
src/core/operations/ADD.mjs
Normal file
76
src/core/operations/ADD.mjs
Normal file
@ -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. <code>fe023da5</code>), 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;
|
76
src/core/operations/AND.mjs
Normal file
76
src/core/operations/AND.mjs
Normal file
@ -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.<br>e.g. <code>fe023da5</code>";
|
||||
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;
|
66
src/core/operations/NOT.mjs
Normal file
66
src/core/operations/NOT.mjs
Normal file
@ -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;
|
76
src/core/operations/OR.mjs
Normal file
76
src/core/operations/OR.mjs
Normal file
@ -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.<br>e.g. <code>fe023da5</code>";
|
||||
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;
|
76
src/core/operations/SUB.mjs
Normal file
76
src/core/operations/SUB.mjs
Normal file
@ -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. <code>fe023da5</code>), 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;
|
87
src/core/operations/XOR.mjs
Normal file
87
src/core/operations/XOR.mjs
Normal file
@ -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.<br>e.g. <code>fe023da5</code><br><br><strong>Options</strong><br><u>Null preserving:</u> If the current byte is 0x00 or the same as the key, skip it.<br><br><u>Scheme:</u><ul><li>Standard - key is unchanged after each round</li><li>Input differential - key is set to the value of the previous unprocessed byte</li><li>Output differential - key is set to the value of the previous processed byte</li></ul>";
|
||||
this.inputType = "byteArray";
|
||||
this.outputType = "byteArray";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Key",
|
||||
"type": "toggleString",
|
||||
"value": "",
|
||||
"toggleValues": ["Hex", "Base64", "UTF8", "Latin1"]
|
||||
},
|
||||
{
|
||||
"name": "Scheme",
|
||||
"type": "option",
|
||||
"value": ["Standard", "Input differential", "Output differential"]
|
||||
},
|
||||
{
|
||||
"name": "Null preserving",
|
||||
"type": "boolean",
|
||||
"value": false
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
const key = Utils.convertToByteArray(args[0].string || "", args[0].option),
|
||||
[, scheme, nullPreserving] = args;
|
||||
|
||||
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;
|
132
src/core/operations/XORBruteForce.mjs
Normal file
132
src/core/operations/XORBruteForce.mjs
Normal file
@ -0,0 +1,132 @@
|
||||
/**
|
||||
* @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";
|
||||
import { toHex } from "../lib/Hex";
|
||||
|
||||
/**
|
||||
* XOR Brute Force operation
|
||||
*/
|
||||
class XORBruteForce extends Operation {
|
||||
|
||||
/**
|
||||
* XORBruteForce constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "XOR Brute Force";
|
||||
this.module = "Default";
|
||||
this.description = "Enumerate all possible XOR solutions. Current maximum key length is 2 due to browser performance.<br><br>Optionally enter a string that you expect to find in the plaintext to filter results (crib).";
|
||||
this.inputType = "byteArray";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Key length",
|
||||
"type": "number",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"name": "Sample length",
|
||||
"type": "number",
|
||||
"value": 100
|
||||
},
|
||||
{
|
||||
"name": "Sample offset",
|
||||
"type": "number",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"name": "Scheme",
|
||||
"type": "option",
|
||||
"value": ["Standard", "Input differential", "Output differential"]
|
||||
},
|
||||
{
|
||||
"name": "Null preserving",
|
||||
"type": "boolean",
|
||||
"value": false
|
||||
},
|
||||
{
|
||||
"name": "Print key",
|
||||
"type": "boolean",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"name": "Output as hex",
|
||||
"type": "boolean",
|
||||
"value": false
|
||||
},
|
||||
{
|
||||
"name": "Crib (known plaintext string)",
|
||||
"type": "binaryString",
|
||||
"value": ""
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [keyLength, sampleLength, sampleOffset, scheme, nullPreserving, printKey, outputHex, /* ignore element */] = args, //eslint-disable-line array-bracket-spacing
|
||||
crib = args[7].toLowerCase();
|
||||
|
||||
const output = [];
|
||||
let result,
|
||||
resultUtf8,
|
||||
record = "";
|
||||
|
||||
input = input.slice(sampleOffset, sampleOffset + sampleLength);
|
||||
|
||||
if (ENVIRONMENT_IS_WORKER())
|
||||
self.sendStatusMessage("Calculating " + Math.pow(256, keyLength) + " values...");
|
||||
|
||||
/**
|
||||
* Converts an integer to an array of bytes expressing that number.
|
||||
*
|
||||
* @param {number} int
|
||||
* @param {number} len - Length of the resulting array
|
||||
* @returns {array}
|
||||
*/
|
||||
const intToByteArray = (int, len) => {
|
||||
const res = Array(len).fill(0);
|
||||
for (let i = len - 1; i >= 0; i--) {
|
||||
res[i] = int & 0xff;
|
||||
int = int >>> 8;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
for (let key = 1, l = Math.pow(256, keyLength); key < l; key++) {
|
||||
if (key % 10000 === 0 && ENVIRONMENT_IS_WORKER()) {
|
||||
self.sendStatusMessage("Calculating " + l + " values... " + Math.floor(key / l * 100) + "%");
|
||||
}
|
||||
|
||||
result = bitOp(input, intToByteArray(key, keyLength), xor, nullPreserving, scheme);
|
||||
resultUtf8 = Utils.byteArrayToUtf8(result);
|
||||
record = "";
|
||||
|
||||
if (crib && resultUtf8.toLowerCase().indexOf(crib) < 0) continue;
|
||||
if (printKey) record += "Key = " + Utils.hex(key, (2*keyLength)) + ": ";
|
||||
if (outputHex) {
|
||||
record += toHex(result);
|
||||
} else {
|
||||
record += Utils.printable(resultUtf8, false);
|
||||
}
|
||||
|
||||
output.push(record);
|
||||
}
|
||||
|
||||
return output.join("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default XORBruteForce;
|
@ -27,7 +27,7 @@ import TestRegister from "./TestRegister";
|
||||
import "./tests/operations/Base58";
|
||||
import "./tests/operations/Base64";
|
||||
import "./tests/operations/BCD";
|
||||
// import "./tests/operations/BitwiseOp";
|
||||
import "./tests/operations/BitwiseOp";
|
||||
import "./tests/operations/BSON";
|
||||
import "./tests/operations/ByteRepr";
|
||||
import "./tests/operations/CartesianProduct";
|
||||
|
Loading…
Reference in New Issue
Block a user