Merge branch 'gchq:master' into word_count2
This commit is contained in:
commit
b3143451e6
@ -29,8 +29,7 @@ RUN npm run build
|
|||||||
#########################################
|
#########################################
|
||||||
# We are using Github Actions: redhat-actions/buildah-build@v2 which needs manual selection of arch in base image
|
# We are using Github Actions: redhat-actions/buildah-build@v2 which needs manual selection of arch in base image
|
||||||
# Remove TARGETARCH if docker buildx is supported in the CI release as --platform=$TARGETPLATFORM will be automatically set
|
# Remove TARGETARCH if docker buildx is supported in the CI release as --platform=$TARGETPLATFORM will be automatically set
|
||||||
ARG TARGETARCH
|
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
FROM ${TARGETARCH}/nginx:stable-alpine AS cyberchef
|
FROM --platform=${TARGETPLATFORM} nginx:stable-alpine AS cyberchef
|
||||||
|
|
||||||
COPY --from=builder /app/build/prod /usr/share/nginx/html/
|
COPY --from=builder /app/build/prod /usr/share/nginx/html/
|
||||||
|
|||||||
21
README.md
21
README.md
@ -20,21 +20,36 @@ 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
|
## Running Locally with Docker
|
||||||
|
|
||||||
If you would like to try out CyberChef locally you can either build it yourself:
|
**Prerequisites**
|
||||||
|
|
||||||
|
- [Docker](hhttps://www.docker.com/products/docker-desktop/)
|
||||||
|
- Docker Desktop must be open and running on your machine
|
||||||
|
|
||||||
|
|
||||||
|
#### Option 1: Build the Docker Image Yourself
|
||||||
|
|
||||||
|
1. Build the docker image
|
||||||
```bash
|
```bash
|
||||||
docker build --tag cyberchef --ulimit nofile=10000 .
|
docker build --tag cyberchef --ulimit nofile=10000 .
|
||||||
|
```
|
||||||
|
2. Run the docker container
|
||||||
|
```bash
|
||||||
docker run -it -p 8080:80 cyberchef
|
docker run -it -p 8080:80 cyberchef
|
||||||
```
|
```
|
||||||
|
3. Navigate to `http://localhost:8080` in your browser
|
||||||
|
|
||||||
Or you can use our image directly:
|
#### Option 2: Use the pre-built Docker Image
|
||||||
|
|
||||||
|
If you prefer to skip the build process, you can use the pre-built image
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -it -p 8080:80 ghcr.io/gchq/cyberchef:latest
|
docker run -it -p 8080:80 ghcr.io/gchq/cyberchef:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Just like before, navigate to `http://localhost:8080` in your browser.
|
||||||
|
|
||||||
This image is built and published through our [GitHub Workflows](.github/workflows/releases.yml)
|
This image is built and published through our [GitHub Workflows](.github/workflows/releases.yml)
|
||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|||||||
69
package-lock.json
generated
69
package-lock.json
generated
@ -46,6 +46,8 @@
|
|||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"flat": "^6.0.1",
|
"flat": "^6.0.1",
|
||||||
"geodesy": "1.1.3",
|
"geodesy": "1.1.3",
|
||||||
|
"handlebars": "^4.7.8",
|
||||||
|
"hash-wasm": "^4.12.0",
|
||||||
"highlight.js": "^11.9.0",
|
"highlight.js": "^11.9.0",
|
||||||
"ieee754": "^1.2.1",
|
"ieee754": "^1.2.1",
|
||||||
"jimp": "^0.22.12",
|
"jimp": "^0.22.12",
|
||||||
@ -95,6 +97,7 @@
|
|||||||
"ua-parser-js": "^1.0.38",
|
"ua-parser-js": "^1.0.38",
|
||||||
"unorm": "^1.6.0",
|
"unorm": "^1.6.0",
|
||||||
"utf8": "^3.0.0",
|
"utf8": "^3.0.0",
|
||||||
|
"uuid": "^11.1.0",
|
||||||
"vkbeautify": "^0.99.3",
|
"vkbeautify": "^0.99.3",
|
||||||
"xpath": "0.0.34",
|
"xpath": "0.0.34",
|
||||||
"xregexp": "^5.1.1",
|
"xregexp": "^5.1.1",
|
||||||
@ -10843,6 +10846,27 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/handlebars": {
|
||||||
|
"version": "4.7.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
|
||||||
|
"integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"minimist": "^1.2.5",
|
||||||
|
"neo-async": "^2.6.2",
|
||||||
|
"source-map": "^0.6.1",
|
||||||
|
"wordwrap": "^1.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"handlebars": "bin/handlebars"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.7"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"uglify-js": "^3.1.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/has-ansi": {
|
"node_modules/has-ansi": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
|
||||||
@ -10941,6 +10965,11 @@
|
|||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hash-wasm": {
|
||||||
|
"version": "4.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hash-wasm/-/hash-wasm-4.12.0.tgz",
|
||||||
|
"integrity": "sha512-+/2B2rYLb48I/evdOIhP+K/DD2ca2fgBjp6O+GBEnCDk2e4rpeXIK8GvIyRPjTezgmWn9gmKwkQjjx6BtqDHVQ=="
|
||||||
|
},
|
||||||
"node_modules/hash.js": {
|
"node_modules/hash.js": {
|
||||||
"version": "1.1.7",
|
"version": "1.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
|
||||||
@ -13663,7 +13692,6 @@
|
|||||||
"version": "2.6.2",
|
"version": "2.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/netmask": {
|
"node_modules/netmask": {
|
||||||
@ -13885,6 +13913,15 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nightwatch/node_modules/uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/nightwatch/node_modules/yallist": {
|
"node_modules/nightwatch/node_modules/yallist": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
@ -16828,6 +16865,15 @@
|
|||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sockjs/node_modules/uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/socks": {
|
"node_modules/socks": {
|
||||||
"version": "2.8.3",
|
"version": "2.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
|
||||||
@ -16868,7 +16914,6 @@
|
|||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||||
"devOptional": true,
|
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
@ -18115,13 +18160,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/uuid": {
|
"node_modules/uuid": {
|
||||||
"version": "8.3.2",
|
"version": "11.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
|
||||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
"integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
|
||||||
"dev": true,
|
"funding": [
|
||||||
"license": "MIT",
|
"https://github.com/sponsors/broofa",
|
||||||
|
"https://github.com/sponsors/ctavan"
|
||||||
|
],
|
||||||
"bin": {
|
"bin": {
|
||||||
"uuid": "dist/bin/uuid"
|
"uuid": "dist/esm/bin/uuid"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/v8flags": {
|
"node_modules/v8flags": {
|
||||||
@ -18886,6 +18933,12 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/wordwrap": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/worker-loader": {
|
"node_modules/worker-loader": {
|
||||||
"version": "3.0.8",
|
"version": "3.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-3.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-3.0.8.tgz",
|
||||||
|
|||||||
@ -132,6 +132,8 @@
|
|||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"flat": "^6.0.1",
|
"flat": "^6.0.1",
|
||||||
"geodesy": "1.1.3",
|
"geodesy": "1.1.3",
|
||||||
|
"handlebars": "^4.7.8",
|
||||||
|
"hash-wasm": "^4.12.0",
|
||||||
"highlight.js": "^11.9.0",
|
"highlight.js": "^11.9.0",
|
||||||
"ieee754": "^1.2.1",
|
"ieee754": "^1.2.1",
|
||||||
"jimp": "^0.22.12",
|
"jimp": "^0.22.12",
|
||||||
@ -181,6 +183,7 @@
|
|||||||
"ua-parser-js": "^1.0.38",
|
"ua-parser-js": "^1.0.38",
|
||||||
"unorm": "^1.6.0",
|
"unorm": "^1.6.0",
|
||||||
"utf8": "^3.0.0",
|
"utf8": "^3.0.0",
|
||||||
|
"uuid": "^11.1.0",
|
||||||
"vkbeautify": "^0.99.3",
|
"vkbeautify": "^0.99.3",
|
||||||
"xpath": "0.0.34",
|
"xpath": "0.0.34",
|
||||||
"xregexp": "^5.1.1",
|
"xregexp": "^5.1.1",
|
||||||
|
|||||||
@ -376,7 +376,8 @@
|
|||||||
"Extract EXIF",
|
"Extract EXIF",
|
||||||
"Extract ID3",
|
"Extract ID3",
|
||||||
"Extract Files",
|
"Extract Files",
|
||||||
"RAKE"
|
"RAKE",
|
||||||
|
"Template"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -426,6 +427,7 @@
|
|||||||
"Snefru",
|
"Snefru",
|
||||||
"BLAKE2b",
|
"BLAKE2b",
|
||||||
"BLAKE2s",
|
"BLAKE2s",
|
||||||
|
"BLAKE3",
|
||||||
"GOST Hash",
|
"GOST Hash",
|
||||||
"Streebog",
|
"Streebog",
|
||||||
"SSDEEP",
|
"SSDEEP",
|
||||||
@ -550,6 +552,7 @@
|
|||||||
"Pseudo-Random Number Generator",
|
"Pseudo-Random Number Generator",
|
||||||
"Generate De Bruijn Sequence",
|
"Generate De Bruijn Sequence",
|
||||||
"Generate UUID",
|
"Generate UUID",
|
||||||
|
"Analyse UUID",
|
||||||
"Generate TOTP",
|
"Generate TOTP",
|
||||||
"Generate HOTP",
|
"Generate HOTP",
|
||||||
"Generate QR Code",
|
"Generate QR Code",
|
||||||
|
|||||||
48
src/core/operations/AnalyseUUID.mjs
Normal file
48
src/core/operations/AnalyseUUID.mjs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2023
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as uuid from "uuid";
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analyse UUID operation
|
||||||
|
*/
|
||||||
|
class AnalyseUUID extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AnalyseUUID constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "Analyse UUID";
|
||||||
|
this.module = "Crypto";
|
||||||
|
this.description = "Tries to determine information about a given UUID and suggests which version may have been used to generate it";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Universally_unique_identifier";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
try {
|
||||||
|
const uuidVersion = uuid.version(input);
|
||||||
|
return "UUID version: " + uuidVersion;
|
||||||
|
} catch (error) {
|
||||||
|
throw new OperationError("Invalid UUID");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AnalyseUUID;
|
||||||
58
src/core/operations/BLAKE3.mjs
Normal file
58
src/core/operations/BLAKE3.mjs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* @author xumptex [xumptex@outlook.fr]
|
||||||
|
* @copyright Crown Copyright 2025
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import { blake3 } from "hash-wasm";
|
||||||
|
/**
|
||||||
|
* BLAKE3 operation
|
||||||
|
*/
|
||||||
|
class BLAKE3 extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BLAKE3 constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "BLAKE3";
|
||||||
|
this.module = "Hashing";
|
||||||
|
this.description = "Hashes the input using BLAKE3 (UTF-8 encoded), with an optional key (also UTF-8), and outputs the result in hexadecimal format.";
|
||||||
|
this.infoURL = "https://en.wikipedia.org/wiki/BLAKE_(hash_function)#BLAKE3";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Size (bytes)",
|
||||||
|
"type": "number"
|
||||||
|
}, {
|
||||||
|
"name": "Key",
|
||||||
|
"type": "string",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const key = args[1];
|
||||||
|
const size = args[0];
|
||||||
|
// Check if the user want a key hash or not
|
||||||
|
if (key === "") {
|
||||||
|
return blake3(input, size*8);
|
||||||
|
} if (key.length !== 32) {
|
||||||
|
throw new OperationError("The key must be exactly 32 bytes long");
|
||||||
|
}
|
||||||
|
return blake3(input, size*8, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BLAKE3;
|
||||||
@ -51,7 +51,7 @@ class ExtractEmailAddresses extends Operation {
|
|||||||
run(input, args) {
|
run(input, args) {
|
||||||
const [displayTotal, sort, unique] = args,
|
const [displayTotal, sort, unique] = args,
|
||||||
// email regex from: https://www.regextester.com/98066
|
// email regex from: https://www.regextester.com/98066
|
||||||
regex = /(?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9])?\.)+[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}\])/ig;
|
regex = /(?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9])?\.)+[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\])/ig;
|
||||||
|
|
||||||
const results = search(
|
const results = search(
|
||||||
input,
|
input,
|
||||||
|
|||||||
@ -21,7 +21,7 @@ class ExtractIPAddresses extends Operation {
|
|||||||
|
|
||||||
this.name = "Extract IP addresses";
|
this.name = "Extract IP addresses";
|
||||||
this.module = "Regex";
|
this.module = "Regex";
|
||||||
this.description = "Extracts all IPv4 and IPv6 addresses.<br><br>Warning: Given a string <code>710.65.0.456</code>, this will match <code>10.65.0.45</code> so always check the original input!";
|
this.description = "Extracts all IPv4 and IPv6 addresses.<br><br>Warning: Given a string <code>1.2.3.4.5.6.7.8</code>, this will match <code>1.2.3.4 and 5.6.7.8</code> so always check the original input!";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [
|
this.args = [
|
||||||
@ -65,7 +65,21 @@ class ExtractIPAddresses extends Operation {
|
|||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const [includeIpv4, includeIpv6, removeLocal, displayTotal, sort, unique] = args,
|
const [includeIpv4, includeIpv6, removeLocal, displayTotal, sort, unique] = args,
|
||||||
ipv4 = "(?:(?:\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d|\\d)(?:\\/\\d{1,2})?",
|
|
||||||
|
// IPv4 decimal groups can have values 0 to 255. To construct a regex the following sub-regex is reused:
|
||||||
|
ipv4DecimalByte = "(?:25[0-5]|2[0-4]\\d|1?[0-9]\\d|\\d)",
|
||||||
|
ipv4OctalByte = "(?:0[1-3]?[0-7]{1,2})",
|
||||||
|
|
||||||
|
// Look behind and ahead will be used to exclude matches with additional decimal digits left and right of IP address
|
||||||
|
lookBehind = "(?<!\\d)",
|
||||||
|
lookAhead = "(?!\\d)",
|
||||||
|
|
||||||
|
// Each variant requires exactly 4 groups with literal . between.
|
||||||
|
ipv4Decimal = "(?:" + lookBehind + ipv4DecimalByte + "\\.){3}" + "(?:" + ipv4DecimalByte + lookAhead + ")",
|
||||||
|
ipv4Octal = "(?:" + lookBehind + ipv4OctalByte + "\\.){3}" + "(?:" + ipv4OctalByte + lookAhead + ")",
|
||||||
|
|
||||||
|
// Then we allow IPv4 addresses to be expressed either entirely in decimal or entirely in Octal
|
||||||
|
ipv4 = "(?:" + ipv4Decimal + "|" + ipv4Octal + ")",
|
||||||
ipv6 = "((?=.*::)(?!.*::.+::)(::)?([\\dA-F]{1,4}:(:|\\b)|){5}|([\\dA-F]{1,4}:){6})(([\\dA-F]{1,4}((?!\\3)::|:\\b|(?![\\dA-F])))|(?!\\2\\3)){2}";
|
ipv6 = "((?=.*::)(?!.*::.+::)(::)?([\\dA-F]{1,4}:(:|\\b)|){5}|([\\dA-F]{1,4}:){6})(([\\dA-F]{1,4}((?!\\3)::|:\\b|(?![\\dA-F])))|(?!\\2\\3)){2}";
|
||||||
let ips = "";
|
let ips = "";
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import crypto from "crypto";
|
import * as uuid from "uuid";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
/**
|
/**
|
||||||
* Generate UUID operation
|
* Generate UUID operation
|
||||||
*/
|
*/
|
||||||
@ -20,11 +20,38 @@ class GenerateUUID extends Operation {
|
|||||||
|
|
||||||
this.name = "Generate UUID";
|
this.name = "Generate UUID";
|
||||||
this.module = "Crypto";
|
this.module = "Crypto";
|
||||||
this.description = "Generates an RFC 4122 version 4 compliant Universally Unique Identifier (UUID), also known as a Globally Unique Identifier (GUID).<br><br>A version 4 UUID relies on random numbers, in this case generated using <code>window.crypto</code> if available and falling back to <code>Math.random</code> if not.";
|
this.description =
|
||||||
|
"Generates an RFC 9562 (formerly RFC 4122) compliant Universally Unique Identifier (UUID), " +
|
||||||
|
"also known as a Globally Unique Identifier (GUID).<br>" +
|
||||||
|
"<br>" +
|
||||||
|
"We currently support generating the following UUID versions:<br>" +
|
||||||
|
"<ul>" +
|
||||||
|
"<li><strong>v1</strong>: Timestamp-based</li>" +
|
||||||
|
"<li><strong>v3</strong>: Namespace w/ MD5</li>" +
|
||||||
|
"<li><strong>v4</strong>: Random (default)</li>" +
|
||||||
|
"<li><strong>v5</strong>: Namespace w/ SHA-1</li>" +
|
||||||
|
"<li><strong>v6</strong>: Timestamp, reordered</li>" +
|
||||||
|
"<li><strong>v7</strong>: Unix Epoch time-based</li>" +
|
||||||
|
"</ul>" +
|
||||||
|
"UUIDs are generated using the <a href='https://npmjs.org/uuid/'><code>uuid</code><a> package.<br>";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Universally_unique_identifier";
|
this.infoURL = "https://wikipedia.org/wiki/Universally_unique_identifier";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [];
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Version",
|
||||||
|
hint: "UUID version",
|
||||||
|
type: "option",
|
||||||
|
value: ["v1", "v3", "v4", "v5", "v6", "v7"],
|
||||||
|
defaultIndex: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Namespace",
|
||||||
|
hint: "UUID namespace (UUID; valid for v3 and v5)",
|
||||||
|
type: "string",
|
||||||
|
value: "1b671a64-40d5-491e-99b0-da01ff1f3341"
|
||||||
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,16 +60,17 @@ class GenerateUUID extends Operation {
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const buf = new Uint32Array(4).map(() => {
|
const [version, namespace] = args;
|
||||||
return crypto.randomBytes(4).readUInt32BE(0, true);
|
const hasDesiredVersion = typeof uuid[version] === "function";
|
||||||
});
|
if (!hasDesiredVersion) throw new OperationError("Invalid UUID version");
|
||||||
let i = 0;
|
|
||||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
const requiresNamespace = ["v3", "v5"].includes(version);
|
||||||
const r = (buf[i >> 3] >> ((i % 8) * 4)) & 0xf,
|
if (!requiresNamespace) return uuid[version]();
|
||||||
v = c === "x" ? r : (r & 0x3 | 0x8);
|
|
||||||
i++;
|
const hasValidNamespace = typeof namespace === "string" && uuid.validate(namespace);
|
||||||
return v.toString(16);
|
if (!hasValidNamespace) throw new OperationError("Invalid UUID namespace");
|
||||||
});
|
|
||||||
|
return uuid[version](input, namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -72,7 +72,7 @@ class RailFenceCipherDecode extends Operation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return plaintext.join("").trim();
|
return plaintext.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,7 +66,7 @@ class RailFenceCipherEncode extends Operation {
|
|||||||
rows[rowIdx] += plaintext[pos];
|
rows[rowIdx] += plaintext[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
return rows.join("").trim();
|
return rows.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @author j433866 [j433866@gmail.com]
|
* @author j433866 [j433866@gmail.com]
|
||||||
* @copyright Crown Copyright 2019
|
* @author 0xff1ce [github.com/0xff1ce]
|
||||||
|
* @copyright Crown Copyright 2024
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ class ShowOnMap extends Operation {
|
|||||||
this.name = "Show on map";
|
this.name = "Show on map";
|
||||||
this.module = "Hashing";
|
this.module = "Hashing";
|
||||||
this.description = "Displays co-ordinates on a slippy map.<br><br>Co-ordinates will be converted to decimal degrees before being shown on the map.<br><br>Supported formats:<ul><li>Degrees Minutes Seconds (DMS)</li><li>Degrees Decimal Minutes (DDM)</li><li>Decimal Degrees (DD)</li><li>Geohash</li><li>Military Grid Reference System (MGRS)</li><li>Ordnance Survey National Grid (OSNG)</li><li>Universal Transverse Mercator (UTM)</li></ul><br>This operation will not work offline.";
|
this.description = "Displays co-ordinates on a slippy map.<br><br>Co-ordinates will be converted to decimal degrees before being shown on the map.<br><br>Supported formats:<ul><li>Degrees Minutes Seconds (DMS)</li><li>Degrees Decimal Minutes (DDM)</li><li>Decimal Degrees (DD)</li><li>Geohash</li><li>Military Grid Reference System (MGRS)</li><li>Ordnance Survey National Grid (OSNG)</li><li>Universal Transverse Mercator (UTM)</li></ul><br>This operation will not work offline.";
|
||||||
this.infoURL = "https://foundation.wikimedia.org/wiki/Maps_Terms_of_Use";
|
this.infoURL = "https://osmfoundation.org/wiki/Terms_of_Use";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.presentType = "html";
|
this.presentType = "html";
|
||||||
@ -85,10 +86,10 @@ class ShowOnMap extends Operation {
|
|||||||
data = "0, 0";
|
data = "0, 0";
|
||||||
}
|
}
|
||||||
const zoomLevel = args[0];
|
const zoomLevel = args[0];
|
||||||
const tileUrl = "https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png",
|
const tileUrl = "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||||
tileAttribution = "<a href=\"https://wikimediafoundation.org/wiki/Maps_Terms_of_Use\">Wikimedia maps</a> | © <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
|
tileAttribution = "© <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
|
||||||
leafletUrl = "https://unpkg.com/leaflet@1.5.0/dist/leaflet.js",
|
leafletUrl = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.js",
|
||||||
leafletCssUrl = "https://unpkg.com/leaflet@1.5.0/dist/leaflet.css";
|
leafletCssUrl = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.css";
|
||||||
return `<link rel="stylesheet" href="${leafletCssUrl}" crossorigin=""/>
|
return `<link rel="stylesheet" href="${leafletCssUrl}" crossorigin=""/>
|
||||||
<style>
|
<style>
|
||||||
#output-text .cm-content,
|
#output-text .cm-content,
|
||||||
|
|||||||
53
src/core/operations/Template.mjs
Normal file
53
src/core/operations/Template.mjs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* @author kendallgoto [k@kgo.to]
|
||||||
|
* @copyright Crown Copyright 2025
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import Handlebars from "handlebars";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template operation
|
||||||
|
*/
|
||||||
|
class Template extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "Template";
|
||||||
|
this.module = "Handlebars";
|
||||||
|
this.description = "Render a template with Handlebars/Mustache substituting variables using JSON input. Templates will be rendered to plain-text only, to prevent XSS.";
|
||||||
|
this.infoURL = "https://handlebarsjs.com/";
|
||||||
|
this.inputType = "JSON";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Template definition (.handlebars)",
|
||||||
|
type: "text",
|
||||||
|
value: ""
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {JSON} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const [templateStr] = args;
|
||||||
|
try {
|
||||||
|
const template = Handlebars.compile(templateStr);
|
||||||
|
return template(input);
|
||||||
|
} catch (e) {
|
||||||
|
throw new OperationError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Template;
|
||||||
@ -45,11 +45,12 @@ class ToDecimal extends Operation {
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
input = new Uint8Array(input);
|
|
||||||
const delim = Utils.charRep(args[0]),
|
const delim = Utils.charRep(args[0]),
|
||||||
signed = args[1];
|
signed = args[1];
|
||||||
if (signed) {
|
if (signed) {
|
||||||
input = input.map(v => v > 0x7F ? v - 0xFF - 1 : v);
|
input = new Int8Array(input);
|
||||||
|
} else {
|
||||||
|
input = new Uint8Array(input);
|
||||||
}
|
}
|
||||||
return input.join(delim);
|
return input.join(delim);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,13 @@ class URLDecode extends Operation {
|
|||||||
this.infoURL = "https://wikipedia.org/wiki/Percent-encoding";
|
this.infoURL = "https://wikipedia.org/wiki/Percent-encoding";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [];
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Treat \"+\" as space",
|
||||||
|
"type": "boolean",
|
||||||
|
"value": true
|
||||||
|
},
|
||||||
|
];
|
||||||
this.checks = [
|
this.checks = [
|
||||||
{
|
{
|
||||||
pattern: ".*(?:%[\\da-f]{2}.*){4}",
|
pattern: ".*(?:%[\\da-f]{2}.*){4}",
|
||||||
@ -39,7 +45,8 @@ class URLDecode extends Operation {
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const data = input.replace(/\+/g, "%20");
|
const plusIsSpace = args[0];
|
||||||
|
const data = plusIsSpace ? input.replace(/\+/g, "%20") : input;
|
||||||
try {
|
try {
|
||||||
return decodeURIComponent(data);
|
return decodeURIComponent(data);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@ -74,11 +74,11 @@ function transformArgs(opArgsList, newArgs) {
|
|||||||
return opArgs.map((arg) => {
|
return opArgs.map((arg) => {
|
||||||
if (arg.type === "option") {
|
if (arg.type === "option") {
|
||||||
// pick default option if not already chosen
|
// pick default option if not already chosen
|
||||||
return typeof arg.value === "string" ? arg.value : arg.value[0];
|
return typeof arg.value === "string" ? arg.value : arg.value[arg.defaultIndex ?? 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg.type === "editableOption") {
|
if (arg.type === "editableOption") {
|
||||||
return typeof arg.value === "string" ? arg.value : arg.value[0].value;
|
return typeof arg.value === "string" ? arg.value : arg.value[arg.defaultIndex ?? 0].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg.type === "toggleString") {
|
if (arg.type === "toggleString") {
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"@context": "http://schema.org",
|
"@context": "http://schema.org",
|
||||||
|
"@graph": [
|
||||||
|
{
|
||||||
"@type": "Organization",
|
"@type": "Organization",
|
||||||
"url": "https://gchq.github.io/CyberChef/",
|
"url": "https://gchq.github.io/CyberChef/",
|
||||||
"logo": "https://gchq.github.io/CyberChef/images/cyberchef-128x128.png",
|
"logo": "https://gchq.github.io/CyberChef/images/cyberchef-128x128.png",
|
||||||
@ -10,7 +12,6 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"@context": "http://schema.org",
|
|
||||||
"@type": "WebSite",
|
"@type": "WebSite",
|
||||||
"url": "https://gchq.github.io/CyberChef/",
|
"url": "https://gchq.github.io/CyberChef/",
|
||||||
"name": "CyberChef",
|
"name": "CyberChef",
|
||||||
@ -20,4 +21,6 @@
|
|||||||
"query-input": "required name=operation_search_term"
|
"query-input": "required name=operation_search_term"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
@ -580,10 +580,25 @@ Password: 282760`;
|
|||||||
assert.strictEqual(result.toString().substr(0, 37), "-----BEGIN PGP PRIVATE KEY BLOCK-----");
|
assert.strictEqual(result.toString().substr(0, 37), "-----BEGIN PGP PRIVATE KEY BLOCK-----");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("Generate UUID", () => {
|
...[1, 3, 4, 5, 6, 7].map(version => it(`Generate UUID v${version}`, () => {
|
||||||
const result = chef.generateUUID();
|
const result = chef.generateUUID("", { "version": `v${version}` }).toString();
|
||||||
assert.ok(result.toString());
|
assert.ok(result);
|
||||||
assert.strictEqual(result.toString().length, 36);
|
assert.strictEqual(result.length, 36);
|
||||||
|
})),
|
||||||
|
|
||||||
|
...[1, 3, 4, 5, 6, 7].map(version => it(`Analyze UUID v${version}`, () => {
|
||||||
|
const uuid = chef.generateUUID("", { "version": `v${version}` }).toString();
|
||||||
|
const result = chef.analyseUUID(uuid).toString();
|
||||||
|
const expected = `UUID version: ${version}`;
|
||||||
|
assert.strictEqual(result, expected);
|
||||||
|
})),
|
||||||
|
|
||||||
|
it("Generate UUID using defaults", () => {
|
||||||
|
const uuid = chef.generateUUID();
|
||||||
|
assert.ok(uuid);
|
||||||
|
|
||||||
|
const analysis = chef.analyseUUID(uuid).toString();
|
||||||
|
assert.strictEqual(analysis, "UUID version: 4");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("Gzip, Gunzip", () => {
|
it("Gzip, Gunzip", () => {
|
||||||
|
|||||||
@ -29,6 +29,7 @@ import "./tests/BCD.mjs";
|
|||||||
import "./tests/BitwiseOp.mjs";
|
import "./tests/BitwiseOp.mjs";
|
||||||
import "./tests/BLAKE2b.mjs";
|
import "./tests/BLAKE2b.mjs";
|
||||||
import "./tests/BLAKE2s.mjs";
|
import "./tests/BLAKE2s.mjs";
|
||||||
|
import "./tests/BLAKE3.mjs";
|
||||||
import "./tests/Bombe.mjs";
|
import "./tests/Bombe.mjs";
|
||||||
import "./tests/BSON.mjs";
|
import "./tests/BSON.mjs";
|
||||||
import "./tests/ByteRepr.mjs";
|
import "./tests/ByteRepr.mjs";
|
||||||
@ -65,6 +66,7 @@ import "./tests/ELFInfo.mjs";
|
|||||||
import "./tests/Enigma.mjs";
|
import "./tests/Enigma.mjs";
|
||||||
import "./tests/ExtractEmailAddresses.mjs";
|
import "./tests/ExtractEmailAddresses.mjs";
|
||||||
import "./tests/ExtractHashes.mjs";
|
import "./tests/ExtractHashes.mjs";
|
||||||
|
import "./tests/ExtractIPAddresses.mjs";
|
||||||
import "./tests/Float.mjs";
|
import "./tests/Float.mjs";
|
||||||
import "./tests/FileTree.mjs";
|
import "./tests/FileTree.mjs";
|
||||||
import "./tests/FletcherChecksum.mjs";
|
import "./tests/FletcherChecksum.mjs";
|
||||||
@ -157,12 +159,14 @@ import "./tests/Subsection.mjs";
|
|||||||
import "./tests/SwapCase.mjs";
|
import "./tests/SwapCase.mjs";
|
||||||
import "./tests/SymmetricDifference.mjs";
|
import "./tests/SymmetricDifference.mjs";
|
||||||
import "./tests/TakeNthBytes.mjs";
|
import "./tests/TakeNthBytes.mjs";
|
||||||
|
import "./tests/Template.mjs";
|
||||||
import "./tests/TextEncodingBruteForce.mjs";
|
import "./tests/TextEncodingBruteForce.mjs";
|
||||||
import "./tests/ToFromInsensitiveRegex.mjs";
|
import "./tests/ToFromInsensitiveRegex.mjs";
|
||||||
import "./tests/TranslateDateTimeFormat.mjs";
|
import "./tests/TranslateDateTimeFormat.mjs";
|
||||||
import "./tests/Typex.mjs";
|
import "./tests/Typex.mjs";
|
||||||
import "./tests/UnescapeString.mjs";
|
import "./tests/UnescapeString.mjs";
|
||||||
import "./tests/Unicode.mjs";
|
import "./tests/Unicode.mjs";
|
||||||
|
import "./tests/URLEncodeDecode.mjs";
|
||||||
import "./tests/RSA.mjs";
|
import "./tests/RSA.mjs";
|
||||||
import "./tests/CBOREncode.mjs";
|
import "./tests/CBOREncode.mjs";
|
||||||
import "./tests/CBORDecode.mjs";
|
import "./tests/CBORDecode.mjs";
|
||||||
|
|||||||
55
tests/operations/tests/BLAKE3.mjs
Normal file
55
tests/operations/tests/BLAKE3.mjs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* BLAKE3 tests.
|
||||||
|
* @author xumptex [xumptex@outlook.fr]
|
||||||
|
* @copyright Crown Copyright 2025
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "BLAKE3: 8 - Hello world",
|
||||||
|
input: "Hello world",
|
||||||
|
expectedOutput: "e7e6fb7d2869d109",
|
||||||
|
recipeConfig: [
|
||||||
|
{ "op": "BLAKE3",
|
||||||
|
"args": [8, ""] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "BLAKE3: 16 - Hello world 2",
|
||||||
|
input: "Hello world 2",
|
||||||
|
expectedOutput: "2a3df5fe5f0d3fcdd995fc203c7f7c52",
|
||||||
|
recipeConfig: [
|
||||||
|
{ "op": "BLAKE3",
|
||||||
|
"args": [16, ""] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "BLAKE3: 32 - Hello world",
|
||||||
|
input: "Hello world",
|
||||||
|
expectedOutput: "e7e6fb7d2869d109b62cdb1227208d4016cdaa0af6603d95223c6a698137d945",
|
||||||
|
recipeConfig: [
|
||||||
|
{ "op": "BLAKE3",
|
||||||
|
"args": [32, ""] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "BLAKE3: Key Test",
|
||||||
|
input: "Hello world",
|
||||||
|
expectedOutput: "59dd23ac9d025690",
|
||||||
|
recipeConfig: [
|
||||||
|
{ "op": "BLAKE3",
|
||||||
|
"args": [8, "ThiskeyisexactlythirtytwoBytesLo"] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "BLAKE3: Key Test 2",
|
||||||
|
input: "Hello world",
|
||||||
|
expectedOutput: "c8302c9634c1da42",
|
||||||
|
recipeConfig: [
|
||||||
|
{ "op": "BLAKE3",
|
||||||
|
"args": [8, "ThiskeyisexactlythirtytwoByteslo"] }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]);
|
||||||
@ -528,4 +528,15 @@ TestRegister.addTests([
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Rail Fence Cipher Encode: Normal with Offset with Spaces",
|
||||||
|
input: "No one expects the spanish Inquisition.",
|
||||||
|
expectedOutput: " e n ut.ooeepcstesaihIqiiinNnxthpsnso",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rail Fence Cipher Encode",
|
||||||
|
"args": [3, 2]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||
133
tests/operations/tests/ExtractIPAddresses.mjs
Normal file
133
tests/operations/tests/ExtractIPAddresses.mjs
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/**
|
||||||
|
* ExtractIPAddresses tests.
|
||||||
|
*
|
||||||
|
* @author gchqdev365 [gchqdev365@outlook.com]
|
||||||
|
* @copyright Crown Copyright 2025
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "ExtractIPAddress All Zeros",
|
||||||
|
input: "0.0.0.0",
|
||||||
|
expectedOutput: "0.0.0.0",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Extract IP addresses",
|
||||||
|
"args": [true, true, false, false, false, false]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ExtractIPAddress All 10s",
|
||||||
|
input: "10.10.10.10",
|
||||||
|
expectedOutput: "10.10.10.10",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Extract IP addresses",
|
||||||
|
"args": [true, true, false, false, false, false]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ExtractIPAddress All 10s",
|
||||||
|
input: "100.100.100.100",
|
||||||
|
expectedOutput: "100.100.100.100",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Extract IP addresses",
|
||||||
|
"args": [true, true, false, false, false, false]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ExtractIPAddress 255s",
|
||||||
|
input: "255.255.255.255",
|
||||||
|
expectedOutput: "255.255.255.255",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Extract IP addresses",
|
||||||
|
"args": [true, true, false, false, false, false]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ExtractIPAddress double digits",
|
||||||
|
input: "10.10.10.10 25.25.25.25 99.99.99.99",
|
||||||
|
expectedOutput: "10.10.10.10\n25.25.25.25\n99.99.99.99",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Extract IP addresses",
|
||||||
|
"args": [true, true, false, false, false, false]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ExtractIPAddress 256 in middle",
|
||||||
|
input: "255.256.255.255 255.255.256.255",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Extract IP addresses",
|
||||||
|
"args": [true, true, false, false, false, false]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ExtractIPAddress 256 at each end",
|
||||||
|
input: "256.255.255.255 255.255.255.256",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Extract IP addresses",
|
||||||
|
"args": [true, true, false, false, false, false]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ExtractIPAddress silly example",
|
||||||
|
input: "710.65.0.456",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Extract IP addresses",
|
||||||
|
"args": [true, true, false, false, false, false]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ExtractIPAddress longer dotted decimal",
|
||||||
|
input: "1.2.3.4.5.6.7.8",
|
||||||
|
expectedOutput: "1.2.3.4\n5.6.7.8",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Extract IP addresses",
|
||||||
|
"args": [true, true, false, false, false, false]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ExtractIPAddress octal valid",
|
||||||
|
input: "01.01.01.01 0123.0123.0123.0123 0377.0377.0377.0377",
|
||||||
|
expectedOutput: "01.01.01.01\n0123.0123.0123.0123\n0377.0377.0377.0377",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Extract IP addresses",
|
||||||
|
"args": [true, true, false, false, false, false]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ExtractIPAddress octal invalid",
|
||||||
|
input: "0378.01.01.01 03.0377.2.3",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Extract IP addresses",
|
||||||
|
"args": [true, true, false, false, false, false]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
53
tests/operations/tests/Template.mjs
Normal file
53
tests/operations/tests/Template.mjs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* @author kendallgoto [k@kgo.to]
|
||||||
|
* @copyright Crown Copyright 2025
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
"name": "Template: Simple Print",
|
||||||
|
"input": "{}",
|
||||||
|
"expectedOutput": "Hello, world!",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "Template",
|
||||||
|
"args": ["Hello, world!"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Template: Print Basic Variables",
|
||||||
|
"input": "{\"one\": 1, \"two\": 2}",
|
||||||
|
"expectedOutput": "1 2",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "Template",
|
||||||
|
"args": ["{{ one }} {{ two }}"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Template: Partials",
|
||||||
|
"input": "{\"users\":[{\"name\":\"Someone\",\"age\":25},{\"name\":\"Someone Else\",\"age\":32}]}",
|
||||||
|
"expectedOutput": "Name: Someone\nAge: 25\n\nName: Someone Else\nAge: 32\n\n",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "Template",
|
||||||
|
"args": ["{{#*inline \"user\"}}\nName: {{ name }}\nAge: {{ age }}\n{{/inline}}\n{{#each users}}\n{{> user}}\n\n{{/each}}"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Template: Disallow XSS",
|
||||||
|
"input": "{\"test\": \"<script></script>\"}",
|
||||||
|
"expectedOutput": "<script></script><script></script>",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "Template",
|
||||||
|
"args": ["<script></script>{{ test }}"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]);
|
||||||
92
tests/operations/tests/URLEncodeDecode.mjs
Normal file
92
tests/operations/tests/URLEncodeDecode.mjs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/**
|
||||||
|
* URLEncode and URLDecode tests.
|
||||||
|
*
|
||||||
|
* @author es45411 [135977478+es45411@users.noreply.github.com]
|
||||||
|
*
|
||||||
|
* @copyright Crown Copyright 2018
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
// URL Decode
|
||||||
|
{
|
||||||
|
name: "URLDecode: nothing",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "URL Decode",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "URLDecode: spaces without special chars",
|
||||||
|
input: "Hello%20world%21",
|
||||||
|
expectedOutput: "Hello world!",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "URL Decode",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "URLDecode: spaces with special chars",
|
||||||
|
input: "Hello%20world!",
|
||||||
|
expectedOutput: "Hello world!",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "URL Decode",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "URLDecode: decode plus as space",
|
||||||
|
input: "Hello%20world!",
|
||||||
|
expectedOutput: "Hello world!",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "URL Decode",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// URL Encode
|
||||||
|
{
|
||||||
|
name: "URLEncode: nothing",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "URL Encode",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "URLEncode: spaces without special chars",
|
||||||
|
input: "Hello world!",
|
||||||
|
expectedOutput: "Hello%20world!",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "URL Encode",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "URLEncode: spaces with special chars",
|
||||||
|
input: "Hello world!",
|
||||||
|
expectedOutput: "Hello%20world%21",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "URL Encode",
|
||||||
|
args: [true],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
Loading…
x
Reference in New Issue
Block a user