@@ -6,7 +6,7 @@ There are lots of opportunities to contribute to CyberChef. If you want ideas, t
Before your contributions can be accepted, you must:
Before your contributions can be accepted, you must:
- - Sign the [GCHQ Contributor Licence Agreement](https://github.com/gchq/Gaffer/wiki/GCHQ-OSS-Contributor-License-Agreement-V1.0)
+ - Sign the [GCHQ Contributor Licence Agreement](https://cla-assistant.io/gchq/CyberChef)
- Push your changes to your fork.
- Push your changes to your fork.
- Submit a pull request.
- Submit a pull request.
@@ -22,15 +22,15 @@ Before your contributions can be accepted, you must:
* Line endings: UNIX style (\n)
* Line endings: UNIX style (\n)
-## Design Principals
+## Design Principles
1. If at all possible, all operations and features should be client-side and not rely on connections to an external server. This increases the utility of CyberChef on closed networks and in virtual machines that are not connected to the Internet. Calls to external APIs may be accepted if there is no other option, but not for critical components.
1. If at all possible, all operations and features should be client-side and not rely on connections to an external server. This increases the utility of CyberChef on closed networks and in virtual machines that are not connected to the Internet. Calls to external APIs may be accepted if there is no other option, but not for critical components.
-2. Latency should be kept to a minimum to enhance the user experience. This means that all operation code should sit on the client, rather than being loaded dynamically from a server.
-3. Use Vanilla JS if at all possible to reduce the number of libraries required and relied upon. Frameworks like jQuery, although included, should not be used unless absolutely necessary.
-4. Minimise the use of large libraries, especially for niche operations that won't be used very often - these will be downloaded by everyone using the app, whether they use that operation or not (due to principal 2).
+2. Latency should be kept to a minimum to enhance the user experience. This means that operation code should sit on the client and be executed there. However, as a trade-off between latency and bandwidth, operation code with large dependencies can be loaded in discrete modules in order to reduce the size of the initial download. The downloading of additional modules must remain entirely transparent so that the user is not inconvenienced.
+3. Large libraries should be kept in separate modules so that they are not downloaded by everyone who uses the app, just those who specifically require the relevant operations.
+4. Use Vanilla JS if at all possible to reduce the number of libraries required and relied upon. Frameworks like jQuery, although included, should not be used unless absolutely necessary.
-With these principals in mind, any changes or additions to CyberChef should keep it:
+With these principles in mind, any changes or additions to CyberChef should keep it:
+ run: npx grunt prod --msg="Version 10 is here! Read about the new features <a href='https://github.com/gchq/CyberChef/wiki/Character-encoding,-EOL-separators,-and-editor-features'>here</a>"
+ # Webpack seems to use a lot of open files, increase the max open file limit to accomodate.
+ extra-args: |
+ --ulimit nofile=10000
+
+
+ - name: Upload Release Assets
+ id: upload-release-assets
+ uses: svenstaro/upload-release-action@v2
+ with:
+ repo_token: ${{ secrets.GITHUB_TOKEN }}
+ file: build/prod/*.zip
+ tag: ${{ github.ref }}
+ overwrite: true
+ file_glob: true
+ body: "See the [CHANGELOG](https://github.com/gchq/CyberChef/blob/master/CHANGELOG.md) and [commit messages](https://github.com/gchq/CyberChef/commits/master) for details."
+CyberChef uses the [semver](https://semver.org/) system to manage versioning: `<MAJOR>.<MINOR>.<PATCH>`.
+
+- MAJOR version changes represent a significant change to the fundamental architecture of CyberChef and may (but don't always) make breaking changes that are not backwards compatible.
+- MINOR version changes usually mean the addition of new operations or reasonably significant new features.
+- PATCH versions are used for bug fixes and any other small tweaks that modify or improve existing capabilities.
+
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).
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).
+## Details
+
+### [10.8.0] - 2024-02-13
+- Add official Docker images [@AshCorr] | [#1699]
+- Improvements to the 'Magic' operation, allowing it to recognise more data formats and provide more accurate results [@n1073645] [@n1474335] | [#966] [b765534b](https://github.com/gchq/CyberChef/commit/b765534b8b2a0454a5132a0a52d1d8844bcbdaaa)
+
+### [9.18.0] - 2020-03-13
+- 'Convert to NATO alphabet' operation added [@MarvinJWendt] | [#674]
+- 'Defang IP Addresses' operation added [@h345983745] | [#556]
+
+</details>
+
+## [9.0.0] - 2019-07-09
+- [Multiple inputs](https://github.com/gchq/CyberChef/wiki/Multiple-Inputs) are now supported in the main web UI, allowing you to upload and process multiple files at once [@j433866] | [#566]
+- A [Node.js API](https://github.com/gchq/CyberChef/wiki/Node-API) has been implemented, meaning that CyberChef can now be used as a library, either to provide specific operations, or an entire baking environment [@d98762625] | [#291]
+- A [read-eval-print loop (REPL)](https://github.com/gchq/CyberChef/wiki/Node-API#repl) is also included to enable prototyping and experimentation with the API [@d98762625] | [#291]
+- Light and dark Solarized themes added [@j433866] | [#566]
+
+<details>
+ <summary>Click to expand v8 minor versions</summary>
+- '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]
-CyberChef is a simple, intuitive web app for carrying out all manner of "cyber" operations within a web browser. These operations include simple encoding like XOR or Base64, more complex encryption like AES, DES and Blowfish, creating binary and hexdumps, compression and decompression of data, calculating hashes and checksums, IPv6 and X.509 parsing, changing character encodings, and much more.
+CyberChef is a simple, intuitive web app for carrying out all manner of "cyber" operations within a web browser. These operations include simple encoding like XOR and Base64, more complex encryption like AES, DES and Blowfish, creating binary and hexdumps, compression and decompression of data, calculating hashes and checksums, IPv6 and X.509 parsing, changing character encodings, and much more.
The tool is designed to enable both technical and non-technical analysts to manipulate data in complex ways without having to deal with complex tools or algorithms. It was conceived, designed, built and incrementally improved by an analyst in their 10% innovation time over several years.
The tool is designed to enable both technical and non-technical analysts to manipulate data in complex ways without having to deal with complex tools or algorithms. It was conceived, designed, built and incrementally improved by an analyst in their 10% innovation time over several years.
@@ -22,6 +20,22 @@ Cryptographic operations in CyberChef should not be relied upon to provide secur
[A live demo can be found here][1] - have fun!
[A live demo can be found here][1] - have fun!
+## Containers
+
+If you would like to try out CyberChef locally you can either build it yourself:
+docker run -it -p 8080:80 ghcr.io/gchq/cyberchef:latest
+```
+
+This image is built and published through our [GitHub Workflows](.github/workflows/releases.yml)
## How it works
## How it works
@@ -50,12 +64,12 @@ You can use as many operations as you like in simple or complex ways. Some examp
- Drag and drop
- Drag and drop
- Operations can be dragged in and out of the recipe list, or reorganised.
- 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
- Auto Bake
- Whenever you modify the input or the recipe, CyberChef will automatically "bake" for you and produce the output immediately.
- 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).
- This can be turned off and operated manually if it is affecting performance (if the input is very large, for instance).
- Automated encoding detection
- Automated encoding detection
- - CyberChef uses [a number of techniques](https://github.com/gchq/CyberChef/wiki/Automatic-detection-of-encoded-data-using-CyberChef-Magic) to attempt to automatically detect which encodings your data is under. If it finds a suitable operation which can make sense of your data, it displays the 'magic' icon in the Output field which you can click to decode your data.
+ - CyberChef uses [a number of techniques](https://github.com/gchq/CyberChef/wiki/Automatic-detection-of-encoded-data-using-CyberChef-Magic) to attempt to automatically detect which encodings your data is under. If it finds a suitable operation that make sense of your data, it displays the 'magic' icon in the Output field which you can click to decode your data.
- Breakpoints
- Breakpoints
- You can set breakpoints on any operation in your recipe to pause execution before running it.
- You can set breakpoints on any operation in your recipe to pause execution before running it.
- You can also step through the recipe one operation at a time to see what the data looks like at each stage.
- You can also step through the recipe one operation at a time to see what the data looks like at each stage.
@@ -67,26 +81,38 @@ You can use as many operations as you like in simple or complex ways. Some examp
- Highlighting
- 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]).
- 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
- 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
- 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.
- 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.
+ - Due to this feature, CyberChef can be downloaded and run locally. You can use the link in the top left corner of the app to download a full copy of CyberChef and drop it into a virtual machine, share it with other people, or host it in a closed network.
+
+
+## Deep linking
+
+By manipulating CyberChef's URL hash, you can change the initial settings with which the page opens.
+The format is `https://gchq.github.io/CyberChef/#recipe=Operation()&input=...`
+
+Supported arguments are `recipe`, `input` (encoded in Base64), and `theme`.
## Browser support
## Browser support
CyberChef is built to support
CyberChef is built to support
- - Google Chrome 40+
- - Mozilla Firefox 35+
- - Microsoft Edge 14+
+ - Google Chrome 50+
+ - Mozilla Firefox 38+
+
+
+## Node.js support
+
+CyberChef is built to fully support Node.js `v16`. For more information, see the ["Node API" wiki page](https://github.com/gchq/CyberChef/wiki/Node-API)
## Contributing
## Contributing
-Contributing a new operation to CyberChef is super easy! There is a quickstart script which will walk you through the process. If you can write basic JavaScript, you can write a CyberChef operation.
+Contributing a new operation to CyberChef is super easy! The quickstart script will walk you through the process. If you can write basic JavaScript, you can write a CyberChef operation.
-An installation walkthrough, how-to guides for adding new operations and themes, descriptions of the repository structure, available data types and coding conventions can all be found in the project [wiki pages](https://github.com/gchq/CyberChef/wiki).
+An installation walkthrough, how-to guides for adding new operations and themes, descriptions of the repository structure, available data types and coding conventions can all be found in the ["Contributing" wiki page](https://github.com/gchq/CyberChef/wiki/Contributing).
- Push your changes to your fork.
- Push your changes to your fork.
- Submit a pull request. If you are doing this for the first time, you will be prompted to sign the [GCHQ Contributor Licence Agreement](https://cla-assistant.io/gchq/CyberChef) via the CLA assistant on the pull request. This will also ask whether you are happy for GCHQ to contact you about a token of thanks for your contribution, or about job opportunities at GCHQ.
- Submit a pull request. If you are doing this for the first time, you will be prompted to sign the [GCHQ Contributor Licence Agreement](https://cla-assistant.io/gchq/CyberChef) via the CLA assistant on the pull request. This will also ask whether you are happy for GCHQ to contact you about a token of thanks for your contribution, or about job opportunities at GCHQ.
@@ -94,7 +120,7 @@ An installation walkthrough, how-to guides for adding new operations and themes,
## Licencing
## Licencing
-CyberChef is released under the [Apache 2.0 Licence](https://www.apache.org/licenses/LICENSE-2.0) and is covered by [Crown Copyright](https://www.nationalarchives.gov.uk/information-management/re-using-public-sector-information/copyright-and-re-use/crown-copyright/).
+CyberChef is released under the [Apache 2.0 Licence](https://www.apache.org/licenses/LICENSE-2.0) and is covered by [Crown Copyright](https://www.nationalarchives.gov.uk/information-management/re-using-public-sector-information/uk-government-licensing-framework/crown-copyright/).
+ if (alphabet.length !== 64 && alphabet.length !== 65) { // Allow for padding
+ throw new OperationError(`Error: Base64 alphabet should be 64 characters long, or 65 with a padding character. Found ${alphabet.length}: ${alphabet}`);
+ }
+ // Remove non-alphabet characters
if (removeNonAlphChars) {
if (removeNonAlphChars) {
const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
+export const cryptNotice = "WARNING: Cryptographic operations in CyberChef should not be relied upon to provide security in any situation. No guarantee is offered for their correctness. We advise you not to use keys generated from CyberChef in operational contexts.";
+ * A set of randomised example SIGABA cipher/control rotors (these rotors are interchangeable). Cipher and control rotors can be referred to as C and R rotors respectively.
+ * The control rotor bank consists of 5 control rotors in either a forward or reversed orientation. Signals to the control rotor bank always go from right-to-left.
+ */
+export class ControlBank {
+
+ /**
+ * ControlBank constructor. The rotors have been reversed as signals go from right-to-left through the control rotors.
+ *
+ * @param {Object[]} rotors - list of CRRotors
+ */
+ constructor(rotors) {
+ this.rotors = [...rotors].reverse();
+ }
+
+ /**
+ * Encrypts a letter.
+ *
+ * @param {char} inputPos - the input position of the signal
+ // 14 is the offset of "O" from "A" - the next rotor steps once the previous rotor reaches "O"
+ if (FRotor.state === 14) {
+ if (MRotor.state === 14) {
+ SRotor.step();
+ }
+ MRotor.step();
+ }
+ FRotor.step();
+ }
+
+ /**
+ * The goThroughControl function combines getting the outputs from the control rotor bank and then stepping them.
+ *
+ * @returns {number[]}
+ */
+ goThroughControl() {
+ const outputs = this.getOutputs();
+ this.step();
+ return outputs;
+ }
+
+}
+
+/**
+ * The index rotor bank consists of 5 index rotors all placed in the forwards orientation.
+ */
+export class IndexBank {
+
+ /**
+ * IndexBank constructor
+ *
+ * @param {Object[]} rotors - list of IRotors
+ */
+ constructor(rotors) {
+ this.rotors = rotors;
+ }
+
+ /**
+ * Encrypts a number.
+ *
+ * @param {number} inputPos - the input position of the signal
+ * @returns {number}
+ */
+ crypt(inputPos) {
+ for (const rotor of this.rotors) {
+ inputPos = rotor.crypt(inputPos);
+ }
+ return inputPos;
+ }
+
+ /**
+ * The goThroughIndex function takes the inputs from the control rotor bank and returns the list of outputs after encryption through the index rotors.
+ *
+ * @param {number[]} controlInputs - inputs from the control rotors
+ * @returns {number[]}
+ */
+ goThroughIndex(controlInputs) {
+ const outputs = [];
+ for (const inp of controlInputs) {
+ outputs.push(this.crypt(inp));
+ }
+ return outputs;
+ }
+
+}
+
+/**
+ * Rotor class
+ */
+export class Rotor {
+
+ /**
+ * Rotor constructor
+ *
+ * @param {number[]} wireSetting - the wirings within the rotor: mapping from left-to-right, the index of the number in the list maps onto the number at that index
+ * @param {bool} rev - true if the rotor is reversed, false if it isn't
+ * @param {number} key - the starting position or state of the rotor
+ * Get the number mapping from the wireSetting (only different from wireSetting if rotor is reversed)
+ *
+ * @param {number[]} wireSetting - the wirings within the rotors
+ * @param {bool} rev - true if reversed, false if not
+ * @returns {number[]}
+ */
+ getNumMapping(wireSetting, rev) {
+ if (rev===false) {
+ return wireSetting;
+ } else {
+ const length = wireSetting.length;
+ const tempMapping = new Array(length);
+ for (let i=0; i<length; i++) {
+ tempMapping[wireSetting[i]] = i;
+ }
+ return tempMapping;
+ }
+ }
+
+ /**
+ * Get the position mapping (how the position numbers map onto the numbers of the rotor)
+ *
+ * @param {bool} rev - true if reversed, false if not
+ * @returns {number[]}
+ */
+ getPosMapping(rev) {
+ const length = this.numMapping.length;
+ const posMapping = [];
+ if (rev===false) {
+ for (let i = this.state; i < this.state+length; i++) {
+ let res = i%length;
+ if (res<0) {
+ res += length;
+ }
+ posMapping.push(res);
+ }
+ } else {
+ for (let i = this.state; i > this.state-length; i--) {
+ let res = i%length;
+ if (res<0) {
+ res += length;
+ }
+ posMapping.push(res);
+ }
+ }
+ return posMapping;
+ }
+
+ /**
+ * Encrypt/decrypt data. This process is identical to the rotors of cipher machines such as Enigma or Typex.
+ *
+ * @param {number} inputPos - the input position of the signal (the data to encrypt/decrypt)
+ * @param {string} direction - one of "leftToRight" and "rightToLeft", states the direction in which the signal passes through the rotor
+ * @returns {number}
+ */
+ cryptNum(inputPos, direction) {
+ const inpNum = this.posMapping[inputPos];
+ let outNum;
+ if (direction === "leftToRight") {
+ outNum = this.numMapping[inpNum];
+ } else if (direction === "rightToLeft") {
+ outNum = this.numMapping.indexOf(inpNum);
+ }
+ const outPos = this.posMapping.indexOf(outNum);
+ return outPos;
+ }
+
+ /**
+ * Steps the rotor. The number at position 0 will be moved to position 1 etc.
+ */
+ step() {
+ const lastNum = this.posMapping.pop();
+ this.posMapping.splice(0, 0, lastNum);
+ this.state = this.posMapping[0];
+ }
+
+}
+
+/**
+ * A CRRotor is a cipher (C) or control (R) rotor. These rotors are identical and interchangeable. A C or R rotor consists of 26 contacts, one for each letter, and may be put into either a forwards of reversed orientation.
+ */
+export class CRRotor extends Rotor {
+
+ /**
+ * CRRotor constructor
+ *
+ * @param {string} wireSetting - the rotor wirings (string of letters)
+ * @param {char} key - initial state of rotor
+ * @param {bool} rev - true if reversed, false if not
+ * An IRotor is an index rotor, which consists of 10 contacts each numbered from 0 to 9. Unlike C and R rotors, they cannot be put in the reversed orientation. The index rotors do not step at any point during encryption or decryption.
+ */
+export class IRotor extends Rotor {
+
+ /**
+ * IRotor constructor
+ *
+ * @param {string} wireSetting - the rotor wirings (string of numbers)