Merge branch 'gchq:master' into master
This commit is contained in:
commit
d5f46f74c2
@ -3,7 +3,7 @@
|
|||||||
{
|
{
|
||||||
"name": "CyberChef",
|
"name": "CyberChef",
|
||||||
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
||||||
"image": "mcr.microsoft.com/devcontainers/javascript-node:1-18-bookworm",
|
"image": "mcr.microsoft.com/devcontainers/javascript-node:24-trixie",
|
||||||
|
|
||||||
// Features to add to the dev container. More info: https://containers.dev/features.
|
// Features to add to the dev container. More info: https://containers.dev/features.
|
||||||
"features": {
|
"features": {
|
||||||
|
|||||||
71
.github/dependabot.yml
vendored
71
.github/dependabot.yml
vendored
@ -15,6 +15,8 @@ updates:
|
|||||||
day: 'friday'
|
day: 'friday'
|
||||||
time: '03:00'
|
time: '03:00'
|
||||||
timezone: Europe/London
|
timezone: Europe/London
|
||||||
|
cooldown:
|
||||||
|
default-days: 2
|
||||||
commit-message:
|
commit-message:
|
||||||
prefix: 'chore (deps): '
|
prefix: 'chore (deps): '
|
||||||
ignore:
|
ignore:
|
||||||
@ -25,16 +27,10 @@ updates:
|
|||||||
# see issue #2214 for rationale for each of these
|
# see issue #2214 for rationale for each of these
|
||||||
- dependency-name: '@xmldom/xmldom'
|
- dependency-name: '@xmldom/xmldom'
|
||||||
versions: [ '>=0.9.0' ]
|
versions: [ '>=0.9.0' ]
|
||||||
- dependency-name: 'bcryptjs'
|
|
||||||
versions: [ '>=3.0.0' ]
|
|
||||||
- dependency-name: 'bootstrap'
|
- dependency-name: 'bootstrap'
|
||||||
versions: [ '>=5.0.0' ]
|
versions: [ '>=5.0.0' ]
|
||||||
- dependency-name: 'bson'
|
|
||||||
versions: [ '>=5.0.0' ]
|
|
||||||
- dependency-name: 'cbor'
|
- dependency-name: 'cbor'
|
||||||
versions: [ '>=10.0.0' ]
|
versions: [ '>=10.0.0' ]
|
||||||
- dependency-name: 'cspell'
|
|
||||||
versions: [ '>=9.0.0' ]
|
|
||||||
- dependency-name: 'eslint'
|
- dependency-name: 'eslint'
|
||||||
versions: [ '>=10.0.0' ]
|
versions: [ '>=10.0.0' ]
|
||||||
- dependency-name: 'eslint-plugin-jsdoc'
|
- dependency-name: 'eslint-plugin-jsdoc'
|
||||||
@ -43,13 +39,14 @@ updates:
|
|||||||
versions: [ '>=0.4.0' ]
|
versions: [ '>=0.4.0' ]
|
||||||
- dependency-name: 'geodesy'
|
- dependency-name: 'geodesy'
|
||||||
versions: [ '>=2.0.0' ]
|
versions: [ '>=2.0.0' ]
|
||||||
- dependency-name: 'otpauth'
|
- dependency-name: 'jimp'
|
||||||
versions: [ '>=9.4.0' ]
|
versions: [ '1.6.1' ]
|
||||||
- dependency-name: 'webpack-dev-server'
|
- dependency-name: 'jq-web'
|
||||||
versions: [ '>=5.1.0' ]
|
versions: [ '>=0.6.0' ]
|
||||||
groups:
|
groups:
|
||||||
#
|
#
|
||||||
# Grouping so we don't get a seperate PR for every patch version.
|
# Grouping so patch version updates are batched together in a single PR
|
||||||
|
# and similarly with minor version updates
|
||||||
#
|
#
|
||||||
patch-updates:
|
patch-updates:
|
||||||
applies-to: version-updates
|
applies-to: version-updates
|
||||||
@ -57,16 +54,44 @@ updates:
|
|||||||
- '*'
|
- '*'
|
||||||
update-types:
|
update-types:
|
||||||
- 'patch'
|
- 'patch'
|
||||||
|
minor-updates:
|
||||||
|
applies-to: version-updates
|
||||||
|
patterns:
|
||||||
|
- '*'
|
||||||
|
update-types:
|
||||||
|
- 'minor'
|
||||||
|
|
||||||
# Can't enable this until we are using Node 24 as the latest actions all require this version
|
# Versioning on Github Actions
|
||||||
# - package-ecosystem: "github-actions"
|
- package-ecosystem: "github-actions"
|
||||||
# # Workflow files stored in the default location of `.github/workflows`; no need to
|
# Workflow files stored in the default location of `.github/workflows`; no need to
|
||||||
# # specify `/.github/workflows` for `directory`
|
# specify `/.github/workflows` for `directory`
|
||||||
# directory: '/'
|
directory: '/'
|
||||||
# schedule:
|
schedule:
|
||||||
# interval: 'weekly'
|
interval: 'weekly'
|
||||||
# day: 'friday'
|
day: 'friday'
|
||||||
# time: '03:00'
|
time: '03:00'
|
||||||
# timezone: Europe/London
|
timezone: Europe/London
|
||||||
# commit-message:
|
cooldown:
|
||||||
# prefix: 'chore (deps): '
|
default-days: 4
|
||||||
|
commit-message:
|
||||||
|
prefix: 'chore (deps): '
|
||||||
|
groups:
|
||||||
|
actions-dependencies:
|
||||||
|
patterns:
|
||||||
|
- "*"
|
||||||
|
|
||||||
|
- package-ecosystem: docker
|
||||||
|
directory: /
|
||||||
|
schedule:
|
||||||
|
interval: 'weekly'
|
||||||
|
day: 'friday'
|
||||||
|
time: '03:00'
|
||||||
|
timezone: Europe/London
|
||||||
|
cooldown:
|
||||||
|
default-days: 4
|
||||||
|
commit-message:
|
||||||
|
prefix: 'chore (deps): '
|
||||||
|
groups:
|
||||||
|
docker-dependencies:
|
||||||
|
patterns:
|
||||||
|
- "*"
|
||||||
|
|||||||
19
.github/workflows/master.yml
vendored
19
.github/workflows/master.yml
vendored
@ -16,18 +16,17 @@ jobs:
|
|||||||
pages: write
|
pages: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||||
|
|
||||||
- name: Set node version
|
- name: Set node version
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 24
|
||||||
registry-url: "https://registry.npmjs.org"
|
registry-url: "https://registry.npmjs.org"
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: |
|
run: |
|
||||||
export DETECT_CHROMEDRIVER_VERSION=true
|
npm ci
|
||||||
npm install
|
|
||||||
npm run setheapsize
|
npm run setheapsize
|
||||||
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
@ -45,9 +44,17 @@ jobs:
|
|||||||
- name: Generate sitemap
|
- name: Generate sitemap
|
||||||
run: npx grunt exec:sitemap
|
run: npx grunt exec:sitemap
|
||||||
|
|
||||||
|
- name: Setup Chrome
|
||||||
|
id: setup-chrome
|
||||||
|
if: success()
|
||||||
|
run: |
|
||||||
|
npx @puppeteer/browsers install chrome@148
|
||||||
|
echo chromedir=$(dirname $(find `pwd`/chrome/* -name chrome -print -quit)) >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: UI Tests
|
- name: UI Tests
|
||||||
if: success()
|
if: success()
|
||||||
run: |
|
run: |
|
||||||
|
export PATH=${{ steps.setup-chrome.outputs.chromedir }}:$PATH
|
||||||
sudo apt-get install xvfb
|
sudo apt-get install xvfb
|
||||||
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||||
|
|
||||||
@ -57,7 +64,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
if: success() && github.ref == 'refs/heads/master'
|
if: success() && github.ref == 'refs/heads/master'
|
||||||
uses: crazy-max/ghaction-github-pages@v3
|
uses: crazy-max/ghaction-github-pages@1d6ee9b181a81033a16bd707a1401afa978daab4 # v5.0.0
|
||||||
with:
|
with:
|
||||||
target_branch: gh-pages
|
target_branch: gh-pages
|
||||||
build_dir: ./build/prod
|
build_dir: ./build/prod
|
||||||
|
|||||||
45
.github/workflows/pull_requests.yml
vendored
45
.github/workflows/pull_requests.yml
vendored
@ -12,18 +12,17 @@ jobs:
|
|||||||
main:
|
main:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||||
|
|
||||||
- name: Set node version
|
- name: Set node version
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 24
|
||||||
registry-url: "https://registry.npmjs.org"
|
registry-url: "https://registry.npmjs.org"
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: |
|
run: |
|
||||||
export DETECT_CHROMEDRIVER_VERSION=true
|
npm ci
|
||||||
npm install
|
|
||||||
npm run setheapsize
|
npm run setheapsize
|
||||||
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
@ -38,20 +37,38 @@ jobs:
|
|||||||
if: success()
|
if: success()
|
||||||
run: npx grunt prod
|
run: npx grunt prod
|
||||||
|
|
||||||
|
- name: Upload Build Artefact
|
||||||
|
if: success()
|
||||||
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
|
with:
|
||||||
|
name: zipped-build
|
||||||
|
path: build/prod/*.zip
|
||||||
|
retention-days: 5
|
||||||
|
|
||||||
|
- name: Setup Chrome
|
||||||
|
id: setup-chrome
|
||||||
|
if: success()
|
||||||
|
run: |
|
||||||
|
npx @puppeteer/browsers install chrome@148
|
||||||
|
echo chromedir=$(dirname $(find `pwd`/chrome/* -name chrome -print -quit)) >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: UI Tests
|
||||||
|
if: success()
|
||||||
|
run: |
|
||||||
|
export PATH=${{ steps.setup-chrome.outputs.chromedir }}:$PATH
|
||||||
|
sudo apt-get install xvfb
|
||||||
|
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
if: success()
|
||||||
|
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
|
||||||
|
|
||||||
- name: Production Image Build
|
- name: Production Image Build
|
||||||
if: success()
|
if: success()
|
||||||
id: build-image
|
id: build-image
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
||||||
with:
|
with:
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||||
- name: UI Tests
|
|
||||||
if: success()
|
|
||||||
run: |
|
|
||||||
sudo apt-get install xvfb
|
|
||||||
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
|
||||||
|
|||||||
44
.github/workflows/releases.yml
vendored
44
.github/workflows/releases.yml
vendored
@ -22,17 +22,16 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||||
|
|
||||||
- name: Set node version
|
- name: Set node version
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 24
|
||||||
registry-url: "https://registry.npmjs.org"
|
registry-url: "https://registry.npmjs.org"
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: |
|
run: |
|
||||||
export DETECT_CHROMEDRIVER_VERSION=true
|
|
||||||
npm ci
|
npm ci
|
||||||
npm run setheapsize
|
npm run setheapsize
|
||||||
|
|
||||||
@ -47,20 +46,29 @@ jobs:
|
|||||||
- name: Production Build
|
- name: Production Build
|
||||||
run: npx grunt prod
|
run: npx grunt prod
|
||||||
|
|
||||||
- name: UI Tests
|
- name: Setup Chrome
|
||||||
|
id: setup-chrome
|
||||||
|
if: success()
|
||||||
run: |
|
run: |
|
||||||
|
npx @puppeteer/browsers install chrome@148
|
||||||
|
echo chromedir=$(dirname $(find `pwd`/chrome/* -name chrome -print -quit)) >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: UI Tests
|
||||||
|
if: success()
|
||||||
|
run: |
|
||||||
|
export PATH=${{ steps.setup-chrome.outputs.chromedir }}:$PATH
|
||||||
sudo apt-get install xvfb
|
sudo apt-get install xvfb
|
||||||
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
|
||||||
|
|
||||||
- name: Image Metadata
|
- name: Image Metadata
|
||||||
id: image-metadata
|
id: image-metadata
|
||||||
uses: docker/metadata-action@v4
|
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
|
||||||
with:
|
with:
|
||||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
tags: |
|
tags: |
|
||||||
@ -69,24 +77,24 @@ jobs:
|
|||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
|
|
||||||
- name: Log in to GHCR
|
- name: Log in to GHCR
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||||
with:
|
with:
|
||||||
registry: ${{ env.REGISTRY }}
|
registry: ${{ env.REGISTRY }}
|
||||||
username: ${{ env.REGISTRY_USER }}
|
username: ${{ env.REGISTRY_USER }}
|
||||||
password: ${{ env.REGISTRY_PASSWORD }}
|
password: ${{ env.REGISTRY_PASSWORD }}
|
||||||
|
|
||||||
- name: Publish to GHCR
|
- name: Publish to GHCR
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
tags: ${{ steps.image-metadata.outputs.tags }}
|
tags: ${{ steps.image-metadata.outputs.tags }}
|
||||||
labels: ${{ steps.image-metadata.outputs.labels }}
|
labels: ${{ steps.image-metadata.outputs.labels }}
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||||
|
|
||||||
- name: Upload Release Assets
|
- name: Upload Release Assets
|
||||||
id: upload-release-assets
|
id: upload-release-assets
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@29e53e917877a24fad85510ded594ab3c9ca12de # v2
|
||||||
with:
|
with:
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
file: build/prod/*.zip
|
file: build/prod/*.zip
|
||||||
@ -102,12 +110,12 @@ jobs:
|
|||||||
needs: main
|
needs: main
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||||
|
|
||||||
- name: Set node version
|
- name: Set node version
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 24
|
||||||
registry-url: "https://registry.npmjs.org"
|
registry-url: "https://registry.npmjs.org"
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
@ -116,11 +124,5 @@ jobs:
|
|||||||
- name: Create machine generated files
|
- name: Create machine generated files
|
||||||
run: npm run node
|
run: npm run node
|
||||||
|
|
||||||
- name: Reset node version ready for publish
|
|
||||||
uses: actions/setup-node@v6
|
|
||||||
with:
|
|
||||||
node-version: ^24.5
|
|
||||||
registry-url: "https://registry.npmjs.org"
|
|
||||||
|
|
||||||
- name: Publish to NPM
|
- name: Publish to NPM
|
||||||
run: npm publish
|
run: npm publish
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -10,6 +10,8 @@ src/core/config/OperationConfig.json
|
|||||||
src/core/operations/index.mjs
|
src/core/operations/index.mjs
|
||||||
src/node/config/OperationConfig.json
|
src/node/config/OperationConfig.json
|
||||||
src/node/index.mjs
|
src/node/index.mjs
|
||||||
|
tests/operations/index.mjs
|
||||||
**/*.DS_Store
|
**/*.DS_Store
|
||||||
tests/browser/output/*
|
tests/browser/output/*
|
||||||
.node-version
|
.node-version
|
||||||
|
chrome
|
||||||
|
|||||||
356
CHANGELOG.md
356
CHANGELOG.md
@ -13,6 +13,173 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
|
|
||||||
## Details
|
## Details
|
||||||
|
|
||||||
|
### [11.1.0] - 2026-06-13
|
||||||
|
This release includes a security fix ([#2557])
|
||||||
|
- Security: Add fix, and tests, for Lorem Ipsum DoS issue [@GCHQDeveloper581] | [#2557]
|
||||||
|
- chore (deps): bump the patch-updates group with 4 updates | [#2552]
|
||||||
|
- chore (deps): bump the actions-dependencies group with 2 updates | [#2551]
|
||||||
|
- chore (deps): bump the docker-dependencies group with 2 updates | [#2550]
|
||||||
|
- chore (deps): bump protobufjs from 8.5.0 to 8.6.2 in the minor-updates group | [#2553]
|
||||||
|
- Security Policy Update [@C85297] | [#2547]
|
||||||
|
- Fix spurious error messages generated during webpack build [@GCHQDeveloper581] | [#2545]
|
||||||
|
- chore (deps): bump shell-quote from 1.8.3 to 1.8.4 | [#2543]
|
||||||
|
- Implementing ROR13 feature [@Fufu-btw] | [#2539]
|
||||||
|
- New operation improvements [@jl5193] [@GCHQDeveloper581] | [#1431]
|
||||||
|
- Npm and yarn/major version updates [@GCHQDeveloper581] | [#2527]
|
||||||
|
- Update README to reflect AES Decrypt changes [@andreasrtv] | [#2502]
|
||||||
|
- feat: add Escape Smart Characters operation [@HarelKatz] | [#2391]
|
||||||
|
- feat: Get AES IV from input (QoL) [@andreasrtv] | [#2471]
|
||||||
|
- fix: validate text encoding options [@SyedIshmumAhnaf] | [#2497]
|
||||||
|
- chore (deps): bump the minor-updates group with 5 updates [@GCHQDeveloper581] | [#2500]
|
||||||
|
- chore (deps): bump the patch-updates group with 2 updates | [#2499]
|
||||||
|
- chore (deps): bump nginxinc/nginx-unprivileged from `df0e9ed` to `0a1e718` in the docker-dependencies group | [#2498]
|
||||||
|
- Add remove ANSI escape codes operation [@Louis-Ladd] [@GCHQDeveloper581] | [#2143]
|
||||||
|
- Fix option ingredients being overwriten [@C85297] | [#2341]
|
||||||
|
- chore (deps): bump qs and express | [#2478]
|
||||||
|
- chore (deps): bump tmp from 0.2.5 to 0.2.7 | [#2479]
|
||||||
|
- chore (deps): bump the patch-updates group across 1 directory with 6 updates | [#2463]
|
||||||
|
- chore (deps): bump the docker-dependencies group across 1 directory with 2 updates | [#2468]
|
||||||
|
- chore (deps): bump terser from 5.46.2 to 5.48.0 | [#2385]
|
||||||
|
- Make dependabot quieter [@GCHQDeveloper581] | [#2467]
|
||||||
|
- update sitemap [@Blank0120] | [#2443]
|
||||||
|
- Bump webpack-dev-server to 5.2.4 [@GCHQDeveloper581] | [#2417]
|
||||||
|
- Fix pgp tests [@GCHQDeveloper581] [@C85297] | [#2461]
|
||||||
|
- chore (deps): bump the patch-updates group across 1 directory with 4 updates | [#2438]
|
||||||
|
- chore (deps): bump docker/setup-buildx-action from 4.0.0 to 4.1.0 | [#2439]
|
||||||
|
- chore (deps): bump docker/login-action from 4.1.0 to 4.2.0 | [#2441]
|
||||||
|
- chore (deps): bump docker/metadata-action from 6.0.0 to 6.1.0 | [#2442]
|
||||||
|
- update bson [@Blank0120] [@GCHQDeveloper581] | [#2425]
|
||||||
|
- chore (deps): bump webpack from 5.106.2 to 5.107.1 | [#2428]
|
||||||
|
- chore (deps): bump protobufjs from 7.5.8 to 7.6.0 | [#2429]
|
||||||
|
- chore (deps): bump sql-formatter from 15.7.4 to 15.8.0 | [#2430]
|
||||||
|
- chore (deps): bump docker/build-push-action from 7.1.0 to 7.2.0 | [#2431]
|
||||||
|
- Fix flaky `npm run testui` [@lzandman] | [#2412]
|
||||||
|
- Include git ref in website download zip name [@C85297] | [#2339]
|
||||||
|
- Bump nginxinc/nginx-unprivileged from `808f784` to `b9f7ba1` | [#2389]
|
||||||
|
- Series Chart HTML Formatting fix [@C85297] | [#2403]
|
||||||
|
- Parse Ethernet Frame HTML formatting fix [@C85297] | [#2402]
|
||||||
|
- Parse IPv4 Header HTML formatting fix [@C85297] | [#2401]
|
||||||
|
- Update chromedriver, and install corresponding chrome in workflows (fixes build) [@GCHQDeveloper581] | [#2387]
|
||||||
|
- chore (deps): bump @codemirror/view from 6.41.1 to 6.43.0 | [#2384]
|
||||||
|
- chore (deps): bump globals from 17.5.0 to 17.6.0 | [#2386]
|
||||||
|
- chore (deps): bump the patch-updates group across 1 directory with 3 updates | [#2388]
|
||||||
|
- [StepSecurity] Apply security best practices [@GCHQDeveloper581] StepSecurity Bot <bot@stepsecurity.io> | [#2378]
|
||||||
|
- Build docker container for arm v7 as well [@GCHQDeveloper581] | [#2379]
|
||||||
|
- chore (deps): bump fast-uri from 3.1.0 to 3.1.2 | [#2372]
|
||||||
|
- update bcryptjs [@C85297] [@GCHQDeveloper581] | [#2368]
|
||||||
|
- chore (deps): bump picomatch from 2.3.1 to 2.3.2 | [#2370]
|
||||||
|
- chore (deps): bump ip-address from 10.1.0 to 10.2.0 | [#2371]
|
||||||
|
- chore (deps): bump axios from 1.15.0 to 1.16.0 | [#2369]
|
||||||
|
- feat(operation-wrap): add new Wrap operation to format text at specified line width [@0xff1ce] | [#1882]
|
||||||
|
- chore (deps): bump the patch-updates group across 1 directory with 5 updates | [#2354]
|
||||||
|
- chore (deps): bump docker/login-action from 3 to 4 | [#2363]
|
||||||
|
- chore (deps): bump docker/setup-buildx-action from 3 to 4 | [#2364]
|
||||||
|
- chore (deps): bump crazy-max/ghaction-github-pages from 3 to 5 | [#2365]
|
||||||
|
- chore (deps): bump docker/metadata-action from 4 to 6 | [#2366]
|
||||||
|
- chore (deps): bump docker/setup-qemu-action from 3 to 4 | [#2367]
|
||||||
|
- Update dependabot for Node 24. [@GCHQDeveloper581] | [#2361]
|
||||||
|
- chore (deps): bump uuid from 13.0.0 to 14.0.0 | [#2332]
|
||||||
|
- chore (deps): bump webpack-bundle-analyzer from 5.2.0 to 5.3.0 | [#2353]
|
||||||
|
- Fix all zeros after 16384 bytes with Blake3 [@zachbowden] [@GCHQDeveloper581] | [#2351]
|
||||||
|
|
||||||
|
## [11.0.0] - 2026-04-28
|
||||||
|
- Revert sitemap to v8.0.X to fix build/deploy on master [@GCHQDeveloper581] | [#2348]
|
||||||
|
- Node version update from 22 to 24 [@lzandman] [@GCHQDeveloper581] | [#2347]
|
||||||
|
- Fix XSS in Show Base64 offsets [@C85297] | [#2346]
|
||||||
|
- Make compatible with node >=22 [@GCHQDeveloper581] | [#2273]
|
||||||
|
- Fix(node): enable asynchronous operation support in Node.js API [@engin0223] [@GCHQDeveloper581] | [#2342]
|
||||||
|
- Feature: Change to nginx-unprivileged image for better kubernetes support [@hsolberg] | [#1922]
|
||||||
|
|
||||||
|
Breaking changes:
|
||||||
|
- Minimum supported node version - now v24 (was v16)
|
||||||
|
- Change of exported port on Docker Container - now 8080 (was 80)
|
||||||
|
- Node API now exports "bake" and "execute" functions as async.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Click to expand v10 minor versions</summary>
|
||||||
|
|
||||||
|
### [10.24.0] - 2026-04-27
|
||||||
|
- Update CONTRIBUTING.md [@GCHQDeveloper581] | [#2333]
|
||||||
|
- Fix, and link, Fernet tests [@GCHQDeveloper581] | [#2335]
|
||||||
|
- [#927] added parity bit operation [@j83305] | [#1036]
|
||||||
|
- Feature md link blanks [@BjoernAkAManf] [@GCHQDeveloper581] | [#660]
|
||||||
|
- Accessibility - Add support for screenreaders in operations search [@mattnotmitt] | [#1862]
|
||||||
|
- Added metadata extraction for UUID strings. [@ko80240] | [#2322]
|
||||||
|
- chore (deps): bump the patch-updates group with 6 updates | [#2330]
|
||||||
|
- chore (deps): bump @codemirror/search from 6.6.0 to 6.7.0 | [#2331]
|
||||||
|
- (Feature) Improve CI [@GCHQDeveloper581] | [#2328]
|
||||||
|
- Update dependabot.yml [@GCHQDeveloper581] | [#2326]
|
||||||
|
- chore (deps): bump lodash, grunt-legacy-log and grunt-legacy-util | [#2327]
|
||||||
|
- chore (deps): bump the patch-updates group with 6 updates [@GCHQDeveloper581] | [#2323]
|
||||||
|
- chore (deps): bump autoprefixer from 10.4.27 to 10.5.0 | [#2324]
|
||||||
|
- chore (deps): bump dompurify from 3.3.3 to 3.4.0 | [#2321]
|
||||||
|
- chore (deps): bump follow-redirects from 1.15.11 to 1.16.0 | [#2320]
|
||||||
|
- Regular Expression operation email address regex: Support IPv4 domains [@C85297] [@GCHQDeveloper581] | [#2167]
|
||||||
|
- Rewriting fixCryptoApiImports and fixSnackbarMarkup to js to make it OS agnostic [@BigYellowHammer] | [#2298]
|
||||||
|
- chore (deps): bump basic-ftp from 5.2.1 to 5.2.2 | [#2317]
|
||||||
|
- chore (deps): bump axios from 1.13.6 to 1.15.0 | [#2316]
|
||||||
|
- chore (deps): bump webpack from 5.105.4 to 5.106.0 | [#2315]
|
||||||
|
- chore (deps): bump basic-ftp from 5.2.0 to 5.2.1 | [#2313]
|
||||||
|
- Update vulnerable dependencies [@GCHQDeveloper581] | [#2311]
|
||||||
|
|
||||||
|
### [10.23.0] - 2026-04-06
|
||||||
|
- Properly escape HTML entities in sampleDelim to avoid XSS issue [@GCHQDeveloper581] | [#2307]
|
||||||
|
- chore (deps): bump lodash from 4.17.23 to 4.18.1 | [#2304]
|
||||||
|
- chore (deps): bump @codemirror/view from 6.40.0 to 6.41.0 | [#2305]
|
||||||
|
- chore (deps): bump the patch-updates group with 2 updates | [#2303]
|
||||||
|
- chore (deps): bump @xmldom/xmldom from 0.8.11 to 0.8.12 | [#2302]
|
||||||
|
- chore (deps): bump picomatch | [#2299]
|
||||||
|
- chore (deps): bump node-forge from 1.3.3 to 1.4.0 | [#2297]
|
||||||
|
- chore (deps): bump the patch-updates group with 3 updates | [#2296]
|
||||||
|
- chore (deps) bump chromedriver from 130.0.4 to 146.0.6 [@GCHQDeveloper581] | [#2292]
|
||||||
|
- ParseEthernetFrame - Fix vlan calculation [@Kalkran] | [#2295]
|
||||||
|
- Add pull request template with AI usage disclosure [@C85297] | [#2279]
|
||||||
|
- fix: return empty output for zero-length To Modhex input [@saschabuehrle] | [#2249]
|
||||||
|
- Added tab focus to top banner and navigation to About/Support Modal [@j264415] | [#1733]
|
||||||
|
- Add Parse Ethernet frame Operation, allow Parse IPv4 Header to cascade [@Kalkran] | [#1722]
|
||||||
|
- Selection and Deselection of autobake checkbox using keyboard [@j264415] | [#1727]
|
||||||
|
- chore (deps): bump @babel/runtime from 7.28.6 to 7.29.2 | [#2263]
|
||||||
|
- Add more helpful error for when numerical ingredient is left empty [@Lamby777] [@C85297] | [#1540]
|
||||||
|
- chore (deps): bump @codemirror/view from 6.39.17 to 6.40.0 | [#2262]
|
||||||
|
- Bump flatted from 3.3.2 to 3.4.2 [@GCHQDeveloper581] | [#2266]
|
||||||
|
- feat: add Raw option for Jq operation [@rtpt-romankarwacik] | [#2237]
|
||||||
|
- chore (deps): bump core-js from 3.48.0 to 3.49.0 | [#2261]
|
||||||
|
- chore (deps): bump the patch-updates group with 6 updates | [#2260]
|
||||||
|
- Add Extract Audio Metadata operation [@d0s1nt] [@GCHQDeveloper581] | [#2170]
|
||||||
|
- Fix Jq issue [@GCHQDeveloper581] | [#2210]
|
||||||
|
- Configure dependabot updates [@GCHQDeveloper581] | [#2259]
|
||||||
|
- fix(A1Z26): return empty string instead of empty array for empty input [@brick-pixel] | [#2257]
|
||||||
|
- Fix broken Docker link in README [@am-periphery] | [#2250]
|
||||||
|
- Update some dependencies, including a number causing npm audit warnings [@GCHQDeveloper581] | [#2236]
|
||||||
|
- Bump axios from 1.7.9 to 1.13.6 | [#2234]
|
||||||
|
- Bump jws from 3.2.2 to 3.2.3 | [#2235]
|
||||||
|
- Bump pbkdf2 from 3.1.2 to 3.1.5 | [#2229]
|
||||||
|
- Bump form-data from 4.0.1 to 4.0.5 | [#2228]
|
||||||
|
- Bump basic-ftp from 5.0.5 to 5.2.0 | [#2231]
|
||||||
|
- feat: add ARM disassembler operation [@thomasxm] | [#2156]
|
||||||
|
- Add Text/Integer Converter operation [@p-leriche] [@GCHQDeveloper581] | [#2213]
|
||||||
|
- Feat/rc6 add RC6 Encrypt/Decrypt operations [@thomasxm] | [#2163]
|
||||||
|
- [bugfix] Add Bootstrap form style for CodeMirror editor [@Swonkie] | [#2161]
|
||||||
|
- Add Flask Session operations (Decode, Sign, Verify) [@ThePlayer372-FR] | [#2208]
|
||||||
|
- fix: `jq-web` -> `jq-wasm`, includes `jq` version `1.8.1` [@W-Floyd] [@GCHQDeveloper581] | [#2223]
|
||||||
|
- Bump jsonwebtoken from 8.5.1 to 9.0.0 [@GCHQDeveloper581] | [#2219]
|
||||||
|
- Bump basic-ftp from 5.0.5 to 5.2.0 | [#2218]
|
||||||
|
- feat: add random integer generation operation [@cktgh] | [#2151]
|
||||||
|
- Add BigInt utility functions for number theory operations [@p-leriche] [@GCHQDeveloper581] | [#2205]
|
||||||
|
- Improve SQL Beautify: use sql-formatter and support bind variables [@aby-jo] [@GCHQDeveloper581] | [#2071]
|
||||||
|
- update tesseract.js to 6.0.1 [@atsiv1] | [#2133]
|
||||||
|
- Fix hint tooltip display issues [@bartvanandel] | [#2017]
|
||||||
|
- Simplify babel dependencies [@GCHQDeveloper581] | [#2204]
|
||||||
|
- Dependency updates [@GCHQDeveloper581] | [#2201]
|
||||||
|
- Fix: Move Magic checks from Escape to Unescape Unicode Characters [@fjh1997] | [#2195]
|
||||||
|
- Paste spreadsheets as text [@C85297] | [#2200]
|
||||||
|
- Fix Roboto Mono font [@C85297] | [#2199]
|
||||||
|
- Fix return of buffer for PNG QR image generation [@GCHQDeveloper581] [@C85297] | [#2125]
|
||||||
|
- Update JIMP [@C85297] | [#2171]
|
||||||
|
- Overwrite NGINX maintainer label [@C85297] | [#2194]
|
||||||
|
- Bump v10.22.1 [@GCHQDeveloper581] | [#2193]
|
||||||
|
- Fix npm publish - Run "npm ci" and "npm run node" under node 18 then switch to node 24.5 [@GCHQDeveloper581] | [#2192]
|
||||||
|
|
||||||
### [10.22.0] - 2026-02-11
|
### [10.22.0] - 2026-02-11
|
||||||
- Separate npm publish out into separate job and run with Node 24.5 [@GCHQDeveloper581] | [#2188]
|
- Separate npm publish out into separate job and run with Node 24.5 [@GCHQDeveloper581] | [#2188]
|
||||||
- Fixed Percent delimiter for hex encoding [@beneri] [@C85297] | [#2137]
|
- Fixed Percent delimiter for hex encoding [@beneri] [@C85297] | [#2137]
|
||||||
@ -195,6 +362,8 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
- Added 'Levenshtein Distance' operation [@mikecat] | [#1498]
|
- Added 'Levenshtein Distance' operation [@mikecat] | [#1498]
|
||||||
- Added 'Swap case' operation [@mikecat] | [#1499]
|
- Added 'Swap case' operation [@mikecat] | [#1499]
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
## [10.0.0] - 2023-03-22
|
## [10.0.0] - 2023-03-22
|
||||||
- [Full details explained here](https://github.com/gchq/CyberChef/wiki/Character-encoding,-EOL-separators,-and-editor-features)
|
- [Full details explained here](https://github.com/gchq/CyberChef/wiki/Character-encoding,-EOL-separators,-and-editor-features)
|
||||||
- Status bars added to the Input and Output [@n1474335] | [#1405]
|
- Status bars added to the Input and Output [@n1474335] | [#1405]
|
||||||
@ -538,6 +707,10 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
## [4.0.0] - 2016-11-28
|
## [4.0.0] - 2016-11-28
|
||||||
- Initial open source commit [@n1474335] | [b1d73a72](https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306)
|
- Initial open source commit [@n1474335] | [b1d73a72](https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306)
|
||||||
|
|
||||||
|
[11.1.0]: https://github.com/gchq/CyberChef/releases/tag/v11.1.0
|
||||||
|
[11.0.0]: https://github.com/gchq/CyberChef/releases/tag/v11.0.0
|
||||||
|
[10.24.0]: https://github.com/gchq/CyberChef/releases/tag/v10.24.0
|
||||||
|
[10.23.0]: https://github.com/gchq/CyberChef/releases/tag/v10.23.0
|
||||||
[10.22.0]: https://github.com/gchq/CyberChef/releases/tag/v10.22.0
|
[10.22.0]: https://github.com/gchq/CyberChef/releases/tag/v10.22.0
|
||||||
[10.21.0]: https://github.com/gchq/CyberChef/releases/tag/v10.21.0
|
[10.21.0]: https://github.com/gchq/CyberChef/releases/tag/v10.21.0
|
||||||
[10.20.0]: https://github.com/gchq/CyberChef/releases/tag/v10.20.0
|
[10.20.0]: https://github.com/gchq/CyberChef/releases/tag/v10.20.0
|
||||||
@ -552,7 +725,7 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
[10.11.0]: https://github.com/gchq/CyberChef/releases/tag/v10.11.0
|
[10.11.0]: https://github.com/gchq/CyberChef/releases/tag/v10.11.0
|
||||||
[10.10.0]: https://github.com/gchq/CyberChef/releases/tag/v10.10.0
|
[10.10.0]: https://github.com/gchq/CyberChef/releases/tag/v10.10.0
|
||||||
[10.9.0]: https://github.com/gchq/CyberChef/releases/tag/v10.9.0
|
[10.9.0]: https://github.com/gchq/CyberChef/releases/tag/v10.9.0
|
||||||
[10.8.0]: https://github.com/gchq/CyberChef/releases/tag/v10.7.0
|
[10.8.0]: https://github.com/gchq/CyberChef/releases/tag/v10.8.0
|
||||||
[10.7.0]: https://github.com/gchq/CyberChef/releases/tag/v10.7.0
|
[10.7.0]: https://github.com/gchq/CyberChef/releases/tag/v10.7.0
|
||||||
[10.6.0]: https://github.com/gchq/CyberChef/releases/tag/v10.6.0
|
[10.6.0]: https://github.com/gchq/CyberChef/releases/tag/v10.6.0
|
||||||
[10.5.0]: https://github.com/gchq/CyberChef/releases/tag/v10.5.0
|
[10.5.0]: https://github.com/gchq/CyberChef/releases/tag/v10.5.0
|
||||||
@ -797,6 +970,37 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
[@t-martine]: https://github.com/t-martine
|
[@t-martine]: https://github.com/t-martine
|
||||||
[@wesinator]: https://github.com/wesinator
|
[@wesinator]: https://github.com/wesinator
|
||||||
[@Raka-loah]: https://github.com/Raka-loah
|
[@Raka-loah]: https://github.com/Raka-loah
|
||||||
|
[@Kalkran]: https://github.com/Kalkran
|
||||||
|
[@saschabuehrle]: https://github.com/saschabuehrle
|
||||||
|
[@j264415]: https://github.com/j264415
|
||||||
|
[@Lamby777]: https://github.com/Lamby777
|
||||||
|
[@rtpt-romankarwacik]: https://github.com/rtpt-romankarwacik
|
||||||
|
[@d0s1nt]: https://github.com/d0s1nt
|
||||||
|
[@brick-pixel]: https://github.com/brick-pixel
|
||||||
|
[@am-periphery]: https://github.com/am-periphery
|
||||||
|
[@p-leriche]: https://github.com/p-leriche
|
||||||
|
[@Swonkie]: https://github.com/Swonkie
|
||||||
|
[@ThePlayer372-FR]: https://github.com/ThePlayer372-FR
|
||||||
|
[@W-Floyd]: https://github.com/W-Floyd
|
||||||
|
[@cktgh]: https://github.com/cktgh
|
||||||
|
[@aby-jo]: https://github.com/aby-jo
|
||||||
|
[@atsiv1]: https://github.com/atsiv1
|
||||||
|
[@fjh1997]: https://github.com/fjh1997
|
||||||
|
[@j83305]: https://github.com/j83305
|
||||||
|
[@BjoernAkAManf]: https://github.com/BjoernAkAManf
|
||||||
|
[@ko80240]: https://github.com/ko80240
|
||||||
|
[@BigYellowHammer]: https://github.com/BigYellowHammer
|
||||||
|
[@hsolberg]: https://github.com/hsolberg
|
||||||
|
[@lzandman]: https://github.com/lzandman
|
||||||
|
[@engin0223]: https://github.com/engin0223
|
||||||
|
[@Fufu-btw]: https://github.com/Fufu-btw
|
||||||
|
[@jl5193]: https://github.com/jl5193
|
||||||
|
[@andreasrtv]: https://github.com/andreasrtv
|
||||||
|
[@HarelKatz]: https://github.com/HarelKatz
|
||||||
|
[@SyedIshmumAhnaf]: https://github.com/SyedIshmumAhnaf
|
||||||
|
[@Louis-Ladd]: https://github.com/Louis-Ladd
|
||||||
|
[@Blank0120]: https://github.com/Blank0120
|
||||||
|
[@zachbowden]: https://github.com/zachbowden
|
||||||
|
|
||||||
|
|
||||||
[8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
|
[8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
|
||||||
@ -1010,4 +1214,154 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
[#2183]: https://github.com/gchq/CyberChef/pull/2183
|
[#2183]: https://github.com/gchq/CyberChef/pull/2183
|
||||||
[#2182]: https://github.com/gchq/CyberChef/pull/2182
|
[#2182]: https://github.com/gchq/CyberChef/pull/2182
|
||||||
[#2181]: https://github.com/gchq/CyberChef/pull/2181
|
[#2181]: https://github.com/gchq/CyberChef/pull/2181
|
||||||
|
[#2307]: https://github.com/gchq/CyberChef/pull/2307
|
||||||
|
[#2304]: https://github.com/gchq/CyberChef/pull/2304
|
||||||
|
[#2305]: https://github.com/gchq/CyberChef/pull/2305
|
||||||
|
[#2303]: https://github.com/gchq/CyberChef/pull/2303
|
||||||
|
[#2302]: https://github.com/gchq/CyberChef/pull/2302
|
||||||
|
[#2299]: https://github.com/gchq/CyberChef/pull/2299
|
||||||
|
[#2297]: https://github.com/gchq/CyberChef/pull/2297
|
||||||
|
[#2296]: https://github.com/gchq/CyberChef/pull/2296
|
||||||
|
[#2292]: https://github.com/gchq/CyberChef/pull/2292
|
||||||
|
[#2295]: https://github.com/gchq/CyberChef/pull/2295
|
||||||
|
[#2279]: https://github.com/gchq/CyberChef/pull/2279
|
||||||
|
[#2249]: https://github.com/gchq/CyberChef/pull/2249
|
||||||
|
[#1733]: https://github.com/gchq/CyberChef/pull/1733
|
||||||
|
[#1722]: https://github.com/gchq/CyberChef/pull/1722
|
||||||
|
[#1727]: https://github.com/gchq/CyberChef/pull/1727
|
||||||
|
[#2263]: https://github.com/gchq/CyberChef/pull/2263
|
||||||
|
[#1540]: https://github.com/gchq/CyberChef/pull/1540
|
||||||
|
[#2262]: https://github.com/gchq/CyberChef/pull/2262
|
||||||
|
[#2266]: https://github.com/gchq/CyberChef/pull/2266
|
||||||
|
[#2237]: https://github.com/gchq/CyberChef/pull/2237
|
||||||
|
[#2261]: https://github.com/gchq/CyberChef/pull/2261
|
||||||
|
[#2260]: https://github.com/gchq/CyberChef/pull/2260
|
||||||
|
[#2170]: https://github.com/gchq/CyberChef/pull/2170
|
||||||
|
[#2210]: https://github.com/gchq/CyberChef/pull/2210
|
||||||
|
[#2259]: https://github.com/gchq/CyberChef/pull/2259
|
||||||
|
[#2257]: https://github.com/gchq/CyberChef/pull/2257
|
||||||
|
[#2250]: https://github.com/gchq/CyberChef/pull/2250
|
||||||
|
[#2236]: https://github.com/gchq/CyberChef/pull/2236
|
||||||
|
[#2234]: https://github.com/gchq/CyberChef/pull/2234
|
||||||
|
[#2235]: https://github.com/gchq/CyberChef/pull/2235
|
||||||
|
[#2229]: https://github.com/gchq/CyberChef/pull/2229
|
||||||
|
[#2228]: https://github.com/gchq/CyberChef/pull/2228
|
||||||
|
[#2231]: https://github.com/gchq/CyberChef/pull/2231
|
||||||
|
[#2156]: https://github.com/gchq/CyberChef/pull/2156
|
||||||
|
[#2213]: https://github.com/gchq/CyberChef/pull/2213
|
||||||
|
[#2163]: https://github.com/gchq/CyberChef/pull/2163
|
||||||
|
[#2161]: https://github.com/gchq/CyberChef/pull/2161
|
||||||
|
[#2208]: https://github.com/gchq/CyberChef/pull/2208
|
||||||
|
[#2223]: https://github.com/gchq/CyberChef/pull/2223
|
||||||
|
[#2219]: https://github.com/gchq/CyberChef/pull/2219
|
||||||
|
[#2218]: https://github.com/gchq/CyberChef/pull/2218
|
||||||
|
[#2151]: https://github.com/gchq/CyberChef/pull/2151
|
||||||
|
[#2205]: https://github.com/gchq/CyberChef/pull/2205
|
||||||
|
[#2071]: https://github.com/gchq/CyberChef/pull/2071
|
||||||
|
[#2133]: https://github.com/gchq/CyberChef/pull/2133
|
||||||
|
[#2017]: https://github.com/gchq/CyberChef/pull/2017
|
||||||
|
[#2204]: https://github.com/gchq/CyberChef/pull/2204
|
||||||
|
[#2201]: https://github.com/gchq/CyberChef/pull/2201
|
||||||
|
[#2195]: https://github.com/gchq/CyberChef/pull/2195
|
||||||
|
[#2200]: https://github.com/gchq/CyberChef/pull/2200
|
||||||
|
[#2199]: https://github.com/gchq/CyberChef/pull/2199
|
||||||
|
[#2125]: https://github.com/gchq/CyberChef/pull/2125
|
||||||
|
[#2171]: https://github.com/gchq/CyberChef/pull/2171
|
||||||
|
[#2194]: https://github.com/gchq/CyberChef/pull/2194
|
||||||
|
[#2193]: https://github.com/gchq/CyberChef/pull/2193
|
||||||
|
[#2192]: https://github.com/gchq/CyberChef/pull/2192
|
||||||
|
[#2333]: https://github.com/gchq/CyberChef/pull/2333
|
||||||
|
[#2335]: https://github.com/gchq/CyberChef/pull/2335
|
||||||
|
[#1036]: https://github.com/gchq/CyberChef/pull/1036
|
||||||
|
[#660]: https://github.com/gchq/CyberChef/pull/660
|
||||||
|
[#1862]: https://github.com/gchq/CyberChef/pull/1862
|
||||||
|
[#2322]: https://github.com/gchq/CyberChef/pull/2322
|
||||||
|
[#2330]: https://github.com/gchq/CyberChef/pull/2330
|
||||||
|
[#2331]: https://github.com/gchq/CyberChef/pull/2331
|
||||||
|
[#2328]: https://github.com/gchq/CyberChef/pull/2328
|
||||||
|
[#2326]: https://github.com/gchq/CyberChef/pull/2326
|
||||||
|
[#2327]: https://github.com/gchq/CyberChef/pull/2327
|
||||||
|
[#2323]: https://github.com/gchq/CyberChef/pull/2323
|
||||||
|
[#2324]: https://github.com/gchq/CyberChef/pull/2324
|
||||||
|
[#2321]: https://github.com/gchq/CyberChef/pull/2321
|
||||||
|
[#2320]: https://github.com/gchq/CyberChef/pull/2320
|
||||||
|
[#2167]: https://github.com/gchq/CyberChef/pull/2167
|
||||||
|
[#2298]: https://github.com/gchq/CyberChef/pull/2298
|
||||||
|
[#2317]: https://github.com/gchq/CyberChef/pull/2317
|
||||||
|
[#2316]: https://github.com/gchq/CyberChef/pull/2316
|
||||||
|
[#2315]: https://github.com/gchq/CyberChef/pull/2315
|
||||||
|
[#2313]: https://github.com/gchq/CyberChef/pull/2313
|
||||||
|
[#2311]: https://github.com/gchq/CyberChef/pull/2311
|
||||||
|
[#2348]: https://github.com/gchq/CyberChef/pull/2348
|
||||||
|
[#2347]: https://github.com/gchq/CyberChef/pull/2347
|
||||||
|
[#2346]: https://github.com/gchq/CyberChef/pull/2346
|
||||||
|
[#2273]: https://github.com/gchq/CyberChef/pull/2273
|
||||||
|
[#2342]: https://github.com/gchq/CyberChef/pull/2342
|
||||||
|
[#1922]: https://github.com/gchq/CyberChef/pull/1922
|
||||||
|
[#2557]: https://github.com/gchq/CyberChef/pull/2557
|
||||||
|
[#2552]: https://github.com/gchq/CyberChef/pull/2552
|
||||||
|
[#2551]: https://github.com/gchq/CyberChef/pull/2551
|
||||||
|
[#2550]: https://github.com/gchq/CyberChef/pull/2550
|
||||||
|
[#2553]: https://github.com/gchq/CyberChef/pull/2553
|
||||||
|
[#2547]: https://github.com/gchq/CyberChef/pull/2547
|
||||||
|
[#2545]: https://github.com/gchq/CyberChef/pull/2545
|
||||||
|
[#2543]: https://github.com/gchq/CyberChef/pull/2543
|
||||||
|
[#2539]: https://github.com/gchq/CyberChef/pull/2539
|
||||||
|
[#1431]: https://github.com/gchq/CyberChef/pull/1431
|
||||||
|
[#2527]: https://github.com/gchq/CyberChef/pull/2527
|
||||||
|
[#2502]: https://github.com/gchq/CyberChef/pull/2502
|
||||||
|
[#2391]: https://github.com/gchq/CyberChef/pull/2391
|
||||||
|
[#2471]: https://github.com/gchq/CyberChef/pull/2471
|
||||||
|
[#2497]: https://github.com/gchq/CyberChef/pull/2497
|
||||||
|
[#2500]: https://github.com/gchq/CyberChef/pull/2500
|
||||||
|
[#2499]: https://github.com/gchq/CyberChef/pull/2499
|
||||||
|
[#2498]: https://github.com/gchq/CyberChef/pull/2498
|
||||||
|
[#2143]: https://github.com/gchq/CyberChef/pull/2143
|
||||||
|
[#2341]: https://github.com/gchq/CyberChef/pull/2341
|
||||||
|
[#2478]: https://github.com/gchq/CyberChef/pull/2478
|
||||||
|
[#2479]: https://github.com/gchq/CyberChef/pull/2479
|
||||||
|
[#2463]: https://github.com/gchq/CyberChef/pull/2463
|
||||||
|
[#2468]: https://github.com/gchq/CyberChef/pull/2468
|
||||||
|
[#2385]: https://github.com/gchq/CyberChef/pull/2385
|
||||||
|
[#2467]: https://github.com/gchq/CyberChef/pull/2467
|
||||||
|
[#2443]: https://github.com/gchq/CyberChef/pull/2443
|
||||||
|
[#2417]: https://github.com/gchq/CyberChef/pull/2417
|
||||||
|
[#2461]: https://github.com/gchq/CyberChef/pull/2461
|
||||||
|
[#2438]: https://github.com/gchq/CyberChef/pull/2438
|
||||||
|
[#2439]: https://github.com/gchq/CyberChef/pull/2439
|
||||||
|
[#2441]: https://github.com/gchq/CyberChef/pull/2441
|
||||||
|
[#2442]: https://github.com/gchq/CyberChef/pull/2442
|
||||||
|
[#2425]: https://github.com/gchq/CyberChef/pull/2425
|
||||||
|
[#2428]: https://github.com/gchq/CyberChef/pull/2428
|
||||||
|
[#2429]: https://github.com/gchq/CyberChef/pull/2429
|
||||||
|
[#2430]: https://github.com/gchq/CyberChef/pull/2430
|
||||||
|
[#2431]: https://github.com/gchq/CyberChef/pull/2431
|
||||||
|
[#2412]: https://github.com/gchq/CyberChef/pull/2412
|
||||||
|
[#2339]: https://github.com/gchq/CyberChef/pull/2339
|
||||||
|
[#2389]: https://github.com/gchq/CyberChef/pull/2389
|
||||||
|
[#2403]: https://github.com/gchq/CyberChef/pull/2403
|
||||||
|
[#2402]: https://github.com/gchq/CyberChef/pull/2402
|
||||||
|
[#2401]: https://github.com/gchq/CyberChef/pull/2401
|
||||||
|
[#2387]: https://github.com/gchq/CyberChef/pull/2387
|
||||||
|
[#2384]: https://github.com/gchq/CyberChef/pull/2384
|
||||||
|
[#2386]: https://github.com/gchq/CyberChef/pull/2386
|
||||||
|
[#2388]: https://github.com/gchq/CyberChef/pull/2388
|
||||||
|
[#2378]: https://github.com/gchq/CyberChef/pull/2378
|
||||||
|
[#2379]: https://github.com/gchq/CyberChef/pull/2379
|
||||||
|
[#2372]: https://github.com/gchq/CyberChef/pull/2372
|
||||||
|
[#2368]: https://github.com/gchq/CyberChef/pull/2368
|
||||||
|
[#2370]: https://github.com/gchq/CyberChef/pull/2370
|
||||||
|
[#2371]: https://github.com/gchq/CyberChef/pull/2371
|
||||||
|
[#2369]: https://github.com/gchq/CyberChef/pull/2369
|
||||||
|
[#1882]: https://github.com/gchq/CyberChef/pull/1882
|
||||||
|
[#2354]: https://github.com/gchq/CyberChef/pull/2354
|
||||||
|
[#2363]: https://github.com/gchq/CyberChef/pull/2363
|
||||||
|
[#2364]: https://github.com/gchq/CyberChef/pull/2364
|
||||||
|
[#2365]: https://github.com/gchq/CyberChef/pull/2365
|
||||||
|
[#2366]: https://github.com/gchq/CyberChef/pull/2366
|
||||||
|
[#2367]: https://github.com/gchq/CyberChef/pull/2367
|
||||||
|
[#2361]: https://github.com/gchq/CyberChef/pull/2361
|
||||||
|
[#2332]: https://github.com/gchq/CyberChef/pull/2332
|
||||||
|
[#2353]: https://github.com/gchq/CyberChef/pull/2353
|
||||||
|
[#2351]: https://github.com/gchq/CyberChef/pull/2351
|
||||||
|
|
||||||
|
|||||||
@ -6,10 +6,13 @@ There are lots of opportunities to contribute to CyberChef. If you want ideas, t
|
|||||||
|
|
||||||
Before your contributions can be accepted, you must:
|
Before your contributions can be accepted, you must:
|
||||||
|
|
||||||
- Sign the [GCHQ Contributor Licence Agreement](https://cla-assistant.io/gchq/CyberChef)
|
- Fork the CyberChef repo
|
||||||
|
- Create a new branch within your fork for the changes
|
||||||
- Push your changes to your fork.
|
- Push your changes to your fork.
|
||||||
|
- Sign the [GCHQ Contributor Licence Agreement](https://cla-assistant.io/gchq/CyberChef)
|
||||||
- Submit a pull request.
|
- Submit a pull request.
|
||||||
|
|
||||||
|
Please note that we will ***reject*** pull requests from the master branch of your fork owing to the mess it makes of our own working repositories and the extra work entailed.
|
||||||
|
|
||||||
## Coding conventions
|
## Coding conventions
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
# Modifier --platform=$BUILDPLATFORM limits the platform to "BUILDPLATFORM" during buildx multi-platform builds
|
# Modifier --platform=$BUILDPLATFORM limits the platform to "BUILDPLATFORM" during buildx multi-platform builds
|
||||||
# This is because npm "chromedriver" package is not compatiable with all platforms
|
# This is because npm "chromedriver" package is not compatiable with all platforms
|
||||||
# For more info see: https://docs.docker.com/build/building/multi-platform/#cross-compilation
|
# For more info see: https://docs.docker.com/build/building/multi-platform/#cross-compilation
|
||||||
FROM --platform=$BUILDPLATFORM node:18-alpine AS builder
|
FROM --platform=$BUILDPLATFORM node:24-alpine@sha256:fb71d01345f11b708a3553c66e7c74074f2d506400ea81973343d915cb64eef0 AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ RUN npm run build
|
|||||||
#########################################
|
#########################################
|
||||||
# Package static build files into nginx #
|
# Package static build files into nginx #
|
||||||
#########################################
|
#########################################
|
||||||
FROM nginx:stable-alpine AS cyberchef
|
FROM nginxinc/nginx-unprivileged:stable-alpine@sha256:37f356a5eba5d187365b4f59cd6cc29f1f922ad18146d554b576a80983377e6a AS cyberchef
|
||||||
|
|
||||||
LABEL maintainer="GCHQ <oss@gchq.gov.uk>"
|
LABEL maintainer="GCHQ <oss@gchq.gov.uk>"
|
||||||
|
|
||||||
|
|||||||
35
Gruntfile.js
35
Gruntfile.js
@ -6,7 +6,7 @@ const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPl
|
|||||||
const glob = require("glob");
|
const glob = require("glob");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
const nodeFlags = "--experimental-modules --experimental-json-modules --experimental-specifier-resolution=node --no-warnings --no-deprecation";
|
const nodeFlags = "--no-warnings --no-deprecation";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grunt configuration for building the app in various formats.
|
* Grunt configuration for building the app in various formats.
|
||||||
@ -89,6 +89,8 @@ module.exports = function (grunt) {
|
|||||||
const compileYear = grunt.template.today("UTC:yyyy"),
|
const compileYear = grunt.template.today("UTC:yyyy"),
|
||||||
compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC",
|
compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC",
|
||||||
pkg = grunt.file.readJSON("package.json"),
|
pkg = grunt.file.readJSON("package.json"),
|
||||||
|
version = process.env.GITHUB_SHA || `v${pkg.version}`,
|
||||||
|
downloadZipFilename = `CyberChef_${version}.zip`,
|
||||||
webpackConfig = require("./webpack.config.js"),
|
webpackConfig = require("./webpack.config.js"),
|
||||||
BUILD_CONSTANTS = {
|
BUILD_CONSTANTS = {
|
||||||
COMPILE_YEAR: JSON.stringify(compileYear),
|
COMPILE_YEAR: JSON.stringify(compileYear),
|
||||||
@ -129,7 +131,9 @@ module.exports = function (grunt) {
|
|||||||
chunks: ["main"],
|
chunks: ["main"],
|
||||||
compileYear: compileYear,
|
compileYear: compileYear,
|
||||||
compileTime: compileTime,
|
compileTime: compileTime,
|
||||||
version: pkg.version,
|
version: version,
|
||||||
|
latestReleaseVersion: pkg.version,
|
||||||
|
downloadZipFilename: downloadZipFilename,
|
||||||
minify: {
|
minify: {
|
||||||
removeComments: true,
|
removeComments: true,
|
||||||
collapseWhitespace: true,
|
collapseWhitespace: true,
|
||||||
@ -140,7 +144,8 @@ module.exports = function (grunt) {
|
|||||||
new BundleAnalyzerPlugin({
|
new BundleAnalyzerPlugin({
|
||||||
analyzerMode: "static",
|
analyzerMode: "static",
|
||||||
reportFilename: "BundleAnalyzerReport.html",
|
reportFilename: "BundleAnalyzerReport.html",
|
||||||
openAnalyzer: false
|
openAnalyzer: false,
|
||||||
|
excludeAssets: /.*Worker.js/
|
||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@ -245,7 +250,7 @@ module.exports = function (grunt) {
|
|||||||
"!build/prod/index.html",
|
"!build/prod/index.html",
|
||||||
"!build/prod/BundleAnalyzerReport.html",
|
"!build/prod/BundleAnalyzerReport.html",
|
||||||
],
|
],
|
||||||
dest: `build/prod/CyberChef_v${pkg.version}.zip`
|
dest: `build/prod/${downloadZipFilename}`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
connect: {
|
connect: {
|
||||||
@ -333,12 +338,12 @@ module.exports = function (grunt) {
|
|||||||
switch (process.platform) {
|
switch (process.platform) {
|
||||||
case "darwin":
|
case "darwin":
|
||||||
return chainCommands([
|
return chainCommands([
|
||||||
`shasum -a 256 build/prod/CyberChef_v${pkg.version}.zip | awk '{print $1;}' > build/prod/sha256digest.txt`,
|
`shasum -a 256 build/prod/${downloadZipFilename} | awk '{print $1;}' > build/prod/sha256digest.txt`,
|
||||||
`sed -i '' -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`
|
`sed -i '' -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`
|
||||||
]);
|
]);
|
||||||
default:
|
default:
|
||||||
return chainCommands([
|
return chainCommands([
|
||||||
`sha256sum build/prod/CyberChef_v${pkg.version}.zip | awk '{print $1;}' > build/prod/sha256digest.txt`,
|
`sha256sum build/prod/${downloadZipFilename} | awk '{print $1;}' > build/prod/sha256digest.txt`,
|
||||||
`sed -i -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`
|
`sed -i -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -411,25 +416,11 @@ module.exports = function (grunt) {
|
|||||||
stdout: false,
|
stdout: false,
|
||||||
},
|
},
|
||||||
fixCryptoApiImports: {
|
fixCryptoApiImports: {
|
||||||
command: function () {
|
command: `node ${nodeFlags} src/core/config/scripts/fixCryptoApiImports.mjs`,
|
||||||
switch (process.platform) {
|
|
||||||
case "darwin":
|
|
||||||
return `find ./node_modules/crypto-api/src/ \\( -type d -name .git -prune \\) -o -type f -print0 | xargs -0 sed -i '' -e '/\\.mjs/!s/\\(from "\\.[^"]*\\)";/\\1.mjs";/g'`;
|
|
||||||
default:
|
|
||||||
return `find ./node_modules/crypto-api/src/ \\( -type d -name .git -prune \\) -o -type f -print0 | xargs -0 sed -i -e '/\\.mjs/!s/\\(from "\\.[^"]*\\)";/\\1.mjs";/g'`;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
stdout: false
|
stdout: false
|
||||||
},
|
},
|
||||||
fixSnackbarMarkup: {
|
fixSnackbarMarkup: {
|
||||||
command: function () {
|
command: `node ${nodeFlags} src/core/config/scripts/fixSnackBarMarkup.mjs`,
|
||||||
switch (process.platform) {
|
|
||||||
case "darwin":
|
|
||||||
return `sed -i '' 's/<div id=snackbar-container\\/>/<div id=snackbar-container>/g' ./node_modules/snackbarjs/src/snackbar.js`;
|
|
||||||
default:
|
|
||||||
return `sed -i 's/<div id=snackbar-container\\/>/<div id=snackbar-container>/g' ./node_modules/snackbarjs/src/snackbar.js`;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
stdout: false
|
stdout: false
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
10
README.md
10
README.md
@ -36,7 +36,7 @@ docker build --tag cyberchef --ulimit nofile=10000 .
|
|||||||
```
|
```
|
||||||
2. Run the docker container
|
2. Run the docker container
|
||||||
```bash
|
```bash
|
||||||
docker run -it -p 8080:80 cyberchef
|
docker run -it -p 8080:8080 cyberchef
|
||||||
```
|
```
|
||||||
3. Navigate to `http://localhost:8080` in your browser
|
3. Navigate to `http://localhost:8080` in your browser
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ docker run -it -p 8080:80 cyberchef
|
|||||||
If you prefer to skip the build process, you can use the pre-built 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:8080 ghcr.io/gchq/cyberchef:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
Just like before, navigate to `http://localhost:8080` in your browser.
|
Just like before, navigate to `http://localhost:8080` in your browser.
|
||||||
@ -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]
|
- [Carry out different operations on data of different types][8]
|
||||||
- [Use parts of the input as arguments to operations][9]
|
- [Use parts of the input as arguments to operations][9]
|
||||||
- [Perform AES decryption, extracting the IV from the beginning of the cipher stream][10]
|
- [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]
|
- [Automagically detect several layers of nested encoding][12]
|
||||||
|
|
||||||
|
|
||||||
@ -120,7 +121,7 @@ CyberChef is built to support
|
|||||||
|
|
||||||
## Node.js support
|
## Node.js support
|
||||||
|
|
||||||
CyberChef is built to fully support Node.js `v16`. For more information, see the ["Node API" wiki page](https://github.com/gchq/CyberChef/wiki/Node-API)
|
CyberChef is built to fully support Node.js `v24`. For more information, see the ["Node API" wiki page](https://github.com/gchq/CyberChef/wiki/Node-API)
|
||||||
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
@ -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
|
[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
|
[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
|
[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
|
[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
|
[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
|
||||||
|
|||||||
26
SECURITY.md
26
SECURITY.md
@ -2,25 +2,15 @@
|
|||||||
|
|
||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
CyberChef is supported on a best endeavours basis. Patches will be applied to
|
CyberChef is supported on a best endeavours basis.
|
||||||
the latest version rather than retroactively to older versions. To ensure you
|
Patches will be applied to the latest version rather than retroactively to older versions.
|
||||||
are using the most secure version of CyberChef, please make sure you have the
|
To ensure you are using the most secure version of CyberChef, please make sure you have the [latest release](https://github.com/gchq/CyberChef/releases/latest). [The official website](https://gchq.github.io/CyberChef/) is always up to date.
|
||||||
[latest release](https://github.com/gchq/CyberChef/releases/latest). The
|
|
||||||
official [live demo](https://gchq.github.io/CyberChef/) is always up to date.
|
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
In most scenarios, the most appropriate way to report a vulnerability is to
|
If you discover a vulnerability in CyberChef, please do not publicly disclose it, and do not create a GitHub issue.
|
||||||
[raise a new issue](https://github.com/gchq/CyberChef/issues/new/choose)
|
|
||||||
describing the problem in as much detail as possible, ideally with examples.
|
|
||||||
This will obviously be public. If you feel that the vulnerability is
|
|
||||||
significant enough to warrant a private disclosure, please email
|
|
||||||
[oss@gchq.gov.uk](mailto:oss@gchq.gov.uk) and
|
|
||||||
[n1474335@gmail.com](mailto:n1474335@gmail.com).
|
|
||||||
|
|
||||||
Disclosures of vulnerabilities in CyberChef are always welcomed. Whilst we aim
|
Instead, send an email as soon as possible to [CyberChefSecurity@gchq.gov.uk](mailto:CyberChefSecurity@gchq.gov.uk).
|
||||||
to write clean and secure code free from bugs, we recognise that this is an open
|
The report will be acknowledged and actioned urgently by the CyberChef maintainers.
|
||||||
source project written by analysts in their spare time, relying on dozens of
|
|
||||||
open source libraries that are modified and updated on a regular basis. We hope
|
If you do not receive a timely acknowledgement, please notify [oss@gchq.gov.uk](mailto:oss@gchq.gov.uk) and [CyberChef@gchq.gov.uk](mailto:CyberChef@gchq.gov.uk) of your vulnerability report.
|
||||||
that the community will continue to support us as we endeavour to maintain and
|
|
||||||
develop this tool together.
|
|
||||||
|
|||||||
@ -16,6 +16,9 @@ module.exports = function(api) {
|
|||||||
"regenerator": true
|
"regenerator": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
]
|
],
|
||||||
|
"generatorOpts": {
|
||||||
|
"importAttributesKeyword": "with"
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
6469
package-lock.json
generated
6469
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
109
package.json
109
package.json
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "cyberchef",
|
"name": "cyberchef",
|
||||||
"version": "10.22.1",
|
"version": "11.1.0",
|
||||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||||
"author": "n1474335 <n1474335@gmail.com>",
|
"author": "GCHQ <CyberChef@gchq.gov.uk>",
|
||||||
"homepage": "https://gchq.github.io/CyberChef",
|
"homepage": "https://gchq.github.io/CyberChef",
|
||||||
"copyright": "Crown copyright 2016",
|
"copyright": "Crown copyright 2016",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
@ -36,59 +36,60 @@
|
|||||||
"browserslist": [
|
"browserslist": [
|
||||||
"Chrome >= 50",
|
"Chrome >= 50",
|
||||||
"Firefox >= 38",
|
"Firefox >= 38",
|
||||||
"node >= 16"
|
"node >= 24"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/eslint-parser": "^7.28.6",
|
"@babel/eslint-parser": "^7.29.7",
|
||||||
"@babel/plugin-syntax-import-assertions": "^7.28.6",
|
"@babel/plugin-syntax-import-assertions": "^7.28.6",
|
||||||
"@babel/plugin-transform-runtime": "^7.29.0",
|
"@babel/plugin-transform-runtime": "^7.29.7",
|
||||||
"@babel/preset-env": "^7.29.2",
|
"@babel/preset-env": "^7.29.7",
|
||||||
"@babel/runtime": "^7.29.2",
|
"@babel/runtime": "^7.29.7",
|
||||||
"@codemirror/commands": "^6.10.3",
|
"@codemirror/commands": "^6.10.3",
|
||||||
"@codemirror/language": "^6.12.3",
|
"@codemirror/language": "^6.12.3",
|
||||||
"@codemirror/search": "^6.6.0",
|
"@codemirror/search": "^6.7.0",
|
||||||
"@codemirror/state": "^6.5.4",
|
"@codemirror/state": "^6.5.4",
|
||||||
"@codemirror/view": "^6.40.0",
|
"@codemirror/view": "^6.43.1",
|
||||||
"autoprefixer": "^10.4.27",
|
"@puppeteer/browsers": "3.0.4",
|
||||||
|
"autoprefixer": "^10.5.0",
|
||||||
"babel-loader": "^10.1.1",
|
"babel-loader": "^10.1.1",
|
||||||
"base64-loader": "^1.0.0",
|
"base64-loader": "^1.0.0",
|
||||||
"chromedriver": "^146.0.6",
|
"chromedriver": "^148.0.4",
|
||||||
"cli-progress": "^3.12.0",
|
"cli-progress": "^3.12.0",
|
||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
"compression-webpack-plugin": "^11.1.0",
|
"compression-webpack-plugin": "^12.0.0",
|
||||||
"copy-webpack-plugin": "^13.0.1",
|
"copy-webpack-plugin": "^14.0.0",
|
||||||
"core-js": "^3.49.0",
|
"core-js": "^3.49.0",
|
||||||
"cspell": "^8.19.4",
|
"cspell": "^10.0.1",
|
||||||
"css-loader": "7.1.4",
|
"css-loader": "^7.1.4",
|
||||||
"eslint": "^9.39.4",
|
"eslint": "^9.39.4",
|
||||||
"eslint-plugin-jsdoc": "^50.8.0",
|
"eslint-plugin-jsdoc": "^50.8.0",
|
||||||
"globals": "^15.15.0",
|
"globals": "^17.6.0",
|
||||||
"grunt": "^1.6.1",
|
"grunt": "^1.6.2",
|
||||||
"grunt-chmod": "~1.1.1",
|
"grunt-chmod": "~1.1.1",
|
||||||
"grunt-concurrent": "^3.0.0",
|
"grunt-concurrent": "^3.0.0",
|
||||||
"grunt-contrib-clean": "~2.0.1",
|
"grunt-contrib-clean": "~2.0.1",
|
||||||
"grunt-contrib-connect": "^5.0.1",
|
"grunt-contrib-connect": "^5.0.1",
|
||||||
"grunt-contrib-copy": "~1.0.0",
|
"grunt-contrib-copy": "~1.0.0",
|
||||||
"grunt-contrib-watch": "^1.1.0",
|
"grunt-contrib-watch": "^1.1.0",
|
||||||
"grunt-eslint": "^25.0.0",
|
"grunt-eslint": "^26.0.0",
|
||||||
"grunt-exec": "~3.0.0",
|
"grunt-exec": "~3.0.0",
|
||||||
"grunt-webpack": "^6.0.0",
|
"grunt-webpack": "^8.0.0",
|
||||||
"grunt-zip": "^1.0.0",
|
"grunt-zip": "^1.0.0",
|
||||||
"html-webpack-plugin": "^5.6.6",
|
"html-webpack-plugin": "^5.6.7",
|
||||||
"imports-loader": "^5.0.0",
|
"imports-loader": "^5.0.0",
|
||||||
"mini-css-extract-plugin": "2.10.2",
|
"mini-css-extract-plugin": "2.10.2",
|
||||||
"modify-source-webpack-plugin": "^4.1.0",
|
"modify-source-webpack-plugin": "^4.1.0",
|
||||||
"nightwatch": "^3.15.0",
|
"nightwatch": "^3.16.0",
|
||||||
"postcss": "^8.5.8",
|
"postcss": "^8.5.15",
|
||||||
"postcss-css-variables": "^0.19.0",
|
"postcss-css-variables": "^0.19.0",
|
||||||
"postcss-import": "^16.1.1",
|
"postcss-import": "^16.1.1",
|
||||||
"postcss-loader": "^8.2.1",
|
"postcss-loader": "^8.2.1",
|
||||||
"prompt": "^1.3.0",
|
"prompt": "^1.3.0",
|
||||||
"sitemap": "^8.0.3",
|
"sitemap": "^9.0.1",
|
||||||
"terser": "^5.46.1",
|
"terser": "^5.48.0",
|
||||||
"webpack": "^5.105.4",
|
"webpack": "^5.107.2",
|
||||||
"webpack-bundle-analyzer": "^4.10.2",
|
"webpack-bundle-analyzer": "^5.3.0",
|
||||||
"webpack-dev-server": "5.0.4",
|
"webpack-dev-server": "^5.2.4",
|
||||||
"webpack-node-externals": "^3.0.0",
|
"webpack-node-externals": "^3.0.0",
|
||||||
"worker-loader": "^3.0.8"
|
"worker-loader": "^3.0.8"
|
||||||
},
|
},
|
||||||
@ -96,22 +97,23 @@
|
|||||||
"@alexaltea/capstone-js": "^3.0.5",
|
"@alexaltea/capstone-js": "^3.0.5",
|
||||||
"@astronautlabs/amf": "^0.0.6",
|
"@astronautlabs/amf": "^0.0.6",
|
||||||
"@blu3r4y/lzma": "^2.3.3",
|
"@blu3r4y/lzma": "^2.3.3",
|
||||||
|
"@noble/hashes": "2.2.0",
|
||||||
"@wavesenterprise/crypto-gost-js": "^2.1.0-RC1",
|
"@wavesenterprise/crypto-gost-js": "^2.1.0-RC1",
|
||||||
"@xmldom/xmldom": "^0.8.11",
|
"@xmldom/xmldom": "^0.8.13",
|
||||||
"argon2-browser": "^1.18.0",
|
"argon2-browser": "^1.18.0",
|
||||||
"arrive": "^2.5.2",
|
"arrive": "^2.5.3",
|
||||||
"assert": "^2.1.0",
|
"assert": "^2.1.0",
|
||||||
"avsc": "^5.7.9",
|
"avsc": "^5.7.9",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^3.0.3",
|
||||||
"bignumber.js": "^9.3.1",
|
"bignumber.js": "^11.1.3",
|
||||||
"blakejs": "^1.2.1",
|
"blakejs": "^1.2.1",
|
||||||
"bootstrap": "4.6.2",
|
"bootstrap": "4.6.2",
|
||||||
"bootstrap-colorpicker": "^3.4.0",
|
"bootstrap-colorpicker": "^3.4.0",
|
||||||
"bootstrap-material-design": "^4.1.3",
|
"bootstrap-material-design": "^4.1.3",
|
||||||
"browserify-zlib": "^0.2.0",
|
"browserify-zlib": "^0.2.0",
|
||||||
"bson": "^4.7.2",
|
"bson": "^7.2.0",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"cbor": "9.0.2",
|
"cbor": "10.0.12",
|
||||||
"chi-squared": "^1.1.0",
|
"chi-squared": "^1.1.0",
|
||||||
"codepage": "^1.15.0",
|
"codepage": "^1.15.0",
|
||||||
"crypto-api": "^0.8.5",
|
"crypto-api": "^0.8.5",
|
||||||
@ -120,8 +122,8 @@
|
|||||||
"ctph.js": "0.0.5",
|
"ctph.js": "0.0.5",
|
||||||
"d3": "7.9.0",
|
"d3": "7.9.0",
|
||||||
"d3-hexbin": "^0.2.2",
|
"d3-hexbin": "^0.2.2",
|
||||||
"diff": "^5.2.2",
|
"diff": "^9.0.0",
|
||||||
"dompurify": "^3.3.3",
|
"dompurify": "^3.4.8",
|
||||||
"es6-promisify": "^7.0.0",
|
"es6-promisify": "^7.0.0",
|
||||||
"escodegen": "^2.1.0",
|
"escodegen": "^2.1.0",
|
||||||
"esprima": "^4.0.1",
|
"esprima": "^4.0.1",
|
||||||
@ -132,31 +134,30 @@
|
|||||||
"flat": "^6.0.1",
|
"flat": "^6.0.1",
|
||||||
"geodesy": "1.1.3",
|
"geodesy": "1.1.3",
|
||||||
"handlebars": "^4.7.9",
|
"handlebars": "^4.7.9",
|
||||||
"hash-wasm": "^4.12.0",
|
|
||||||
"highlight.js": "^11.11.1",
|
"highlight.js": "^11.11.1",
|
||||||
"ieee754": "^1.2.1",
|
"ieee754": "^1.2.1",
|
||||||
"jimp": "^1.6.0",
|
"jimp": "1.6.0",
|
||||||
"jq-web": "^0.5.1",
|
"jq-web": "^0.5.1",
|
||||||
"jquery": "3.7.1",
|
"jquery": "3.7.1",
|
||||||
"js-sha3": "^0.9.3",
|
"js-sha3": "^0.9.3",
|
||||||
"jsesc": "^3.1.0",
|
"jsesc": "^3.1.0",
|
||||||
"json5": "^2.2.3",
|
"json5": "^2.2.3",
|
||||||
"jsonata": "^2.1.0",
|
"jsonata": "^2.2.1",
|
||||||
"jsonpath-plus": "^10.4.0",
|
"jsonpath-plus": "^10.4.0",
|
||||||
"jsonwebtoken": "9.0.3",
|
"jsonwebtoken": "9.0.3",
|
||||||
"jsqr": "^1.4.0",
|
"jsqr": "^1.4.0",
|
||||||
"jsrsasign": "^11.1.1",
|
"jsrsasign": "^11.1.3",
|
||||||
"kbpgp": "^2.1.17",
|
"kbpgp": "^2.1.17",
|
||||||
"libbzip2-wasm": "0.0.4",
|
"libbzip2-wasm": "0.0.4",
|
||||||
"libyara-wasm": "^1.2.1",
|
"libyara-wasm": "^1.2.1",
|
||||||
"lodash": "^4.17.23",
|
"lodash": "^4.18.1",
|
||||||
"loglevel": "^1.9.2",
|
"loglevel": "^1.9.2",
|
||||||
"loglevel-message-prefix": "^3.0.0",
|
"loglevel-message-prefix": "^3.0.0",
|
||||||
"lz-string": "^1.5.0",
|
"lz-string": "^1.5.0",
|
||||||
"lz4js": "^0.2.0",
|
"lz4js": "^0.2.0",
|
||||||
"markdown-it": "^14.1.1",
|
"markdown-it": "^14.2.0",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"moment-timezone": "^0.6.1",
|
"moment-timezone": "^0.6.2",
|
||||||
"ngeohash": "^0.6.3",
|
"ngeohash": "^0.6.3",
|
||||||
"node-forge": "^1.4.0",
|
"node-forge": "^1.4.0",
|
||||||
"node-md6": "^0.1.0",
|
"node-md6": "^0.1.0",
|
||||||
@ -164,11 +165,12 @@
|
|||||||
"notepack.io": "^3.0.1",
|
"notepack.io": "^3.0.1",
|
||||||
"ntlm": "^0.1.3",
|
"ntlm": "^0.1.3",
|
||||||
"nwmatcher": "^1.4.4",
|
"nwmatcher": "^1.4.4",
|
||||||
"otpauth": "9.3.6",
|
"otpauth": "^9.5.0",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"popper.js": "^1.16.1",
|
"popper.js": "^1.16.1",
|
||||||
"process": "^0.11.10",
|
"process": "^0.11.10",
|
||||||
"protobufjs": "^7.5.4",
|
"protobufjs": "^8.6.2",
|
||||||
|
"punycode.js": "^2.3.1",
|
||||||
"qr-image": "^3.2.0",
|
"qr-image": "^3.2.0",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rison": "^0.1.1",
|
"rison": "^0.1.1",
|
||||||
@ -176,15 +178,15 @@
|
|||||||
"snackbarjs": "^1.1.0",
|
"snackbarjs": "^1.1.0",
|
||||||
"sortablejs": "^1.15.7",
|
"sortablejs": "^1.15.7",
|
||||||
"split.js": "^1.6.5",
|
"split.js": "^1.6.5",
|
||||||
"sql-formatter": "^15.6.12",
|
"sql-formatter": "^15.8.1",
|
||||||
"ssdeep.js": "0.0.3",
|
"ssdeep.js": "0.0.3",
|
||||||
"stream-browserify": "^3.0.0",
|
"stream-browserify": "^3.0.0",
|
||||||
"tesseract.js": "^6.0.1",
|
"tesseract.js": "^7.0.0",
|
||||||
"ua-parser-js": "^1.0.41",
|
"ua-parser-js": "^2.0.10",
|
||||||
"unorm": "^1.6.0",
|
"unorm": "^1.6.0",
|
||||||
"url": "^0.11.4",
|
"url": "^0.11.4",
|
||||||
"utf8": "^3.0.0",
|
"utf8": "^3.0.0",
|
||||||
"uuid": "^13.0.0",
|
"uuid": "^14.0.0",
|
||||||
"vkbeautify": "^0.99.3",
|
"vkbeautify": "^0.99.3",
|
||||||
"xpath": "0.0.34",
|
"xpath": "0.0.34",
|
||||||
"xregexp": "^5.1.2",
|
"xregexp": "^5.1.2",
|
||||||
@ -194,18 +196,21 @@
|
|||||||
"start": "npx grunt dev",
|
"start": "npx grunt dev",
|
||||||
"build": "npx grunt prod",
|
"build": "npx grunt prod",
|
||||||
"node": "npx grunt node",
|
"node": "npx grunt node",
|
||||||
"repl": "node --experimental-modules --experimental-json-modules --experimental-specifier-resolution=node --no-experimental-fetch --no-warnings src/node/repl.mjs",
|
"repl": "node --no-warnings src/node/repl.mjs",
|
||||||
"test": "npx grunt configTests && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation --openssl-legacy-provider --no-experimental-fetch tests/node/index.mjs && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation --openssl-legacy-provider --no-experimental-fetch --trace-uncaught tests/operations/index.mjs",
|
"test": "npx grunt configTests && node --no-warnings --no-deprecation --openssl-legacy-provider tests/node/index.mjs && node --no-warnings --no-deprecation --openssl-legacy-provider --trace-uncaught tests/operations/index.mjs",
|
||||||
"testnodeconsumer": "npx grunt testnodeconsumer",
|
"testnodeconsumer": "npx grunt testnodeconsumer",
|
||||||
"testui": "npx grunt testui",
|
"testui": "npx grunt testui",
|
||||||
"testuidev": "npx nightwatch --env=dev",
|
"testuidev": "npx nightwatch --env=dev",
|
||||||
"lint": "npx grunt lint",
|
"lint": "npx grunt lint",
|
||||||
"lint:grammar": "cspell ./src",
|
"lint:grammar": "cspell ./src",
|
||||||
"postinstall": "npx grunt exec:fixCryptoApiImports && npx grunt exec:fixSnackbarMarkup",
|
"postinstall": "npx grunt exec:fixCryptoApiImports && npx grunt exec:fixSnackbarMarkup",
|
||||||
"newop": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newOperation.mjs",
|
"newop": "node src/core/config/scripts/newOperation.mjs",
|
||||||
"minor": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newMinorVersion.mjs && npm version minor --git-tag-version=false && echo \"Updated to version v$(npm pkg get version | xargs), please create a pull request and once merged use 'npm run tag'\"",
|
"minor": "node src/core/config/scripts/newMinorVersion.mjs && npm version minor --git-tag-version=false && echo \"Updated to version v$(npm pkg get version | xargs), please create a pull request and once merged use 'npm run tag'\"",
|
||||||
"tag": "git tag -s \"v$(npm pkg get version | xargs)\" -m \"$(npm pkg get version | xargs)\" && echo \"Created v$(npm pkg get version | xargs), now check and push the tag\"",
|
"tag": "git tag -s \"v$(npm pkg get version | xargs)\" -m \"$(npm pkg get version | xargs)\" && echo \"Created v$(npm pkg get version | xargs), now check and push the tag\"",
|
||||||
"getheapsize": "node -e 'console.log(`node heap limit = ${require(\"v8\").getHeapStatistics().heap_size_limit / (1024 * 1024)} Mb`)'",
|
"getheapsize": "node -e 'console.log(`node heap limit = ${require(\"v8\").getHeapStatistics().heap_size_limit / (1024 * 1024)} Mb`)'",
|
||||||
"setheapsize": "export NODE_OPTIONS=--max_old_space_size=2048"
|
"setheapsize": "export NODE_OPTIONS=--max_old_space_size=2048"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=24 <25"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -138,6 +138,8 @@ class Chef {
|
|||||||
|
|
||||||
if (!highlights) return false;
|
if (!highlights) return false;
|
||||||
|
|
||||||
|
if (direction === "reverse") highlights.reverse();
|
||||||
|
|
||||||
for (let i = 0; i < highlights.length; i++) {
|
for (let i = 0; i < highlights.length; i++) {
|
||||||
// Remove multiple highlights before processing again
|
// Remove multiple highlights before processing again
|
||||||
pos = [pos[0]];
|
pos = [pos[0]];
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Chef from "./Chef.mjs";
|
import Chef from "./Chef.mjs";
|
||||||
import OperationConfig from "./config/OperationConfig.json" assert {type: "json"};
|
import OperationConfig from "./config/OperationConfig.json" with { type: "json" };
|
||||||
import OpModules from "./config/modules/OpModules.mjs";
|
import OpModules from "./config/modules/OpModules.mjs";
|
||||||
import loglevelMessagePrefix from "loglevel-message-prefix";
|
import loglevelMessagePrefix from "loglevel-message-prefix";
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import OperationConfig from "./config/OperationConfig.json" assert {type: "json"};
|
import OperationConfig from "./config/OperationConfig.json" with { type: "json" };
|
||||||
import OperationError from "./errors/OperationError.mjs";
|
import OperationError from "./errors/OperationError.mjs";
|
||||||
import Operation from "./Operation.mjs";
|
import Operation from "./Operation.mjs";
|
||||||
import DishError from "./errors/DishError.mjs";
|
import DishError from "./errors/DishError.mjs";
|
||||||
|
|||||||
@ -49,6 +49,7 @@
|
|||||||
"Escape Unicode Characters",
|
"Escape Unicode Characters",
|
||||||
"Unescape Unicode Characters",
|
"Unescape Unicode Characters",
|
||||||
"Normalise Unicode",
|
"Normalise Unicode",
|
||||||
|
"Escape Smart Characters",
|
||||||
"To Quoted Printable",
|
"To Quoted Printable",
|
||||||
"From Quoted Printable",
|
"From Quoted Printable",
|
||||||
"To Punycode",
|
"To Punycode",
|
||||||
@ -118,6 +119,7 @@
|
|||||||
"GOST Verify",
|
"GOST Verify",
|
||||||
"GOST Key Wrap",
|
"GOST Key Wrap",
|
||||||
"GOST Key Unwrap",
|
"GOST Key Unwrap",
|
||||||
|
"ROR13",
|
||||||
"ROT13",
|
"ROT13",
|
||||||
"ROT13 Brute Force",
|
"ROT13 Brute Force",
|
||||||
"ROT47",
|
"ROT47",
|
||||||
@ -188,6 +190,7 @@
|
|||||||
"Generate PGP Key Pair",
|
"Generate PGP Key Pair",
|
||||||
"PGP Encrypt",
|
"PGP Encrypt",
|
||||||
"PGP Decrypt",
|
"PGP Decrypt",
|
||||||
|
"PGP Sign",
|
||||||
"PGP Verify",
|
"PGP Verify",
|
||||||
"PGP Encrypt and Sign",
|
"PGP Encrypt and Sign",
|
||||||
"PGP Decrypt and Verify",
|
"PGP Decrypt and Verify",
|
||||||
@ -239,6 +242,7 @@
|
|||||||
"Bit shift right",
|
"Bit shift right",
|
||||||
"Rotate left",
|
"Rotate left",
|
||||||
"Rotate right",
|
"Rotate right",
|
||||||
|
"ROR13",
|
||||||
"ROT13",
|
"ROT13",
|
||||||
"ROT8000"
|
"ROT8000"
|
||||||
]
|
]
|
||||||
@ -304,6 +308,7 @@
|
|||||||
"Diff",
|
"Diff",
|
||||||
"Remove whitespace",
|
"Remove whitespace",
|
||||||
"Remove null bytes",
|
"Remove null bytes",
|
||||||
|
"Remove ANSI Escape Codes",
|
||||||
"To Upper case",
|
"To Upper case",
|
||||||
"To Lower case",
|
"To Lower case",
|
||||||
"Swap case",
|
"Swap case",
|
||||||
@ -349,6 +354,7 @@
|
|||||||
"Pseudo-Random Number Generator",
|
"Pseudo-Random Number Generator",
|
||||||
"Sleep",
|
"Sleep",
|
||||||
"File Tree",
|
"File Tree",
|
||||||
|
"Wrap",
|
||||||
"Take nth bytes",
|
"Take nth bytes",
|
||||||
"Drop nth bytes"
|
"Drop nth bytes"
|
||||||
]
|
]
|
||||||
@ -466,7 +472,8 @@
|
|||||||
"Luhn Checksum",
|
"Luhn Checksum",
|
||||||
"CRC Checksum",
|
"CRC Checksum",
|
||||||
"TCP/IP Checksum",
|
"TCP/IP Checksum",
|
||||||
"XOR Checksum"
|
"XOR Checksum",
|
||||||
|
"Parity Bit"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
54
src/core/config/scripts/fixCryptoApiImports.mjs
Normal file
54
src/core/config/scripts/fixCryptoApiImports.mjs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* This script updates crypto-api package
|
||||||
|
* It adds .mjs to local imports where its missing
|
||||||
|
*
|
||||||
|
* before:
|
||||||
|
* import foo from "./bar";
|
||||||
|
* after
|
||||||
|
* import foo from "./bar.mjs";
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint no-console: ["off"] */
|
||||||
|
|
||||||
|
import { readdirSync, readFileSync, writeFileSync } from "fs";
|
||||||
|
import { join } from "path";
|
||||||
|
|
||||||
|
// Base directory of crypto-api source
|
||||||
|
const baseDir = join(process.cwd(), "node_modules/crypto-api/src");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively walk a directory, updating import statements
|
||||||
|
* to include ".mjs" if missing
|
||||||
|
*/
|
||||||
|
function walk(dir) {
|
||||||
|
const entries = readdirSync(dir, { withFileTypes: true });
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (entry.name === ".git") continue;
|
||||||
|
|
||||||
|
const fullPath = join(dir, entry.name);
|
||||||
|
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
walk(fullPath);
|
||||||
|
} else if (entry.isFile()) {
|
||||||
|
const content = readFileSync(fullPath, "utf8");
|
||||||
|
|
||||||
|
// Add .mjs to imports if not present
|
||||||
|
const updated = content.replace(
|
||||||
|
/from "(\.[^"]*)";/g,
|
||||||
|
(match, p1) => {
|
||||||
|
if (p1.endsWith(".mjs")) return match;
|
||||||
|
return `from "${p1}.mjs";`;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (updated !== content) {
|
||||||
|
writeFileSync(fullPath, updated, "utf8");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the walker
|
||||||
|
walk(baseDir);
|
||||||
28
src/core/config/scripts/fixSnackBarMarkup.mjs
Normal file
28
src/core/config/scripts/fixSnackBarMarkup.mjs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* This script updates snackbarjs package
|
||||||
|
* Replaces self-closing div with standard opening div
|
||||||
|
*
|
||||||
|
* before:
|
||||||
|
* <div id=snackbar-container/>
|
||||||
|
* after:
|
||||||
|
* <div id=snackbar-container>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint no-console: ["off"] */
|
||||||
|
|
||||||
|
import { readFileSync, writeFileSync } from "fs";
|
||||||
|
import { join } from "path";
|
||||||
|
|
||||||
|
// Base directory of snackbarjs source
|
||||||
|
const filePath = join(process.cwd(), "node_modules/snackbarjs/src/snackbar.js");
|
||||||
|
|
||||||
|
const content = readFileSync(filePath, "utf8");
|
||||||
|
|
||||||
|
// Replace self-closing div with standard opening div
|
||||||
|
const updated = content.replace(
|
||||||
|
/<div id=snackbar-container\/>/g,
|
||||||
|
"<div id=snackbar-container>"
|
||||||
|
);
|
||||||
|
|
||||||
|
writeFileSync(filePath, updated, "utf8");
|
||||||
@ -58,3 +58,66 @@ fs.writeFileSync(
|
|||||||
code
|
code
|
||||||
);
|
);
|
||||||
console.log("Written operation index.");
|
console.log("Written operation index.");
|
||||||
|
|
||||||
|
// find all test files
|
||||||
|
const testsDir = path.join(process.cwd() + "/tests/operations/tests/");
|
||||||
|
const testObjs = [];
|
||||||
|
fs.readdirSync(testsDir).forEach(file => {
|
||||||
|
if (!file.endsWith(".mjs")) return;
|
||||||
|
testObjs.push(file.split(".mjs")[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Construct test index file
|
||||||
|
code = `/**
|
||||||
|
* THIS FILE IS AUTOMATICALLY GENERATED BY src/core/config/scripts/generateOpsIndex.mjs
|
||||||
|
*
|
||||||
|
* @author john [john19696@protonmail.com]
|
||||||
|
* @author tlwr [toby@toby.codes]
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright ${new Date().getUTCFullYear()}
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
setLongTestFailure,
|
||||||
|
logTestReport,
|
||||||
|
} from "../lib/utils.mjs";
|
||||||
|
|
||||||
|
import "../lib/wasmFetchPolyfill.mjs";
|
||||||
|
|
||||||
|
import TestRegister from "../lib/TestRegister.mjs";
|
||||||
|
`;
|
||||||
|
|
||||||
|
testObjs.forEach(obj => {
|
||||||
|
if (obj !== "SplitColourChannels")
|
||||||
|
code += `import "./tests/${obj}.mjs";\n`;
|
||||||
|
else
|
||||||
|
code += `// Cannot test operations that use the File type yet
|
||||||
|
// import "./tests/SplitColourChannels.mjs";\n`;
|
||||||
|
});
|
||||||
|
|
||||||
|
code += `
|
||||||
|
|
||||||
|
const testStatus = {
|
||||||
|
allTestsPassing: true,
|
||||||
|
counts: {
|
||||||
|
total: 0,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
setLongTestFailure();
|
||||||
|
|
||||||
|
const logOpsTestReport = logTestReport.bind(null, testStatus);
|
||||||
|
|
||||||
|
(async function() {
|
||||||
|
const results = await TestRegister.runTests();
|
||||||
|
logOpsTestReport(results);
|
||||||
|
})();
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Write tests file
|
||||||
|
fs.writeFileSync(
|
||||||
|
path.join(testsDir, "../index.mjs"),
|
||||||
|
code
|
||||||
|
);
|
||||||
|
console.log("Written operation tests index.");
|
||||||
|
|||||||
@ -23,7 +23,7 @@ if (!fs.existsSync(dir)) {
|
|||||||
console.log("Example> node --experimental-modules src/core/config/scripts/newOperation.mjs");
|
console.log("Example> node --experimental-modules src/core/config/scripts/newOperation.mjs");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
const testDir = path.join(process.cwd() + "/tests/operations/tests/");
|
||||||
const ioTypes = ["string", "byteArray", "number", "html", "ArrayBuffer", "BigNumber", "JSON", "File", "List<File>"];
|
const ioTypes = ["string", "byteArray", "number", "html", "ArrayBuffer", "BigNumber", "JSON", "File", "List<File>"];
|
||||||
|
|
||||||
const schema = {
|
const schema = {
|
||||||
@ -123,6 +123,30 @@ prompt.get(schema, (err, result) => {
|
|||||||
return txt.charAt(0).toUpperCase() + txt.substr(1);
|
return txt.charAt(0).toUpperCase() + txt.substr(1);
|
||||||
}).replace(/[\s-()./]/g, "");
|
}).replace(/[\s-()./]/g, "");
|
||||||
|
|
||||||
|
const testTemplate = `/**
|
||||||
|
* ${moduleName} tests
|
||||||
|
*
|
||||||
|
* @author ${result.authorName} [${result.authorEmail}]
|
||||||
|
* @copyright Crown Copyright ${(new Date()).getFullYear()}
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "${result.opName}: test",
|
||||||
|
input: "Example input",
|
||||||
|
expectedOutput: "Expected output",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "${result.opName}",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
`;
|
||||||
|
|
||||||
const template = `/**
|
const template = `/**
|
||||||
* @author ${result.authorName} [${result.authorEmail}]
|
* @author ${result.authorName} [${result.authorEmail}]
|
||||||
@ -218,13 +242,16 @@ export default ${moduleName};
|
|||||||
}
|
}
|
||||||
fs.writeFileSync(filename, template);
|
fs.writeFileSync(filename, template);
|
||||||
|
|
||||||
|
const testFilename = path.join(testDir, `./${moduleName}.mjs`);
|
||||||
|
fs.writeFileSync(testFilename, testTemplate);
|
||||||
|
|
||||||
console.log(`\nOperation template written to ${colors.green(filename)}`);
|
console.log(`\nOperation template written to ${colors.green(filename)}`);
|
||||||
|
console.log(`\nOperation test template written to ${colors.green(testFilename)}`);
|
||||||
console.log(`\nNext steps:
|
console.log(`\nNext steps:
|
||||||
1. Add your operation to ${colors.green("src/core/config/Categories.json")}
|
1. Add your operation to ${colors.green("src/core/config/Categories.json")}
|
||||||
2. Write your operation code.
|
2. Write your operation code in ${colors.green(filename)}
|
||||||
3. Write tests in ${colors.green("tests/operations/tests/")}
|
3. Write your operation test code in ${colors.green(testFilename)}
|
||||||
4. Run ${colors.cyan("npm run lint")} and ${colors.cyan("npm run test")}
|
4. Run ${colors.cyan("npm run lint")} and ${colors.cyan("npm run test")}
|
||||||
5. Submit a Pull Request to get your operation added to the official CyberChef repository.`);
|
5. Submit a Pull Request to get your operation added to the official CyberChef repository.`);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
class DishType {
|
class DishType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Warn translations dont work without value from bind
|
* Warn translations don't work without value from bind
|
||||||
*/
|
*/
|
||||||
static checkForValue(value) {
|
static checkForValue(value) {
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Custom error type for handling operation that isnt included in node.js API
|
* Custom error type for handling operation that isn't included in node.js API
|
||||||
*
|
*
|
||||||
* @author d98762625 [d98762625@gmail.com]
|
* @author d98762625 [d98762625@gmail.com]
|
||||||
* @copyright Crown Copyright 2018
|
* @copyright Crown Copyright 2018
|
||||||
|
|||||||
@ -45,6 +45,11 @@ export function search(input, searchRegex, removeRegex=null, sortBy=null, unique
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Email regular expression
|
||||||
|
*/
|
||||||
|
export const EMAIL_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;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URL regular expression
|
* URL regular expression
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import OperationConfig from "../config/OperationConfig.json" assert {type: "json"};
|
import OperationConfig from "../config/OperationConfig.json" with { type: "json" };
|
||||||
import Utils, { isWorkerEnvironment } from "../Utils.mjs";
|
import Utils, { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
import Recipe from "../Recipe.mjs";
|
import Recipe from "../Recipe.mjs";
|
||||||
import Dish from "../Dish.mjs";
|
import Dish from "../Dish.mjs";
|
||||||
|
|||||||
50
src/core/lib/ParityBit.mjs
Normal file
50
src/core/lib/ParityBit.mjs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* Parity Bit functions.
|
||||||
|
*
|
||||||
|
* @author j83305 [awz22@protonmail.com]
|
||||||
|
* @copyright Crown Copyright 2020
|
||||||
|
* @license Apache-2.0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to take the user input and encode using the given arguments
|
||||||
|
* @param input string of binary
|
||||||
|
* @param args array
|
||||||
|
*/
|
||||||
|
export function calculateParityBit(input, args) {
|
||||||
|
let count1s = 0;
|
||||||
|
for (let i = 0; i < input.length; i++) {
|
||||||
|
const character = input.charAt(i);
|
||||||
|
if (character === "1") {
|
||||||
|
count1s++;
|
||||||
|
} else if (character !== args[3] && character !== "0" && character !== " ") {
|
||||||
|
throw new OperationError("unexpected character encountered: \"" + character + "\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let parityBit = "1";
|
||||||
|
const flipflop = args[0] === "Even Parity" ? 0 : 1;
|
||||||
|
if (count1s % 2 === flipflop) {
|
||||||
|
parityBit = "0";
|
||||||
|
}
|
||||||
|
if (args[1] === "End") {
|
||||||
|
return input + parityBit;
|
||||||
|
} else {
|
||||||
|
return parityBit + input;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* just removes the parity bit to return the original data
|
||||||
|
* @param input string of binary, encoded
|
||||||
|
* @param args array
|
||||||
|
*/
|
||||||
|
export function decodeParityBit(input, args) {
|
||||||
|
if (args[1] === "End") {
|
||||||
|
return input.slice(0, -1);
|
||||||
|
} else {
|
||||||
|
return input.slice(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -39,41 +39,46 @@ class AESDecrypt extends Operation {
|
|||||||
"value": "",
|
"value": "",
|
||||||
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "IV Length",
|
||||||
|
"type": "number",
|
||||||
|
"value": 16
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Mode",
|
"name": "Mode",
|
||||||
"type": "argSelector",
|
"type": "argSelector",
|
||||||
"value": [
|
"value": [
|
||||||
{
|
{
|
||||||
name: "CBC",
|
name: "CBC",
|
||||||
off: [5, 6]
|
off: [6, 7]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "CFB",
|
name: "CFB",
|
||||||
off: [5, 6]
|
off: [6, 7]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "OFB",
|
name: "OFB",
|
||||||
off: [5, 6]
|
off: [6, 7]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "CTR",
|
name: "CTR",
|
||||||
off: [5, 6]
|
off: [6, 7]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "GCM",
|
name: "GCM",
|
||||||
on: [5, 6]
|
on: [6, 7]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ECB",
|
name: "ECB",
|
||||||
off: [5, 6]
|
off: [6, 7]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "CBC/NoPadding",
|
name: "CBC/NoPadding",
|
||||||
off: [5, 6]
|
off: [6, 7]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ECB/NoPadding",
|
name: "ECB/NoPadding",
|
||||||
off: [5, 6]
|
off: [6, 7]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -98,6 +103,26 @@ class AESDecrypt extends Operation {
|
|||||||
"type": "toggleString",
|
"type": "toggleString",
|
||||||
"value": "",
|
"value": "",
|
||||||
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
"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
|
* @throws {OperationError} if cannot decrypt input or invalid key length
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
|
let iv;
|
||||||
|
|
||||||
const key = Utils.convertToByteString(args[0].string, args[0].option),
|
const key = Utils.convertToByteString(args[0].string, args[0].option),
|
||||||
iv = Utils.convertToByteString(args[1].string, args[1].option),
|
ivLength = args[2],
|
||||||
mode = args[2].split("/")[0],
|
mode = args[3].split("/")[0],
|
||||||
noPadding = args[2].endsWith("NoPadding"),
|
noPadding = args[3].endsWith("NoPadding"),
|
||||||
inputType = args[3],
|
inputType = args[4],
|
||||||
outputType = args[4],
|
outputType = args[5],
|
||||||
gcmTag = Utils.convertToByteString(args[5].string, args[5].option),
|
gcmTag = Utils.convertToByteString(args[6].string, args[6].option),
|
||||||
aad = 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) {
|
if ([16, 24, 32].indexOf(key.length) < 0) {
|
||||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||||
@ -130,6 +159,22 @@ The following algorithms will be used based on the size of the key:
|
|||||||
|
|
||||||
input = Utils.convertToByteString(input, inputType);
|
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);
|
const decipher = forge.cipher.createDecipher("AES-" + mode, key);
|
||||||
|
|
||||||
/* Allow for a "no padding" mode */
|
/* Allow for a "no padding" mode */
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import Operation from "../Operation.mjs";
|
|||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import forge from "node-forge";
|
import forge from "node-forge";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import { toHexFast } from "../lib/Hex.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AES Encrypt operation
|
* AES Encrypt operation
|
||||||
@ -92,6 +93,11 @@ class AESEncrypt extends Operation {
|
|||||||
"type": "toggleString",
|
"type": "toggleString",
|
||||||
"value": "",
|
"value": "",
|
||||||
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Include IV in output",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Off", "Prepend", "Append"]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -110,7 +116,8 @@ class AESEncrypt extends Operation {
|
|||||||
noPadding = args[2].endsWith("NoPadding"),
|
noPadding = args[2].endsWith("NoPadding"),
|
||||||
inputType = args[3],
|
inputType = args[3],
|
||||||
outputType = args[4],
|
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) {
|
if ([16, 24, 32].indexOf(key.length) < 0) {
|
||||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||||
@ -140,19 +147,27 @@ The following algorithms will be used based on the size of the key:
|
|||||||
cipher.update(forge.util.createBuffer(input));
|
cipher.update(forge.util.createBuffer(input));
|
||||||
cipher.finish();
|
cipher.finish();
|
||||||
|
|
||||||
|
let output = cipher.output.getBytes();
|
||||||
|
|
||||||
|
if (includeIV === "Prepend") {
|
||||||
|
output = iv + output;
|
||||||
|
} else if (includeIV === "Append") {
|
||||||
|
output = output + iv;
|
||||||
|
}
|
||||||
|
|
||||||
if (outputType === "Hex") {
|
if (outputType === "Hex") {
|
||||||
|
output = toHexFast(Utils.strToByteArray(output));
|
||||||
|
|
||||||
if (mode === "GCM") {
|
if (mode === "GCM") {
|
||||||
return cipher.output.toHex() + "\n\n" +
|
return output + "\n\n" +
|
||||||
"Tag: " + cipher.mode.tag.toHex();
|
"Tag: " + cipher.mode.tag.toHex();
|
||||||
}
|
}
|
||||||
return cipher.output.toHex();
|
} else if (mode === "GCM") {
|
||||||
} else {
|
return output + "\n\n" +
|
||||||
if (mode === "GCM") {
|
|
||||||
return cipher.output.getBytes() + "\n\n" +
|
|
||||||
"Tag: " + cipher.mode.tag.getBytes();
|
"Tag: " + cipher.mode.tag.getBytes();
|
||||||
}
|
}
|
||||||
return cipher.output.getBytes();
|
|
||||||
}
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @author n1474335 [n1474335@gmail.com]
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @author ko80240 [csk.dev@proton.me]
|
||||||
* @copyright Crown Copyright 2023
|
* @copyright Crown Copyright 2023
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -8,6 +9,7 @@ import * as uuid from "uuid";
|
|||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import { toHex } from "../lib/Hex.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Analyse UUID operation
|
* Analyse UUID operation
|
||||||
@ -22,27 +24,128 @@ class AnalyseUUID extends Operation {
|
|||||||
|
|
||||||
this.name = "Analyse UUID";
|
this.name = "Analyse UUID";
|
||||||
this.module = "Crypto";
|
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.description = "Operation for extracting metadata and detecting the version of a given UUID.";
|
||||||
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: "Include Metadata",
|
||||||
|
type: "boolean",
|
||||||
|
value: true
|
||||||
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} input
|
* @param {string} input - Expects a valid UUID string
|
||||||
* @param {Object[]} args
|
* @param {Object[]} args
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
|
input = input.trim();
|
||||||
|
|
||||||
|
let uuidVersion, uuidBytes;
|
||||||
try {
|
try {
|
||||||
const uuidVersion = uuid.version(input);
|
uuidVersion = uuid.version(input); // Re-using the uuid library to extract version
|
||||||
return "UUID version: " + uuidVersion;
|
uuidBytes = uuid.parse(input); // Re-using the uuid library to parse bytes
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new OperationError("Invalid UUID");
|
throw new OperationError("Invalid UUID");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [includeMetadata] = args;
|
||||||
|
const dv = new DataView(uuidBytes.buffer, uuidBytes.byteOffset, uuidBytes.byteLength); // Dataview helps handle the multi-byte ints
|
||||||
|
const uuidInteger = (dv.getBigUint64(0) << 64n) | dv.getBigUint64(8);
|
||||||
|
|
||||||
|
const sections = [`Version:\n${uuidVersion}`];
|
||||||
|
|
||||||
|
if (includeMetadata) {
|
||||||
|
const parser = UUID_PARSERS[uuidVersion];
|
||||||
|
const decoded = parser?.(uuidBytes, dv);
|
||||||
|
sections.push(formatDecoded(decoded));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sections.push(`UUID Integer:\n${uuidInteger}`);
|
||||||
|
|
||||||
|
return sections.filter(Boolean).join("\n\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AnalyseUUID;
|
export default AnalyseUUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metadata can be extracted for versions 1, 6, and 7.
|
||||||
|
* Enum-like frozen mapping of UUID version to parser function.
|
||||||
|
*/
|
||||||
|
const UUID_PARSERS = Object.freeze({
|
||||||
|
1: parsev1v6,
|
||||||
|
6: parsev1v6,
|
||||||
|
7: parsev7,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Versions 1 and 6. Note 6 is a re-order of 1.
|
||||||
|
* Version 1 == layout: timeLow(32) | timeMid(16) | timeHi(12)
|
||||||
|
* Version 6 == layout: timeHi(32) | timeMid(16) | timeLow(12)
|
||||||
|
*/
|
||||||
|
function parsev1v6(uuidBytes, dv) {
|
||||||
|
const isV1 = (uuidBytes[6] >> 4) === 1;
|
||||||
|
|
||||||
|
const timeStamp =
|
||||||
|
isV1 ? (
|
||||||
|
(BigInt(dv.getUint16(6) & 0x0fff) << 48n) | // mask off version bits
|
||||||
|
(BigInt(dv.getUint16(4)) << 32n) |
|
||||||
|
BigInt(dv.getUint32(0))
|
||||||
|
) : (
|
||||||
|
(BigInt(dv.getUint32(0)) << 28n) |
|
||||||
|
(BigInt(dv.getUint16(4)) << 12n) |
|
||||||
|
(BigInt(dv.getUint16(6) & 0x0fff))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Convert to Unix time
|
||||||
|
const milliseconds =
|
||||||
|
Number(
|
||||||
|
(timeStamp - 122192928000000000n) / 10000n
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
timestamp: milliseconds,
|
||||||
|
isoTimestamp: new Date(milliseconds).toISOString(),
|
||||||
|
clock: ((uuidBytes[8] & 0x3f) << 8) | uuidBytes[9],
|
||||||
|
node: toHex(uuidBytes.slice(10), ":").toUpperCase()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Version 7 */
|
||||||
|
function parsev7(uuidBytes, dv) {
|
||||||
|
const milliseconds = Number((BigInt(dv.getUint32(0)) << 16n) | BigInt(dv.getUint16(4)));
|
||||||
|
|
||||||
|
return {
|
||||||
|
timestamp: milliseconds,
|
||||||
|
isoTimestamp: new Date(milliseconds).toISOString(),
|
||||||
|
randA: ((uuidBytes[6] & 0x0f) << 8) | uuidBytes[7],
|
||||||
|
randB: toHex(uuidBytes.slice(8), "").toUpperCase()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats metadata
|
||||||
|
*
|
||||||
|
* @param {Object|undefined} decoded
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function formatDecoded(decoded) {
|
||||||
|
if (!decoded) return "No metadata available. Only versions 1, 6, 7 are supported.";
|
||||||
|
|
||||||
|
return Object.entries({
|
||||||
|
"Timestamp": decoded.timestamp,
|
||||||
|
"Timestamp (ISO)": decoded.isoTimestamp,
|
||||||
|
"Node": decoded.node,
|
||||||
|
"Clock": decoded.clock,
|
||||||
|
"Rand A": decoded.randA,
|
||||||
|
"Rand B": decoded.randB
|
||||||
|
})
|
||||||
|
.filter(([, value]) => value !== undefined)
|
||||||
|
.map(([label, value]) => `${label}:\n${value}`)
|
||||||
|
.join("\n\n");
|
||||||
|
}
|
||||||
|
|||||||
@ -6,7 +6,10 @@
|
|||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import { blake3 } from "hash-wasm";
|
import Utils from "../Utils.mjs";
|
||||||
|
import { blake3 } from "@noble/hashes/blake3.js";
|
||||||
|
import { bytesToHex } from "@noble/hashes/utils.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BLAKE3 operation
|
* BLAKE3 operation
|
||||||
*/
|
*/
|
||||||
@ -44,13 +47,16 @@ class BLAKE3 extends Operation {
|
|||||||
run(input, args) {
|
run(input, args) {
|
||||||
const key = args[1];
|
const key = args[1];
|
||||||
const size = args[0];
|
const size = args[0];
|
||||||
// Check if the user want a key hash or not
|
const opts = { dkLen: size };
|
||||||
if (key === "") {
|
const inputBytes = new Uint8Array(Utils.strToArrayBuffer(input));
|
||||||
return blake3(input, size*8);
|
if (key !== "") {
|
||||||
} if (key.length !== 32) {
|
const keyBytes = new Uint8Array(Utils.strToArrayBuffer(key));
|
||||||
|
if (keyBytes.length !== 32) {
|
||||||
throw new OperationError("The key must be exactly 32 bytes long");
|
throw new OperationError("The key must be exactly 32 bytes long");
|
||||||
}
|
}
|
||||||
return blake3(input, size*8, key);
|
opts.key = keyBytes;
|
||||||
|
}
|
||||||
|
return bytesToHex(blake3(inputBytes, opts));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import bson from "bson";
|
import { deserialize } from "bson";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,7 +37,7 @@ class BSONDeserialise extends Operation {
|
|||||||
if (!input.byteLength) return "";
|
if (!input.byteLength) return "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = bson.deserialize(new Buffer(input));
|
const data = deserialize(new Uint8Array(input));
|
||||||
return JSON.stringify(data, null, 2);
|
return JSON.stringify(data, null, 2);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(err.toString());
|
throw new OperationError(err.toString());
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import bson from "bson";
|
import { serialize } from "bson";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,7 +38,8 @@ class BSONSerialise extends Operation {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(input);
|
const data = JSON.parse(input);
|
||||||
return bson.serialize(data).buffer;
|
const result = serialize(data);
|
||||||
|
return result.buffer.slice(result.byteOffset, result.byteOffset + result.byteLength);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(err.toString());
|
throw new OperationError(err.toString());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,7 +43,7 @@ class Bcrypt extends Operation {
|
|||||||
const rounds = args[0];
|
const rounds = args[0];
|
||||||
const salt = await bcrypt.genSalt(rounds);
|
const salt = await bcrypt.genSalt(rounds);
|
||||||
|
|
||||||
return await bcrypt.hash(input, salt, null, p => {
|
return await bcrypt.hash(input, salt, undefined, p => {
|
||||||
// Progress callback
|
// Progress callback
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage(`Progress: ${(p * 100).toFixed(0)}%`);
|
self.sendStatusMessage(`Progress: ${(p * 100).toFixed(0)}%`);
|
||||||
|
|||||||
@ -43,7 +43,7 @@ class BcryptCompare extends Operation {
|
|||||||
async run(input, args) {
|
async run(input, args) {
|
||||||
const hash = args[0];
|
const hash = args[0];
|
||||||
|
|
||||||
const match = await bcrypt.compare(input, hash, null, p => {
|
const match = await bcrypt.compare(input, hash, undefined, p => {
|
||||||
// Progress callback
|
// Progress callback
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage(`Progress: ${(p * 100).toFixed(0)}%`);
|
self.sendStatusMessage(`Progress: ${(p * 100).toFixed(0)}%`);
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import cptable from "codepage";
|
import cptable from "codepage";
|
||||||
import {CHR_ENC_CODE_PAGES} from "../lib/ChrEnc.mjs";
|
import {CHR_ENC_CODE_PAGES} from "../lib/ChrEnc.mjs";
|
||||||
|
|
||||||
@ -48,6 +49,9 @@ class DecodeText extends Operation {
|
|||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const format = CHR_ENC_CODE_PAGES[args[0]];
|
const format = CHR_ENC_CODE_PAGES[args[0]];
|
||||||
|
if (!format) {
|
||||||
|
throw new OperationError("Invalid encoding");
|
||||||
|
}
|
||||||
return cptable.utils.decode(format, new Uint8Array(input));
|
return cptable.utils.decode(format, new Uint8Array(input));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import cptable from "codepage";
|
import cptable from "codepage";
|
||||||
import {CHR_ENC_CODE_PAGES} from "../lib/ChrEnc.mjs";
|
import {CHR_ENC_CODE_PAGES} from "../lib/ChrEnc.mjs";
|
||||||
|
|
||||||
@ -48,6 +49,9 @@ class EncodeText extends Operation {
|
|||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const format = CHR_ENC_CODE_PAGES[args[0]];
|
const format = CHR_ENC_CODE_PAGES[args[0]];
|
||||||
|
if (!format) {
|
||||||
|
throw new OperationError("Invalid encoding");
|
||||||
|
}
|
||||||
const encoded = cptable.utils.encode(format, input);
|
const encoded = cptable.utils.encode(format, input);
|
||||||
return new Uint8Array(encoded).buffer;
|
return new Uint8Array(encoded).buffer;
|
||||||
}
|
}
|
||||||
|
|||||||
129
src/core/operations/EscapeSmartCharacters.mjs
Normal file
129
src/core/operations/EscapeSmartCharacters.mjs
Normal file
@ -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.<br><br>Characters with no ASCII mapping (e.g. <code>☣</code>) are handled according to the 'Unmappable characters' option.<br><br>e.g. <code>“Hello” — world…</code> becomes <code>\"Hello\" -- world...</code>";
|
||||||
|
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;
|
||||||
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import { search } from "../lib/Extract.mjs";
|
import { EMAIL_REGEX, search } from "../lib/Extract.mjs";
|
||||||
import { caseInsensitiveSort } from "../lib/Sort.mjs";
|
import { caseInsensitiveSort } from "../lib/Sort.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,8 +50,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
|
regex = EMAIL_REGEX;
|
||||||
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,
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import punycode from "punycode";
|
import punycode from "punycode.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* From Punycode operation
|
* From Punycode operation
|
||||||
|
|||||||
@ -50,6 +50,14 @@ class GenerateDeBruijnSequence extends Operation {
|
|||||||
throw new OperationError("Invalid alphabet size, required to be between 2 and 9 (inclusive).");
|
throw new OperationError("Invalid alphabet size, required to be between 2 and 9 (inclusive).");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Number.isInteger(k)) {
|
||||||
|
throw new OperationError("Invalid alphabet size, required to be integer.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Number.isInteger(n)) {
|
||||||
|
throw new OperationError("Invalid key length, required to be integer.");
|
||||||
|
}
|
||||||
|
|
||||||
if (n < 2) {
|
if (n < 2) {
|
||||||
throw new OperationError("Invalid key length, required to be at least 2.");
|
throw new OperationError("Invalid key length, required to be at least 2.");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,10 @@ import Operation from "../Operation.mjs";
|
|||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import { GenerateParagraphs, GenerateSentences, GenerateWords, GenerateBytes } from "../lib/LoremIpsum.mjs";
|
import { GenerateParagraphs, GenerateSentences, GenerateWords, GenerateBytes } from "../lib/LoremIpsum.mjs";
|
||||||
|
|
||||||
|
// arbitrary limits set to avoid DoS by requesting ridiculous amounts of data
|
||||||
|
const maxLoremWords = 100_000; // same limit also used for paragraphs/sentences
|
||||||
|
const maxLoremCharacters = 1_000_000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate Lorem Ipsum operation
|
* Generate Lorem Ipsum operation
|
||||||
*/
|
*/
|
||||||
@ -47,9 +51,7 @@ class GenerateLoremIpsum extends Operation {
|
|||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const [length, lengthType] = args;
|
const [length, lengthType] = args;
|
||||||
if (length < 1) {
|
checkLimits(lengthType, length);
|
||||||
throw new OperationError("Length must be greater than 0");
|
|
||||||
}
|
|
||||||
switch (lengthType) {
|
switch (lengthType) {
|
||||||
case "Paragraphs":
|
case "Paragraphs":
|
||||||
return GenerateParagraphs(length);
|
return GenerateParagraphs(length);
|
||||||
@ -68,3 +70,32 @@ class GenerateLoremIpsum extends Operation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default GenerateLoremIpsum;
|
export default GenerateLoremIpsum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check combined validity of lengthType and length arguments
|
||||||
|
* @param {string} lengthType
|
||||||
|
* @param {number} length
|
||||||
|
* @throws {OperationError}
|
||||||
|
*/
|
||||||
|
function checkLimits(lengthType, length) {
|
||||||
|
if (length < 1) {
|
||||||
|
throw new OperationError("Length must be greater than 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (lengthType) {
|
||||||
|
case "Paragraphs":
|
||||||
|
case "Sentences":
|
||||||
|
case "Words":
|
||||||
|
if (length > maxLoremWords) {
|
||||||
|
throw new OperationError("Length must be less than " + maxLoremWords);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Bytes":
|
||||||
|
if (length > maxLoremCharacters) {
|
||||||
|
throw new OperationError("Length must be less than " + maxLoremCharacters);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new OperationError("Invalid length type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import { getSubkeySize, ASP } from "../lib/PGP.mjs";
|
|||||||
import { cryptNotice } from "../lib/Crypt.mjs";
|
import { cryptNotice } from "../lib/Crypt.mjs";
|
||||||
import * as es6promisify from "es6-promisify";
|
import * as es6promisify from "es6-promisify";
|
||||||
const promisify = es6promisify.default ? es6promisify.default.promisify : es6promisify.promisify;
|
const promisify = es6promisify.default ? es6promisify.default.promisify : es6promisify.promisify;
|
||||||
|
const KEY_FLAGS = kbpgp.const.openpgp.key_flags;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,11 +74,11 @@ class GeneratePGPKeyPair extends Operation {
|
|||||||
if (name) userIdentifier += name;
|
if (name) userIdentifier += name;
|
||||||
if (email) userIdentifier += ` <${email}>`;
|
if (email) userIdentifier += ` <${email}>`;
|
||||||
|
|
||||||
let flags = kbpgp.const.openpgp.certify_keys;
|
let flags = KEY_FLAGS.certify_keys;
|
||||||
flags |= kbpgp.const.openpgp.sign_data;
|
flags |= KEY_FLAGS.sign_data;
|
||||||
flags |= kbpgp.const.openpgp.auth;
|
flags |= KEY_FLAGS.auth;
|
||||||
flags |= kbpgp.const.openpgp.encrypt_comm;
|
flags |= KEY_FLAGS.encrypt_comm;
|
||||||
flags |= kbpgp.const.openpgp.encrypt_storage;
|
flags |= KEY_FLAGS.encrypt_storage;
|
||||||
|
|
||||||
const keyGenerationOptions = {
|
const keyGenerationOptions = {
|
||||||
userid: userIdentifier,
|
userid: userIdentifier,
|
||||||
@ -89,11 +90,11 @@ class GeneratePGPKeyPair extends Operation {
|
|||||||
},
|
},
|
||||||
subkeys: [{
|
subkeys: [{
|
||||||
"nbits": getSubkeySize(keySize),
|
"nbits": getSubkeySize(keySize),
|
||||||
"flags": kbpgp.const.openpgp.sign_data,
|
"flags": KEY_FLAGS.sign_data,
|
||||||
"expire_in": 86400 * 365 * 8
|
"expire_in": 86400 * 365 * 8
|
||||||
}, {
|
}, {
|
||||||
"nbits": getSubkeySize(keySize),
|
"nbits": getSubkeySize(keySize),
|
||||||
"flags": kbpgp.const.openpgp.encrypt_comm | kbpgp.const.openpgp.encrypt_storage,
|
"flags": KEY_FLAGS.encrypt_comm | KEY_FLAGS.encrypt_storage,
|
||||||
"expire_in": 86400 * 365 * 2
|
"expire_in": 86400 * 365 * 2
|
||||||
}],
|
}],
|
||||||
asp: ASP
|
asp: ASP
|
||||||
|
|||||||
@ -99,7 +99,7 @@ class OffsetChecker extends Operation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return outputs.join(sampleDelim);
|
return outputs.join(Utils.escapeHtml(sampleDelim));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
83
src/core/operations/PGPSign.mjs
Normal file
83
src/core/operations/PGPSign.mjs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* @author GCHQDeveloper581
|
||||||
|
* @copyright Crown Copyright 2026
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import kbpgp from "kbpgp";
|
||||||
|
import { ASP, importPrivateKey } from "../lib/PGP.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import * as es6promisify from "es6-promisify";
|
||||||
|
const promisify = es6promisify.default ? es6promisify.default.promisify : es6promisify.promisify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PGP Sign operation
|
||||||
|
*/
|
||||||
|
class PGPSign extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PGPSign constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "PGP Sign";
|
||||||
|
this.module = "PGP";
|
||||||
|
this.description = [
|
||||||
|
"Input: the message you want to sign",
|
||||||
|
"<br><br>",
|
||||||
|
"Arguments: the ASCII-armoured PGP private key of the sender.",
|
||||||
|
"<br><br>",
|
||||||
|
"Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.",
|
||||||
|
"<br><br>",
|
||||||
|
"This function uses the Keybase implementation of PGP.",
|
||||||
|
].join("\n");
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Pretty_Good_Privacy"; // Usually a Wikipedia link. Remember to remove localisation (i.e. https://wikipedia.org/etc rather than https://en.wikipedia.org/etc)
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Private key of signer",
|
||||||
|
"type": "text",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Private key passphrase (optional)",
|
||||||
|
"type": "string",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*
|
||||||
|
* @throws {OperationError} if failed private key import or failed encryption
|
||||||
|
*/
|
||||||
|
async run(input, args) {
|
||||||
|
const message = input,
|
||||||
|
[privateKey, passphrase] = args;
|
||||||
|
let signedMessage;
|
||||||
|
|
||||||
|
if (!privateKey) throw new OperationError("Enter the private key of the signer.");
|
||||||
|
const privKey = await importPrivateKey(privateKey, passphrase);
|
||||||
|
|
||||||
|
try {
|
||||||
|
signedMessage = await promisify(kbpgp.box)({
|
||||||
|
"msg": message,
|
||||||
|
"sign_with": privKey,
|
||||||
|
"asp": ASP
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
throw new OperationError(`Couldn't sign message: ${err}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return signedMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PGPSign;
|
||||||
128
src/core/operations/ParityBit.mjs
Normal file
128
src/core/operations/ParityBit.mjs
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/**
|
||||||
|
* @author j83305 [awz22@protonmail.com]
|
||||||
|
* @copyright Crown Copyright 2020
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import { calculateParityBit, decodeParityBit } from "../lib/ParityBit.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parity Bit operation
|
||||||
|
*/
|
||||||
|
class ParityBit extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ParityBit constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "Parity Bit";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "A parity bit, or check bit, is the simplest form of error detection. It is a bit which is added to a string of bits and represents if the number of 1's in the binary string is an even number or odd number.<br><br>If a delimiter is specified, the parity bit calculation will be performed on each 'block' of the input data, where the blocks are created by slicing the input at each occurrence of the delimiter character";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Parity_bit";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Mode",
|
||||||
|
type: "option",
|
||||||
|
value: [
|
||||||
|
"Even Parity",
|
||||||
|
"Odd Parity"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Postion",
|
||||||
|
type: "option",
|
||||||
|
value: [
|
||||||
|
"Start",
|
||||||
|
"End"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Encode or Decode",
|
||||||
|
type: "option",
|
||||||
|
value: [
|
||||||
|
"Encode",
|
||||||
|
"Decode"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Delimiter",
|
||||||
|
type: "shortString",
|
||||||
|
value: ""
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
if (input.length === 0) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* determines weather to use the encode or decode method based off args[2]
|
||||||
|
* @param input input to be encoded or decoded
|
||||||
|
* @param args array
|
||||||
|
*/
|
||||||
|
const method = (input, args) => args[2] === "Encode" ? calculateParityBit(input, args) : decodeParityBit(input, args);
|
||||||
|
if (args[3].length > 0) {
|
||||||
|
const byteStrings = input.split(args[3]);
|
||||||
|
for (let byteStringsArrayIndex = 0; byteStringsArrayIndex < byteStrings.length; byteStringsArrayIndex++) {
|
||||||
|
byteStrings[byteStringsArrayIndex] = method(byteStrings[byteStringsArrayIndex], args);
|
||||||
|
}
|
||||||
|
return byteStrings.join(args[3]);
|
||||||
|
}
|
||||||
|
return method(input, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlight Parity Bit
|
||||||
|
*
|
||||||
|
* @param {Object[]} pos
|
||||||
|
* @param {number} pos[].start
|
||||||
|
* @param {number} pos[].end
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {Object[]} pos
|
||||||
|
*/
|
||||||
|
highlight(pos, args) {
|
||||||
|
if (args[3].length === 0) {
|
||||||
|
if (args[1] === "Prepend") {
|
||||||
|
pos[0].start += 1;
|
||||||
|
pos[0].end += 1;
|
||||||
|
}
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
// need to be able to read input to do the highlighting when there is a delimiter
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlight Parity Bit in reverse
|
||||||
|
*
|
||||||
|
* @param {Object[]} pos
|
||||||
|
* @param {number} pos[].start
|
||||||
|
* @param {number} pos[].end
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {Object[]} pos
|
||||||
|
*/
|
||||||
|
highlightReverse(pos, args) {
|
||||||
|
if (args[3].length === 0) {
|
||||||
|
if (args[1] === "Prepend") {
|
||||||
|
if (pos[0].start > 0) {
|
||||||
|
pos[0].start -= 1;
|
||||||
|
}
|
||||||
|
pos[0].end -= 1;
|
||||||
|
}
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ParityBit;
|
||||||
@ -92,7 +92,7 @@ class ParseEthernetFrame extends Operation {
|
|||||||
const packetData = input.slice(offset);
|
const packetData = input.slice(offset);
|
||||||
|
|
||||||
if (outputFormat === "Packet data") {
|
if (outputFormat === "Packet data") {
|
||||||
return Utils.byteArrayToChars(packetData);
|
return Utils.escapeHtml(Utils.byteArrayToChars(packetData));
|
||||||
} else if (outputFormat === "Packet data (hex)") {
|
} else if (outputFormat === "Packet data (hex)") {
|
||||||
return toHex(packetData);
|
return toHex(packetData);
|
||||||
} else if (outputFormat === "Text output") {
|
} else if (outputFormat === "Text output") {
|
||||||
|
|||||||
@ -74,7 +74,7 @@ class ParseIPv4Header extends Operation {
|
|||||||
checksum = input[10] << 8 | input[11],
|
checksum = input[10] << 8 | input[11],
|
||||||
srcIP = input[12] << 24 | input[13] << 16 | input[14] << 8 | input[15],
|
srcIP = input[12] << 24 | input[13] << 16 | input[14] << 8 | input[15],
|
||||||
dstIP = input[16] << 24 | input[17] << 16 | input[18] << 8 | input[19],
|
dstIP = input[16] << 24 | input[17] << 16 | input[18] << 8 | input[19],
|
||||||
checksumHeader = input.slice(0, 10).concat([0, 0]).concat(input.slice(12, 20));
|
checksumHeader = [...input.slice(0, 10), 0, 0, ...input.slice(12, 20)];
|
||||||
let version = (input[0] >>> 4) & 0x0f,
|
let version = (input[0] >>> 4) & 0x0f,
|
||||||
options = [];
|
options = [];
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ class ParseIPv4Header extends Operation {
|
|||||||
} else if (outputFormat === "Data (hex)") {
|
} else if (outputFormat === "Data (hex)") {
|
||||||
return toHex(data);
|
return toHex(data);
|
||||||
} else if (outputFormat === "Data (raw)") {
|
} else if (outputFormat === "Data (raw)") {
|
||||||
return Utils.byteArrayToChars(data);
|
return Utils.escapeHtml(Utils.byteArrayToChars(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import BSON from "bson";
|
import { ObjectId } from "bson";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse ObjectID timestamp operation
|
* Parse ObjectID timestamp operation
|
||||||
@ -35,7 +35,7 @@ class ParseObjectIDTimestamp extends Operation {
|
|||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
try {
|
try {
|
||||||
const objectId = new BSON.ObjectID(input);
|
const objectId = new ObjectId(input);
|
||||||
return objectId.getTimestamp().toISOString();
|
return objectId.getTimestamp().toISOString();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(err);
|
throw new OperationError(err);
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import UAParser from "ua-parser-js";
|
import { UAParser } from "ua-parser-js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse User Agent operation
|
* Parse User Agent operation
|
||||||
|
|||||||
83
src/core/operations/ROR13.mjs
Normal file
83
src/core/operations/ROR13.mjs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* ROR13 Hash operation (Windows API hashing convention)
|
||||||
|
* @author fufu_btw
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements a ROR13 hash used for API name hashing techniques.
|
||||||
|
*/
|
||||||
|
class ROR13 extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "ROR13";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Computes a ROR13 hash used in API hashing techniques.";
|
||||||
|
this.infoURL = "";
|
||||||
|
this.inputType = "byteArray";
|
||||||
|
this.outputType = "string";
|
||||||
|
|
||||||
|
this.args = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotate right (32-bit)
|
||||||
|
*
|
||||||
|
* @param {number} value - input value
|
||||||
|
* @param {number} bits - rotation bits
|
||||||
|
* @returns {number} rotated value
|
||||||
|
*/
|
||||||
|
ror(value, bits) {
|
||||||
|
return ((value >>> bits) | (value << (32 - bits))) >>> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute ROR13 hash
|
||||||
|
*
|
||||||
|
* @param {byteArray} input - input bytes
|
||||||
|
* @param {Object[]} args - operation arguments
|
||||||
|
* @returns {string} hex hash
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
let hash = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < input.length; i++) {
|
||||||
|
const chr = input[i] & 0xFF;
|
||||||
|
hash = this.ror(hash, 13);
|
||||||
|
hash = (hash + chr) >>> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "0x" + hash.toString(16).padStart(8, "0").toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlight input
|
||||||
|
*
|
||||||
|
* @param {Object[]} pos
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {Object[]}
|
||||||
|
*/
|
||||||
|
highlight(pos, args) {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse highlight
|
||||||
|
*
|
||||||
|
* @param {Object[]} pos
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {Object[]}
|
||||||
|
*/
|
||||||
|
highlightReverse(pos, args) {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ROR13;
|
||||||
@ -7,6 +7,7 @@
|
|||||||
import XRegExp from "xregexp";
|
import XRegExp from "xregexp";
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
|
import { EMAIL_REGEX } from "../lib/Extract.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,7 +46,7 @@ class RegularExpression extends Operation {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Email address",
|
name: "Email address",
|
||||||
value: "(?:[\\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-\\uFFFF-a-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}\\])"
|
value: EMAIL_REGEX.source // We use a different regex library, so just take the source regex string here
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "URL",
|
name: "URL",
|
||||||
|
|||||||
41
src/core/operations/RemoveANSIEscapeCodes.mjs
Normal file
41
src/core/operations/RemoveANSIEscapeCodes.mjs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* @author Louis-Ladd [lewisharshman1@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2025
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove ANSI Escape Codes operation
|
||||||
|
*/
|
||||||
|
class RemoveANSIEscapeCodes extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RemoveANSIEscapeCodes constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "Remove ANSI Escape Codes";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Removes ANSI Escape Codes.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/ANSI_escape_code";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const ansiRegex = /\x1B\[[0-?]*[ -/]*[@-~]/g;
|
||||||
|
return input.replace(ansiRegex, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RemoveANSIEscapeCodes;
|
||||||
@ -35,6 +35,11 @@ class RenderMarkdown extends Operation {
|
|||||||
name: "Enable syntax highlighting",
|
name: "Enable syntax highlighting",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: true
|
value: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Open links in new tab.",
|
||||||
|
type: "boolean",
|
||||||
|
value: false
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -45,7 +50,7 @@ class RenderMarkdown extends Operation {
|
|||||||
* @returns {html}
|
* @returns {html}
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const [convertLinks, enableHighlighting] = args,
|
const [convertLinks, enableHighlighting, openLinksBlank] = args,
|
||||||
md = new MarkdownIt({
|
md = new MarkdownIt({
|
||||||
linkify: convertLinks,
|
linkify: convertLinks,
|
||||||
html: false, // Explicitly disable HTML rendering
|
html: false, // Explicitly disable HTML rendering
|
||||||
@ -58,12 +63,38 @@ class RenderMarkdown extends Operation {
|
|||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}),
|
});
|
||||||
rendered = md.render(input);
|
if (openLinksBlank) {
|
||||||
|
this.makeLinksOpenInNewTab(md);
|
||||||
|
}
|
||||||
|
const rendered = md.render(input);
|
||||||
return `<div style="font-family: var(--primary-font-family)">${rendered}</div>`;
|
return `<div style="font-family: var(--primary-font-family)">${rendered}</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds target="_blank" to links.
|
||||||
|
* @param {MarkdownIt} md
|
||||||
|
*/
|
||||||
|
makeLinksOpenInNewTab(md) {
|
||||||
|
// Adapted from: https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer
|
||||||
|
// Remember old renderer, if overridden, or proxy to default renderer
|
||||||
|
const defaultRender = md.renderer.rules.link_open || function(tokens, idx, options, env, self) {
|
||||||
|
return self.renderToken(tokens, idx, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
|
||||||
|
const token = tokens[idx];
|
||||||
|
if (token.attrIndex("target") >= 0) {
|
||||||
|
// Target attribute already set, do not replace.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
token.attrPush(["target", "_blank"]); // add new attribute
|
||||||
|
|
||||||
|
// pass token to default renderer.
|
||||||
|
return defaultRender(tokens, idx, options, env, self);
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default RenderMarkdown;
|
export default RenderMarkdown;
|
||||||
|
|||||||
@ -20,7 +20,7 @@ class SHA2 extends Operation {
|
|||||||
|
|
||||||
this.name = "SHA2";
|
this.name = "SHA2";
|
||||||
this.module = "Crypto";
|
this.module = "Crypto";
|
||||||
this.description = "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.<br><br><ul><li>SHA-512 operates on 64-bit words.</li><li>SHA-256 operates on 32-bit words.</li><li>SHA-384 is largely identical to SHA-512 but is truncated to 384 bytes.</li><li>SHA-224 is largely identical to SHA-256 but is truncated to 224 bytes.</li><li>SHA-512/224 and SHA-512/256 are truncated versions of SHA-512, but the initial values are generated using the method described in Federal Information Processing Standards (FIPS) PUB 180-4.</li></ul> The message digest algorithm for SHA256 variants consists, by default, of 64 rounds, and for SHA512 variants, it is, by default, 160.";
|
this.description = "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.<br><br><ul><li>SHA-512 operates on 64-bit words.</li><li>SHA-256 operates on 32-bit words.</li><li>SHA-384 is largely identical to SHA-512 but is truncated to 384 bits.</li><li>SHA-224 is largely identical to SHA-256 but is truncated to 224 bits.</li><li>SHA-512/224 and SHA-512/256 are truncated versions of SHA-512, but the initial values are generated using the method described in Federal Information Processing Standards (FIPS) PUB 180-4.</li></ul> The message digest algorithm for SHA256 variants consists, by default, of 64 rounds, and for SHA512 variants, it is, by default, 160.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/SHA-2";
|
this.infoURL = "https://wikipedia.org/wiki/SHA-2";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
|
|||||||
@ -15,6 +15,20 @@ import Utils from "../Utils.mjs";
|
|||||||
const d3 = d3temp.default ? d3temp.default : d3temp;
|
const d3 = d3temp.default ? d3temp.default : d3temp;
|
||||||
const nodom = nodomtemp.default ? nodomtemp.default: nodomtemp;
|
const nodom = nodomtemp.default ? nodomtemp.default: nodomtemp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes D3's internal bound data from a nodom tree before serialization.
|
||||||
|
* nodom serializes enumerable expando properties such as __data__ as attributes,
|
||||||
|
* so leaving them on attacker-controlled values can create executable markup.
|
||||||
|
*
|
||||||
|
* @param {Object} node
|
||||||
|
*/
|
||||||
|
function clearD3BoundData(node) {
|
||||||
|
delete node.__data__;
|
||||||
|
|
||||||
|
if (!node.childNodes) return;
|
||||||
|
node.childNodes.forEach(clearD3BoundData);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Series chart operation
|
* Series chart operation
|
||||||
*/
|
*/
|
||||||
@ -222,6 +236,8 @@ class SeriesChart extends Operation {
|
|||||||
.text(serie.name);
|
.text(serie.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
clearD3BoundData(svg.node());
|
||||||
|
|
||||||
return svg._groups[0][0].outerHTML;
|
return svg._groups[0][0].outerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -77,84 +77,84 @@ class ShowBase64Offsets extends Operation {
|
|||||||
staticSection = offset0.slice(0, -3);
|
staticSection = offset0.slice(0, -3);
|
||||||
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||||
Utils.escapeHtml(fromBase64(staticSection, alphabet).slice(0, -2)) + "'>" +
|
Utils.escapeHtml(fromBase64(staticSection, alphabet).slice(0, -2)) + "'>" +
|
||||||
staticSection + "</span>" +
|
Utils.escapeHtml(staticSection) + "</span>" +
|
||||||
"<span class='hl5'>" + offset0.substr(offset0.length - 3, 1) + "</span>" +
|
"<span class='hl5'>" + Utils.escapeHtml(offset0.substr(offset0.length - 3, 1)) + "</span>" +
|
||||||
"<span class='hl3'>" + offset0.substr(offset0.length - 2) + "</span>";
|
"<span class='hl3'>" + Utils.escapeHtml(offset0.substr(offset0.length - 2)) + "</span>";
|
||||||
} else if (len0 % 4 === 3) {
|
} else if (len0 % 4 === 3) {
|
||||||
staticSection = offset0.slice(0, -2);
|
staticSection = offset0.slice(0, -2);
|
||||||
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||||
Utils.escapeHtml(fromBase64(staticSection, alphabet).slice(0, -1)) + "'>" +
|
Utils.escapeHtml(fromBase64(staticSection, alphabet).slice(0, -1)) + "'>" +
|
||||||
staticSection + "</span>" +
|
Utils.escapeHtml(staticSection) + "</span>" +
|
||||||
"<span class='hl5'>" + offset0.substr(offset0.length - 2, 1) + "</span>" +
|
"<span class='hl5'>" + Utils.escapeHtml(offset0.substr(offset0.length - 2, 1)) + "</span>" +
|
||||||
"<span class='hl3'>" + offset0.substr(offset0.length - 1) + "</span>";
|
"<span class='hl3'>" + Utils.escapeHtml(offset0.substr(offset0.length - 1)) + "</span>";
|
||||||
} else {
|
} else {
|
||||||
staticSection = offset0;
|
staticSection = offset0;
|
||||||
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||||
Utils.escapeHtml(fromBase64(staticSection, alphabet)) + "'>" +
|
Utils.escapeHtml(fromBase64(staticSection, alphabet)) + "'>" +
|
||||||
staticSection + "</span>";
|
Utils.escapeHtml(staticSection) + "</span>";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!showVariable) {
|
if (!showVariable) {
|
||||||
offset0 = staticSection;
|
offset0 = Utils.escapeHtml(staticSection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Highlight offset 1
|
// Highlight offset 1
|
||||||
padding = "<span class='hl3'>" + offset1.substr(0, 1) + "</span>" +
|
padding = "<span class='hl3'>" + Utils.escapeHtml(offset1.substr(0, 1)) + "</span>" +
|
||||||
"<span class='hl5'>" + offset1.substr(1, 1) + "</span>";
|
"<span class='hl5'>" + Utils.escapeHtml(offset1.substr(1, 1)) + "</span>";
|
||||||
offset1 = offset1.substr(2);
|
offset1 = offset1.substr(2);
|
||||||
if (len1 % 4 === 2) {
|
if (len1 % 4 === 2) {
|
||||||
staticSection = offset1.slice(0, -3);
|
staticSection = offset1.slice(0, -3);
|
||||||
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||||
Utils.escapeHtml(fromBase64("AA" + staticSection, alphabet).slice(1, -2)) + "'>" +
|
Utils.escapeHtml(fromBase64("AA" + staticSection, alphabet).slice(1, -2)) + "'>" +
|
||||||
staticSection + "</span>" +
|
Utils.escapeHtml(staticSection) + "</span>" +
|
||||||
"<span class='hl5'>" + offset1.substr(offset1.length - 3, 1) + "</span>" +
|
"<span class='hl5'>" + Utils.escapeHtml(offset1.substr(offset1.length - 3, 1)) + "</span>" +
|
||||||
"<span class='hl3'>" + offset1.substr(offset1.length - 2) + "</span>";
|
"<span class='hl3'>" + Utils.escapeHtml(offset1.substr(offset1.length - 2)) + "</span>";
|
||||||
} else if (len1 % 4 === 3) {
|
} else if (len1 % 4 === 3) {
|
||||||
staticSection = offset1.slice(0, -2);
|
staticSection = offset1.slice(0, -2);
|
||||||
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||||
Utils.escapeHtml(fromBase64("AA" + staticSection, alphabet).slice(1, -1)) + "'>" +
|
Utils.escapeHtml(fromBase64("AA" + staticSection, alphabet).slice(1, -1)) + "'>" +
|
||||||
staticSection + "</span>" +
|
Utils.escapeHtml(staticSection) + "</span>" +
|
||||||
"<span class='hl5'>" + offset1.substr(offset1.length - 2, 1) + "</span>" +
|
"<span class='hl5'>" + Utils.escapeHtml(offset1.substr(offset1.length - 2, 1)) + "</span>" +
|
||||||
"<span class='hl3'>" + offset1.substr(offset1.length - 1) + "</span>";
|
"<span class='hl3'>" + Utils.escapeHtml(offset1.substr(offset1.length - 1)) + "</span>";
|
||||||
} else {
|
} else {
|
||||||
staticSection = offset1;
|
staticSection = offset1;
|
||||||
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||||
Utils.escapeHtml(fromBase64("AA" + staticSection, alphabet).slice(1)) + "'>" +
|
Utils.escapeHtml(fromBase64("AA" + staticSection, alphabet).slice(1)) + "'>" +
|
||||||
staticSection + "</span>";
|
Utils.escapeHtml(staticSection) + "</span>";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!showVariable) {
|
if (!showVariable) {
|
||||||
offset1 = staticSection;
|
offset1 = Utils.escapeHtml(staticSection);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Highlight offset 2
|
// Highlight offset 2
|
||||||
padding = "<span class='hl3'>" + offset2.substr(0, 2) + "</span>" +
|
padding = "<span class='hl3'>" + Utils.escapeHtml(offset2.substr(0, 2)) + "</span>" +
|
||||||
"<span class='hl5'>" + offset2.substr(2, 1) + "</span>";
|
"<span class='hl5'>" + Utils.escapeHtml(offset2.substr(2, 1)) + "</span>";
|
||||||
offset2 = offset2.substr(3);
|
offset2 = offset2.substr(3);
|
||||||
if (len2 % 4 === 2) {
|
if (len2 % 4 === 2) {
|
||||||
staticSection = offset2.slice(0, -3);
|
staticSection = offset2.slice(0, -3);
|
||||||
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||||
Utils.escapeHtml(fromBase64("AAA" + staticSection, alphabet).slice(2, -2)) + "'>" +
|
Utils.escapeHtml(fromBase64("AAA" + staticSection, alphabet).slice(2, -2)) + "'>" +
|
||||||
staticSection + "</span>" +
|
Utils.escapeHtml(staticSection) + "</span>" +
|
||||||
"<span class='hl5'>" + offset2.substr(offset2.length - 3, 1) + "</span>" +
|
"<span class='hl5'>" + Utils.escapeHtml(offset2.substr(offset2.length - 3, 1)) + "</span>" +
|
||||||
"<span class='hl3'>" + offset2.substr(offset2.length - 2) + "</span>";
|
"<span class='hl3'>" + Utils.escapeHtml(offset2.substr(offset2.length - 2)) + "</span>";
|
||||||
} else if (len2 % 4 === 3) {
|
} else if (len2 % 4 === 3) {
|
||||||
staticSection = offset2.slice(0, -2);
|
staticSection = offset2.slice(0, -2);
|
||||||
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||||
Utils.escapeHtml(fromBase64("AAA" + staticSection, alphabet).slice(2, -2)) + "'>" +
|
Utils.escapeHtml(fromBase64("AAA" + staticSection, alphabet).slice(2, -2)) + "'>" +
|
||||||
staticSection + "</span>" +
|
Utils.escapeHtml(staticSection) + "</span>" +
|
||||||
"<span class='hl5'>" + offset2.substr(offset2.length - 2, 1) + "</span>" +
|
"<span class='hl5'>" + Utils.escapeHtml(offset2.substr(offset2.length - 2, 1)) + "</span>" +
|
||||||
"<span class='hl3'>" + offset2.substr(offset2.length - 1) + "</span>";
|
"<span class='hl3'>" + Utils.escapeHtml(offset2.substr(offset2.length - 1)) + "</span>";
|
||||||
} else {
|
} else {
|
||||||
staticSection = offset2;
|
staticSection = offset2;
|
||||||
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
|
||||||
Utils.escapeHtml(fromBase64("AAA" + staticSection, alphabet).slice(2)) + "'>" +
|
Utils.escapeHtml(fromBase64("AAA" + staticSection, alphabet).slice(2)) + "'>" +
|
||||||
staticSection + "</span>";
|
Utils.escapeHtml(staticSection) + "</span>";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!showVariable) {
|
if (!showVariable) {
|
||||||
offset2 = staticSection;
|
offset2 = Utils.escapeHtml(staticSection);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (showVariable ? "Characters highlighted in <span class='hl5'>green</span> could change if the input is surrounded by more data." +
|
return (showVariable ? "Characters highlighted in <span class='hl5'>green</span> could change if the input is surrounded by more data." +
|
||||||
|
|||||||
@ -8,6 +8,8 @@ import Operation from "../Operation.mjs";
|
|||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
const MAX_WIDTH = 65536;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To Hexdump operation
|
* To Hexdump operation
|
||||||
*/
|
*/
|
||||||
@ -30,7 +32,8 @@ class ToHexdump extends Operation {
|
|||||||
"name": "Width",
|
"name": "Width",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"value": 16,
|
"value": 16,
|
||||||
"min": 1
|
"min": 1,
|
||||||
|
"max": MAX_WIDTH
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Upper case hex",
|
"name": "Upper case hex",
|
||||||
@ -63,6 +66,9 @@ class ToHexdump extends Operation {
|
|||||||
if (length < 1 || Math.round(length) !== length)
|
if (length < 1 || Math.round(length) !== length)
|
||||||
throw new OperationError("Width must be a positive integer");
|
throw new OperationError("Width must be a positive integer");
|
||||||
|
|
||||||
|
if (length > MAX_WIDTH)
|
||||||
|
throw new OperationError(`Width must be no more than ${MAX_WIDTH}`);
|
||||||
|
|
||||||
const lines = [];
|
const lines = [];
|
||||||
for (let i = 0; i < data.length; i += length) {
|
for (let i = 0; i < data.length; i += length) {
|
||||||
let lineNo = Utils.hex(i, 8);
|
let lineNo = Utils.hex(i, 8);
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import punycode from "punycode";
|
import punycode from "punycode.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To Punycode operation
|
* To Punycode operation
|
||||||
|
|||||||
47
src/core/operations/Wrap.mjs
Normal file
47
src/core/operations/Wrap.mjs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* @author 0xff1ce [github.com/0xff1ce]
|
||||||
|
* @copyright Crown Copyright 2024
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap operation
|
||||||
|
*/
|
||||||
|
class Wrap extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "Wrap";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Wraps the input text at a specified number of characters per line.";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Line Width",
|
||||||
|
"type": "number",
|
||||||
|
"value": 64,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
if (!input) return ""; // Handle empty input
|
||||||
|
const lineWidth = args[0];
|
||||||
|
const regex = new RegExp(`.{1,${lineWidth}}`, "g");
|
||||||
|
return input.match(regex).join("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Wrap;
|
||||||
@ -88,16 +88,17 @@ class NodeRecipe {
|
|||||||
* @param {NodeDish} dish
|
* @param {NodeDish} dish
|
||||||
* @returns {NodeDish}
|
* @returns {NodeDish}
|
||||||
*/
|
*/
|
||||||
execute(dish) {
|
async execute(dish) {
|
||||||
return this.opList.reduce((prev, curr) => {
|
let prev = dish;
|
||||||
// CASE where opList item is op and args
|
for (const curr of this.opList) {
|
||||||
if (Object.prototype.hasOwnProperty.call(curr, "op") &&
|
if (Object.prototype.hasOwnProperty.call(curr, "op") &&
|
||||||
Object.prototype.hasOwnProperty.call(curr, "args")) {
|
Object.prototype.hasOwnProperty.call(curr, "args")) {
|
||||||
return curr.op(prev, curr.args);
|
prev = await curr.op(prev, curr.args);
|
||||||
|
} else {
|
||||||
|
prev = await curr(prev);
|
||||||
}
|
}
|
||||||
// CASE opList item is just op.
|
}
|
||||||
return curr(prev);
|
return prev;
|
||||||
}, dish);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
import NodeDish from "./NodeDish.mjs";
|
import NodeDish from "./NodeDish.mjs";
|
||||||
import NodeRecipe from "./NodeRecipe.mjs";
|
import NodeRecipe from "./NodeRecipe.mjs";
|
||||||
import OperationConfig from "../core/config/OperationConfig.json" assert {type: "json"};
|
import OperationConfig from "../core/config/OperationConfig.json" with { type: "json" };
|
||||||
import { sanitise, removeSubheadingsFromArray, sentenceToCamelCase } from "./apiUtils.mjs";
|
import { sanitise, removeSubheadingsFromArray, sentenceToCamelCase } from "./apiUtils.mjs";
|
||||||
import ExcludedOperationError from "../core/errors/ExcludedOperationError.mjs";
|
import ExcludedOperationError from "../core/errors/ExcludedOperationError.mjs";
|
||||||
|
|
||||||
@ -324,10 +324,10 @@ export function help(input) {
|
|||||||
* @returns {NodeDish} of the result
|
* @returns {NodeDish} of the result
|
||||||
* @throws {TypeError} if invalid recipe given.
|
* @throws {TypeError} if invalid recipe given.
|
||||||
*/
|
*/
|
||||||
export function bake(input, recipeConfig) {
|
export async function bake(input, recipeConfig) {
|
||||||
const recipe = new NodeRecipe(recipeConfig);
|
const recipe = new NodeRecipe(recipeConfig);
|
||||||
const dish = ensureIsDish(input);
|
const dish = ensureIsDish(input);
|
||||||
return recipe.execute(dish);
|
return await recipe.execute(dish);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,14 @@ class App {
|
|||||||
this.progress = 0;
|
this.progress = 0;
|
||||||
this.ingId = 0;
|
this.ingId = 0;
|
||||||
|
|
||||||
|
// stateChangeId increments on every statechange dispatch; bakeStateId records
|
||||||
|
// the stateChangeId captured when the most recent bake started. autoBake uses
|
||||||
|
// these to decide whether the output is genuinely stale, so a debounced
|
||||||
|
// autoBake firing shortly after a manual bake doesn't clobber the bake's
|
||||||
|
// hideStaleIndicator with a redundant showStaleIndicator.
|
||||||
|
this.stateChangeId = 0;
|
||||||
|
this.bakeStateId = -1;
|
||||||
|
|
||||||
this.appLoaded = false;
|
this.appLoaded = false;
|
||||||
this.workerLoaded = false;
|
this.workerLoaded = false;
|
||||||
this.waitersLoaded = false;
|
this.waitersLoaded = false;
|
||||||
@ -136,6 +144,9 @@ class App {
|
|||||||
bake(step=false) {
|
bake(step=false) {
|
||||||
if (this.baking) return;
|
if (this.baking) return;
|
||||||
|
|
||||||
|
// Record which state version this bake is covering.
|
||||||
|
this.bakeStateId = this.stateChangeId;
|
||||||
|
|
||||||
// Reset attemptHighlight flag
|
// Reset attemptHighlight flag
|
||||||
this.options.attemptHighlight = true;
|
this.options.attemptHighlight = true;
|
||||||
|
|
||||||
@ -166,7 +177,10 @@ class App {
|
|||||||
nums: [this.manager.tabs.getActiveTab("input")],
|
nums: [this.manager.tabs.getActiveTab("input")],
|
||||||
step: false
|
step: false
|
||||||
});
|
});
|
||||||
} else {
|
} else if (this.bakeStateId < this.stateChangeId) {
|
||||||
|
// Only show stale-indicator if the most recent bake didn't cover the
|
||||||
|
// current state. Without this guard, a debounced autoBake firing after
|
||||||
|
// a manual bake completed would re-show the indicator on fresh output.
|
||||||
this.manager.controls.showStaleIndicator();
|
this.manager.controls.showStaleIndicator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -768,6 +782,10 @@ class App {
|
|||||||
* @param {event} e
|
* @param {event} e
|
||||||
*/
|
*/
|
||||||
stateChange(e) {
|
stateChange(e) {
|
||||||
|
// Bump the state-change counter synchronously so a manual bake invoked between
|
||||||
|
// here and the debounced autoBake firing can record it via bakeStateId.
|
||||||
|
this.stateChangeId++;
|
||||||
|
|
||||||
debounce(function() {
|
debounce(function() {
|
||||||
this.progress = 0;
|
this.progress = 0;
|
||||||
this.autoBake();
|
this.autoBake();
|
||||||
|
|||||||
@ -166,6 +166,7 @@ class HTMLIngredient {
|
|||||||
id="${this.id}"
|
id="${this.id}"
|
||||||
tabindex="${this.tabIndex}"
|
tabindex="${this.tabIndex}"
|
||||||
arg-name="${this.name}"
|
arg-name="${this.name}"
|
||||||
|
data-target="${this.target}"
|
||||||
${this.disabled ? "disabled" : ""}>`;
|
${this.disabled ? "disabled" : ""}>`;
|
||||||
for (i = 0; i < this.value.length; i++) {
|
for (i = 0; i < this.value.length; i++) {
|
||||||
if ((m = this.value[i].name.match(/\[([a-z0-9 -()^]+)\]/i))) {
|
if ((m = this.value[i].name.match(/\[([a-z0-9 -()^]+)\]/i))) {
|
||||||
|
|||||||
@ -43,17 +43,23 @@ class HTMLOperation {
|
|||||||
/**
|
/**
|
||||||
* Renders the operation in HTML as a stub operation with no ingredients.
|
* Renders the operation in HTML as a stub operation with no ingredients.
|
||||||
*
|
*
|
||||||
|
* @param {boolean} removeIcon - show icon for removing operation
|
||||||
|
* @param {string} elementId - element ID for aria usage
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
toStubHtml(removeIcon) {
|
toStubHtml(removeIcon = false, elementId = null) {
|
||||||
let html = "<li class='operation'";
|
let html = "<li class='operation'";
|
||||||
|
|
||||||
|
if (elementId) {
|
||||||
|
html += ` id='${elementId}'`;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.description) {
|
if (this.description) {
|
||||||
const infoLink = this.infoURL ? `<hr>${titleFromWikiLink(this.infoURL)}` : "";
|
const infoLink = this.infoURL ? `<hr>${titleFromWikiLink(this.infoURL)}` : "";
|
||||||
|
|
||||||
html += ` data-container='body' data-toggle='popover' data-placement='right'
|
html += ` data-container='body' data-toggle='popover' data-placement='right'
|
||||||
data-content="${this.description}${infoLink}" data-html='true' data-trigger='hover'
|
data-content="${this.description}${infoLink}" data-html='true' data-trigger='hover'
|
||||||
data-boundary='viewport'`;
|
data-boundary='viewport' role='button'`;
|
||||||
}
|
}
|
||||||
|
|
||||||
html += ">" + this.name;
|
html += ">" + this.name;
|
||||||
|
|||||||
@ -173,7 +173,7 @@
|
|||||||
Operations
|
Operations
|
||||||
<span class="op-count"></span>
|
<span class="op-count"></span>
|
||||||
</div>
|
</div>
|
||||||
<input id="search" type="search" class="form-control" placeholder="Search..." autocomplete="off" tabindex="0" data-help-title="Searching for operations" data-help="<p>Use the search box to find useful operations.</p><p>Both operation names and descriptions are queried using a fuzzy matching algorithm.</p>">
|
<input id="search" type="search" class="form-control" placeholder="Search..." autocomplete="off" tabindex="0" data-help-title="Searching for operations" data-help="<p>Use the search box to find useful operations.</p><p>Both operation names and descriptions are queried using a fuzzy matching algorithm.</p>" aria-owns="search-results">
|
||||||
<ul id="search-results" class="op-list"></ul>
|
<ul id="search-results" class="op-list"></ul>
|
||||||
<div id="categories" class="panel-group no-select"></div>
|
<div id="categories" class="panel-group no-select"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -868,15 +868,15 @@
|
|||||||
Be aware that the standalone version will never update itself, meaning it will not receive bug fixes or new features until you re-download newer versions manually.
|
Be aware that the standalone version will never update itself, meaning it will not receive bug fixes or new features until you re-download newer versions manually.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h6>CyberChef v<%= htmlWebpackPlugin.options.version %></h6>
|
<h6>CyberChef <%= htmlWebpackPlugin.options.version %></h6>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Build time: <%= htmlWebpackPlugin.options.compileTime %></li>
|
<li>Build time: <%= htmlWebpackPlugin.options.compileTime %></li>
|
||||||
<li>The changelog for this version can be viewed <a href="https://github.com/gchq/CyberChef/blob/v<%= htmlWebpackPlugin.options.version %>/CHANGELOG.md">here</a></li>
|
<li>The changelog for this version can be viewed <a href="https://github.com/gchq/CyberChef/blob/v<%= htmlWebpackPlugin.options.latestReleaseVersion %>/CHANGELOG.md">here</a></li>
|
||||||
<li>© Crown Copyright 2016-<%= htmlWebpackPlugin.options.compileYear %></li>
|
<li>© Crown Copyright 2016-<%= htmlWebpackPlugin.options.compileYear %></li>
|
||||||
<li>Released under the Apache Licence, Version 2.0</li>
|
<li>Released under the Apache Licence, Version 2.0</li>
|
||||||
<li>SHA256 hash: DOWNLOAD_HASH_PLACEHOLDER</li>
|
<li>SHA256 hash: DOWNLOAD_HASH_PLACEHOLDER</li>
|
||||||
</ul>
|
</ul>
|
||||||
<a href="CyberChef_v<%= htmlWebpackPlugin.options.version %>.zip" download class="btn btn-outline-primary">Download ZIP file</a>
|
<a href="<%= htmlWebpackPlugin.options.downloadZipFilename %>" download class="btn btn-outline-primary">Download ZIP file</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Ok</button>
|
<button type="button" class="btn btn-primary" data-dismiss="modal">Ok</button>
|
||||||
|
|||||||
@ -17,8 +17,8 @@ import * as CanvasComponents from "../core/lib/CanvasComponents.mjs";
|
|||||||
|
|
||||||
// CyberChef
|
// CyberChef
|
||||||
import App from "./App.mjs";
|
import App from "./App.mjs";
|
||||||
import Categories from "../core/config/Categories.json" assert {type: "json"};
|
import Categories from "../core/config/Categories.json" with { type: "json" };
|
||||||
import OperationConfig from "../core/config/OperationConfig.json" assert {type: "json"};
|
import OperationConfig from "../core/config/OperationConfig.json" with { type: "json" };
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import sm from "sitemap";
|
import { SitemapStream, streamToPromise } from "sitemap";
|
||||||
import OperationConfig from "../../core/config/OperationConfig.json" assert { type: "json" };
|
import OperationConfig from "../../core/config/OperationConfig.json" with { type: "json" };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates an XML sitemap for all CyberChef operations and a number of recipes.
|
* Generates an XML sitemap for all CyberChef operations and a number of recipes.
|
||||||
@ -11,7 +11,7 @@ import OperationConfig from "../../core/config/OperationConfig.json" assert { ty
|
|||||||
|
|
||||||
const baseUrl = "https://gchq.github.io/CyberChef/";
|
const baseUrl = "https://gchq.github.io/CyberChef/";
|
||||||
|
|
||||||
const smStream = new sm.SitemapStream({});
|
const smStream = new SitemapStream({});
|
||||||
|
|
||||||
smStream.write({
|
smStream.write({
|
||||||
url: baseUrl,
|
url: baseUrl,
|
||||||
@ -28,6 +28,6 @@ for (const op in OperationConfig) {
|
|||||||
}
|
}
|
||||||
smStream.end();
|
smStream.end();
|
||||||
|
|
||||||
sm.streamToPromise(smStream).then(
|
streamToPromise(smStream).then(
|
||||||
(buffer) => console.log(buffer.toString()), // eslint-disable-line no-console
|
(buffer) => console.log(buffer.toString()), // eslint-disable-line no-console
|
||||||
);
|
);
|
||||||
|
|||||||
@ -28,17 +28,16 @@ class OperationsWaiter {
|
|||||||
this.removeIntent = false;
|
this.removeIntent = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for search events.
|
* Handler for search events.
|
||||||
* Finds operations which match the given search term and displays them under the search box.
|
* Finds operations which match the given search term and displays them under the search box.
|
||||||
*
|
*
|
||||||
* @param {event} e
|
* @param {KeyboardEvent | ClipboardEvent | Event} e
|
||||||
*/
|
*/
|
||||||
searchOperations(e) {
|
searchOperations(e) {
|
||||||
let ops, selected;
|
let ops, selected;
|
||||||
|
|
||||||
if (e.type === "search" || e.keyCode === 13) { // Search or Return
|
if ((e.type === "search" && e.target.value !== "") || e.keyCode === 13) { // Search (non-empty) or Return
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
ops = document.querySelectorAll("#search-results li");
|
ops = document.querySelectorAll("#search-results li");
|
||||||
if (ops.length) {
|
if (ops.length) {
|
||||||
@ -49,27 +48,43 @@ class OperationsWaiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the operation element with the correct attributes when selected
|
||||||
|
* @param {HTMLElement} element
|
||||||
|
*/
|
||||||
|
const _selectOperation = (element) => {
|
||||||
|
element.classList.add("selected-op");
|
||||||
|
element.scrollIntoView({block: "nearest"});
|
||||||
|
$(element).popover("show");
|
||||||
|
e.target.setAttribute("aria-activedescendant", element.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the operation element with the correct attributes when deselected
|
||||||
|
* @param {HTMLElement} element
|
||||||
|
*/
|
||||||
|
const _deselectOperation = (element) => {
|
||||||
|
element.classList.remove("selected-op");
|
||||||
|
$(element).popover("hide");
|
||||||
|
};
|
||||||
|
|
||||||
if (e.keyCode === 40) { // Down
|
if (e.keyCode === 40) { // Down
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
ops = document.querySelectorAll("#search-results li");
|
ops = document.querySelectorAll("#search-results li");
|
||||||
if (ops.length) {
|
if (ops.length) {
|
||||||
selected = this.getSelectedOp(ops);
|
selected = this.getSelectedOp(ops);
|
||||||
if (selected > -1) {
|
if (selected > -1) _deselectOperation(ops[selected]);
|
||||||
ops[selected].classList.remove("selected-op");
|
|
||||||
}
|
|
||||||
if (selected === ops.length-1) selected = -1;
|
if (selected === ops.length-1) selected = -1;
|
||||||
ops[selected+1].classList.add("selected-op");
|
_selectOperation(ops[selected+1]);
|
||||||
}
|
}
|
||||||
} else if (e.keyCode === 38) { // Up
|
} else if (e.keyCode === 38) { // Up
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
ops = document.querySelectorAll("#search-results li");
|
ops = document.querySelectorAll("#search-results li");
|
||||||
if (ops.length) {
|
if (ops.length) {
|
||||||
selected = this.getSelectedOp(ops);
|
selected = this.getSelectedOp(ops);
|
||||||
if (selected > -1) {
|
if (selected > -1) _deselectOperation(ops[selected]);
|
||||||
ops[selected].classList.remove("selected-op");
|
|
||||||
}
|
|
||||||
if (selected === 0) selected = ops.length;
|
if (selected === 0) selected = ops.length;
|
||||||
ops[selected-1].classList.add("selected-op");
|
_selectOperation(ops[selected-1]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const searchResultsEl = document.getElementById("search-results");
|
const searchResultsEl = document.getElementById("search-results");
|
||||||
@ -83,11 +98,13 @@ class OperationsWaiter {
|
|||||||
searchResultsEl.removeChild(searchResultsEl.firstChild);
|
searchResultsEl.removeChild(searchResultsEl.firstChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.querySelector("#search").removeAttribute("aria-activedescendant");
|
||||||
|
|
||||||
$("#categories .show").collapse("hide");
|
$("#categories .show").collapse("hide");
|
||||||
if (str) {
|
if (str) {
|
||||||
const matchedOps = this.filterOperations(str, true);
|
const matchedOps = this.filterOperations(str, true);
|
||||||
const matchedOpsHtml = matchedOps
|
const matchedOpsHtml = matchedOps
|
||||||
.map(v => v.toStubHtml())
|
.map((operation, idx) => operation.toStubHtml(false, `search-result-${idx}`))
|
||||||
.join("");
|
.join("");
|
||||||
|
|
||||||
searchResultsEl.innerHTML = matchedOpsHtml;
|
searchResultsEl.innerHTML = matchedOpsHtml;
|
||||||
@ -103,7 +120,7 @@ class OperationsWaiter {
|
|||||||
* @param {string} searchStr
|
* @param {string} searchStr
|
||||||
* @param {boolean} highlight - Whether or not to highlight the matching string in the operation
|
* @param {boolean} highlight - Whether or not to highlight the matching string in the operation
|
||||||
* name and description
|
* name and description
|
||||||
* @returns {string[]}
|
* @returns {HTMLOperation[]}
|
||||||
*/
|
*/
|
||||||
filterOperations(inStr, highlight) {
|
filterOperations(inStr, highlight) {
|
||||||
const matchedOps = [];
|
const matchedOps = [];
|
||||||
|
|||||||
@ -487,11 +487,19 @@ class RecipeWaiter {
|
|||||||
* @param {HTMLElement} op
|
* @param {HTMLElement} op
|
||||||
*/
|
*/
|
||||||
triggerArgEvents(op) {
|
triggerArgEvents(op) {
|
||||||
// Trigger populateOption and argSelector events
|
// Trigger argSelector events and populateOption events only where the target is empty.
|
||||||
|
// When loading a saved recipe, arguments are populated before this method is called, so
|
||||||
|
// re-triggering populateOption events would overwrite saved custom values with defaults.
|
||||||
|
const args = op.querySelectorAll(".arg");
|
||||||
const triggerableOptions = op.querySelectorAll(".populate-option, .arg-selector");
|
const triggerableOptions = op.querySelectorAll(".populate-option, .arg-selector");
|
||||||
const evt = new Event("change", {bubbles: true});
|
const evt = new Event("change", {bubbles: true});
|
||||||
|
|
||||||
if (triggerableOptions.length) {
|
if (triggerableOptions.length) {
|
||||||
for (const el of triggerableOptions) {
|
for (const el of triggerableOptions) {
|
||||||
|
if (el.classList.contains("populate-option")) {
|
||||||
|
const target = args[el.getAttribute("data-target")];
|
||||||
|
if (target && target.value !== "") continue;
|
||||||
|
}
|
||||||
el.dispatchEvent(evt);
|
el.dispatchEvent(evt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 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, "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, "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 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"]);
|
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, "AND", "test input", "4$04 $044", [{ "option": "Hex", "string": "34" }]);
|
||||||
testOp(browser, "Add line numbers", "test input", "1 test input");
|
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"], []]);
|
testOp(browser, ["From Hex", "Add Text To Image", "SHA2"], Images.PNG_HEX, "50cdf8ea483c55564a091650c2bccb4586f919b721e5fe9d6a61660505b4346d6ebdb2ef0cf075a7728cd84cb26ea3e477b5bd86a94a49a27d79423994afb60a", [[], ["Chef", "Center", "Middle", 0, 0, 16, "Roboto"], []]);
|
||||||
@ -64,7 +64,7 @@ module.exports = {
|
|||||||
testOp(browser, "BSON serialise", '{"a":"test"}', "\u0011\u0000\u0000\u0000\u0002a\u0000\u0005\u0000\u0000\u0000test\u0000\u0000");
|
testOp(browser, "BSON serialise", '{"a":"test"}', "\u0011\u0000\u0000\u0000\u0002a\u0000\u0005\u0000\u0000\u0000test\u0000\u0000");
|
||||||
// testOp(browser, "Bacon Cipher Decode", "test input", "test_output");
|
// testOp(browser, "Bacon Cipher Decode", "test input", "test_output");
|
||||||
// testOp(browser, "Bacon Cipher Encode", "test input", "test_output");
|
// testOp(browser, "Bacon Cipher Encode", "test input", "test_output");
|
||||||
testOp(browser, "Bcrypt", "test input", /^\$2a\$06\$.{53}$/, [6]);
|
testOp(browser, "Bcrypt", "test input", /^\$2b\$06\$.{53}$/, [6]);
|
||||||
testOp(browser, "Bcrypt compare", "test input", "Match: test input", ["$2a$05$FCfBSVX7OeRkK.9kQVFCiOYu9XtwtIbePqUiroD1lkASW9q5QClzG"]);
|
testOp(browser, "Bcrypt compare", "test input", "Match: test input", ["$2a$05$FCfBSVX7OeRkK.9kQVFCiOYu9XtwtIbePqUiroD1lkASW9q5QClzG"]);
|
||||||
testOp(browser, "Bcrypt parse", "$2a$05$kXWtAIGB/R8VEzInoM5ocOTBtyc0m2YTIwFiBU/0XoW032f9QrkWW", /Rounds: 5/);
|
testOp(browser, "Bcrypt parse", "$2a$05$kXWtAIGB/R8VEzInoM5ocOTBtyc0m2YTIwFiBU/0XoW032f9QrkWW", /Rounds: 5/);
|
||||||
testOp(browser, "Bifid Cipher Decode", "qblb tfovy", "test input", ["pass"]);
|
testOp(browser, "Bifid Cipher Decode", "qblb tfovy", "test input", ["pass"]);
|
||||||
@ -80,8 +80,8 @@ module.exports = {
|
|||||||
testOpHtml(browser, "Bombe", "XTSYN WAEUG EZALY NRQIM AMLZX MFUOD AWXLY LZCUZ QOQBQ JLCPK NDDRW F", "table tr:last-child td:first-child", "ECG", ["3-rotor", "LEYJVCNIXWPBQMDRTAKZGFUHOS", "BDFHJLCPRTXVZNYEIWGAKMUSQO<W", "AJDKSIRUXBLHWTMCQGZNPYFVOE<F", "ESOVPZJAYQUIRHXLNFTGKDCMWB<K", "AY BR CU DH EQ FS GL IP JX KN MO TZ VW", "HELLO CYBER CHEFU SER", 0, true]);
|
testOpHtml(browser, "Bombe", "XTSYN WAEUG EZALY NRQIM AMLZX MFUOD AWXLY LZCUZ QOQBQ JLCPK NDDRW F", "table tr:last-child td:first-child", "ECG", ["3-rotor", "LEYJVCNIXWPBQMDRTAKZGFUHOS", "BDFHJLCPRTXVZNYEIWGAKMUSQO<W", "AJDKSIRUXBLHWTMCQGZNPYFVOE<F", "ESOVPZJAYQUIRHXLNFTGKDCMWB<K", "AY BR CU DH EQ FS GL IP JX KN MO TZ VW", "HELLO CYBER CHEFU SER", 0, true]);
|
||||||
testOp(browser, ["Bzip2 Compress", "To Hex"], "test input", "42 5a 68 39 31 41 59 26 53 59 cf 96 82 1d 00 00 03 91 80 40 00 02 21 4e 00 20 00 21 90 c2 10 c0 88 33 92 8e df 17 72 45 38 50 90 cf 96 82 1d");
|
testOp(browser, ["Bzip2 Compress", "To Hex"], "test input", "42 5a 68 39 31 41 59 26 53 59 cf 96 82 1d 00 00 03 91 80 40 00 02 21 4e 00 20 00 21 90 c2 10 c0 88 33 92 8e df 17 72 45 38 50 90 cf 96 82 1d");
|
||||||
testOp(browser, ["From Hex", "Bzip2 Decompress"], "425a68393141592653597b0884b7000003038000008200ce00200021a647a4218013709517c5dc914e14241ec2212dc0", "test_output", [[], [true]]);
|
testOp(browser, ["From Hex", "Bzip2 Decompress"], "425a68393141592653597b0884b7000003038000008200ce00200021a647a4218013709517c5dc914e14241ec2212dc0", "test_output", [[], [true]]);
|
||||||
// testOp(browser, "CBOR Decode", "test input", "test output");
|
testOp(browser, ["From Hex", "CBOR Decode"], "f9 3e 00", "1.5");
|
||||||
// testOp(browser, "CBOR Encode", "test input", "test output");
|
testOp(browser, ["CBOR Encode", "To Hex"], "1.5", "f9 3e 00");
|
||||||
testOp(browser, "CRC Checksum", "test input", "77c7", ["CRC-16"]);
|
testOp(browser, "CRC Checksum", "test input", "77c7", ["CRC-16"]);
|
||||||
testOp(browser, "CRC Checksum", "test input", "29822bc8", ["CRC-32"]);
|
testOp(browser, "CRC Checksum", "test input", "29822bc8", ["CRC-32"]);
|
||||||
testOp(browser, "CRC Checksum", "test input", "9d", ["CRC-8"]);
|
testOp(browser, "CRC Checksum", "test input", "9d", ["CRC-8"]);
|
||||||
@ -278,11 +278,11 @@ module.exports = {
|
|||||||
testOpHtml(browser, "Parse UDP", "04 89 00 35 00 2c 01 01", "tr:last-child td:last-child", "0x0101");
|
testOpHtml(browser, "Parse UDP", "04 89 00 35 00 2c 01 01", "tr:last-child td:last-child", "0x0101");
|
||||||
// testOp(browser, "Parse UNIX file permissions", "test input", "test_output");
|
// testOp(browser, "Parse UNIX file permissions", "test input", "test_output");
|
||||||
// testOp(browser, "Parse URI", "test input", "test_output");
|
// testOp(browser, "Parse URI", "test input", "test_output");
|
||||||
// testOp(browser, "Parse User Agent", "test input", "test_output");
|
testOp(browser, "Parse User Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0 ", /Architecture: amd64/);
|
||||||
// testOp(browser, "Parse X.509 certificate", "test input", "test_output");
|
// testOp(browser, "Parse X.509 certificate", "test input", "test_output");
|
||||||
testOpFile(browser, "Play Media", "files/mp3example.mp3", "audio", "");
|
testOpFile(browser, "Play Media", "files/mp3example.mp3", "audio", "");
|
||||||
// testOp(browser, "Power Set", "test input", "test_output");
|
// testOp(browser, "Power Set", "test input", "test_output");
|
||||||
// testOp(browser, "Protobuf Decode", "test input", "test_output");
|
testOp(browser, ["From Hex", "Protobuf Decode"], "0d1c0000001203596f751a024d65202b2a0a0a066162633132331200", /"1": "abc123"/, [[], ["", false, false]]);
|
||||||
// testOp(browser, "Pseudo-Random Number Generator", "test input", "test_output");
|
// testOp(browser, "Pseudo-Random Number Generator", "test input", "test_output");
|
||||||
// testOp(browser, "RC2 Decrypt", "test input", "test_output");
|
// testOp(browser, "RC2 Decrypt", "test input", "test_output");
|
||||||
// testOp(browser, "RC2 Encrypt", "test input", "test_output");
|
// testOp(browser, "RC2 Encrypt", "test input", "test_output");
|
||||||
|
|||||||
48
tests/browser/03_recipe_load.js
Normal file
48
tests/browser/03_recipe_load.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* Regression tests for recipe loading behaviour.
|
||||||
|
*
|
||||||
|
* @author C85297 [95289555+C85297@users.noreply.github.com]
|
||||||
|
* @copyright Crown Copyright
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
const utils = require("./browserUtils.js");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
before: browser => {
|
||||||
|
browser
|
||||||
|
.resizeWindow(1280, 800)
|
||||||
|
.url(browser.launchUrl)
|
||||||
|
.useCss()
|
||||||
|
.waitForElementNotPresent("#preloader", 10000);
|
||||||
|
},
|
||||||
|
|
||||||
|
"Recipe load preserves populated arguments": browser => {
|
||||||
|
const inputFormat = "HH:mm:ss a MMM DD, YYYY ";
|
||||||
|
const input = "10:20:30 pm Sep 26, 2019 ";
|
||||||
|
|
||||||
|
utils.loadRecipe(
|
||||||
|
browser,
|
||||||
|
"Translate DateTime Format",
|
||||||
|
input,
|
||||||
|
[
|
||||||
|
"Standard date and time",
|
||||||
|
inputFormat,
|
||||||
|
"UTC",
|
||||||
|
"DD/MM/YYYY HH:mm:ss",
|
||||||
|
"UTC"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
browser.execute(() => {
|
||||||
|
return Array.from(document.querySelectorAll("#rec-list li.operation .arg"))
|
||||||
|
.map(arg => arg.value);
|
||||||
|
}, [], function({value}) {
|
||||||
|
browser.expect(value[1]).to.equal(inputFormat);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
after: browser => {
|
||||||
|
browser.end();
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -51,14 +51,17 @@ function setInput(browser, input, type=true) {
|
|||||||
*/
|
*/
|
||||||
function bake(browser) {
|
function bake(browser) {
|
||||||
browser
|
browser
|
||||||
|
// Let any pending debounced inputChange/stateChange (~20ms each) fire so the
|
||||||
|
// worker has the latest input buffer before we ask it to bake.
|
||||||
|
.pause(50)
|
||||||
// Ensure we're not currently busy
|
// Ensure we're not currently busy
|
||||||
.waitForElementNotVisible("#output-loader", 5000)
|
.waitForElementNotVisible("#output-loader", 10000)
|
||||||
.expect.element("#bake span").text.to.equal("BAKE!");
|
.expect.element("#bake span").text.to.equal("BAKE!");
|
||||||
|
|
||||||
browser
|
browser
|
||||||
.click("#bake")
|
.click("#bake")
|
||||||
.waitForElementNotVisible("#stale-indicator", 5000)
|
.waitForElementNotVisible("#stale-indicator", 10000)
|
||||||
.waitForElementNotVisible("#output-loader", 5000);
|
.waitForElementNotVisible("#output-loader", 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @function
|
/** @function
|
||||||
|
|||||||
31
tests/lib/wasmFetchPolyfill.mjs
Normal file
31
tests/lib/wasmFetchPolyfill.mjs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Polyfill for Node.js 22+ where globalThis.fetch is built-in but rejects
|
||||||
|
* bare filesystem paths. WASM libraries like argon2-browser call fetch() with
|
||||||
|
* an absolute path (e.g. "/path/to/argon2.wasm") expecting a browser-style
|
||||||
|
* fallback, but Node.js 22's fetch throws synchronously for non-URL strings.
|
||||||
|
*
|
||||||
|
* This wrapper intercepts such calls and serves the file via Node's fs module,
|
||||||
|
* returning a synthetic Response so the WASM module loads correctly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { readFile } from "fs/promises";
|
||||||
|
|
||||||
|
if (globalThis.fetch) {
|
||||||
|
const originalFetch = globalThis.fetch;
|
||||||
|
globalThis.fetch = async function patchedFetch(url, options) {
|
||||||
|
const urlStr = typeof url === "string" ?
|
||||||
|
url :
|
||||||
|
url instanceof URL ?
|
||||||
|
url.href :
|
||||||
|
String(url);
|
||||||
|
// Intercept bare filesystem paths (absolute POSIX or Windows)
|
||||||
|
if (urlStr.startsWith("/") || /^[A-Za-z]:[/\\]/.test(urlStr)) {
|
||||||
|
const buffer = await readFile(urlStr);
|
||||||
|
return new Response(buffer, {
|
||||||
|
status: 200,
|
||||||
|
headers: { "Content-Type": "application/wasm" },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return originalFetch(url, options);
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
const assert = require("assert");
|
const assert = require("assert");
|
||||||
|
|
||||||
require("cyberchef").then(chef => {
|
require("cyberchef").then(async chef => {
|
||||||
|
|
||||||
const d = chef.bake("Testing, 1 2 3", [
|
const d = await chef.bake("Testing, 1 2 3", [
|
||||||
chef.toHex,
|
chef.toHex,
|
||||||
chef.reverse,
|
chef.reverse,
|
||||||
{
|
{
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import assert from "assert";
|
|||||||
import chef from "cyberchef";
|
import chef from "cyberchef";
|
||||||
import { bake, toHex, reverse, unique, multiply } from "cyberchef";
|
import { bake, toHex, reverse, unique, multiply } from "cyberchef";
|
||||||
|
|
||||||
const a = bake("Testing, 1 2 3", [
|
const a = await bake("Testing, 1 2 3", [
|
||||||
toHex,
|
toHex,
|
||||||
reverse,
|
reverse,
|
||||||
{
|
{
|
||||||
@ -28,7 +28,7 @@ const a = bake("Testing, 1 2 3", [
|
|||||||
|
|
||||||
assert.equal(a.value, "630957449041920");
|
assert.equal(a.value, "630957449041920");
|
||||||
|
|
||||||
const b = chef.bake("Testing, 1 2 3", [
|
const b = await chef.bake("Testing, 1 2 3", [
|
||||||
chef.toHex,
|
chef.toHex,
|
||||||
chef.reverse,
|
chef.reverse,
|
||||||
{
|
{
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import {
|
|||||||
import TestRegister from "../lib/TestRegister.mjs";
|
import TestRegister from "../lib/TestRegister.mjs";
|
||||||
import "./tests/nodeApi.mjs";
|
import "./tests/nodeApi.mjs";
|
||||||
import "./tests/operations.mjs";
|
import "./tests/operations.mjs";
|
||||||
|
import "./tests/PGP.mjs";
|
||||||
import "./tests/File.mjs";
|
import "./tests/File.mjs";
|
||||||
import "./tests/Dish.mjs";
|
import "./tests/Dish.mjs";
|
||||||
import "./tests/NodeDish.mjs";
|
import "./tests/NodeDish.mjs";
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import TestRegister from "../../lib/TestRegister.mjs";
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
import Categories from "../../../src/core/config/Categories.json" assert {type: "json"};
|
import Categories from "../../../src/core/config/Categories.json" with { type: "json" };
|
||||||
import OperationConfig from "../../../src/core/config/OperationConfig.json" assert {type: "json"};
|
import OperationConfig from "../../../src/core/config/OperationConfig.json" with { type: "json" };
|
||||||
import it from "../assertionHandler.mjs";
|
import it from "../assertionHandler.mjs";
|
||||||
import assert from "assert";
|
import assert from "assert";
|
||||||
|
|
||||||
|
|||||||
69
tests/node/tests/PGP.mjs
Normal file
69
tests/node/tests/PGP.mjs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* PGP node tests.
|
||||||
|
*
|
||||||
|
* @author C85297 [95289555+C85297@users.noreply.github.com]
|
||||||
|
* @copyright Crown Copyright 2026
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import assert from "assert";
|
||||||
|
import kbpgp from "kbpgp";
|
||||||
|
import * as es6promisify from "es6-promisify";
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
import it from "../assertionHandler.mjs";
|
||||||
|
import GeneratePGPKeyPair from "../../../src/core/operations/GeneratePGPKeyPair.mjs";
|
||||||
|
|
||||||
|
const promisify = es6promisify.default ? es6promisify.default.promisify : es6promisify.promisify;
|
||||||
|
|
||||||
|
const PUBLIC_KEY_BLOCK = /-----BEGIN PGP PUBLIC KEY BLOCK-----[\s\S]*-----END PGP PUBLIC KEY BLOCK-----/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a PGP key pair and import the generated public key.
|
||||||
|
*
|
||||||
|
* @param {string} keyType
|
||||||
|
* @returns {Promise<Object>}
|
||||||
|
*/
|
||||||
|
async function generateAndImportPublicKey(keyType) {
|
||||||
|
const operation = new GeneratePGPKeyPair();
|
||||||
|
const generatedKeyPair = await operation.run("", [
|
||||||
|
keyType,
|
||||||
|
"",
|
||||||
|
"User",
|
||||||
|
"akb@notreal.gchq.gov.uk"
|
||||||
|
]);
|
||||||
|
|
||||||
|
const publicKey = generatedKeyPair.match(PUBLIC_KEY_BLOCK);
|
||||||
|
|
||||||
|
assert(publicKey, "Generated key pair should contain an ASCII-armoured public key");
|
||||||
|
|
||||||
|
return promisify(kbpgp.KeyManager.import_from_armored_pgp)({
|
||||||
|
armored: publicKey[0],
|
||||||
|
opts: {
|
||||||
|
"no_check_keys": true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
TestRegister.addApiTests([
|
||||||
|
it("Generate PGP Key Pair: ECC keys should include ECDSA signing and ECDH encryption subkeys", async () => {
|
||||||
|
const publicKey = await generateAndImportPublicKey("ECC-256");
|
||||||
|
const subkeyAlgorithms = publicKey.subkeys.map(subkey => subkey.key.type);
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
publicKey.primary.key.type,
|
||||||
|
kbpgp.const.openpgp.public_key_algorithms.ECDSA,
|
||||||
|
"Generated ECC PGP primary key should use ECDSA"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
subkeyAlgorithms.includes(kbpgp.const.openpgp.public_key_algorithms.ECDSA),
|
||||||
|
"Generated ECC PGP key should include an ECDSA signing subkey"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
subkeyAlgorithms.includes(kbpgp.const.openpgp.public_key_algorithms.ECDH),
|
||||||
|
"Generated ECC PGP key should include an ECDH encryption subkey"
|
||||||
|
);
|
||||||
|
})
|
||||||
|
]);
|
||||||
@ -170,77 +170,77 @@ TestRegister.addApiTests([
|
|||||||
assert(chef.bake);
|
assert(chef.bake);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should return NodeDish", () => {
|
it("chef.bake: should return NodeDish", async () => {
|
||||||
const result = chef.bake("input", "to base 64");
|
const result = await chef.bake("input", "to base 64");
|
||||||
assert(result instanceof NodeDish);
|
assert(result instanceof NodeDish);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should take an input and an op name and perform it", () => {
|
it("chef.bake: should take an input and an op name and perform it", async () => {
|
||||||
const result = chef.bake("some input", "to base 32");
|
const result = await chef.bake("some input", "to base 32");
|
||||||
assert.strictEqual(result.toString(), "ONXW2ZJANFXHA5LU");
|
assert.strictEqual(result.toString(), "ONXW2ZJANFXHA5LU");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should complain if recipe isnt a valid object", () => {
|
it("chef.bake: should complain if recipe isnt a valid object", async () => {
|
||||||
assert.throws(() => chef.bake("some input", 3264), {
|
await assert.rejects(() => chef.bake("some input", 3264), {
|
||||||
name: "TypeError",
|
name: "TypeError",
|
||||||
message: "Recipe can only contain function names or functions"
|
message: "Recipe can only contain function names or functions"
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: Should complain if string op is invalid", () => {
|
it("chef.bake: Should complain if string op is invalid", async () => {
|
||||||
assert.throws(() => chef.bake("some input", "not a valid operation"), {
|
await assert.rejects(() => chef.bake("some input", "not a valid operation"), {
|
||||||
name: "TypeError",
|
name: "TypeError",
|
||||||
message: "Couldn't find an operation with name 'not a valid operation'."
|
message: "Couldn't find an operation with name 'not a valid operation'."
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: Should take an input and an operation and perform it", () => {
|
it("chef.bake: Should take an input and an operation and perform it", async () => {
|
||||||
const result = chef.bake("https://google.com/search?q=help", chef.parseURI);
|
const result = await chef.bake("https://google.com/search?q=help", chef.parseURI);
|
||||||
assert.strictEqual(result.toString(), "Protocol:\thttps:\nHostname:\tgoogle.com\nPath name:\t/search\nArguments:\n\tq = help\n");
|
assert.strictEqual(result.toString(), "Protocol:\thttps:\nHostname:\tgoogle.com\nPath name:\t/search\nArguments:\n\tq = help\n");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: Should complain if an invalid operation is inputted", () => {
|
it("chef.bake: Should complain if an invalid operation is inputted", async () => {
|
||||||
assert.throws(() => chef.bake("https://google.com/search?q=help", () => {}), {
|
await assert.rejects(() => chef.bake("https://google.com/search?q=help", () => {}), {
|
||||||
name: "TypeError",
|
name: "TypeError",
|
||||||
message: "Inputted function not a Chef operation."
|
message: "Inputted function not a Chef operation."
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: accepts an array of operation names and performs them all in order", () => {
|
it("chef.bake: accepts an array of operation names and performs them all in order", async () => {
|
||||||
const result = chef.bake("https://google.com/search?q=that's a complicated question", ["URL encode", "URL decode", "Parse URI"]);
|
const result = await chef.bake("https://google.com/search?q=that's a complicated question", ["URL encode", "URL decode", "Parse URI"]);
|
||||||
assert.strictEqual(result.toString(), "Protocol:\thttps:\nHostname:\tgoogle.com\nPath name:\t/search\nArguments:\n\tq = that's a complicated question\n");
|
assert.strictEqual(result.toString(), "Protocol:\thttps:\nHostname:\tgoogle.com\nPath name:\t/search\nArguments:\n\tq = that's a complicated question\n");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: forgiving with operation names", () =>{
|
it("chef.bake: forgiving with operation names", async () =>{
|
||||||
const result = chef.bake("https://google.com/search?q=that's a complicated question", ["urlencode", "url decode", "parseURI"]);
|
const result = await chef.bake("https://google.com/search?q=that's a complicated question", ["urlencode", "url decode", "parseURI"]);
|
||||||
assert.strictEqual(result.toString(), "Protocol:\thttps:\nHostname:\tgoogle.com\nPath name:\t/search\nArguments:\n\tq = that's a complicated question\n");
|
assert.strictEqual(result.toString(), "Protocol:\thttps:\nHostname:\tgoogle.com\nPath name:\t/search\nArguments:\n\tq = that's a complicated question\n");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: forgiving with operation names", () =>{
|
it("chef.bake: forgiving with operation names", async () =>{
|
||||||
const result = chef.bake("hello", ["to base 64"]);
|
const result = await chef.bake("hello", ["to base 64"]);
|
||||||
assert.strictEqual(result.toString(), "aGVsbG8=");
|
assert.strictEqual(result.toString(), "aGVsbG8=");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: if recipe is empty array, return input as dish", () => {
|
it("chef.bake: if recipe is empty array, return input as dish", async () => {
|
||||||
const result = chef.bake("some input", []);
|
const result = await chef.bake("some input", []);
|
||||||
assert.strictEqual(result.toString(), "some input");
|
assert.strictEqual(result.toString(), "some input");
|
||||||
assert(result instanceof NodeDish, "Result is not instance of NodeDish");
|
assert(result instanceof NodeDish, "Result is not instance of NodeDish");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: accepts an array of operations as recipe", () => {
|
it("chef.bake: accepts an array of operations as recipe", async () => {
|
||||||
const result = chef.bake("https://google.com/search?q=that's a complicated question", [chef.URLEncode, chef.URLDecode, chef.parseURI]);
|
const result = await chef.bake("https://google.com/search?q=that's a complicated question", [chef.URLEncode, chef.URLDecode, chef.parseURI]);
|
||||||
assert.strictEqual(result.toString(), "Protocol:\thttps:\nHostname:\tgoogle.com\nPath name:\t/search\nArguments:\n\tq = that's a complicated question\n");
|
assert.strictEqual(result.toString(), "Protocol:\thttps:\nHostname:\tgoogle.com\nPath name:\t/search\nArguments:\n\tq = that's a complicated question\n");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("should complain if an invalid operation is inputted as part of array", () => {
|
it("should complain if an invalid operation is inputted as part of array", async () => {
|
||||||
assert.throws(() => chef.bake("something", [() => {}]), {
|
await assert.rejects(() => chef.bake("something", [() => {}]), {
|
||||||
name: "TypeError",
|
name: "TypeError",
|
||||||
message: "Inputted function not a Chef operation."
|
message: "Inputted function not a Chef operation."
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should take single JSON object describing op and args OBJ", () => {
|
it("chef.bake: should take single JSON object describing op and args OBJ", async () => {
|
||||||
const result = chef.bake("some input", {
|
const result = await chef.bake("some input", {
|
||||||
op: chef.toHex,
|
op: chef.toHex,
|
||||||
args: {
|
args: {
|
||||||
Delimiter: "Colon"
|
Delimiter: "Colon"
|
||||||
@ -249,23 +249,23 @@ TestRegister.addApiTests([
|
|||||||
assert.strictEqual(result.toString(), "73:6f:6d:65:20:69:6e:70:75:74");
|
assert.strictEqual(result.toString(), "73:6f:6d:65:20:69:6e:70:75:74");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should take single JSON object desribing op with optional args", () => {
|
it("chef.bake: should take single JSON object desribing op with optional args", async () => {
|
||||||
const result = chef.bake("some input", {
|
const result = await chef.bake("some input", {
|
||||||
op: chef.toHex,
|
op: chef.toHex,
|
||||||
});
|
});
|
||||||
assert.strictEqual(result.toString(), "73 6f 6d 65 20 69 6e 70 75 74");
|
assert.strictEqual(result.toString(), "73 6f 6d 65 20 69 6e 70 75 74");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should take single JSON object describing op and args ARRAY", () => {
|
it("chef.bake: should take single JSON object describing op and args ARRAY", async () => {
|
||||||
const result = chef.bake("some input", {
|
const result = await chef.bake("some input", {
|
||||||
op: chef.toHex,
|
op: chef.toHex,
|
||||||
args: ["Colon"]
|
args: ["Colon"]
|
||||||
});
|
});
|
||||||
assert.strictEqual(result.toString(), "73:6f:6d:65:20:69:6e:70:75:74");
|
assert.strictEqual(result.toString(), "73:6f:6d:65:20:69:6e:70:75:74");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should error if op in JSON is not chef op", () => {
|
it("chef.bake: should error if op in JSON is not chef op", async () => {
|
||||||
assert.throws(() => chef.bake("some input", {
|
await assert.rejects(() => chef.bake("some input", {
|
||||||
op: () => {},
|
op: () => {},
|
||||||
args: ["Colon"],
|
args: ["Colon"],
|
||||||
}), {
|
}), {
|
||||||
@ -274,8 +274,8 @@ TestRegister.addApiTests([
|
|||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should take multiple ops in JSON object form, some ops by string", () => {
|
it("chef.bake: should take multiple ops in JSON object form, some ops by string", async () => {
|
||||||
const result = chef.bake("some input", [
|
const result = await chef.bake("some input", [
|
||||||
{
|
{
|
||||||
op: chef.toHex,
|
op: chef.toHex,
|
||||||
args: ["Colon"]
|
args: ["Colon"]
|
||||||
@ -290,8 +290,8 @@ TestRegister.addApiTests([
|
|||||||
assert.strictEqual(result.toString(), "67;63;72;66;146;72;66;144;72;66;65;72;62;60;72;66;71;72;66;145;72;67;60;72;67;65;72;67;64");
|
assert.strictEqual(result.toString(), "67;63;72;66;146;72;66;144;72;66;65;72;62;60;72;66;71;72;66;145;72;67;60;72;67;65;72;67;64");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should take multiple ops in JSON object form, some without args", () => {
|
it("chef.bake: should take multiple ops in JSON object form, some without args", async () => {
|
||||||
const result = chef.bake("some input", [
|
const result = await chef.bake("some input", [
|
||||||
{
|
{
|
||||||
op: chef.toHex,
|
op: chef.toHex,
|
||||||
},
|
},
|
||||||
@ -305,8 +305,8 @@ TestRegister.addApiTests([
|
|||||||
assert.strictEqual(result.toString(), "67;63;40;66;146;40;66;144;40;66;65;40;62;60;40;66;71;40;66;145;40;67;60;40;67;65;40;67;64");
|
assert.strictEqual(result.toString(), "67;63;40;66;146;40;66;144;40;66;65;40;62;60;40;66;71;40;66;145;40;67;60;40;67;65;40;67;64");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should handle op with multiple args", () => {
|
it("chef.bake: should handle op with multiple args", async () => {
|
||||||
const result = chef.bake("some input", {
|
const result = await chef.bake("some input", {
|
||||||
op: "to morse code",
|
op: "to morse code",
|
||||||
args: {
|
args: {
|
||||||
formatOptions: "Dash/Dot",
|
formatOptions: "Dash/Dot",
|
||||||
@ -317,13 +317,13 @@ TestRegister.addApiTests([
|
|||||||
assert.strictEqual(result.toString(), "DotDotDot\\DashDashDash\\DashDash\\Dot,DotDot\\DashDot\\DotDashDashDot\\DotDotDash\\Dash");
|
assert.strictEqual(result.toString(), "DotDotDot\\DashDashDash\\DashDash\\Dot,DotDot\\DashDot\\DotDashDashDot\\DotDotDash\\Dash");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should take compact JSON format from Chef Website as recipe", () => {
|
it("chef.bake: should take compact JSON format from Chef Website as recipe", async () => {
|
||||||
const result = chef.bake("some input", [{"op": "To Morse Code", "args": ["Dash/Dot", "Backslash", "Comma"]}, {"op": "Hex to PEM", "args": ["SOMETHING"]}, {"op": "To Snake case", "args": [false]}]);
|
const result = await chef.bake("some input", [{"op": "To Morse Code", "args": ["Dash/Dot", "Backslash", "Comma"]}, {"op": "Hex to PEM", "args": ["SOMETHING"]}, {"op": "To Snake case", "args": [false]}]);
|
||||||
assert.strictEqual(result.toString(), "begin_something_anananaaaaak_da_aaak_da_aaaaananaaaaaaan_da_aaaaaaanan_da_aaak_end_something");
|
assert.strictEqual(result.toString(), "begin_something_anananaaaaak_da_aaak_da_aaaaananaaaaaaan_da_aaaaaaanan_da_aaak_end_something");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should accept Clean JSON format from Chef website as recipe", () => {
|
it("chef.bake: should accept Clean JSON format from Chef website as recipe", async () => {
|
||||||
const result = chef.bake("some input", [
|
const result = await chef.bake("some input", [
|
||||||
{ "op": "To Morse Code",
|
{ "op": "To Morse Code",
|
||||||
"args": ["Dash/Dot", "Backslash", "Comma"] },
|
"args": ["Dash/Dot", "Backslash", "Comma"] },
|
||||||
{ "op": "Hex to PEM",
|
{ "op": "Hex to PEM",
|
||||||
@ -334,8 +334,8 @@ TestRegister.addApiTests([
|
|||||||
assert.strictEqual(result.toString(), "begin_something_anananaaaaak_da_aaak_da_aaaaananaaaaaaan_da_aaaaaaanan_da_aaak_end_something");
|
assert.strictEqual(result.toString(), "begin_something_anananaaaaak_da_aaak_da_aaaaananaaaaaaan_da_aaaaaaanan_da_aaak_end_something");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should accept Clean JSON format from Chef website - args optional", () => {
|
it("chef.bake: should accept Clean JSON format from Chef website - args optional", async () => {
|
||||||
const result = chef.bake("some input", [
|
const result = await chef.bake("some input", [
|
||||||
{ "op": "To Morse Code" },
|
{ "op": "To Morse Code" },
|
||||||
{ "op": "Hex to PEM",
|
{ "op": "Hex to PEM",
|
||||||
"args": ["SOMETHING"] },
|
"args": ["SOMETHING"] },
|
||||||
@ -345,31 +345,28 @@ TestRegister.addApiTests([
|
|||||||
assert.strictEqual(result.toString(), "begin_something_aaaaaaaaaaaaaa_end_something");
|
assert.strictEqual(result.toString(), "begin_something_aaaaaaaaaaaaaa_end_something");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should accept operation names from Chef Website which contain forward slash", () => {
|
it("chef.bake: should accept operation names from Chef Website which contain forward slash", async () => {
|
||||||
const result = chef.bake("I'll have the test salmon", [
|
const result = await chef.bake("I'll have the test salmon", [
|
||||||
{ "op": "Find / Replace",
|
{ "op": "Find / Replace",
|
||||||
"args": [{ "option": "Regex", "string": "test" }, "good", true, false, true, false]}
|
"args": [{ "option": "Regex", "string": "test" }, "good", true, false, true, false]}
|
||||||
]);
|
]);
|
||||||
assert.strictEqual(result.toString(), "I'll have the good salmon");
|
assert.strictEqual(result.toString(), "I'll have the good salmon");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should accept operation names from Chef Website which contain a hyphen", () => {
|
it("chef.bake: should accept operation names from Chef Website which contain a hyphen", async () => {
|
||||||
const result = chef.bake("I'll have the test salmon", [
|
const result = await chef.bake("I'll have the test salmon", [
|
||||||
{ "op": "Adler-32 Checksum",
|
{ "op": "Adler-32 Checksum",
|
||||||
"args": [] }
|
"args": [] }
|
||||||
]);
|
]);
|
||||||
assert.strictEqual(result.toString(), "6e4208f8");
|
assert.strictEqual(result.toString(), "6e4208f8");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: should accept operation names from Chef Website which contain a period", () => {
|
it("chef.bake: should accept operation names from Chef Website which contain a period", async () => {
|
||||||
const result = chef.bake("30 13 02 01 05 16 0e 41 6e 79 62 6f 64 79 20 74 68 65 72 65 3f", [
|
const result = await chef.bake("30 13 02 01 05 16 0e 41 6e 79 62 6f 64 79 20 74 68 65 72 65 3f", [
|
||||||
{ "op": "Parse ASN.1 hex string",
|
{ "op": "Parse ASN.1 hex string",
|
||||||
"args": [0, 32] }
|
"args": [0, 32] }
|
||||||
]);
|
]);
|
||||||
assert.strictEqual(result.toString(), `SEQUENCE
|
assert.strictEqual(result.toString(), `SEQUENCE\n INTEGER 05\n IA5String 'Anybody there?'\n`);
|
||||||
INTEGER 05
|
|
||||||
IA5String 'Anybody there?'
|
|
||||||
`);
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("Excluded operations: throw a sensible error when you try and call one", () => {
|
it("Excluded operations: throw a sensible error when you try and call one", () => {
|
||||||
@ -381,16 +378,16 @@ TestRegister.addApiTests([
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("chef.bake: cannot accept flowControl operations in recipe", () => {
|
it("chef.bake: cannot accept flowControl operations in recipe", async () => {
|
||||||
assert.throws(() => chef.bake("some input", "magic"), {
|
await assert.rejects(() => chef.bake("some input", "magic"), {
|
||||||
name: "TypeError",
|
name: "TypeError",
|
||||||
message: "flowControl operations like Magic are not currently allowed in recipes for chef.bake in the Node API"
|
message: "flowControl operations like Magic are not currently allowed in recipes for chef.bake in the Node API"
|
||||||
});
|
});
|
||||||
assert.throws(() => chef.bake("some input", magic), {
|
await assert.rejects(() => chef.bake("some input", magic), {
|
||||||
name: "TypeError",
|
name: "TypeError",
|
||||||
message: "flowControl operations like Magic are not currently allowed in recipes for chef.bake in the Node API"
|
message: "flowControl operations like Magic are not currently allowed in recipes for chef.bake in the Node API"
|
||||||
});
|
});
|
||||||
assert.throws(() => chef.bake("some input", ["to base 64", "magic"]), {
|
await assert.rejects(() => chef.bake("some input", ["to base 64", "magic"]), {
|
||||||
name: "TypeError",
|
name: "TypeError",
|
||||||
message: "flowControl operations like Magic are not currently allowed in recipes for chef.bake in the Node API"
|
message: "flowControl operations like Magic are not currently allowed in recipes for chef.bake in the Node API"
|
||||||
});
|
});
|
||||||
|
|||||||
@ -79,7 +79,46 @@ TestRegister.addApiTests([
|
|||||||
string: "some iv some iv1",
|
string: "some iv some iv1",
|
||||||
option: "utf8",
|
option: "utf8",
|
||||||
},
|
},
|
||||||
|
ivLength: 16,
|
||||||
mode: "OFB",
|
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?");
|
assert.equal(result.toString(), "a slightly longer sampleinput?");
|
||||||
}),
|
}),
|
||||||
@ -136,8 +175,8 @@ Tiger-128`;
|
|||||||
it("Bcrypt", async () => {
|
it("Bcrypt", async () => {
|
||||||
const result = await chef.bcrypt("Put a Sock In It");
|
const result = await chef.bcrypt("Put a Sock In It");
|
||||||
const strResult = result.toString();
|
const strResult = result.toString();
|
||||||
assert.equal(strResult.length, 60);
|
assert.match(strResult, /^\$2b\$10\$[./A-Za-z0-9]{53}$/);
|
||||||
assert.equal(strResult.slice(0, 7), "$2a$10$");
|
assert.equal(strResult.split("$").length, 4);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("bcryptCompare", async() => {
|
it("bcryptCompare", async() => {
|
||||||
@ -589,8 +628,7 @@ Password: 282760`;
|
|||||||
...[1, 3, 4, 5, 6, 7].map(version => it(`Analyze UUID v${version}`, () => {
|
...[1, 3, 4, 5, 6, 7].map(version => it(`Analyze UUID v${version}`, () => {
|
||||||
const uuid = chef.generateUUID("", { "version": `v${version}` }).toString();
|
const uuid = chef.generateUUID("", { "version": `v${version}` }).toString();
|
||||||
const result = chef.analyseUUID(uuid).toString();
|
const result = chef.analyseUUID(uuid).toString();
|
||||||
const expected = `UUID version: ${version}`;
|
assert.ok(result.startsWith(`Version:\n${version}\n`), `Expected output to start with "Version:\\n${version}\\n", got: ${result}`);
|
||||||
assert.strictEqual(result, expected);
|
|
||||||
})),
|
})),
|
||||||
|
|
||||||
it("Generate UUID using defaults", () => {
|
it("Generate UUID using defaults", () => {
|
||||||
@ -598,7 +636,7 @@ Password: 282760`;
|
|||||||
assert.ok(uuid);
|
assert.ok(uuid);
|
||||||
|
|
||||||
const analysis = chef.analyseUUID(uuid).toString();
|
const analysis = chef.analyseUUID(uuid).toString();
|
||||||
assert.strictEqual(analysis, "UUID version: 4");
|
assert.ok(analysis.startsWith("Version:\n4\n"), `Expected output to start with "Version:\\n4\\n", got: ${analysis}`);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("Gzip, Gunzip", () => {
|
it("Gzip, Gunzip", () => {
|
||||||
|
|||||||
@ -1,207 +0,0 @@
|
|||||||
/* eslint no-console: 0 */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test Runner
|
|
||||||
*
|
|
||||||
* For running the tests in the test register.
|
|
||||||
*
|
|
||||||
* @author tlwr [toby@toby.codes]
|
|
||||||
* @author n1474335 [n1474335@gmail.com]
|
|
||||||
* @copyright Crown Copyright 2017
|
|
||||||
* @license Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { setLongTestFailure, logTestReport } from "../lib/utils.mjs";
|
|
||||||
|
|
||||||
import TestRegister from "../lib/TestRegister.mjs";
|
|
||||||
import "./tests/A1Z26CipherDecode.mjs";
|
|
||||||
import "./tests/AESKeyWrap.mjs";
|
|
||||||
import "./tests/AlternatingCaps.mjs";
|
|
||||||
import "./tests/AvroToJSON.mjs";
|
|
||||||
import "./tests/BaconCipher.mjs";
|
|
||||||
import "./tests/Base32.mjs";
|
|
||||||
import "./tests/Base45.mjs";
|
|
||||||
import "./tests/Base58.mjs";
|
|
||||||
import "./tests/Base62.mjs";
|
|
||||||
import "./tests/Base64.mjs";
|
|
||||||
import "./tests/Base85.mjs";
|
|
||||||
import "./tests/Base92.mjs";
|
|
||||||
import "./tests/BCD.mjs";
|
|
||||||
import "./tests/Bech32.mjs";
|
|
||||||
import "./tests/BitwiseOp.mjs";
|
|
||||||
import "./tests/BLAKE2b.mjs";
|
|
||||||
import "./tests/BLAKE2s.mjs";
|
|
||||||
import "./tests/BLAKE3.mjs";
|
|
||||||
import "./tests/Bombe.mjs";
|
|
||||||
import "./tests/BSON.mjs";
|
|
||||||
import "./tests/ByteRepr.mjs";
|
|
||||||
import "./tests/CaesarBoxCipher.mjs";
|
|
||||||
import "./tests/CaretMdecode.mjs";
|
|
||||||
import "./tests/CartesianProduct.mjs";
|
|
||||||
import "./tests/CBORDecode.mjs";
|
|
||||||
import "./tests/CBOREncode.mjs";
|
|
||||||
import "./tests/CetaceanCipherDecode.mjs";
|
|
||||||
import "./tests/CetaceanCipherEncode.mjs";
|
|
||||||
import "./tests/ChaCha.mjs";
|
|
||||||
import "./tests/ChangeIPFormat.mjs";
|
|
||||||
import "./tests/CharEnc.mjs";
|
|
||||||
import "./tests/Charts.mjs";
|
|
||||||
import "./tests/Ciphers.mjs";
|
|
||||||
import "./tests/CipherSaber2.mjs";
|
|
||||||
import "./tests/CMAC.mjs";
|
|
||||||
import "./tests/Code.mjs";
|
|
||||||
import "./tests/Colossus.mjs";
|
|
||||||
import "./tests/Comment.mjs";
|
|
||||||
import "./tests/Compress.mjs";
|
|
||||||
import "./tests/ConditionalJump.mjs";
|
|
||||||
import "./tests/ConvertCoordinateFormat.mjs";
|
|
||||||
import "./tests/ConvertLeetSpeak.mjs";
|
|
||||||
import "./tests/ConvertToNATOAlphabet.mjs";
|
|
||||||
import "./tests/CRCChecksum.mjs";
|
|
||||||
import "./tests/Crypt.mjs";
|
|
||||||
import "./tests/CSV.mjs";
|
|
||||||
import "./tests/DateTime.mjs";
|
|
||||||
import "./tests/DefangIP.mjs";
|
|
||||||
import "./tests/DisassembleARM.mjs";
|
|
||||||
import "./tests/DropNthBytes.mjs";
|
|
||||||
import "./tests/ECDSA.mjs";
|
|
||||||
import "./tests/ELFInfo.mjs";
|
|
||||||
import "./tests/Enigma.mjs";
|
|
||||||
import "./tests/ExtractAudioMetadata.mjs";
|
|
||||||
import "./tests/ExtractEmailAddresses.mjs";
|
|
||||||
import "./tests/ExtractHashes.mjs";
|
|
||||||
import "./tests/ExtractIPAddresses.mjs";
|
|
||||||
import "./tests/Float.mjs";
|
|
||||||
import "./tests/FileTree.mjs";
|
|
||||||
import "./tests/FletcherChecksum.mjs";
|
|
||||||
import "./tests/Fork.mjs";
|
|
||||||
import "./tests/FromDecimal.mjs";
|
|
||||||
import "./tests/GenerateAllChecksums.mjs";
|
|
||||||
import "./tests/GenerateAllHashes.mjs";
|
|
||||||
import "./tests/GenerateDeBruijnSequence.mjs";
|
|
||||||
import "./tests/GenerateQRCode.mjs";
|
|
||||||
import "./tests/GetAllCasings.mjs";
|
|
||||||
import "./tests/GOST.mjs";
|
|
||||||
import "./tests/Gunzip.mjs";
|
|
||||||
import "./tests/Gzip.mjs";
|
|
||||||
import "./tests/Hash.mjs";
|
|
||||||
import "./tests/HASSH.mjs";
|
|
||||||
import "./tests/HaversineDistance.mjs";
|
|
||||||
import "./tests/Hex.mjs";
|
|
||||||
import "./tests/Hexdump.mjs";
|
|
||||||
import "./tests/HKDF.mjs";
|
|
||||||
import "./tests/Image.mjs";
|
|
||||||
import "./tests/IndexOfCoincidence.mjs";
|
|
||||||
import "./tests/JA3Fingerprint.mjs";
|
|
||||||
import "./tests/JA4.mjs";
|
|
||||||
import "./tests/JA3SFingerprint.mjs";
|
|
||||||
import "./tests/Jsonata.mjs";
|
|
||||||
import "./tests/JSONBeautify.mjs";
|
|
||||||
import "./tests/JSONMinify.mjs";
|
|
||||||
import "./tests/JSONtoCSV.mjs";
|
|
||||||
import "./tests/Jump.mjs";
|
|
||||||
import "./tests/JWK.mjs";
|
|
||||||
import "./tests/JWTDecode.mjs";
|
|
||||||
import "./tests/JWTSign.mjs";
|
|
||||||
import "./tests/JWTVerify.mjs";
|
|
||||||
import "./tests/LevenshteinDistance.mjs";
|
|
||||||
import "./tests/Lorenz.mjs";
|
|
||||||
import "./tests/LS47.mjs";
|
|
||||||
import "./tests/LuhnChecksum.mjs";
|
|
||||||
import "./tests/LZNT1Decompress.mjs";
|
|
||||||
import "./tests/LZString.mjs";
|
|
||||||
import "./tests/Magic.mjs";
|
|
||||||
import "./tests/Media.mjs";
|
|
||||||
import "./tests/MIMEDecoding.mjs";
|
|
||||||
import "./tests/Modhex.mjs";
|
|
||||||
import "./tests/MorseCode.mjs";
|
|
||||||
import "./tests/MS.mjs";
|
|
||||||
import "./tests/MultipleBombe.mjs";
|
|
||||||
import "./tests/MurmurHash3.mjs";
|
|
||||||
import "./tests/NetBIOS.mjs";
|
|
||||||
import "./tests/NormaliseUnicode.mjs";
|
|
||||||
import "./tests/NTLM.mjs";
|
|
||||||
import "./tests/OTP.mjs";
|
|
||||||
import "./tests/ParseEthernetFrame.mjs";
|
|
||||||
import "./tests/ParseIPRange.mjs";
|
|
||||||
import "./tests/ParseObjectIDTimestamp.mjs";
|
|
||||||
import "./tests/ParseQRCode.mjs";
|
|
||||||
import "./tests/ParseSSHHostKey.mjs";
|
|
||||||
import "./tests/ParseTCP.mjs";
|
|
||||||
import "./tests/ParseTLSRecord.mjs";
|
|
||||||
import "./tests/ParseTLV.mjs";
|
|
||||||
import "./tests/ParseUDP.mjs";
|
|
||||||
import "./tests/PEMtoHex.mjs";
|
|
||||||
import "./tests/PGP.mjs";
|
|
||||||
import "./tests/PHP.mjs";
|
|
||||||
import "./tests/PHPSerialize.mjs";
|
|
||||||
import "./tests/PowerSet.mjs";
|
|
||||||
import "./tests/Protobuf.mjs";
|
|
||||||
import "./tests/PubKeyFromCert.mjs";
|
|
||||||
import "./tests/PubKeyFromPrivKey.mjs";
|
|
||||||
import "./tests/Rabbit.mjs";
|
|
||||||
import "./tests/RAKE.mjs";
|
|
||||||
import "./tests/Regex.mjs";
|
|
||||||
import "./tests/Register.mjs";
|
|
||||||
import "./tests/RisonEncodeDecode.mjs";
|
|
||||||
import "./tests/Rotate.mjs";
|
|
||||||
import "./tests/RSA.mjs";
|
|
||||||
import "./tests/Salsa20.mjs";
|
|
||||||
import "./tests/XSalsa20.mjs";
|
|
||||||
import "./tests/SeqUtils.mjs";
|
|
||||||
import "./tests/SetDifference.mjs";
|
|
||||||
import "./tests/SetIntersection.mjs";
|
|
||||||
import "./tests/SetUnion.mjs";
|
|
||||||
import "./tests/Shuffle.mjs";
|
|
||||||
import "./tests/SIGABA.mjs";
|
|
||||||
import "./tests/SM2.mjs";
|
|
||||||
import "./tests/SM4.mjs";
|
|
||||||
import "./tests/RC6.mjs";
|
|
||||||
// import "./tests/SplitColourChannels.mjs"; // Cannot test operations that use the File type yet
|
|
||||||
import "./tests/SQLBeautify.mjs";
|
|
||||||
import "./tests/StrUtils.mjs";
|
|
||||||
import "./tests/StripIPv4Header.mjs";
|
|
||||||
import "./tests/StripTCPHeader.mjs";
|
|
||||||
import "./tests/StripUDPHeader.mjs";
|
|
||||||
import "./tests/Subsection.mjs";
|
|
||||||
import "./tests/SwapCase.mjs";
|
|
||||||
import "./tests/SymmetricDifference.mjs";
|
|
||||||
import "./tests/TakeNthBytes.mjs";
|
|
||||||
import "./tests/Template.mjs";
|
|
||||||
import "./tests/TextEncodingBruteForce.mjs";
|
|
||||||
import "./tests/TextIntegerConverter.mjs";
|
|
||||||
import "./tests/ToFromInsensitiveRegex.mjs";
|
|
||||||
import "./tests/TranslateDateTimeFormat.mjs";
|
|
||||||
import "./tests/Typex.mjs";
|
|
||||||
import "./tests/UnescapeString.mjs";
|
|
||||||
import "./tests/Unicode.mjs";
|
|
||||||
import "./tests/URLEncodeDecode.mjs";
|
|
||||||
import "./tests/RSA.mjs";
|
|
||||||
import "./tests/CBOREncode.mjs";
|
|
||||||
import "./tests/CBORDecode.mjs";
|
|
||||||
import "./tests/JA3Fingerprint.mjs";
|
|
||||||
import "./tests/JA3SFingerprint.mjs";
|
|
||||||
import "./tests/HASSH.mjs";
|
|
||||||
import "./tests/JSONtoYAML.mjs";
|
|
||||||
|
|
||||||
// Cannot test operations that use the File type yet
|
|
||||||
// import "./tests/SplitColourChannels.mjs";
|
|
||||||
import "./tests/YARA.mjs";
|
|
||||||
import "./tests/ParseCSR.mjs";
|
|
||||||
import "./tests/XXTEA.mjs";
|
|
||||||
|
|
||||||
const testStatus = {
|
|
||||||
allTestsPassing: true,
|
|
||||||
counts: {
|
|
||||||
total: 0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
setLongTestFailure();
|
|
||||||
|
|
||||||
const logOpsTestReport = logTestReport.bind(null, testStatus);
|
|
||||||
|
|
||||||
(async function () {
|
|
||||||
const results = await TestRegister.runTests();
|
|
||||||
logOpsTestReport(results);
|
|
||||||
})();
|
|
||||||
66
tests/operations/tests/AnalyseUUID.mjs
Normal file
66
tests/operations/tests/AnalyseUUID.mjs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* Analyse UUID tests
|
||||||
|
*
|
||||||
|
* @author ko80240 [csk.dev@proton.me]
|
||||||
|
* @copyright Crown Copyright 2023
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
"name": "Analyse UUID: v1 UUID extracts timestamp, clock, and node",
|
||||||
|
"input": "cefa1760-28ee-11f1-9f95-1fb76af3e239",
|
||||||
|
"expectedOutput": "Version:\n1\n\nTimestamp:\n1774514156502\n\nTimestamp (ISO):\n2026-03-26T08:35:56.502Z\n\nNode:\n1F:B7:6A:F3:E2:39\n\nClock:\n8085\n\nUUID Integer:\n275119515460318071558429785403790975545",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "Analyse UUID",
|
||||||
|
"args": [true]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Analyse UUID: v7 UUID extracts timestamp, randA, and randB",
|
||||||
|
"input": "019d294a-af64-7728-9524-26da08f50708",
|
||||||
|
"expectedOutput": "Version:\n7\n\nTimestamp:\n1774514253668\n\nTimestamp (ISO):\n2026-03-26T08:37:33.668Z\n\nRand A:\n1832\n\nRand B:\n952426DA08F50708\n\nUUID Integer:\n2145256098533991595556290452700595976",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "Analyse UUID",
|
||||||
|
"args": [true]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Analyse UUID: v4 UUID should show no metadata - not possible",
|
||||||
|
"input": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
||||||
|
"expectedOutput": "Version:\n4\n\nNo metadata available. Only versions 1, 6, 7 are supported.\n\nUUID Integer:\n324969006592305634633390616021200786553",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "Analyse UUID",
|
||||||
|
"args": [true]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Analyse UUID: if the 'Include Metadata' option is false it should return not metadata",
|
||||||
|
"input": "cefa1760-28ee-11f1-9f95-1fb76af3e239",
|
||||||
|
"expectedOutput": "Version:\n1\n\nUUID Integer:\n275119515460318071558429785403790975545",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "Analyse UUID",
|
||||||
|
"args": [false]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Analyse UUID: invalid UUID should return error message",
|
||||||
|
"input": "not-a-uuid",
|
||||||
|
"expectedOutput": "Invalid UUID",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "Analyse UUID",
|
||||||
|
"args": [true]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]);
|
||||||
@ -51,5 +51,23 @@ TestRegister.addTests([
|
|||||||
{ "op": "BLAKE3",
|
{ "op": "BLAKE3",
|
||||||
"args": [8, "ThiskeyisexactlythirtytwoByteslo"] }
|
"args": [8, "ThiskeyisexactlythirtytwoByteslo"] }
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "BLAKE3: 16390 - test",
|
||||||
|
input: "test",
|
||||||
|
expectedMatch: /4878.{32760}555fe06b242738d5/,
|
||||||
|
recipeConfig: [
|
||||||
|
{ "op": "BLAKE3",
|
||||||
|
"args": [16390, ""] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "BLAKE3: 16390 - key test",
|
||||||
|
input: "test",
|
||||||
|
expectedMatch: /a8d0.{32760}19ccd9b9726b46ae/,
|
||||||
|
recipeConfig: [
|
||||||
|
{ "op": "BLAKE3",
|
||||||
|
"args": [16390, "ThiskeyisexactlythirtytwoBytesLo"] }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|||||||
@ -116,4 +116,15 @@ TestRegister.addTests([
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Show Base64 offsets: escapes static output",
|
||||||
|
input: "\x00\x10\x83\x10\x51\x87",
|
||||||
|
expectedOutput: "<script>\n<AQmsBRk66\n<ia1AEIM6",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Show Base64 offsets",
|
||||||
|
args: ["<script>ale(1)/.ABCDEFGHIJKLMNOPQRSTUVWXYZbdfghjkmnoquvwxyz023456", false, "Raw"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||
@ -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",
|
name: "Generate Base64 Windows PowerShell",
|
||||||
input: "ZABpAHIAIAAiAGMAOgBcAHAAcgBvAGcAcgBhAG0AIABmAGkAbABlAHMAIgAgAA==",
|
input: "ZABpAHIAIAAiAGMAOgBcAHAAcgBvAGcAcgBhAG0AIABmAGkAbABlAHMAIgAgAA==",
|
||||||
|
|||||||
@ -41,6 +41,17 @@ TestRegister.addTests([
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Series chart escapes x-axis values in serialized SVG",
|
||||||
|
input: `s,x"><script>globalThis.seriesChartInjected=1</script><g a=",1`,
|
||||||
|
unexpectedMatch: /<script>|__data__=/,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Series chart",
|
||||||
|
"args": ["Line feed", "Comma", "", 1, "red"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Heatmap chart",
|
name: "Heatmap chart",
|
||||||
input: "100 100\n200 200\n300 300\n400 400\n500 500",
|
input: "100 100\n200 200\n300 300\n400 400\n500 500",
|
||||||
|
|||||||
@ -74,7 +74,8 @@ The following algorithms will be used based on the size of the key:
|
|||||||
{"option": "Hex", "string": ""},
|
{"option": "Hex", "string": ""},
|
||||||
{"option": "Hex", "string": ""},
|
{"option": "Hex", "string": ""},
|
||||||
"CBC", "Raw", "Hex",
|
"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": "00112233445566778899aabbccddeeff"},
|
||||||
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
"CBC", "Raw", "Hex",
|
"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": "00112233445566778899aabbccddeeff"},
|
||||||
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
"CTR", "Raw", "Hex",
|
"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"},
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
"CBC", "Raw", "Hex",
|
"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"},
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
"CFB", "Raw", "Hex",
|
"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"},
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
"OFB", "Raw", "Hex",
|
"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"},
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
"CTR", "Raw", "Hex",
|
"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": "00112233445566778899aabbccddeeff"},
|
||||||
{"option": "Hex", "string": ""},
|
{"option": "Hex", "string": ""},
|
||||||
"ECB", "Raw", "Hex",
|
"ECB", "Raw", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -204,7 +212,8 @@ Tag: 16a3e732a605cc9ca29108f742ca0743`,
|
|||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
{"option": "Hex", "string": ""},
|
{"option": "Hex", "string": ""},
|
||||||
"GCM", "Raw", "Hex",
|
"GCM", "Raw", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -222,7 +231,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`,
|
|||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
{"option": "Hex", "string": "ffeeddccbbaa99887766554433221100"},
|
{"option": "Hex", "string": "ffeeddccbbaa99887766554433221100"},
|
||||||
"GCM", "Raw", "Hex",
|
"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": "51e201d463698ef5f717f71f5b4712af"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"CBC", "Hex", "Hex",
|
"CBC", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -254,7 +265,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`,
|
|||||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"CFB", "Hex", "Hex",
|
"CFB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -270,7 +282,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`,
|
|||||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"OFB", "Hex", "Hex",
|
"OFB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -286,7 +299,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`,
|
|||||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"CTR", "Hex", "Hex",
|
"CTR", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -304,7 +318,8 @@ Tag: 70fad2ca19412c20f40fd06918736e56`,
|
|||||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"GCM", "Hex", "Hex",
|
"GCM", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -322,7 +337,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`,
|
|||||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"GCM", "Hex", "Hex",
|
"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": "51e201d463698ef5f717f71f5b4712af"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"ECB", "Hex", "Hex",
|
"ECB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -354,7 +371,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`,
|
|||||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"CBC", "Hex", "Hex",
|
"CBC", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -370,7 +388,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`,
|
|||||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"CFB", "Hex", "Hex",
|
"CFB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -386,7 +405,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`,
|
|||||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"OFB", "Hex", "Hex",
|
"OFB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -402,7 +422,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`,
|
|||||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"CTR", "Hex", "Hex",
|
"CTR", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -420,7 +441,8 @@ Tag: 86db597d5302595223cadbd990f1309b`,
|
|||||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"GCM", "Hex", "Hex",
|
"GCM", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -438,7 +460,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`,
|
|||||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"GCM", "Hex", "Hex",
|
"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": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"ECB", "Hex", "Hex",
|
"ECB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -470,7 +494,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`,
|
|||||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"CBC", "Hex", "Hex",
|
"CBC", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -486,7 +511,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`,
|
|||||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"CFB", "Hex", "Hex",
|
"CFB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -502,7 +528,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`,
|
|||||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"OFB", "Hex", "Hex",
|
"OFB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -518,7 +545,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`,
|
|||||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"CTR", "Hex", "Hex",
|
"CTR", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -536,7 +564,8 @@ Tag: 821b1e5f32dad052e502775a523d957a`,
|
|||||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"GCM", "Hex", "Hex",
|
"GCM", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""}
|
{"option": "Hex", "string": ""},
|
||||||
|
"Off"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -554,7 +583,8 @@ Tag: a8f04c4d93bbef82bef61a103371aef9`,
|
|||||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"GCM", "Hex", "Hex",
|
"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": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
"ECB", "Hex", "Hex",
|
"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": ""},
|
{"option": "Hex", "string": ""},
|
||||||
{"option": "Hex", "string": ""},
|
{"option": "Hex", "string": ""},
|
||||||
|
16,
|
||||||
"CBC", "Hex", "Raw",
|
"CBC", "Hex", "Raw",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
16,
|
||||||
"CBC", "Hex", "Raw",
|
"CBC", "Hex", "Raw",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
16,
|
||||||
"CTR", "Hex", "Raw",
|
"CTR", "Hex", "Raw",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
|
16,
|
||||||
"CBC", "Hex", "Raw",
|
"CBC", "Hex", "Raw",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
|
16,
|
||||||
"CFB", "Hex", "Raw",
|
"CFB", "Hex", "Raw",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
|
16,
|
||||||
"OFB", "Hex", "Raw",
|
"OFB", "Hex", "Raw",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
|
16,
|
||||||
"CTR", "Hex", "Raw",
|
"CTR", "Hex", "Raw",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
{"option": "Hex", "string": ""},
|
{"option": "Hex", "string": ""},
|
||||||
|
16,
|
||||||
"ECB", "Hex", "Raw",
|
"ECB", "Hex", "Raw",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
{"option": "Hex", "string": ""},
|
{"option": "Hex", "string": ""},
|
||||||
|
16,
|
||||||
"GCM", "Hex", "Raw",
|
"GCM", "Hex", "Raw",
|
||||||
{"option": "Hex", "string": "16a3e732a605cc9ca29108f742ca0743"},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||||
{"option": "Hex", "string": "ffeeddccbbaa99887766554433221100"},
|
{"option": "Hex", "string": "ffeeddccbbaa99887766554433221100"},
|
||||||
|
16,
|
||||||
"GCM", "Hex", "Raw",
|
"GCM", "Hex", "Raw",
|
||||||
{"option": "Hex", "string": "3b5378917f67b0aade9891fc6c291646"},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"CBC", "Hex", "Hex",
|
"CBC", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"CFB", "Hex", "Hex",
|
"CFB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"OFB", "Hex", "Hex",
|
"OFB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"CTR", "Hex", "Hex",
|
"CTR", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"GCM", "Hex", "Hex",
|
"GCM", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": "70fad2ca19412c20f40fd06918736e56"},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"GCM", "Hex", "Hex",
|
"GCM", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": "61cc4b70809452b0b3e38f913fa0a109"},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"ECB", "Hex", "Hex",
|
"ECB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"CBC", "Hex", "Hex",
|
"CBC", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"CFB", "Hex", "Hex",
|
"CFB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"OFB", "Hex", "Hex",
|
"OFB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"CTR", "Hex", "Hex",
|
"CTR", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"GCM", "Hex", "Hex",
|
"GCM", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": "86db597d5302595223cadbd990f1309b"},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"GCM", "Hex", "Hex",
|
"GCM", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": "aeedf3e6ca4201577c0cf3e9ce58159d"},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"ECB", "Hex", "Hex",
|
"ECB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"CBC", "Hex", "Hex",
|
"CBC", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"CFB", "Hex", "Hex",
|
"CFB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"OFB", "Hex", "Hex",
|
"OFB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"CTR", "Hex", "Hex",
|
"CTR", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"GCM", "Hex", "Hex",
|
"GCM", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": "821b1e5f32dad052e502775a523d957a"},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"GCM", "Hex", "Hex",
|
"GCM", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": "a8f04c4d93bbef82bef61a103371aef9"},
|
{"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": [
|
"args": [
|
||||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||||
|
16,
|
||||||
"ECB", "Hex", "Hex",
|
"ECB", "Hex", "Hex",
|
||||||
{"option": "Hex", "string": ""},
|
{"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"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
132
tests/operations/tests/EscapeSmartCharacters.mjs
Normal file
132
tests/operations/tests/EscapeSmartCharacters.mjs
Normal file
@ -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"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]);
|
||||||
@ -11,44 +11,70 @@ TestRegister.addTests([
|
|||||||
{
|
{
|
||||||
name: "Extract email address",
|
name: "Extract email address",
|
||||||
input: "email@example.com\nfirstname.lastname@example.com\nemail@subdomain.example.com\nfirstname+lastname@example.com\n1234567890@example.com\nemail@example-one.com\n_______@example.com email@example.name\nemail@example.museum email@example.co.jp firstname-lastname@example.com",
|
input: "email@example.com\nfirstname.lastname@example.com\nemail@subdomain.example.com\nfirstname+lastname@example.com\n1234567890@example.com\nemail@example-one.com\n_______@example.com email@example.name\nemail@example.museum email@example.co.jp firstname-lastname@example.com",
|
||||||
expectedOutput: "email@example.com\nfirstname.lastname@example.com\nemail@subdomain.example.com\nfirstname+lastname@example.com\n1234567890@example.com\nemail@example-one.com\n_______@example.com\nemail@example.name\nemail@example.museum\nemail@example.co.jp\nfirstname-lastname@example.com",
|
expectedOutput:
|
||||||
|
"email@example.com\nfirstname.lastname@example.com\nemail@subdomain.example.com\nfirstname+lastname@example.com\n1234567890@example.com\nemail@example-one.com\n_______@example.com\nemail@example.name\nemail@example.museum\nemail@example.co.jp\nfirstname-lastname@example.com",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "Extract email addresses",
|
op: "Extract email addresses",
|
||||||
"args": [false]
|
args: [false],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Extract email address - Display total",
|
name: "Extract email address - Display total",
|
||||||
input: "email@example.com\nfirstname.lastname@example.com\nemail@subdomain.example.com\nfirstname+lastname@example.com\n1234567890@example.com\nemail@example-one.com\n_______@example.com email@example.name\nemail@example.museum email@example.co.jp firstname-lastname@example.com",
|
input: "email@example.com\nfirstname.lastname@example.com\nemail@subdomain.example.com\nfirstname+lastname@example.com\n1234567890@example.com\nemail@example-one.com\n_______@example.com email@example.name\nemail@example.museum email@example.co.jp firstname-lastname@example.com",
|
||||||
expectedOutput: "Total found: 11\n\nemail@example.com\nfirstname.lastname@example.com\nemail@subdomain.example.com\nfirstname+lastname@example.com\n1234567890@example.com\nemail@example-one.com\n_______@example.com\nemail@example.name\nemail@example.museum\nemail@example.co.jp\nfirstname-lastname@example.com",
|
expectedOutput:
|
||||||
|
"Total found: 11\n\nemail@example.com\nfirstname.lastname@example.com\nemail@subdomain.example.com\nfirstname+lastname@example.com\n1234567890@example.com\nemail@example-one.com\n_______@example.com\nemail@example.name\nemail@example.museum\nemail@example.co.jp\nfirstname-lastname@example.com",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "Extract email addresses",
|
op: "Extract email addresses",
|
||||||
"args": [true]
|
args: [true],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Extract email address (Internationalized)",
|
name: "Extract email address (Internationalized)",
|
||||||
input: "\u4f0a\u662d\u5091@\u90f5\u4ef6.\u5546\u52d9 \u093e\u092e@\u092e\u094b\u0939\u0928.\u0908\u0928\u094d\u092b\u094b\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c \u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc Jos\u1ec5Silv\u1ec5@googl\u1ec5.com\nJos\u1ec5Silv\u1ec5@google.com and Jos\u1ec5Silva@google.com\nFoO@BaR.CoM, john@192.168.10.100\ng\xf3mez@junk.br and Abc.123@example.com.\nuser+mailbox/department=shipping@example.com\n\u7528\u6237@\u4f8b\u5b50.\u5e7f\u544a\n\u0909\u092a\u092f\u094b\u0917\u0915\u0930\u094d\u0924\u093e@\u0909\u0926\u093e\u0939\u0930\u0923.\u0915\u0949\u092e\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nD\xf6rte@S\xf6rensen.example.com\n\u0430\u0434\u0436\u0430\u0439@\u044d\u043a\u0437\u0430\u043c\u043f\u043b.\u0440\u0443\u0441\ntest@xn--bcher-kva.com",
|
input: "\u4f0a\u662d\u5091@\u90f5\u4ef6.\u5546\u52d9 \u093e\u092e@\u092e\u094b\u0939\u0928.\u0908\u0928\u094d\u092b\u094b\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c \u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc Jos\u1ec5Silv\u1ec5@googl\u1ec5.com\nJos\u1ec5Silv\u1ec5@google.com and Jos\u1ec5Silva@google.com\nFoO@BaR.CoM, john@192.168.10.100\ng\xf3mez@junk.br and Abc.123@example.com.\nuser+mailbox/department=shipping@example.com\n\u7528\u6237@\u4f8b\u5b50.\u5e7f\u544a\n\u0909\u092a\u092f\u094b\u0917\u0915\u0930\u094d\u0924\u093e@\u0909\u0926\u093e\u0939\u0930\u0923.\u0915\u0949\u092e\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nD\xf6rte@S\xf6rensen.example.com\n\u0430\u0434\u0436\u0430\u0439@\u044d\u043a\u0437\u0430\u043c\u043f\u043b.\u0440\u0443\u0441\ntest@xn--bcher-kva.com",
|
||||||
expectedOutput: "\u4f0a\u662d\u5091@\u90f5\u4ef6.\u5546\u52d9\n\u093e\u092e@\u092e\u094b\u0939\u0928.\u0908\u0928\u094d\u092b\u094b\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nJos\u1ec5Silv\u1ec5@googl\u1ec5.com\nJos\u1ec5Silv\u1ec5@google.com\nJos\u1ec5Silva@google.com\nFoO@BaR.CoM\njohn@192.168.10.100\ng\xf3mez@junk.br\nAbc.123@example.com\nuser+mailbox/department=shipping@example.com\n\u7528\u6237@\u4f8b\u5b50.\u5e7f\u544a\n\u0909\u092a\u092f\u094b\u0917\u0915\u0930\u094d\u0924\u093e@\u0909\u0926\u093e\u0939\u0930\u0923.\u0915\u0949\u092e\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nD\xf6rte@S\xf6rensen.example.com\n\u0430\u0434\u0436\u0430\u0439@\u044d\u043a\u0437\u0430\u043c\u043f\u043b.\u0440\u0443\u0441\ntest@xn--bcher-kva.com",
|
expectedOutput:
|
||||||
|
"\u4f0a\u662d\u5091@\u90f5\u4ef6.\u5546\u52d9\n\u093e\u092e@\u092e\u094b\u0939\u0928.\u0908\u0928\u094d\u092b\u094b\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nJos\u1ec5Silv\u1ec5@googl\u1ec5.com\nJos\u1ec5Silv\u1ec5@google.com\nJos\u1ec5Silva@google.com\nFoO@BaR.CoM\njohn@192.168.10.100\ng\xf3mez@junk.br\nAbc.123@example.com\nuser+mailbox/department=shipping@example.com\n\u7528\u6237@\u4f8b\u5b50.\u5e7f\u544a\n\u0909\u092a\u092f\u094b\u0917\u0915\u0930\u094d\u0924\u093e@\u0909\u0926\u093e\u0939\u0930\u0923.\u0915\u0949\u092e\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nD\xf6rte@S\xf6rensen.example.com\n\u0430\u0434\u0436\u0430\u0439@\u044d\u043a\u0437\u0430\u043c\u043f\u043b.\u0440\u0443\u0441\ntest@xn--bcher-kva.com",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "Extract email addresses",
|
op: "Extract email addresses",
|
||||||
"args": [false]
|
args: [false],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Extract email address - Display total (Internationalized)",
|
name: "Extract email address - Display total (Internationalized)",
|
||||||
input: "\u4f0a\u662d\u5091@\u90f5\u4ef6.\u5546\u52d9 \u093e\u092e@\u092e\u094b\u0939\u0928.\u0908\u0928\u094d\u092b\u094b\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c \u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc Jos\u1ec5Silv\u1ec5@googl\u1ec5.com\nJos\u1ec5Silv\u1ec5@google.com and Jos\u1ec5Silva@google.com\nFoO@BaR.CoM, john@192.168.10.100\ng\xf3mez@junk.br and Abc.123@example.com.\nuser+mailbox/department=shipping@example.com\n\u7528\u6237@\u4f8b\u5b50.\u5e7f\u544a\n\u0909\u092a\u092f\u094b\u0917\u0915\u0930\u094d\u0924\u093e@\u0909\u0926\u093e\u0939\u0930\u0923.\u0915\u0949\u092e\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nD\xf6rte@S\xf6rensen.example.com\n\u0430\u0434\u0436\u0430\u0439@\u044d\u043a\u0437\u0430\u043c\u043f\u043b.\u0440\u0443\u0441\ntest@xn--bcher-kva.com",
|
input: "\u4f0a\u662d\u5091@\u90f5\u4ef6.\u5546\u52d9 \u093e\u092e@\u092e\u094b\u0939\u0928.\u0908\u0928\u094d\u092b\u094b\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c \u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc Jos\u1ec5Silv\u1ec5@googl\u1ec5.com\nJos\u1ec5Silv\u1ec5@google.com and Jos\u1ec5Silva@google.com\nFoO@BaR.CoM, john@192.168.10.100\ng\xf3mez@junk.br and Abc.123@example.com.\nuser+mailbox/department=shipping@example.com\n\u7528\u6237@\u4f8b\u5b50.\u5e7f\u544a\n\u0909\u092a\u092f\u094b\u0917\u0915\u0930\u094d\u0924\u093e@\u0909\u0926\u093e\u0939\u0930\u0923.\u0915\u0949\u092e\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nD\xf6rte@S\xf6rensen.example.com\n\u0430\u0434\u0436\u0430\u0439@\u044d\u043a\u0437\u0430\u043c\u043f\u043b.\u0440\u0443\u0441\ntest@xn--bcher-kva.com",
|
||||||
expectedOutput: "Total found: 19\n\n\u4f0a\u662d\u5091@\u90f5\u4ef6.\u5546\u52d9\n\u093e\u092e@\u092e\u094b\u0939\u0928.\u0908\u0928\u094d\u092b\u094b\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nJos\u1ec5Silv\u1ec5@googl\u1ec5.com\nJos\u1ec5Silv\u1ec5@google.com\nJos\u1ec5Silva@google.com\nFoO@BaR.CoM\njohn@192.168.10.100\ng\xf3mez@junk.br\nAbc.123@example.com\nuser+mailbox/department=shipping@example.com\n\u7528\u6237@\u4f8b\u5b50.\u5e7f\u544a\n\u0909\u092a\u092f\u094b\u0917\u0915\u0930\u094d\u0924\u093e@\u0909\u0926\u093e\u0939\u0930\u0923.\u0915\u0949\u092e\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nD\xf6rte@S\xf6rensen.example.com\n\u0430\u0434\u0436\u0430\u0439@\u044d\u043a\u0437\u0430\u043c\u043f\u043b.\u0440\u0443\u0441\ntest@xn--bcher-kva.com",
|
expectedOutput:
|
||||||
|
"Total found: 19\n\n\u4f0a\u662d\u5091@\u90f5\u4ef6.\u5546\u52d9\n\u093e\u092e@\u092e\u094b\u0939\u0928.\u0908\u0928\u094d\u092b\u094b\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nJos\u1ec5Silv\u1ec5@googl\u1ec5.com\nJos\u1ec5Silv\u1ec5@google.com\nJos\u1ec5Silva@google.com\nFoO@BaR.CoM\njohn@192.168.10.100\ng\xf3mez@junk.br\nAbc.123@example.com\nuser+mailbox/department=shipping@example.com\n\u7528\u6237@\u4f8b\u5b50.\u5e7f\u544a\n\u0909\u092a\u092f\u094b\u0917\u0915\u0930\u094d\u0924\u093e@\u0909\u0926\u093e\u0939\u0930\u0923.\u0915\u0949\u092e\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nD\xf6rte@S\xf6rensen.example.com\n\u0430\u0434\u0436\u0430\u0439@\u044d\u043a\u0437\u0430\u043c\u043f\u043b.\u0440\u0443\u0441\ntest@xn--bcher-kva.com",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "Extract email addresses",
|
op: "Extract email addresses",
|
||||||
"args": [true]
|
args: [true],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Extract email address - IP address",
|
||||||
|
input: "yaunwfkb\nexample@[127.0.0.1]\n091nvka",
|
||||||
|
expectedOutput: "example@[127.0.0.1]",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Extract email addresses",
|
||||||
|
args: [false],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Extract email address - invalid IP address",
|
||||||
|
input: "yaunwfkb\nfalse_positive@[1.2.3.]\n091nvka",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Extract email addresses",
|
||||||
|
args: [false],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
* @copyright Karsten Silkenbäumer 2019
|
* @copyright Karsten Silkenbäumer 2019
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
import TestRegister from "../TestRegister";
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
TestRegister.addTests([
|
TestRegister.addTests([
|
||||||
{
|
{
|
||||||
@ -47,7 +47,7 @@ TestRegister.addTests([
|
|||||||
{
|
{
|
||||||
name: "Fernet Encrypt: no input",
|
name: "Fernet Encrypt: no input",
|
||||||
input: "",
|
input: "",
|
||||||
expectedMatch: /^gAAAAABce-[\w-]+={0,2}$/,
|
expectedMatch: /^gAAA[\w-]+={0,2}$/,
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
op: "Fernet Encrypt",
|
op: "Fernet Encrypt",
|
||||||
@ -69,12 +69,27 @@ TestRegister.addTests([
|
|||||||
{
|
{
|
||||||
name: "Fernet Encrypt: valid arguments",
|
name: "Fernet Encrypt: valid arguments",
|
||||||
input: "This is a secret message.\n",
|
input: "This is a secret message.\n",
|
||||||
expectedMatch: /^gAAAAABce-[\w-]+={0,2}$/,
|
expectedMatch: /^gAAA[\w-]+={0,2}$/,
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
op: "Fernet Encrypt",
|
op: "Fernet Encrypt",
|
||||||
args: ["MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI="]
|
args: ["MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI="]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fernet Encrypt/Decrypt: round trip",
|
||||||
|
input: "This is a secret message.\n",
|
||||||
|
expectedOutput: "This is a secret message.\n",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fernet Encrypt",
|
||||||
|
args: ["MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI="]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "Fernet Decrypt",
|
||||||
|
args: ["MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI="]
|
||||||
|
},
|
||||||
|
],
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|||||||
@ -14,15 +14,18 @@ const validTokenSha256 = "eyJyb2xlIjoic3VwZXJ1c2VyIiwidXNlciI6ImFkbWluIn0.aab3Ew
|
|||||||
const validKey = "mysecretkey";
|
const validKey = "mysecretkey";
|
||||||
const wrongKey = "notTheKey";
|
const wrongKey = "notTheKey";
|
||||||
|
|
||||||
const outputObject = {
|
const outputObject = `{
|
||||||
user: "admin",
|
"role": "superuser",
|
||||||
role: "superuser",
|
"user": "admin"
|
||||||
};
|
}`;
|
||||||
|
|
||||||
const outputVerify = {
|
const outputVerify = `{
|
||||||
valid: true,
|
"valid": true,
|
||||||
payload: outputObject,
|
"payload": {
|
||||||
};
|
"role": "superuser",
|
||||||
|
"user": "admin"
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
|
||||||
TestRegister.addTests([
|
TestRegister.addTests([
|
||||||
{
|
{
|
||||||
|
|||||||
80
tests/operations/tests/GenerateLoremIpsum.mjs
Normal file
80
tests/operations/tests/GenerateLoremIpsum.mjs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* Generate Lorem Ipsum tests
|
||||||
|
*
|
||||||
|
* @author GCHQDeveloper581
|
||||||
|
* @copyright Crown Copyright 2025
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Generate Lorem Ipsum: Exceeds Word Limit",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: "Length must be less than 100000",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Generate Lorem Ipsum",
|
||||||
|
"args": [999_999, "Words"]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Generate Lorem Ipsum: Within Word Limit",
|
||||||
|
input: "",
|
||||||
|
// each word is >= 3 characters long, so expect at least 3000 characters
|
||||||
|
expectedMatch: /.{3000,}/s,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Generate Lorem Ipsum",
|
||||||
|
"args": [1000, "Words"]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Generate Lorem Ipsum: Exceeds Byte Limit",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: "Length must be less than 1000000",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Generate Lorem Ipsum",
|
||||||
|
"args": [1_000_001, "Bytes"]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Generate Lorem Ipsum: Exceeds Sentence Limit",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: "Length must be less than 100000",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Generate Lorem Ipsum",
|
||||||
|
"args": [999_999, "Sentences"]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Generate Lorem Ipsum: Exceeds Paragraph Limit",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: "Length must be less than 100000",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Generate Lorem Ipsum",
|
||||||
|
"args": [999_999, "Paragraphs"]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Generate Lorem Ipsum: Incorrect lengthType",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: "Invalid length type",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Generate Lorem Ipsum",
|
||||||
|
"args": [999_999, "Novels"]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
]);
|
||||||
@ -126,6 +126,17 @@ TestRegister.addTests([
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "To Hexdump: Width too large",
|
||||||
|
input: "H",
|
||||||
|
expectedOutput: "Width must be no more than 65536",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "To Hexdump",
|
||||||
|
args: [155555555555555, false, false, false]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "From Hexdump: xxd",
|
name: "From Hexdump: xxd",
|
||||||
input: `00000000: 0001 0203 0405 0607 0809 0a0b 0c0d 0e0f ................
|
input: `00000000: 0001 0203 0405 0607 0809 0a0b 0c0d 0e0f ................
|
||||||
|
|||||||
@ -12,7 +12,7 @@ TestRegister.addTests([
|
|||||||
{
|
{
|
||||||
name: "IPv6 Transition: IPv4 to IPv6",
|
name: "IPv6 Transition: IPv4 to IPv6",
|
||||||
input: "198.51.100.7",
|
input: "198.51.100.7",
|
||||||
expectedOutput: "6to4: 2002:c633:6407::/48\nIPv4 Mapped: ::ffff:c633:6407\nIPv4 Translated: ::ffff:0:c633:6407\nNat 64: 64:ff9b::c633:6407",
|
expectedOutput: "6to4: 2002:c633:6407::/48\nIPv4 Mapped: ::ffff:c633:6407\nIPv4 Translated: ::ffff:0:c633:6407\nNat 64: 64:ff9b::c633:6407\n",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
op: "IPv6 Transition Addresses",
|
op: "IPv6 Transition Addresses",
|
||||||
@ -22,7 +22,7 @@ TestRegister.addTests([
|
|||||||
}, {
|
}, {
|
||||||
name: "IPv6 Transition: IPv4 /24 Range to IPv6",
|
name: "IPv6 Transition: IPv4 /24 Range to IPv6",
|
||||||
input: "198.51.100.0/24",
|
input: "198.51.100.0/24",
|
||||||
expectedOutput: "6to4: 2002:c633:6400::/40\nIPv4 Mapped: ::ffff:c633:6400/120\nIPv4 Translated: ::ffff:0:c633:6400/120\nNat 64: 64:ff9b::c633:6400/120",
|
expectedOutput: "6to4: 2002:c633:6400::/40\nIPv4 Mapped: ::ffff:c633:6400/120\nIPv4 Translated: ::ffff:0:c633:6400/120\nNat 64: 64:ff9b::c633:6400/120\n",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
op: "IPv6 Transition Addresses",
|
op: "IPv6 Transition Addresses",
|
||||||
@ -32,7 +32,7 @@ TestRegister.addTests([
|
|||||||
}, {
|
}, {
|
||||||
name: "IPv6 Transition: IPv4 to IPv6 Remove headers",
|
name: "IPv6 Transition: IPv4 to IPv6 Remove headers",
|
||||||
input: "198.51.100.7",
|
input: "198.51.100.7",
|
||||||
expectedOutput: "2002:c633:6407::/48\n::ffff:c633:6407\n::ffff:0:c633:6407\n64:ff9b::c633:6407",
|
expectedOutput: "2002:c633:6407::/48\n::ffff:c633:6407\n::ffff:0:c633:6407\n64:ff9b::c633:6407\n",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
op: "IPv6 Transition Addresses",
|
op: "IPv6 Transition Addresses",
|
||||||
@ -42,7 +42,7 @@ TestRegister.addTests([
|
|||||||
}, {
|
}, {
|
||||||
name: "IPv6 Transition: IPv6 to IPv4",
|
name: "IPv6 Transition: IPv6 to IPv4",
|
||||||
input: "64:ff9b::c633:6407",
|
input: "64:ff9b::c633:6407",
|
||||||
expectedOutput: "IPv4: 198.51.100.7",
|
expectedOutput: "IPv4: 198.51.100.7\n",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
op: "IPv6 Transition Addresses",
|
op: "IPv6 Transition Addresses",
|
||||||
|
|||||||
@ -10,138 +10,144 @@ import {ASCII_TEXT, UTF8_TEXT, ALL_BYTES} from "../../samples/Ciphers.mjs";
|
|||||||
|
|
||||||
// RSA-1024
|
// RSA-1024
|
||||||
const ALICE_PRIVATE = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
const ALICE_PRIVATE = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||||
Version: Keybase OpenPGP v2.0.77
|
Version: Keybase OpenPGP v2.1.17
|
||||||
Comment: https://keybase.io/crypto
|
Comment: https://keybase.io/crypto
|
||||||
|
|
||||||
xcEYBFsNaYsBBAC9rnmjTzLLBCey2gq9un+XXP089sP3AONhSivdJlJEEWjt999o
|
xcEYBGoXHs0BBADB6Loj+NXNQBgVNCDtFYxNvjvVinPAqW7/spsvjCOhDrIkqGf2
|
||||||
g8vM18TcEk1sxyItp/GLlE/T70NPFAvdVXKI0KDQZ9fm77JDKitl587npRaspOOX
|
foY6sjLpsdZaHh+CtEApc3Fn3gLSq17PCY0KJwcirbp3kYyEzZ2rAhJlpqmW3mua
|
||||||
L1yUVFGVr4YEPDLoAT4PJgwI3TsEBfLGeOZqBqd/stw/FKjrNZJLRYfjnQARAQAB
|
mqffrOgOpvlR1Hoa7SL4qTWqvwX68p5PUcETKAKE2CQVMj1mki882ldMzQARAQAB
|
||||||
AAP9G3EGgAM74fXJQy1wUwqMMvsXrUjgs6IZQ0Cryo7PZVxExfNlCtsmZ42VGWbn
|
AAP7BMz0sshJzsOL9RZtzEDQ0OnpRE+hrv7i2xy6X9J53VZmTacHr+ARBan8vbFj
|
||||||
H071OY22eu8LWCn2nut+MUM6EnjDZ7e/u85eHd0r5fY/3Vl0lQCy53RDdEQ3w8vA
|
66Y8RHme7wfHInmqGzoX5ktHvRH52+gm902kPUWW9WPtoIT+j2n1/ifzZI4SJl8g
|
||||||
XcUSabxwqpubmtyC3jxIXmVH6rLLmSpGGX8IqHRTfNDwHTECAPsgeVy0qkT0kJq1
|
ssysKwNz+Et+1ffxPJGkWnblyrXG6JtNwmwBjMgAA1jxqPcCAP6k7GDbW9gtt2B1
|
||||||
Aw8gthHO6c3m1NOcAPyTqSRLVspxRDB0LuYHnVxAN+dUHFYAfwPj+h+E6ROolqe4
|
5d+0g78dSf2WXLhO0YqmromyXm1Ub9asKfL42eayXZjy6KQb5xlO9bNWH5AkfGx7
|
||||||
IKtrls8CAMFcwisDUQXFQFmO2pkpgaQTkN9XjGqBhjYd1EGs+WcYZb7eD98Ue0TZ
|
qVTPox8CAMLxBcfhzC92e7kDApuebFadCiIrSv0puE57DbVyMb8xtY+khl/pHlnA
|
||||||
GUF4UtzHUW5hIiCgkTrwpdpRqE3xudMCAJbhnzE+Mj7yKAHAV8LjZfpJA9hh1G8c
|
9IslbZTBFRbjJgcprHWvtUhd7NUhHpMB/A/iYINYQ9jLovVtijsmeGc1zAHCYtzN
|
||||||
ATDpoWD1yAcLO1mMVkSExpMHoiuQ5ujzWyCHYnXDdRo6jkowP4JxIX+axs0AwrQE
|
36UtikIDDs+uWT5RD5RDRh8CXEtpGs8wvyQsfmt0xLwdtilvFdefq9aoPc0AwrQE
|
||||||
EwEKAB4FAlsNaYsCGy8DCwkHAxUKCAIeAQIXgAMWAgECGQEACgkQhCRlSN+Y5IXj
|
EwEKAB4FAmoXHs0CGy8DCwkHAxUKCAIeAQIXgAMWAgECGQEACgkQG3UgSyrfjYz9
|
||||||
5QP8CZns1zlWk7S37Dhvxe3K3EYVgefc+EDWsj3xvlo+QUKQMAmANFNnqYzt++mv
|
WwQAtBfgtztR1z05tzkCfEAGHMNmcJoUdh5kUnDJa0ekg3rSAYWTP294+OLQM/Up
|
||||||
cVhvGzyn+wa244fJb3xGYAi+G4Ya5pWQbXSzAVhjteHyLcjS6VZ/ydxDGCZK37Gc
|
t7KjprDNQjMDy24gaBldAInTgo8I/x1JcfQeluuZKKe4lbmST6229onE6bXeb17n
|
||||||
MYs/8x4kwdU+A8/bQhJ+nRVEJjkg0OcoH9rJv0kB+ilcC7LHwRgEWw1piwEEAOXO
|
aLZaSiYI/qLyC8xeb9WkfmR8uRumXSFrTJxHvPzLB4Pgx2nHwRgEahcezQEEAKjU
|
||||||
Jib0QIvuqKAZiN3Yol3xC9Wz5aXQyg7qCnnYHHrPIMgYvGrTjjvDFCwM5uxCv38Q
|
543TxZbzZiae6XWFIXjFgWE/vBC+5ZYEyTAG6jtwfP4tgagb+chJG+hoFA9HZXXP
|
||||||
d6rJnzrRXTC1EiAia/b7f76Z0r4W+j6KdVCGpQnVQE6b//WdY5ys1xLAkNr4xwNj
|
r5CPiNZUW6aPpbaMRmubIZs7uCpw3RfcZ+AR+Q9unf0kCJxXThRBhhWHipaLB44M
|
||||||
42nrOIMGB1qV0XezJ4VBOMpMHlwE2WR27HOQakXDABEBAAEAA/9Svw4BzMVJHaBe
|
weCueUawRjwnJVog9nIEE1Heg5G9/fHemLZJ7iU/ABEBAAEAA/4wEreATe20Rsgu
|
||||||
NZOQviaIyPjH9ETmle2LvT4UbXqjxd057544oQCACFhFHEgyHj6x1A4i0wKgvS5f
|
dQ9a1DasseheLYy6Y/Dxn5k94KovlJ8yrPh/Sr/8BL06lvAnTZgZTLLcAdLf3JNg
|
||||||
EXP7WimhUEybo8YktbYX691QGPHNNQw5dc6IzLZmSm9p1zpuOs1VBHs6lpR5Y0WT
|
QQTZjuW55cRBu73aegvM4UKvmTxAXgJXk9ADpYTfH7yyyp3B6VTFt5kFwIzFJqvo
|
||||||
/2vDrbY2Loa+Dojuvuq3hY1Bu5fjcQIA/SdK6T8sEYwdZTfCKEWdvMQ8zhjioNNn
|
b7NNN87qNuCAfOumSA31k2K+RUupiQIA0EVM8yCWvB8qG0+qW63yqwuP4/YGtg7L
|
||||||
5enUNT/WQXw6qvkczD2U48PlIXpwfn4Rjh3sGEiumng334LTslXtvwIA6GOl6eFC
|
G5a+v6+Fz8UuLKtBchy4xfPZMP5IsXdbAtYQiPlSvAZNRYH1eG+eNQIAz4XRXQZI
|
||||||
337clY0Yyog7cTsEZTdCQBIScZi7grMuL9KFWx4UbfHiDS976MRu1ciATCTSCdc5
|
KO7yHawxUsEfuTt1G9yKjUCYCN4yiD/cfYtXoB9wLHRmsC6mBc8XwhtszYnQGKRV
|
||||||
xgLEUF51WrWw/QIApR/pGgDg/Ow32jS38VonCH6TpFFMk9KciKCMm7sRrG3J6kFK
|
+fdYoluxcH30IwIAxKHe5hylDp5/LO0pZK+uXQqD6D30Q5xzeWwHgfXsce6PXZ1J
|
||||||
UxuxWXPs+pWXjTn6ItfrX6M8dZZkC2BBR9UyrqB5wsCDBBgBCgAPBQJbDWmLBQkP
|
9tblAyYDjRzCGtJ1sjqsVeEEZTU6s5r9Y9ViCaTvwsCDBBgBCgAPBQJqFx7NBQkP
|
||||||
CZwAAhsuAKgJEIQkZUjfmOSFnSAEGQEKAAYFAlsNaYsACgkQPtlTQFIjCzrjvQQA
|
CZwAAhsuAKgJEBt1IEsq342MnSAEGQEKAAYFAmoXHs0ACgkQOfwkCKoimvpKxQP/
|
||||||
hyGjZ2zDMxyXA3oEoD3RfjPQtAYFPJ5i0/ir/FD2nX7//cyd8zJS24P6S9+ID8vB
|
U55dBOApPc0egWCgEBaUocwZ6Tg8dvCw5/8h/ttHtb7dh4G+XHq3zPOz8yHS22r0
|
||||||
0n+JwF6KrvjqpMneXXbPmi5OebqMogLahWmhCtjriDKrfJJiL0HmTKGl89p2Z59e
|
uTmDbQFT7QnPWuFgN5UBYIM4jilTbeVLbCPYTXvCnzAF6QRLV1OdwrESpFs4vqwZ
|
||||||
BoLbm4Jpk1rL7EmoibsmUZdBUutf0tw5IusXd/B5sNwhdgQArBzyHVIFyN+fegTE
|
UmffzoeI6rFHI9HHHiUZ/S2u9YdyqLfHMTZe9s8iByuMtgP+IzQHozMdEXNFUlFp
|
||||||
9cR677M92NjYhqY8c+fF/AV+7XQv0Vsi9B//HeTMCml6jytxdSIZBl7uLrasIOd0
|
xw/b5Tv4ps5Hs+/iSiGJDJvC6xtWXi2kpU2kNACKW69vt/5DLloTNHVOAR7Zo4zV
|
||||||
FJk+VP7UrOfDaz6oVq+tarStAelfqT9DRQXw+nEdes4bxDsPvi1OieTtexJRO181
|
OYo6u//mQRvjtmzvr5WJg6Ti+o/nZEaUIL7CXaCwbdeJkG8QSX1U5l734U1D2U+J
|
||||||
zdsmOukv2RhgrJzFCcpzAkUYGqjHwRgEWw1piwEEALDKG2L6NNhTXZ3MJJLVtEPD
|
wmTfuZ1DQBdl7A2rTInPmI5Iuz7HwRcEahcezQEEAMQmvSmxyBpSKd7pRbYzTNDn
|
||||||
65c9KmT8DagJXCp0cl3bQbcs+zLmsfYwnIKNTOxnhxAER+5e6jmW4K7sbLY593rO
|
tTJtCmFRi/jFh5nA4bU280srqNzFD00YiWFSEn+FXimJjLgDhu3v9XI74KBINZd/
|
||||||
iqDXXX8OR28t88IGjlIrVd+2t6+ma5ecSgsyVqBDFFTpAzg+QFWdk2VEOlA5zNfC
|
uRzxgvW2972T0ogxx4BPrRa3tCcdJKijKwfnNG0T9mrNz2W4P2JY0ZR0pIC94nm0
|
||||||
dX94pLUMjPDAHSsZfrufABEBAAEAA/wIFwePzPFUIOR8zxWxXnQkUbfbMOJawqoB
|
mg8EkEHxwCypavxmo/mpABEBAAEAA/ICZzFHLpTzjw4iz+dcMS1uSn+znnPTjtq/
|
||||||
UYRVMQT2xIzKTBWmq6XjJTBUTREDFG26zudXwiInxn67ongLErX/Zhohq8lBYjjx
|
a6wath9TmQdKwY+hgd/RBlkFngdtcUB75LODMIffYmKrDz9IiN/CGMl4G0CBoVTP
|
||||||
QkQRtU+QSDsksdJJL0Lj/6SAkljkhXmO+jYmRVirQfGBVl33Dk9YWnd/VePO5epn
|
gx+mmCGLUX3T0ozDra8dmO5Tv8LIbF4xpx0GOA1gQ0mNC1w2NJRyJY7PIF6bevdy
|
||||||
nYPxEGT+MQIA6n9nHmzbz5ohSi6Ovn4OW0704K3kLhOQ3WP3j+5+bWXv0Xd89w7v
|
lFl6ZAp/AgD4RILvX1Cj3ZMJcQ6G7loyUSiVQRpR7uMVfGlIJeP4rAXqpvfyeUnn
|
||||||
ZMyv0IJOvhOw1670BcBxbI/CSFD4Nz+k+QIAwQAP/M8TdG1Twwx6yED0syNvPDfN
|
jT28RsFFszcKHZXRxWby2fBscDxtwEsTAgDKQrGL6jRBvojwNn4kixBG9v1RkRBr
|
||||||
5hzZM8031zTBbguSRJskD18aBtwcUun93+dcilRY94gXbl4xSq3YitTDVwIAvX+P
|
PykEUJsOmOlgmd2hQslfD/dNrJSwxvzl8q5RI1PlI1343UdRQEDDY6PTAgCPADVb
|
||||||
06nJmFdgeoanpcYIBA4hwi+LPyfPcGo6tfnsxk7ul1mBK27TR+AjnJ+HNFCh54CM
|
3ghi5A2uh+LyORRt2A7C353Mz8cofue/N78ViChBy1Bh7Yyh0jo/wtoaP98aQfYq
|
||||||
4cLH1djyBmwEt30Wm6FjwsCDBBgBCgAPBQJbDWmLBQkDwmcAAhsuAKgJEIQkZUjf
|
Z2krI8wWrLIfUHx8mtvCwIMEGAEKAA8FAmoXHs0FCQPCZwACGy4AqAkQG3UgSyrf
|
||||||
mOSFnSAEGQEKAAYFAlsNaYsACgkQW/Z2teklb4u5/gP/fnZ7ZuV+l4c2EQY5Xnk8
|
jYydIAQZAQoABgUCahcezQAKCRCNZtcgmBdHpJhpA/4+MD1IjjP9ttE6Sg2/vdUJ
|
||||||
S/lY3Xr9zoucjQwQWeRKwAQYoiovzxA4XV8gGyrdAsrIPUFLp7PmUBG4YJV/7sVo
|
Yzij2vQMwBIcrYPJ3vW86g4WMz8a2kaBC+MAoHzYNvv7CwZPpXpvGm9jWww7EKOm
|
||||||
zzRwVq+jS8Jo0xYbGJMv2DuAnXXrYCZWZRqRscr1Wlc+CUACmxYZjC1DVVrAXr0j
|
Gwuza7Yi9kseqVz+/wIJcseiI3e/o9XCRgbXtTJmgNsJW3fRIJnmMnuAJ/4ykL1G
|
||||||
TqYTk+jjhemTTAtUelgMhcX82wP9EEU66hCYFUayjn4bBlR1yEvMpJd8JSTHR/dZ
|
x4i15bky1sW0pvoXAaCL0Y1BBACvg8WLxpdnvWWYHv9z/x9cDOxZG2j2/rjG2VnC
|
||||||
H8t3Ri6R2AYRqBxro0JEXDhL9iDnuPQVxsbgq2YlhHrPJI8opKuxV7wrXrupzwFf
|
lDkZI4+/DM2NB9l/dDiUqiuaSipPHELW2zFHG9uvnVnB8lTwsJ8pnP2n4zWdxfqf
|
||||||
KixJMNwsAPk/nSc4qIZvXTi2fmyAZDJYUgsm6CwkxumaVvIdVNGRmxqGSRTuEInt
|
IkEm6mZ6yp+uNaLPO4RiqjwPirSNqharqUSxRYtIFwlcpoCQcW00B55vMiawZX2G
|
||||||
W03Cwfs=
|
Eq/5/Q==
|
||||||
=Mb52
|
=HBWf
|
||||||
-----END PGP PRIVATE KEY BLOCK-----`;
|
-----END PGP PRIVATE KEY BLOCK-----`;
|
||||||
|
|
||||||
const ALICE_PUBLIC = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
const ALICE_PUBLIC = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
Version: Keybase OpenPGP v2.0.77
|
Version: Keybase OpenPGP v2.1.17
|
||||||
Comment: https://keybase.io/crypto
|
Comment: https://keybase.io/crypto
|
||||||
|
|
||||||
xo0EWw1piwEEAL2ueaNPMssEJ7LaCr26f5dc/Tz2w/cA42FKK90mUkQRaO3332iD
|
xo0EahcezQEEAMHouiP41c1AGBU0IO0VjE2+O9WKc8Cpbv+ymy+MI6EOsiSoZ/Z+
|
||||||
y8zXxNwSTWzHIi2n8YuUT9PvQ08UC91VcojQoNBn1+bvskMqK2XnzuelFqyk45cv
|
hjqyMumx1loeH4K0QClzcWfeAtKrXs8JjQonByKtuneRjITNnasCEmWmqZbea5qa
|
||||||
XJRUUZWvhgQ8MugBPg8mDAjdOwQF8sZ45moGp3+y3D8UqOs1kktFh+OdABEBAAHN
|
p9+s6A6m+VHUehrtIvipNaq/Bfrynk9RwRMoAoTYJBUyPWaSLzzaV0zNABEBAAHN
|
||||||
AMK0BBMBCgAeBQJbDWmLAhsvAwsJBwMVCggCHgECF4ADFgIBAhkBAAoJEIQkZUjf
|
AMK0BBMBCgAeBQJqFx7NAhsvAwsJBwMVCggCHgECF4ADFgIBAhkBAAoJEBt1IEsq
|
||||||
mOSF4+UD/AmZ7Nc5VpO0t+w4b8XtytxGFYHn3PhA1rI98b5aPkFCkDAJgDRTZ6mM
|
342M/VsEALQX4Lc7Udc9Obc5AnxABhzDZnCaFHYeZFJwyWtHpIN60gGFkz9vePji
|
||||||
7fvpr3FYbxs8p/sGtuOHyW98RmAIvhuGGuaVkG10swFYY7Xh8i3I0ulWf8ncQxgm
|
0DP1Kbeyo6awzUIzA8tuIGgZXQCJ04KPCP8dSXH0HpbrmSinuJW5kk+ttvaJxOm1
|
||||||
St+xnDGLP/MeJMHVPgPP20ISfp0VRCY5INDnKB/ayb9JAfopXAuyzo0EWw1piwEE
|
3m9e52i2WkomCP6i8gvMXm/VpH5kfLkbpl0ha0ycR7z8yweD4Mdpzo0EahcezQEE
|
||||||
AOXOJib0QIvuqKAZiN3Yol3xC9Wz5aXQyg7qCnnYHHrPIMgYvGrTjjvDFCwM5uxC
|
AKjU543TxZbzZiae6XWFIXjFgWE/vBC+5ZYEyTAG6jtwfP4tgagb+chJG+hoFA9H
|
||||||
v38Qd6rJnzrRXTC1EiAia/b7f76Z0r4W+j6KdVCGpQnVQE6b//WdY5ys1xLAkNr4
|
ZXXPr5CPiNZUW6aPpbaMRmubIZs7uCpw3RfcZ+AR+Q9unf0kCJxXThRBhhWHipaL
|
||||||
xwNj42nrOIMGB1qV0XezJ4VBOMpMHlwE2WR27HOQakXDABEBAAHCwIMEGAEKAA8F
|
B44MweCueUawRjwnJVog9nIEE1Heg5G9/fHemLZJ7iU/ABEBAAHCwIMEGAEKAA8F
|
||||||
AlsNaYsFCQ8JnAACGy4AqAkQhCRlSN+Y5IWdIAQZAQoABgUCWw1piwAKCRA+2VNA
|
AmoXHs0FCQ8JnAACGy4AqAkQG3UgSyrfjYydIAQZAQoABgUCahcezQAKCRA5/CQI
|
||||||
UiMLOuO9BACHIaNnbMMzHJcDegSgPdF+M9C0BgU8nmLT+Kv8UPadfv/9zJ3zMlLb
|
qiKa+krFA/9Tnl0E4Ck9zR6BYKAQFpShzBnpODx28LDn/yH+20e1vt2Hgb5cerfM
|
||||||
g/pL34gPy8HSf4nAXoqu+Oqkyd5dds+aLk55uoyiAtqFaaEK2OuIMqt8kmIvQeZM
|
87PzIdLbavS5OYNtAVPtCc9a4WA3lQFggziOKVNt5UtsI9hNe8KfMAXpBEtXU53C
|
||||||
oaXz2nZnn14GgtubgmmTWsvsSaiJuyZRl0FS61/S3Dki6xd38Hmw3CF2BACsHPId
|
sRKkWzi+rBlSZ9/Oh4jqsUcj0cceJRn9La71h3Kot8cxNl72zyIHK4y2A/4jNAej
|
||||||
UgXI3596BMT1xHrvsz3Y2NiGpjxz58X8BX7tdC/RWyL0H/8d5MwKaXqPK3F1IhkG
|
Mx0Rc0VSUWnHD9vlO/imzkez7+JKIYkMm8LrG1ZeLaSlTaQ0AIpbr2+3/kMuWhM0
|
||||||
Xu4utqwg53QUmT5U/tSs58NrPqhWr61qtK0B6V+pP0NFBfD6cR16zhvEOw++LU6J
|
dU4BHtmjjNU5ijq7/+ZBG+O2bO+vlYmDpOL6j+dkRpQgvsJdoLBt14mQbxBJfVTm
|
||||||
5O17ElE7XzXN2yY66S/ZGGCsnMUJynMCRRgaqM6NBFsNaYsBBACwyhti+jTYU12d
|
XvfhTUPZT4nCZN+5nUNAF2XsDatMic+Yjki7Ps6NBGoXHs0BBADEJr0pscgaUine
|
||||||
zCSS1bRDw+uXPSpk/A2oCVwqdHJd20G3LPsy5rH2MJyCjUzsZ4cQBEfuXuo5luCu
|
6UW2M0zQ57UybQphUYv4xYeZwOG1NvNLK6jcxQ9NGIlhUhJ/hV4piYy4A4bt7/Vy
|
||||||
7Gy2Ofd6zoqg111/DkdvLfPCBo5SK1XftrevpmuXnEoLMlagQxRU6QM4PkBVnZNl
|
O+CgSDWXf7kc8YL1tve9k9KIMceAT60Wt7QnHSSooysH5zRtE/Zqzc9luD9iWNGU
|
||||||
RDpQOczXwnV/eKS1DIzwwB0rGX67nwARAQABwsCDBBgBCgAPBQJbDWmLBQkDwmcA
|
dKSAveJ5tJoPBJBB8cAsqWr8ZqP5qQARAQABwsCDBBgBCgAPBQJqFx7NBQkDwmcA
|
||||||
AhsuAKgJEIQkZUjfmOSFnSAEGQEKAAYFAlsNaYsACgkQW/Z2teklb4u5/gP/fnZ7
|
AhsuAKgJEBt1IEsq342MnSAEGQEKAAYFAmoXHs0ACgkQjWbXIJgXR6SYaQP+PjA9
|
||||||
ZuV+l4c2EQY5Xnk8S/lY3Xr9zoucjQwQWeRKwAQYoiovzxA4XV8gGyrdAsrIPUFL
|
SI4z/bbROkoNv73VCWM4o9r0DMASHK2Dyd71vOoOFjM/GtpGgQvjAKB82Db7+wsG
|
||||||
p7PmUBG4YJV/7sVozzRwVq+jS8Jo0xYbGJMv2DuAnXXrYCZWZRqRscr1Wlc+CUAC
|
T6V6bxpvY1sMOxCjphsLs2u2IvZLHqlc/v8CCXLHoiN3v6PVwkYG17UyZoDbCVt3
|
||||||
mxYZjC1DVVrAXr0jTqYTk+jjhemTTAtUelgMhcX82wP9EEU66hCYFUayjn4bBlR1
|
0SCZ5jJ7gCf+MpC9RseIteW5MtbFtKb6FwGgi9GNQQQAr4PFi8aXZ71lmB7/c/8f
|
||||||
yEvMpJd8JSTHR/dZH8t3Ri6R2AYRqBxro0JEXDhL9iDnuPQVxsbgq2YlhHrPJI8o
|
XAzsWRto9v64xtlZwpQ5GSOPvwzNjQfZf3Q4lKormkoqTxxC1tsxRxvbr51ZwfJU
|
||||||
pKuxV7wrXrupzwFfKixJMNwsAPk/nSc4qIZvXTi2fmyAZDJYUgsm6CwkxumaVvId
|
8LCfKZz9p+M1ncX6nyJBJupmesqfrjWizzuEYqo8D4q0jaoWq6lEsUWLSBcJXKaA
|
||||||
VNGRmxqGSRTuEIntW03Cwfs=
|
kHFtNAeebzImsGV9hhKv+f0=
|
||||||
=PuGL
|
=IODM
|
||||||
-----END PGP PUBLIC KEY BLOCK-----`;
|
-----END PGP PUBLIC KEY BLOCK-----`;
|
||||||
|
|
||||||
// ECC-384
|
// ECC-384
|
||||||
const BOB_PRIVATE = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
const BOB_PRIVATE = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||||
Version: Keybase OpenPGP v2.0.77
|
Version: Keybase OpenPGP v2.1.17
|
||||||
Comment: https://keybase.io/crypto
|
Comment: https://keybase.io/crypto
|
||||||
|
|
||||||
xcAABFsNafYBAYDHiv+tCi4267xI6iTmBrhOKdNbKLWIYMG1OoE1f9qpT+nAVKFR
|
xaQEahclbRMFK4EEACIDAwSvC1SlbUU7/QJFldLQGfAeyhu0mRvTIcxzANM9SdkI
|
||||||
zUAFXKqQjqMDESkAEQEAAQABewd7cLkIQHGKly8PE+P0h7fV7X5bJqwZiqDwC8DU
|
dS2ArnVOZCB7cnfj5AF1nAjphKCv+01LAkGpCF6dUrvDwDeicMaq+E1OPVc+G0bH
|
||||||
38vCUO/KtkZO3jEQYA1U9DsNDQDA73KCr3K1tSX1afeWzb8vVBY4ZzXocKb9AMDV
|
O4qQwJgyRLV/GNUZ0ASSmNYAAYCxPV5eRqoX/13vQ38EFBDqWVQE5BuIvvFqNI2R
|
||||||
Vk17t1N4nClMfqpGIDELtYBMiiCDyJ0AwLsnQb9cE+g1MZETtNDYXXxilkO/4CP9
|
2RW7hAyI8AWazxDF90gurec8mWYXJM0AwpYEExMKAB4FAmoXJW0CGy8DCwkHAxUK
|
||||||
8j4HzQDCZAQTAQoAHgUCWw1p9gIbLwMLCQcDFQoIAh4BAheAAxYCAQIZAQAKCRCE
|
CAIeAQIXgAMWAgECGQEACgkQXd9oo/PqkifstAF+KMP1xACDyAqsoZjzmOdD03+r
|
||||||
cIHWt/IPg+sqAYC6goCyOCYD/DytOW3I2cb12iDyFOSDsOx6lrmIgLyP0dDnbJHb
|
qaHk3EDO7J98qA+g3laUj/bx21IM8FJNEJHKs9TpAYD8LpHAGHmDuBKZDCZKabIS
|
||||||
S9ar68yuHeDqP7jHiARbDWn2AQEAwSE4qpbLQzSIUfwmfWXmHneAuQIkEYawRxK/
|
avxAOuoEHOOu9GlGk+8LgftPLW3EYUf/R7m4mGIq1UzHdwRqFyVtEwgqhkjOPQMB
|
||||||
H1JkGxcAEQEAAQAA/0pvbnK5OdBGMABBSehs3LrW/hWWIL0y/MfS7h/6gSJ5AID3
|
BwIDBGf0GrkZYEH+SU15lkMjYcHndaqwYbF+JPgUVc6ZiQYDkaY2uodq+n82HoNr
|
||||||
YOgHLqEgM1Bo2TzvIjwlAIDH3E+0ynQFdLH96FPp47eLAH9e/NZ74e2N8sTMBoYO
|
zsCvKJxzC9upm8qzOwFHL+C7UvoAAP9MeWPmsuLSLXq+cVeqoEHAFQ/VYTBL/N7A
|
||||||
1sbcLp7CkwQYAQoADwUCWw1p9gUJDwmcAAIbLgBICRCEcIHWt/IPgz0gBBkBCgAG
|
XeiiDdUbKBFmwsAnBBgTCgAPBQJqFyVtBQkPCZwAAhsCAGoJEF3faKPz6pInXyAE
|
||||||
BQJbDWn2AAoJELU8cYHhYcru2lwBAL4OUK2fkhzh2VU3meXgAMWjoP6ryRUCTmSQ
|
GRMKAAYFAmoXJW0ACgkQVQZtQ9p5kJtfDQD+Ns1eh7rEAXveFSOLhx7Vw/5kUWm8
|
||||||
xuULvvCyfZMBfiHzV5QLgXSUVUA7Og6mlH5pw2gtgsZhijwwywkzF3tQ+s++hOZR
|
wVWbqWDK5tJTF5EA/2+3jIQfg+/pE+VkO/NuIGQ9bUqGmGuX0s14TcjqDm9LNugB
|
||||||
161wHxQKgwHIU8eIBFsNafYBAQCjOV/I3a0HkXVtLndCrWFcjmLzim9PX8EpYUV3
|
f27462A7iEkTab0nOQXtd6+L3PeHRUPUT1CFq+74M5GABr0wobJ5CCaQNxQH++IK
|
||||||
yG2/AQARAQABAAD8DBWPVduzl7/ZJcAu7CzR7F376NxG8J42+ioX12n9cNEAgNj7
|
vwF+MSD0JajEVgi99qzSQOTZe8UGArddSCIJuUxNwEzaxvT6DombpLJ2O4yYklR/
|
||||||
qAcnQCtTDlb1waf4mdcAgMCTCuwur8AqIOSjoOzqwucAf1MfeKXhwNAEtoiD7S44
|
xwoJx3sEahclbRIIKoZIzj0DAQcCAwRjn9T4UunA8a8ZuWP31AJheebCAcPFWBGx
|
||||||
f8UvxsKTBBgBCgAPBQJbDWn2BQkDwmcAAhsuAEgJEIRwgda38g+DPSAEGQEKAAYF
|
dkxFeX65heVpMipOZ97EczRkitfAmiwt7cREq6yhvZ42KMOcZHPIAwEKCQABAFwA
|
||||||
AlsNafYACgkQNBtaoVz6VrvTVAD+LD063VrU7vlJ7xQwtMun4G3FW+RKgb7Rsww8
|
UyvBBcchnSFCguG8EbEeA+DFKS62fvhqMHyMLGtfDUvChwQYEwoADwUCahclbQUJ
|
||||||
B1mt68F5dQGAm8ctxECzEMmyO8jSkjOLkG6u8zLQWFm9MBZqcdmt6EUDf1dA/3xu
|
A8JnAAIbDAAKCRBd32ij8+qSJ1+sAX4wkp3GZiRAtUZujC3bJ0ukYJjieNHFapA6
|
||||||
/y59qEGb0j4w
|
r+0ku3mR/9OFDbVaTPEcL7nhgGY94q8BfRvczdClIK0rdY/bopQDq4uERoiB/bsH
|
||||||
=I/Gz
|
1VFadIEvMZeIppWGb8d93IpZErGT9xQI8A==
|
||||||
|
=XC/n
|
||||||
-----END PGP PRIVATE KEY BLOCK-----`;
|
-----END PGP PRIVATE KEY BLOCK-----`;
|
||||||
|
|
||||||
const BOB_PUBLIC = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
const BOB_PUBLIC = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
Version: Keybase OpenPGP v2.0.77
|
Version: Keybase OpenPGP v2.1.17
|
||||||
Comment: https://keybase.io/crypto
|
Comment: https://keybase.io/crypto
|
||||||
|
|
||||||
xj0EWw1p9gEBgMeK/60KLjbrvEjqJOYGuE4p01sotYhgwbU6gTV/2qlP6cBUoVHN
|
xm8EahclbRMFK4EEACIDAwSvC1SlbUU7/QJFldLQGfAeyhu0mRvTIcxzANM9SdkI
|
||||||
QAVcqpCOowMRKQARAQABzQDCZAQTAQoAHgUCWw1p9gIbLwMLCQcDFQoIAh4BAheA
|
dS2ArnVOZCB7cnfj5AF1nAjphKCv+01LAkGpCF6dUrvDwDeicMaq+E1OPVc+G0bH
|
||||||
AxYCAQIZAQAKCRCEcIHWt/IPg+sqAYC6goCyOCYD/DytOW3I2cb12iDyFOSDsOx6
|
O4qQwJgyRLV/GNUZ0ASSmNbNAMKWBBMTCgAeBQJqFyVtAhsvAwsJBwMVCggCHgEC
|
||||||
lrmIgLyP0dDnbJHbS9ar68yuHeDqP7jOLQRbDWn2AQEAwSE4qpbLQzSIUfwmfWXm
|
F4ADFgIBAhkBAAoJEF3faKPz6pIn7LQBfijD9cQAg8gKrKGY85jnQ9N/q6mh5NxA
|
||||||
HneAuQIkEYawRxK/H1JkGxcAEQEAAcKTBBgBCgAPBQJbDWn2BQkPCZwAAhsuAEgJ
|
zuyffKgPoN5WlI/28dtSDPBSTRCRyrPU6QGA/C6RwBh5g7gSmQwmSmmyEmr8QDrq
|
||||||
EIRwgda38g+DPSAEGQEKAAYFAlsNafYACgkQtTxxgeFhyu7aXAEAvg5QrZ+SHOHZ
|
BBzjrvRpRpPvC4H7Ty1txGFH/0e5uJhiKtVMzlIEahclbRMIKoZIzj0DAQcCAwRn
|
||||||
VTeZ5eAAxaOg/qvJFQJOZJDG5Qu+8LJ9kwF+IfNXlAuBdJRVQDs6DqaUfmnDaC2C
|
9Bq5GWBB/klNeZZDI2HB53WqsGGxfiT4FFXOmYkGA5GmNrqHavp/Nh6Da87Aryic
|
||||||
xmGKPDDLCTMXe1D6z76E5lHXrXAfFAqDAchTzi0EWw1p9gEBAKM5X8jdrQeRdW0u
|
cwvbqZvKszsBRy/gu1L6wsAnBBgTCgAPBQJqFyVtBQkPCZwAAhsCAGoJEF3faKPz
|
||||||
d0KtYVyOYvOKb09fwSlhRXfIbb8BABEBAAHCkwQYAQoADwUCWw1p9gUJA8JnAAIb
|
6pInXyAEGRMKAAYFAmoXJW0ACgkQVQZtQ9p5kJtfDQD+Ns1eh7rEAXveFSOLhx7V
|
||||||
LgBICRCEcIHWt/IPgz0gBBkBCgAGBQJbDWn2AAoJEDQbWqFc+la701QA/iw9Ot1a
|
w/5kUWm8wVWbqWDK5tJTF5EA/2+3jIQfg+/pE+VkO/NuIGQ9bUqGmGuX0s14Tcjq
|
||||||
1O75Se8UMLTLp+BtxVvkSoG+0bMMPAdZrevBeXUBgJvHLcRAsxDJsjvI0pIzi5Bu
|
Dm9LNugBf27462A7iEkTab0nOQXtd6+L3PeHRUPUT1CFq+74M5GABr0wobJ5CCaQ
|
||||||
rvMy0FhZvTAWanHZrehFA39XQP98bv8ufahBm9I+MA==
|
NxQH++IKvwF+MSD0JajEVgi99qzSQOTZe8UGArddSCIJuUxNwEzaxvT6DombpLJ2
|
||||||
=K9ht
|
O4yYklR/xwoJzlYEahclbRIIKoZIzj0DAQcCAwRjn9T4UunA8a8ZuWP31AJheebC
|
||||||
|
AcPFWBGxdkxFeX65heVpMipOZ97EczRkitfAmiwt7cREq6yhvZ42KMOcZHPIAwEK
|
||||||
|
CcKHBBgTCgAPBQJqFyVtBQkDwmcAAhsMAAoJEF3faKPz6pInX6wBfjCSncZmJEC1
|
||||||
|
Rm6MLdsnS6RgmOJ40cVqkDqv7SS7eZH/04UNtVpM8RwvueGAZj3irwF9G9zN0KUg
|
||||||
|
rSt1j9uilAOri4RGiIH9uwfVUVp0gS8xl4imlYZvx33cilkSsZP3FAjw
|
||||||
|
=BHOx
|
||||||
-----END PGP PUBLIC KEY BLOCK-----`;
|
-----END PGP PUBLIC KEY BLOCK-----`;
|
||||||
|
|
||||||
TestRegister.addTests([
|
TestRegister.addTests([
|
||||||
@ -205,29 +211,46 @@ TestRegister.addTests([
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "PGP Sign/Verify: RSA, All bytes",
|
||||||
|
input: ALL_BYTES,
|
||||||
|
expectedMatch: /Signed by PGP key ID: 2ADF8D8C\nPGP fingerprint: 7afe93ff7614167c3fe831fe1b75204b2adf8d8c\nSigned on .*\n----------------------------------\n/,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "PGP Sign",
|
||||||
|
"args": [ALICE_PRIVATE, ""]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "PGP Verify",
|
||||||
|
"args": [ALICE_PUBLIC]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "PGP Decrypt and Verify: UTF8, Alice -> Bob",
|
name: "PGP Decrypt and Verify: UTF8, Alice -> Bob",
|
||||||
input: `-----BEGIN PGP MESSAGE-----
|
input: `-----BEGIN PGP MESSAGE-----
|
||||||
Version: Keybase OpenPGP v2.0.77
|
Version: Keybase OpenPGP v2.1.17
|
||||||
Comment: https://keybase.io/crypto
|
Comment: https://keybase.io/crypto
|
||||||
|
|
||||||
wTwDhHCB1rfyD4MBAX9ld8xGcf2v+X+pwINN0R0TvkWxNesKOQIKPV01AH8JG0J+
|
wX4DEY2FMRPYAl0SAgMEKY2yuB8s16oRWWhJ1RsxNhR8byKFUyFZvi0ETIORMYu+
|
||||||
+yFqLXqDHgYSLANNamfSwQoBOTWuh/5V6gpiXVm2oLHPv997AtoD/kVQrqylF5Xo
|
kkLWgFlVjqPV9q2eVtuVK9f+S/OIm0pztImhq5ZNMDB8r7s0wX4YskSrWRpMKwRr
|
||||||
HUsqPGtSgBA5WPX8tMoHKuqWxEy9FviLnIv73OZN0Ph70uo2E+QIv0Qx27znK0Jy
|
CtoNlPS3//fT3Ll4a2tn8guxyC7lAtmJ6nxZj+qpSZLSwQwBhFlgARdqlp4eTAhF
|
||||||
KDSERvcldgShmVbDP3Pxtxkfr9xa2gar5f0OPovOmKGsTGciQJqPkclRwzIXg12L
|
PRcqHVCqZYSTdjAyerLtfZDaswEwLgGxsshRSJ7BDHxg7NqRcdFkChrWT0s4JpnV
|
||||||
hyd2ElYOMf6vg/yOc06sX4Ih1Tn6JkYqMVJydykMv3g4Z8OXTfwrMLxwO1n3ZB/T
|
/Woq0xcApim1bpyHXG/tT4oM3hbjfpulb92gq2TUNdzb9lJGaKbLHl/0zkoBvHDE
|
||||||
OLdhBdsnREnyCqntBVjMKoRTQhfwq48n7b6caZ+aCPISdDIyDKBpxEzXaNBeEY2V
|
pxtr021JXERB8MNDIIpDESpjCrZ20YCHNr/sBqVm0yM7YGrDLlV+n7oUgL4HK2FU
|
||||||
GCqORM9WhsQ4A6pAx2SP694qH5vgOwrYrgeOU17oK++mzd1GyU2CXoFi73/PANJD
|
tehxUEt4rca81UesYu/Wul6mHh/7Ft4jJuZuf/w9fCWQ6z+9MAEOBXdzWUp5BCyF
|
||||||
TdC3hGr+S4XeuqZ368QG1cBWhNybsOu5sM2YbArb71ZMYuLDp+VolJbEkVf4c/dD
|
ce1STpICAdtRHInJ9zR08qn0ahrwHsvHPFPVIQJDargD5MSqav/3LS2TYqKYYKHy
|
||||||
pVEOaX39NVKe6HcpOiw+CFO6GEkQqCXNprWK6ivBHzkAlF2pjjqlS6qhWxFPicSD
|
TUCxIWqA77Qk3rEaFX+eHxTW4BTlMPArA7ffywkgJAPzrLL+gEgtOLCv2RhNZevR
|
||||||
+1ZKM1fmZu99bhTmdqE3MJx//QMu7mvlHaM85OQkWhWPBxGw/60GVBX9YtvUtfMS
|
weglQRtcuh5N/F9fsmPfsi80R0//LpEeyFX6GueXDw81+AKG9pOTI71Ny8H4W0eA
|
||||||
IOE1W/Zqmqzq+4frwnzWwYv9/U1RwIs/qlFVnzliREOzW+om8EncSSd7fQ==
|
B5dCiOFNHZKCZUlA6GFa04X/XgmfPzTPMtgizbT72/2kfwxJGZY4ngdMVLqfhnVA
|
||||||
=fEAT
|
nfyQLFrOF9giJqDEsjtPXJ0h20stMLMykPUIK0UUf9vPthE86ugCY1XcGQWsuB4U
|
||||||
|
jmdH1dqEUk29TaUz/97s
|
||||||
|
=Ah/0
|
||||||
-----END PGP MESSAGE-----
|
-----END PGP MESSAGE-----
|
||||||
`,
|
`,
|
||||||
expectedOutput: `Signed by PGP key ID: DF98E485
|
expectedOutput: `Signed by PGP key ID: 2ADF8D8C
|
||||||
PGP fingerprint: e94e06dd0b3744a0e970de9d84246548df98e485
|
PGP fingerprint: 7afe93ff7614167c3fe831fe1b75204b2adf8d8c
|
||||||
Signed on Tue, 29 May 2018 15:44:52 GMT
|
Signed on Wed, 27 May 2026 17:18:20 GMT
|
||||||
----------------------------------
|
----------------------------------
|
||||||
${UTF8_TEXT}`,
|
${UTF8_TEXT}`,
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
@ -238,19 +261,19 @@ ${UTF8_TEXT}`,
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "PGP Decrypt: ASCII, Alice -> Bob",
|
name: "PGP Decrypt: ASCII, Alice",
|
||||||
input: `-----BEGIN PGP MESSAGE-----
|
input: `-----BEGIN PGP MESSAGE-----
|
||||||
Version: Keybase OpenPGP v2.0.77
|
Version: Keybase OpenPGP v2.1.17
|
||||||
Comment: https://keybase.io/crypto
|
Comment: https://keybase.io/crypto
|
||||||
|
|
||||||
wYwDPtlTQFIjCzoBBACSlbN7tmQVxR5ZD0rvCwXUkxO3RU8WgBkkmrTCUs9a+xrS
|
wYwDOfwkCKoimvoBA/98ONH8b+HoaDOVLhtF+9Pz5Sk/NZ43htOpm/3+b2B81GKZ
|
||||||
F9HuKcpX/N6XrwTXyuX3BN2tGys4zd6nHV8jYqBoIyWJsWe3viTa1dh/x4183+GP
|
fcUfJYzItyt4X5Ps1ksfrArokG6blkIHPwZdcF7TJ9rWy/cC9S3zP/LF893xT9Z7
|
||||||
fP61gizi3pj0gi2vfGnMhnThbdiO32PVKAeHLHBK+r3XlXZ0kzZCQKRgd55yr9Kk
|
buWj1BjqfNy15WtGJnnQeCJVI4ya0cb3G/I/zAF/mT6R/JcldbJ1OTz9Zy5pZtKi
|
||||||
Aa4SR+qpvtdobkDzbnbhcPLR6CQ8TMjTiNXEpgTc1i0JcP8jaMVFzBt8qgmDMdqU
|
AQL7B8IscCxsx9jxc1ZR3swn+fr603BVP6/mXRRtKIa5DXZR5uMU9ChZ5AYQeHXe
|
||||||
H2qMY1O7hezH3fp+EZzCAccJMtK7VPk13WAgMRH22HirG4aK1i75IVOtjBgObzDh
|
ZzstlcSJWJvuF+uJy3Yc07ttzqQtOQGLh0iBeALK7BWqLsUBqKabZSHTZ4uFdkv9
|
||||||
8zKua7QLi6wJD/AtQ+D3/NgVpzoXwdoLvTjEcAyy+YWNWkJF/jvx3XV1Q/Fz7sHJ
|
86ZebPsfjVlhz4oFYenBUq1C15Zpvut28pHpgh2TLuXPHKkmTwI2Zz9LvVRjBW7A
|
||||||
/bspORYvbi591S4U0m4pikwiOZk=
|
rmDPrpTfy9MOrkjkY7zQSevi
|
||||||
=AVb/
|
=/Zwh
|
||||||
-----END PGP MESSAGE-----`,
|
-----END PGP MESSAGE-----`,
|
||||||
expectedOutput: ASCII_TEXT,
|
expectedOutput: ASCII_TEXT,
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
@ -262,21 +285,22 @@ H2qMY1O7hezH3fp+EZzCAccJMtK7VPk13WAgMRH22HirG4aK1i75IVOtjBgObzDh
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "PGP Verify: ASCII, Alice",
|
name: "PGP Verify: ASCII, Alice",
|
||||||
input: `-----BEGIN PGP SIGNED MESSAGE-----
|
input: `-----BEGIN PGP MESSAGE-----
|
||||||
Hash: SHA256
|
Version: Keybase OpenPGP v2.1.17
|
||||||
|
Comment: https://keybase.io/crypto
|
||||||
|
|
||||||
A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools.
|
yMB1AnicO8LLzMDFaPlHhWOV0qxfjKcnljJkiTsIOiok5+fm5ucp5GYWlyRmpyqU
|
||||||
-----BEGIN PGP SIGNATURE-----
|
ZCSWKBSk5hfkpCrkggTKM1LzFEqKKjPz0hVK8hVSUosz0/MUivNzU0syQGJA/UC1
|
||||||
|
Jak5lQpp+fk5BUX5+WkKmcUgtaV5KalFqcUlmbmJJSCTUxWAGlLzSjNLKhWAimA6
|
||||||
iLMEAQEIAB0WIQRLbJy6MLpYOr9qojE+2VNAUiMLOgUCXRTsvwAKCRA+2VNAUiML
|
wfqK9Q7NYWFg5GJgY2UCOYyBi1MA5tqzj1kYZqaFSuxmUvBnvvAzZOOuyT9vnT75
|
||||||
OuaHBADMMNtsuN92Fb+UrDimsv6TDQpbJhDkwp9kZdKYP5HAmSYAhXBG7N+YCMw+
|
5GVzY2WfOB8H08l5vCZNbBUegsqPPh2aXPQgo8GglTPO2e7qY75g49mzDm+8POfH
|
||||||
v2FSpUu9jJiPBm1K1SEwLufQVexoRv6RsBNolRFB07sArau0s0DnIXUchCZWvyTP
|
nstrb2/93JHrXD5fbcbuVrsFJ01XWE2Xy7HtTgrasGG7ySLZqLStBj2r0n4dTX7g
|
||||||
1KsjBnDr84U2b11H58g4DlTT4gQrz30rFuHz9AGmPAtDHbSXIA==
|
MV1ETCdx6nqHA+4as4Oy9040BACRHYIP
|
||||||
=vnk/
|
=rkte
|
||||||
-----END PGP SIGNATURE-----`,
|
-----END PGP MESSAGE-----`,
|
||||||
expectedOutput: `Signed by PGP key ID: DF98E485
|
expectedOutput: `Signed by PGP key ID: 2ADF8D8C
|
||||||
PGP fingerprint: e94e06dd0b3744a0e970de9d84246548df98e485
|
PGP fingerprint: 7afe93ff7614167c3fe831fe1b75204b2adf8d8c
|
||||||
Signed on Thu, 27 Jun 2019 16:20:15 GMT
|
Signed on Wed, 27 May 2026 19:03:45 GMT
|
||||||
----------------------------------
|
----------------------------------
|
||||||
A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools.`,
|
A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools.`,
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
|
|||||||
147
tests/operations/tests/ParityBit.mjs
Normal file
147
tests/operations/tests/ParityBit.mjs
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/**
|
||||||
|
* Parity Bit tests
|
||||||
|
*
|
||||||
|
* @author j83305 [awz22@protonmail.com]
|
||||||
|
* @copyright Crown Copyright 2020
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Parity bit encode in even parity, 1 block of binary of arbitrary length, prepend, even number of 1s",
|
||||||
|
input: "01010101 10101010",
|
||||||
|
expectedOutput: "001010101 10101010",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Parity Bit",
|
||||||
|
"args": [
|
||||||
|
"Even Parity",
|
||||||
|
"Start",
|
||||||
|
"Encode",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Parity bit encode in even parity, 1 block of binary of arbitrary length, prepend, odd number of 1s",
|
||||||
|
input: "01010101 10101011",
|
||||||
|
expectedOutput: "101010101 10101011",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Parity Bit",
|
||||||
|
"args": [
|
||||||
|
"Even Parity",
|
||||||
|
"Start",
|
||||||
|
"Encode",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Parity bit encode in even parity, 1 block of binary of arbitrary length, append, odd number of 1s",
|
||||||
|
input: "01010101 10101011",
|
||||||
|
expectedOutput: "01010101 101010111",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Parity Bit",
|
||||||
|
"args": [
|
||||||
|
"Even Parity",
|
||||||
|
"End",
|
||||||
|
"Encode",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Parity bit encode in odd parity, 1 block of binary of arbitrary length, prepend, even number of 1s",
|
||||||
|
input: "01010101 10101010",
|
||||||
|
expectedOutput: "101010101 10101010",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Parity Bit",
|
||||||
|
"args": [
|
||||||
|
"Odd Parity",
|
||||||
|
"Start",
|
||||||
|
"Encode",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Parity bit encode in odd parity, 1 block of binary of arbitrary length, prepend, odd number of 1s",
|
||||||
|
input: "01010101 10101011",
|
||||||
|
expectedOutput: "001010101 10101011",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Parity Bit",
|
||||||
|
"args": [
|
||||||
|
"Odd Parity",
|
||||||
|
"Start",
|
||||||
|
"Encode",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Parity bit encode in odd parity, 1 block of binary of arbitrary length, append, odd number of 1s",
|
||||||
|
input: "01010101 10101011",
|
||||||
|
expectedOutput: "01010101 101010110",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Parity Bit",
|
||||||
|
"args": [
|
||||||
|
"Odd Parity",
|
||||||
|
"End",
|
||||||
|
"Encode",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Parity bit encode in even parity, binary for 'hello world!', prepend to each byte",
|
||||||
|
input: "hello world!",
|
||||||
|
expectedOutput: "101101000 001100101 001101100 001101100 001101111 100100000 001110111 001101111 001110010 001101100 101100100 000100001",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Binary",
|
||||||
|
"args": ["Space"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "Parity Bit",
|
||||||
|
"args": [
|
||||||
|
"Even Parity",
|
||||||
|
"Start",
|
||||||
|
"Encode",
|
||||||
|
" "
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Parity bit encode in odd parity, binary for 'hello world!', append to each byte",
|
||||||
|
input: "hello world!",
|
||||||
|
expectedOutput: "011010000 011001011 011011001 011011001 011011111 001000000 011101111 011011111 011100101 011011001 011001000 001000011",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Binary",
|
||||||
|
"args": ["Space"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "Parity Bit",
|
||||||
|
"args": [
|
||||||
|
"Odd Parity",
|
||||||
|
"End",
|
||||||
|
"Encode",
|
||||||
|
" "
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]);
|
||||||
@ -41,5 +41,16 @@ TestRegister.addTests([
|
|||||||
"args": ["Hex", "Text output"]
|
"args": ["Hex", "Text output"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Parse Ethernet frame escapes packet data HTML",
|
||||||
|
input: "000000000000ffffffffffff08003c696d67207372633d78206f6e6572726f723d616c6572742831293e3c7363726970743e616c6572742832293c2f7363726970743e",
|
||||||
|
expectedOutput: "<img src=x onerror=alert(1)><script>alert(2)</script>",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Parse Ethernet frame",
|
||||||
|
"args": ["Hex", "Packet data"]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user