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).
+- 'Index of Coincidence' operation added [@Ge0rg3] | [#571]
+
### [8.31.0] - 2019-04-12
- The downloadable version of CyberChef is now a .zip file containing separate modules rather than a single .htm file. It is still completely standalone and will not make any external network requests. This change reduces the complexity of the build process significantly. [@n1474335]
@@ -130,6 +152,13 @@ All major and minor version changes will be documented in this file. Details of
@@ -50,7 +50,7 @@ You can use as many operations as you like in simple or complex ways. Some examp
- Drag and drop
- Operations can be dragged in and out of the recipe list, or reorganised.
- - Files up to 500MB can be dragged over the input box to load them directly into the browser.
+ - Files up to 2GB can be dragged over the input box to load them directly into the browser.
- Auto Bake
- Whenever you modify the input or the recipe, CyberChef will automatically "bake" for you and produce the output immediately.
- This can be turned off and operated manually if it is affecting performance (if the input is very large, for instance).
@@ -67,7 +67,7 @@ You can use as many operations as you like in simple or complex ways. Some examp
- Highlighting
- When you highlight text in the input or output, the offset and length values will be displayed and, if possible, the corresponding data will be highlighted in the output or input respectively (example: [highlight the word 'question' in the input to see where it appears in the output][11]).
- Save to file and load from file
- - You can save the output to a file at any time or load a file by dragging and dropping it into the input field. Files up to around 500MB are supported (depending on your browser), however some operations may take a very long time to run over this much data.
+ - You can save the output to a file at any time or load a file by dragging and dropping it into the input field. Files up to around 2GB are supported (depending on your browser), however some operations may take a very long time to run over this much data.
- CyberChef is entirely client-side
- It should be noted that none of your recipe configuration or input (either text or files) is ever sent to the CyberChef web server - all processing is carried out within your browser, on your own computer.
- Due to this feature, CyberChef can be compiled into a single HTML file. You can download this file and drop it into a virtual machine, share it with other people, or use it independently on your local machine.
+import OperationError from "../errors/OperationError";
+import { isImage } from "../lib/FileType";
+import { toBase64 } from "../lib/Base64";
+import jimp from "jimp";
+
+/**
+ * Add Text To Image operation
+ */
+class AddTextToImage extends Operation {
+
+ /**
+ * AddTextToImage constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "Add Text To Image";
+ this.module = "Image";
+ this.description = "Adds text onto an image.<br><br>Text can be horizontally or vertically aligned, or the position can be manually specified.<br>Variants of the Roboto font face are available in any size or colour.";
+ this.infoURL = "";
+ this.inputType = "ArrayBuffer";
+ this.outputType = "ArrayBuffer";
+ this.presentType = "html";
+ this.args = [
+ {
+ name: "Text",
+ type: "string",
+ value: ""
+ },
+ {
+ name: "Horizontal align",
+ type: "option",
+ value: ["None", "Left", "Center", "Right"]
+ },
+ {
+ name: "Vertical align",
+ type: "option",
+ value: ["None", "Top", "Middle", "Bottom"]
+ },
+ {
+ name: "X position",
+ type: "number",
+ value: 0
+ },
+ {
+ name: "Y position",
+ type: "number",
+ value: 0
+ },
+ {
+ name: "Size",
+ type: "number",
+ value: 32,
+ min: 8
+ },
+ {
+ name: "Font face",
+ type: "option",
+ value: [
+ "Roboto",
+ "Roboto Black",
+ "Roboto Mono",
+ "Roboto Slab"
+ ]
+ },
+ {
+ name: "Red",
+ type: "number",
+ value: 255,
+ min: 0,
+ max: 255
+ },
+ {
+ name: "Green",
+ type: "number",
+ value: 255,
+ min: 0,
+ max: 255
+ },
+ {
+ name: "Blue",
+ type: "number",
+ value: 255,
+ min: 0,
+ max: 255
+ },
+ {
+ name: "Alpha",
+ type: "number",
+ value: 255,
+ min: 0,
+ max: 255
+ }
+ ];
+ }
+
+ /**
+ * @param {ArrayBuffer} input
+ * @param {Object[]} args
+ * @returns {byteArray}
+ */
+ async run(input, args) {
+ const text = args[0],
+ hAlign = args[1],
+ vAlign = args[2],
+ size = args[5],
+ fontFace = args[6],
+ red = args[7],
+ green = args[8],
+ blue = args[9],
+ alpha = args[10];
+
+ let xPos = args[3],
+ yPos = args[4];
+
+ if (!isImage(new Uint8Array(input))) {
+ throw new OperationError("Invalid file type.");
+ }
+
+ let image;
+ try {
+ image = await jimp.read(input);
+ } catch (err) {
+ throw new OperationError(`Error loading image. (${err})`);
+ }
+ try {
+ if (ENVIRONMENT_IS_WORKER())
+ self.sendStatusMessage("Adding text to image...");
+import OperationError from "../errors/OperationError";
+import Bzip2 from "libbzip2-wasm";
+
+/**
+ * Bzip2 Compress operation
+ */
+class Bzip2Compress extends Operation {
+
+ /**
+ * Bzip2Compress constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "Bzip2 Compress";
+ this.module = "Compression";
+ this.description = "Bzip2 is a compression library developed by Julian Seward (of GHC fame) that uses the Burrows-Wheeler algorithm. It only supports compressing single files and its compression is slow, however is more effective than Deflate (.gz & .zip).";
+import OperationError from "../errors/OperationError";
+
+import { toHexFast } from "../lib/Hex";
+
+/**
+ * CRC-8 Checksum operation
+ */
+class CRC8Checksum extends Operation {
+
+ /**
+ * CRC8Checksum constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "CRC-8 Checksum";
+ this.module = "Crypto";
+ this.description = "A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data.<br><br>The CRC was invented by W. Wesley Peterson in 1961.";
+import OperationError from "../errors/OperationError";
+import { isImage } from "../lib/FileType";
+import { toBase64 } from "../lib/Base64";
+import jimp from "jimp";
+
+/**
+ * Convert Image Format operation
+ */
+class ConvertImageFormat extends Operation {
+
+ /**
+ * ConvertImageFormat constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "Convert Image Format";
+ this.module = "Image";
+ this.description = "Converts an image between different formats. Supported formats:<br><ul><li>Joint Photographic Experts Group (JPEG)</li><li>Portable Network Graphics (PNG)</li><li>Bitmap (BMP)</li><li>Tagged Image File Format (TIFF)</li></ul><br>Note: GIF files are supported for input, but cannot be outputted.";
@@ -26,8 +26,8 @@ class CropImage extends Operation {
this.module = "Image";
this.description = "Crops an image to the specified region, or automatically crops edges.<br><br><b><u>Autocrop</u></b><br>Automatically crops same-colour borders from the image.<br><br><u>Autocrop tolerance</u><br>A percentage value for the tolerance of colour difference between pixels.<br><br><u>Only autocrop frames</u><br>Only crop real frames (all sides must have the same border)<br><br><u>Symmetric autocrop</u><br>Force autocrop to be symmetric (top/bottom and left/right are cropped by the same amount)<br><br><u>Autocrop keep border</u><br>The number of pixels of border to leave around the image.";
@@ -21,7 +21,12 @@ class DetectFileType extends Operation {
this.name = "Detect File Type";
this.module = "Default";
- this.description = "Attempts to guess the MIME (Multipurpose Internet Mail Extensions) type of the data based on 'magic bytes'.<br><br>Currently supports the following file types: 7z, amr, avi, bmp, bz2, class, cr2, crx, dex, dmg, doc, elf, eot, epub, exe, flac, flv, gif, gz, ico, iso, jpg, jxr, m4a, m4v, mid, mkv, mov, mp3, mp4, mpg, ogg, otf, pdf, png, ppt, ps, psd, rar, rtf, sqlite, swf, tar, tar.z, tif, ttf, utf8, vmdk, wav, webm, webp, wmv, woff, woff2, xls, xz, zip.";
+ this.description = "Attempts to guess the MIME (Multipurpose Internet Mail Extensions) type of the data based on 'magic bytes'.<br><br>Currently supports the following file types: " +
@@ -19,30 +24,45 @@ class Entropy extends Operation {
super();
this.name = "Entropy";
- this.module = "Default";
+ this.module = "Charts";
this.description = "Shannon Entropy, in the context of information theory, is a measure of the rate at which information is produced by a source of data. It can be used, in a broad sense, to detect whether data is likely to be structured or unstructured. 8 is the maximum, representing highly unstructured, 'random' data. English language text usually falls somewhere between 3.5 and 5. Properly encrypted or compressed data should have an entropy of over 7.5.";
* Displays the entropy as a scale bar for web apps.
*
* @param {number} entropy
- * @returns {html}
+ * @returns {HTML}
*/
- present(entropy) {
+ createShannonEntropyVisualization(entropy) {
return `Shannon entropy: ${entropy}
-<br><canvas id='chart-area'></canvas><br>
-- 0 represents no randomness (i.e. all the bytes in the data have the same value) whereas 8, the maximum, represents a completely random string.
-- Standard English text usually falls somewhere between 3.5 and 5.
-- Properly encrypted or compressed data of a reasonable length should have an entropy of over 7.5.
-
-The following results show the entropy of chunks of the input data. Chunks with particularly high entropy could suggest encrypted or compressed sections.
-
-<br><script>
- var canvas = document.getElementById("chart-area"),
+ - 0 represents no randomness (i.e. all the bytes in the data have the same value) whereas 8, the maximum, represents a completely random string.
+ - Standard English text usually falls somewhere between 3.5 and 5.
+ - Properly encrypted or compressed data of a reasonable length should have an entropy of over 7.5.
+
+ The following results show the entropy of chunks of the input data. Chunks with particularly high entropy could suggest encrypted or compressed sections.
+
+ <br><script>
+ var canvas = document.getElementById("chart-area"),
+import OperationError from "../errors/OperationError";
+import GostDigest from "../vendor/gost/gostDigest";
+import {toHexFast} from "../lib/Hex";
+
+/**
+ * GOST hash operation
+ */
+class GOSTHash extends Operation {
+
+ /**
+ * GOSTHash constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "GOST hash";
+ this.module = "Hashing";
+ this.description = "The GOST hash function, defined in the standards GOST R 34.11-94 and GOST 34.311-95 is a 256-bit cryptographic hash function. It was initially defined in the Russian national standard GOST R 34.11-94 <i>Information Technology – Cryptographic Information Security – Hash Function</i>. The equivalent standard used by other member-states of the CIS is GOST 34.311-95.<br><br>This function must not be confused with a different Streebog hash function, which is defined in the new revision of the standard GOST R 34.11-2012.<br><br>The GOST hash function is based on the GOST block cipher.";
import OperationError from "../errors/OperationError";
-import qr from "qr-image";
+import { generateQrCode } from "../lib/QRCode";
import { toBase64 } from "../lib/Base64";
import { isImage } from "../lib/FileType";
import Utils from "../Utils";
@@ -27,7 +27,7 @@ class GenerateQRCode extends Operation {
this.description = "Generates a Quick Response (QR) code from the input text.<br><br>A QR code is a type of matrix barcode (or two-dimensional barcode) first designed in 1994 for the automotive industry in Japan. A barcode is a machine-readable optical label that contains information about the item to which it is attached.";
+ * @author George O [georgeomnet+cyberchef@gmail.com]
+ * @copyright Crown Copyright 2019
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import Utils from "../Utils";
+
+/**
+ * Index of Coincidence operation
+ */
+class IndexOfCoincidence extends Operation {
+
+ /**
+ * IndexOfCoincidence constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "Index of Coincidence";
+ this.module = "Default";
+ this.description = "Index of Coincidence (IC) is the probability of two randomly selected characters being the same. This can be used to determine whether text is readable or random, with English text having an IC of around 0.066. IC can therefore be a sound method to automate frequency analysis.";
import OperationError from "../errors/OperationError";
-import { isImage } from "../lib/FileType";
-import jsqr from "jsqr";
-import jimp from "jimp";
+import { isImage } from "../lib/FileType.mjs";
+import { parseQrCode } from "../lib/QRCode";
/**
* Parse QR Code operation
@@ -25,7 +24,7 @@ class ParseQRCode extends Operation {
this.module = "Image";
this.description = "Reads an image file and attempts to detect and read a Quick Response (QR) code from the image.<br><br><u>Normalise Image</u><br>Attempts to normalise the image before parsing it to improve detection of a QR code.";
+import OperationError from "../errors/OperationError";
+import GostDigest from "../vendor/gost/gostDigest";
+import {toHexFast} from "../lib/Hex";
+
+/**
+ * Streebog operation
+ */
+class Streebog extends Operation {
+
+ /**
+ * Streebog constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "Streebog";
+ this.module = "Hashing";
+ this.description = "Streebog is a cryptographic hash function defined in the Russian national standard GOST R 34.11-2012 <i>Information Technology \u2013 Cryptographic Information Security \u2013 Hash Function</i>. It was created to replace an obsolete GOST hash function defined in the old standard GOST R 34.11-94, and as an asymmetric reply to SHA-3 competition by the US National Institute of Standards and Technology.";
@@ -20,7 +20,7 @@ class UnescapeString extends Operation {
this.name = "Unescape string";
this.module = "Default";
- this.description = "Unescapes characters in a string that have been escaped. For example, <code>Don\\'t stop me now</code> becomes <code>Don't stop me now</code>.<br><br>Supports the following escape sequences:<ul><li><code>\\n</code> (Line feed/newline)</li><li><code>\\r</code> (Carriage return)</li><li><code>\\t</code> (Horizontal tab)</li><li><code>\\b</code> (Backspace)</li><li><code>\\f</code> (Form feed)</li><li><code>\\xnn</code> (Hex, where n is 0-f)</li><li><code>\\\\</code> (Backslash)</li><li><code>\\'</code> (Single quote)</li><li><code>\\"</code> (Double quote)</li><li><code>\\unnnn</code> (Unicode character)</li><li><code>\\u{nnnnnn}</code> (Unicode code point)</li></ul>";
+ this.description = "Unescapes characters in a string that have been escaped. For example, <code>Don\\'t stop me now</code> becomes <code>Don't stop me now</code>.<br><br>Supports the following escape sequences:<ul><li><code>\\n</code> (Line feed/newline)</li><li><code>\\r</code> (Carriage return)</li><li><code>\\t</code> (Horizontal tab)</li><li><code>\\b</code> (Backspace)</li><li><code>\\f</code> (Form feed)</li><li><code>\\nnn</code> (Octal, where n is 0-7)</li><li><code>\\xnn</code> (Hex, where n is 0-f)</li><li><code>\\\\</code> (Backslash)</li><li><code>\\'</code> (Single quote)</li><li><code>\\"</code> (Double quote)</li><li><code>\\unnnn</code> (Unicode character)</li><li><code>\\u{nnnnnn}</code> (Unicode code point)</li></ul>";
+ * BER.decode(object, format) convert javascript object to ASN.1 format CryptoOperationData<br><br>
+ * If object has members tagNumber, tagClass and tagConstructed
+ * it is clear define encoding rules. Else method use defaul rules:
+ * <ul>
+ * <li>Empty string or null - NULL</li>
+ * <li>String starts with '0x' and has 0-9 and a-f characters - INTEGER</li>
+ * <li>String like d.d.d.d (d - set of digits) - OBJECT IDENTIFIER</li>
+ * <li>String with characters 0 and 1 - BIT STRING</li>
+ * <li>Strings 'true' or 'false' - BOOLEAN</li>
+ * <li>String has only 0-9 and a-f characters - OCTET STRING</li>
+ * <li>String has only characters with code 0-255 - PrintableString</li>
+ * <li>Other strings - UTF8String</li>
+ * <li>Number - INTEGER</li>
+ * <li>Date - GeneralizedTime</li>
+ * <li>Boolean - SEQUENCE</li>
+ * <li>CryptoOperationData - OCTET STRING</li>
+ * </ul>
+ * SEQUENCE or SET arrays recursively encoded for each item.<br>
+ * OCTET STRING and BIT STRING can presents as array with one item.
+ * It means encapsulates encoding for child element.<br>
+ *
+ * If CONTEXT or APPLICATION classes item presents as array with one
+ * item we use EXPLICIT encoding for element, else IMPLICIT encoding.<br>
+ *
+ * @memberOf GostCoding.BER
+ * @param {Object} object Object to encoding
+ * @param {string} format Encoding rule: 'DER' or 'CER', default 'DER'
+ * @param {boolean} onlyContent Encode content only, without header
+ * @returns {CryptoOperationData} BER encoded data
+ */
+ encode: function (object, format, onlyContent) {
+ return encodeBER(object, format, onlyContent).buffer;
+ },
+ /**
+ * BER.encode(data) convert ASN.1 format CryptoOperationData data to javascript object<br><br>
+ *
+ * Conversion rules to javascript object:
+ * <ul>
+ * <li>BOOLEAN - Boolean object</li>
+ * <li>INTEGER, ENUMIRATED - Integer object if len <= 6 (48 bits) else Int16 encoded string</li>
+ * <li>BIT STRING - Integer object if len <= 5 (w/o unsedBit octet - 32 bits) else String like '10111100' or Array with one item in case of incapsulates encoding</li>
+ * <li>OCTET STRING - Hex encoded string or Array with one item in case of incapsulates encoding</li>
+ * <li>OBJECT IDENTIFIER - String with object identifier</li>
+ * <li>SEQUENCE, SET - Array of encoded items</li>
+ throw new (root.NotSupportedError || Error)('Algorithm ' + name + '-' + mode + ' is not valid for ' + method);
+} // </editor-fold>
+
+/**
+ * Object implements dedicated Web Workers and provide a simple way to create
+ * and run GOST cryptographic algorithms in background thread.
+ *
+ * Object provide interface to GOST low-level cryptogric classes:
+ * <ul>
+ * <li>GostCipher - implementation of GOST 28147, GOST R 34.12, GOST R 34.13 Encryption algorithms. Reference {@link http://tools.ietf.org/html/rfc5830}</li>
+ * <li>GostDigest - implementation of GOST R 34.11 Hash Function algorithms. References {@link http://tools.ietf.org/html/rfc5831} and {@link http://tools.ietf.org/html/rfc6986}</li>
+ * <li>GostSign - implementation of GOST R 34.10 Digital Signature algorithms. References {@link http://tools.ietf.org/html/rfc5832} and {@link http://tools.ietf.org/html/rfc7091}</li>
+ * </ul>
+ * @namespace gostEngine
+ */
+var gostEngine = {
+ /**
+ * gostEngine.execute(algorithm, method, args) Entry point to execution
+ * all low-level GOST cryptographic methods
+ *
+ * <ul>
+ * <li>Determine the appropriate engine for a given execution method</li>
+ * <li>Create cipher object for determineted engine</li>
+ * <li>Execute method of cipher with given args</li>
- magicButton.setAttribute("data-original-title", `<i>${opSequence}</i> will produce <span class="data-text">"${Utils.escapeHtml(Utils.truncate(result), 30)}"</span>`);
+ <button type="button" class="btn btn-primary bmd-btn-icon" id="save-all-to-file" data-toggle="tooltip" title="Save all outputs to a zip file" style="display: none">
+ Keep the current tab in sync between the input and output.
+ </label>
+ </div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" id="reset-options">Reset options to default</button>
@@ -599,7 +674,7 @@
</a>
<div class="collapse" id="faq-load-files">
<p>Yes! Just drag your file over the input box and drop it.</p>
- <p>CyberChef can handle files up to around 500MB (depending on your browser), however some of the operations may take a very long time to run over this much data.</p>
+ <p>CyberChef can handle files up to around 2GB (depending on your browser), however some of the operations may take a very long time to run over this much data.</p>
<p>If the output is larger than a certain threshold (default 1MiB), it will be presented to you as a file available for download. Slices of the file can be viewed in the output if you need to inspect them.</p>