mirror of
https://github.com/gchq/CyberChef
synced 2025-01-12 12:38:48 +00:00
Merge branch 'gchq:master' into protobufstreamdecode
This commit is contained in:
commit
a51ead9051
77 changed files with 4047 additions and 3407 deletions
6
.github/workflows/codeql.yml
vendored
6
.github/workflows/codeql.yml
vendored
|
@ -22,12 +22,12 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v1
|
uses: github/codeql-action/init@v2
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v1
|
uses: github/codeql-action/analyze@v2
|
||||||
|
|
8
.github/workflows/master.yml
vendored
8
.github/workflows/master.yml
vendored
|
@ -10,12 +10,12 @@ jobs:
|
||||||
main:
|
main:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set node version
|
- name: Set node version
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: '17.x'
|
node-version: '18.x'
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: |
|
run: |
|
||||||
|
@ -47,7 +47,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@v2
|
uses: crazy-max/ghaction-github-pages@v3
|
||||||
with:
|
with:
|
||||||
target_branch: gh-pages
|
target_branch: gh-pages
|
||||||
build_dir: ./build/prod
|
build_dir: ./build/prod
|
||||||
|
|
6
.github/workflows/pull_requests.yml
vendored
6
.github/workflows/pull_requests.yml
vendored
|
@ -9,12 +9,12 @@ jobs:
|
||||||
main:
|
main:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set node version
|
- name: Set node version
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: '17.x'
|
node-version: '18.x'
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: |
|
run: |
|
||||||
|
|
6
.github/workflows/releases.yml
vendored
6
.github/workflows/releases.yml
vendored
|
@ -10,12 +10,12 @@ jobs:
|
||||||
main:
|
main:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set node version
|
- name: Set node version
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: '17.x'
|
node-version: '18.x'
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: |
|
run: |
|
||||||
|
|
2
.nvmrc
2
.nvmrc
|
@ -1 +1 @@
|
||||||
17
|
18
|
||||||
|
|
47
CHANGELOG.md
47
CHANGELOG.md
|
@ -13,6 +13,33 @@ All major and minor version changes will be documented in this file. Details of
|
||||||
|
|
||||||
## Details
|
## Details
|
||||||
|
|
||||||
|
### [9.55.0] - 2022-12-09
|
||||||
|
- Added 'AMF Encode' and 'AMF Decode' operations [@n1474335] | [760eff4]
|
||||||
|
|
||||||
|
### [9.54.0] - 2022-11-25
|
||||||
|
- Added 'Rabbit' operation [@mikecat] | [#1450]
|
||||||
|
|
||||||
|
### [9.53.0] - 2022-11-25
|
||||||
|
- Added 'AES Key Wrap' and 'AES Key Unwrap' operations [@mikecat] | [#1456]
|
||||||
|
|
||||||
|
### [9.52.0] - 2022-11-25
|
||||||
|
- Added 'ChaCha' operation [@joostrijneveld] | [#1466]
|
||||||
|
|
||||||
|
### [9.51.0] - 2022-11-25
|
||||||
|
- Added 'CMAC' operation [@mikecat] | [#1457]
|
||||||
|
|
||||||
|
### [9.50.0] - 2022-11-25
|
||||||
|
- Added 'Shuffle' operation [@mikecat] | [#1472]
|
||||||
|
|
||||||
|
### [9.49.0] - 2022-11-11
|
||||||
|
- Added 'LZ4 Compress' and 'LZ4 Decompress' operations [@n1474335] | [31a7f83]
|
||||||
|
|
||||||
|
### [9.48.0] - 2022-10-14
|
||||||
|
- Added 'LM Hash' and 'NT Hash' operations [@n1474335] [@brun0ne] | [#1427]
|
||||||
|
|
||||||
|
### [9.47.0] - 2022-10-14
|
||||||
|
- Added 'LZMA Decompress' and 'LZMA Compress' operations [@mattnotmitt] | [#1421]
|
||||||
|
|
||||||
### [9.46.0] - 2022-07-08
|
### [9.46.0] - 2022-07-08
|
||||||
- Added 'Cetacean Cipher Encode' and 'Cetacean Cipher Decode' operations [@valdelaseras] | [#1308]
|
- Added 'Cetacean Cipher Encode' and 'Cetacean Cipher Decode' operations [@valdelaseras] | [#1308]
|
||||||
|
|
||||||
|
@ -315,6 +342,15 @@ All major and minor version changes will be documented in this file. Details of
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[9.55.0]: https://github.com/gchq/CyberChef/releases/tag/v9.55.0
|
||||||
|
[9.54.0]: https://github.com/gchq/CyberChef/releases/tag/v9.54.0
|
||||||
|
[9.53.0]: https://github.com/gchq/CyberChef/releases/tag/v9.53.0
|
||||||
|
[9.52.0]: https://github.com/gchq/CyberChef/releases/tag/v9.52.0
|
||||||
|
[9.51.0]: https://github.com/gchq/CyberChef/releases/tag/v9.51.0
|
||||||
|
[9.50.0]: https://github.com/gchq/CyberChef/releases/tag/v9.50.0
|
||||||
|
[9.49.0]: https://github.com/gchq/CyberChef/releases/tag/v9.49.0
|
||||||
|
[9.48.0]: https://github.com/gchq/CyberChef/releases/tag/v9.48.0
|
||||||
|
[9.47.0]: https://github.com/gchq/CyberChef/releases/tag/v9.47.0
|
||||||
[9.46.0]: https://github.com/gchq/CyberChef/releases/tag/v9.46.0
|
[9.46.0]: https://github.com/gchq/CyberChef/releases/tag/v9.46.0
|
||||||
[9.45.0]: https://github.com/gchq/CyberChef/releases/tag/v9.45.0
|
[9.45.0]: https://github.com/gchq/CyberChef/releases/tag/v9.45.0
|
||||||
[9.44.0]: https://github.com/gchq/CyberChef/releases/tag/v9.44.0
|
[9.44.0]: https://github.com/gchq/CyberChef/releases/tag/v9.44.0
|
||||||
|
@ -450,6 +486,8 @@ All major and minor version changes will be documented in this file. Details of
|
||||||
[@crespyl]: https://github.com/crespyl
|
[@crespyl]: https://github.com/crespyl
|
||||||
[@thomasleplus]: https://github.com/thomasleplus
|
[@thomasleplus]: https://github.com/thomasleplus
|
||||||
[@valdelaseras]: https://github.com/valdelaseras
|
[@valdelaseras]: https://github.com/valdelaseras
|
||||||
|
[@brun0ne]: https://github.com/brun0ne
|
||||||
|
[@joostrijneveld]: https://github.com/joostrijneveld
|
||||||
|
|
||||||
[8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
|
[8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
|
||||||
[9a33498]: https://github.com/gchq/CyberChef/commit/9a33498fed26a8df9c9f35f39a78a174bf50a513
|
[9a33498]: https://github.com/gchq/CyberChef/commit/9a33498fed26a8df9c9f35f39a78a174bf50a513
|
||||||
|
@ -457,6 +495,8 @@ All major and minor version changes will be documented in this file. Details of
|
||||||
[e9ca4dc]: https://github.com/gchq/CyberChef/commit/e9ca4dc9caf98f33fd986431cd400c88082a42b8
|
[e9ca4dc]: https://github.com/gchq/CyberChef/commit/e9ca4dc9caf98f33fd986431cd400c88082a42b8
|
||||||
[dd18e52]: https://github.com/gchq/CyberChef/commit/dd18e529939078b89867297b181a584e8b2cc7da
|
[dd18e52]: https://github.com/gchq/CyberChef/commit/dd18e529939078b89867297b181a584e8b2cc7da
|
||||||
[a895d1d]: https://github.com/gchq/CyberChef/commit/a895d1d82a2f92d440a0c5eca2bc7c898107b737
|
[a895d1d]: https://github.com/gchq/CyberChef/commit/a895d1d82a2f92d440a0c5eca2bc7c898107b737
|
||||||
|
[31a7f83]: https://github.com/gchq/CyberChef/commit/31a7f83b82e78927f89689f323fcb9185144d6ff
|
||||||
|
[760eff4]: https://github.com/gchq/CyberChef/commit/760eff49b5307aaa3104c5e5b437ffe62299acd1
|
||||||
|
|
||||||
[#95]: https://github.com/gchq/CyberChef/pull/299
|
[#95]: https://github.com/gchq/CyberChef/pull/299
|
||||||
[#173]: https://github.com/gchq/CyberChef/pull/173
|
[#173]: https://github.com/gchq/CyberChef/pull/173
|
||||||
|
@ -552,4 +592,11 @@ All major and minor version changes will be documented in this file. Details of
|
||||||
[#1266]: https://github.com/gchq/CyberChef/pull/1266
|
[#1266]: https://github.com/gchq/CyberChef/pull/1266
|
||||||
[#1250]: https://github.com/gchq/CyberChef/pull/1250
|
[#1250]: https://github.com/gchq/CyberChef/pull/1250
|
||||||
[#1308]: https://github.com/gchq/CyberChef/pull/1308
|
[#1308]: https://github.com/gchq/CyberChef/pull/1308
|
||||||
|
[#1421]: https://github.com/gchq/CyberChef/pull/1421
|
||||||
|
[#1427]: https://github.com/gchq/CyberChef/pull/1427
|
||||||
|
[#1472]: https://github.com/gchq/CyberChef/pull/1472
|
||||||
|
[#1457]: https://github.com/gchq/CyberChef/pull/1457
|
||||||
|
[#1466]: https://github.com/gchq/CyberChef/pull/1466
|
||||||
|
[#1456]: https://github.com/gchq/CyberChef/pull/1456
|
||||||
|
[#1450]: https://github.com/gchq/CyberChef/pull/1450
|
||||||
|
|
||||||
|
|
10
README.md
10
README.md
|
@ -54,7 +54,7 @@ You can use as many operations as you like in simple or complex ways. Some examp
|
||||||
- Whenever you modify the input or the recipe, CyberChef will automatically "bake" for you and produce the output immediately.
|
- Whenever you modify the input or the recipe, CyberChef will automatically "bake" for you and produce the output immediately.
|
||||||
- This can be turned off and operated manually if it is affecting performance (if the input is very large, for instance).
|
- This can be turned off and operated manually if it is affecting performance (if the input is very large, for instance).
|
||||||
- Automated encoding detection
|
- Automated encoding detection
|
||||||
- CyberChef uses [a number of techniques](https://github.com/gchq/CyberChef/wiki/Automatic-detection-of-encoded-data-using-CyberChef-Magic) to attempt to automatically detect which encodings your data is under. If it finds a suitable operation which can make sense of your data, it displays the 'magic' icon in the Output field which you can click to decode your data.
|
- CyberChef uses [a number of techniques](https://github.com/gchq/CyberChef/wiki/Automatic-detection-of-encoded-data-using-CyberChef-Magic) to attempt to automatically detect which encodings your data is under. If it finds a suitable operation that make sense of your data, it displays the 'magic' icon in the Output field which you can click to decode your data.
|
||||||
- Breakpoints
|
- Breakpoints
|
||||||
- You can set breakpoints on any operation in your recipe to pause execution before running it.
|
- You can set breakpoints on any operation in your recipe to pause execution before running it.
|
||||||
- You can also step through the recipe one operation at a time to see what the data looks like at each stage.
|
- You can also step through the recipe one operation at a time to see what the data looks like at each stage.
|
||||||
|
@ -66,7 +66,7 @@ You can use as many operations as you like in simple or complex ways. Some examp
|
||||||
- Highlighting
|
- Highlighting
|
||||||
- When you highlight text in the input or output, the offset and length values will be displayed and, if possible, the corresponding data will be highlighted in the output or input respectively (example: [highlight the word 'question' in the input to see where it appears in the output][11]).
|
- When you highlight text in the input or output, the offset and length values will be displayed and, if possible, the corresponding data will be highlighted in the output or input respectively (example: [highlight the word 'question' in the input to see where it appears in the output][11]).
|
||||||
- Save to file and load from file
|
- Save to file and load from file
|
||||||
- You can save the output to a file at any time or load a file by dragging and dropping it into the input field. Files up to around 2GB are supported (depending on your browser), however some operations may take a very long time to run over this much data.
|
- You can save the output to a file at any time or load a file by dragging and dropping it into the input field. Files up to around 2GB are supported (depending on your browser), however, some operations may take a very long time to run over this much data.
|
||||||
- CyberChef is entirely client-side
|
- CyberChef is entirely client-side
|
||||||
- It should be noted that none of your recipe configuration or input (either text or files) is ever sent to the CyberChef web server - all processing is carried out within your browser, on your own computer.
|
- It should be noted that none of your recipe configuration or input (either text or files) is ever sent to the CyberChef web server - all processing is carried out within your browser, on your own computer.
|
||||||
- Due to this feature, CyberChef can be downloaded and run locally. You can use the link in the top left corner of the app to download a full copy of CyberChef and drop it into a virtual machine, share it with other people, or host it in a closed network.
|
- Due to this feature, CyberChef can be downloaded and run locally. You can use the link in the top left corner of the app to download a full copy of CyberChef and drop it into a virtual machine, share it with other people, or host it in a closed network.
|
||||||
|
@ -74,7 +74,7 @@ You can use as many operations as you like in simple or complex ways. Some examp
|
||||||
|
|
||||||
## Deep linking
|
## Deep linking
|
||||||
|
|
||||||
By manipulation of CyberChef's URL hash, you can change the initial settings with which the page opens.
|
By manipulating CyberChef's URL hash, you can change the initial settings with which the page opens.
|
||||||
The format is `https://gchq.github.io/CyberChef/#recipe=Operation()&input=...`
|
The format is `https://gchq.github.io/CyberChef/#recipe=Operation()&input=...`
|
||||||
|
|
||||||
Supported arguments are `recipe`, `input` (encoded in Base64), and `theme`.
|
Supported arguments are `recipe`, `input` (encoded in Base64), and `theme`.
|
||||||
|
@ -90,12 +90,12 @@ CyberChef is built to support
|
||||||
|
|
||||||
## Node.js support
|
## Node.js support
|
||||||
|
|
||||||
CyberChef is built to fully support Node.js `v10` and partially supports `v12`. Named imports using a deep import specifier does not work in `v12`. For more information, see the Node API page in the project [wiki pages](https://github.com/gchq/CyberChef/wiki)
|
CyberChef is built to fully support Node.js `v16`. For more information, see the Node API page in the project [wiki pages](https://github.com/gchq/CyberChef/wiki)
|
||||||
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Contributing a new operation to CyberChef is super easy! There is a quickstart script which will walk you through the process. If you can write basic JavaScript, you can write a CyberChef operation.
|
Contributing a new operation to CyberChef is super easy! The quickstart script will walk you through the process. If you can write basic JavaScript, you can write a CyberChef operation.
|
||||||
|
|
||||||
An installation walkthrough, how-to guides for adding new operations and themes, descriptions of the repository structure, available data types and coding conventions can all be found in the project [wiki pages](https://github.com/gchq/CyberChef/wiki).
|
An installation walkthrough, how-to guides for adding new operations and themes, descriptions of the repository structure, available data types and coding conventions can all be found in the project [wiki pages](https://github.com/gchq/CyberChef/wiki).
|
||||||
|
|
||||||
|
|
3632
package-lock.json
generated
3632
package-lock.json
generated
File diff suppressed because it is too large
Load diff
20
package.json
20
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "cyberchef",
|
"name": "cyberchef",
|
||||||
"version": "9.46.0",
|
"version": "9.55.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": "n1474335 <n1474335@gmail.com>",
|
||||||
"homepage": "https://gchq.github.io/CyberChef",
|
"homepage": "https://gchq.github.io/CyberChef",
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
"babel-loader": "^8.2.5",
|
"babel-loader": "^8.2.5",
|
||||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||||
"babel-plugin-transform-builtin-extend": "1.1.2",
|
"babel-plugin-transform-builtin-extend": "1.1.2",
|
||||||
"chromedriver": "^101.0.0",
|
"chromedriver": "^103.0.0",
|
||||||
"cli-progress": "^3.11.1",
|
"cli-progress": "^3.11.1",
|
||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
"copy-webpack-plugin": "^11.0.0",
|
"copy-webpack-plugin": "^11.0.0",
|
||||||
|
@ -77,7 +77,6 @@
|
||||||
"postcss-import": "^14.1.0",
|
"postcss-import": "^14.1.0",
|
||||||
"postcss-loader": "^7.0.0",
|
"postcss-loader": "^7.0.0",
|
||||||
"prompt": "^1.3.0",
|
"prompt": "^1.3.0",
|
||||||
"sass-loader": "^13.0.0",
|
|
||||||
"sitemap": "^7.1.1",
|
"sitemap": "^7.1.1",
|
||||||
"terser": "^5.14.0",
|
"terser": "^5.14.0",
|
||||||
"webpack": "^5.73.0",
|
"webpack": "^5.73.0",
|
||||||
|
@ -87,7 +86,9 @@
|
||||||
"worker-loader": "^3.0.8"
|
"worker-loader": "^3.0.8"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@astronautlabs/amf": "^0.0.6",
|
||||||
"@babel/polyfill": "^7.12.1",
|
"@babel/polyfill": "^7.12.1",
|
||||||
|
"@blu3r4y/lzma": "^2.3.3",
|
||||||
"arrive": "^2.4.1",
|
"arrive": "^2.4.1",
|
||||||
"avsc": "^5.7.4",
|
"avsc": "^5.7.4",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
|
@ -123,26 +124,27 @@
|
||||||
"js-sha3": "^0.8.0",
|
"js-sha3": "^0.8.0",
|
||||||
"jsesc": "^3.0.2",
|
"jsesc": "^3.0.2",
|
||||||
"json5": "^2.2.1",
|
"json5": "^2.2.1",
|
||||||
"jsonpath": "^1.1.1",
|
"jsonpath-plus": "^7.2.0",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"jsqr": "^1.4.0",
|
"jsqr": "^1.4.0",
|
||||||
"jsrsasign": "^10.5.23",
|
"jsrsasign": "^10.5.23",
|
||||||
"kbpgp": "2.1.15",
|
"kbpgp": "2.1.15",
|
||||||
"libbzip2-wasm": "0.0.4",
|
"libbzip2-wasm": "0.0.4",
|
||||||
"libyara-wasm": "^1.1.0",
|
"libyara-wasm": "^1.2.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"loglevel": "^1.8.0",
|
"loglevel": "^1.8.0",
|
||||||
"loglevel-message-prefix": "^3.0.0",
|
"loglevel-message-prefix": "^3.0.0",
|
||||||
"lz-string": "^1.4.4",
|
"lz-string": "^1.4.4",
|
||||||
|
"lz4js": "^0.2.0",
|
||||||
"markdown-it": "^13.0.1",
|
"markdown-it": "^13.0.1",
|
||||||
"moment": "^2.29.3",
|
"moment": "^2.29.3",
|
||||||
"moment-timezone": "^0.5.34",
|
"moment-timezone": "^0.5.34",
|
||||||
"ngeohash": "^0.6.3",
|
"ngeohash": "^0.6.3",
|
||||||
"node-forge": "^1.3.1",
|
"node-forge": "^1.3.1",
|
||||||
"node-md6": "^0.1.0",
|
"node-md6": "^0.1.0",
|
||||||
"node-sass": "^7.0.1",
|
|
||||||
"nodom": "^2.4.0",
|
"nodom": "^2.4.0",
|
||||||
"notepack.io": "^3.0.1",
|
"notepack.io": "^3.0.1",
|
||||||
|
"ntlm": "^0.1.3",
|
||||||
"nwmatcher": "^1.4.4",
|
"nwmatcher": "^1.4.4",
|
||||||
"otp": "0.1.3",
|
"otp": "0.1.3",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
|
@ -150,13 +152,14 @@
|
||||||
"process": "^0.11.10",
|
"process": "^0.11.10",
|
||||||
"protobufjs": "^6.11.3",
|
"protobufjs": "^6.11.3",
|
||||||
"qr-image": "^3.2.0",
|
"qr-image": "^3.2.0",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
"scryptsy": "^2.1.0",
|
"scryptsy": "^2.1.0",
|
||||||
"snackbarjs": "^1.1.0",
|
"snackbarjs": "^1.1.0",
|
||||||
"sortablejs": "^1.15.0",
|
"sortablejs": "^1.15.0",
|
||||||
"split.js": "^1.6.5",
|
"split.js": "^1.6.5",
|
||||||
"ssdeep.js": "0.0.3",
|
"ssdeep.js": "0.0.3",
|
||||||
"stream-browserify": "^3.0.0",
|
"stream-browserify": "^3.0.0",
|
||||||
"tesseract.js": "2.1.5",
|
"tesseract.js": "3.0.2",
|
||||||
"ua-parser-js": "^1.0.2",
|
"ua-parser-js": "^1.0.2",
|
||||||
"unorm": "^1.6.0",
|
"unorm": "^1.6.0",
|
||||||
"utf8": "^3.0.0",
|
"utf8": "^3.0.0",
|
||||||
|
@ -169,8 +172,9 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npx grunt dev",
|
"start": "npx grunt dev",
|
||||||
"build": "npx grunt prod",
|
"build": "npx grunt prod",
|
||||||
|
"node": "npx grunt node",
|
||||||
"repl": "node --experimental-modules --experimental-json-modules --experimental-specifier-resolution=node --no-warnings src/node/repl.mjs",
|
"repl": "node --experimental-modules --experimental-json-modules --experimental-specifier-resolution=node --no-warnings src/node/repl.mjs",
|
||||||
"test": "npx grunt configTests && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation tests/node/index.mjs && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation tests/operations/index.mjs",
|
"test": "npx grunt configTests && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation --openssl-legacy-provider tests/node/index.mjs && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation --openssl-legacy-provider 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",
|
||||||
|
|
|
@ -27,6 +27,7 @@ class Ingredient {
|
||||||
this.toggleValues = [];
|
this.toggleValues = [];
|
||||||
this.target = null;
|
this.target = null;
|
||||||
this.defaultIndex = 0;
|
this.defaultIndex = 0;
|
||||||
|
this.maxLength = null;
|
||||||
this.min = null;
|
this.min = null;
|
||||||
this.max = null;
|
this.max = null;
|
||||||
this.step = 1;
|
this.step = 1;
|
||||||
|
@ -53,6 +54,7 @@ class Ingredient {
|
||||||
this.toggleValues = ingredientConfig.toggleValues;
|
this.toggleValues = ingredientConfig.toggleValues;
|
||||||
this.target = typeof ingredientConfig.target !== "undefined" ? ingredientConfig.target : null;
|
this.target = typeof ingredientConfig.target !== "undefined" ? ingredientConfig.target : null;
|
||||||
this.defaultIndex = typeof ingredientConfig.defaultIndex !== "undefined" ? ingredientConfig.defaultIndex : 0;
|
this.defaultIndex = typeof ingredientConfig.defaultIndex !== "undefined" ? ingredientConfig.defaultIndex : 0;
|
||||||
|
this.maxLength = ingredientConfig.maxLength || null;
|
||||||
this.min = ingredientConfig.min;
|
this.min = ingredientConfig.min;
|
||||||
this.max = ingredientConfig.max;
|
this.max = ingredientConfig.max;
|
||||||
this.step = ingredientConfig.step;
|
this.step = ingredientConfig.step;
|
||||||
|
|
|
@ -184,6 +184,7 @@ class Operation {
|
||||||
if (ing.disabled) conf.disabled = ing.disabled;
|
if (ing.disabled) conf.disabled = ing.disabled;
|
||||||
if (ing.target) conf.target = ing.target;
|
if (ing.target) conf.target = ing.target;
|
||||||
if (ing.defaultIndex) conf.defaultIndex = ing.defaultIndex;
|
if (ing.defaultIndex) conf.defaultIndex = ing.defaultIndex;
|
||||||
|
if (ing.maxLength) conf.maxLength = ing.maxLength;
|
||||||
if (typeof ing.min === "number") conf.min = ing.min;
|
if (typeof ing.min === "number") conf.min = ing.min;
|
||||||
if (typeof ing.max === "number") conf.max = ing.max;
|
if (typeof ing.max === "number") conf.max = ing.max;
|
||||||
if (ing.step) conf.step = ing.step;
|
if (ing.step) conf.step = ing.step;
|
||||||
|
|
|
@ -206,7 +206,7 @@ class Utils {
|
||||||
* Utils.parseEscapedChars("\\n");
|
* Utils.parseEscapedChars("\\n");
|
||||||
*/
|
*/
|
||||||
static parseEscapedChars(str) {
|
static parseEscapedChars(str) {
|
||||||
return str.replace(/\\([bfnrtv'"]|[0-3][0-7]{2}|[0-7]{1,2}|x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]{1,6}\}|\\)/g, function(m, a) {
|
return str.replace(/\\([abfnrtv'"]|[0-3][0-7]{2}|[0-7]{1,2}|x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]{1,6}\}|\\)/g, function(m, a) {
|
||||||
switch (a[0]) {
|
switch (a[0]) {
|
||||||
case "\\":
|
case "\\":
|
||||||
return "\\";
|
return "\\";
|
||||||
|
@ -219,6 +219,8 @@ class Utils {
|
||||||
case "6":
|
case "6":
|
||||||
case "7":
|
case "7":
|
||||||
return String.fromCharCode(parseInt(a, 8));
|
return String.fromCharCode(parseInt(a, 8));
|
||||||
|
case "a":
|
||||||
|
return String.fromCharCode(7);
|
||||||
case "b":
|
case "b":
|
||||||
return "\b";
|
return "\b";
|
||||||
case "t":
|
case "t":
|
||||||
|
@ -380,6 +382,70 @@ class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a byte array to an integer.
|
||||||
|
*
|
||||||
|
* @param {byteArray} byteArray
|
||||||
|
* @param {string} byteorder - "little" or "big"
|
||||||
|
* @returns {integer}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // returns 67305985
|
||||||
|
* Utils.byteArrayToInt([1, 2, 3, 4], "little");
|
||||||
|
*
|
||||||
|
* // returns 16909060
|
||||||
|
* Utils.byteArrayToInt([1, 2, 3, 4], "big");
|
||||||
|
*/
|
||||||
|
static byteArrayToInt(byteArray, byteorder) {
|
||||||
|
let value = 0;
|
||||||
|
if (byteorder === "big") {
|
||||||
|
for (let i = 0; i < byteArray.length; i++) {
|
||||||
|
value = (value * 256) + byteArray[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = byteArray.length - 1; i >= 0; i--) {
|
||||||
|
value = (value * 256) + byteArray[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an integer to a byte array of {length} bytes.
|
||||||
|
*
|
||||||
|
* @param {integer} value
|
||||||
|
* @param {integer} length
|
||||||
|
* @param {string} byteorder - "little" or "big"
|
||||||
|
* @returns {byteArray}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // returns [5, 255, 109, 1]
|
||||||
|
* Utils.intToByteArray(23985925, 4, "little");
|
||||||
|
*
|
||||||
|
* // returns [1, 109, 255, 5]
|
||||||
|
* Utils.intToByteArray(23985925, 4, "big");
|
||||||
|
*
|
||||||
|
* // returns [0, 0, 0, 0, 1, 109, 255, 5]
|
||||||
|
* Utils.intToByteArray(23985925, 8, "big");
|
||||||
|
*/
|
||||||
|
static intToByteArray(value, length, byteorder) {
|
||||||
|
const arr = new Array(length);
|
||||||
|
if (byteorder === "little") {
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
arr[i] = value & 0xFF;
|
||||||
|
value = value >>> 8;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = length - 1; i >= 0; i--) {
|
||||||
|
arr[i] = value & 0xFF;
|
||||||
|
value = value >>> 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a string to an ArrayBuffer.
|
* Converts a string to an ArrayBuffer.
|
||||||
* Treats the string as UTF-8 if any values are over 255.
|
* Treats the string as UTF-8 if any values are over 255.
|
||||||
|
|
|
@ -46,6 +46,8 @@
|
||||||
"From Quoted Printable",
|
"From Quoted Printable",
|
||||||
"To Punycode",
|
"To Punycode",
|
||||||
"From Punycode",
|
"From Punycode",
|
||||||
|
"AMF Encode",
|
||||||
|
"AMF Decode",
|
||||||
"To Hex Content",
|
"To Hex Content",
|
||||||
"From Hex Content",
|
"From Hex Content",
|
||||||
"PEM to Hex",
|
"PEM to Hex",
|
||||||
|
@ -85,6 +87,8 @@
|
||||||
"RC2 Decrypt",
|
"RC2 Decrypt",
|
||||||
"RC4",
|
"RC4",
|
||||||
"RC4 Drop",
|
"RC4 Drop",
|
||||||
|
"ChaCha",
|
||||||
|
"Rabbit",
|
||||||
"SM4 Encrypt",
|
"SM4 Encrypt",
|
||||||
"SM4 Decrypt",
|
"SM4 Decrypt",
|
||||||
"ROT13",
|
"ROT13",
|
||||||
|
@ -124,6 +128,8 @@
|
||||||
"JWT Decode",
|
"JWT Decode",
|
||||||
"Citrix CTX1 Encode",
|
"Citrix CTX1 Encode",
|
||||||
"Citrix CTX1 Decode",
|
"Citrix CTX1 Decode",
|
||||||
|
"AES Key Wrap",
|
||||||
|
"AES Key Unwrap",
|
||||||
"Pseudo-Random Number Generator",
|
"Pseudo-Random Number Generator",
|
||||||
"Enigma",
|
"Enigma",
|
||||||
"Bombe",
|
"Bombe",
|
||||||
|
@ -250,6 +256,7 @@
|
||||||
"To Table",
|
"To Table",
|
||||||
"Reverse",
|
"Reverse",
|
||||||
"Sort",
|
"Sort",
|
||||||
|
"Shuffle",
|
||||||
"Unique",
|
"Unique",
|
||||||
"Split",
|
"Split",
|
||||||
"Filter",
|
"Filter",
|
||||||
|
@ -331,8 +338,12 @@
|
||||||
"Bzip2 Compress",
|
"Bzip2 Compress",
|
||||||
"Tar",
|
"Tar",
|
||||||
"Untar",
|
"Untar",
|
||||||
|
"LZString Decompress",
|
||||||
"LZString Compress",
|
"LZString Compress",
|
||||||
"LZString Decompress"
|
"LZMA Decompress",
|
||||||
|
"LZMA Compress",
|
||||||
|
"LZ4 Decompress",
|
||||||
|
"LZ4 Compress"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -364,10 +375,13 @@
|
||||||
"Compare SSDEEP hashes",
|
"Compare SSDEEP hashes",
|
||||||
"Compare CTPH hashes",
|
"Compare CTPH hashes",
|
||||||
"HMAC",
|
"HMAC",
|
||||||
|
"CMAC",
|
||||||
"Bcrypt",
|
"Bcrypt",
|
||||||
"Bcrypt compare",
|
"Bcrypt compare",
|
||||||
"Bcrypt parse",
|
"Bcrypt parse",
|
||||||
"Scrypt",
|
"Scrypt",
|
||||||
|
"NT Hash",
|
||||||
|
"LM Hash",
|
||||||
"Fletcher-8 Checksum",
|
"Fletcher-8 Checksum",
|
||||||
"Fletcher-16 Checksum",
|
"Fletcher-16 Checksum",
|
||||||
"Fletcher-32 Checksum",
|
"Fletcher-32 Checksum",
|
||||||
|
|
|
@ -136,7 +136,7 @@ const getFeature = function() {
|
||||||
|
|
||||||
fs.writeFileSync(path.join(process.cwd(), "CHANGELOG.md"), changelogData);
|
fs.writeFileSync(path.join(process.cwd(), "CHANGELOG.md"), changelogData);
|
||||||
|
|
||||||
console.log("Written CHANGELOG.md");
|
console.log("Written CHANGELOG.md\nCommit changes and then run `npm version minor`.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -105,13 +105,17 @@ export function fromHex(data, delim="Auto", byteLen=2) {
|
||||||
throw new OperationError("Byte length must be a positive integer");
|
throw new OperationError("Byte length must be a positive integer");
|
||||||
|
|
||||||
if (delim !== "None") {
|
if (delim !== "None") {
|
||||||
const delimRegex = delim === "Auto" ? /[^a-f\d]|(0x)/gi : Utils.regexRep(delim);
|
const delimRegex = delim === "Auto" ? /[^a-f\d]|0x/gi : Utils.regexRep(delim);
|
||||||
data = data.replace(delimRegex, "");
|
data = data.split(delimRegex);
|
||||||
|
} else {
|
||||||
|
data = [data];
|
||||||
}
|
}
|
||||||
|
|
||||||
const output = [];
|
const output = [];
|
||||||
for (let i = 0; i < data.length; i += byteLen) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
output.push(parseInt(data.substr(i, byteLen), 16));
|
for (let j = 0; j < data[i].length; j += byteLen) {
|
||||||
|
output.push(parseInt(data[i].substr(j, byteLen), 16));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,3 +103,15 @@ export function hexadecimalSort(a, b) {
|
||||||
|
|
||||||
return a.localeCompare(b);
|
return a.localeCompare(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comparison operation for sorting by length
|
||||||
|
*
|
||||||
|
* @param {string} a
|
||||||
|
* @param {string} b
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
export function lengthSort(a, b) {
|
||||||
|
return a.length - b.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
128
src/core/operations/AESKeyUnwrap.mjs
Normal file
128
src/core/operations/AESKeyUnwrap.mjs
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import { toHexFast } from "../lib/Hex.mjs";
|
||||||
|
import forge from "node-forge";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES Key Unwrap operation
|
||||||
|
*/
|
||||||
|
class AESKeyUnwrap extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AESKeyUnwrap constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "AES Key Unwrap";
|
||||||
|
this.module = "Ciphers";
|
||||||
|
this.description = "Decryptor for a key wrapping algorithm defined in RFC3394, which is used to protect keys in untrusted storage or communications, using AES.<br><br>This algorithm uses an AES key (KEK: key-encryption key) and a 64-bit IV to decrypt 64-bit blocks.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Key_wrap";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Key (KEK)",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "IV",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "a6a6a6a6a6a6a6a6",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Input",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Hex", "Raw"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Output",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Hex", "Raw"]
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const kek = Utils.convertToByteString(args[0].string, args[0].option),
|
||||||
|
iv = Utils.convertToByteString(args[1].string, args[1].option),
|
||||||
|
inputType = args[2],
|
||||||
|
outputType = args[3];
|
||||||
|
|
||||||
|
if (kek.length !== 16 && kek.length !== 24 && kek.length !== 32) {
|
||||||
|
throw new OperationError("KEK must be either 16, 24, or 32 bytes (currently " + kek.length + " bytes)");
|
||||||
|
}
|
||||||
|
if (iv.length !== 8) {
|
||||||
|
throw new OperationError("IV must be 8 bytes (currently " + iv.length + " bytes)");
|
||||||
|
}
|
||||||
|
const inputData = Utils.convertToByteString(input, inputType);
|
||||||
|
if (inputData.length % 8 !== 0 || inputData.length < 24) {
|
||||||
|
throw new OperationError("input must be 8n (n>=3) bytes (currently " + inputData.length + " bytes)");
|
||||||
|
}
|
||||||
|
|
||||||
|
const cipher = forge.cipher.createCipher("AES-ECB", kek);
|
||||||
|
cipher.start();
|
||||||
|
cipher.update(forge.util.createBuffer(""));
|
||||||
|
cipher.finish();
|
||||||
|
const paddingBlock = cipher.output.getBytes();
|
||||||
|
|
||||||
|
const decipher = forge.cipher.createDecipher("AES-ECB", kek);
|
||||||
|
|
||||||
|
let A = inputData.substring(0, 8);
|
||||||
|
const R = [];
|
||||||
|
for (let i = 8; i < inputData.length; i += 8) {
|
||||||
|
R.push(inputData.substring(i, i + 8));
|
||||||
|
}
|
||||||
|
let cntLower = R.length >>> 0;
|
||||||
|
let cntUpper = (R.length / ((1 << 30) * 4)) >>> 0;
|
||||||
|
cntUpper = cntUpper * 6 + ((cntLower * 6 / ((1 << 30) * 4)) >>> 0);
|
||||||
|
cntLower = cntLower * 6 >>> 0;
|
||||||
|
for (let j = 5; j >= 0; j--) {
|
||||||
|
for (let i = R.length - 1; i >= 0; i--) {
|
||||||
|
const aBuffer = Utils.strToArrayBuffer(A);
|
||||||
|
const aView = new DataView(aBuffer);
|
||||||
|
aView.setUint32(0, aView.getUint32(0) ^ cntUpper);
|
||||||
|
aView.setUint32(4, aView.getUint32(4) ^ cntLower);
|
||||||
|
A = Utils.arrayBufferToStr(aBuffer, false);
|
||||||
|
decipher.start();
|
||||||
|
decipher.update(forge.util.createBuffer(A + R[i] + paddingBlock));
|
||||||
|
decipher.finish();
|
||||||
|
const B = decipher.output.getBytes();
|
||||||
|
A = B.substring(0, 8);
|
||||||
|
R[i] = B.substring(8, 16);
|
||||||
|
cntLower--;
|
||||||
|
if (cntLower < 0) {
|
||||||
|
cntUpper--;
|
||||||
|
cntLower = 0xffffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (A !== iv) {
|
||||||
|
throw new OperationError("IV mismatch");
|
||||||
|
}
|
||||||
|
const P = R.join("");
|
||||||
|
|
||||||
|
if (outputType === "Hex") {
|
||||||
|
return toHexFast(Utils.strToArrayBuffer(P));
|
||||||
|
}
|
||||||
|
return P;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AESKeyUnwrap;
|
115
src/core/operations/AESKeyWrap.mjs
Normal file
115
src/core/operations/AESKeyWrap.mjs
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import { toHexFast } from "../lib/Hex.mjs";
|
||||||
|
import forge from "node-forge";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES Key Wrap operation
|
||||||
|
*/
|
||||||
|
class AESKeyWrap extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AESKeyWrap constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "AES Key Wrap";
|
||||||
|
this.module = "Ciphers";
|
||||||
|
this.description = "A key wrapping algorithm defined in RFC3394, which is used to protect keys in untrusted storage or communications, using AES.<br><br>This algorithm uses an AES key (KEK: key-encryption key) and a 64-bit IV to encrypt 64-bit blocks.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Key_wrap";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Key (KEK)",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "IV",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "a6a6a6a6a6a6a6a6",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Input",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Hex", "Raw"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Output",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Hex", "Raw"]
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const kek = Utils.convertToByteString(args[0].string, args[0].option),
|
||||||
|
iv = Utils.convertToByteString(args[1].string, args[1].option),
|
||||||
|
inputType = args[2],
|
||||||
|
outputType = args[3];
|
||||||
|
|
||||||
|
if (kek.length !== 16 && kek.length !== 24 && kek.length !== 32) {
|
||||||
|
throw new OperationError("KEK must be either 16, 24, or 32 bytes (currently " + kek.length + " bytes)");
|
||||||
|
}
|
||||||
|
if (iv.length !== 8) {
|
||||||
|
throw new OperationError("IV must be 8 bytes (currently " + iv.length + " bytes)");
|
||||||
|
}
|
||||||
|
const inputData = Utils.convertToByteString(input, inputType);
|
||||||
|
if (inputData.length % 8 !== 0 || inputData.length < 16) {
|
||||||
|
throw new OperationError("input must be 8n (n>=2) bytes (currently " + inputData.length + " bytes)");
|
||||||
|
}
|
||||||
|
|
||||||
|
const cipher = forge.cipher.createCipher("AES-ECB", kek);
|
||||||
|
|
||||||
|
let A = iv;
|
||||||
|
const R = [];
|
||||||
|
for (let i = 0; i < inputData.length; i += 8) {
|
||||||
|
R.push(inputData.substring(i, i + 8));
|
||||||
|
}
|
||||||
|
let cntLower = 1, cntUpper = 0;
|
||||||
|
for (let j = 0; j < 6; j++) {
|
||||||
|
for (let i = 0; i < R.length; i++) {
|
||||||
|
cipher.start();
|
||||||
|
cipher.update(forge.util.createBuffer(A + R[i]));
|
||||||
|
cipher.finish();
|
||||||
|
const B = cipher.output.getBytes();
|
||||||
|
const msbBuffer = Utils.strToArrayBuffer(B.substring(0, 8));
|
||||||
|
const msbView = new DataView(msbBuffer);
|
||||||
|
msbView.setUint32(0, msbView.getUint32(0) ^ cntUpper);
|
||||||
|
msbView.setUint32(4, msbView.getUint32(4) ^ cntLower);
|
||||||
|
A = Utils.arrayBufferToStr(msbBuffer, false);
|
||||||
|
R[i] = B.substring(8, 16);
|
||||||
|
cntLower++;
|
||||||
|
if (cntLower > 0xffffffff) {
|
||||||
|
cntUpper++;
|
||||||
|
cntLower = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const C = A + R.join("");
|
||||||
|
|
||||||
|
if (outputType === "Hex") {
|
||||||
|
return toHexFast(Utils.strToArrayBuffer(C));
|
||||||
|
}
|
||||||
|
return C;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AESKeyWrap;
|
52
src/core/operations/AMFDecode.mjs
Normal file
52
src/core/operations/AMFDecode.mjs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import "reflect-metadata"; // Required as a shim for the amf library
|
||||||
|
import { AMF0, AMF3 } from "@astronautlabs/amf";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMF Decode operation
|
||||||
|
*/
|
||||||
|
class AMFDecode extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMFDecode constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "AMF Decode";
|
||||||
|
this.module = "Encodings";
|
||||||
|
this.description = "Action Message Format (AMF) is a binary format used to serialize object graphs such as ActionScript objects and XML, or send messages between an Adobe Flash client and a remote service, usually a Flash Media Server or third party alternatives.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Action_Message_Format";
|
||||||
|
this.inputType = "ArrayBuffer";
|
||||||
|
this.outputType = "JSON";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Format",
|
||||||
|
type: "option",
|
||||||
|
value: ["AMF0", "AMF3"],
|
||||||
|
defaultIndex: 1
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {JSON}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const [format] = args;
|
||||||
|
const handler = format === "AMF0" ? AMF0 : AMF3;
|
||||||
|
const encoded = new Uint8Array(input);
|
||||||
|
return handler.Value.deserialize(encoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AMFDecode;
|
52
src/core/operations/AMFEncode.mjs
Normal file
52
src/core/operations/AMFEncode.mjs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import "reflect-metadata"; // Required as a shim for the amf library
|
||||||
|
import { AMF0, AMF3 } from "@astronautlabs/amf";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMF Encode operation
|
||||||
|
*/
|
||||||
|
class AMFEncode extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMFEncode constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "AMF Encode";
|
||||||
|
this.module = "Encodings";
|
||||||
|
this.description = "Action Message Format (AMF) is a binary format used to serialize object graphs such as ActionScript objects and XML, or send messages between an Adobe Flash client and a remote service, usually a Flash Media Server or third party alternatives.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Action_Message_Format";
|
||||||
|
this.inputType = "JSON";
|
||||||
|
this.outputType = "ArrayBuffer";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Format",
|
||||||
|
type: "option",
|
||||||
|
value: ["AMF0", "AMF3"],
|
||||||
|
defaultIndex: 1
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {JSON} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {ArrayBuffer}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const [format] = args;
|
||||||
|
const handler = format === "AMF0" ? AMF0 : AMF3;
|
||||||
|
const output = handler.Value.any(input).serialize();
|
||||||
|
return output.buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AMFEncode;
|
149
src/core/operations/CMAC.mjs
Normal file
149
src/core/operations/CMAC.mjs
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import forge from "node-forge";
|
||||||
|
import { toHexFast } from "../lib/Hex.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CMAC operation
|
||||||
|
*/
|
||||||
|
class CMAC extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CMAC constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "CMAC";
|
||||||
|
this.module = "Crypto";
|
||||||
|
this.description = "CMAC is a block-cipher based message authentication code algorithm.<br><br>RFC4493 defines AES-CMAC that uses AES encryption with a 128-bit key.<br>NIST SP 800-38B suggests usages of AES with other key lengths and Triple DES.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/CMAC";
|
||||||
|
this.inputType = "ArrayBuffer";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Key",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Encryption algorithm",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["AES", "Triple DES"]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const key = Utils.convertToByteString(args[0].string, args[0].option);
|
||||||
|
const algo = args[1];
|
||||||
|
|
||||||
|
const info = (function() {
|
||||||
|
switch (algo) {
|
||||||
|
case "AES":
|
||||||
|
if (key.length !== 16 && key.length !== 24 && key.length !== 32) {
|
||||||
|
throw new OperationError("The key for AES must be either 16, 24, or 32 bytes (currently " + key.length + " bytes)");
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
"algorithm": "AES-ECB",
|
||||||
|
"key": key,
|
||||||
|
"blockSize": 16,
|
||||||
|
"Rb": new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x87]),
|
||||||
|
};
|
||||||
|
case "Triple DES":
|
||||||
|
if (key.length !== 16 && key.length !== 24) {
|
||||||
|
throw new OperationError("The key for Triple DES must be 16 or 24 bytes (currently " + key.length + " bytes)");
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
"algorithm": "3DES-ECB",
|
||||||
|
"key": key.length === 16 ? key + key.substring(0, 8) : key,
|
||||||
|
"blockSize": 8,
|
||||||
|
"Rb": new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0x1b]),
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
throw new OperationError("Undefined encryption algorithm");
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
const xor = function(a, b, out) {
|
||||||
|
if (!out) out = new Uint8Array(a.length);
|
||||||
|
for (let i = 0; i < a.length; i++) {
|
||||||
|
out[i] = a[i] ^ b[i];
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
const leftShift1 = function(a) {
|
||||||
|
const out = new Uint8Array(a.length);
|
||||||
|
let carry = 0;
|
||||||
|
for (let i = a.length - 1; i >= 0; i--) {
|
||||||
|
out[i] = (a[i] << 1) | carry;
|
||||||
|
carry = a[i] >> 7;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
const cipher = forge.cipher.createCipher(info.algorithm, info.key);
|
||||||
|
const encrypt = function(a, out) {
|
||||||
|
if (!out) out = new Uint8Array(a.length);
|
||||||
|
cipher.start();
|
||||||
|
cipher.update(forge.util.createBuffer(a));
|
||||||
|
cipher.finish();
|
||||||
|
const cipherText = cipher.output.getBytes();
|
||||||
|
for (let i = 0; i < a.length; i++) {
|
||||||
|
out[i] = cipherText.charCodeAt(i);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
const L = encrypt(new Uint8Array(info.blockSize));
|
||||||
|
const K1 = leftShift1(L);
|
||||||
|
if (L[0] & 0x80) xor(K1, info.Rb, K1);
|
||||||
|
const K2 = leftShift1(K1);
|
||||||
|
if (K1[0] & 0x80) xor(K2, info.Rb, K2);
|
||||||
|
|
||||||
|
const n = Math.ceil(input.byteLength / info.blockSize);
|
||||||
|
const lastBlock = (function() {
|
||||||
|
if (n === 0) {
|
||||||
|
const data = new Uint8Array(K2);
|
||||||
|
data[0] ^= 0x80;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
const inputLast = new Uint8Array(input, info.blockSize * (n - 1));
|
||||||
|
if (inputLast.length === info.blockSize) {
|
||||||
|
return xor(inputLast, K1, inputLast);
|
||||||
|
} else {
|
||||||
|
const data = new Uint8Array(info.blockSize);
|
||||||
|
data.set(inputLast, 0);
|
||||||
|
data[inputLast.length] = 0x80;
|
||||||
|
return xor(data, K2, data);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
const X = new Uint8Array(info.blockSize);
|
||||||
|
const Y = new Uint8Array(info.blockSize);
|
||||||
|
for (let i = 0; i < n - 1; i++) {
|
||||||
|
xor(X, new Uint8Array(input, info.blockSize * i, info.blockSize), Y);
|
||||||
|
encrypt(Y, X);
|
||||||
|
}
|
||||||
|
xor(lastBlock, X, Y);
|
||||||
|
const T = encrypt(Y);
|
||||||
|
return toHexFast(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CMAC;
|
234
src/core/operations/ChaCha.mjs
Normal file
234
src/core/operations/ChaCha.mjs
Normal file
|
@ -0,0 +1,234 @@
|
||||||
|
/**
|
||||||
|
* @author joostrijneveld [joost@joostrijneveld.nl]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import { toHex } from "../lib/Hex.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the ChaCha block function
|
||||||
|
*
|
||||||
|
* @param {byteArray} key
|
||||||
|
* @param {byteArray} nonce
|
||||||
|
* @param {byteArray} counter
|
||||||
|
* @param {integer} rounds
|
||||||
|
* @returns {byteArray}
|
||||||
|
*/
|
||||||
|
function chacha(key, nonce, counter, rounds) {
|
||||||
|
const tau = "expand 16-byte k";
|
||||||
|
const sigma = "expand 32-byte k";
|
||||||
|
|
||||||
|
let state, c;
|
||||||
|
if (key.length === 16) {
|
||||||
|
c = Utils.strToByteArray(tau);
|
||||||
|
state = c.concat(key).concat(key);
|
||||||
|
} else {
|
||||||
|
c = Utils.strToByteArray(sigma);
|
||||||
|
state = c.concat(key);
|
||||||
|
}
|
||||||
|
state = state.concat(counter).concat(nonce);
|
||||||
|
|
||||||
|
const x = Array();
|
||||||
|
for (let i = 0; i < 64; i += 4) {
|
||||||
|
x.push(Utils.byteArrayToInt(state.slice(i, i + 4), "little"));
|
||||||
|
}
|
||||||
|
const a = [...x];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Macro to compute a 32-bit rotate-left operation
|
||||||
|
*
|
||||||
|
* @param {integer} x
|
||||||
|
* @param {integer} n
|
||||||
|
* @returns {integer}
|
||||||
|
*/
|
||||||
|
function ROL32(x, n) {
|
||||||
|
return ((x << n) & 0xFFFFFFFF) | (x >>> (32 - n));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Macro to compute a single ChaCha quarterround operation
|
||||||
|
*
|
||||||
|
* @param {integer} x
|
||||||
|
* @param {integer} a
|
||||||
|
* @param {integer} b
|
||||||
|
* @param {integer} c
|
||||||
|
* @param {integer} d
|
||||||
|
* @returns {integer}
|
||||||
|
*/
|
||||||
|
function quarterround(x, a, b, c, d) {
|
||||||
|
x[a] = ((x[a] + x[b]) & 0xFFFFFFFF); x[d] = ROL32(x[d] ^ x[a], 16);
|
||||||
|
x[c] = ((x[c] + x[d]) & 0xFFFFFFFF); x[b] = ROL32(x[b] ^ x[c], 12);
|
||||||
|
x[a] = ((x[a] + x[b]) & 0xFFFFFFFF); x[d] = ROL32(x[d] ^ x[a], 8);
|
||||||
|
x[c] = ((x[c] + x[d]) & 0xFFFFFFFF); x[b] = ROL32(x[b] ^ x[c], 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < rounds / 2; i++) {
|
||||||
|
quarterround(x, 0, 4, 8, 12);
|
||||||
|
quarterround(x, 1, 5, 9, 13);
|
||||||
|
quarterround(x, 2, 6, 10, 14);
|
||||||
|
quarterround(x, 3, 7, 11, 15);
|
||||||
|
quarterround(x, 0, 5, 10, 15);
|
||||||
|
quarterround(x, 1, 6, 11, 12);
|
||||||
|
quarterround(x, 2, 7, 8, 13);
|
||||||
|
quarterround(x, 3, 4, 9, 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < 16; i++) {
|
||||||
|
x[i] = (x[i] + a[i]) & 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = Array();
|
||||||
|
for (let i = 0; i < 16; i++) {
|
||||||
|
output = output.concat(Utils.intToByteArray(x[i], 4, "little"));
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ChaCha operation
|
||||||
|
*/
|
||||||
|
class ChaCha extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ChaCha constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "ChaCha";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "ChaCha is a stream cipher designed by Daniel J. Bernstein. It is a variant of the Salsa stream cipher. Several parameterizations exist; 'ChaCha' may refer to the original construction, or to the variant as described in RFC-8439. ChaCha is often used with Poly1305, in the ChaCha20-Poly1305 AEAD construction.<br><br><b>Key:</b> ChaCha uses a key of 16 or 32 bytes (128 or 256 bits).<br><br><b>Nonce:</b> ChaCha uses a nonce of 8 or 12 bytes (64 or 96 bits).<br><br><b>Counter:</b> ChaCha uses a counter of 4 or 8 bytes (32 or 64 bits); together, the nonce and counter must add up to 16 bytes. The counter starts at zero at the start of the keystream, and is incremented at every 64 bytes.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Salsa20#ChaCha_variant";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Key",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Nonce",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64", "Integer"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Counter",
|
||||||
|
"type": "number",
|
||||||
|
"value": 0,
|
||||||
|
"min": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Rounds",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["20", "12", "8"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Input",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Hex", "Raw"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Output",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Raw", "Hex"]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const key = Utils.convertToByteArray(args[0].string, args[0].option),
|
||||||
|
nonceType = args[1].option,
|
||||||
|
rounds = parseInt(args[3], 10),
|
||||||
|
inputType = args[4],
|
||||||
|
outputType = args[5];
|
||||||
|
|
||||||
|
if (key.length !== 16 && key.length !== 32) {
|
||||||
|
throw new OperationError(`Invalid key length: ${key.length} bytes.
|
||||||
|
|
||||||
|
ChaCha uses a key of 16 or 32 bytes (128 or 256 bits).`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let counter, nonce, counterLength;
|
||||||
|
if (nonceType === "Integer") {
|
||||||
|
nonce = Utils.intToByteArray(parseInt(args[1].string, 10), 12, "little");
|
||||||
|
counterLength = 4;
|
||||||
|
} else {
|
||||||
|
nonce = Utils.convertToByteArray(args[1].string, args[1].option);
|
||||||
|
if (!(nonce.length === 12 || nonce.length === 8)) {
|
||||||
|
throw new OperationError(`Invalid nonce length: ${nonce.length} bytes.
|
||||||
|
|
||||||
|
ChaCha uses a nonce of 8 or 12 bytes (64 or 96 bits).`);
|
||||||
|
}
|
||||||
|
counterLength = 16 - nonce.length;
|
||||||
|
}
|
||||||
|
counter = Utils.intToByteArray(args[2], counterLength, "little");
|
||||||
|
|
||||||
|
const output = [];
|
||||||
|
input = Utils.convertToByteArray(input, inputType);
|
||||||
|
|
||||||
|
let counterAsInt = Utils.byteArrayToInt(counter, "little");
|
||||||
|
for (let i = 0; i < input.length; i += 64) {
|
||||||
|
counter = Utils.intToByteArray(counterAsInt, counterLength, "little");
|
||||||
|
const stream = chacha(key, nonce, counter, rounds);
|
||||||
|
for (let j = 0; j < 64 && i + j < input.length; j++) {
|
||||||
|
output.push(input[i + j] ^ stream[j]);
|
||||||
|
}
|
||||||
|
counterAsInt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outputType === "Hex") {
|
||||||
|
return toHex(output);
|
||||||
|
} else {
|
||||||
|
return Utils.arrayBufferToStr(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlight ChaCha
|
||||||
|
*
|
||||||
|
* @param {Object[]} pos
|
||||||
|
* @param {number} pos[].start
|
||||||
|
* @param {number} pos[].end
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {Object[]} pos
|
||||||
|
*/
|
||||||
|
highlight(pos, args) {
|
||||||
|
const inputType = args[4],
|
||||||
|
outputType = args[5];
|
||||||
|
if (inputType === "Raw" && outputType === "Raw") {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlight ChaCha in reverse
|
||||||
|
*
|
||||||
|
* @param {Object[]} pos
|
||||||
|
* @param {number} pos[].start
|
||||||
|
* @param {number} pos[].end
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {Object[]} pos
|
||||||
|
*/
|
||||||
|
highlightReverse(pos, args) {
|
||||||
|
const inputType = args[4],
|
||||||
|
outputType = args[5];
|
||||||
|
if (inputType === "Raw" && outputType === "Raw") {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ChaCha;
|
|
@ -51,10 +51,27 @@ class DNSOverHTTPS extends Operation {
|
||||||
value: [
|
value: [
|
||||||
"A",
|
"A",
|
||||||
"AAAA",
|
"AAAA",
|
||||||
"TXT",
|
"ANAME",
|
||||||
"MX",
|
"CERT",
|
||||||
|
"CNAME",
|
||||||
"DNSKEY",
|
"DNSKEY",
|
||||||
"NS"
|
"HTTPS",
|
||||||
|
"IPSECKEY",
|
||||||
|
"LOC",
|
||||||
|
"MX",
|
||||||
|
"NS",
|
||||||
|
"OPENPGPKEY",
|
||||||
|
"PTR",
|
||||||
|
"RRSIG",
|
||||||
|
"SIG",
|
||||||
|
"SOA",
|
||||||
|
"SPF",
|
||||||
|
"SRV",
|
||||||
|
"SSHFP",
|
||||||
|
"TA",
|
||||||
|
"TXT",
|
||||||
|
"URI",
|
||||||
|
"ANY"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,10 +35,18 @@ class Fletcher32Checksum extends Operation {
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
let a = 0,
|
let a = 0,
|
||||||
b = 0;
|
b = 0;
|
||||||
input = new Uint8Array(input);
|
if (ArrayBuffer.isView(input)) {
|
||||||
|
input = new DataView(input.buffer, input.byteOffset, input.byteLength);
|
||||||
|
} else {
|
||||||
|
input = new DataView(input);
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.byteLength - 1; i += 2) {
|
||||||
a = (a + input[i]) % 0xffff;
|
a = (a + input.getUint16(i, true)) % 0xffff;
|
||||||
|
b = (b + a) % 0xffff;
|
||||||
|
}
|
||||||
|
if (input.byteLength % 2 !== 0) {
|
||||||
|
a = (a + input.getUint8(input.byteLength - 1)) % 0xffff;
|
||||||
b = (b + a) % 0xffff;
|
b = (b + a) % 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,22 @@ class Fletcher64Checksum extends Operation {
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
let a = 0,
|
let a = 0,
|
||||||
b = 0;
|
b = 0;
|
||||||
input = new Uint8Array(input);
|
if (ArrayBuffer.isView(input)) {
|
||||||
|
input = new DataView(input.buffer, input.byteOffset, input.byteLength);
|
||||||
|
} else {
|
||||||
|
input = new DataView(input);
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.byteLength - 3; i += 4) {
|
||||||
a = (a + input[i]) % 0xffffffff;
|
a = (a + input.getUint32(i, true)) % 0xffffffff;
|
||||||
|
b = (b + a) % 0xffffffff;
|
||||||
|
}
|
||||||
|
if (input.byteLength % 4 !== 0) {
|
||||||
|
let lastValue = 0;
|
||||||
|
for (let i = 0; i < input.byteLength % 4; i++) {
|
||||||
|
lastValue = (lastValue << 8) | input.getUint8(input.byteLength - 1 - i);
|
||||||
|
}
|
||||||
|
a = (a + lastValue) % 0xffffffff;
|
||||||
b = (b + a) % 0xffffffff;
|
b = (b + a) % 0xffffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import {alphabetName, ALPHABET_OPTIONS} from "../lib/Base85.mjs";
|
import {ALPHABET_OPTIONS} from "../lib/Base85.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* From Base85 operation
|
* From Base85 operation
|
||||||
|
@ -37,6 +37,12 @@ class FromBase85 extends Operation {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: true
|
value: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "All-zero group char",
|
||||||
|
type: "binaryShortString",
|
||||||
|
value: "z",
|
||||||
|
maxLength: 1
|
||||||
|
}
|
||||||
];
|
];
|
||||||
this.checks = [
|
this.checks = [
|
||||||
{
|
{
|
||||||
|
@ -76,8 +82,8 @@ class FromBase85 extends Operation {
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const alphabet = Utils.expandAlphRange(args[0]).join(""),
|
const alphabet = Utils.expandAlphRange(args[0]).join(""),
|
||||||
encoding = alphabetName(alphabet),
|
|
||||||
removeNonAlphChars = args[1],
|
removeNonAlphChars = args[1],
|
||||||
|
allZeroGroupChar = typeof args[2] === "string" ? args[2].slice(0, 1) : "",
|
||||||
result = [];
|
result = [];
|
||||||
|
|
||||||
if (alphabet.length !== 85 ||
|
if (alphabet.length !== 85 ||
|
||||||
|
@ -85,14 +91,21 @@ class FromBase85 extends Operation {
|
||||||
throw new OperationError("Alphabet must be of length 85");
|
throw new OperationError("Alphabet must be of length 85");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allZeroGroupChar && alphabet.includes(allZeroGroupChar)) {
|
||||||
|
throw new OperationError("The all-zero group char cannot appear in the alphabet");
|
||||||
|
}
|
||||||
|
|
||||||
// Remove delimiters if present
|
// Remove delimiters if present
|
||||||
const matches = input.match(/^<~(.+?)~>$/);
|
const matches = input.match(/^<~(.+?)~>$/);
|
||||||
if (matches !== null) input = matches[1];
|
if (matches !== null) input = matches[1];
|
||||||
|
|
||||||
// Remove non-alphabet characters
|
// Remove non-alphabet characters
|
||||||
if (removeNonAlphChars) {
|
if (removeNonAlphChars) {
|
||||||
const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
|
const re = new RegExp("[^~" + allZeroGroupChar +alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
|
||||||
input = input.replace(re, "");
|
input = input.replace(re, "");
|
||||||
|
// Remove delimiters again if present (incase of non-alphabet characters in front/behind delimiters)
|
||||||
|
const matches = input.match(/^<~(.+?)~>$/);
|
||||||
|
if (matches !== null) input = matches[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.length === 0) return [];
|
if (input.length === 0) return [];
|
||||||
|
@ -100,7 +113,7 @@ class FromBase85 extends Operation {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let block, blockBytes;
|
let block, blockBytes;
|
||||||
while (i < input.length) {
|
while (i < input.length) {
|
||||||
if (encoding === "Standard" && input[i] === "z") {
|
if (input[i] === allZeroGroupChar) {
|
||||||
result.push(0, 0, 0, 0);
|
result.push(0, 0, 0, 0);
|
||||||
i++;
|
i++;
|
||||||
} else {
|
} else {
|
||||||
|
@ -110,7 +123,7 @@ class FromBase85 extends Operation {
|
||||||
.split("")
|
.split("")
|
||||||
.map((chr, idx) => {
|
.map((chr, idx) => {
|
||||||
const digit = alphabet.indexOf(chr);
|
const digit = alphabet.indexOf(chr);
|
||||||
if (digit < 0 || digit > 84) {
|
if ((digit < 0 || digit > 84) && chr !== allZeroGroupChar) {
|
||||||
throw `Invalid character '${chr}' at index ${i + idx}`;
|
throw `Invalid character '${chr}' at index ${i + idx}`;
|
||||||
}
|
}
|
||||||
return digit;
|
return digit;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* @author n1474335 [n1474335@gmail.com]
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @author john19696 [john19696@protonmail.com]
|
||||||
* @copyright Crown Copyright 2016
|
* @copyright Crown Copyright 2016
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
@ -33,6 +34,9 @@ import BLAKE2b from "./BLAKE2b.mjs";
|
||||||
import BLAKE2s from "./BLAKE2s.mjs";
|
import BLAKE2s from "./BLAKE2s.mjs";
|
||||||
import Streebog from "./Streebog.mjs";
|
import Streebog from "./Streebog.mjs";
|
||||||
import GOSTHash from "./GOSTHash.mjs";
|
import GOSTHash from "./GOSTHash.mjs";
|
||||||
|
import LMHash from "./LMHash.mjs";
|
||||||
|
import NTHash from "./NTHash.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate all hashes operation
|
* Generate all hashes operation
|
||||||
|
@ -51,7 +55,75 @@ class GenerateAllHashes extends Operation {
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Comparison_of_cryptographic_hash_functions";
|
this.infoURL = "https://wikipedia.org/wiki/Comparison_of_cryptographic_hash_functions";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "ArrayBuffer";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [];
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Length (bits)",
|
||||||
|
type: "option",
|
||||||
|
value: [
|
||||||
|
"All", "128", "160", "224", "256", "320", "384", "512"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Include names",
|
||||||
|
type: "boolean",
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
];
|
||||||
|
this.hashes = [
|
||||||
|
{name: "MD2", algo: (new MD2()), inputType: "arrayBuffer", params: []},
|
||||||
|
{name: "MD4", algo: (new MD4()), inputType: "arrayBuffer", params: []},
|
||||||
|
{name: "MD5", algo: (new MD5()), inputType: "arrayBuffer", params: []},
|
||||||
|
{name: "MD6", algo: (new MD6()), inputType: "str", params: []},
|
||||||
|
{name: "SHA0", algo: (new SHA0()), inputType: "arrayBuffer", params: []},
|
||||||
|
{name: "SHA1", algo: (new SHA1()), inputType: "arrayBuffer", params: []},
|
||||||
|
{name: "SHA2 224", algo: (new SHA2()), inputType: "arrayBuffer", params: ["224"]},
|
||||||
|
{name: "SHA2 256", algo: (new SHA2()), inputType: "arrayBuffer", params: ["256"]},
|
||||||
|
{name: "SHA2 384", algo: (new SHA2()), inputType: "arrayBuffer", params: ["384"]},
|
||||||
|
{name: "SHA2 512", algo: (new SHA2()), inputType: "arrayBuffer", params: ["512"]},
|
||||||
|
{name: "SHA3 224", algo: (new SHA3()), inputType: "arrayBuffer", params: ["224"]},
|
||||||
|
{name: "SHA3 256", algo: (new SHA3()), inputType: "arrayBuffer", params: ["256"]},
|
||||||
|
{name: "SHA3 384", algo: (new SHA3()), inputType: "arrayBuffer", params: ["384"]},
|
||||||
|
{name: "SHA3 512", algo: (new SHA3()), inputType: "arrayBuffer", params: ["512"]},
|
||||||
|
{name: "Keccak 224", algo: (new Keccak()), inputType: "arrayBuffer", params: ["224"]},
|
||||||
|
{name: "Keccak 256", algo: (new Keccak()), inputType: "arrayBuffer", params: ["256"]},
|
||||||
|
{name: "Keccak 384", algo: (new Keccak()), inputType: "arrayBuffer", params: ["384"]},
|
||||||
|
{name: "Keccak 512", algo: (new Keccak()), inputType: "arrayBuffer", params: ["512"]},
|
||||||
|
{name: "Shake 128", algo: (new Shake()), inputType: "arrayBuffer", params: ["128", 256]},
|
||||||
|
{name: "Shake 256", algo: (new Shake()), inputType: "arrayBuffer", params: ["256", 512]},
|
||||||
|
{name: "RIPEMD-128", algo: (new RIPEMD()), inputType: "arrayBuffer", params: ["128"]},
|
||||||
|
{name: "RIPEMD-160", algo: (new RIPEMD()), inputType: "arrayBuffer", params: ["160"]},
|
||||||
|
{name: "RIPEMD-256", algo: (new RIPEMD()), inputType: "arrayBuffer", params: ["256"]},
|
||||||
|
{name: "RIPEMD-320", algo: (new RIPEMD()), inputType: "arrayBuffer", params: ["320"]},
|
||||||
|
{name: "HAS-160", algo: (new HAS160()), inputType: "arrayBuffer", params: []},
|
||||||
|
{name: "Whirlpool-0", algo: (new Whirlpool()), inputType: "arrayBuffer", params: ["Whirlpool-0"]},
|
||||||
|
{name: "Whirlpool-T", algo: (new Whirlpool()), inputType: "arrayBuffer", params: ["Whirlpool-T"]},
|
||||||
|
{name: "Whirlpool", algo: (new Whirlpool()), inputType: "arrayBuffer", params: ["Whirlpool"]},
|
||||||
|
{name: "BLAKE2b-128", algo: (new BLAKE2b), inputType: "arrayBuffer", params: ["128", "Hex", {string: "", option: "UTF8"}]},
|
||||||
|
{name: "BLAKE2b-160", algo: (new BLAKE2b), inputType: "arrayBuffer", params: ["160", "Hex", {string: "", option: "UTF8"}]},
|
||||||
|
{name: "BLAKE2b-256", algo: (new BLAKE2b), inputType: "arrayBuffer", params: ["256", "Hex", {string: "", option: "UTF8"}]},
|
||||||
|
{name: "BLAKE2b-384", algo: (new BLAKE2b), inputType: "arrayBuffer", params: ["384", "Hex", {string: "", option: "UTF8"}]},
|
||||||
|
{name: "BLAKE2b-512", algo: (new BLAKE2b), inputType: "arrayBuffer", params: ["512", "Hex", {string: "", option: "UTF8"}]},
|
||||||
|
{name: "BLAKE2s-128", algo: (new BLAKE2s), inputType: "arrayBuffer", params: ["128", "Hex", {string: "", option: "UTF8"}]},
|
||||||
|
{name: "BLAKE2s-160", algo: (new BLAKE2s), inputType: "arrayBuffer", params: ["160", "Hex", {string: "", option: "UTF8"}]},
|
||||||
|
{name: "BLAKE2s-256", algo: (new BLAKE2s), inputType: "arrayBuffer", params: ["256", "Hex", {string: "", option: "UTF8"}]},
|
||||||
|
{name: "Streebog-256", algo: (new Streebog), inputType: "arrayBuffer", params: ["256"]},
|
||||||
|
{name: "Streebog-512", algo: (new Streebog), inputType: "arrayBuffer", params: ["512"]},
|
||||||
|
{name: "GOST", algo: (new GOSTHash), inputType: "arrayBuffer", params: ["D-A"]},
|
||||||
|
{name: "LM Hash", algo: (new LMHash), inputType: "str", params: []},
|
||||||
|
{name: "NT Hash", algo: (new NTHash), inputType: "str", params: []},
|
||||||
|
{name: "SSDEEP", algo: (new SSDEEP()), inputType: "str"},
|
||||||
|
{name: "CTPH", algo: (new CTPH()), inputType: "str"}
|
||||||
|
];
|
||||||
|
this.checksums = [
|
||||||
|
{name: "Fletcher-8", algo: (new Fletcher8Checksum), inputType: "byteArray", params: []},
|
||||||
|
{name: "Fletcher-16", algo: (new Fletcher16Checksum), inputType: "byteArray", params: []},
|
||||||
|
{name: "Fletcher-32", algo: (new Fletcher32Checksum), inputType: "byteArray", params: []},
|
||||||
|
{name: "Fletcher-64", algo: (new Fletcher64Checksum), inputType: "byteArray", params: []},
|
||||||
|
{name: "Adler-32", algo: (new Adler32Checksum), inputType: "byteArray", params: []},
|
||||||
|
{name: "CRC-8", algo: (new CRC8Checksum), inputType: "arrayBuffer", params: ["CRC-8"]},
|
||||||
|
{name: "CRC-16", algo: (new CRC16Checksum), inputType: "arrayBuffer", params: []},
|
||||||
|
{name: "CRC-32", algo: (new CRC32Checksum), inputType: "arrayBuffer", params: []}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,63 +132,74 @@ class GenerateAllHashes extends Operation {
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const arrayBuffer = input,
|
const [length, includeNames] = args;
|
||||||
str = Utils.arrayBufferToStr(arrayBuffer, false),
|
this.inputArrayBuffer = input;
|
||||||
byteArray = new Uint8Array(arrayBuffer),
|
this.inputStr = Utils.arrayBufferToStr(input, false);
|
||||||
output = "MD2: " + (new MD2()).run(arrayBuffer, []) +
|
this.inputByteArray = new Uint8Array(input);
|
||||||
"\nMD4: " + (new MD4()).run(arrayBuffer, []) +
|
|
||||||
"\nMD5: " + (new MD5()).run(arrayBuffer, []) +
|
let digest, output = "";
|
||||||
"\nMD6: " + (new MD6()).run(str, []) +
|
// iterate over each of the hashes
|
||||||
"\nSHA0: " + (new SHA0()).run(arrayBuffer, []) +
|
this.hashes.forEach(hash => {
|
||||||
"\nSHA1: " + (new SHA1()).run(arrayBuffer, []) +
|
digest = this.executeAlgo(hash.algo, hash.inputType, hash.params || []);
|
||||||
"\nSHA2 224: " + (new SHA2()).run(arrayBuffer, ["224"]) +
|
output += this.formatDigest(digest, length, includeNames, hash.name);
|
||||||
"\nSHA2 256: " + (new SHA2()).run(arrayBuffer, ["256"]) +
|
});
|
||||||
"\nSHA2 384: " + (new SHA2()).run(arrayBuffer, ["384"]) +
|
|
||||||
"\nSHA2 512: " + (new SHA2()).run(arrayBuffer, ["512"]) +
|
if (length === "All") {
|
||||||
"\nSHA3 224: " + (new SHA3()).run(arrayBuffer, ["224"]) +
|
output += "\nChecksums:\n";
|
||||||
"\nSHA3 256: " + (new SHA3()).run(arrayBuffer, ["256"]) +
|
this.checksums.forEach(checksum => {
|
||||||
"\nSHA3 384: " + (new SHA3()).run(arrayBuffer, ["384"]) +
|
digest = this.executeAlgo(checksum.algo, checksum.inputType, checksum.params || []);
|
||||||
"\nSHA3 512: " + (new SHA3()).run(arrayBuffer, ["512"]) +
|
output += this.formatDigest(digest, length, includeNames, checksum.name);
|
||||||
"\nKeccak 224: " + (new Keccak()).run(arrayBuffer, ["224"]) +
|
});
|
||||||
"\nKeccak 256: " + (new Keccak()).run(arrayBuffer, ["256"]) +
|
}
|
||||||
"\nKeccak 384: " + (new Keccak()).run(arrayBuffer, ["384"]) +
|
|
||||||
"\nKeccak 512: " + (new Keccak()).run(arrayBuffer, ["512"]) +
|
|
||||||
"\nShake 128: " + (new Shake()).run(arrayBuffer, ["128", 256]) +
|
|
||||||
"\nShake 256: " + (new Shake()).run(arrayBuffer, ["256", 512]) +
|
|
||||||
"\nRIPEMD-128: " + (new RIPEMD()).run(arrayBuffer, ["128"]) +
|
|
||||||
"\nRIPEMD-160: " + (new RIPEMD()).run(arrayBuffer, ["160"]) +
|
|
||||||
"\nRIPEMD-256: " + (new RIPEMD()).run(arrayBuffer, ["256"]) +
|
|
||||||
"\nRIPEMD-320: " + (new RIPEMD()).run(arrayBuffer, ["320"]) +
|
|
||||||
"\nHAS-160: " + (new HAS160()).run(arrayBuffer, []) +
|
|
||||||
"\nWhirlpool-0: " + (new Whirlpool()).run(arrayBuffer, ["Whirlpool-0"]) +
|
|
||||||
"\nWhirlpool-T: " + (new Whirlpool()).run(arrayBuffer, ["Whirlpool-T"]) +
|
|
||||||
"\nWhirlpool: " + (new Whirlpool()).run(arrayBuffer, ["Whirlpool"]) +
|
|
||||||
"\nBLAKE2b-128: " + (new BLAKE2b).run(arrayBuffer, ["128", "Hex", {string: "", option: "UTF8"}]) +
|
|
||||||
"\nBLAKE2b-160: " + (new BLAKE2b).run(arrayBuffer, ["160", "Hex", {string: "", option: "UTF8"}]) +
|
|
||||||
"\nBLAKE2b-256: " + (new BLAKE2b).run(arrayBuffer, ["256", "Hex", {string: "", option: "UTF8"}]) +
|
|
||||||
"\nBLAKE2b-384: " + (new BLAKE2b).run(arrayBuffer, ["384", "Hex", {string: "", option: "UTF8"}]) +
|
|
||||||
"\nBLAKE2b-512: " + (new BLAKE2b).run(arrayBuffer, ["512", "Hex", {string: "", option: "UTF8"}]) +
|
|
||||||
"\nBLAKE2s-128: " + (new BLAKE2s).run(arrayBuffer, ["128", "Hex", {string: "", option: "UTF8"}]) +
|
|
||||||
"\nBLAKE2s-160: " + (new BLAKE2s).run(arrayBuffer, ["160", "Hex", {string: "", option: "UTF8"}]) +
|
|
||||||
"\nBLAKE2s-256: " + (new BLAKE2s).run(arrayBuffer, ["256", "Hex", {string: "", option: "UTF8"}]) +
|
|
||||||
"\nStreebog-256: " + (new Streebog).run(arrayBuffer, ["256"]) +
|
|
||||||
"\nStreebog-512: " + (new Streebog).run(arrayBuffer, ["512"]) +
|
|
||||||
"\nGOST: " + (new GOSTHash).run(arrayBuffer, ["D-A"]) +
|
|
||||||
"\nSSDEEP: " + (new SSDEEP()).run(str) +
|
|
||||||
"\nCTPH: " + (new CTPH()).run(str) +
|
|
||||||
"\n\nChecksums:" +
|
|
||||||
"\nFletcher-8: " + (new Fletcher8Checksum).run(byteArray, []) +
|
|
||||||
"\nFletcher-16: " + (new Fletcher16Checksum).run(byteArray, []) +
|
|
||||||
"\nFletcher-32: " + (new Fletcher32Checksum).run(byteArray, []) +
|
|
||||||
"\nFletcher-64: " + (new Fletcher64Checksum).run(byteArray, []) +
|
|
||||||
"\nAdler-32: " + (new Adler32Checksum).run(byteArray, []) +
|
|
||||||
"\nCRC-8: " + (new CRC8Checksum).run(arrayBuffer, ["CRC-8"]) +
|
|
||||||
"\nCRC-16: " + (new CRC16Checksum).run(arrayBuffer, []) +
|
|
||||||
"\nCRC-32: " + (new CRC32Checksum).run(arrayBuffer, []);
|
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a hash or checksum algorithm
|
||||||
|
*
|
||||||
|
* @param {Function} algo - The hash or checksum algorithm
|
||||||
|
* @param {string} inputType
|
||||||
|
* @param {Object[]} [params=[]]
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
executeAlgo(algo, inputType, params=[]) {
|
||||||
|
let digest = null;
|
||||||
|
switch (inputType) {
|
||||||
|
case "arrayBuffer":
|
||||||
|
digest = algo.run(this.inputArrayBuffer, params);
|
||||||
|
break;
|
||||||
|
case "str":
|
||||||
|
digest = algo.run(this.inputStr, params);
|
||||||
|
break;
|
||||||
|
case "byteArray":
|
||||||
|
digest = algo.run(this.inputByteArray, params);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new OperationError("Unknown hash input type: " + inputType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return digest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the digest depending on user-specified arguments
|
||||||
|
* @param {string} digest
|
||||||
|
* @param {string} length
|
||||||
|
* @param {boolean} includeNames
|
||||||
|
* @param {string} name
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
formatDigest(digest, length, includeNames, name) {
|
||||||
|
if (length !== "All" && (digest.length * 4) !== parseInt(length, 10))
|
||||||
|
return "";
|
||||||
|
|
||||||
|
if (!includeNames)
|
||||||
|
return digest + "\n";
|
||||||
|
|
||||||
|
return `${name}:${" ".repeat(13-name.length)}${digest}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default GenerateAllHashes;
|
export default GenerateAllHashes;
|
||||||
|
|
|
@ -44,7 +44,7 @@ class GenerateQRCode extends Operation {
|
||||||
{
|
{
|
||||||
"name": "Margin (num modules)",
|
"name": "Margin (num modules)",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"value": 2,
|
"value": 4,
|
||||||
"min": 0
|
"min": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import jpath from "jsonpath";
|
import {JSONPath} from "jsonpath-plus";
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
@ -27,14 +27,20 @@ class JPathExpression extends Operation {
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
"name": "Query",
|
name: "Query",
|
||||||
"type": "string",
|
type: "string",
|
||||||
"value": ""
|
value: ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Result delimiter",
|
name: "Result delimiter",
|
||||||
"type": "binaryShortString",
|
type: "binaryShortString",
|
||||||
"value": "\\n"
|
value: "\\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Prevent eval",
|
||||||
|
type: "boolean",
|
||||||
|
value: true,
|
||||||
|
description: "Evaluated expressions are disabled by default for security reasons"
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -45,18 +51,21 @@ class JPathExpression extends Operation {
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const [query, delimiter] = args;
|
const [query, delimiter, preventEval] = args;
|
||||||
let results,
|
let results, jsonObj;
|
||||||
obj;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
obj = JSON.parse(input);
|
jsonObj = JSON.parse(input);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(`Invalid input JSON: ${err.message}`);
|
throw new OperationError(`Invalid input JSON: ${err.message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
results = jpath.query(obj, query);
|
results = JSONPath({
|
||||||
|
path: query,
|
||||||
|
json: jsonObj,
|
||||||
|
preventEval: preventEval
|
||||||
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(`Invalid JPath expression: ${err.message}`);
|
throw new OperationError(`Invalid JPath expression: ${err.message}`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,8 +114,11 @@ class JSONToCSV extends Operation {
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
escapeCellContents(data, force=false) {
|
escapeCellContents(data, force=false) {
|
||||||
if (typeof data === "number") data = data.toString();
|
if (data !== "string") {
|
||||||
if (force && typeof data !== "string") data = JSON.stringify(data);
|
const isPrimitive = data == null || typeof data !== "object";
|
||||||
|
if (isPrimitive) data = `${data}`;
|
||||||
|
else if (force) data = JSON.stringify(data);
|
||||||
|
}
|
||||||
|
|
||||||
// Double quotes should be doubled up
|
// Double quotes should be doubled up
|
||||||
data = data.replace(/"/g, '""');
|
data = data.replace(/"/g, '""');
|
||||||
|
|
|
@ -26,6 +26,13 @@ class JWTDecode extends Operation {
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "JSON";
|
this.outputType = "JSON";
|
||||||
this.args = [];
|
this.args = [];
|
||||||
|
this.checks = [
|
||||||
|
{
|
||||||
|
pattern: "^ey([A-Za-z0-9_-]+)\\.ey([A-Za-z0-9_-]+)\\.([A-Za-z0-9_-]+)$",
|
||||||
|
flags: "",
|
||||||
|
args: []
|
||||||
|
},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
41
src/core/operations/LMHash.mjs
Normal file
41
src/core/operations/LMHash.mjs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/**
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import {smbhash} from "ntlm";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LM Hash operation
|
||||||
|
*/
|
||||||
|
class LMHash extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LMHash constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "LM Hash";
|
||||||
|
this.module = "Crypto";
|
||||||
|
this.description = "An LM Hash, or LAN Manager Hash, is a deprecated way of storing passwords on old Microsoft operating systems. It is particularly weak and can be cracked in seconds on modern hardware using rainbow tables.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/LAN_Manager#Password_hashing_algorithm";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
return smbhash.lmhash(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LMHash;
|
43
src/core/operations/LZ4Compress.mjs
Normal file
43
src/core/operations/LZ4Compress.mjs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import lz4 from "lz4js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LZ4 Compress operation
|
||||||
|
*/
|
||||||
|
class LZ4Compress extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LZ4Compress constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "LZ4 Compress";
|
||||||
|
this.module = "Compression";
|
||||||
|
this.description = "LZ4 is a lossless data compression algorithm that is focused on compression and decompression speed. It belongs to the LZ77 family of byte-oriented compression schemes.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/LZ4_(compression_algorithm)";
|
||||||
|
this.inputType = "ArrayBuffer";
|
||||||
|
this.outputType = "ArrayBuffer";
|
||||||
|
this.args = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {ArrayBuffer}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const inBuf = new Uint8Array(input);
|
||||||
|
const compressed = lz4.compress(inBuf);
|
||||||
|
return compressed.buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LZ4Compress;
|
43
src/core/operations/LZ4Decompress.mjs
Normal file
43
src/core/operations/LZ4Decompress.mjs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import lz4 from "lz4js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LZ4 Decompress operation
|
||||||
|
*/
|
||||||
|
class LZ4Decompress extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LZ4Decompress constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "LZ4 Decompress";
|
||||||
|
this.module = "Compression";
|
||||||
|
this.description = "LZ4 is a lossless data compression algorithm that is focused on compression and decompression speed. It belongs to the LZ77 family of byte-oriented compression schemes.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/LZ4_(compression_algorithm)";
|
||||||
|
this.inputType = "ArrayBuffer";
|
||||||
|
this.outputType = "ArrayBuffer";
|
||||||
|
this.args = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {ArrayBuffer}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const inBuf = new Uint8Array(input);
|
||||||
|
const decompressed = lz4.decompress(inBuf);
|
||||||
|
return decompressed.buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LZ4Decompress;
|
64
src/core/operations/LZMACompress.mjs
Normal file
64
src/core/operations/LZMACompress.mjs
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/**
|
||||||
|
* @author Matt C [me@mitt.dev]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
import { compress } from "@blu3r4y/lzma";
|
||||||
|
import {isWorkerEnvironment} from "../Utils.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LZMA Compress operation
|
||||||
|
*/
|
||||||
|
class LZMACompress extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LZMACompress constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "LZMA Compress";
|
||||||
|
this.module = "Compression";
|
||||||
|
this.description = "Compresses data using the Lempel\u2013Ziv\u2013Markov chain algorithm. Compression mode determines the speed and effectiveness of the compression: 1 is fastest and less effective, 9 is slowest and most effective";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Markov_chain_algorithm";
|
||||||
|
this.inputType = "ArrayBuffer";
|
||||||
|
this.outputType = "ArrayBuffer";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Compression Mode",
|
||||||
|
type: "option",
|
||||||
|
value: [
|
||||||
|
"1", "2", "3", "4", "5", "6", "7", "8", "9"
|
||||||
|
],
|
||||||
|
"defaultIndex": 6
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {ArrayBuffer}
|
||||||
|
*/
|
||||||
|
async run(input, args) {
|
||||||
|
const mode = Number(args[0]);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
compress(new Uint8Array(input), mode, (result, error) => {
|
||||||
|
if (error) {
|
||||||
|
reject(new OperationError(`Failed to compress input: ${error.message}`));
|
||||||
|
}
|
||||||
|
// The compression returns as an Int8Array, but we can just get the unsigned data from the buffer
|
||||||
|
resolve(new Int8Array(result).buffer);
|
||||||
|
}, (percent) => {
|
||||||
|
if (isWorkerEnvironment()) self.sendStatusMessage(`Compressing input: ${(percent*100).toFixed(2)}%`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LZMACompress;
|
57
src/core/operations/LZMADecompress.mjs
Normal file
57
src/core/operations/LZMADecompress.mjs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/**
|
||||||
|
* @author Matt C [me@mitt.dev]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import {decompress} from "@blu3r4y/lzma";
|
||||||
|
import Utils, {isWorkerEnvironment} from "../Utils.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LZMA Decompress operation
|
||||||
|
*/
|
||||||
|
class LZMADecompress extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LZMADecompress constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "LZMA Decompress";
|
||||||
|
this.module = "Compression";
|
||||||
|
this.description = "Decompresses data using the Lempel-Ziv-Markov chain Algorithm.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Markov_chain_algorithm";
|
||||||
|
this.inputType = "ArrayBuffer";
|
||||||
|
this.outputType = "ArrayBuffer";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {ArrayBuffer}
|
||||||
|
*/
|
||||||
|
async run(input, args) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
decompress(new Uint8Array(input), (result, error) => {
|
||||||
|
if (error) {
|
||||||
|
reject(new OperationError(`Failed to decompress input: ${error.message}`));
|
||||||
|
}
|
||||||
|
// The decompression returns either a String or an untyped unsigned int8 array, but we can just get the unsigned data from the buffer
|
||||||
|
|
||||||
|
if (typeof result == "string") {
|
||||||
|
resolve(Utils.strToArrayBuffer(result));
|
||||||
|
} else {
|
||||||
|
resolve(new Int8Array(result).buffer);
|
||||||
|
}
|
||||||
|
}, (percent) => {
|
||||||
|
if (isWorkerEnvironment()) self.sendStatusMessage(`Decompressing input: ${(percent*100).toFixed(2)}%`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LZMADecompress;
|
46
src/core/operations/NTHash.mjs
Normal file
46
src/core/operations/NTHash.mjs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/**
|
||||||
|
* @author brun0ne [brunonblok@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
|
||||||
|
import cptable from "codepage";
|
||||||
|
import {runHash} from "../lib/Hash.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NT Hash operation
|
||||||
|
*/
|
||||||
|
class NTHash extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NTHash constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "NT Hash";
|
||||||
|
this.module = "Crypto";
|
||||||
|
this.description = "An NT Hash, sometimes referred to as an NTLM hash, is a method of storing passwords on Windows systems. It works by running MD4 on UTF-16LE encoded input. NTLM hashes are considered weak because they can be brute-forced very easily with modern hardware.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/NT_LAN_Manager";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const format = 1200; // UTF-16LE
|
||||||
|
const encoded = cptable.utils.encode(format, input);
|
||||||
|
const hashed = runHash("md4", encoded);
|
||||||
|
|
||||||
|
return hashed.toUpperCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NTHash;
|
|
@ -12,10 +12,8 @@ import { isImage } from "../lib/FileType.mjs";
|
||||||
import { toBase64 } from "../lib/Base64.mjs";
|
import { toBase64 } from "../lib/Base64.mjs";
|
||||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||||
|
|
||||||
import Tesseract from "tesseract.js";
|
|
||||||
const { createWorker } = Tesseract;
|
|
||||||
|
|
||||||
import process from "process";
|
import process from "process";
|
||||||
|
import { createWorker } from "tesseract.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optical Character Recognition operation
|
* Optical Character Recognition operation
|
||||||
|
@ -55,7 +53,7 @@ class OpticalCharacterRecognition extends Operation {
|
||||||
|
|
||||||
const type = isImage(input);
|
const type = isImage(input);
|
||||||
if (!type) {
|
if (!type) {
|
||||||
throw new OperationError("Invalid File Type");
|
throw new OperationError("Unsupported file type (supported: jpg,png,pbm,bmp) or no file provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
const assetDir = isWorkerEnvironment() ? `${self.docURL}/assets/` : `${process.cwd()}/src/core/vendor/`;
|
const assetDir = isWorkerEnvironment() ? `${self.docURL}/assets/` : `${process.cwd()}/src/core/vendor/`;
|
||||||
|
@ -74,7 +72,7 @@ class OpticalCharacterRecognition extends Operation {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await worker.load();
|
await worker.load();
|
||||||
self.sendStatusMessage("Loading English language...");
|
self.sendStatusMessage(`Loading English language pack...`);
|
||||||
await worker.loadLanguage("eng");
|
await worker.loadLanguage("eng");
|
||||||
self.sendStatusMessage("Intialising Tesseract API...");
|
self.sendStatusMessage("Intialising Tesseract API...");
|
||||||
await worker.initialize("eng");
|
await worker.initialize("eng");
|
||||||
|
|
|
@ -45,8 +45,8 @@ class ParseASN1HexString extends Operation {
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const [index, truncateLen] = args;
|
const [index, truncateLen] = args;
|
||||||
return r.ASN1HEX.dump(input.replace(/\s/g, ""), {
|
return r.ASN1HEX.dump(input.replace(/\s/g, "").toLowerCase(), {
|
||||||
"ommitLongOctet": truncateLen
|
"ommit_long_octet": truncateLen
|
||||||
}, index);
|
}, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ class ParseSSHHostKey extends Operation {
|
||||||
|
|
||||||
this.name = "Parse SSH Host Key";
|
this.name = "Parse SSH Host Key";
|
||||||
this.module = "Default";
|
this.module = "Default";
|
||||||
this.description = "Parses a SSH host key and extracts fields from it.<br>The key type can be:<ul><li>ssh-rsa</li><li>ssh-dss</li><li>ecdsa-sha2</li></ul>The key format can be either Hex or Base64.";
|
this.description = "Parses a SSH host key and extracts fields from it.<br>The key type can be:<ul><li>ssh-rsa</li><li>ssh-dss</li><li>ecdsa-sha2</li><li>ssh-ed25519</li></ul>The key format can be either Hex or Base64.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Secure_Shell";
|
this.infoURL = "https://wikipedia.org/wiki/Secure_Shell";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
|
@ -71,6 +71,8 @@ class ParseSSHHostKey extends Operation {
|
||||||
} else if (keyType.startsWith("ecdsa-sha2")) {
|
} else if (keyType.startsWith("ecdsa-sha2")) {
|
||||||
output += `\nCurve: ${Utils.byteArrayToChars(fromHex(fields[1]))}`;
|
output += `\nCurve: ${Utils.byteArrayToChars(fromHex(fields[1]))}`;
|
||||||
output += `\nPoint: 0x${fields.slice(2)}`;
|
output += `\nPoint: 0x${fields.slice(2)}`;
|
||||||
|
} else if (keyType === "ssh-ed25519") {
|
||||||
|
output += `\nx: 0x${fields[1]}`;
|
||||||
} else {
|
} else {
|
||||||
output += "\nUnsupported key type.";
|
output += "\nUnsupported key type.";
|
||||||
output += `\nParameters: ${fields.slice(1)}`;
|
output += `\nParameters: ${fields.slice(1)}`;
|
||||||
|
|
|
@ -57,9 +57,11 @@ class ParseX509Certificate extends Operation {
|
||||||
const cert = new r.X509(),
|
const cert = new r.X509(),
|
||||||
inputFormat = args[0];
|
inputFormat = args[0];
|
||||||
|
|
||||||
|
let undefinedInputFormat = false;
|
||||||
|
try {
|
||||||
switch (inputFormat) {
|
switch (inputFormat) {
|
||||||
case "DER Hex":
|
case "DER Hex":
|
||||||
input = input.replace(/\s/g, "");
|
input = input.replace(/\s/g, "").toLowerCase();
|
||||||
cert.readCertHex(input);
|
cert.readCertHex(input);
|
||||||
break;
|
break;
|
||||||
case "PEM":
|
case "PEM":
|
||||||
|
@ -72,8 +74,12 @@ class ParseX509Certificate extends Operation {
|
||||||
cert.readCertHex(toHex(Utils.strToByteArray(input), ""));
|
cert.readCertHex(toHex(Utils.strToByteArray(input), ""));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw "Undefined input format";
|
undefinedInputFormat = true;
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
throw "Certificate load error (non-certificate input?)";
|
||||||
|
}
|
||||||
|
if (undefinedInputFormat) throw "Undefined input format";
|
||||||
|
|
||||||
const sn = cert.getSerialNumberHex(),
|
const sn = cert.getSerialNumberHex(),
|
||||||
issuer = cert.getIssuer(),
|
issuer = cert.getIssuer(),
|
||||||
|
|
|
@ -52,8 +52,12 @@ class PseudoRandomNumberGenerator extends Operation {
|
||||||
let bytes;
|
let bytes;
|
||||||
|
|
||||||
if (isWorkerEnvironment() && self.crypto) {
|
if (isWorkerEnvironment() && self.crypto) {
|
||||||
bytes = self.crypto.getRandomValues(new Uint8Array(numBytes));
|
bytes = new ArrayBuffer(numBytes);
|
||||||
bytes = Utils.arrayBufferToStr(bytes.buffer);
|
const CHUNK_SIZE = 65536;
|
||||||
|
for (let i = 0; i < numBytes; i += CHUNK_SIZE) {
|
||||||
|
self.crypto.getRandomValues(new Uint8Array(bytes, i, Math.min(numBytes - i, CHUNK_SIZE)));
|
||||||
|
}
|
||||||
|
bytes = Utils.arrayBufferToStr(bytes);
|
||||||
} else {
|
} else {
|
||||||
bytes = forge.random.getBytesSync(numBytes);
|
bytes = forge.random.getBytesSync(numBytes);
|
||||||
}
|
}
|
||||||
|
|
247
src/core/operations/Rabbit.mjs
Normal file
247
src/core/operations/Rabbit.mjs
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import { toHexFast } from "../lib/Hex.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rabbit operation
|
||||||
|
*/
|
||||||
|
class Rabbit extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rabbit constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "Rabbit";
|
||||||
|
this.module = "Ciphers";
|
||||||
|
this.description = "Rabbit is a high-speed stream cipher introduced in 2003 and defined in RFC 4503.<br><br>The cipher uses a 128-bit key and an optional 64-bit initialization vector (IV).<br><br>big-endian: based on RFC4503 and RFC3447<br>little-endian: compatible with Crypto++";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Rabbit_(cipher)";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Key",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "IV",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Endianness",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Big", "Little"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Input",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Raw", "Hex"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Output",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Raw", "Hex"]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const key = Utils.convertToByteArray(args[0].string, args[0].option),
|
||||||
|
iv = Utils.convertToByteArray(args[1].string, args[1].option),
|
||||||
|
endianness = args[2],
|
||||||
|
inputType = args[3],
|
||||||
|
outputType = args[4];
|
||||||
|
|
||||||
|
const littleEndian = endianness === "Little";
|
||||||
|
|
||||||
|
if (key.length !== 16) {
|
||||||
|
throw new OperationError(`Invalid key length: ${key.length} bytes (expected: 16)`);
|
||||||
|
}
|
||||||
|
if (iv.length !== 0 && iv.length !== 8) {
|
||||||
|
throw new OperationError(`Invalid IV length: ${iv.length} bytes (expected: 0 or 8)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inner State
|
||||||
|
const X = new Uint32Array(8), C = new Uint32Array(8);
|
||||||
|
let b = 0;
|
||||||
|
|
||||||
|
// Counter System
|
||||||
|
const A = [
|
||||||
|
0x4d34d34d, 0xd34d34d3, 0x34d34d34, 0x4d34d34d,
|
||||||
|
0xd34d34d3, 0x34d34d34, 0x4d34d34d, 0xd34d34d3
|
||||||
|
];
|
||||||
|
const counterUpdate = function() {
|
||||||
|
for (let j = 0; j < 8; j++) {
|
||||||
|
const temp = C[j] + A[j] + b;
|
||||||
|
b = (temp / ((1 << 30) * 4)) >>> 0;
|
||||||
|
C[j] = temp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Next-State Function
|
||||||
|
const g = function(u, v) {
|
||||||
|
const uv = (u + v) >>> 0;
|
||||||
|
const upper = uv >>> 16, lower = uv & 0xffff;
|
||||||
|
const upperUpper = upper * upper;
|
||||||
|
const upperLower2 = 2 * upper * lower;
|
||||||
|
const lowerLower = lower * lower;
|
||||||
|
const mswTemp = upperUpper + ((upperLower2 / (1 << 16)) >>> 0);
|
||||||
|
const lswTemp = lowerLower + (upperLower2 & 0xffff) * (1 << 16);
|
||||||
|
const msw = mswTemp + ((lswTemp / ((1 << 30) * 4)) >>> 0);
|
||||||
|
const lsw = lswTemp >>> 0;
|
||||||
|
return lsw ^ msw;
|
||||||
|
};
|
||||||
|
const leftRotate = function(value, width) {
|
||||||
|
return (value << width) | (value >>> (32 - width));
|
||||||
|
};
|
||||||
|
const nextStateHelper1 = function(v0, v1, v2) {
|
||||||
|
return v0 + leftRotate(v1, 16) + leftRotate(v2, 16);
|
||||||
|
};
|
||||||
|
const nextStateHelper2 = function(v0, v1, v2) {
|
||||||
|
return v0 + leftRotate(v1, 8) + v2;
|
||||||
|
};
|
||||||
|
const G = new Uint32Array(8);
|
||||||
|
const nextState = function() {
|
||||||
|
for (let j = 0; j < 8; j++) {
|
||||||
|
G[j] = g(X[j], C[j]);
|
||||||
|
}
|
||||||
|
X[0] = nextStateHelper1(G[0], G[7], G[6]);
|
||||||
|
X[1] = nextStateHelper2(G[1], G[0], G[7]);
|
||||||
|
X[2] = nextStateHelper1(G[2], G[1], G[0]);
|
||||||
|
X[3] = nextStateHelper2(G[3], G[2], G[1]);
|
||||||
|
X[4] = nextStateHelper1(G[4], G[3], G[2]);
|
||||||
|
X[5] = nextStateHelper2(G[5], G[4], G[3]);
|
||||||
|
X[6] = nextStateHelper1(G[6], G[5], G[4]);
|
||||||
|
X[7] = nextStateHelper2(G[7], G[6], G[5]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Key Setup Scheme
|
||||||
|
const K = new Uint16Array(8);
|
||||||
|
if (littleEndian) {
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
K[i] = (key[1 + 2 * i] << 8) | key[2 * i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
K[i] = (key[14 - 2 * i] << 8) | key[15 - 2 * i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let j = 0; j < 8; j++) {
|
||||||
|
if (j % 2 === 0) {
|
||||||
|
X[j] = (K[(j + 1) % 8] << 16) | K[j];
|
||||||
|
C[j] = (K[(j + 4) % 8] << 16) | K[(j + 5) % 8];
|
||||||
|
} else {
|
||||||
|
X[j] = (K[(j + 5) % 8] << 16) | K[(j + 4) % 8];
|
||||||
|
C[j] = (K[j] << 16) | K[(j + 1) % 8];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
counterUpdate();
|
||||||
|
nextState();
|
||||||
|
}
|
||||||
|
for (let j = 0; j < 8; j++) {
|
||||||
|
C[j] = C[j] ^ X[(j + 4) % 8];
|
||||||
|
}
|
||||||
|
|
||||||
|
// IV Setup Scheme
|
||||||
|
if (iv.length === 8) {
|
||||||
|
const getIVValue = function(a, b, c, d) {
|
||||||
|
if (littleEndian) {
|
||||||
|
return (iv[a] << 24) | (iv[b] << 16) |
|
||||||
|
(iv[c] << 8) | iv[d];
|
||||||
|
} else {
|
||||||
|
return (iv[7 - a] << 24) | (iv[7 - b] << 16) |
|
||||||
|
(iv[7 - c] << 8) | iv[7 - d];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
C[0] = C[0] ^ getIVValue(3, 2, 1, 0);
|
||||||
|
C[1] = C[1] ^ getIVValue(7, 6, 3, 2);
|
||||||
|
C[2] = C[2] ^ getIVValue(7, 6, 5, 4);
|
||||||
|
C[3] = C[3] ^ getIVValue(5, 4, 1, 0);
|
||||||
|
C[4] = C[4] ^ getIVValue(3, 2, 1, 0);
|
||||||
|
C[5] = C[5] ^ getIVValue(7, 6, 3, 2);
|
||||||
|
C[6] = C[6] ^ getIVValue(7, 6, 5, 4);
|
||||||
|
C[7] = C[7] ^ getIVValue(5, 4, 1, 0);
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
counterUpdate();
|
||||||
|
nextState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extraction Scheme
|
||||||
|
const S = new Uint8Array(16);
|
||||||
|
const extract = function() {
|
||||||
|
let pos = 0;
|
||||||
|
const addPart = function(value) {
|
||||||
|
S[pos++] = value >>> 8;
|
||||||
|
S[pos++] = value & 0xff;
|
||||||
|
};
|
||||||
|
counterUpdate();
|
||||||
|
nextState();
|
||||||
|
addPart((X[6] >>> 16) ^ (X[1] & 0xffff));
|
||||||
|
addPart((X[6] & 0xffff) ^ (X[3] >>> 16));
|
||||||
|
addPart((X[4] >>> 16) ^ (X[7] & 0xffff));
|
||||||
|
addPart((X[4] & 0xffff) ^ (X[1] >>> 16));
|
||||||
|
addPart((X[2] >>> 16) ^ (X[5] & 0xffff));
|
||||||
|
addPart((X[2] & 0xffff) ^ (X[7] >>> 16));
|
||||||
|
addPart((X[0] >>> 16) ^ (X[3] & 0xffff));
|
||||||
|
addPart((X[0] & 0xffff) ^ (X[5] >>> 16));
|
||||||
|
if (littleEndian) {
|
||||||
|
for (let i = 0, j = S.length - 1; i < j;) {
|
||||||
|
const temp = S[i];
|
||||||
|
S[i] = S[j];
|
||||||
|
S[j] = temp;
|
||||||
|
i++;
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const data = Utils.convertToByteString(input, inputType);
|
||||||
|
const result = new Uint8Array(data.length);
|
||||||
|
for (let i = 0; i <= data.length - 16; i += 16) {
|
||||||
|
extract();
|
||||||
|
for (let j = 0; j < 16; j++) {
|
||||||
|
result[i + j] = data.charCodeAt(i + j) ^ S[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data.length % 16 !== 0) {
|
||||||
|
const offset = data.length - data.length % 16;
|
||||||
|
const length = data.length - offset;
|
||||||
|
extract();
|
||||||
|
if (littleEndian) {
|
||||||
|
for (let j = 0; j < length; j++) {
|
||||||
|
result[offset + j] = data.charCodeAt(offset + j) ^ S[j];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let j = 0; j < length; j++) {
|
||||||
|
result[offset + j] = data.charCodeAt(offset + j) ^ S[16 - length + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outputType === "Hex") {
|
||||||
|
return toHexFast(result);
|
||||||
|
}
|
||||||
|
return Utils.byteArrayToChars(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Rabbit;
|
|
@ -7,7 +7,6 @@
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import {INFLATE_BUFFER_TYPE} from "../lib/Zlib.mjs";
|
import {INFLATE_BUFFER_TYPE} from "../lib/Zlib.mjs";
|
||||||
import rawinflate from "zlibjs/bin/rawinflate.min.js";
|
import rawinflate from "zlibjs/bin/rawinflate.min.js";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
|
||||||
|
|
||||||
const Zlib = rawinflate.Zlib;
|
const Zlib = rawinflate.Zlib;
|
||||||
|
|
||||||
|
@ -83,25 +82,6 @@ class RawInflate extends Operation {
|
||||||
}),
|
}),
|
||||||
result = new Uint8Array(inflate.decompress());
|
result = new Uint8Array(inflate.decompress());
|
||||||
|
|
||||||
// Raw Inflate sometimes messes up and returns nonsense like this:
|
|
||||||
// ]....]....]....]....]....]....]....]....]....]....]....]....]....]...
|
|
||||||
// e.g. Input data of [8b, 1d, dc, 44]
|
|
||||||
// Look for the first two square brackets:
|
|
||||||
if (result.length > 158 && result[0] === 93 && result[5] === 93) {
|
|
||||||
// If the first two square brackets are there, check that the others
|
|
||||||
// are also there. If they are, throw an error. If not, continue.
|
|
||||||
let valid = false;
|
|
||||||
for (let i = 0; i < 155; i += 5) {
|
|
||||||
if (result[i] !== 93) {
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid) {
|
|
||||||
throw new OperationError("Error: Unable to inflate data");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// This seems to be the easiest way...
|
|
||||||
return result.buffer;
|
return result.buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse operation
|
* Reverse operation
|
||||||
|
@ -26,7 +27,8 @@ class Reverse extends Operation {
|
||||||
{
|
{
|
||||||
"name": "By",
|
"name": "By",
|
||||||
"type": "option",
|
"type": "option",
|
||||||
"value": ["Character", "Line"]
|
"value": ["Byte", "Character", "Line"],
|
||||||
|
"defaultIndex": 1
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -57,6 +59,24 @@ class Reverse extends Operation {
|
||||||
result.push(0x0a);
|
result.push(0x0a);
|
||||||
}
|
}
|
||||||
return result.slice(0, input.length);
|
return result.slice(0, input.length);
|
||||||
|
} else if (args[0] === "Character") {
|
||||||
|
const inputString = Utils.byteArrayToUtf8(input);
|
||||||
|
let result = "";
|
||||||
|
for (let i = inputString.length - 1; i >= 0; i--) {
|
||||||
|
const c = inputString.charCodeAt(i);
|
||||||
|
if (i > 0 && 0xdc00 <= c && c <= 0xdfff) {
|
||||||
|
const c2 = inputString.charCodeAt(i - 1);
|
||||||
|
if (0xd800 <= c2 && c2 <= 0xdbff) {
|
||||||
|
// surrogates
|
||||||
|
result += inputString.charAt(i - 1);
|
||||||
|
result += inputString.charAt(i);
|
||||||
|
i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result += inputString.charAt(i);
|
||||||
|
}
|
||||||
|
return Utils.strToUtf8ByteArray(result);
|
||||||
} else {
|
} else {
|
||||||
return input.reverse();
|
return input.reverse();
|
||||||
}
|
}
|
||||||
|
|
78
src/core/operations/Shuffle.mjs
Normal file
78
src/core/operations/Shuffle.mjs
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuffle operation
|
||||||
|
*/
|
||||||
|
class Shuffle extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuffle constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "Shuffle";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Randomly reorders input elements.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Shuffling";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Delimiter",
|
||||||
|
type: "option",
|
||||||
|
value: INPUT_DELIM_OPTIONS
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const delim = Utils.charRep(args[0]);
|
||||||
|
if (input.length === 0) return input;
|
||||||
|
|
||||||
|
// return a random number in [0, 1)
|
||||||
|
const rng = (typeof crypto) !== "undefined" && crypto.getRandomValues ? (function() {
|
||||||
|
const buf = new Uint32Array(2);
|
||||||
|
return function() {
|
||||||
|
// generate 53-bit random integer: 21 + 32 bits
|
||||||
|
crypto.getRandomValues(buf);
|
||||||
|
const value = (buf[0] >>> (32 - 21)) * ((1 << 30) * 4) + buf[1];
|
||||||
|
return value / ((1 << 23) * (1 << 30));
|
||||||
|
};
|
||||||
|
})() : Math.random;
|
||||||
|
|
||||||
|
// return a random integer in [0, max)
|
||||||
|
const randint = function(max) {
|
||||||
|
return Math.floor(rng() * max);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Split input into shuffleable sections
|
||||||
|
const toShuffle = input.split(delim);
|
||||||
|
|
||||||
|
// shuffle elements
|
||||||
|
for (let i = toShuffle.length - 1; i > 0; i--) {
|
||||||
|
const idx = randint(i + 1);
|
||||||
|
const tmp = toShuffle[idx];
|
||||||
|
toShuffle[idx] = toShuffle[i];
|
||||||
|
toShuffle[i] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return toShuffle.join(delim);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Shuffle;
|
|
@ -7,7 +7,7 @@
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs";
|
import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs";
|
||||||
import {caseInsensitiveSort, ipSort, numericSort, hexadecimalSort} from "../lib/Sort.mjs";
|
import {caseInsensitiveSort, ipSort, numericSort, hexadecimalSort, lengthSort} from "../lib/Sort.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort operation
|
* Sort operation
|
||||||
|
@ -39,7 +39,7 @@ class Sort extends Operation {
|
||||||
{
|
{
|
||||||
"name": "Order",
|
"name": "Order",
|
||||||
"type": "option",
|
"type": "option",
|
||||||
"value": ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric", "Numeric (hexadecimal)"]
|
"value": ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric", "Numeric (hexadecimal)", "Length"]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,8 @@ class Sort extends Operation {
|
||||||
sorted = sorted.sort(numericSort);
|
sorted = sorted.sort(numericSort);
|
||||||
} else if (order === "Numeric (hexadecimal)") {
|
} else if (order === "Numeric (hexadecimal)") {
|
||||||
sorted = sorted.sort(hexadecimalSort);
|
sorted = sorted.sort(hexadecimalSort);
|
||||||
|
} else if (order === "Length") {
|
||||||
|
sorted = sorted.sort(lengthSort);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sortReverse) sorted.reverse();
|
if (sortReverse) sorted.reverse();
|
||||||
|
|
|
@ -34,10 +34,50 @@ class Substitute extends Operation {
|
||||||
"name": "Ciphertext",
|
"name": "Ciphertext",
|
||||||
"type": "binaryString",
|
"type": "binaryString",
|
||||||
"value": "XYZABCDEFGHIJKLMNOPQRSTUVW"
|
"value": "XYZABCDEFGHIJKLMNOPQRSTUVW"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ignore case",
|
||||||
|
"type": "boolean",
|
||||||
|
"value": false
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a single character using the dictionary, if ignoreCase is true then
|
||||||
|
* check in the dictionary for both upper and lower case versions of the character.
|
||||||
|
* In output the input character case is preserved.
|
||||||
|
* @param {string} char
|
||||||
|
* @param {Object} dict
|
||||||
|
* @param {boolean} ignoreCase
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
cipherSingleChar(char, dict, ignoreCase) {
|
||||||
|
if (!ignoreCase)
|
||||||
|
return dict[char] || char;
|
||||||
|
|
||||||
|
const isUpperCase = char === char.toUpperCase();
|
||||||
|
|
||||||
|
// convert using the dictionary keeping the case of the input character
|
||||||
|
|
||||||
|
if (dict[char] !== undefined) {
|
||||||
|
// if the character is in the dictionary return the value with the input case
|
||||||
|
return isUpperCase ? dict[char].toUpperCase() : dict[char].toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for the other case, if it is in the dictionary return the value with the right case
|
||||||
|
if (isUpperCase) {
|
||||||
|
if (dict[char.toLowerCase()] !== undefined)
|
||||||
|
return dict[char.toLowerCase()].toUpperCase();
|
||||||
|
} else {
|
||||||
|
if (dict[char.toUpperCase()] !== undefined)
|
||||||
|
return dict[char.toUpperCase()].toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
return char;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} input
|
* @param {string} input
|
||||||
* @param {Object[]} args
|
* @param {Object[]} args
|
||||||
|
@ -45,17 +85,23 @@ class Substitute extends Operation {
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const plaintext = Utils.expandAlphRange([...args[0]]),
|
const plaintext = Utils.expandAlphRange([...args[0]]),
|
||||||
ciphertext = Utils.expandAlphRange([...args[1]]);
|
ciphertext = Utils.expandAlphRange([...args[1]]),
|
||||||
let output = "",
|
ignoreCase = args[2];
|
||||||
index = -1;
|
let output = "";
|
||||||
|
|
||||||
if (plaintext.length !== ciphertext.length) {
|
if (plaintext.length !== ciphertext.length) {
|
||||||
output = "Warning: Plaintext and Ciphertext lengths differ\n\n";
|
output = "Warning: Plaintext and Ciphertext lengths differ\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create dictionary for conversion
|
||||||
|
const dict = {};
|
||||||
|
for (let i = 0; i < Math.min(ciphertext.length, plaintext.length); i++) {
|
||||||
|
dict[plaintext[i]] = ciphertext[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// map every letter with the conversion function
|
||||||
for (const character of input) {
|
for (const character of input) {
|
||||||
index = plaintext.indexOf(character);
|
output += this.cipherSingleChar(character, dict, ignoreCase);
|
||||||
output += index > -1 && index < ciphertext.length ? ciphertext[index] : character;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
|
|
|
@ -20,7 +20,7 @@ class ToTable extends Operation {
|
||||||
|
|
||||||
this.name = "To Table";
|
this.name = "To Table";
|
||||||
this.module = "Default";
|
this.module = "Default";
|
||||||
this.description = "Data can be split on different characters and rendered as an HTML or ASCII table with an optional header row.<br><br>Supports the CSV (Comma Separated Values) file format by default. Change the cell delimiter argument to <code>\\t</code> to support TSV (Tab Separated Values) or <code>|</code> for PSV (Pipe Separated Values).<br><br>You can enter as many delimiters as you like. Each character will be treat as a separate possible delimiter.";
|
this.description = "Data can be split on different characters and rendered as an HTML, ASCII or Markdown table with an optional header row.<br><br>Supports the CSV (Comma Separated Values) file format by default. Change the cell delimiter argument to <code>\\t</code> to support TSV (Tab Separated Values) or <code>|</code> for PSV (Pipe Separated Values).<br><br>You can enter as many delimiters as you like. Each character will be treat as a separate possible delimiter.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Comma-separated_values";
|
this.infoURL = "https://wikipedia.org/wiki/Comma-separated_values";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "html";
|
this.outputType = "html";
|
||||||
|
@ -43,7 +43,7 @@ class ToTable extends Operation {
|
||||||
{
|
{
|
||||||
"name": "Format",
|
"name": "Format",
|
||||||
"type": "option",
|
"type": "option",
|
||||||
"value": ["ASCII", "HTML"]
|
"value": ["ASCII", "HTML", "Markdown"]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,9 @@ class ToTable extends Operation {
|
||||||
case "ASCII":
|
case "ASCII":
|
||||||
return asciiOutput(tableData);
|
return asciiOutput(tableData);
|
||||||
case "HTML":
|
case "HTML":
|
||||||
|
return htmlOutput(tableData);
|
||||||
|
case "Markdown":
|
||||||
|
return markdownOutput(tableData);
|
||||||
default:
|
default:
|
||||||
return htmlOutput(tableData);
|
return htmlOutput(tableData);
|
||||||
}
|
}
|
||||||
|
@ -183,6 +186,59 @@ class ToTable extends Operation {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outputs an array of data as a Markdown table.
|
||||||
|
*
|
||||||
|
* @param {string[][]} tableData
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function markdownOutput(tableData) {
|
||||||
|
const headerDivider = "-";
|
||||||
|
const verticalBorder = "|";
|
||||||
|
|
||||||
|
let output = "";
|
||||||
|
const longestCells = [];
|
||||||
|
|
||||||
|
// Find longestCells value per column to pad cells equally.
|
||||||
|
tableData.forEach(function(row, index) {
|
||||||
|
row.forEach(function(cell, cellIndex) {
|
||||||
|
if (longestCells[cellIndex] === undefined || cell.length > longestCells[cellIndex]) {
|
||||||
|
longestCells[cellIndex] = cell.length;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ignoring the checkbox, as current Mardown renderer in CF doesn't handle table without headers
|
||||||
|
const row = tableData.shift();
|
||||||
|
output += outputRow(row, longestCells);
|
||||||
|
let rowOutput = verticalBorder;
|
||||||
|
row.forEach(function(cell, index) {
|
||||||
|
rowOutput += " " + headerDivider + " " + verticalBorder;
|
||||||
|
});
|
||||||
|
output += rowOutput += "\n";
|
||||||
|
|
||||||
|
// Add the rest of the table rows.
|
||||||
|
tableData.forEach(function(row, index) {
|
||||||
|
output += outputRow(row, longestCells);
|
||||||
|
});
|
||||||
|
|
||||||
|
return output;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outputs a row of correctly padded cells.
|
||||||
|
*/
|
||||||
|
function outputRow(row, longestCells) {
|
||||||
|
let rowOutput = verticalBorder;
|
||||||
|
row.forEach(function(cell, index) {
|
||||||
|
rowOutput += " " + cell + " ".repeat(longestCells[index] - cell.length) + " " + verticalBorder;
|
||||||
|
});
|
||||||
|
rowOutput += "\n";
|
||||||
|
return rowOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ class TripleDESDecrypt extends Operation {
|
||||||
inputType = args[3],
|
inputType = args[3],
|
||||||
outputType = args[4];
|
outputType = args[4];
|
||||||
|
|
||||||
if (key.length !== 24) {
|
if (key.length !== 24 && key.length !== 16) {
|
||||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||||
|
|
||||||
Triple DES uses a key length of 24 bytes (192 bits).
|
Triple DES uses a key length of 24 bytes (192 bits).
|
||||||
|
@ -85,7 +85,8 @@ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
|
||||||
|
|
||||||
input = Utils.convertToByteString(input, inputType);
|
input = Utils.convertToByteString(input, inputType);
|
||||||
|
|
||||||
const decipher = forge.cipher.createDecipher("3DES-" + mode, key);
|
const decipher = forge.cipher.createDecipher("3DES-" + mode,
|
||||||
|
key.length === 16 ? key + key.substring(0, 8) : key);
|
||||||
|
|
||||||
/* Allow for a "no padding" mode */
|
/* Allow for a "no padding" mode */
|
||||||
if (noPadding) {
|
if (noPadding) {
|
||||||
|
|
|
@ -69,7 +69,7 @@ class TripleDESEncrypt extends Operation {
|
||||||
inputType = args[3],
|
inputType = args[3],
|
||||||
outputType = args[4];
|
outputType = args[4];
|
||||||
|
|
||||||
if (key.length !== 24) {
|
if (key.length !== 24 && key.length !== 16) {
|
||||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||||
|
|
||||||
Triple DES uses a key length of 24 bytes (192 bits).
|
Triple DES uses a key length of 24 bytes (192 bits).
|
||||||
|
@ -84,7 +84,8 @@ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
|
||||||
|
|
||||||
input = Utils.convertToByteString(input, inputType);
|
input = Utils.convertToByteString(input, inputType);
|
||||||
|
|
||||||
const cipher = forge.cipher.createCipher("3DES-" + mode, key);
|
const cipher = forge.cipher.createCipher("3DES-" + mode,
|
||||||
|
key.length === 16 ? key + key.substring(0, 8) : key);
|
||||||
cipher.start({iv: iv});
|
cipher.start({iv: iv});
|
||||||
cipher.update(forge.util.createBuffer(input));
|
cipher.update(forge.util.createBuffer(input));
|
||||||
cipher.finish();
|
cipher.finish();
|
||||||
|
|
|
@ -79,6 +79,9 @@ class UNIXTimestampToWindowsFiletime extends Operation {
|
||||||
flipped += result.charAt(i);
|
flipped += result.charAt(i);
|
||||||
flipped += result.charAt(i + 1);
|
flipped += result.charAt(i + 1);
|
||||||
}
|
}
|
||||||
|
if (result.length % 2 !== 0) {
|
||||||
|
flipped += "0" + result.charAt(0);
|
||||||
|
}
|
||||||
result = flipped;
|
result = flipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ class ViewBitPlane extends Operation {
|
||||||
* @returns {html}
|
* @returns {html}
|
||||||
*/
|
*/
|
||||||
present(data) {
|
present(data) {
|
||||||
if (!data.length) return "";
|
if (!data.byteLength) return "";
|
||||||
const type = isImage(data);
|
const type = isImage(data);
|
||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(data)}">`;
|
return `<img src="data:${type};base64,${toBase64(data)}">`;
|
||||||
|
|
|
@ -52,7 +52,10 @@ class WindowsFiletimeToUNIXTimestamp extends Operation {
|
||||||
if (format === "Hex (little endian)") {
|
if (format === "Hex (little endian)") {
|
||||||
// Swap endianness
|
// Swap endianness
|
||||||
let result = "";
|
let result = "";
|
||||||
for (let i = input.length - 2; i >= 0; i -= 2) {
|
if (input.length % 2 !== 0) {
|
||||||
|
result += input.charAt(input.length - 1);
|
||||||
|
}
|
||||||
|
for (let i = input.length - input.length % 2 - 2; i >= 0; i -= 2) {
|
||||||
result += input.charAt(i);
|
result += input.charAt(i);
|
||||||
result += input.charAt(i + 1);
|
result += input.charAt(i + 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,17 @@ class YARARules extends Operation {
|
||||||
name: "Show counts",
|
name: "Show counts",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: true
|
value: true
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
name: "Show rule warnings",
|
||||||
|
type: "boolean",
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Show console module messages",
|
||||||
|
type: "boolean",
|
||||||
|
value: true
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +74,7 @@ class YARARules extends Operation {
|
||||||
async run(input, args) {
|
async run(input, args) {
|
||||||
if (isWorkerEnvironment())
|
if (isWorkerEnvironment())
|
||||||
self.sendStatusMessage("Instantiating YARA...");
|
self.sendStatusMessage("Instantiating YARA...");
|
||||||
const [rules, showStrings, showLengths, showMeta, showCounts] = args;
|
const [rules, showStrings, showLengths, showMeta, showCounts, showRuleWarns, showConsole] = args;
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
Yara().then(yara => {
|
Yara().then(yara => {
|
||||||
if (isWorkerEnvironment()) self.sendStatusMessage("Converting data for YARA.");
|
if (isWorkerEnvironment()) self.sendStatusMessage("Converting data for YARA.");
|
||||||
|
@ -83,11 +93,19 @@ class YARARules extends Operation {
|
||||||
const compileError = resp.compileErrors.get(i);
|
const compileError = resp.compileErrors.get(i);
|
||||||
if (!compileError.warning) {
|
if (!compileError.warning) {
|
||||||
reject(new OperationError(`Error on line ${compileError.lineNumber}: ${compileError.message}`));
|
reject(new OperationError(`Error on line ${compileError.lineNumber}: ${compileError.message}`));
|
||||||
} else {
|
} else if (showRuleWarns) {
|
||||||
matchString += `Warning on line ${compileError.lineNumber}: ${compileError.message}`;
|
matchString += `Warning on line ${compileError.lineNumber}: ${compileError.message}\n`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showConsole) {
|
||||||
|
const consoleLogs = resp.consoleLogs;
|
||||||
|
for (let i = 0; i < consoleLogs.size(); i++) {
|
||||||
|
matchString += consoleLogs.get(i) + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const matchedRules = resp.matchedRules;
|
const matchedRules = resp.matchedRules;
|
||||||
for (let i = 0; i < matchedRules.size(); i++) {
|
for (let i = 0; i < matchedRules.size(); i++) {
|
||||||
const rule = matchedRules.get(i);
|
const rule = matchedRules.get(i);
|
||||||
|
@ -100,11 +118,11 @@ class YARARules extends Operation {
|
||||||
}
|
}
|
||||||
meta = meta.slice(0, -2) + "]";
|
meta = meta.slice(0, -2) + "]";
|
||||||
}
|
}
|
||||||
const countString = showCounts ? `${matches.size()} time${matches.size() > 1 ? "s" : ""}` : "";
|
const countString = matches.size() === 0 ? "" : (showCounts ? ` (${matches.size()} time${matches.size() > 1 ? "s" : ""})` : "");
|
||||||
if (matches.size() === 0 || !(showStrings || showLengths)) {
|
if (matches.size() === 0 || !(showStrings || showLengths)) {
|
||||||
matchString += `Input matches rule "${rule.ruleName}"${meta}${countString.length > 0 ? ` ${countString}`: ""}.\n`;
|
matchString += `Input matches rule "${rule.ruleName}"${meta}${countString.length > 0 ? ` ${countString}`: ""}.\n`;
|
||||||
} else {
|
} else {
|
||||||
matchString += `Rule "${rule.ruleName}"${meta} matches (${countString}):\n`;
|
matchString += `Rule "${rule.ruleName}"${meta} matches${countString}:\n`;
|
||||||
for (let j = 0; j < matches.size(); j++) {
|
for (let j = 0; j < matches.size(); j++) {
|
||||||
const match = matches.get(j);
|
const match = matches.get(j);
|
||||||
if (showStrings || showLengths) {
|
if (showStrings || showLengths) {
|
||||||
|
|
|
@ -30,6 +30,7 @@ class HTMLIngredient {
|
||||||
this.rows = config.rows || false;
|
this.rows = config.rows || false;
|
||||||
this.target = config.target;
|
this.target = config.target;
|
||||||
this.defaultIndex = config.defaultIndex || 0;
|
this.defaultIndex = config.defaultIndex || 0;
|
||||||
|
this.maxLength = config.maxLength || null;
|
||||||
this.toggleValues = config.toggleValues;
|
this.toggleValues = config.toggleValues;
|
||||||
this.ingId = this.app.nextIngId();
|
this.ingId = this.app.nextIngId();
|
||||||
this.id = "ing-" + this.ingId;
|
this.id = "ing-" + this.ingId;
|
||||||
|
@ -63,7 +64,8 @@ class HTMLIngredient {
|
||||||
tabindex="${this.tabIndex}"
|
tabindex="${this.tabIndex}"
|
||||||
arg-name="${this.name}"
|
arg-name="${this.name}"
|
||||||
value="${this.value}"
|
value="${this.value}"
|
||||||
${this.disabled ? "disabled" : ""}>
|
${this.disabled ? "disabled" : ""}
|
||||||
|
${this.maxLength ? `maxlength="${this.maxLength}"` : ""}>
|
||||||
</div>`;
|
</div>`;
|
||||||
break;
|
break;
|
||||||
case "shortString":
|
case "shortString":
|
||||||
|
@ -78,7 +80,8 @@ class HTMLIngredient {
|
||||||
tabindex="${this.tabIndex}"
|
tabindex="${this.tabIndex}"
|
||||||
arg-name="${this.name}"
|
arg-name="${this.name}"
|
||||||
value="${this.value}"
|
value="${this.value}"
|
||||||
${this.disabled ? "disabled" : ""}>
|
${this.disabled ? "disabled" : ""}
|
||||||
|
${this.maxLength ? `maxlength="${this.maxLength}"` : ""}>
|
||||||
</div>`;
|
</div>`;
|
||||||
break;
|
break;
|
||||||
case "toggleString":
|
case "toggleString":
|
||||||
|
@ -93,7 +96,8 @@ class HTMLIngredient {
|
||||||
tabindex="${this.tabIndex}"
|
tabindex="${this.tabIndex}"
|
||||||
arg-name="${this.name}"
|
arg-name="${this.name}"
|
||||||
value="${this.value}"
|
value="${this.value}"
|
||||||
${this.disabled ? "disabled" : ""}>
|
${this.disabled ? "disabled" : ""}
|
||||||
|
${this.maxLength ? `maxlength="${this.maxLength}"` : ""}>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group-append">
|
<div class="input-group-append">
|
||||||
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">${this.toggleValues[0]}</button>
|
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">${this.toggleValues[0]}</button>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
import "highlight.js/styles/vs.css";
|
import "highlight.js/styles/vs.css";
|
||||||
|
|
||||||
/* Frameworks */
|
/* Frameworks */
|
||||||
import "./vendors/bootstrap.scss";
|
import "bootstrap-material-design/dist/css/bootstrap-material-design.css";
|
||||||
import "bootstrap-colorpicker/dist/css/bootstrap-colorpicker.css";
|
import "bootstrap-colorpicker/dist/css/bootstrap-colorpicker.css";
|
||||||
|
|
||||||
/* CyberChef styles */
|
/* CyberChef styles */
|
||||||
|
|
|
@ -82,7 +82,17 @@ a:focus {
|
||||||
border-color: var(--btn-success-hover-border-colour);
|
border-color: var(--btn-success-hover-border-colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
select.form-control:not([size]):not([multiple]), select.custom-file-control:not([size]):not([multiple]) {
|
select.form-control,
|
||||||
|
select.form-control:focus {
|
||||||
|
background-color: var(--primary-background-colour) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
select.form-control:focus {
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
select.form-control:not([size]):not([multiple]),
|
||||||
|
select.custom-file-control:not([size]):not([multiple]) {
|
||||||
height: unset !important;
|
height: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +155,8 @@ optgroup {
|
||||||
color: var(--primary-font-colour);
|
color: var(--primary-font-colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-bordered th, .table-bordered td {
|
.table-bordered th,
|
||||||
|
.table-bordered td {
|
||||||
border: 1px solid var(--table-border-colour);
|
border: 1px solid var(--table-border-colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +183,9 @@ optgroup {
|
||||||
color: var(--subtext-font-colour);
|
color: var(--subtext-font-colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-tabs>li>a.nav-link.active, .nav-tabs>li>a.nav-link.active:focus, .nav-tabs>li>a.nav-link.active:hover {
|
.nav-tabs>li>a.nav-link.active,
|
||||||
|
.nav-tabs>li>a.nav-link.active:focus,
|
||||||
|
.nav-tabs>li>a.nav-link.active:hover {
|
||||||
background-color: var(--secondary-background-colour);
|
background-color: var(--secondary-background-colour);
|
||||||
border-color: var(--secondary-border-colour);
|
border-color: var(--secondary-border-colour);
|
||||||
border-bottom-color: transparent;
|
border-bottom-color: transparent;
|
||||||
|
@ -183,7 +196,8 @@ optgroup {
|
||||||
border-color: var(--primary-border-colour);
|
border-color: var(--primary-border-colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav a.nav-link:focus, .nav a.nav-link:hover {
|
.nav a.nav-link:focus,
|
||||||
|
.nav a.nav-link:hover {
|
||||||
background-color: var(--secondary-border-colour);
|
background-color: var(--secondary-border-colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +213,8 @@ optgroup {
|
||||||
color: var(--primary-font-colour);
|
color: var(--primary-font-colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-menu a:focus, .dropdown-menu a:hover {
|
.dropdown-menu a:focus,
|
||||||
|
.dropdown-menu a:hover {
|
||||||
background-color: var(--secondary-background-colour);
|
background-color: var(--secondary-background-colour);
|
||||||
color: var(--primary-font-colour);
|
color: var(--primary-font-colour);
|
||||||
}
|
}
|
||||||
|
|
23
src/web/stylesheets/vendors/bootstrap.scss
vendored
23
src/web/stylesheets/vendors/bootstrap.scss
vendored
|
@ -1,23 +0,0 @@
|
||||||
/**
|
|
||||||
* Bootstrap Material Design with overrides
|
|
||||||
*
|
|
||||||
* @author n1474335 [n1474335@gmail.com]
|
|
||||||
* @copyright Crown Copyright 2018
|
|
||||||
* @license Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
@import "~bootstrap-material-design/scss/variables/colors";
|
|
||||||
|
|
||||||
$theme-colors: (
|
|
||||||
primary: $blue-700,
|
|
||||||
success: $green,
|
|
||||||
info: $light-blue,
|
|
||||||
warning: $deep-orange,
|
|
||||||
danger: $red,
|
|
||||||
light: $grey-100,
|
|
||||||
dark: $grey-800
|
|
||||||
);
|
|
||||||
|
|
||||||
$bmd-form-line-height: 1.25;
|
|
||||||
|
|
||||||
@import "~bootstrap-material-design/scss/core";
|
|
|
@ -45,10 +45,10 @@ TestRegister.addApiTests([
|
||||||
const result = chef.ADD("sample input", {
|
const result = chef.ADD("sample input", {
|
||||||
key: {
|
key: {
|
||||||
string: "some key",
|
string: "some key",
|
||||||
option: "Hex"
|
option: "utf8"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
assert.equal(result.toString(), "aO[^ZS\u000eW\\^cb");
|
assert.equal(result.toString(), "\xe6\xd0\xda\xd5\x8c\xd0\x85\xe2\xe1\xdf\xe2\xd9");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
@ -121,10 +121,10 @@ Tiger-128`;
|
||||||
const result = chef.AND("Scot-free", {
|
const result = chef.AND("Scot-free", {
|
||||||
key: {
|
key: {
|
||||||
string: "Raining Cats and Dogs",
|
string: "Raining Cats and Dogs",
|
||||||
option: "Hex",
|
option: "utf8",
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
assert.strictEqual(result.toString(), "\u0000\"M$(D E");
|
assert.strictEqual(result.toString(), "Raid)fb A");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("atBash Cipher", () => {
|
it("atBash Cipher", () => {
|
||||||
|
@ -371,10 +371,10 @@ color: white;
|
||||||
},
|
},
|
||||||
salt: {
|
salt: {
|
||||||
string: "Market",
|
string: "Market",
|
||||||
option: "Hex",
|
option: "utf8",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
assert.strictEqual(result.toString(), "7c21a9f5063a4d62fb1050068245c181");
|
assert.strictEqual(result.toString(), "4930d5d200e80f18c96b5550d13c6af8");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("Derive PBKDF2 Key", () => {
|
it("Derive PBKDF2 Key", () => {
|
||||||
|
|
|
@ -30,6 +30,7 @@ import "./tests/ByteRepr.mjs";
|
||||||
import "./tests/CartesianProduct.mjs";
|
import "./tests/CartesianProduct.mjs";
|
||||||
import "./tests/CetaceanCipherEncode.mjs";
|
import "./tests/CetaceanCipherEncode.mjs";
|
||||||
import "./tests/CetaceanCipherDecode.mjs";
|
import "./tests/CetaceanCipherDecode.mjs";
|
||||||
|
import "./tests/ChaCha.mjs";
|
||||||
import "./tests/CharEnc.mjs";
|
import "./tests/CharEnc.mjs";
|
||||||
import "./tests/ChangeIPFormat.mjs";
|
import "./tests/ChangeIPFormat.mjs";
|
||||||
import "./tests/Charts.mjs";
|
import "./tests/Charts.mjs";
|
||||||
|
@ -45,6 +46,7 @@ import "./tests/DateTime.mjs";
|
||||||
import "./tests/ExtractEmailAddresses.mjs";
|
import "./tests/ExtractEmailAddresses.mjs";
|
||||||
import "./tests/Fork.mjs";
|
import "./tests/Fork.mjs";
|
||||||
import "./tests/FromDecimal.mjs";
|
import "./tests/FromDecimal.mjs";
|
||||||
|
import "./tests/GenerateAllHashes.mjs";
|
||||||
import "./tests/Gzip.mjs";
|
import "./tests/Gzip.mjs";
|
||||||
import "./tests/Gunzip.mjs";
|
import "./tests/Gunzip.mjs";
|
||||||
import "./tests/Hash.mjs";
|
import "./tests/Hash.mjs";
|
||||||
|
@ -119,9 +121,15 @@ import "./tests/SIGABA.mjs";
|
||||||
import "./tests/ELFInfo.mjs";
|
import "./tests/ELFInfo.mjs";
|
||||||
import "./tests/Subsection.mjs";
|
import "./tests/Subsection.mjs";
|
||||||
import "./tests/CaesarBoxCipher.mjs";
|
import "./tests/CaesarBoxCipher.mjs";
|
||||||
|
import "./tests/UnescapeString.mjs";
|
||||||
import "./tests/LS47.mjs";
|
import "./tests/LS47.mjs";
|
||||||
import "./tests/LZString.mjs";
|
import "./tests/LZString.mjs";
|
||||||
|
import "./tests/NTLM.mjs";
|
||||||
|
import "./tests/Shuffle.mjs";
|
||||||
|
import "./tests/FletcherChecksum.mjs";
|
||||||
|
import "./tests/CMAC.mjs";
|
||||||
|
import "./tests/AESKeyWrap.mjs";
|
||||||
|
import "./tests/Rabbit.mjs";
|
||||||
|
|
||||||
// Cannot test operations that use the File type yet
|
// Cannot test operations that use the File type yet
|
||||||
// import "./tests/SplitColourChannels.mjs";
|
// import "./tests/SplitColourChannels.mjs";
|
||||||
|
|
324
tests/operations/tests/AESKeyWrap.mjs
Normal file
324
tests/operations/tests/AESKeyWrap.mjs
Normal file
|
@ -0,0 +1,324 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: RFC Test Vector, 128-bit data, 128-bit KEK",
|
||||||
|
"input": "00112233445566778899aabbccddeeff",
|
||||||
|
"expectedOutput": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: RFC Test Vector, 128-bit data, 192-bit KEK",
|
||||||
|
"input": "00112233445566778899aabbccddeeff",
|
||||||
|
"expectedOutput": "96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f1011121314151617"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: RFC Test Vector, 128-bit data, 256-bit KEK",
|
||||||
|
"input": "00112233445566778899aabbccddeeff",
|
||||||
|
"expectedOutput": "64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: RFC Test Vector, 192-bit data, 192-bit KEK",
|
||||||
|
"input": "00112233445566778899aabbccddeeff0001020304050607",
|
||||||
|
"expectedOutput": "031d33264e15d33268f24ec260743edce1c6c7ddee725a936ba814915c6762d2",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f1011121314151617"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: RFC Test Vector, 192-bit data, 256-bit KEK",
|
||||||
|
"input": "00112233445566778899aabbccddeeff0001020304050607",
|
||||||
|
"expectedOutput": "a8f9bc1612c68b3ff6e6f4fbe30e71e4769c8b80a32cb8958cd5d17d6b254da1",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: RFC Test Vector, 256-bit data, 256-bit KEK",
|
||||||
|
"input": "00112233445566778899aabbccddeeff000102030405060708090a0b0c0d0e0f",
|
||||||
|
"expectedOutput": "28c9f404c4b810f4cbccb35cfb87f8263f5786e2d80ed326cbc7f0e71a99f43bfb988b9b7a02dd21",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: RFC Test Vector, 128-bit data, 128-bit KEK",
|
||||||
|
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5",
|
||||||
|
"expectedOutput": "00112233445566778899aabbccddeeff",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: RFC Test Vector, 128-bit data, 192-bit KEK",
|
||||||
|
"input": "96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d",
|
||||||
|
"expectedOutput": "00112233445566778899aabbccddeeff",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f1011121314151617"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: RFC Test Vector, 128-bit data, 256-bit KEK",
|
||||||
|
"input": "64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7",
|
||||||
|
"expectedOutput": "00112233445566778899aabbccddeeff",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: RFC Test Vector, 192-bit data, 192-bit KEK",
|
||||||
|
"input": "031d33264e15d33268f24ec260743edce1c6c7ddee725a936ba814915c6762d2",
|
||||||
|
"expectedOutput": "00112233445566778899aabbccddeeff0001020304050607",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f1011121314151617"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: RFC Test Vector, 192-bit data, 256-bit KEK",
|
||||||
|
"input": "a8f9bc1612c68b3ff6e6f4fbe30e71e4769c8b80a32cb8958cd5d17d6b254da1",
|
||||||
|
"expectedOutput": "00112233445566778899aabbccddeeff0001020304050607",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: RFC Test Vector, 256-bit data, 256-bit KEK",
|
||||||
|
"input": "28c9f404c4b810f4cbccb35cfb87f8263f5786e2d80ed326cbc7f0e71a99f43bfb988b9b7a02dd21",
|
||||||
|
"expectedOutput": "00112233445566778899aabbccddeeff000102030405060708090a0b0c0d0e0f",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: invalid KEK length",
|
||||||
|
"input": "00112233445566778899aabbccddeeff",
|
||||||
|
"expectedOutput": "KEK must be either 16, 24, or 32 bytes (currently 10 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00010203040506070809"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: invalid IV length",
|
||||||
|
"input": "00112233445566778899aabbccddeeff",
|
||||||
|
"expectedOutput": "IV must be 8 bytes (currently 6 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: input length not multiple of 8",
|
||||||
|
"input": "00112233445566778899aabbccddeeff0102",
|
||||||
|
"expectedOutput": "input must be 8n (n>=2) bytes (currently 18 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: input too short",
|
||||||
|
"input": "0011223344556677",
|
||||||
|
"expectedOutput": "input must be 8n (n>=2) bytes (currently 8 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: invalid KEK length",
|
||||||
|
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5",
|
||||||
|
"expectedOutput": "KEK must be either 16, 24, or 32 bytes (currently 10 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00010203040506070809"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: invalid IV length",
|
||||||
|
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5",
|
||||||
|
"expectedOutput": "IV must be 8 bytes (currently 6 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: input length not multiple of 8",
|
||||||
|
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5e621",
|
||||||
|
"expectedOutput": "input must be 8n (n>=3) bytes (currently 26 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: input too short",
|
||||||
|
"input": "1fa68b0a8112b447aef34bd8fb5a7b82",
|
||||||
|
"expectedOutput": "input must be 8n (n>=3) bytes (currently 16 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: corrupted input",
|
||||||
|
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe6",
|
||||||
|
"expectedOutput": "IV mismatch",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
|
@ -16,6 +16,10 @@ DIb:@FD,*)+C]U=@3BN#EcYf8ATD3s@q?d$AftVqCh[NqF<G:8+EV:.+Cf>-FD5W8ARlolDIal(\
|
||||||
DId<j@<?3r@:F%a+D58'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G>u\
|
DId<j@<?3r@:F%a+D58'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G>u\
|
||||||
D.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c";
|
D.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c";
|
||||||
|
|
||||||
|
const allZeroExample = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";
|
||||||
|
|
||||||
|
const allZeroOutput = "zz!!*-'\"9eu7#RLhG$k3[W&.oNg'GVB\"(`=52*$$(B+<_pR,UFcb-n-Vr/1iJ-0JP==1c70M3&s#]4?Ykm5X@_(6q'R884cEH9MJ8X:f1+h<)lt#=BSg3>[:ZC?t!MSA7]@cBPD3sCi+'.E,fo>FEMbNG^4U^I!pHnJ:W<)KS>/9Ll%\"IN/`jYOHG]iPa.Q$R$jD4S=Q7DTV8*TUnsrdW2ZetXKAY/Yd(L?['d?O\\@K2_]Y2%o^qmn*`5Ta:aN;TJbg\"GZd*^:jeCE.%f\\,!5gtgiEi8N\\UjQ5OekiqBum-X60nF?)@o_%qPq\"ad`r;HWp";
|
||||||
|
|
||||||
TestRegister.addTests([
|
TestRegister.addTests([
|
||||||
{
|
{
|
||||||
name: "To Base85",
|
name: "To Base85",
|
||||||
|
@ -45,4 +49,22 @@ TestRegister.addTests([
|
||||||
"args": ["!-u", false] }
|
"args": ["!-u", false] }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "To Base85",
|
||||||
|
input: allZeroExample,
|
||||||
|
expectedOutput: allZeroOutput,
|
||||||
|
recipeConfig: [
|
||||||
|
{ "op": "To Base85",
|
||||||
|
"args": ["!-u"] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Base85",
|
||||||
|
input: allZeroOutput,
|
||||||
|
expectedOutput: allZeroExample,
|
||||||
|
recipeConfig: [
|
||||||
|
{ "op": "From Base85",
|
||||||
|
"args": ["!-u", true, "z"] }
|
||||||
|
]
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
314
tests/operations/tests/CMAC.mjs
Normal file
314
tests/operations/tests/CMAC.mjs
Normal file
|
@ -0,0 +1,314 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
// values in "NIST's CSRC" testcases are taken from here:
|
||||||
|
// https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES128 NIST's CSRC Example #1",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "bb1d6929e95937287fa37d129b756746",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "2b7e151628aed2a6abf7158809cf4f3c"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES128 NIST's CSRC Example #2",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172a",
|
||||||
|
"expectedOutput": "070a16b46b4d4144f79bdd9dd04a287c",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "2b7e151628aed2a6abf7158809cf4f3c"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES128 NIST's CSRC Example #3",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a57",
|
||||||
|
"expectedOutput": "7d85449ea6ea19c823a7bf78837dfade",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "2b7e151628aed2a6abf7158809cf4f3c"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES128 NIST's CSRC Example #4",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
|
||||||
|
"expectedOutput": "51f0bebf7e3b9d92fc49741779363cfe",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "2b7e151628aed2a6abf7158809cf4f3c"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES192 NIST's CSRC Example #1",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "d17ddf46adaacde531cac483de7a9367",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES192 NIST's CSRC Example #2",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172a",
|
||||||
|
"expectedOutput": "9e99a7bf31e710900662f65e617c5184",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES192 NIST's CSRC Example #3",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a57",
|
||||||
|
"expectedOutput": "3d75c194ed96070444a9fa7ec740ecf8",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES192 NIST's CSRC Example #4",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
|
||||||
|
"expectedOutput": "a1d5df0eed790f794d77589659f39a11",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES256 NIST's CSRC Example #1",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "028962f61b7bf89efc6b551f4667d983",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES256 NIST's CSRC Example #2",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172a",
|
||||||
|
"expectedOutput": "28a7023f452e8f82bd4bf28d8c37c35c",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES256 NIST's CSRC Example #3",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a57",
|
||||||
|
"expectedOutput": "156727dc0878944a023c1fe03bad6d93",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES256 NIST's CSRC Example #4",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
|
||||||
|
"expectedOutput": "e1992190549f6ed5696a2c056c315410",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (1) NIST's CSRC Sample #1",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "7db0d37df936c550",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef01456789abcdef0123"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (1) NIST's CSRC Sample #2",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172a",
|
||||||
|
"expectedOutput": "30239cf1f52e6609",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef01456789abcdef0123"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (1) NIST's CSRC Sample #3",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a57",
|
||||||
|
"expectedOutput": "6c9f3ee4923f6be2",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef01456789abcdef0123"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (1) NIST's CSRC Sample #4",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51",
|
||||||
|
"expectedOutput": "99429bd0bf7904e5",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef01456789abcdef0123"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (2) NIST's CSRC Sample #1",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "79ce52a7f786a960",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef010123456789abcdef"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (2) NIST's CSRC Sample #2",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172a",
|
||||||
|
"expectedOutput": "cc18a0b79af2413b",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef010123456789abcdef"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (2) NIST's CSRC Sample #3",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a57",
|
||||||
|
"expectedOutput": "c06d377ecd101969",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef010123456789abcdef"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (2) NIST's CSRC Sample #4",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51",
|
||||||
|
"expectedOutput": "9cd33580f9b64dfb",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef010123456789abcdef"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES: invalid key length",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "The key for AES must be either 16, 24, or 32 bytes (currently 20 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "00112233445566778899aabbccddeeff01234567"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES: invalid key length",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "The key for Triple DES must be 16 or 24 bytes (currently 20 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "00112233445566778899aabbccddeeff01234567"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]);
|
151
tests/operations/tests/ChaCha.mjs
Normal file
151
tests/operations/tests/ChaCha.mjs
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/**
|
||||||
|
* ChaCha tests.
|
||||||
|
*
|
||||||
|
* @author joostrijneveld [joost@joostrijneveld.nl]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "ChaCha: no key",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: `Invalid key length: 0 bytes.
|
||||||
|
|
||||||
|
ChaCha uses a key of 16 or 32 bytes (128 or 256 bits).`,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
0, "20", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: no nonce",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: `Invalid nonce length: 0 bytes.
|
||||||
|
|
||||||
|
ChaCha uses a nonce of 8 or 12 bytes (64 or 96 bits).`,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
0, "20", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: RFC8439",
|
||||||
|
input: "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.",
|
||||||
|
expectedOutput: "6e 2e 35 9a 25 68 f9 80 41 ba 07 28 dd 0d 69 81 e9 7e 7a ec 1d 43 60 c2 0a 27 af cc fd 9f ae 0b f9 1b 65 c5 52 47 33 ab 8f 59 3d ab cd 62 b3 57 16 39 d6 24 e6 51 52 ab 8f 53 0c 35 9f 08 61 d8 07 ca 0d bf 50 0d 6a 61 56 a3 8e 08 8a 22 b6 5e 52 bc 51 4d 16 cc f8 06 81 8c e9 1a b7 79 37 36 5a f9 0b bf 74 a3 5b e6 b4 0b 8e ed f2 78 5e 42 87 4d",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f"},
|
||||||
|
{"option": "Hex", "string": "00:00:00:00:00:00:00:4a:00:00:00:00"},
|
||||||
|
1, "20", "Raw", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: draft-strombergson-chacha-test-vectors-01 TC7.1",
|
||||||
|
input: "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
||||||
|
expectedOutput: "29 56 0d 28 0b 45 28 40 0a 8f 4b 79 53 69 fb 3a 01 10 55 99 e9 f1 ed 58 27 9c fc 9e ce 2d c5 f9 9f 1c 2e 52 c9 82 38 f5 42 a5 c0 a8 81 d8 50 b6 15 d3 ac d9 fb db 02 6e 93 68 56 5d a5 0e 0d 49 dd 5b e8 ef 74 24 8b 3e 25 1d 96 5d 8f cb 21 e7 cf e2 04 d4 00 78 06 fb ee 3c e9 4c 74 bf ba d2 c1 1c 62 1b a0 48 14 7c 5c aa 94 d1 82 cc ff 6f d5 cf 44 ad f9 6e 3d 68 28 1b b4 96 76 af 87 e7",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff"},
|
||||||
|
{"option": "Hex", "string": "0f 1e 2d 3c 4b 5a 69 78"},
|
||||||
|
0, "8", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: draft-strombergson-chacha-test-vectors-01 TC7.2",
|
||||||
|
input: "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
||||||
|
expectedOutput: "5e dd c2 d9 42 8f ce ee c5 0a 52 a9 64 ea e0 ff b0 4b 2d e0 06 a9 b0 4c ff 36 8f fa 92 11 16 b2 e8 e2 64 ba bd 2e fa 0d e4 3e f2 e3 b6 d0 65 e8 f7 c0 a1 78 37 b0 a4 0e b0 e2 c7 a3 74 2c 87 53 ed e5 f3 f6 d1 9b e5 54 67 5e 50 6a 77 5c 63 f0 94 d4 96 5c 31 93 19 dc d7 50 6f 45 7b 11 7b 84 b1 0b 24 6e 95 6c 2d a8 89 8a 65 6c ee f3 f7 b7 16 45 b1 9f 70 1d b8 44 85 ce 51 21 f0 f6 17 ef",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff"},
|
||||||
|
{"option": "Hex", "string": "0f 1e 2d 3c 4b 5a 69 78"},
|
||||||
|
0, "12", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: draft-strombergson-chacha-test-vectors-01 TC7.3",
|
||||||
|
input: "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
||||||
|
expectedOutput: "d1 ab f6 30 46 7e b4 f6 7f 1c fb 47 cd 62 6a ae 8a fe db be 4f f8 fc 5f e9 cf ae 30 7e 74 ed 45 1f 14 04 42 5a d2 b5 45 69 d5 f1 81 48 93 99 71 ab b8 fa fc 88 ce 4a c7 fe 1c 3d 1f 7a 1e b7 ca e7 6c a8 7b 61 a9 71 35 41 49 77 60 dd 9a e0 59 35 0c ad 0d ce df aa 80 a8 83 11 9a 1a 6f 98 7f d1 ce 91 fd 8e e0 82 80 34 b4 11 20 0a 97 45 a2 85 55 44 75 d1 2a fc 04 88 7f ef 35 16 d1 2a 2c",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff"},
|
||||||
|
{"option": "Hex", "string": "0f 1e 2d 3c 4b 5a 69 78"},
|
||||||
|
0, "20", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: draft-strombergson-chacha-test-vectors-01 TC7.4",
|
||||||
|
input: "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
||||||
|
expectedOutput: "db 43 ad 9d 1e 84 2d 12 72 e4 53 0e 27 6b 3f 56 8f 88 59 b3 f7 cf 6d 9d 2c 74 fa 53 80 8c b5 15 7a 8e bf 46 ad 3d cc 4b 6c 7d ad de 13 17 84 b0 12 0e 0e 22 f6 d5 f9 ff a7 40 7d 4a 21 b6 95 d9 c5 dd 30 bf 55 61 2f ab 9b dd 11 89 20 c1 98 16 47 0c 7f 5d cd 42 32 5d bb ed 8c 57 a5 62 81 c1 44 cb 0f 03 e8 1b 30 04 62 4e 06 50 a1 ce 5a fa f9 a7 cd 81 63 f6 db d7 26 02 25 7d d9 6e 47 1e",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff ff ee dd cc bb aa 99 88 77 66 55 44 33 22 11 00"},
|
||||||
|
{"option": "Hex", "string": "0f 1e 2d 3c 4b 5a 69 78"},
|
||||||
|
0, "8", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: draft-strombergson-chacha-test-vectors-01 TC7.5",
|
||||||
|
input: "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
||||||
|
expectedOutput: "7e d1 2a 3a 63 91 2a e9 41 ba 6d 4c 0d 5e 86 2e 56 8b 0e 55 89 34 69 35 50 5f 06 4b 8c 26 98 db f7 d8 50 66 7d 8e 67 be 63 9f 3b 4f 6a 16 f9 2e 65 ea 80 f6 c7 42 94 45 da 1f c2 c1 b9 36 50 40 e3 2e 50 c4 10 6f 3b 3d a1 ce 7c cb 1e 71 40 b1 53 49 3c 0f 3a d9 a9 bc ff 07 7e c4 59 6f 1d 0f 29 bf 9c ba a5 02 82 0f 73 2a f5 a9 3c 49 ee e3 3d 1c 4f 12 af 3b 42 97 af 91 fe 41 ea 9e 94 a2",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff ff ee dd cc bb aa 99 88 77 66 55 44 33 22 11 00"},
|
||||||
|
{"option": "Hex", "string": "0f 1e 2d 3c 4b 5a 69 78"},
|
||||||
|
0, "12", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: draft-strombergson-chacha-test-vectors-01 TC7.6",
|
||||||
|
input: "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
||||||
|
expectedOutput: "9f ad f4 09 c0 08 11 d0 04 31 d6 7e fb d8 8f ba 59 21 8d 5d 67 08 b1 d6 85 86 3f ab bb 0e 96 1e ea 48 0f d6 fb 53 2b fd 49 4b 21 51 01 50 57 42 3a b6 0a 63 fe 4f 55 f7 a2 12 e2 16 7c ca b9 31 fb fd 29 cf 7b c1 d2 79 ed df 25 dd 31 6b b8 84 3d 6e de e0 bd 1e f1 21 d1 2f a1 7c bc 2c 57 4c cc ab 5e 27 51 67 b0 8b d6 86 f8 a0 9d f8 7e c3 ff b3 53 61 b9 4e bf a1 3f ec 0e 48 89 d1 8d a5",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff ff ee dd cc bb aa 99 88 77 66 55 44 33 22 11 00"},
|
||||||
|
{"option": "Hex", "string": "0f 1e 2d 3c 4b 5a 69 78"},
|
||||||
|
0, "20", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
|
@ -185,11 +185,11 @@ TestRegister.addTests([
|
||||||
{
|
{
|
||||||
name: "JPath Expression: Empty expression",
|
name: "JPath Expression: Empty expression",
|
||||||
input: JSON.stringify(JSON_TEST_DATA),
|
input: JSON.stringify(JSON_TEST_DATA),
|
||||||
expectedOutput: "Invalid JPath expression: we need a path",
|
expectedOutput: "",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "JPath expression",
|
"op": "JPath expression",
|
||||||
"args": ["", "\n"]
|
"args": ["", "\n", true]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -205,7 +205,7 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "JPath expression",
|
"op": "JPath expression",
|
||||||
"args": ["$.store.book[*].author", "\n"]
|
"args": ["$.store.book[*].author", "\n", true]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -223,7 +223,7 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "JPath expression",
|
"op": "JPath expression",
|
||||||
"args": ["$..title", "\n"]
|
"args": ["$..title", "\n", true]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -238,7 +238,7 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "JPath expression",
|
"op": "JPath expression",
|
||||||
"args": ["$.store.*", "\n"]
|
"args": ["$.store.*", "\n", true]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -249,7 +249,7 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "JPath expression",
|
"op": "JPath expression",
|
||||||
"args": ["$..book[-1:]", "\n"]
|
"args": ["$..book[-1:]", "\n", true]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -263,7 +263,7 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "JPath expression",
|
"op": "JPath expression",
|
||||||
"args": ["$..book[:2]", "\n"]
|
"args": ["$..book[:2]", "\n", true]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -277,7 +277,7 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "JPath expression",
|
"op": "JPath expression",
|
||||||
"args": ["$..book[?(@.isbn)]", "\n"]
|
"args": ["$..book[?(@.isbn)]", "\n", false]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -292,7 +292,7 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "JPath expression",
|
"op": "JPath expression",
|
||||||
"args": ["$..book[?(@.price<30 && @.category==\"fiction\")]", "\n"]
|
"args": ["$..book[?(@.price<30 && @.category==\"fiction\")]", "\n", false]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -306,10 +306,25 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "JPath expression",
|
"op": "JPath expression",
|
||||||
"args": ["$..book[?(@.price<10)]", "\n"]
|
"args": ["$..book[?(@.price<10)]", "\n", false]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "JPath Expression: Script-based expression",
|
||||||
|
input: "[{}]",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "JPath expression",
|
||||||
|
"args": [
|
||||||
|
"$..[?(({__proto__:[].constructor}).constructor(\"self.postMessage({action:'bakeComplete',data:{bakeId:1,dish:{type:1,value:''},duration:1,error:false,id:undefined,inputNum:2,progress:1,result:'<iframe/onload=debugger>',type: 'html'}});\")();)]",
|
||||||
|
"\n",
|
||||||
|
true
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
expectedOutput: "Invalid JPath expression: Eval [?(expr)] prevented in JSONPath expression."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "CSS selector",
|
name: "CSS selector",
|
||||||
input: '<div id="test">\n<p class="a">hello</p>\n<p>world</p>\n<p class="a">again</p>\n</div>',
|
input: '<div id="test">\n<p class="a">hello</p>\n<p>world</p>\n<p class="a">again</p>\n</div>',
|
||||||
|
|
|
@ -23,4 +23,86 @@ TestRegister.addTests([
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "LZMA compress & decompress",
|
||||||
|
input: "The cat sat on the mat.",
|
||||||
|
// Generated using command `echo -n "The cat sat on the mat." | lzma -z -6 | xxd -p`
|
||||||
|
expectedOutput: "The cat sat on the mat.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "LZMA Compress",
|
||||||
|
"args": ["6"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "LZMA Decompress",
|
||||||
|
"args": []
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "LZMA decompress: binary",
|
||||||
|
// Generated using command `echo "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10" | xxd -r -p | lzma -z -6 | xxd -p`
|
||||||
|
input: "5d00008000ffffffffffffffff00000052500a84f99bb28021a969d627e03e8a922effffbd160000",
|
||||||
|
expectedOutput: "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["Space"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "LZMA Decompress",
|
||||||
|
"args": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "To Hex",
|
||||||
|
"args": ["Space", 0]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "LZMA decompress: string",
|
||||||
|
// Generated using command `echo -n "The cat sat on the mat." | lzma -z -6 | xxd -p`
|
||||||
|
input: "5d00008000ffffffffffffffff002a1a08a202b1a4b814b912c94c4152e1641907d3fd8cd903ffff4fec0000",
|
||||||
|
expectedOutput: "The cat sat on the mat.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["Space"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "LZMA Decompress",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "LZ4 Compress",
|
||||||
|
input: "The cat sat on the mat.",
|
||||||
|
expectedOutput: "04224d184070df170000805468652063617420736174206f6e20746865206d61742e00000000",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "LZ4 Compress",
|
||||||
|
"args": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "To Hex",
|
||||||
|
"args": ["None", 0]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "LZ4 Decompress",
|
||||||
|
input: "04224d184070df170000805468652063617420736174206f6e20746865206d61742e00000000",
|
||||||
|
expectedOutput: "The cat sat on the mat.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "LZ4 Decompress",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
108
tests/operations/tests/FletcherChecksum.mjs
Normal file
108
tests/operations/tests/FletcherChecksum.mjs
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Fletcher-16 Checksum: abcde",
|
||||||
|
input: "abcde",
|
||||||
|
expectedOutput: "c8f0",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-16 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-16 Checksum: abcdef",
|
||||||
|
input: "abcdef",
|
||||||
|
expectedOutput: "2057",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-16 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-16 Checksum: abcdefgh",
|
||||||
|
input: "abcdefgh",
|
||||||
|
expectedOutput: "0627",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-16 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-32 Checksum: abcde",
|
||||||
|
input: "abcde",
|
||||||
|
expectedOutput: "f04fc729",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-32 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-32 Checksum: abcdef",
|
||||||
|
input: "abcdef",
|
||||||
|
expectedOutput: "56502d2a",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-32 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-32 Checksum: abcdefgh",
|
||||||
|
input: "abcdefgh",
|
||||||
|
expectedOutput: "ebe19591",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-32 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-64 Checksum: abcde",
|
||||||
|
input: "abcde",
|
||||||
|
expectedOutput: "c8c6c527646362c6",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-64 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-64 Checksum: abcdef",
|
||||||
|
input: "abcdef",
|
||||||
|
expectedOutput: "c8c72b276463c8c6",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-64 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-64 Checksum: abcdefgh",
|
||||||
|
input: "abcdefgh",
|
||||||
|
expectedOutput: "312e2b28cccac8c6",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-64 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
115
tests/operations/tests/GenerateAllHashes.mjs
Normal file
115
tests/operations/tests/GenerateAllHashes.mjs
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
/**
|
||||||
|
* GenerateAllHashes tests.
|
||||||
|
*
|
||||||
|
* @author john19696 [john19696@protonmail.com]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Full generate all hashes",
|
||||||
|
input: "test",
|
||||||
|
expectedOutput: `MD2: dd34716876364a02d0195e2fb9ae2d1b
|
||||||
|
MD4: db346d691d7acc4dc2625db19f9e3f52
|
||||||
|
MD5: 098f6bcd4621d373cade4e832627b4f6
|
||||||
|
MD6: 93c8a7d0ff132f325138a82b2baa98c12a7c9ac982feb6c5b310a1ca713615bd
|
||||||
|
SHA0: f8d3b312442a67706057aeb45b983221afb4f035
|
||||||
|
SHA1: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
|
||||||
|
SHA2 224: 90a3ed9e32b2aaf4c61c410eb925426119e1a9dc53d4286ade99a809
|
||||||
|
SHA2 256: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
|
||||||
|
SHA2 384: 768412320f7b0aa5812fce428dc4706b3cae50e02a64caa16a782249bfe8efc4b7ef1ccb126255d196047dfedf17a0a9
|
||||||
|
SHA2 512: ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff
|
||||||
|
SHA3 224: 3797bf0afbbfca4a7bbba7602a2b552746876517a7f9b7ce2db0ae7b
|
||||||
|
SHA3 256: 36f028580bb02cc8272a9a020f4200e346e276ae664e45ee80745574e2f5ab80
|
||||||
|
SHA3 384: e516dabb23b6e30026863543282780a3ae0dccf05551cf0295178d7ff0f1b41eecb9db3ff219007c4e097260d58621bd
|
||||||
|
SHA3 512: 9ece086e9bac491fac5c1d1046ca11d737b92a2b2ebd93f005d7b710110c0a678288166e7fbe796883a4f2e9b3ca9f484f521d0ce464345cc1aec96779149c14
|
||||||
|
Keccak 224: 3be30a9ff64f34a5861116c5198987ad780165f8366e67aff4760b5e
|
||||||
|
Keccak 256: 9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658
|
||||||
|
Keccak 384: 53d0ba137307d4c2f9b6674c83edbd58b70c0f4340133ed0adc6fba1d2478a6a03b7788229e775d2de8ae8c0759d0527
|
||||||
|
Keccak 512: 1e2e9fc2002b002d75198b7503210c05a1baac4560916a3c6d93bcce3a50d7f00fd395bf1647b9abb8d1afcc9c76c289b0c9383ba386a956da4b38934417789e
|
||||||
|
Shake 128: d3b0aa9cd8b7255622cebc631e867d4093d6f6010191a53973c45fec9b07c774
|
||||||
|
Shake 256: b54ff7255705a71ee2925e4a3e30e41aed489a579d5595e0df13e32e1e4dd202a7c7f68b31d6418d9845eb4d757adda6ab189e1bb340db818e5b3bc725d992fa
|
||||||
|
RIPEMD-128: f1abb5083c9ff8a9dbbca9cd2b11fead
|
||||||
|
RIPEMD-160: 5e52fee47e6b070565f74372468cdc699de89107
|
||||||
|
RIPEMD-256: fe0289110d07daeee9d9500e14c57787d9083f6ba10e6bcb256f86bb4fe7b981
|
||||||
|
RIPEMD-320: 3b0a2e841e589cf583634a5dd265d2b5d497c4cc44b241e34e0f62d03e98c1b9dc72970b9bc20eb5
|
||||||
|
HAS-160: cb15e491eec6e769771d1f811315139c93071084
|
||||||
|
Whirlpool-0: d50ff71342b521974bae166539871922669afcfc7181250ebbae015c317ebb797173a69e7a05afd11099a9f0918159cd5bc88434d3ca44513d7263caea9244fe
|
||||||
|
Whirlpool-T: e6b4aa087751b4428171777f1893ba585404c7e0171787720eba0d8bccd710dc2c42f874c572bfae4cedabf50f2c80bf923805d4e31c504b86ca3bc59265e7dd
|
||||||
|
Whirlpool: b913d5bbb8e461c2c5961cbe0edcdadfd29f068225ceb37da6defcf89849368f8c6c2eb6a4c4ac75775d032a0ecfdfe8550573062b653fe92fc7b8fb3b7be8d6
|
||||||
|
BLAKE2b-128: 44a8995dd50b6657a037a7839304535b
|
||||||
|
BLAKE2b-160: a34fc3b6d2cce8beb3216c2bbb5e55739e8121ed
|
||||||
|
BLAKE2b-256: 928b20366943e2afd11ebc0eae2e53a93bf177a4fcf35bcc64d503704e65e202
|
||||||
|
BLAKE2b-384: 8a84b8666c8fcfb69f2ec41f578d7c85fbdb504ea6510fb05b50fcbf7ed8153c77943bc2da73abb136834e1a0d4f22cb
|
||||||
|
BLAKE2b-512: a71079d42853dea26e453004338670a53814b78137ffbed07603a41d76a483aa9bc33b582f77d30a65e6f29a896c0411f38312e1d66e0bf16386c86a89bea572
|
||||||
|
BLAKE2s-128: e9ddd9926b9dcb382e09be39ba403d2c
|
||||||
|
BLAKE2s-160: d6197dabec2bd6f4ff303b8e519e8f15d42a453d
|
||||||
|
BLAKE2s-256: f308fc02ce9172ad02a7d75800ecfc027109bc67987ea32aba9b8dcc7b10150e
|
||||||
|
Streebog-256: 12a50838191b5504f1e5f2fd078714cf6b592b9d29af99d0b10d8d02881c3857
|
||||||
|
Streebog-512: 7200bf5dea560f0d7960d07fdc8874ad9f3b86ece2e45f5502ae2e176f2c928e0e581152281f5aee818318bed7cbe6aa69999589234723ceb33175598365b5c8
|
||||||
|
GOST: ee67303696d205ddd2b2363e8e01b4b7199a80957d94d7678eaad3fc834c5a27
|
||||||
|
LM Hash: 01FC5A6BE7BC6929AAD3B435B51404EE
|
||||||
|
NT Hash: 0CB6948805F797BF2A82807973B89537
|
||||||
|
SSDEEP: 3:Hn:Hn
|
||||||
|
CTPH: A:E:E
|
||||||
|
|
||||||
|
Checksums:
|
||||||
|
Fletcher-8: 3d
|
||||||
|
Fletcher-16: 5dc1
|
||||||
|
Fletcher-32: 3f5cd9e7
|
||||||
|
Fletcher-64: 7473657474736574
|
||||||
|
Adler-32: 045d01c1
|
||||||
|
CRC-8: b9
|
||||||
|
CRC-16: f82e
|
||||||
|
CRC-32: d87f7e0c
|
||||||
|
`,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Generate all hashes",
|
||||||
|
"args": ["All", true]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Hashes with length 32",
|
||||||
|
input: "test",
|
||||||
|
expectedOutput: `MD2: dd34716876364a02d0195e2fb9ae2d1b
|
||||||
|
MD4: db346d691d7acc4dc2625db19f9e3f52
|
||||||
|
MD5: 098f6bcd4621d373cade4e832627b4f6
|
||||||
|
RIPEMD-128: f1abb5083c9ff8a9dbbca9cd2b11fead
|
||||||
|
BLAKE2b-128: 44a8995dd50b6657a037a7839304535b
|
||||||
|
BLAKE2s-128: e9ddd9926b9dcb382e09be39ba403d2c
|
||||||
|
LM Hash: 01FC5A6BE7BC6929AAD3B435B51404EE
|
||||||
|
NT Hash: 0CB6948805F797BF2A82807973B89537
|
||||||
|
`,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Generate all hashes",
|
||||||
|
"args": ["128", true]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Hashes without names",
|
||||||
|
input: "test",
|
||||||
|
expectedOutput: `93c8a7d0ff132f325138a82b2baa98c12a7c9ac982feb6c5b310a1ca713615bd
|
||||||
|
9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
|
||||||
|
36f028580bb02cc8272a9a020f4200e346e276ae664e45ee80745574e2f5ab80
|
||||||
|
9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658
|
||||||
|
d3b0aa9cd8b7255622cebc631e867d4093d6f6010191a53973c45fec9b07c774
|
||||||
|
fe0289110d07daeee9d9500e14c57787d9083f6ba10e6bcb256f86bb4fe7b981
|
||||||
|
928b20366943e2afd11ebc0eae2e53a93bf177a4fcf35bcc64d503704e65e202
|
||||||
|
f308fc02ce9172ad02a7d75800ecfc027109bc67987ea32aba9b8dcc7b10150e
|
||||||
|
12a50838191b5504f1e5f2fd078714cf6b592b9d29af99d0b10d8d02881c3857
|
||||||
|
ee67303696d205ddd2b2363e8e01b4b7199a80957d94d7678eaad3fc834c5a27
|
||||||
|
`,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Generate all hashes",
|
||||||
|
"args": ["256", false]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]);
|
|
@ -46,6 +46,17 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "JSON to CSV: boolean and null as values",
|
||||||
|
input: JSON.stringify({a: false, b: null, c: 3}),
|
||||||
|
expectedOutput: "a,b,c\r\nfalse,null,3\r\n",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "JSON to CSV",
|
||||||
|
args: [",", "\\r\\n"]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "JSON to CSV: JSON as an array",
|
name: "JSON to CSV: JSON as an array",
|
||||||
input: JSON.stringify([{a: 1, b: "2", c: 3}]),
|
input: JSON.stringify([{a: 1, b: "2", c: 3}]),
|
||||||
|
|
34
tests/operations/tests/NTLM.mjs
Normal file
34
tests/operations/tests/NTLM.mjs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* NTLM test.
|
||||||
|
*
|
||||||
|
* @author brun0ne [brunonblok@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "NT Hash",
|
||||||
|
input: "QWERTYUIOPASDFGHJKLZXCVBNM1234567890!@#$%^&*()_+.,?/",
|
||||||
|
expectedOutput: "C5FA1C40E55734A8E528DBFE21766D23",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "NT Hash",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "LM Hash",
|
||||||
|
input: "QWERTYUIOPASDFGHJKLZXCVBNM1234567890!@#$%^&*()_+.,?/",
|
||||||
|
expectedOutput: "6D9DF16655336CA75A3C13DD18BA8156",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "LM Hash",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
]);
|
|
@ -49,6 +49,18 @@ Point: 0x046c59592006272250a15070142a6be36d1e45464313f930d985a6e6f0eba3cd39d0367
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "SSH Host Key: Ed25519",
|
||||||
|
input: "AAAAC3NzaC1lZDI1NTE5AAAAIBOF6r99IkvqGu1kwZrHHIqjpTB5w79bpv67B/Aw3+WJ",
|
||||||
|
expectedOutput: `Key type: ssh-ed25519
|
||||||
|
x: 0x1385eabf7d224bea1aed64c19ac71c8aa3a53079c3bf5ba6febb07f030dfe589`,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Parse SSH Host Key",
|
||||||
|
args: ["Base64"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "SSH Host Key: Extract key",
|
name: "SSH Host Key: Extract key",
|
||||||
input: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDiJZ/9W9Ix/Dk9b+K4E+RGCug1AtkGXaJ9vNIY0YHFHLpWsB8DAuh/cGEI9TLbL1gzR2wG+RJNQ2EAQVWe6ypkK63Jm4zw4re+vhEiszpnP889J0h5N9yzyTndesrl4d3cQtv861FcKDPxUJbRALdtl6gwOB7BCL8gsXJLLVLO4EesrbPXD454qpVt7CgJXEXByOFjcIm3XwkdOnXMPHHnMSD7EIN1SvQMD6PfIDrbDd6KQt5QXW/Rc/BsfX5cbUIV1QW5A/GbepXHHKmWRtLC2J/mH3hW2Zq/hITPEaJdG1CtIilQmJaZGXpfGIwFeb0Av9pSL926arZZ6vDi9ctF test@test",
|
input: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDiJZ/9W9Ix/Dk9b+K4E+RGCug1AtkGXaJ9vNIY0YHFHLpWsB8DAuh/cGEI9TLbL1gzR2wG+RJNQ2EAQVWe6ypkK63Jm4zw4re+vhEiszpnP889J0h5N9yzyTndesrl4d3cQtv861FcKDPxUJbRALdtl6gwOB7BCL8gsXJLLVLO4EesrbPXD454qpVt7CgJXEXByOFjcIm3XwkdOnXMPHHnMSD7EIN1SvQMD6PfIDrbDd6KQt5QXW/Rc/BsfX5cbUIV1QW5A/GbepXHHKmWRtLC2J/mH3hW2Zq/hITPEaJdG1CtIilQmJaZGXpfGIwFeb0Av9pSL926arZZ6vDi9ctF test@test",
|
||||||
|
|
177
tests/operations/tests/Rabbit.mjs
Normal file
177
tests/operations/tests/Rabbit.mjs
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Rabbit: RFC Test vector, without IV 1",
|
||||||
|
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
expectedOutput: "b15754f036a5d6ecf56b45261c4af70288e8d815c59c0c397b696c4789c68aa7f416a1c3700cd451da68d1881673d696",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: RFC Test vector, without IV 2",
|
||||||
|
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
expectedOutput: "3d2df3c83ef627a1e97fc38487e2519cf576cd61f4405b8896bf53aa8554fc19e5547473fbdb43508ae53b20204d4c5e",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "912813292e3d36fe3bfc62f1dc51c3ac"},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: RFC Test vector, without IV 3",
|
||||||
|
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
expectedOutput: "0cb10dcda041cdac32eb5cfd02d0609b95fc9fca0f17015a7b7092114cff3ead9649e5de8bfc7f3f924147ad3a947428",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "8395741587e0c733e9e9ab01c09b0043"},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: RFC Test vector, with IV 1",
|
||||||
|
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
expectedOutput: "c6a7275ef85495d87ccd5d376705b7ed5f29a6ac04f5efd47b8f293270dc4a8d2ade822b29de6c1ee52bdb8a47bf8f66",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": "0000000000000000"},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: RFC Test vector, with IV 2",
|
||||||
|
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
expectedOutput: "1fcd4eb9580012e2e0dccc9222017d6da75f4e10d12125017b2499ffed936f2eebc112c393e738392356bdd012029ba7",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": "c373f575c1267e59"},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: RFC Test vector, with IV 3",
|
||||||
|
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
expectedOutput: "445ad8c805858dbf70b6af23a151104d96c8f27947f42c5baeae67c6acc35b039fcbfc895fa71c17313df034f01551cb",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": "a6eb561ad2f41727"},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: generated stream should be XORed with the input",
|
||||||
|
input: "cedda96c054e3ddd93da7ed05e2a4b7bdb0c00fe214f03502e2708b2c2bfc77aa2311b0b9af8aa78d119f92b26db0a6b",
|
||||||
|
expectedOutput: "7f8afd9c33ebeb3166b13bf64260bc7953e4d8ebe4d30f69554e64f54b794ddd5627bac8eaf47e290b7128a330a8dcfd",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: least significant bits should be used for the last block",
|
||||||
|
input: "0000000000000000",
|
||||||
|
expectedOutput: "f56b45261c4af702",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: invalid key length",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: "Invalid key length: 8 bytes (expected: 16)",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "0000000000000000"},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: invalid IV length",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: "Invalid IV length: 4 bytes (expected: 0 or 8)",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": "00000000"},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// this testcase is taken from the first example on Crypto++ Wiki
|
||||||
|
// https://www.cryptopp.com/wiki/Rabbit
|
||||||
|
name: "Rabbit: little-endian mode (Crypto++ compatible)",
|
||||||
|
input: "Rabbit stream cipher test",
|
||||||
|
expectedOutput: "1ae2d4edcf9b6063b00fd6fda0b223aded157e77031cf0440b",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "23c2731e8b5469fd8dabb5bc592a0f3a"},
|
||||||
|
{"option": "Hex", "string": "712906405ef03201"},
|
||||||
|
"Little", "Raw", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]);
|
54
tests/operations/tests/Shuffle.mjs
Normal file
54
tests/operations/tests/Shuffle.mjs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
"name": "Shuffle empty",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "Shuffle",
|
||||||
|
"args": ["Comma"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Shuffle bytes",
|
||||||
|
"input": "12345678",
|
||||||
|
"expectedOutput": "31 32 33 34 35 36 37 38",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "Shuffle",
|
||||||
|
"args": ["Nothing (separate chars)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "To Hex",
|
||||||
|
"args": ["Space", 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "Sort",
|
||||||
|
"args": ["Space", false, "Alphabetical (case sensitive)"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Shuffle lines",
|
||||||
|
"input": "1\n2\n3\n4\n5\n6\n7\n8\n9\na\nb\nc\nd\ne\nf\n",
|
||||||
|
"expectedOutput": "\n1\n2\n3\n4\n5\n6\n7\n8\n9\na\nb\nc\nd\ne\nf",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "Shuffle",
|
||||||
|
"args": ["Line feed"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "Sort",
|
||||||
|
"args": ["Line feed", false, "Alphabetical (case sensitive)"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]);
|
55
tests/operations/tests/UnescapeString.mjs
Normal file
55
tests/operations/tests/UnescapeString.mjs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
* UnescapeString tests.
|
||||||
|
*
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "UnescapeString: escape sequences",
|
||||||
|
input: "\\a\\b\\f\\n\\r\\t\\v\\'\\\"",
|
||||||
|
expectedOutput: String.fromCharCode(0x07, 0x08, 0x0c, 0x0a, 0x0d, 0x09,
|
||||||
|
0x0b, 0x27, 0x22),
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Unescape string",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "UnescapeString: octals",
|
||||||
|
input: "\\0\\01\\012\\1\\12",
|
||||||
|
expectedOutput: String.fromCharCode(0, 1, 10, 1, 10),
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Unescape string",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "UnescapeString: hexadecimals",
|
||||||
|
input: "\\x00\\xAA\\xaa",
|
||||||
|
expectedOutput: String.fromCharCode(0, 170, 170),
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Unescape string",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "UnescapeString: unicode",
|
||||||
|
input: "\\u0061\\u{0062}",
|
||||||
|
expectedOutput: "ab",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Unescape string",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
|
@ -8,6 +8,22 @@
|
||||||
*/
|
*/
|
||||||
import TestRegister from "../../lib/TestRegister.mjs";
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
const CONSOLE_COMPILE_WARNING_RULE = `import "console"
|
||||||
|
rule a
|
||||||
|
{
|
||||||
|
strings:
|
||||||
|
$s=" "
|
||||||
|
condition:
|
||||||
|
$s and console.log("log rule a")
|
||||||
|
}
|
||||||
|
rule b
|
||||||
|
{
|
||||||
|
strings:
|
||||||
|
$s=" "
|
||||||
|
condition:
|
||||||
|
$s and console.hex("log rule b: int8(0)=", int8(0))
|
||||||
|
}`;
|
||||||
|
|
||||||
TestRegister.addTests([
|
TestRegister.addTests([
|
||||||
{
|
{
|
||||||
name: "YARA Match: simple foobar",
|
name: "YARA Match: simple foobar",
|
||||||
|
@ -20,5 +36,56 @@ TestRegister.addTests([
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "YARA Match: hashing rules",
|
||||||
|
input: "Hello World!",
|
||||||
|
expectedOutput: "Input matches rule \"HelloWorldMD5\".\nInput matches rule \"HelloWorldSHA256\".\n",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "YARA Rules",
|
||||||
|
"args": [
|
||||||
|
`import "hash"
|
||||||
|
rule HelloWorldMD5 {
|
||||||
|
condition:
|
||||||
|
hash.md5(0,filesize) == "ed076287532e86365e841e92bfc50d8c"
|
||||||
|
}
|
||||||
|
|
||||||
|
rule HelloWorldSHA256 {
|
||||||
|
condition:
|
||||||
|
hash.sha256(0,filesize) == "7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069"
|
||||||
|
}`,
|
||||||
|
true, true, true, true, false, false
|
||||||
|
],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "YARA Match: compile warnings",
|
||||||
|
input: "CyberChef Yara",
|
||||||
|
expectedOutput: "Warning on line 5: string \"$s\" may slow down scanning\n" +
|
||||||
|
"Warning on line 12: string \"$s\" may slow down scanning\n" +
|
||||||
|
"Input matches rule \"a\".\n" +
|
||||||
|
"Input matches rule \"b\".\n",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "YARA Rules",
|
||||||
|
"args": [CONSOLE_COMPILE_WARNING_RULE, false, false, false, false, true, false],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "YARA Match: console messages",
|
||||||
|
input: "CyberChef Yara",
|
||||||
|
expectedOutput: "log rule a\n" +
|
||||||
|
"log rule b: int8(0)=0x43\n" +
|
||||||
|
"Input matches rule \"a\".\n" +
|
||||||
|
"Input matches rule \"b\".\n",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "YARA Rules",
|
||||||
|
"args": [CONSOLE_COMPILE_WARNING_RULE, false, false, false, false, false, true],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,8 @@ module.exports = {
|
||||||
"buffer": require.resolve("buffer/"),
|
"buffer": require.resolve("buffer/"),
|
||||||
"crypto": require.resolve("crypto-browserify"),
|
"crypto": require.resolve("crypto-browserify"),
|
||||||
"stream": require.resolve("stream-browserify"),
|
"stream": require.resolve("stream-browserify"),
|
||||||
"zlib": require.resolve("browserify-zlib")
|
"zlib": require.resolve("browserify-zlib"),
|
||||||
|
"process": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
|
@ -164,19 +165,6 @@ module.exports = {
|
||||||
"postcss-loader",
|
"postcss-loader",
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
test: /\.scss$/,
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: MiniCssExtractPlugin.loader,
|
|
||||||
options: {
|
|
||||||
publicPath: "../"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"css-loader",
|
|
||||||
"sass-loader",
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
test: /\.(ico|eot|ttf|woff|woff2)$/,
|
test: /\.(ico|eot|ttf|woff|woff2)$/,
|
||||||
type: "asset/resource",
|
type: "asset/resource",
|
||||||
|
|
Loading…
Reference in a new issue