diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 451186bd..00000000 --- a/.babelrc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "presets": [ - ["@babel/preset-env", { - "targets": { - "chrome": 40, - "firefox": 35, - "edge": 14, - "node": "6.5" - }, - "modules": false, - "useBuiltIns": "entry" - }] - ], - "plugins": [ - ["babel-plugin-transform-builtin-extend", { - "globals": ["Error"] - }] - ] -} diff --git a/CHANGELOG.md b/CHANGELOG.md index 875244b9..87a81bdd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog -All notable changes to CyberChef will be documented in this file. +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.12.0] - 2018-11-21 +- 'Citrix CTX1 Encode' and 'Citrix CTX1 Decode' operations added [@bwhitn] | [#428] ### [8.11.0] - 2018-11-13 - 'CSV to JSON' and 'JSON to CSV' operations added [@n1474335] | [#277] @@ -52,7 +55,7 @@ All notable changes to CyberChef will be documented in this file. - Added support for loading, processing and downloading files up to 500MB [@n1474335] | [#224] ## [6.0.0] - 2017-09-19 -- Threading support added. All recipe processing moved into a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) to increase performance and allowing long-running operations to be cancelled [@n1474335] | [#173] +- Threading support added. All recipe processing moved into a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) to increase performance and to allow long-running operations to be cancelled [@n1474335] | [#173] - Module system created so that operations relying on large libraries can be downloaded separately as required, reducing the initial loading time for the app [@n1474335] | [#173] ## [5.0.0] - 2017-03-30 @@ -62,6 +65,11 @@ All notable changes to CyberChef will be documented in this file. - Initial open source commit [@n1474335] | [b1d73a72](https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306) + +[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 +[8.9.0]: https://github.com/gchq/CyberChef/releases/tag/v8.9.0 [8.8.0]: https://github.com/gchq/CyberChef/releases/tag/v8.8.0 [8.7.0]: https://github.com/gchq/CyberChef/releases/tag/v8.7.0 [8.6.0]: https://github.com/gchq/CyberChef/releases/tag/v8.6.0 @@ -87,6 +95,7 @@ All notable changes to CyberChef will be documented in this file. [@PenguinGeorge]: https://github.com/PenguinGeorge [@arnydo]: https://github.com/arnydo [@klaxon1]: https://github.com/klaxon1 +[@bwhitn]: https://github.com/bwhitn [#95]: https://github.com/gchq/CyberChef/pull/299 [#173]: https://github.com/gchq/CyberChef/pull/173 @@ -109,3 +118,4 @@ All notable changes to CyberChef will be documented in this file. [#351]: https://github.com/gchq/CyberChef/pull/351 [#387]: https://github.com/gchq/CyberChef/pull/387 [#394]: https://github.com/gchq/CyberChef/pull/394 +[#428]: https://github.com/gchq/CyberChef/pull/428 diff --git a/Gruntfile.js b/Gruntfile.js index 4b433146..c109b45a 100755 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -144,7 +144,7 @@ module.exports = function (grunt) { options: { configFile: "./.eslintrc.json" }, - configs: ["Gruntfile.js"], + configs: ["*.js"], core: ["src/core/**/*.{js,mjs}", "!src/core/vendor/**/*", "!src/core/operations/legacy/**/*"], web: ["src/web/**/*.{js,mjs}"], node: ["src/node/**/*.{js,mjs}"], diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 00000000..e25f9da1 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,24 @@ +module.exports = function(api) { + api.cache.forever(); + + return { + "presets": [ + ["@babel/preset-env", { + "targets": { + "chrome": 40, + "firefox": 35, + "edge": 14, + "safari": 11, + "node": "6.5" + }, + "modules": false, + "useBuiltIns": "entry" + }] + ], + "plugins": [ + ["babel-plugin-transform-builtin-extend", { + "globals": ["Error"] + }] + ] + }; +}; diff --git a/package-lock.json b/package-lock.json index c79682e8..855dbed9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "cyberchef", - "version": "8.11.2", + "version": "8.12.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 81a96c5e..096101d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cyberchef", - "version": "8.11.2", + "version": "8.12.1", "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.", "author": "n1474335 ", "homepage": "https://gchq.github.io/CyberChef", diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index ee638893..4fac84c9 100755 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -95,6 +95,8 @@ "JWT Sign", "JWT Verify", "JWT Decode", + "Citrix CTX1 Encode", + "Citrix CTX1 Decode", "Pseudo-Random Number Generator" ] }, diff --git a/src/core/operations/CitrixCTX1Decode.mjs b/src/core/operations/CitrixCTX1Decode.mjs new file mode 100644 index 00000000..31c20ee9 --- /dev/null +++ b/src/core/operations/CitrixCTX1Decode.mjs @@ -0,0 +1,58 @@ +/** + * @author bwhitn [brian.m.whitney@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import OperationError from "../errors/OperationError"; +import cptable from "../vendor/js-codepage/cptable.js"; + +/** + * Citrix CTX1 Decode operation + */ +class CitrixCTX1Decode extends Operation { + + /** + * CitrixCTX1Decode constructor + */ + constructor() { + super(); + + this.name = "Citrix CTX1 Decode"; + this.module = "Encodings"; + this.description = "Decodes strings in a Citrix CTX1 password format to plaintext."; + this.infoURL = "https://www.reddit.com/r/AskNetsec/comments/1s3r6y/citrix_ctx1_hash_decoding/"; + this.inputType = "byteArray"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + if (input.length % 4 !== 0) { + throw new OperationError("Incorrect hash length"); + } + const revinput = input.reverse(); + const result = []; + let temp = 0; + for (let i = 0; i < revinput.length; i += 2) { + if (i + 2 >= revinput.length) { + temp = 0; + } else { + temp = ((revinput[i + 2] - 0x41) & 0xf) ^ (((revinput[i + 3]- 0x41) << 4) & 0xf0); + } + temp = (((revinput[i] - 0x41) & 0xf) ^ (((revinput[i + 1] - 0x41) << 4) & 0xf0)) ^ 0xa5 ^ temp; + result.push(temp); + } + // Decodes a utf-16le string + return cptable.utils.decode(1200, result.reverse()); + } + +} + +export default CitrixCTX1Decode; diff --git a/src/core/operations/CitrixCTX1Encode.mjs b/src/core/operations/CitrixCTX1Encode.mjs new file mode 100644 index 00000000..add563d8 --- /dev/null +++ b/src/core/operations/CitrixCTX1Encode.mjs @@ -0,0 +1,50 @@ +/** + * @author bwhitn [brian.m.whitney@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import cptable from "../vendor/js-codepage/cptable.js"; + +/** + * Citrix CTX1 Encode operation + */ +class CitrixCTX1Encode extends Operation { + + /** + * CitrixCTX1Encode constructor + */ + constructor() { + super(); + + this.name = "Citrix CTX1 Encode"; + this.module = "Encodings"; + this.description = "Encodes strings to Citrix CTX1 password format."; + this.infoURL = "https://www.reddit.com/r/AskNetsec/comments/1s3r6y/citrix_ctx1_hash_decoding/"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const utf16pass = Array.from(cptable.utils.encode(1200, input)); + const result = []; + let temp = 0; + for (let i = 0; i < utf16pass.length; i++) { + temp = utf16pass[i] ^ 0xa5 ^ temp; + result.push(((temp >>> 4) & 0xf) + 0x41); + result.push((temp & 0xf) + 0x41); + } + + return result; + } + +} + +export default CitrixCTX1Encode; diff --git a/test/tests/operations/Ciphers.mjs b/test/tests/operations/Ciphers.mjs index 553216ef..fdc98a3a 100644 --- a/test/tests/operations/Ciphers.mjs +++ b/test/tests/operations/Ciphers.mjs @@ -220,6 +220,39 @@ TestRegister.addTests([ } ], }, + { + name: "Citrix CTX1 Encode", + input: "Password1", + expectedOutput: "PFFAJEDBOHECJEDBODEGIMCJPOFLJKDPKLAO", + recipeConfig: [ + { + "op": "Citrix CTX1 Encode", + "args": [] + } + ], + }, + { + name: "Citrix CTX1 Decode: normal", + input: "PFFAJEDBOHECJEDBODEGIMCJPOFLJKDPKLAO", + expectedOutput: "Password1", + recipeConfig: [ + { + "op": "Citrix CTX1 Decode", + "args": [] + } + ], + }, + { + name: "Citrix CTX1 Decode: invalid length", + input: "PFFAJEDBOHECJEDBODEGIMCJPOFLJKDPKLA", + expectedOutput: "Incorrect hash length", + recipeConfig: [ + { + "op": "Citrix CTX1 Decode", + "args": [] + } + ], + }, { name: "Vigenère Encode: no input", input: "", diff --git a/webpack.config.js b/webpack.config.js index f05586f0..8c3da50f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,5 +1,6 @@ const webpack = require("webpack"); const ExtractTextPlugin = require("extract-text-webpack-plugin"); +const path = require("path"); /** * Webpack configuration details for use with Grunt. @@ -58,13 +59,13 @@ module.exports = { { test: /\.m?js$/, exclude: /node_modules\/(?!jsesc|crypto-api)/, + options: { + configFile: path.resolve(__dirname, "babel.config.js"), + cacheDirectory: true, + compact: false + }, type: "javascript/auto", - loader: "babel-loader?compact=false", - query: { - presets: [ - require.resolve("@babel/preset-env"), - ] - } + loader: "babel-loader", }, { test: /forge.min.js$/,