From 5318bab19fe842a0696a40317c779d105e7df16c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 09:40:18 +0100 Subject: [PATCH 1/7] chore (deps): bump nginxinc/nginx-unprivileged from `df0e9ed` to `0a1e718` in the docker-dependencies group (#2498) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 864f1606..6e6ee6f6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN npm run build ######################################### # Package static build files into nginx # ######################################### -FROM nginxinc/nginx-unprivileged:stable-alpine@sha256:df0e9edf92b8436ff797fe5a2cbfc66be1df775c113d322ccadf5c7f3100eda8 AS cyberchef +FROM nginxinc/nginx-unprivileged:stable-alpine@sha256:0a1e718ff1e1a22fc519d0c2e5b6872681f01e37c8a2817ec43ce6e716103929 AS cyberchef LABEL maintainer="GCHQ " From 8a5c60ac74d445073ca012bdcf118281098155ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 09:47:23 +0100 Subject: [PATCH 2/7] chore (deps): bump the patch-updates group with 2 updates (#2499) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 16 ++++++++-------- package.json | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 134641ce..f3e9e881 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,7 @@ "d3": "7.9.0", "d3-hexbin": "^0.2.2", "diff": "^5.2.2", - "dompurify": "^3.4.6", + "dompurify": "^3.4.7", "es6-promisify": "^7.0.0", "escodegen": "^2.1.0", "esprima": "^4.0.1", @@ -85,7 +85,7 @@ "path": "^0.12.7", "popper.js": "^1.16.1", "process": "^0.11.10", - "protobufjs": "^7.6.1", + "protobufjs": "^7.6.2", "punycode.js": "^2.3.1", "qr-image": "^3.2.0", "reflect-metadata": "^0.2.2", @@ -8620,9 +8620,9 @@ } }, "node_modules/dompurify": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.6.tgz", - "integrity": "sha512-+7gzEI8trIIQkVCvQ3ucGtNfH3nOmDgVTzc62rAAOlMxLth78pwpPoZCPc7CyRzAQF89MqcfPdEWkDwnjgqktg==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.7.tgz", + "integrity": "sha512-2jBxDJY4RR06tQNy4w5FlFH7kfxsQZlufd0sbv+chfHCxeJwrFw2baUDsSwvBISD4K4RDbd0PTfy3uNXsR6siA==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -15101,9 +15101,9 @@ "license": "MIT" }, "node_modules/protobufjs": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.1.tgz", - "integrity": "sha512-4K0myLaWL5EteuSAro91EGFgcfVgxb64Jx+7oDAY6GOkXD4M69yuSEljNcInGVCA5sOPxmZ/EqDLj2x0Q0+Ygg==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.2.tgz", + "integrity": "sha512-N9EiLovGEQOJSPF26Ij7qUGvahfEnq0eeYZ02aigIedkmz1qZSwjnP9SBITHJuF/6MYbIW4HDN8zdYjsjqJKXQ==", "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { diff --git a/package.json b/package.json index d7d1b48a..6faf49f3 100644 --- a/package.json +++ b/package.json @@ -123,7 +123,7 @@ "d3": "7.9.0", "d3-hexbin": "^0.2.2", "diff": "^5.2.2", - "dompurify": "^3.4.6", + "dompurify": "^3.4.7", "es6-promisify": "^7.0.0", "escodegen": "^2.1.0", "esprima": "^4.0.1", @@ -169,7 +169,7 @@ "path": "^0.12.7", "popper.js": "^1.16.1", "process": "^0.11.10", - "protobufjs": "^7.6.1", + "protobufjs": "^7.6.2", "punycode.js": "^2.3.1", "qr-image": "^3.2.0", "reflect-metadata": "^0.2.2", From 3034d63f90f3e2d5b3079fc7f4f0d774131b05f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 10:26:43 +0100 Subject: [PATCH 3/7] chore (deps): bump the minor-updates group with 5 updates (#2500) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: GCHQDeveloper581 <63102987+GCHQDeveloper581@users.noreply.github.com> (removed jq-web update, and added it to dependabot.yml block list) --- .github/dependabot.yml | 2 ++ package-lock.json | 77 +++++++++++++++++++++++------------------- package.json | 8 ++--- 3 files changed, 48 insertions(+), 39 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ded5077c..16cd1c3a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -41,6 +41,8 @@ updates: versions: [ '>=2.0.0' ] - dependency-name: 'jimp' versions: [ '1.6.1' ] + - dependency-name: 'jq-web' + versions: [ '>=0.6.0' ] groups: # # Grouping so patch version updates are batched together in a single PR diff --git a/package-lock.json b/package-lock.json index f3e9e881..623c8440 100644 --- a/package-lock.json +++ b/package-lock.json @@ -58,7 +58,7 @@ "js-sha3": "^0.9.3", "jsesc": "^3.1.0", "json5": "^2.2.3", - "jsonata": "^2.1.0", + "jsonata": "^2.2.1", "jsonpath-plus": "^10.4.0", "jsonwebtoken": "9.0.3", "jsqr": "^1.4.0", @@ -71,7 +71,7 @@ "loglevel-message-prefix": "^3.0.0", "lz-string": "^1.5.0", "lz4js": "^0.2.0", - "markdown-it": "^14.1.1", + "markdown-it": "^14.2.0", "moment": "^2.30.1", "moment-timezone": "^0.6.2", "ngeohash": "^0.6.3", @@ -109,7 +109,7 @@ "zlibjs": "^0.3.1" }, "devDependencies": { - "@babel/eslint-parser": "^7.28.6", + "@babel/eslint-parser": "^7.29.7", "@babel/plugin-syntax-import-assertions": "^7.28.6", "@babel/plugin-transform-runtime": "^7.29.7", "@babel/preset-env": "^7.29.7", @@ -149,7 +149,7 @@ "imports-loader": "^5.0.0", "mini-css-extract-plugin": "2.10.2", "modify-source-webpack-plugin": "^4.1.0", - "nightwatch": "^3.15.0", + "nightwatch": "^3.16.0", "postcss": "^8.5.15", "postcss-css-variables": "^0.19.0", "postcss-import": "^16.1.1", @@ -279,9 +279,9 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.28.6.tgz", - "integrity": "sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.29.7.tgz", + "integrity": "sha512-zxt+UJTOMKvUt3yOg+D58MLuz334pHp93qifMFcjIIO+9hN6t+ufw2gi7vDPMpxvfnHRR+3VVXvIjineCcgyXw==", "dev": true, "license": "MIT", "dependencies": { @@ -12413,9 +12413,9 @@ } }, "node_modules/jsonata": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.1.0.tgz", - "integrity": "sha512-OCzaRMK8HobtX8fp37uIVmL8CY1IGc/a6gLsDqz3quExFR09/U78HUzWYr7T31UEB6+Eu0/8dkVD5fFDOl9a8w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.2.1.tgz", + "integrity": "sha512-xd1uwUrKeIcJbsWhaoS3qAX4Ea8m0Mw0G5nlnAQvPT7TbZ5qaPdzBVTQia9KfyuyQm+nenfyjvzUDTRYHsC2sw==", "license": "MIT", "engines": { "node": ">= 8" @@ -12683,9 +12683,19 @@ "license": "MIT" }, "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz", + "integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], "license": "MIT", "dependencies": { "uc.micro": "^2.0.0" @@ -13002,14 +13012,24 @@ } }, "node_modules/markdown-it": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", - "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz", + "integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", - "linkify-it": "^5.0.0", + "linkify-it": "^5.0.1", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" @@ -13557,9 +13577,9 @@ } }, "node_modules/nightwatch": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-3.15.0.tgz", - "integrity": "sha512-Vvh7TsDyEN1YzOsDNoafEUPJDQ6jfnmJPAsWo/EmygljZiRk1Ja/pEqNAhE5UdYJzF38SNO46gJS8IRk9mUNfA==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-3.16.0.tgz", + "integrity": "sha512-B0/zFPY5ujEwIWIPqo2ClgITZ3chB3Nfq86YNWCyE3/P8BrCSvv2Y6BNUA+9mgu8WM/XF6GNlV3LONzZ1S+JSQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13584,7 +13604,7 @@ "glob": "7.2.3", "jsdom": "^24.1.0", "lodash": "^4.17.21", - "minimatch": "3.1.2", + "minimatch": "3.1.5", "minimist": "1.2.6", "mocha": "10.8.2", "nightwatch-axe-verbose": "^2.3.0", @@ -13602,7 +13622,7 @@ "nightwatch": "bin/nightwatch" }, "engines": { - "node": ">= 16" + "node": ">= 18.20.5" }, "peerDependencies": { "@cucumber/cucumber": "*" @@ -13681,19 +13701,6 @@ "node": ">=10" } }, - "node_modules/nightwatch/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/nightwatch/node_modules/minimist": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", diff --git a/package.json b/package.json index 6faf49f3..8a82b685 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "node >= 24" ], "devDependencies": { - "@babel/eslint-parser": "^7.28.6", + "@babel/eslint-parser": "^7.29.7", "@babel/plugin-syntax-import-assertions": "^7.28.6", "@babel/plugin-transform-runtime": "^7.29.7", "@babel/preset-env": "^7.29.7", @@ -79,7 +79,7 @@ "imports-loader": "^5.0.0", "mini-css-extract-plugin": "2.10.2", "modify-source-webpack-plugin": "^4.1.0", - "nightwatch": "^3.15.0", + "nightwatch": "^3.16.0", "postcss": "^8.5.15", "postcss-css-variables": "^0.19.0", "postcss-import": "^16.1.1", @@ -142,7 +142,7 @@ "js-sha3": "^0.9.3", "jsesc": "^3.1.0", "json5": "^2.2.3", - "jsonata": "^2.1.0", + "jsonata": "^2.2.1", "jsonpath-plus": "^10.4.0", "jsonwebtoken": "9.0.3", "jsqr": "^1.4.0", @@ -155,7 +155,7 @@ "loglevel-message-prefix": "^3.0.0", "lz-string": "^1.5.0", "lz4js": "^0.2.0", - "markdown-it": "^14.1.1", + "markdown-it": "^14.2.0", "moment": "^2.30.1", "moment-timezone": "^0.6.2", "ngeohash": "^0.6.3", From 20b46bf1a0a788fbb9bd095ed45e3bb2e1d548f8 Mon Sep 17 00:00:00 2001 From: Syed Ishmum Ahnaf Date: Fri, 5 Jun 2026 15:47:48 +0600 Subject: [PATCH 4/7] fix: validate text encoding options (#2497) --- src/core/operations/DecodeText.mjs | 4 ++++ src/core/operations/EncodeText.mjs | 4 ++++ tests/operations/tests/CharEnc.mjs | 26 ++++++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/src/core/operations/DecodeText.mjs b/src/core/operations/DecodeText.mjs index 0fc9d2b5..baf23336 100644 --- a/src/core/operations/DecodeText.mjs +++ b/src/core/operations/DecodeText.mjs @@ -5,6 +5,7 @@ */ import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; import cptable from "codepage"; import {CHR_ENC_CODE_PAGES} from "../lib/ChrEnc.mjs"; @@ -48,6 +49,9 @@ class DecodeText extends Operation { */ run(input, args) { const format = CHR_ENC_CODE_PAGES[args[0]]; + if (!format) { + throw new OperationError("Invalid encoding"); + } return cptable.utils.decode(format, new Uint8Array(input)); } diff --git a/src/core/operations/EncodeText.mjs b/src/core/operations/EncodeText.mjs index 8cc1450f..5cc09742 100644 --- a/src/core/operations/EncodeText.mjs +++ b/src/core/operations/EncodeText.mjs @@ -5,6 +5,7 @@ */ import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; import cptable from "codepage"; import {CHR_ENC_CODE_PAGES} from "../lib/ChrEnc.mjs"; @@ -48,6 +49,9 @@ class EncodeText extends Operation { */ run(input, args) { const format = CHR_ENC_CODE_PAGES[args[0]]; + if (!format) { + throw new OperationError("Invalid encoding"); + } const encoded = cptable.utils.encode(format, input); return new Uint8Array(encoded).buffer; } diff --git a/tests/operations/tests/CharEnc.mjs b/tests/operations/tests/CharEnc.mjs index eecfaab6..83f71ca9 100644 --- a/tests/operations/tests/CharEnc.mjs +++ b/tests/operations/tests/CharEnc.mjs @@ -68,6 +68,32 @@ TestRegister.addTests([ }, ], }, + { + name: "Encode text: empty encoding", + input: "hello", + expectedOutput: "Invalid encoding", + recipeConfig: [ + { + "op": "Encode text", + "args": [""] + }, + ], + }, + { + name: "Decode text: empty encoding", + input: "68 65 6c 6c 6f", + expectedOutput: "Invalid encoding", + recipeConfig: [ + { + "op": "From Hex", + "args": ["Space"] + }, + { + "op": "Decode text", + "args": [""] + }, + ], + }, { name: "Generate Base64 Windows PowerShell", input: "ZABpAHIAIAAiAGMAOgBcAHAAcgBvAGcAcgBhAG0AIABmAGkAbABlAHMAIgAgAA==", From da202d54f160fb07728f7070b4eccd1b765543cb Mon Sep 17 00:00:00 2001 From: andreas Date: Fri, 5 Jun 2026 12:23:38 +0200 Subject: [PATCH 5/7] feat: Get AES IV from input (QoL) (#2471) --- src/core/operations/AESDecrypt.mjs | 77 ++++-- src/core/operations/AESEncrypt.mjs | 37 ++- tests/browser/02_ops.js | 4 +- tests/node/tests/operations.mjs | 39 ++++ tests/operations/tests/Crypt.mjs | 350 +++++++++++++++++++++++----- tests/operations/tests/Register.mjs | 4 +- 6 files changed, 419 insertions(+), 92 deletions(-) diff --git a/src/core/operations/AESDecrypt.mjs b/src/core/operations/AESDecrypt.mjs index 5e6cec26..44e6cab2 100644 --- a/src/core/operations/AESDecrypt.mjs +++ b/src/core/operations/AESDecrypt.mjs @@ -39,41 +39,46 @@ class AESDecrypt extends Operation { "value": "", "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"] }, + { + "name": "IV Length", + "type": "number", + "value": 16 + }, { "name": "Mode", "type": "argSelector", "value": [ { name: "CBC", - off: [5, 6] + off: [6, 7] }, { name: "CFB", - off: [5, 6] + off: [6, 7] }, { name: "OFB", - off: [5, 6] + off: [6, 7] }, { name: "CTR", - off: [5, 6] + off: [6, 7] }, { name: "GCM", - on: [5, 6] + on: [6, 7] }, { name: "ECB", - off: [5, 6] + off: [6, 7] }, { name: "CBC/NoPadding", - off: [5, 6] + off: [6, 7] }, { name: "ECB/NoPadding", - off: [5, 6] + off: [6, 7] } ] }, @@ -98,6 +103,26 @@ class AESDecrypt extends Operation { "type": "toggleString", "value": "", "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"] + }, + { + "name": "IV from input", + "type": "argSelector", + "value": [ + { + name: "Off", + on: [1], + off: [2] + }, + { + name: "From start", + on: [2], + off: [1] + }, { + name: "From end", + on: [2], + off: [1] + } + ] } ]; } @@ -110,14 +135,18 @@ class AESDecrypt extends Operation { * @throws {OperationError} if cannot decrypt input or invalid key length */ run(input, args) { + let iv; + const key = Utils.convertToByteString(args[0].string, args[0].option), - iv = Utils.convertToByteString(args[1].string, args[1].option), - mode = args[2].split("/")[0], - noPadding = args[2].endsWith("NoPadding"), - inputType = args[3], - outputType = args[4], - gcmTag = Utils.convertToByteString(args[5].string, args[5].option), - aad = Utils.convertToByteString(args[6].string, args[6].option); + ivLength = args[2], + mode = args[3].split("/")[0], + noPadding = args[3].endsWith("NoPadding"), + inputType = args[4], + outputType = args[5], + gcmTag = Utils.convertToByteString(args[6].string, args[6].option), + aad = Utils.convertToByteString(args[7].string, args[7].option), + ivFromInput = args[8]; + if ([16, 24, 32].indexOf(key.length) < 0) { throw new OperationError(`Invalid key length: ${key.length} bytes @@ -130,11 +159,27 @@ The following algorithms will be used based on the size of the key: input = Utils.convertToByteString(input, inputType); + if (ivFromInput !== "Off") { + if (input.length <= ivLength) { + throw new OperationError(`Input is too short to contain an IV of ${ivLength} bytes.`); + } + + if (ivFromInput === "From start") { + iv = input.substr(0, ivLength); + input = input.substr(ivLength); + } else { + iv = input.substr(input.length - ivLength); + input = input.substr(0, input.length - ivLength); + } + } else { + iv = Utils.convertToByteString(args[1].string, args[1].option); + } + const decipher = forge.cipher.createDecipher("AES-" + mode, key); /* Allow for a "no padding" mode */ if (noPadding) { - decipher.mode.unpad = function(output, options) { + decipher.mode.unpad = function (output, options) { return true; }; } diff --git a/src/core/operations/AESEncrypt.mjs b/src/core/operations/AESEncrypt.mjs index 84e1c540..8a1c25de 100644 --- a/src/core/operations/AESEncrypt.mjs +++ b/src/core/operations/AESEncrypt.mjs @@ -8,6 +8,7 @@ import Operation from "../Operation.mjs"; import Utils from "../Utils.mjs"; import forge from "node-forge"; import OperationError from "../errors/OperationError.mjs"; +import { toHexFast } from "../lib/Hex.mjs"; /** * AES Encrypt operation @@ -92,6 +93,11 @@ class AESEncrypt extends Operation { "type": "toggleString", "value": "", "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"] + }, + { + "name": "Include IV in output", + "type": "option", + "value": ["Off", "Prepend", "Append"] } ]; } @@ -107,10 +113,11 @@ class AESEncrypt extends Operation { const key = Utils.convertToByteString(args[0].string, args[0].option), iv = Utils.convertToByteString(args[1].string, args[1].option), mode = args[2].split("/")[0], - noPadding = args[2].endsWith("NoPadding"), + noPadding = args[2].endsWith("NoPadding"), inputType = args[3], outputType = args[4], - aad = Utils.convertToByteString(args[5].string, args[5].option); + aad = Utils.convertToByteString(args[5].string, args[5].option), + includeIV = args[6]; if ([16, 24, 32].indexOf(key.length) < 0) { throw new OperationError(`Invalid key length: ${key.length} bytes @@ -133,26 +140,34 @@ The following algorithms will be used based on the size of the key: additionalData: mode === "GCM" ? aad : undefined }); if (noPadding) { - cipher.mode.pad = function(output, options) { + cipher.mode.pad = function (output, options) { return true; }; } cipher.update(forge.util.createBuffer(input)); cipher.finish(); + let output = cipher.output.getBytes(); + + if (includeIV === "Prepend") { + output = iv + output; + } else if (includeIV === "Append") { + output = output + iv; + } + if (outputType === "Hex") { + output = toHexFast(Utils.strToByteArray(output)); + if (mode === "GCM") { - return cipher.output.toHex() + "\n\n" + + return output + "\n\n" + "Tag: " + cipher.mode.tag.toHex(); } - return cipher.output.toHex(); - } else { - if (mode === "GCM") { - return cipher.output.getBytes() + "\n\n" + - "Tag: " + cipher.mode.tag.getBytes(); - } - return cipher.output.getBytes(); + } else if (mode === "GCM") { + return output + "\n\n" + + "Tag: " + cipher.mode.tag.getBytes(); } + + return output; } } diff --git a/tests/browser/02_ops.js b/tests/browser/02_ops.js index 9d29f50d..32bd14d6 100644 --- a/tests/browser/02_ops.js +++ b/tests/browser/02_ops.js @@ -30,8 +30,8 @@ module.exports = { testOp(browser, "A1Z26 Cipher Decode", "20 5 19 20 15 21 20 16 21 20", "testoutput"); testOp(browser, "A1Z26 Cipher Encode", "test input", "20 5 19 20 9 14 16 21 20"); testOp(browser, "ADD", "test input", "Ê»ÉÊv¿ÄÆËÊ", [{ "option": "Hex", "string": "56" }]); - testOp(browser, "AES Decrypt", "b443f7f7c16ac5396a34273f6f639caa", "test output", [{ "option": "Hex", "string": "00112233445566778899aabbccddeeff" }, { "option": "Hex", "string": "00000000000000000000000000000000" }, "CBC", "Hex", "Raw", { "option": "Hex", "string": "" }]); - testOp(browser, "AES Encrypt", "test input", "e42eb8fbfb7a98fff061cd2c1a794d92", [{"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00000000000000000000000000000000"}, "CBC", "Raw", "Hex"]); + testOp(browser, "AES Decrypt", "b443f7f7c16ac5396a34273f6f639caa", "test output", [{ "option": "Hex", "string": "00112233445566778899aabbccddeeff" }, { "option": "Hex", "string": "00000000000000000000000000000000" }, 16, "CBC", "Hex", "Raw", { "option": "Hex", "string": "" }, { "option": "Hex", "string": "" }, "Off"]); + testOp(browser, "AES Encrypt", "test input", "e42eb8fbfb7a98fff061cd2c1a794d92", [{"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00000000000000000000000000000000"}, "CBC", "Raw", "Hex", "Off"]); testOp(browser, "AND", "test input", "4$04 $044", [{ "option": "Hex", "string": "34" }]); testOp(browser, "Add line numbers", "test input", "1 test input"); testOp(browser, ["From Hex", "Add Text To Image", "SHA2"], Images.PNG_HEX, "50cdf8ea483c55564a091650c2bccb4586f919b721e5fe9d6a61660505b4346d6ebdb2ef0cf075a7728cd84cb26ea3e477b5bd86a94a49a27d79423994afb60a", [[], ["Chef", "Center", "Middle", 0, 0, 16, "Roboto"], []]); diff --git a/tests/node/tests/operations.mjs b/tests/node/tests/operations.mjs index 3b2bbda6..6cf85718 100644 --- a/tests/node/tests/operations.mjs +++ b/tests/node/tests/operations.mjs @@ -79,7 +79,46 @@ TestRegister.addApiTests([ string: "some iv some iv1", option: "utf8", }, + ivLength: 16, mode: "OFB", + inputType: "Hex", + outputType: "Raw", + gcmTag: { + option: "Hex", + string: "" + }, + aad: { + option: "Hex", + string: "" + }, + ivFromInput: "Off" + }); + assert.equal(result.toString(), "a slightly longer sampleinput?"); + }), + + it("AES decrypt: IV from input", () => { + const result = AESDecrypt("4a123af235a507bbc9d5871721d61b98504d569a9a5a7847e2d78315fec7736f6d6520697620736f6d6520697631", { + key: { + string: "some longer key1", + option: "utf8", + }, + iv: { + string: "", + option: "Hex", + }, + ivLength: 16, + mode: "OFB", + inputType: "Hex", + outputType: "Raw", + gcmTag: { + option: "Hex", + string: "" + }, + aad: { + option: "Hex", + string: "" + }, + ivFromInput: "From end" }); assert.equal(result.toString(), "a slightly longer sampleinput?"); }), diff --git a/tests/operations/tests/Crypt.mjs b/tests/operations/tests/Crypt.mjs index 504f64b9..18b1c6e5 100644 --- a/tests/operations/tests/Crypt.mjs +++ b/tests/operations/tests/Crypt.mjs @@ -74,7 +74,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": ""}, {"option": "Hex", "string": ""}, "CBC", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -90,7 +91,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00000000000000000000000000000000"}, "CBC", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -106,7 +108,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00000000000000000000000000000000"}, "CTR", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -122,7 +125,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, "CBC", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -138,7 +142,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, "CFB", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -154,7 +159,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, "OFB", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -170,7 +176,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, "CTR", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -186,7 +193,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": ""}, "ECB", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -204,7 +212,8 @@ Tag: 16a3e732a605cc9ca29108f742ca0743`, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": ""}, "GCM", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -222,7 +231,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "ffeeddccbbaa99887766554433221100"}, "GCM", "Raw", "Hex", - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -238,7 +248,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`, {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CBC", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -254,7 +265,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`, {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CFB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -270,7 +282,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`, {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "OFB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -286,7 +299,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`, {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CTR", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -304,7 +318,8 @@ Tag: 70fad2ca19412c20f40fd06918736e56`, {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "GCM", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -322,7 +337,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`, {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "GCM", "Hex", "Hex", - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -338,7 +354,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`, {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "ECB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -354,7 +371,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`, {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CBC", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -370,7 +388,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`, {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CFB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -386,7 +405,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`, {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "OFB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -402,7 +422,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`, {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CTR", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -420,7 +441,8 @@ Tag: 86db597d5302595223cadbd990f1309b`, {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "GCM", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -438,7 +460,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`, {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "GCM", "Hex", "Hex", - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -454,7 +477,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`, {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "ECB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -470,7 +494,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`, {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CBC", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -486,7 +511,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`, {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CFB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -502,7 +528,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`, {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "OFB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -518,7 +545,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`, {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CTR", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -536,7 +564,8 @@ Tag: 821b1e5f32dad052e502775a523d957a`, {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "GCM", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -554,7 +583,8 @@ Tag: a8f04c4d93bbef82bef61a103371aef9`, {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "GCM", "Hex", "Hex", - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -570,7 +600,46 @@ Tag: a8f04c4d93bbef82bef61a103371aef9`, {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "ECB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" + ] + } + ], + }, + { + name: "AES Encrypt: AES-256-GCM, Binary, AAD, prepend IV to output", + input: "7a0e643132750e96d805d11e9e48e281fa39a41039286423cc1c045e5442b40bf1c3f2822bded3f9c8ef11cb25da64dda9c7ab87c246bd305385150c98f31465c2a6180fe81d31ea289b916504d5a12e1de26cb10adba84a0cb0c86f94bc14bc554f3018", + expectedOutput: `1748e7179bd56570d51fa4ba287cc3e51287f188ad4d7ab0d9ff69b3c29cb11f861389532d8cb9337181da2e8cfc74a84927e8c0dd7a28a32fd485afe694259a63c199b199b95edd87c7aa95329feac340f2b78b72956a85f367044d821766b1b7135815571df44900695f1518cf3ae38ecb650f + +Tag: a8f04c4d93bbef82bef61a103371aef9`, + recipeConfig: [ + { + "op": "AES Encrypt", + "args": [ + {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, + {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + "GCM", "Hex", "Hex", + {"option": "UTF8", "string": "additional data"}, + "Prepend" + ] + } + ], + }, + { + name: "AES Encrypt: AES-256-GCM, Binary, AAD, append IV to output", + input: "7a0e643132750e96d805d11e9e48e281fa39a41039286423cc1c045e5442b40bf1c3f2822bded3f9c8ef11cb25da64dda9c7ab87c246bd305385150c98f31465c2a6180fe81d31ea289b916504d5a12e1de26cb10adba84a0cb0c86f94bc14bc554f3018", + expectedOutput: `1287f188ad4d7ab0d9ff69b3c29cb11f861389532d8cb9337181da2e8cfc74a84927e8c0dd7a28a32fd485afe694259a63c199b199b95edd87c7aa95329feac340f2b78b72956a85f367044d821766b1b7135815571df44900695f1518cf3ae38ecb650f1748e7179bd56570d51fa4ba287cc3e5 + +Tag: a8f04c4d93bbef82bef61a103371aef9`, + recipeConfig: [ + { + "op": "AES Encrypt", + "args": [ + {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, + {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + "GCM", "Hex", "Hex", + {"option": "UTF8", "string": "additional data"}, + "Append" ] } ], @@ -776,9 +845,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": ""}, {"option": "Hex", "string": ""}, + 16, "CBC", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -793,9 +864,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00000000000000000000000000000000"}, + 16, "CBC", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -810,9 +883,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00000000000000000000000000000000"}, + 16, "CTR", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -827,9 +902,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, + 16, "CBC", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -844,9 +921,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, + 16, "CFB", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -861,9 +940,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, + 16, "OFB", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -878,9 +959,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, + 16, "CTR", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -895,9 +978,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": ""}, + 16, "ECB", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -912,9 +997,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": ""}, + 16, "GCM", "Hex", "Raw", {"option": "Hex", "string": "16a3e732a605cc9ca29108f742ca0743"}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -929,9 +1016,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "ffeeddccbbaa99887766554433221100"}, + 16, "GCM", "Hex", "Raw", {"option": "Hex", "string": "3b5378917f67b0aade9891fc6c291646"}, - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -946,9 +1035,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CBC", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -963,9 +1054,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CFB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -980,9 +1073,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "OFB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -997,9 +1092,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CTR", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1014,9 +1111,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "GCM", "Hex", "Hex", {"option": "Hex", "string": "70fad2ca19412c20f40fd06918736e56"}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1031,9 +1130,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "GCM", "Hex", "Hex", {"option": "Hex", "string": "61cc4b70809452b0b3e38f913fa0a109"}, - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -1048,9 +1149,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "ECB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1065,9 +1168,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CBC", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1082,9 +1187,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CFB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1099,9 +1206,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "OFB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1116,9 +1225,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CTR", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1133,9 +1244,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "GCM", "Hex", "Hex", {"option": "Hex", "string": "86db597d5302595223cadbd990f1309b"}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1150,9 +1263,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "GCM", "Hex", "Hex", {"option": "Hex", "string": "aeedf3e6ca4201577c0cf3e9ce58159d"}, - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -1167,9 +1282,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "ECB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1184,9 +1301,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CBC", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1201,9 +1320,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CFB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1218,9 +1339,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "OFB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1235,9 +1358,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CTR", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1252,9 +1377,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "GCM", "Hex", "Hex", {"option": "Hex", "string": "821b1e5f32dad052e502775a523d957a"}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1269,9 +1396,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "GCM", "Hex", "Hex", {"option": "Hex", "string": "a8f04c4d93bbef82bef61a103371aef9"}, - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -1286,9 +1415,106 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "ECB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" + ] + } + ], + }, + { + name: "AES Decrypt: IV from input, with too short input", + input: "1748e7179bd56570d51fa4ba287cc3e5", + expectedOutput: "Input is too short to contain an IV of 16 bytes.", + recipeConfig: [ + { + "op": "AES Decrypt", + "args": [ + {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, + {"option": "Hex", "string": ""}, + 16, + "ECB", "Hex", "Hex", + {"option": "Hex", "string": ""}, + {"option": "Hex", "string": ""}, + "From start" + ] + } + ], + }, + { + name: "AES Decrypt: AES-256-ECB with IV from input start, Binary", + input: "1748e7179bd56570d51fa4ba287cc3e57e8521ba3f356ef692a51841807e141464aadc07bbc0ef2b628b8745bae356d245682a220688afca7be987b60cb120681ed42680ee93a67065619a3beaac11111a6cd88a6afa9e367722cb57df343f8548f2d691b295184da4ed5f3b763aaa8558502cb348ab58e81986337096e90caa", + expectedOutput: "7a0e643132750e96d805d11e9e48e281fa39a41039286423cc1c045e5442b40bf1c3f2822bded3f9c8ef11cb25da64dda9c7ab87c246bd305385150c98f31465c2a6180fe81d31ea289b916504d5a12e1de26cb10adba84a0cb0c86f94bc14bc554f3018", + recipeConfig: [ + { + "op": "AES Decrypt", + "args": [ + {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, + {"option": "Hex", "string": ""}, + 16, + "ECB", "Hex", "Hex", + {"option": "Hex", "string": ""}, + {"option": "Hex", "string": ""}, + "From start" + ] + } + ], + }, + { + name: "AES Decrypt: AES-256-ECB with IV from input end, Binary", + input: "7e8521ba3f356ef692a51841807e141464aadc07bbc0ef2b628b8745bae356d245682a220688afca7be987b60cb120681ed42680ee93a67065619a3beaac11111a6cd88a6afa9e367722cb57df343f8548f2d691b295184da4ed5f3b763aaa8558502cb348ab58e81986337096e90caa1748e7179bd56570d51fa4ba287cc3e5", + expectedOutput: "7a0e643132750e96d805d11e9e48e281fa39a41039286423cc1c045e5442b40bf1c3f2822bded3f9c8ef11cb25da64dda9c7ab87c246bd305385150c98f31465c2a6180fe81d31ea289b916504d5a12e1de26cb10adba84a0cb0c86f94bc14bc554f3018", + recipeConfig: [ + { + "op": "AES Decrypt", + "args": [ + {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, + {"option": "Hex", "string": ""}, + 16, + "ECB", "Hex", "Hex", + {"option": "Hex", "string": ""}, + {"option": "Hex", "string": ""}, + "From end" + ] + } + ], + }, + { + name: "AES Decrypt: AES-256-GCM with IV from input start, Binary, AAD", + input: "1748e7179bd56570d51fa4ba287cc3e51287f188ad4d7ab0d9ff69b3c29cb11f861389532d8cb9337181da2e8cfc74a84927e8c0dd7a28a32fd485afe694259a63c199b199b95edd87c7aa95329feac340f2b78b72956a85f367044d821766b1b7135815571df44900695f1518cf3ae38ecb650f", + expectedOutput: "7a0e643132750e96d805d11e9e48e281fa39a41039286423cc1c045e5442b40bf1c3f2822bded3f9c8ef11cb25da64dda9c7ab87c246bd305385150c98f31465c2a6180fe81d31ea289b916504d5a12e1de26cb10adba84a0cb0c86f94bc14bc554f3018", + recipeConfig: [ + { + "op": "AES Decrypt", + "args": [ + {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, + {"option": "Hex", "string": ""}, + 16, + "GCM", "Hex", "Hex", + {"option": "Hex", "string": "a8f04c4d93bbef82bef61a103371aef9"}, + {"option": "UTF8", "string": "additional data"}, + "From start" + ] + } + ], + }, + { + name: "AES Decrypt: AES-256-GCM with 12-byte IV from input start, Binary, AAD", + input: "1748e7179bd56570d51fa4ba623c81f4605da9ac3df29c67c43abe4aad5230dca82a98ab31f042fe871b81a0a1e8b8af41044d46f627828e7d11eca2d04ac27f4e7c7c9a20da87854df9868a2ddbd67d85f7db92f9ff1272cfb7955a2d279dbe715965011fddf6e730e79e7b22f89817", + expectedOutput: "7a0e643132750e96d805d11e9e48e281fa39a41039286423cc1c045e5442b40bf1c3f2822bded3f9c8ef11cb25da64dda9c7ab87c246bd305385150c98f31465c2a6180fe81d31ea289b916504d5a12e1de26cb10adba84a0cb0c86f94bc14bc554f3018", + recipeConfig: [ + { + "op": "AES Decrypt", + "args": [ + {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, + {"option": "Hex", "string": ""}, + 12, + "GCM", "Hex", "Hex", + {"option": "Hex", "string": "c311c9144f8ae145ec46e2c69179a4b7"}, + {"option": "UTF8", "string": "additional data"}, + "From start" ] } ], diff --git a/tests/operations/tests/Register.mjs b/tests/operations/tests/Register.mjs index 3ef7ef94..e455f0f8 100644 --- a/tests/operations/tests/Register.mjs +++ b/tests/operations/tests/Register.mjs @@ -59,6 +59,7 @@ TestRegister.addTests([ "option": "Hex", "string": "$R0" }, + 16, "CTR", "Hex", "Raw", { "option": "Hex", @@ -67,7 +68,8 @@ TestRegister.addTests([ { "option": "Hex", "string": "" - } + }, + "Off" ] } ] From c9298191890e46b77479a079523728f261e59653 Mon Sep 17 00:00:00 2001 From: Harel Katz <34490550+HarelKatz@users.noreply.github.com> Date: Fri, 5 Jun 2026 15:44:20 +0300 Subject: [PATCH 6/7] feat: add Escape Smart Characters operation (#2391) --- src/core/config/Categories.json | 1 + src/core/operations/EscapeSmartCharacters.mjs | 129 +++++++++++++++++ tests/operations/index.mjs | 1 + .../tests/EscapeSmartCharacters.mjs | 132 ++++++++++++++++++ 4 files changed, 263 insertions(+) create mode 100644 src/core/operations/EscapeSmartCharacters.mjs create mode 100644 tests/operations/tests/EscapeSmartCharacters.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index dd6918dc..d3e7648a 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -49,6 +49,7 @@ "Escape Unicode Characters", "Unescape Unicode Characters", "Normalise Unicode", + "Escape Smart Characters", "To Quoted Printable", "From Quoted Printable", "To Punycode", diff --git a/src/core/operations/EscapeSmartCharacters.mjs b/src/core/operations/EscapeSmartCharacters.mjs new file mode 100644 index 00000000..39444e94 --- /dev/null +++ b/src/core/operations/EscapeSmartCharacters.mjs @@ -0,0 +1,129 @@ +/** + * @author HarelKatz [github.com/HarelKatz] + * @copyright Crown Copyright 2026 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; + +/** + * Escape Smart Characters operation + */ +class EscapeSmartCharacters extends Operation { + + /** + * EscapeSmartCharacters constructor + */ + constructor() { + super(); + + this.name = "Escape Smart Characters"; + this.module = "Default"; + this.description = "Converts smart (typographic) Unicode characters — e.g. smart quotes, em/en dashes, ellipses, ©, ®, ™, arrows — into their plain ASCII equivalents.

Characters with no ASCII mapping (e.g. ) are handled according to the 'Unmappable characters' option.

e.g. “Hello” — world… becomes \"Hello\" -- world..."; + this.infoURL = ""; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "Unmappable characters", + type: "option", + value: ["Include", "Remove", "Replace with '.'"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [unmappable] = args; + let result = ""; + for (const ch of input) { + if (ch.codePointAt(0) < 128) { + result += ch; + } else if (Object.prototype.hasOwnProperty.call(SMART_MAP, ch)) { + result += SMART_MAP[ch]; + } else { + switch (unmappable) { + case "Remove": + break; + case "Replace with '.'": + result += "."; + break; + case "Include": + default: + result += ch; + break; + } + } + } + return result; + } + +} + +const SMART_MAP = { + // Smart double quotes + "“": "\"", // “ left double quotation mark + "”": "\"", // ” right double quotation mark + "„": "\"", // „ double low-9 quotation mark + "‟": "\"", // ‟ double high-reversed-9 quotation mark + "″": "\"", // ″ double prime + + // Smart single quotes / apostrophes + "‘": "'", // ‘ left single quotation mark + "’": "'", // ’ right single quotation mark / apostrophe + "‚": "'", // ‚ single low-9 quotation mark + "‛": "'", // ‛ single high-reversed-9 quotation mark + "′": "'", // ′ prime + + // Dashes & hyphens + "‐": "-", // ‐ hyphen + "‑": "-", // ‑ non-breaking hyphen + "‒": "-", // ‒ figure dash + "–": "-", // – en dash + "—": "--", // — em dash + "―": "--", // ― horizontal bar + + // Ellipsis + "…": "...", // … + + // Trademark / copyright symbols + "©": "(c)", // © + "®": "(r)", // ® + "™": "(tm)", // ™ + + // Arrows + "←": "<--", // ← + "→": "-->", // → + "↑": "^", // ↑ + "↓": "v", // ↓ + "↔": "<->", // ↔ + "⇐": "<==", // ⇐ + "⇒": "==>", // ⇒ + "⇔": "<=>", // ⇔ + + // Guillemets + "«": "<<", // « + "»": ">>", // » + "‹": "<", // ‹ + "›": ">", // › + + // Math & misc symbols + "×": "x", // × + "÷": "/", // ÷ + "±": "+/-", // ± + "•": "*", // • + "·": ".", // · + + // Non-ASCII spaces + "\u00A0": " ", // NBSP + "\u2002": " ", // en space + "\u2003": " ", // em space + "\u2009": " ", // thin space + "\u200A": " " // hair space +}; + +export default EscapeSmartCharacters; diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index c44270fd..44792560 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -69,6 +69,7 @@ import "./tests/DropNthBytes.mjs"; import "./tests/ECDSA.mjs"; import "./tests/ELFInfo.mjs"; import "./tests/Enigma.mjs"; +import "./tests/EscapeSmartCharacters.mjs"; import "./tests/ExtractAudioMetadata.mjs"; import "./tests/ExtractEmailAddresses.mjs"; import "./tests/ExtractHashes.mjs"; diff --git a/tests/operations/tests/EscapeSmartCharacters.mjs b/tests/operations/tests/EscapeSmartCharacters.mjs new file mode 100644 index 00000000..428c3ad8 --- /dev/null +++ b/tests/operations/tests/EscapeSmartCharacters.mjs @@ -0,0 +1,132 @@ +/** + * Escape Smart Characters tests + * + * @author HarelKatz [github.com/HarelKatz] + * @copyright Crown Copyright 2026 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + "name": "Escape Smart Characters: smart quotes and apostrophes", + "input": "“Hello,” she said, ‘yes.’", + "expectedOutput": "\"Hello,\" she said, 'yes.'", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: em dash, en dash and ellipsis", + "input": "page 1–3 — wait…", + "expectedOutput": "page 1-3 -- wait...", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: trademark symbols", + "input": "Foo© Bar® Baz™", + "expectedOutput": "Foo(c) Bar(r) Baz(tm)", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: arrows and guillemets", + "input": "← → ↔ ⇒ « »", + "expectedOutput": "<-- --> <-> ==> << >>", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: math and misc", + "input": "3 × 4 ÷ 2 = 6, ±0.5 • item", + "expectedOutput": "3 x 4 / 2 = 6, +/-0.5 * item", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: NBSP becomes regular space", + "input": "a b c", + "expectedOutput": "a b c", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: unmappable Include preserves char", + "input": "warning: ☣ hazard", + "expectedOutput": "warning: ☣ hazard", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: unmappable Remove drops char", + "input": "warning: ☣ hazard", + "expectedOutput": "warning: hazard", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Remove"] + } + ] + }, + { + "name": "Escape Smart Characters: unmappable Replace substitutes dot", + "input": "warning: ☣ hazard", + "expectedOutput": "warning: . hazard", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Replace with '.'"] + } + ] + }, + { + "name": "Escape Smart Characters: pure ASCII passes through", + "input": "hello world! 123", + "expectedOutput": "hello world! 123", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: empty input", + "input": "", + "expectedOutput": "", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + } +]); From d735496641493725fbdf64f1c0064296c7f3fdac Mon Sep 17 00:00:00 2001 From: andreas Date: Fri, 5 Jun 2026 21:19:24 +0200 Subject: [PATCH 7/7] Update README to reflect AES Decrypt changes (#2502) --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6da7d3ec..50b1a44d 100755 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ You can use as many operations as you like in simple or complex ways. Some examp - [Carry out different operations on data of different types][8] - [Use parts of the input as arguments to operations][9] - [Perform AES decryption, extracting the IV from the beginning of the cipher stream][10] + - [A simpler way to perform the same AES Decryption][13] - [Automagically detect several layers of nested encoding][12] @@ -147,6 +148,7 @@ CyberChef is released under the [Apache 2.0 Licence](https://www.apache.org/lice [7]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA [8]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',false,'base64',10)To_Hex('Space')Return()Label('base64')To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA [9]: https://gchq.github.io/CyberChef/#recipe=Register('key%3D(%5B%5C%5Cda-f%5D*)',true,false)Find_/_Replace(%7B'option':'Regex','string':'.*data%3D(.*)'%7D,'$1',true,false,true)RC4(%7B'option':'Hex','string':'$R0'%7D,'Hex','Latin1')&input=aHR0cDovL21hbHdhcmV6LmJpei9iZWFjb24ucGhwP2tleT0wZTkzMmE1YyZkYXRhPThkYjdkNWViZTM4NjYzYTU0ZWNiYjMzNGUzZGIxMQ - [10]: https://gchq.github.io/CyberChef/#recipe=Register('(.%7B32%7D)',true,false)Drop_bytes(0,32,false)AES_Decrypt(%7B'option':'Hex','string':'1748e7179bd56570d51fa4ba287cc3e5'%7D,%7B'option':'Hex','string':'$R0'%7D,'CTR','Hex','Raw',%7B'option':'Hex','string':''%7D)&input=NTFlMjAxZDQ2MzY5OGVmNWY3MTdmNzFmNWI0NzEyYWYyMGJlNjc0YjNiZmY1M2QzODU0NjM5NmVlNjFkYWFjNDkwOGUzMTljYTNmY2Y3MDg5YmZiNmIzOGVhOTllNzgxZDI2ZTU3N2JhOWRkNmYzMTFhMzk0MjBiODk3OGU5MzAxNGIwNDJkNDQ3MjZjYWVkZjU0MzZlYWY2NTI0MjljMGRmOTRiNTIxNjc2YzdjMmNlODEyMDk3YzI3NzI3M2M3YzcyY2Q4OWFlYzhkOWZiNGEyNzU4NmNjZjZhYTBhZWUyMjRjMzRiYTNiZmRmN2FlYjFkZGQ0Nzc2MjJiOTFlNzJjOWU3MDlhYjYwZjhkYWY3MzFlYzBjYzg1Y2UwZjc0NmZmMTU1NGE1YTNlYzI5MWNhNDBmOWU2MjlhODcyNTkyZDk4OGZkZDgzNDUzNGFiYTc5YzFhZDE2NzY3NjlhN2MwMTBiZjA0NzM5ZWNkYjY1ZDk1MzAyMzcxZDYyOWQ5ZTM3ZTdiNGEzNjFkYTQ2OGYxZWQ1MzU4OTIyZDJlYTc1MmRkMTFjMzY2ZjMwMTdiMTRhYTAxMWQyYWYwM2M0NGY5NTU3OTA5OGExNWUzY2Y5YjQ0ODZmOGZmZTljMjM5ZjM0ZGU3MTUxZjZjYTY1MDBmZTRiODUwYzNmMWMwMmU4MDFjYWYzYTI0NDY0NjE0ZTQyODAxNjE1YjhmZmFhMDdhYzgyNTE0OTNmZmRhN2RlNWRkZjMzNjg4ODBjMmI5NWIwMzBmNDFmOGYxNTA2NmFkZDA3MWE2NmNmNjBlNWY0NmYzYTIzMGQzOTdiNjUyOTYzYTIxYTUzZg + [10]: https://gchq.github.io/CyberChef/#recipe=Register('(.%7B32%7D)',true,false,false)Drop_bytes(0,32,false)AES_Decrypt(%7B'option':'Hex','string':'1748e7179bd56570d51fa4ba287cc3e5'%7D,%7B'option':'Hex','string':'$R0'%7D,16,'CTR','Hex','Raw',%7B'option':'Hex','string':''%7D,%7B'option':'Hex','string':''%7D,'Off')&input=NTFlMjAxZDQ2MzY5OGVmNWY3MTdmNzFmNWI0NzEyYWYyMGJlNjc0YjNiZmY1M2QzODU0NjM5NmVlNjFkYWFjNDkwOGUzMTljYTNmY2Y3MDg5YmZiNmIzOGVhOTllNzgxZDI2ZTU3N2JhOWRkNmYzMTFhMzk0MjBiODk3OGU5MzAxNGIwNDJkNDQ3MjZjYWVkZjU0MzZlYWY2NTI0MjljMGRmOTRiNTIxNjc2YzdjMmNlODEyMDk3YzI3NzI3M2M3YzcyY2Q4OWFlYzhkOWZiNGEyNzU4NmNjZjZhYTBhZWUyMjRjMzRiYTNiZmRmN2FlYjFkZGQ0Nzc2MjJiOTFlNzJjOWU3MDlhYjYwZjhkYWY3MzFlYzBjYzg1Y2UwZjc0NmZmMTU1NGE1YTNlYzI5MWNhNDBmOWU2MjlhODcyNTkyZDk4OGZkZDgzNDUzNGFiYTc5YzFhZDE2NzY3NjlhN2MwMTBiZjA0NzM5ZWNkYjY1ZDk1MzAyMzcxZDYyOWQ5ZTM3ZTdiNGEzNjFkYTQ2OGYxZWQ1MzU4OTIyZDJlYTc1MmRkMTFjMzY2ZjMwMTdiMTRhYTAxMWQyYWYwM2M0NGY5NTU3OTA5OGExNWUzY2Y5YjQ0ODZmOGZmZTljMjM5ZjM0ZGU3MTUxZjZjYTY1MDBmZTRiODUwYzNmMWMwMmU4MDFjYWYzYTI0NDY0NjE0ZTQyODAxNjE1YjhmZmFhMDdhYzgyNTE0OTNmZmRhN2RlNWRkZjMzNjg4ODBjMmI5NWIwMzBmNDFmOGYxNTA2NmFkZDA3MWE2NmNmNjBlNWY0NmYzYTIzMGQzOTdiNjUyOTYzYTIxYTUzZg [11]: https://gchq.github.io/CyberChef/#recipe=XOR(%7B'option':'Hex','string':'3a'%7D,'Standard',false)To_Hexdump(16,false,false)&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4 [12]: https://gchq.github.io/CyberChef/#recipe=Magic(3,false,false)&input=V1VhZ3dzaWFlNm1QOGdOdENDTFVGcENwQ0IyNlJtQkRvREQ4UGFjZEFtekF6QlZqa0syUXN0RlhhS2hwQzZpVVM3UkhxWHJKdEZpc29SU2dvSjR3aGptMWFybTg2NHFhTnE0UmNmVW1MSHJjc0FhWmM1VFhDWWlmTmRnUzgzZ0RlZWpHWDQ2Z2FpTXl1QlY2RXNrSHQxc2NnSjg4eDJ0TlNvdFFEd2JHWTFtbUNvYjJBUkdGdkNLWU5xaU45aXBNcTFaVTFtZ2tkYk51R2NiNzZhUnRZV2hDR1VjOGc5M1VKdWRoYjhodHNoZVpud1RwZ3FoeDgzU1ZKU1pYTVhVakpUMnptcEM3dVhXdHVtcW9rYmRTaTg4WXRrV0RBYzFUb291aDJvSDRENGRkbU5LSldVRHBNd21uZ1VtSzE0eHdtb21jY1BRRTloTTE3MkFQblNxd3hkS1ExNzJSa2NBc3lzbm1qNWdHdFJtVk5OaDJzMzU5d3I2bVMyUVJQ + [13]: https://gchq.github.io/CyberChef/#recipe=AES_Decrypt(%7B'option':'Hex','string':'1748e7179bd56570d51fa4ba287cc3e5'%7D,%7B'option':'Hex','string':'$R0'%7D,16,'CTR','Hex','Raw',%7B'option':'Hex','string':''%7D,%7B'option':'Hex','string':''%7D,'From%20start')&input=NTFlMjAxZDQ2MzY5OGVmNWY3MTdmNzFmNWI0NzEyYWYyMGJlNjc0YjNiZmY1M2QzODU0NjM5NmVlNjFkYWFjNDkwOGUzMTljYTNmY2Y3MDg5YmZiNmIzOGVhOTllNzgxZDI2ZTU3N2JhOWRkNmYzMTFhMzk0MjBiODk3OGU5MzAxNGIwNDJkNDQ3MjZjYWVkZjU0MzZlYWY2NTI0MjljMGRmOTRiNTIxNjc2YzdjMmNlODEyMDk3YzI3NzI3M2M3YzcyY2Q4OWFlYzhkOWZiNGEyNzU4NmNjZjZhYTBhZWUyMjRjMzRiYTNiZmRmN2FlYjFkZGQ0Nzc2MjJiOTFlNzJjOWU3MDlhYjYwZjhkYWY3MzFlYzBjYzg1Y2UwZjc0NmZmMTU1NGE1YTNlYzI5MWNhNDBmOWU2MjlhODcyNTkyZDk4OGZkZDgzNDUzNGFiYTc5YzFhZDE2NzY3NjlhN2MwMTBiZjA0NzM5ZWNkYjY1ZDk1MzAyMzcxZDYyOWQ5ZTM3ZTdiNGEzNjFkYTQ2OGYxZWQ1MzU4OTIyZDJlYTc1MmRkMTFjMzY2ZjMwMTdiMTRhYTAxMWQyYWYwM2M0NGY5NTU3OTA5OGExNWUzY2Y5YjQ0ODZmOGZmZTljMjM5ZjM0ZGU3MTUxZjZjYTY1MDBmZTRiODUwYzNmMWMwMmU4MDFjYWYzYTI0NDY0NjE0ZTQyODAxNjE1YjhmZmFhMDdhYzgyNTE0OTNmZmRhN2RlNWRkZjMzNjg4ODBjMmI5NWIwMzBmNDFmOGYxNTA2NmFkZDA3MWE2NmNmNjBlNWY0NmYzYTIzMGQzOTdiNjUyOTYzYTIxYTUzZg