Browse Source

Merge branch 'master' into feature-extract-files

n1474335 6 years ago
parent
commit
d02124550b

+ 20 - 1
CHANGELOG.md

@@ -1,6 +1,16 @@
 # Changelog
 All major and minor version changes will be documented in this file. Details of patch-level version changes can be found in [commit messages](https://github.com/gchq/CyberChef/commits/master).
 
+
+### [8.15.0] - 2018-12-18
+- 'Text Encoding Brute Force' operation added [@Cynser] | [#439]
+
+### [8.14.0] - 2018-12-18
+- 'To Base62' and 'From Base62' operations added [@tcode2k16] | [#443]
+
+### [8.13.0] - 2018-12-15
+- 'A1Z26 Cipher Encode' and 'A1Z26 Cipher Decode' operations added [@jarmovanlenthe] | [#441]
+
 ### [8.12.0] - 2018-11-21
 - 'Citrix CTX1 Encode' and 'Citrix CTX1 Decode' operations added [@bwhitn] | [#428]
 
@@ -20,7 +30,7 @@ All major and minor version changes will be documented in this file. Details of
 - 'JWT Sign', 'JWT Verify' and 'JWT Decode' operations added [@GCHQ77703] | [#348]
 
 ### [8.6.0] - 2018-08-29
-- 'To Geohash' and 'From Geohash' operations added [@GCHQ77703] | [#344] 
+- 'To Geohash' and 'From Geohash' operations added [@GCHQ77703] | [#344]
 
 ### [8.5.0] - 2018-08-23
 - 'To Braille' and 'From Braille' operations added [@n1474335] | [#255]
@@ -66,6 +76,9 @@ All major and minor version changes will be documented in this file. Details of
 
 
 
+[8.15.0]: https://github.com/gchq/CyberChef/releases/tag/v8.15.0
+[8.14.0]: https://github.com/gchq/CyberChef/releases/tag/v8.14.0
+[8.13.0]: https://github.com/gchq/CyberChef/releases/tag/v8.13.0
 [8.12.0]: https://github.com/gchq/CyberChef/releases/tag/v8.12.0
 [8.11.0]: https://github.com/gchq/CyberChef/releases/tag/v8.11.0
 [8.10.0]: https://github.com/gchq/CyberChef/releases/tag/v8.10.0
@@ -96,6 +109,9 @@ All major and minor version changes will be documented in this file. Details of
 [@arnydo]: https://github.com/arnydo
 [@klaxon1]: https://github.com/klaxon1
 [@bwhitn]: https://github.com/bwhitn
+[@jarmovanlenthe]: https://github.com/jarmovanlenthe
+[@tcode2k16]: https://github.com/tcode2k16
+[@Cynser]: https://github.com/Cynser
 
 [#95]: https://github.com/gchq/CyberChef/pull/299
 [#173]: https://github.com/gchq/CyberChef/pull/173
@@ -119,3 +135,6 @@ All major and minor version changes will be documented in this file. Details of
 [#387]: https://github.com/gchq/CyberChef/pull/387
 [#394]: https://github.com/gchq/CyberChef/pull/394
 [#428]: https://github.com/gchq/CyberChef/pull/428
+[#439]: https://github.com/gchq/CyberChef/pull/439
+[#441]: https://github.com/gchq/CyberChef/pull/441
+[#443]: https://github.com/gchq/CyberChef/pull/443

+ 1 - 1
babel.config.js

@@ -1,7 +1,7 @@
 module.exports = function(api) {
     api.cache.forever();
 
-    return  {
+    return {
         "presets": [
             ["@babel/preset-env", {
                 "targets": {

+ 1 - 1
package-lock.json

@@ -1,6 +1,6 @@
 {
   "name": "cyberchef",
-  "version": "8.12.3",
+  "version": "8.15.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "cyberchef",
-  "version": "8.12.3",
+  "version": "8.15.0",
   "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
   "author": "n1474335 <n1474335@gmail.com>",
   "homepage": "https://gchq.github.io/CyberChef",

+ 5 - 0
src/core/config/Categories.json

@@ -25,6 +25,8 @@
             "From Base32",
             "To Base58",
             "From Base58",
+            "To Base62",
+            "From Base62",
             "To Base85",
             "From Base85",
             "To Base",
@@ -49,6 +51,7 @@
             "Change IP format",
             "Encode text",
             "Decode text",
+            "Text Encoding Brute Force",
             "Swap endianness",
             "To MessagePack",
             "From MessagePack",
@@ -86,6 +89,8 @@
             "Bifid Cipher Decode",
             "Affine Cipher Encode",
             "Affine Cipher Decode",
+            "A1Z26 Cipher Encode",
+            "A1Z26 Cipher Decode",
             "Atbash Cipher",
             "Substitute",
             "Derive PBKDF2 key",

+ 63 - 0
src/core/operations/A1Z26CipherDecode.mjs

@@ -0,0 +1,63 @@
+/**
+ * @author Jarmo van Lenthe [github.com/jarmovanlenthe]
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import Utils from "../Utils";
+import {DELIM_OPTIONS} from "../lib/Delim";
+import OperationError from "../errors/OperationError";
+
+/**
+ * A1Z26 Cipher Decode operation
+ */
+class A1Z26CipherDecode extends Operation {
+
+    /**
+     * A1Z26CipherDecode constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "A1Z26 Cipher Decode";
+        this.module = "Ciphers";
+        this.description = "Converts alphabet order numbers into their corresponding  alphabet character.<br><br>e.g. <code>1</code> becomes <code>a</code> and <code>2</code> becomes <code>b</code>.";
+        this.infoURL = "";
+        this.inputType = "string";
+        this.outputType = "string";
+        this.args = [
+            {
+                name: "Delimiter",
+                type: "option",
+                value: DELIM_OPTIONS
+            }
+        ];
+    }
+
+    /**
+     * @param {string} input
+     * @param {Object[]} args
+     * @returns {string}
+     */
+    run(input, args) {
+        const delim = Utils.charRep(args[0] || "Space");
+
+        if (input.length === 0) {
+            return [];
+        }
+
+        const bites = input.split(delim);
+        let latin1 = "";
+        for (let i = 0; i < bites.length; i++) {
+            if (bites[i] < 1 || bites[i] > 26) {
+                throw new OperationError("Error: all numbers must be between 1 and 26.");
+            }
+            latin1 += Utils.chr(parseInt(bites[i], 10) + 96);
+        }
+        return latin1;
+    }
+
+}
+
+export default A1Z26CipherDecode;

+ 61 - 0
src/core/operations/A1Z26CipherEncode.mjs

@@ -0,0 +1,61 @@
+/**
+ * @author Jarmo van Lenthe [github.com/jarmovanlenthe]
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import Utils from "../Utils";
+import {DELIM_OPTIONS} from "../lib/Delim";
+
+/**
+ * A1Z26 Cipher Encode operation
+ */
+class A1Z26CipherEncode extends Operation {
+
+    /**
+     * A1Z26CipherEncode constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "A1Z26 Cipher Encode";
+        this.module = "Ciphers";
+        this.description = "Converts alphabet characters into their corresponding alphabet order number.<br><br>e.g. <code>a</code> becomes <code>1</code> and <code>b</code> becomes <code>2</code>.<br><br>Non-alphabet characters are dropped.";
+        this.infoURL = "";
+        this.inputType = "string";
+        this.outputType = "string";
+        this.args = [
+            {
+                name: "Delimiter",
+                type: "option",
+                value: DELIM_OPTIONS
+            }
+        ];
+    }
+
+    /**
+     * @param {string} input
+     * @param {Object[]} args
+     * @returns {string}
+     */
+    run(input, args) {
+        const delim = Utils.charRep(args[0] || "Space");
+        let output = "";
+
+        const sanitizedinput = input.toLowerCase(),
+            charcode = Utils.strToCharcode(sanitizedinput);
+
+        for (let i = 0; i < charcode.length; i++) {
+            const ordinal = charcode[i] - 96;
+
+            if (ordinal > 0 && ordinal <= 26) {
+                output += ordinal.toString(10) + delim;
+            }
+        }
+        return output.slice(0, -delim.length);
+    }
+
+}
+
+export default A1Z26CipherEncode;

+ 58 - 0
src/core/operations/FromBase62.mjs

@@ -0,0 +1,58 @@
+/**
+ * @author tcode2k16 [tcode2k16@gmail.com]
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import BigNumber from "bignumber.js";
+import Utils from "../Utils";
+
+
+/**
+ * From Base62 operation
+ */
+class FromBase62 extends Operation {
+
+    /**
+     * FromBase62 constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "From Base62";
+        this.module = "Default";
+        this.description = "Base62 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers. The high number base results in shorter strings than with the decimal or hexadecimal system.";
+        this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems";
+        this.inputType = "string";
+        this.outputType = "byteArray";
+        this.args = [
+            {
+                name: "Alphabet",
+                type: "string",
+                value: "0-9A-Za-z"
+            }
+        ];
+    }
+
+    /**
+     * @param {string} input
+     * @param {Object[]} args
+     * @returns {byteArray}
+     */
+    run(input, args) {
+        if (input.length < 1) return [];
+        const ALPHABET = Utils.expandAlphRange(args[0]).join("");
+        const BN = BigNumber.clone({ ALPHABET });
+
+        const re = new RegExp("[^" + ALPHABET.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
+        input = input.replace(re, "");
+
+        const number = new BN(input, 62);
+
+        return Utils.convertToByteArray(number.toString(16), "Hex");
+    }
+
+}
+
+export default FromBase62;

+ 1 - 1
src/core/operations/HMAC.mjs

@@ -72,7 +72,7 @@ class HMAC extends Operation {
             msg = Utils.arrayBufferToStr(input, false),
             hasher = CryptoApi.getHasher(hashFunc);
 
-        const mac = CryptoApi.getHmac(CryptoApi.encoder.fromUtf(key), hasher);
+        const mac = CryptoApi.getHmac(key, hasher);
         mac.update(msg);
         return CryptoApi.encoder.toHex(mac.finalize());
     }

+ 92 - 0
src/core/operations/TextEncodingBruteForce.mjs

@@ -0,0 +1,92 @@
+/**
+ * @author Cynser
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import Utils from "../Utils";
+import cptable from "../vendor/js-codepage/cptable.js";
+import {IO_FORMAT} from "../lib/ChrEnc";
+
+/**
+ * Text Encoding Brute Force operation
+ */
+class TextEncodingBruteForce extends Operation {
+
+    /**
+     * TextEncodingBruteForce constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "Text Encoding Brute Force";
+        this.module = "CharEnc";
+        this.description = [
+            "Enumerates all supported text encodings for the input, allowing you to quickly spot the correct one.",
+            "<br><br>",
+            "Supported charsets are:",
+            "<ul>",
+            Object.keys(IO_FORMAT).map(e => `<li>${e}</li>`).join("\n"),
+            "</ul>"
+        ].join("\n");
+        this.infoURL = "https://wikipedia.org/wiki/Character_encoding";
+        this.inputType = "string";
+        this.outputType = "json";
+        this.presentType = "html";
+        this.args = [
+            {
+                name: "Mode",
+                type: "option",
+                value: ["Encode", "Decode"]
+            }
+        ];
+    }
+
+    /**
+     * @param {string} input
+     * @param {Object[]} args
+     * @returns {json}
+     */
+    run(input, args) {
+        const output = {},
+            charsets = Object.keys(IO_FORMAT),
+            mode = args[0];
+
+        charsets.forEach(charset => {
+            try {
+                if (mode === "Decode") {
+                    output[charset] = cptable.utils.decode(IO_FORMAT[charset], input);
+                } else {
+                    output[charset] = Utils.arrayBufferToStr(cptable.utils.encode(IO_FORMAT[charset], input));
+                }
+            } catch (err) {
+                output[charset] = "Could not decode.";
+            }
+        });
+
+        return output;
+    }
+
+    /**
+     * Displays the encodings in an HTML table for web apps.
+     *
+     * @param {Object[]} encodings
+     * @returns {html}
+     */
+    present(encodings) {
+        let table = "<table class='table table-hover table-sm table-bordered table-nonfluid'><tr><th>Encoding</th><th>Value</th></tr>";
+
+        for (const enc in encodings) {
+            const value = Utils.printable(encodings[enc], true);
+            table += `<tr><td>${enc}</td><td>${value}</td></tr>`;
+        }
+
+        table += "<table>";
+        return table;
+    }
+
+}
+
+export default TextEncodingBruteForce;

+ 58 - 0
src/core/operations/ToBase62.mjs

@@ -0,0 +1,58 @@
+/**
+ * @author tcode2k16 [tcode2k16@gmail.com]
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import BigNumber from "bignumber.js";
+import Utils from "../Utils";
+import {toHexFast} from "../lib/Hex";
+
+/**
+ * To Base62 operation
+ */
+class ToBase62 extends Operation {
+
+    /**
+     * ToBase62 constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "To Base62";
+        this.module = "Default";
+        this.description = "Base62 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers. The high number base results in shorter strings than with the decimal or hexadecimal system.";
+        this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems";
+        this.inputType = "byteArray";
+        this.outputType = "string";
+        this.args = [
+            {
+                name: "Alphabet",
+                type: "string",
+                value: "0-9A-Za-z"
+            }
+        ];
+    }
+
+    /**
+     * @param {string} input
+     * @param {Object[]} args
+     * @returns {string}
+     */
+    run(input, args) {
+        if (input.length < 1) return "";
+
+        const ALPHABET = Utils.expandAlphRange(args[0]).join("");
+        const BN = BigNumber.clone({ ALPHABET });
+
+        input = toHexFast(input).toUpperCase();
+
+        const number = new BN(input, 16);
+
+        return number.toString(62);
+    }
+
+}
+
+export default ToBase62;

+ 2 - 0
test/index.mjs

@@ -28,6 +28,7 @@ import "./tests/operations/BCD";
 import "./tests/operations/BSON";
 import "./tests/operations/Base58";
 import "./tests/operations/Base64";
+import "./tests/operations/Base62";
 import "./tests/operations/BitwiseOp";
 import "./tests/operations/ByteRepr";
 import "./tests/operations/CartesianProduct";
@@ -74,6 +75,7 @@ import "./tests/operations/SetIntersection";
 import "./tests/operations/SetUnion";
 import "./tests/operations/StrUtils";
 import "./tests/operations/SymmetricDifference";
+import "./tests/operations/TextEncodingBruteForce";
 import "./tests/operations/ToGeohash.mjs";
 import "./tests/operations/TranslateDateTimeFormat";
 import "./tests/operations/Magic";

+ 79 - 0
test/tests/operations/Base62.mjs

@@ -0,0 +1,79 @@
+/**
+ * Base62 tests.
+ *
+ * @author tcode2k16 [tcode2k16@gmail.com]
+ *
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ */
+
+import TestRegister from "../../TestRegister";
+
+TestRegister.addTests([
+    {
+        name: "To Base62: nothing",
+        input: "",
+        expectedOutput: "",
+        recipeConfig: [
+            {
+                op: "To Base62",
+                args: ["0-9A-Za-z"],
+            },
+        ],
+    },
+    {
+        name: "To Base62: Hello, World!",
+        input: "Hello, World!",
+        expectedOutput: "1wJfrzvdbtXUOlUjUf",
+        recipeConfig: [
+            {
+                op: "To Base62",
+                args: ["0-9A-Za-z"],
+            },
+        ],
+    },
+    {
+        name: "To Base62: UTF-8",
+        input: "ნუ პანიკას",
+        expectedOutput: "BPDNbjoGvDCDzHbKT77eWg0vGQrJuWRXltuRVZ",
+        recipeConfig: [
+            {
+                op: "To Base62",
+                args: ["0-9A-Za-z"],
+            },
+        ],
+    },
+    {
+        name: "From Base62: nothing",
+        input: "",
+        expectedOutput: "",
+        recipeConfig: [
+            {
+                op: "From Base62",
+                args: ["0-9A-Za-z"],
+            },
+        ],
+    },
+    {
+        name: "From Base62: Hello, World!",
+        input: "1wJfrzvdbtXUOlUjUf",
+        expectedOutput: "Hello, World!",
+        recipeConfig: [
+            {
+                op: "From Base62",
+                args: ["0-9A-Za-z"],
+            },
+        ],
+    },
+    {
+        name: "From Base62: UTF-8",
+        input: "BPDNbjoGvDCDzHbKT77eWg0vGQrJuWRXltuRVZ",
+        expectedOutput: "ნუ პანიკას",
+        recipeConfig: [
+            {
+                op: "From Base62",
+                args: ["0-9A-Za-z"],
+            },
+        ],
+    }
+]);

+ 33 - 0
test/tests/operations/Ciphers.mjs

@@ -110,6 +110,39 @@ TestRegister.addTests([
             }
         ],
     },
+    {
+        name: "A1Z26 Encode: normal",
+        input: "This is the test sentence.",
+        expectedOutput: "20 8 9 19 9 19 20 8 5 20 5 19 20 19 5 14 20 5 14 3 5",
+        recipeConfig: [
+            {
+                op: "A1Z26 Cipher Encode",
+                args: ["Space"]
+            }
+        ],
+    },
+    {
+        name: "A1Z26 Decode: normal",
+        input: "20 8 9 19 9 19 20 8 5 20 5 19 20 19 5 14 20 5 14 3 5",
+        expectedOutput: "thisisthetestsentence",
+        recipeConfig: [
+            {
+                op: "A1Z26 Cipher Decode",
+                args: ["Space"]
+            }
+        ],
+    },
+    {
+        name: "A1Z26 Decode: error",
+        input: "20 8 9 27",
+        expectedOutput: "Error: all numbers must be between 1 and 26.",
+        recipeConfig: [
+            {
+                op: "A1Z26 Cipher Decode",
+                args: ["Space"]
+            }
+        ],
+    },
     {
         name: "Atbash: no input",
         input: "",

+ 297 - 1
test/tests/operations/Hash.mjs

@@ -405,7 +405,7 @@ TestRegister.addTests([
         ]
     },
     {
-        name: "HMAC SHA256",
+        name: "HMAC: SHA256",
         input: "Hello, World!",
         expectedOutput: "52589bd80ccfa4acbb3f9512dfaf4f700fa5195008aae0b77a9e47dcca75beac",
         recipeConfig: [
@@ -415,6 +415,302 @@ TestRegister.addTests([
             }
         ]
     },
+    {
+        name: "HMAC: RFC4231 Test Case 1 SHA-224",
+        input: "Hi There",
+        expectedOutput: "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"}, "SHA224"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 1 SHA-256",
+        input: "Hi There",
+        expectedOutput: "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"}, "SHA256"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 1 SHA-384",
+        input: "Hi There",
+        expectedOutput: "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"}, "SHA384"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 1 SHA-512",
+        input: "Hi There",
+        expectedOutput: "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"}, "SHA512"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 2 SHA-224",
+        input: "what do ya want for nothing?",
+        expectedOutput: "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "4a656665"}, "SHA224"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 2 SHA-256",
+        input: "what do ya want for nothing?",
+        expectedOutput: "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "4a656665"}, "SHA256"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 2 SHA-384",
+        input: "what do ya want for nothing?",
+        expectedOutput: "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "4a656665"}, "SHA384"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 2 SHA-512",
+        input: "what do ya want for nothing?",
+        expectedOutput: "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "4a656665"}, "SHA512"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 3 SHA-224",
+        input: "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+        expectedOutput: "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea",
+        recipeConfig: [
+            {
+                "op": "From Hex",
+                "args": ["None"]
+            },
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA224"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 3 SHA-256",
+        input: "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+        expectedOutput: "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
+        recipeConfig: [
+            {
+                "op": "From Hex",
+                "args": ["None"]
+            },
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA256"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 3 SHA-384",
+        input: "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+        expectedOutput: "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27",
+        recipeConfig: [
+            {
+                "op": "From Hex",
+                "args": ["None"]
+            },
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA384"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 3 SHA-512",
+        input: "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+        expectedOutput: "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb",
+        recipeConfig: [
+            {
+                "op": "From Hex",
+                "args": ["None"]
+            },
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA512"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 4 SHA-224",
+        input: "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+        expectedOutput: "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a",
+        recipeConfig: [
+            {
+                "op": "From Hex",
+                "args": ["None"]
+            },
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "0102030405060708090a0b0c0d0e0f10111213141516171819"}, "SHA224"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 4 SHA-256",
+        input: "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+        expectedOutput: "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
+        recipeConfig: [
+            {
+                "op": "From Hex",
+                "args": ["None"]
+            },
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "0102030405060708090a0b0c0d0e0f10111213141516171819"}, "SHA256"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 4 SHA-384",
+        input: "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+        expectedOutput: "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb",
+        recipeConfig: [
+            {
+                "op": "From Hex",
+                "args": ["None"]
+            },
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "0102030405060708090a0b0c0d0e0f10111213141516171819"}, "SHA384"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 4 SHA-512",
+        input: "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+        expectedOutput: "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd",
+        recipeConfig: [
+            {
+                "op": "From Hex",
+                "args": ["None"]
+            },
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "0102030405060708090a0b0c0d0e0f10111213141516171819"}, "SHA512"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 6 SHA-224",
+        input: "Test Using Larger Than Block-Size Key - Hash Key First",
+        expectedOutput: "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA224"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 6 SHA-256",
+        input: "Test Using Larger Than Block-Size Key - Hash Key First",
+        expectedOutput: "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA256"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 6 SHA-384",
+        input: "Test Using Larger Than Block-Size Key - Hash Key First",
+        expectedOutput: "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA384"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 6 SHA-512",
+        input: "Test Using Larger Than Block-Size Key - Hash Key First",
+        expectedOutput: "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA512"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 7 SHA-224",
+        input: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
+        expectedOutput: "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA224"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 7 SHA-256",
+        input: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
+        expectedOutput: "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA256"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 7 SHA-384",
+        input: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
+        expectedOutput: "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA384"]
+            }
+        ]
+    },
+    {
+        name: "HMAC: RFC4231 Test Case 7 SHA-512",
+        input: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
+        expectedOutput: "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA512"]
+            }
+        ]
+    },
     {
         name: "MD5: Complex bytes",
         input: "10dc10e32010de10d010dc10d810d910d010e12e",

+ 35 - 0
test/tests/operations/TextEncodingBruteForce.mjs

@@ -0,0 +1,35 @@
+/**
+ * Text Encoding Brute Force tests.
+ *
+ * @author Cynser
+ *
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ */
+import TestRegister from "../../TestRegister";
+
+TestRegister.addTests([
+    {
+        name: "Text Encoding Brute Force - Encode",
+        input: "Булкі праз ляніва сабаку.",
+        expectedMatch: /Windows-1251 Cyrillic \(1251\).{1,10}Булкі праз ляніва сабаку\./,
+        recipeConfig: [
+            {
+                op: "Text Encoding Brute Force",
+                args: ["Encode"],
+            },
+        ],
+    },
+    {
+        name: "Text Encoding Brute Force - Decode",
+        input: "Áóëê³ ïðàç ëÿí³âà ñàáàêó.",
+        expectedMatch: /Windows-1251 Cyrillic \(1251\).{1,10}Булкі праз ляніва сабаку\./,
+        recipeConfig: [
+            {
+                op: "Text Encoding Brute Force",
+                args: ["Decode"],
+            },
+        ],
+    }
+]);
+