mirror of
https://github.com/gchq/CyberChef
synced 2025-12-05 23:53:27 +00:00
Compare commits
101 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1400b5cca4 | ||
|
|
98b5f9cc29 | ||
|
|
e766cb009e | ||
|
|
993e276858 | ||
|
|
a762fb4df4 | ||
|
|
00781fa459 | ||
|
|
c6e7367a4e | ||
|
|
3749bb1222 | ||
|
|
f3c83b2009 | ||
|
|
d3583c31bc | ||
|
|
2f638d8c0c | ||
|
|
74e43ff65a | ||
|
|
4f0b160ed3 | ||
|
|
709b8696fc | ||
|
|
e080c5d72e | ||
|
|
9cc177a9ad | ||
|
|
60b5fe0e76 | ||
|
|
9273f97d88 | ||
|
|
98a6baf55a | ||
|
|
b5677387f5 | ||
|
|
cd3eaa4762 | ||
|
|
9733bf65de | ||
|
|
bc433f0234 | ||
|
|
ad7283ee6f | ||
|
|
5b941358a9 | ||
|
|
f19e898c57 | ||
|
|
590ffa184d | ||
|
|
46de51512f | ||
|
|
a13f2f26e4 | ||
|
|
c9c26f6f9f | ||
|
|
787c29e42b | ||
|
|
1c0b83d833 | ||
|
|
5c767d09b0 | ||
|
|
75dba51f56 | ||
|
|
78a1827af8 | ||
|
|
9e3733b33b | ||
|
|
4ef65589e8 | ||
|
|
cf9e670309 | ||
|
|
b09f98fbb4 | ||
|
|
e43e010163 | ||
|
|
2a5cee0bd3 | ||
|
|
c962bb79f5 | ||
|
|
2e23a33dfc | ||
|
|
bca296ee37 | ||
|
|
2dbd647868 | ||
|
|
2991e7d1fe | ||
|
|
f6f12fc193 | ||
|
|
1fac8c1cea | ||
|
|
590462e2e4 | ||
|
|
291c55befd | ||
|
|
7db1f39473 | ||
|
|
6017578964 | ||
|
|
d2174725a9 | ||
|
|
f630c499d5 | ||
|
|
cfc29ef821 | ||
|
|
83c6775038 | ||
|
|
ae1b12c120 | ||
|
|
c423de545f | ||
|
|
84011371b7 | ||
|
|
f831ec6b7e | ||
|
|
05bfa9158d | ||
|
|
649016bc85 | ||
|
|
7492b874cf | ||
|
|
9ea21af61f | ||
|
|
dd18e52993 | ||
|
|
7712ee7f35 | ||
|
|
a4a13666e6 | ||
|
|
07ef4da892 | ||
|
|
e9ca4dc9ca | ||
|
|
57bb8fbc45 | ||
|
|
9175624210 | ||
|
|
289a417dfb | ||
|
|
8379a9b275 | ||
|
|
5b1fad118f | ||
|
|
5e8985810e | ||
|
|
d2568e2a29 | ||
|
|
6dfc21ef06 | ||
|
|
1f19f2f58c | ||
|
|
1728cc7a85 | ||
|
|
fa2fc2ba33 | ||
|
|
9a33498fed | ||
|
|
a3b873fd96 | ||
|
|
97bd03799e | ||
|
|
ffaaaae2b4 | ||
|
|
ff88d30d2f | ||
|
|
88e3c2ccb2 | ||
|
|
5029356514 | ||
|
|
e57d5a7e75 | ||
|
|
2bbe54cdcd | ||
|
|
0e2423c390 | ||
|
|
8fadad5891 | ||
|
|
c01ce90e06 | ||
|
|
d68c8cb845 | ||
|
|
88947b9d42 | ||
|
|
3c68ad1302 | ||
|
|
e2b3389da6 | ||
|
|
938385c18b | ||
|
|
5d01b06877 | ||
|
|
f007c093eb | ||
|
|
209fc07eac | ||
|
|
ae70cb89ed |
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"parser": "babel-eslint",
|
||||
"parser": "@babel/eslint-parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 9,
|
||||
"ecmaFeatures": {
|
||||
|
||||
1
.github/workflows/codeql.yml
vendored
1
.github/workflows/codeql.yml
vendored
@@ -1,6 +1,7 @@
|
||||
name: "CodeQL Analysis"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
|
||||
11
.github/workflows/master.yml
vendored
11
.github/workflows/master.yml
vendored
@@ -1,6 +1,7 @@
|
||||
name: "Master Build, Test & Deploy"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
@@ -14,7 +15,7 @@ jobs:
|
||||
- name: Set node version
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '10.x'
|
||||
node-version: '17.x'
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
@@ -27,7 +28,7 @@ jobs:
|
||||
- name: Unit Tests
|
||||
run: |
|
||||
npm test
|
||||
npx grunt testnodeconsumer
|
||||
npm run testnodeconsumer
|
||||
|
||||
- name: Production Build
|
||||
if: success()
|
||||
@@ -36,9 +37,9 @@ jobs:
|
||||
- name: Generate sitemap
|
||||
run: npx grunt exec:sitemap
|
||||
|
||||
- name: UI Tests
|
||||
if: success()
|
||||
run: xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||
# - name: UI Tests
|
||||
# if: success()
|
||||
# run: xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||
|
||||
- name: Prepare for GitHub Pages
|
||||
if: success()
|
||||
|
||||
11
.github/workflows/pull_requests.yml
vendored
11
.github/workflows/pull_requests.yml
vendored
@@ -1,6 +1,7 @@
|
||||
name: "Pull Requests"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened]
|
||||
|
||||
@@ -13,7 +14,7 @@ jobs:
|
||||
- name: Set node version
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '10.x'
|
||||
node-version: '17.x'
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
@@ -26,12 +27,12 @@ jobs:
|
||||
- name: Unit Tests
|
||||
run: |
|
||||
npm test
|
||||
npx grunt testnodeconsumer
|
||||
npm run testnodeconsumer
|
||||
|
||||
- name: Production Build
|
||||
if: success()
|
||||
run: npx grunt prod
|
||||
|
||||
- name: UI Tests
|
||||
if: success()
|
||||
run: xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||
# - name: UI Tests
|
||||
# if: success()
|
||||
# run: xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||
|
||||
11
.github/workflows/releases.yml
vendored
11
.github/workflows/releases.yml
vendored
@@ -1,6 +1,7 @@
|
||||
name: "Releases"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
@@ -14,7 +15,7 @@ jobs:
|
||||
- name: Set node version
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '10.x'
|
||||
node-version: '17.x'
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
@@ -27,15 +28,15 @@ jobs:
|
||||
- name: Unit Tests
|
||||
run: |
|
||||
npm test
|
||||
npx grunt testnodeconsumer
|
||||
npm run testnodeconsumer
|
||||
|
||||
- name: Production Build
|
||||
if: success()
|
||||
run: npx grunt prod
|
||||
|
||||
- name: UI Tests
|
||||
if: success()
|
||||
run: xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||
# - name: UI Tests
|
||||
# if: success()
|
||||
# run: xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||
|
||||
- name: Upload Release Assets
|
||||
if: success()
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -11,4 +11,4 @@ src/node/config/OperationConfig.json
|
||||
src/node/index.mjs
|
||||
**/*.DS_Store
|
||||
tests/browser/output/*
|
||||
|
||||
.node-version
|
||||
|
||||
55
CHANGELOG.md
55
CHANGELOG.md
@@ -13,6 +13,34 @@ All major and minor version changes will be documented in this file. Details of
|
||||
|
||||
## Details
|
||||
|
||||
### [9.36.0] - 2022-03-29
|
||||
- 'SIGABA' operation added [@hettysymes] | [#934]
|
||||
|
||||
### [9.35.0] - 2022-03-28
|
||||
- 'To Base45' and 'From Base45' operations added [@t-8ch] | [#1242]
|
||||
|
||||
### [9.34.0] - 2022-03-28
|
||||
- 'Get All Casings' operation added [@n1073645] | [#1065]
|
||||
|
||||
### [9.33.0] - 2022-03-25
|
||||
- Updated to support Node 17 [@n1474335] [@john19696] [@t-8ch] | [[#1326] [#1313] [#1244]
|
||||
- Improved CJS and ESM module support [@d98762625] | [#1037]
|
||||
|
||||
### [9.32.0] - 2021-08-18
|
||||
- 'Protobuf Encode' operation added and decode operation modified to allow decoding with full and partial schemas [@n1474335] | [dd18e52]
|
||||
|
||||
### [9.31.0] - 2021-08-10
|
||||
- 'HASSH Client Fingerprint' and 'HASSH Server Fingerprint' operations added [@n1474335] | [e9ca4dc]
|
||||
|
||||
### [9.30.0] - 2021-08-10
|
||||
- 'JA3S Fingerprint' operation added [@n1474335] | [289a417]
|
||||
|
||||
### [9.29.0] - 2021-07-28
|
||||
- 'JA3 Fingerprint' operation added [@n1474335] | [9a33498]
|
||||
|
||||
### [9.28.0] - 2021-03-26
|
||||
- 'CBOR Encode' and 'CBOR Decode' operations added [@Danh4] | [#999]
|
||||
|
||||
### [9.27.0] - 2021-02-12
|
||||
- 'Fuzzy Match' operation added [@n1474335] | [8ad18b]
|
||||
|
||||
@@ -256,6 +284,15 @@ All major and minor version changes will be documented in this file. Details of
|
||||
|
||||
|
||||
|
||||
[9.36.0]: https://github.com/gchq/CyberChef/releases/tag/v9.36.0
|
||||
[9.35.0]: https://github.com/gchq/CyberChef/releases/tag/v9.35.0
|
||||
[9.34.0]: https://github.com/gchq/CyberChef/releases/tag/v9.34.0
|
||||
[9.33.0]: https://github.com/gchq/CyberChef/releases/tag/v9.33.0
|
||||
[9.32.0]: https://github.com/gchq/CyberChef/releases/tag/v9.32.0
|
||||
[9.31.0]: https://github.com/gchq/CyberChef/releases/tag/v9.31.0
|
||||
[9.30.0]: https://github.com/gchq/CyberChef/releases/tag/v9.30.0
|
||||
[9.29.0]: https://github.com/gchq/CyberChef/releases/tag/v9.29.0
|
||||
[9.28.0]: https://github.com/gchq/CyberChef/releases/tag/v9.28.0
|
||||
[9.27.0]: https://github.com/gchq/CyberChef/releases/tag/v9.27.0
|
||||
[9.26.0]: https://github.com/gchq/CyberChef/releases/tag/v9.26.0
|
||||
[9.25.0]: https://github.com/gchq/CyberChef/releases/tag/v9.25.0
|
||||
@@ -363,8 +400,16 @@ All major and minor version changes will be documented in this file. Details of
|
||||
[@MarvinJWendt]: https://github.com/MarvinJWendt
|
||||
[@dmfj]: https://github.com/dmfj
|
||||
[@mattnotmitt]: https://github.com/mattnotmitt
|
||||
[@Danh4]: https://github.com/Danh4
|
||||
[@john19696]: https://github.com/john19696
|
||||
[@t-8ch]: https://github.com/t-8ch
|
||||
[@hettysymes]: https://github.com/hettysymes
|
||||
|
||||
[8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
|
||||
[9a33498]: https://github.com/gchq/CyberChef/commit/9a33498fed26a8df9c9f35f39a78a174bf50a513
|
||||
[289a417]: https://github.com/gchq/CyberChef/commit/289a417dfb5923de5e1694354ec42a08d9395bfe
|
||||
[e9ca4dc]: https://github.com/gchq/CyberChef/commit/e9ca4dc9caf98f33fd986431cd400c88082a42b8
|
||||
[dd18e52]: https://github.com/gchq/CyberChef/commit/dd18e529939078b89867297b181a584e8b2cc7da
|
||||
|
||||
[#95]: https://github.com/gchq/CyberChef/pull/299
|
||||
[#173]: https://github.com/gchq/CyberChef/pull/173
|
||||
@@ -433,13 +478,21 @@ All major and minor version changes will be documented in this file. Details of
|
||||
[#865]: https://github.com/gchq/CyberChef/pull/865
|
||||
[#912]: https://github.com/gchq/CyberChef/pull/912
|
||||
[#917]: https://github.com/gchq/CyberChef/pull/917
|
||||
[#934]: https://github.com/gchq/CyberChef/pull/934
|
||||
[#948]: https://github.com/gchq/CyberChef/pull/948
|
||||
[#952]: https://github.com/gchq/CyberChef/pull/952
|
||||
[#965]: https://github.com/gchq/CyberChef/pull/965
|
||||
[#966]: https://github.com/gchq/CyberChef/pull/966
|
||||
[#987]: https://github.com/gchq/CyberChef/pull/987
|
||||
[#999]: https://github.com/gchq/CyberChef/pull/999
|
||||
[#1006]: https://github.com/gchq/CyberChef/pull/1006
|
||||
[#1022]: https://github.com/gchq/CyberChef/pull/1022
|
||||
[#1037]: https://github.com/gchq/CyberChef/pull/1037
|
||||
[#1045]: https://github.com/gchq/CyberChef/pull/1045
|
||||
[#1049]: https://github.com/gchq/CyberChef/pull/1049
|
||||
[#1083]: https://github.com/gchq/CyberChef/pull/1083
|
||||
[#1065]: https://github.com/gchq/CyberChef/pull/1065
|
||||
[#1083]: https://github.com/gchq/CyberChef/pull/1083
|
||||
[#1242]: https://github.com/gchq/CyberChef/pull/1242
|
||||
[#1244]: https://github.com/gchq/CyberChef/pull/1244
|
||||
[#1313]: https://github.com/gchq/CyberChef/pull/1313
|
||||
[#1326]: https://github.com/gchq/CyberChef/pull/1326
|
||||
97
Gruntfile.js
97
Gruntfile.js
@@ -6,6 +6,8 @@ const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPl
|
||||
const glob = require("glob");
|
||||
const path = require("path");
|
||||
|
||||
const nodeFlags = "--experimental-modules --experimental-json-modules --experimental-specifier-resolution=node --no-warnings --no-deprecation";
|
||||
|
||||
/**
|
||||
* Grunt configuration for building the app in various formats.
|
||||
*
|
||||
@@ -48,7 +50,7 @@ module.exports = function (grunt) {
|
||||
|
||||
grunt.registerTask("testnodeconsumer",
|
||||
"A task which checks whether consuming CJS and ESM apps work with the CyberChef build",
|
||||
["exec:setupNodeConsumers", "exec:testCJSNodeConsumer", "exec:testESMNodeConsumer", "exec:testESMDeepImportNodeConsumer", "exec:teardownNodeConsumers"]);
|
||||
["exec:setupNodeConsumers", "exec:testCJSNodeConsumer", "exec:testESMNodeConsumer", "exec:teardownNodeConsumers"]);
|
||||
|
||||
grunt.registerTask("default",
|
||||
"Lints the code base",
|
||||
@@ -187,9 +189,6 @@ module.exports = function (grunt) {
|
||||
standalone: ["build/prod/CyberChef*.html"]
|
||||
},
|
||||
eslint: {
|
||||
options: {
|
||||
configFile: "./.eslintrc.json"
|
||||
},
|
||||
configs: ["*.{js,mjs}"],
|
||||
core: ["src/core/**/*.{js,mjs}", "!src/core/vendor/**/*", "!src/core/operations/legacy/**/*"],
|
||||
web: ["src/web/**/*.{js,mjs}", "!src/web/static/**/*"],
|
||||
@@ -201,50 +200,35 @@ module.exports = function (grunt) {
|
||||
web: webpackProdConf(),
|
||||
},
|
||||
"webpack-dev-server": {
|
||||
options: {
|
||||
webpack: webpackConfig,
|
||||
host: "0.0.0.0",
|
||||
port: grunt.option("port") || 8080,
|
||||
disableHostCheck: true,
|
||||
overlay: true,
|
||||
inline: false,
|
||||
clientLogLevel: "error",
|
||||
stats: {
|
||||
children: false,
|
||||
chunks: false,
|
||||
modules: false,
|
||||
entrypoints: false,
|
||||
warningsFilter: [
|
||||
/source-map/,
|
||||
/dependency is an expression/,
|
||||
/export 'default'/,
|
||||
/Can't resolve 'sodium'/
|
||||
],
|
||||
}
|
||||
},
|
||||
options: webpackConfig,
|
||||
start: {
|
||||
webpack: {
|
||||
mode: "development",
|
||||
target: "web",
|
||||
entry: Object.assign({
|
||||
main: "./src/web/index.js"
|
||||
}, moduleEntryPoints),
|
||||
resolve: {
|
||||
alias: {
|
||||
"./config/modules/OpModules.mjs": "./config/modules/Default.mjs"
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin(BUILD_CONSTANTS),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "index.html",
|
||||
template: "./src/web/html/index.html",
|
||||
chunks: ["main"],
|
||||
compileTime: compileTime,
|
||||
version: pkg.version,
|
||||
})
|
||||
]
|
||||
}
|
||||
mode: "development",
|
||||
target: "web",
|
||||
entry: Object.assign({
|
||||
main: "./src/web/index.js"
|
||||
}, moduleEntryPoints),
|
||||
resolve: {
|
||||
alias: {
|
||||
"./config/modules/OpModules.mjs": "./config/modules/Default.mjs"
|
||||
}
|
||||
},
|
||||
devServer: {
|
||||
port: grunt.option("port") || 8080,
|
||||
client: {
|
||||
logging: "error",
|
||||
overlay: true
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin(BUILD_CONSTANTS),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "index.html",
|
||||
template: "./src/web/html/index.html",
|
||||
chunks: ["main"],
|
||||
compileTime: compileTime,
|
||||
version: pkg.version,
|
||||
})
|
||||
]
|
||||
}
|
||||
},
|
||||
zip: {
|
||||
@@ -349,15 +333,15 @@ module.exports = function (grunt) {
|
||||
command: "git gc --prune=now --aggressive"
|
||||
},
|
||||
sitemap: {
|
||||
command: "node --experimental-modules --no-warnings --no-deprecation src/web/static/sitemap.mjs > build/prod/sitemap.xml",
|
||||
command: `node ${nodeFlags} src/web/static/sitemap.mjs > build/prod/sitemap.xml`,
|
||||
sync: true
|
||||
},
|
||||
generateConfig: {
|
||||
command: chainCommands([
|
||||
"echo '\n--- Regenerating config files. ---'",
|
||||
"echo [] > src/core/config/OperationConfig.json",
|
||||
"node --experimental-modules --no-warnings --no-deprecation src/core/config/scripts/generateOpsIndex.mjs",
|
||||
"node --experimental-modules --no-warnings --no-deprecation src/core/config/scripts/generateConfig.mjs",
|
||||
`node ${nodeFlags} src/core/config/scripts/generateOpsIndex.mjs`,
|
||||
`node ${nodeFlags} src/core/config/scripts/generateConfig.mjs`,
|
||||
"echo '--- Config scripts finished. ---\n'"
|
||||
]),
|
||||
sync: true
|
||||
@@ -365,7 +349,7 @@ module.exports = function (grunt) {
|
||||
generateNodeIndex: {
|
||||
command: chainCommands([
|
||||
"echo '\n--- Regenerating node index ---'",
|
||||
"node --experimental-modules --no-warnings --no-deprecation src/node/config/scripts/generateNodeIndex.mjs",
|
||||
`node ${nodeFlags} src/node/config/scripts/generateNodeIndex.mjs`,
|
||||
"echo '--- Node index generated. ---\n'"
|
||||
]),
|
||||
sync: true
|
||||
@@ -393,21 +377,14 @@ module.exports = function (grunt) {
|
||||
testCJSNodeConsumer: {
|
||||
command: chainCommands([
|
||||
`cd ${nodeConsumerTestPath}`,
|
||||
"node --no-warnings cjs-consumer.js",
|
||||
`node ${nodeFlags} cjs-consumer.js`,
|
||||
]),
|
||||
stdout: false,
|
||||
},
|
||||
testESMNodeConsumer: {
|
||||
command: chainCommands([
|
||||
`cd ${nodeConsumerTestPath}`,
|
||||
"node --no-warnings --experimental-modules esm-consumer.mjs",
|
||||
]),
|
||||
stdout: false,
|
||||
},
|
||||
testESMDeepImportNodeConsumer: {
|
||||
command: chainCommands([
|
||||
`cd ${nodeConsumerTestPath}`,
|
||||
"node --no-warnings --experimental-modules esm-deep-import-consumer.mjs",
|
||||
`node ${nodeFlags} esm-consumer.mjs`,
|
||||
]),
|
||||
stdout: false,
|
||||
},
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
[](https://github.com/gchq/CyberChef/actions?query=workflow%3A%22Master+Build%2C+Test+%26+Deploy%22)
|
||||
[](https://lgtm.com/projects/g/gchq/CyberChef/context:javascript)
|
||||
[](https://david-dm.org/gchq/CyberChef)
|
||||
[](https://www.npmjs.com/package/cyberchef)
|
||||
[](https://github.com/gchq/CyberChef/blob/master/LICENSE)
|
||||
[](https://gitter.im/gchq/CyberChef?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
@@ -10,7 +9,7 @@
|
||||
|
||||
#### *The Cyber Swiss Army Knife*
|
||||
|
||||
CyberChef is a simple, intuitive web app for carrying out all manner of "cyber" operations within a web browser. These operations include simple encoding like XOR or Base64, more complex encryption like AES, DES and Blowfish, creating binary and hexdumps, compression and decompression of data, calculating hashes and checksums, IPv6 and X.509 parsing, changing character encodings, and much more.
|
||||
CyberChef is a simple, intuitive web app for carrying out all manner of "cyber" operations within a web browser. These operations include simple encoding like XOR and Base64, more complex encryption like AES, DES and Blowfish, creating binary and hexdumps, compression and decompression of data, calculating hashes and checksums, IPv6 and X.509 parsing, changing character encodings, and much more.
|
||||
|
||||
The tool is designed to enable both technical and non-technical analysts to manipulate data in complex ways without having to deal with complex tools or algorithms. It was conceived, designed, built and incrementally improved by an analyst in their 10% innovation time over several years.
|
||||
|
||||
@@ -106,7 +105,7 @@ An installation walkthrough, how-to guides for adding new operations and themes,
|
||||
|
||||
## Licencing
|
||||
|
||||
CyberChef is released under the [Apache 2.0 Licence](https://www.apache.org/licenses/LICENSE-2.0) and is covered by [Crown Copyright](https://www.nationalarchives.gov.uk/information-management/re-using-public-sector-information/copyright-and-re-use/crown-copyright/).
|
||||
CyberChef is released under the [Apache 2.0 Licence](https://www.apache.org/licenses/LICENSE-2.0) and is covered by [Crown Copyright](https://www.nationalarchives.gov.uk/information-management/re-using-public-sector-information/uk-government-licensing-framework/crown-copyright/).
|
||||
|
||||
|
||||
[1]: https://gchq.github.io/CyberChef
|
||||
|
||||
@@ -11,6 +11,7 @@ module.exports = function(api) {
|
||||
],
|
||||
"plugins": [
|
||||
"dynamic-import-node",
|
||||
"@babel/plugin-syntax-import-assertions",
|
||||
[
|
||||
"babel-plugin-transform-builtin-extend", {
|
||||
"globals": ["Error"]
|
||||
|
||||
28656
package-lock.json
generated
28656
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
148
package.json
148
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "9.27.4",
|
||||
"version": "9.36.0",
|
||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||
"author": "n1474335 <n1474335@gmail.com>",
|
||||
"homepage": "https://gchq.github.io/CyberChef",
|
||||
@@ -27,117 +27,117 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/gchq/CyberChef/"
|
||||
},
|
||||
"main": "src/node/cjs.js",
|
||||
"module": "src/node/index.mjs",
|
||||
"main": "src/node/wrapper.js",
|
||||
"exports": {
|
||||
"import": "./src/node/index.mjs",
|
||||
"require": "./src/node/wrapper.js"
|
||||
},
|
||||
"bugs": "https://github.com/gchq/CyberChef/issues",
|
||||
"browserslist": [
|
||||
"Chrome >= 50",
|
||||
"Firefox >= 38",
|
||||
"node >= 10"
|
||||
"node >= 16"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.16",
|
||||
"@babel/plugin-transform-runtime": "^7.12.15",
|
||||
"@babel/preset-env": "^7.12.16",
|
||||
"autoprefixer": "^10.2.4",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.2.2",
|
||||
"@babel/core": "^7.17.8",
|
||||
"@babel/eslint-parser": "^7.17.0",
|
||||
"@babel/plugin-syntax-import-assertions": "^7.16.7",
|
||||
"@babel/plugin-transform-runtime": "^7.17.0",
|
||||
"@babel/preset-env": "^7.16.11",
|
||||
"@babel/runtime": "^7.17.8",
|
||||
"autoprefixer": "^10.4.4",
|
||||
"babel-loader": "^8.2.4",
|
||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||
"chromedriver": "^88.0.0",
|
||||
"cli-progress": "^3.9.0",
|
||||
"chromedriver": "^99.0.0",
|
||||
"cli-progress": "^3.10.0",
|
||||
"colors": "^1.4.0",
|
||||
"copy-webpack-plugin": "^7.0.0",
|
||||
"css-loader": "^5.0.2",
|
||||
"eslint": "^7.20.0",
|
||||
"exports-loader": "^2.0.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"grunt": "^1.3.0",
|
||||
"copy-webpack-plugin": "^10.2.4",
|
||||
"core-js": "^3.21.1",
|
||||
"css-loader": "6.7.1",
|
||||
"eslint": "^8.12.0",
|
||||
"grunt": "^1.4.1",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-concurrent": "^3.0.0",
|
||||
"grunt-contrib-clean": "~2.0.0",
|
||||
"grunt-contrib-connect": "^3.0.0",
|
||||
"grunt-contrib-copy": "~1.0.0",
|
||||
"grunt-contrib-watch": "^1.1.0",
|
||||
"grunt-eslint": "^23.0.0",
|
||||
"grunt-eslint": "^24.0.0",
|
||||
"grunt-exec": "~3.0.0",
|
||||
"grunt-webpack": "^4.0.2",
|
||||
"grunt-webpack": "^5.0.0",
|
||||
"grunt-zip": "^0.18.2",
|
||||
"html-webpack-plugin": "^5.1.0",
|
||||
"imports-loader": "^2.0.0",
|
||||
"mini-css-extract-plugin": "^1.3.7",
|
||||
"nightwatch": "^1.5.1",
|
||||
"node-sass": "^5.0.0",
|
||||
"postcss": "^8.2.6",
|
||||
"postcss-css-variables": "^0.17.0",
|
||||
"postcss-import": "^14.0.0",
|
||||
"postcss-loader": "^5.0.0",
|
||||
"prompt": "^1.1.0",
|
||||
"sass-loader": "^11.0.1",
|
||||
"sitemap": "^6.3.6",
|
||||
"style-loader": "^2.0.0",
|
||||
"svg-url-loader": "^7.1.1",
|
||||
"url-loader": "^4.1.1",
|
||||
"webpack": "^5.22.0",
|
||||
"webpack-bundle-analyzer": "^4.4.0",
|
||||
"webpack-dev-server": "^3.11.2",
|
||||
"webpack-node-externals": "^2.5.2",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"imports-loader": "^3.1.1",
|
||||
"mini-css-extract-plugin": "2.6.0",
|
||||
"nightwatch": "^2.0.10",
|
||||
"postcss": "^8.4.12",
|
||||
"postcss-css-variables": "^0.18.0",
|
||||
"postcss-import": "^14.1.0",
|
||||
"postcss-loader": "^6.2.1",
|
||||
"prompt": "^1.2.2",
|
||||
"sass-loader": "^12.6.0",
|
||||
"sitemap": "^7.1.1",
|
||||
"terser": "^5.12.1",
|
||||
"webpack": "^5.70.0",
|
||||
"webpack-bundle-analyzer": "^4.5.0",
|
||||
"webpack-dev-server": "4.7.4",
|
||||
"webpack-node-externals": "^3.0.0",
|
||||
"worker-loader": "^3.0.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/runtime": "^7.12.13",
|
||||
"arrive": "^2.4.1",
|
||||
"avsc": "^5.5.3",
|
||||
"avsc": "^5.7.3",
|
||||
"babel-plugin-transform-builtin-extend": "1.1.2",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"bignumber.js": "^9.0.1",
|
||||
"blakejs": "^1.1.0",
|
||||
"bootstrap": "4.6.0",
|
||||
"bootstrap-colorpicker": "^3.2.0",
|
||||
"bignumber.js": "^9.0.2",
|
||||
"blakejs": "^1.2.1",
|
||||
"bootstrap": "4.6.1",
|
||||
"bootstrap-colorpicker": "^3.4.0",
|
||||
"bootstrap-material-design": "^4.1.3",
|
||||
"browserify-zlib": "^0.2.0",
|
||||
"bson": "^4.2.2",
|
||||
"bson": "^4.6.2",
|
||||
"buffer": "^6.0.3",
|
||||
"cbor": "8.1.0",
|
||||
"chi-squared": "^1.1.0",
|
||||
"codepage": "^1.14.0",
|
||||
"core-js": "^3.8.3",
|
||||
"codepage": "^1.15.0",
|
||||
"crypto-api": "^0.8.5",
|
||||
"crypto-browserify": "^3.12.0",
|
||||
"crypto-js": "^4.0.0",
|
||||
"crypto-js": "^4.1.1",
|
||||
"ctph.js": "0.0.5",
|
||||
"d3": "^6.5.0",
|
||||
"d3": "7.3.0",
|
||||
"d3-hexbin": "^0.2.2",
|
||||
"diff": "^5.0.0",
|
||||
"es6-promisify": "^6.1.1",
|
||||
"es6-promisify": "^7.0.0",
|
||||
"escodegen": "^2.0.0",
|
||||
"esm": "^3.2.25",
|
||||
"esprima": "^4.0.1",
|
||||
"exif-parser": "^0.1.12",
|
||||
"file-saver": "^2.0.5",
|
||||
"flat": "^5.0.2",
|
||||
"geodesy": "1.1.3",
|
||||
"highlight.js": "^10.6.0",
|
||||
"highlight.js": "^11.5.0",
|
||||
"jimp": "^0.16.1",
|
||||
"jquery": "3.5.1",
|
||||
"jquery": "3.6.0",
|
||||
"js-crc": "^0.2.0",
|
||||
"js-sha3": "^0.8.0",
|
||||
"jsesc": "^3.0.2",
|
||||
"jsonpath": "^1.1.0",
|
||||
"jsonpath": "^1.1.1",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"jsqr": "^1.3.1",
|
||||
"jsrsasign": "^10.1.10",
|
||||
"jsqr": "^1.4.0",
|
||||
"jsrsasign": "^10.5.14",
|
||||
"kbpgp": "2.1.15",
|
||||
"libbzip2-wasm": "0.0.4",
|
||||
"libyara-wasm": "^1.1.0",
|
||||
"lodash": "^4.17.20",
|
||||
"loglevel": "^1.7.1",
|
||||
"lodash": "^4.17.21",
|
||||
"loglevel": "^1.8.0",
|
||||
"loglevel-message-prefix": "^3.0.0",
|
||||
"markdown-it": "^12.0.4",
|
||||
"markdown-it": "^12.3.2",
|
||||
"moment": "^2.29.1",
|
||||
"moment-timezone": "^0.5.33",
|
||||
"moment-timezone": "^0.5.34",
|
||||
"ngeohash": "^0.6.3",
|
||||
"node-forge": "^0.10.0",
|
||||
"node-forge": "^1.3.0",
|
||||
"node-md6": "^0.1.0",
|
||||
"node-sass": "^7.0.1",
|
||||
"nodom": "^2.4.0",
|
||||
"notepack.io": "^2.3.0",
|
||||
"nwmatcher": "^1.4.4",
|
||||
@@ -145,35 +145,35 @@
|
||||
"path": "^0.12.7",
|
||||
"popper.js": "^1.16.1",
|
||||
"process": "^0.11.10",
|
||||
"protobufjs": "^6.11.2",
|
||||
"qr-image": "^3.2.0",
|
||||
"scryptsy": "^2.1.0",
|
||||
"snackbarjs": "^1.1.0",
|
||||
"sortablejs": "^1.13.0",
|
||||
"split.js": "^1.6.2",
|
||||
"ssdeep.js": "0.0.2",
|
||||
"sortablejs": "^1.15.0",
|
||||
"split.js": "^1.6.5",
|
||||
"ssdeep.js": "0.0.3",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"terser": "^5.6.0",
|
||||
"tesseract.js": "2.1.1",
|
||||
"ua-parser-js": "^0.7.24",
|
||||
"tesseract.js": "2.1.5",
|
||||
"ua-parser-js": "^1.0.2",
|
||||
"unorm": "^1.6.0",
|
||||
"utf8": "^3.0.0",
|
||||
"vkbeautify": "^0.99.3",
|
||||
"xmldom": "^0.4.0",
|
||||
"xmldom": "^0.6.0",
|
||||
"xpath": "0.0.32",
|
||||
"xregexp": "^5.0.1",
|
||||
"xregexp": "^5.1.0",
|
||||
"zlibjs": "^0.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "npx grunt dev",
|
||||
"build": "npx grunt prod",
|
||||
"repl": "node src/node/repl.js",
|
||||
"test": "npx grunt configTests && node --experimental-modules --no-warnings --no-deprecation tests/node/index.mjs && node --experimental-modules --no-warnings --no-deprecation tests/operations/index.mjs",
|
||||
"test-node-consumer": "npx grunt testnodeconsumer",
|
||||
"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",
|
||||
"testnodeconsumer": "npx grunt testnodeconsumer",
|
||||
"testui": "npx grunt testui",
|
||||
"testuidev": "npx nightwatch --env=dev",
|
||||
"lint": "npx grunt lint",
|
||||
"postinstall": "npx grunt exec:fixCryptoApiImports",
|
||||
"newop": "node --experimental-modules src/core/config/scripts/newOperation.mjs",
|
||||
"newop": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newOperation.mjs",
|
||||
"getheapsize": "node -e 'console.log(`node heap limit = ${require(\"v8\").getHeapStatistics().heap_size_limit / (1024 * 1024)} Mb`)'",
|
||||
"setheapsize": "export NODE_OPTIONS=--max_old_space_size=2048"
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import Chef from "./Chef.mjs";
|
||||
import OperationConfig from "./config/OperationConfig.json";
|
||||
import OperationConfig from "./config/OperationConfig.json" assert {type: "json"};
|
||||
import OpModules from "./config/modules/OpModules.mjs";
|
||||
|
||||
// Add ">" to the start of all log messages in the Chef Worker
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import OperationConfig from "./config/OperationConfig.json";
|
||||
import OperationConfig from "./config/OperationConfig.json" assert {type: "json"};
|
||||
import OperationError from "./errors/OperationError.mjs";
|
||||
import Operation from "./Operation.mjs";
|
||||
import DishError from "./errors/DishError.mjs";
|
||||
|
||||
@@ -723,7 +723,8 @@ class Utils {
|
||||
}
|
||||
|
||||
if (removeScriptAndStyle) {
|
||||
htmlStr = recursiveRemove(/<(script|style)[^>]*>.*?<\/(script|style)>/gi, htmlStr);
|
||||
htmlStr = recursiveRemove(/<script[^>]*>.*?<\/script>/gi, htmlStr);
|
||||
htmlStr = recursiveRemove(/<style[^>]*>.*?<\/style>/gi, htmlStr);
|
||||
}
|
||||
return htmlStr.replace(/<[^>]+>/g, "");
|
||||
}
|
||||
@@ -1206,6 +1207,30 @@ class Utils {
|
||||
}[token];
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate object in chunks of given size.
|
||||
*
|
||||
* @param {Iterable} iterable
|
||||
* @param {number} chunksize
|
||||
*/
|
||||
static* chunked(iterable, chunksize) {
|
||||
const iterator = iterable[Symbol.iterator]();
|
||||
while (true) {
|
||||
const res = [];
|
||||
for (let i = 0; i < chunksize; i++) {
|
||||
const next = iterator.next();
|
||||
if (next.done) {
|
||||
break;
|
||||
}
|
||||
res.push(next.value);
|
||||
}
|
||||
if (res.length) {
|
||||
yield res;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
15
src/core/config/Categories.json
Executable file → Normal file
15
src/core/config/Categories.json
Executable file → Normal file
@@ -20,6 +20,8 @@
|
||||
"From Octal",
|
||||
"To Base32",
|
||||
"From Base32",
|
||||
"To Base45",
|
||||
"From Base45",
|
||||
"To Base58",
|
||||
"From Base58",
|
||||
"To Base62",
|
||||
@@ -61,7 +63,9 @@
|
||||
"Parse TLV",
|
||||
"CSV to JSON",
|
||||
"JSON to CSV",
|
||||
"Avro to JSON"
|
||||
"Avro to JSON",
|
||||
"CBOR Encode",
|
||||
"CBOR Decode"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -116,7 +120,8 @@
|
||||
"Multiple Bombe",
|
||||
"Typex",
|
||||
"Lorenz",
|
||||
"Colossus"
|
||||
"Colossus",
|
||||
"SIGABA"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -189,8 +194,13 @@
|
||||
"URL Encode",
|
||||
"URL Decode",
|
||||
"Protobuf Decode",
|
||||
"Protobuf Encode",
|
||||
"VarInt Encode",
|
||||
"VarInt Decode",
|
||||
"JA3 Fingerprint",
|
||||
"JA3S Fingerprint",
|
||||
"HASSH Client Fingerprint",
|
||||
"HASSH Server Fingerprint",
|
||||
"Format MAC addresses",
|
||||
"Change IP format",
|
||||
"Group IP addresses",
|
||||
@@ -223,6 +233,7 @@
|
||||
"From Case Insensitive Regex",
|
||||
"Add line numbers",
|
||||
"Remove line numbers",
|
||||
"Get All Casings",
|
||||
"To Table",
|
||||
"Reverse",
|
||||
"Sort",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import OperationError from "./OperationError.mjs";
|
||||
import DishError from "./DishError.mjs";
|
||||
import ExcludedOperationError from "./ExcludedOperationError";
|
||||
import ExcludedOperationError from "./ExcludedOperationError.mjs";
|
||||
|
||||
export {
|
||||
OperationError,
|
||||
|
||||
27
src/core/lib/Base45.mjs
Normal file
27
src/core/lib/Base45.mjs
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Base45 resources.
|
||||
*
|
||||
* @author Thomas Weißschuh [thomas@t-8ch.de]
|
||||
* @copyright Crown Copyright 2021
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Highlight to Base45
|
||||
*/
|
||||
export function highlightToBase45(pos, args) {
|
||||
pos[0].start = Math.floor(pos[0].start / 2) * 3;
|
||||
pos[0].end = Math.ceil(pos[0].end / 2) * 3;
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight from Base45
|
||||
*/
|
||||
export function highlightFromBase45(pos, args) {
|
||||
pos[0].start = Math.floor(pos[0].start / 3) * 2;
|
||||
pos[0].end = Math.ceil(pos[0].end / 3) * 2;
|
||||
return pos;
|
||||
}
|
||||
|
||||
export const ALPHABET = "0-9A-Z $%*+\\-./:";
|
||||
@@ -34,10 +34,10 @@ export function bitOp (input, key, func, nullPreserving, scheme) {
|
||||
!(nullPreserving && (o === 0 || o === k))) {
|
||||
switch (scheme) {
|
||||
case "Input differential":
|
||||
key[i % key.length] = x;
|
||||
key[i % key.length] = o;
|
||||
break;
|
||||
case "Output differential":
|
||||
key[i % key.length] = o;
|
||||
key[i % key.length] = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
|
||||
/**
|
||||
* @constant
|
||||
@@ -128,7 +129,7 @@ export function getScatterValuesWithColour(input, recordDelimiter, fieldDelimite
|
||||
if (Number.isNaN(x)) throw new OperationError("Values must be numbers in base 10.");
|
||||
if (Number.isNaN(y)) throw new OperationError("Values must be numbers in base 10.");
|
||||
|
||||
return [x, y, colour];
|
||||
return [x, y, Utils.escapeHtml(colour)];
|
||||
});
|
||||
|
||||
return { headings, values };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import OperationConfig from "../config/OperationConfig.json";
|
||||
import OperationConfig from "../config/OperationConfig.json" assert {type: "json"};
|
||||
import Utils, { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import Recipe from "../Recipe.mjs";
|
||||
import Dish from "../Dish.mjs";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Utils from "../Utils.mjs";
|
||||
import protobuf from "protobufjs";
|
||||
|
||||
/**
|
||||
* Protobuf lib. Contains functions to decode protobuf serialised
|
||||
@@ -32,9 +33,10 @@ class Protobuf {
|
||||
this.MSB = 0x80;
|
||||
this.VALUE = 0x7f;
|
||||
|
||||
// Declare offset and length
|
||||
// Declare offset, length, and field type object
|
||||
this.offset = 0;
|
||||
this.LENGTH = data.length;
|
||||
this.fieldTypes = {};
|
||||
}
|
||||
|
||||
// Public Functions
|
||||
@@ -76,15 +78,281 @@ class Protobuf {
|
||||
return pb._varInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode input JSON according to the given schema
|
||||
*
|
||||
* @param {Object} input
|
||||
* @param {Object []} args
|
||||
* @returns {Object}
|
||||
*/
|
||||
static encode(input, args) {
|
||||
this.updateProtoRoot(args[0]);
|
||||
if (!this.mainMessageName) {
|
||||
throw new Error("Schema Error: Schema not defined");
|
||||
}
|
||||
const message = this.parsedProto.root.nested[this.mainMessageName];
|
||||
|
||||
// Convert input into instance of message, and verify instance
|
||||
input = message.fromObject(input);
|
||||
const error = message.verify(input);
|
||||
if (error) {
|
||||
throw new Error("Input Error: " + error);
|
||||
}
|
||||
// Encode input
|
||||
const output = message.encode(input).finish();
|
||||
return new Uint8Array(output).buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Protobuf data
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @returns {Object}
|
||||
*/
|
||||
static decode(input) {
|
||||
static decode(input, args) {
|
||||
this.updateProtoRoot(args[0]);
|
||||
this.showUnknownFields = args[1];
|
||||
this.showTypes = args[2];
|
||||
return this.mergeDecodes(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the parsedProto, throw parsing errors
|
||||
*
|
||||
* @param {string} protoText
|
||||
*/
|
||||
static updateProtoRoot(protoText) {
|
||||
try {
|
||||
this.parsedProto = protobuf.parse(protoText);
|
||||
if (this.parsedProto.package) {
|
||||
this.parsedProto.root = this.parsedProto.root.nested[this.parsedProto.package];
|
||||
}
|
||||
this.updateMainMessageName();
|
||||
} catch (error) {
|
||||
throw new Error("Schema " + error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set mainMessageName to the first instance of a message defined in the schema that is not a submessage
|
||||
*
|
||||
*/
|
||||
static updateMainMessageName() {
|
||||
const messageNames = [];
|
||||
const fieldTypes = [];
|
||||
this.parsedProto.root.nestedArray.forEach(block => {
|
||||
if (block instanceof protobuf.Type) {
|
||||
messageNames.push(block.name);
|
||||
this.parsedProto.root.nested[block.name].fieldsArray.forEach(field => {
|
||||
fieldTypes.push(field.type);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (messageNames.length === 0) {
|
||||
this.mainMessageName = null;
|
||||
} else {
|
||||
// for (const name of messageNames) {
|
||||
// if (!fieldTypes.includes(name)) {
|
||||
// this.mainMessageName = name;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
this.mainMessageName = messageNames[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode input using Protobufjs package and raw methods, compare, and merge results
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @returns {Object}
|
||||
*/
|
||||
static mergeDecodes(input) {
|
||||
const pb = new Protobuf(input);
|
||||
return pb._parse();
|
||||
let rawDecode = pb._parse();
|
||||
let message;
|
||||
|
||||
if (this.showTypes) {
|
||||
rawDecode = this.showRawTypes(rawDecode, pb.fieldTypes);
|
||||
this.parsedProto.root = this.appendTypesToFieldNames(this.parsedProto.root);
|
||||
}
|
||||
|
||||
try {
|
||||
message = this.parsedProto.root.nested[this.mainMessageName];
|
||||
const packageDecode = message.toObject(message.decode(input), {
|
||||
bytes: String,
|
||||
longs: Number,
|
||||
enums: String,
|
||||
defualts: true
|
||||
});
|
||||
const output = {};
|
||||
|
||||
if (this.showUnknownFields) {
|
||||
output[message.name] = packageDecode;
|
||||
output["Unknown Fields"] = this.compareFields(rawDecode, message);
|
||||
return output;
|
||||
} else {
|
||||
return packageDecode;
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
if (message) {
|
||||
throw new Error("Input " + error);
|
||||
} else {
|
||||
return rawDecode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace fieldnames with fieldname and type
|
||||
*
|
||||
* @param {Object} schemaRoot
|
||||
* @returns {Object}
|
||||
*/
|
||||
static appendTypesToFieldNames(schemaRoot) {
|
||||
for (const block of schemaRoot.nestedArray) {
|
||||
if (block instanceof protobuf.Type) {
|
||||
for (const [fieldName, fieldData] of Object.entries(block.fields)) {
|
||||
schemaRoot.nested[block.name].remove(block.fields[fieldName]);
|
||||
schemaRoot.nested[block.name].add(new protobuf.Field(`${fieldName} (${fieldData.type})`, fieldData.id, fieldData.type, fieldData.rule));
|
||||
}
|
||||
}
|
||||
}
|
||||
return schemaRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add field type to field name for fields in the raw decoded output
|
||||
*
|
||||
* @param {Object} rawDecode
|
||||
* @param {Object} fieldTypes
|
||||
* @returns {Object}
|
||||
*/
|
||||
static showRawTypes(rawDecode, fieldTypes) {
|
||||
for (const [fieldNum, value] of Object.entries(rawDecode)) {
|
||||
const fieldType = fieldTypes[fieldNum];
|
||||
let outputFieldValue;
|
||||
let outputFieldType;
|
||||
|
||||
// Submessages
|
||||
if (isNaN(fieldType)) {
|
||||
outputFieldType = 2;
|
||||
|
||||
// Repeated submessages
|
||||
if (Array.isArray(value)) {
|
||||
const fieldInstances = [];
|
||||
for (const instance of Object.keys(value)) {
|
||||
if (typeof(value[instance]) !== "string") {
|
||||
fieldInstances.push(this.showRawTypes(value[instance], fieldType));
|
||||
} else {
|
||||
fieldInstances.push(value[instance]);
|
||||
}
|
||||
}
|
||||
outputFieldValue = fieldInstances;
|
||||
|
||||
// Single submessage
|
||||
} else {
|
||||
outputFieldValue = this.showRawTypes(value, fieldType);
|
||||
}
|
||||
|
||||
// Non-submessage field
|
||||
} else {
|
||||
outputFieldType = fieldType;
|
||||
outputFieldValue = value;
|
||||
}
|
||||
|
||||
// Substitute fieldNum with field number and type
|
||||
rawDecode[`field #${fieldNum}: ${this.getTypeInfo(outputFieldType)}`] = outputFieldValue;
|
||||
delete rawDecode[fieldNum];
|
||||
}
|
||||
return rawDecode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare raw decode to package decode and return discrepancies
|
||||
*
|
||||
* @param rawDecodedMessage
|
||||
* @param schemaMessage
|
||||
* @returns {Object}
|
||||
*/
|
||||
static compareFields(rawDecodedMessage, schemaMessage) {
|
||||
// Define message data using raw decode output and schema
|
||||
const schemaFieldProperties = {};
|
||||
const schemaFieldNames = Object.keys(schemaMessage.fields);
|
||||
schemaFieldNames.forEach(field => schemaFieldProperties[schemaMessage.fields[field].id] = field);
|
||||
|
||||
// Loop over each field present in the raw decode output
|
||||
for (const fieldName in rawDecodedMessage) {
|
||||
let fieldId;
|
||||
if (isNaN(fieldName)) {
|
||||
fieldId = fieldName.match(/^field #(\d+)/)[1];
|
||||
} else {
|
||||
fieldId = fieldName;
|
||||
}
|
||||
|
||||
// Check if this field is defined in the schema
|
||||
if (fieldId in schemaFieldProperties) {
|
||||
const schemaFieldName = schemaFieldProperties[fieldId];
|
||||
|
||||
// Extract the current field data from the raw decode and schema
|
||||
const rawFieldData = rawDecodedMessage[fieldName];
|
||||
const schemaField = schemaMessage.fields[schemaFieldName];
|
||||
|
||||
// Check for repeated fields
|
||||
if (Array.isArray(rawFieldData) && !schemaField.repeated) {
|
||||
rawDecodedMessage[`(${schemaMessage.name}) ${schemaFieldName} is a repeated field`] = rawFieldData;
|
||||
}
|
||||
|
||||
// Check for submessage fields
|
||||
if (schemaField.resolvedType instanceof protobuf.Type) {
|
||||
const subMessageType = schemaMessage.fields[schemaFieldName].type;
|
||||
const schemaSubMessage = this.parsedProto.root.nested[subMessageType];
|
||||
const rawSubMessages = rawDecodedMessage[fieldName];
|
||||
let rawDecodedSubMessage = {};
|
||||
|
||||
// Squash multiple submessage instances into one submessage
|
||||
if (Array.isArray(rawSubMessages)) {
|
||||
rawSubMessages.forEach(subMessageInstance => {
|
||||
const instanceFields = Object.entries(subMessageInstance);
|
||||
instanceFields.forEach(subField => {
|
||||
rawDecodedSubMessage[subField[0]] = subField[1];
|
||||
});
|
||||
});
|
||||
} else {
|
||||
rawDecodedSubMessage = rawSubMessages;
|
||||
}
|
||||
|
||||
// Treat submessage as own message and compare its fields
|
||||
rawDecodedSubMessage = Protobuf.compareFields(rawDecodedSubMessage, schemaSubMessage);
|
||||
if (Object.entries(rawDecodedSubMessage).length !== 0) {
|
||||
rawDecodedMessage[`${schemaFieldName} (${subMessageType}) has missing fields`] = rawDecodedSubMessage;
|
||||
}
|
||||
}
|
||||
delete rawDecodedMessage[fieldName];
|
||||
}
|
||||
}
|
||||
return rawDecodedMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns wiretype information for input wiretype number
|
||||
*
|
||||
* @param {number} wireType
|
||||
* @returns {string}
|
||||
*/
|
||||
static getTypeInfo(wireType) {
|
||||
switch (wireType) {
|
||||
case 0:
|
||||
return "VarInt (e.g. int32, bool)";
|
||||
case 1:
|
||||
return "64-Bit (e.g. fixed64, double)";
|
||||
case 2:
|
||||
return "L-delim (e.g. string, message)";
|
||||
case 5:
|
||||
return "32-Bit (e.g. fixed32, float)";
|
||||
}
|
||||
}
|
||||
|
||||
// Private Class Functions
|
||||
@@ -143,6 +411,11 @@ class Protobuf {
|
||||
const header = this._fieldHeader();
|
||||
const type = header.type;
|
||||
const key = header.key;
|
||||
|
||||
if (typeof(this.fieldTypes[key]) !== "object") {
|
||||
this.fieldTypes[key] = type;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
// varint
|
||||
case 0:
|
||||
@@ -152,7 +425,7 @@ class Protobuf {
|
||||
return { "key": key, "value": this._uint64() };
|
||||
// length delimited
|
||||
case 2:
|
||||
return { "key": key, "value": this._lenDelim() };
|
||||
return { "key": key, "value": this._lenDelim(key) };
|
||||
// fixed 32
|
||||
case 5:
|
||||
return { "key": key, "value": this._uint32() };
|
||||
@@ -237,10 +510,10 @@ class Protobuf {
|
||||
* @returns {number}
|
||||
*/
|
||||
_uint64() {
|
||||
// Read off a Uint64
|
||||
let num = this.data[this.offset++] * 0x1000000 + (this.data[this.offset++] << 16) + (this.data[this.offset++] << 8) + this.data[this.offset++];
|
||||
num = num * 0x100000000 + this.data[this.offset++] * 0x1000000 + (this.data[this.offset++] << 16) + (this.data[this.offset++] << 8) + this.data[this.offset++];
|
||||
return num;
|
||||
// Read off a Uint64 with little-endian
|
||||
const lowerHalf = this.data[this.offset++] + (this.data[this.offset++] * 0x100) + (this.data[this.offset++] * 0x10000) + this.data[this.offset++] * 0x1000000;
|
||||
const upperHalf = this.data[this.offset++] + (this.data[this.offset++] * 0x100) + (this.data[this.offset++] * 0x10000) + this.data[this.offset++] * 0x1000000;
|
||||
return upperHalf * 0x100000000 + lowerHalf;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,7 +522,7 @@ class Protobuf {
|
||||
* @private
|
||||
* @returns {Object|string}
|
||||
*/
|
||||
_lenDelim() {
|
||||
_lenDelim(fieldNum) {
|
||||
// Read off the field length
|
||||
const length = this._varInt();
|
||||
const fieldBytes = this.data.slice(this.offset, this.offset + length);
|
||||
@@ -258,6 +531,10 @@ class Protobuf {
|
||||
// Attempt to parse as a new Protobuf Object
|
||||
const pbObject = new Protobuf(fieldBytes);
|
||||
field = pbObject._parse();
|
||||
|
||||
// Set field types object
|
||||
this.fieldTypes[fieldNum] = {...this.fieldTypes[fieldNum], ...pbObject.fieldTypes};
|
||||
|
||||
} catch (err) {
|
||||
// Otherwise treat as bytes
|
||||
field = Utils.byteArrayToChars(fieldBytes);
|
||||
@@ -276,7 +553,7 @@ class Protobuf {
|
||||
_uint32() {
|
||||
// Use a dataview to read off the integer
|
||||
const dataview = new DataView(new Uint8Array(this.data.slice(this.offset, this.offset + 4)).buffer);
|
||||
const value = dataview.getUint32(0);
|
||||
const value = dataview.getUint32(0, true);
|
||||
this.offset += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
502
src/core/lib/SIGABA.mjs
Normal file
502
src/core/lib/SIGABA.mjs
Normal file
@@ -0,0 +1,502 @@
|
||||
/**
|
||||
* Emulation of the SIGABA machine
|
||||
*
|
||||
* @author hettysymes
|
||||
* @copyright hettysymes 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* A set of randomised example SIGABA cipher/control rotors (these rotors are interchangeable). Cipher and control rotors can be referred to as C and R rotors respectively.
|
||||
*/
|
||||
export const CR_ROTORS = [
|
||||
{name: "Example 1", value: "SRGWANHPJZFXVIDQCEUKBYOLMT"},
|
||||
{name: "Example 2", value: "THQEFSAZVKJYULBODCPXNIMWRG"},
|
||||
{name: "Example 3", value: "XDTUYLEVFNQZBPOGIRCSMHWKAJ"},
|
||||
{name: "Example 4", value: "LOHDMCWUPSTNGVXYFJREQIKBZA"},
|
||||
{name: "Example 5", value: "ERXWNZQIJYLVOFUMSGHTCKPBDA"},
|
||||
{name: "Example 6", value: "FQECYHJIOUMDZVPSLKRTGWXBAN"},
|
||||
{name: "Example 7", value: "TBYIUMKZDJSOPEWXVANHLCFQGR"},
|
||||
{name: "Example 8", value: "QZUPDTFNYIAOMLEBWJXCGHKRSV"},
|
||||
{name: "Example 9", value: "CZWNHEMPOVXLKRSIDGJFYBTQAU"},
|
||||
{name: "Example 10", value: "ENPXJVKYQBFZTICAGMOHWRLDUS"}
|
||||
];
|
||||
|
||||
/**
|
||||
* A set of randomised example SIGABA index rotors (may be referred to as I rotors).
|
||||
*/
|
||||
export const I_ROTORS = [
|
||||
{name: "Example 1", value: "6201348957"},
|
||||
{name: "Example 2", value: "6147253089"},
|
||||
{name: "Example 3", value: "8239647510"},
|
||||
{name: "Example 4", value: "7194835260"},
|
||||
{name: "Example 5", value: "4873205916"}
|
||||
];
|
||||
|
||||
export const NUMBERS = "0123456789".split("");
|
||||
|
||||
/**
|
||||
* Converts a letter to uppercase (if it already isn't)
|
||||
*
|
||||
* @param {char} letter - letter to convert to uppercase
|
||||
* @returns {char}
|
||||
*/
|
||||
export function convToUpperCase(letter) {
|
||||
const charCode = letter.charCodeAt();
|
||||
if (97<=charCode && charCode<=122) {
|
||||
return String.fromCharCode(charCode-32);
|
||||
}
|
||||
return letter;
|
||||
}
|
||||
|
||||
/**
|
||||
* The SIGABA machine consisting of the 3 rotor banks: cipher, control and index banks.
|
||||
*/
|
||||
export class SigabaMachine {
|
||||
|
||||
/**
|
||||
* SigabaMachine constructor
|
||||
*
|
||||
* @param {Object[]} cipherRotors - list of CRRotors
|
||||
* @param {Object[]} controlRotors - list of CRRotors
|
||||
* @param {object[]} indexRotors - list of IRotors
|
||||
*/
|
||||
constructor(cipherRotors, controlRotors, indexRotors) {
|
||||
this.cipherBank = new CipherBank(cipherRotors);
|
||||
this.controlBank = new ControlBank(controlRotors);
|
||||
this.indexBank = new IndexBank(indexRotors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Steps all the correct rotors in the machine.
|
||||
*/
|
||||
step() {
|
||||
const controlOut = this.controlBank.goThroughControl();
|
||||
const indexOut = this.indexBank.goThroughIndex(controlOut);
|
||||
this.cipherBank.step(indexOut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a letter. A space is converted to a "Z" before encryption, and a "Z" is converted to an "X". This allows spaces to be encrypted.
|
||||
*
|
||||
* @param {char} letter - letter to encrypt
|
||||
* @returns {char}
|
||||
*/
|
||||
encryptLetter(letter) {
|
||||
letter = convToUpperCase(letter);
|
||||
if (letter === " ") {
|
||||
letter = "Z";
|
||||
} else if (letter === "Z") {
|
||||
letter = "X";
|
||||
}
|
||||
const encryptedLetter = this.cipherBank.encrypt(letter);
|
||||
this.step();
|
||||
return encryptedLetter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a letter. A letter decrypted as a "Z" is converted to a space before it is output, since spaces are converted to "Z"s before encryption.
|
||||
*
|
||||
* @param {char} letter - letter to decrypt
|
||||
* @returns {char}
|
||||
*/
|
||||
decryptLetter(letter) {
|
||||
letter = convToUpperCase(letter);
|
||||
let decryptedLetter = this.cipherBank.decrypt(letter);
|
||||
if (decryptedLetter === "Z") {
|
||||
decryptedLetter = " ";
|
||||
}
|
||||
this.step();
|
||||
return decryptedLetter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a message of one or more letters
|
||||
*
|
||||
* @param {string} msg - message to encrypt
|
||||
* @returns {string}
|
||||
*/
|
||||
encrypt(msg) {
|
||||
let ciphertext = "";
|
||||
for (const letter of msg) {
|
||||
ciphertext = ciphertext.concat(this.encryptLetter(letter));
|
||||
}
|
||||
return ciphertext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a message of one or more letters
|
||||
*
|
||||
* @param {string} msg - message to decrypt
|
||||
* @returns {string}
|
||||
*/
|
||||
decrypt(msg) {
|
||||
let plaintext = "";
|
||||
for (const letter of msg) {
|
||||
plaintext = plaintext.concat(this.decryptLetter(letter));
|
||||
}
|
||||
return plaintext;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The cipher rotor bank consists of 5 cipher rotors in either a forward or reversed orientation.
|
||||
*/
|
||||
export class CipherBank {
|
||||
|
||||
/**
|
||||
* CipherBank constructor
|
||||
*
|
||||
* @param {Object[]} rotors - list of CRRotors
|
||||
*/
|
||||
constructor(rotors) {
|
||||
this.rotors = rotors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a letter through the cipher rotors (signal goes from left-to-right)
|
||||
*
|
||||
* @param {char} inputPos - the input position of the signal (letter to be encrypted)
|
||||
* @returns {char}
|
||||
*/
|
||||
encrypt(inputPos) {
|
||||
for (const rotor of this.rotors) {
|
||||
inputPos = rotor.crypt(inputPos, "leftToRight");
|
||||
}
|
||||
return inputPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a letter through the cipher rotors (signal goes from right-to-left)
|
||||
*
|
||||
* @param {char} inputPos - the input position of the signal (letter to be decrypted)
|
||||
* @returns {char}
|
||||
*/
|
||||
decrypt(inputPos) {
|
||||
const revOrderedRotors = [...this.rotors].reverse();
|
||||
for (const rotor of revOrderedRotors) {
|
||||
inputPos = rotor.crypt(inputPos, "rightToLeft");
|
||||
}
|
||||
return inputPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Step the cipher rotors forward according to the inputs from the index rotors
|
||||
*
|
||||
* @param {number[]} indexInputs - the inputs from the index rotors
|
||||
*/
|
||||
step(indexInputs) {
|
||||
const logicDict = {0: [0, 9], 1: [7, 8], 2: [5, 6], 3: [3, 4], 4: [1, 2]};
|
||||
const rotorsToMove = [];
|
||||
for (const key in logicDict) {
|
||||
const item = logicDict[key];
|
||||
for (const i of indexInputs) {
|
||||
if (item.includes(i)) {
|
||||
rotorsToMove.push(this.rotors[key]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const rotor of rotorsToMove) {
|
||||
rotor.step();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The control rotor bank consists of 5 control rotors in either a forward or reversed orientation. Signals to the control rotor bank always go from right-to-left.
|
||||
*/
|
||||
export class ControlBank {
|
||||
|
||||
/**
|
||||
* ControlBank constructor. The rotors have been reversed as signals go from right-to-left through the control rotors.
|
||||
*
|
||||
* @param {Object[]} rotors - list of CRRotors
|
||||
*/
|
||||
constructor(rotors) {
|
||||
this.rotors = [...rotors].reverse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a letter.
|
||||
*
|
||||
* @param {char} inputPos - the input position of the signal
|
||||
* @returns {char}
|
||||
*/
|
||||
crypt(inputPos) {
|
||||
for (const rotor of this.rotors) {
|
||||
inputPos = rotor.crypt(inputPos, "rightToLeft");
|
||||
}
|
||||
return inputPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the outputs of the control rotors. The inputs to the control rotors are always "F", "G", "H" and "I".
|
||||
*
|
||||
* @returns {number[]}
|
||||
*/
|
||||
getOutputs() {
|
||||
const outputs = [this.crypt("F"), this.crypt("G"), this.crypt("H"), this.crypt("I")];
|
||||
const logicDict = {1: "B", 2: "C", 3: "DE", 4: "FGH", 5: "IJK", 6: "LMNO", 7: "PQRST", 8: "UVWXYZ", 9: "A"};
|
||||
const numberOutputs = [];
|
||||
for (const key in logicDict) {
|
||||
const item = logicDict[key];
|
||||
for (const output of outputs) {
|
||||
if (item.includes(output)) {
|
||||
numberOutputs.push(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return numberOutputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Steps the control rotors. Only 3 of the control rotors step: one after every encryption, one after every 26, and one after every 26 squared.
|
||||
*/
|
||||
step() {
|
||||
const MRotor = this.rotors[1], FRotor = this.rotors[2], SRotor = this.rotors[3];
|
||||
// 14 is the offset of "O" from "A" - the next rotor steps once the previous rotor reaches "O"
|
||||
if (FRotor.state === 14) {
|
||||
if (MRotor.state === 14) {
|
||||
SRotor.step();
|
||||
}
|
||||
MRotor.step();
|
||||
}
|
||||
FRotor.step();
|
||||
}
|
||||
|
||||
/**
|
||||
* The goThroughControl function combines getting the outputs from the control rotor bank and then stepping them.
|
||||
*
|
||||
* @returns {number[]}
|
||||
*/
|
||||
goThroughControl() {
|
||||
const outputs = this.getOutputs();
|
||||
this.step();
|
||||
return outputs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The index rotor bank consists of 5 index rotors all placed in the forwards orientation.
|
||||
*/
|
||||
export class IndexBank {
|
||||
|
||||
/**
|
||||
* IndexBank constructor
|
||||
*
|
||||
* @param {Object[]} rotors - list of IRotors
|
||||
*/
|
||||
constructor(rotors) {
|
||||
this.rotors = rotors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a number.
|
||||
*
|
||||
* @param {number} inputPos - the input position of the signal
|
||||
* @returns {number}
|
||||
*/
|
||||
crypt(inputPos) {
|
||||
for (const rotor of this.rotors) {
|
||||
inputPos = rotor.crypt(inputPos);
|
||||
}
|
||||
return inputPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* The goThroughIndex function takes the inputs from the control rotor bank and returns the list of outputs after encryption through the index rotors.
|
||||
*
|
||||
* @param {number[]} controlInputs - inputs from the control rotors
|
||||
* @returns {number[]}
|
||||
*/
|
||||
goThroughIndex(controlInputs) {
|
||||
const outputs = [];
|
||||
for (const inp of controlInputs) {
|
||||
outputs.push(this.crypt(inp));
|
||||
}
|
||||
return outputs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotor class
|
||||
*/
|
||||
export class Rotor {
|
||||
|
||||
/**
|
||||
* Rotor constructor
|
||||
*
|
||||
* @param {number[]} wireSetting - the wirings within the rotor: mapping from left-to-right, the index of the number in the list maps onto the number at that index
|
||||
* @param {bool} rev - true if the rotor is reversed, false if it isn't
|
||||
* @param {number} key - the starting position or state of the rotor
|
||||
*/
|
||||
constructor(wireSetting, key, rev) {
|
||||
this.state = key;
|
||||
this.numMapping = this.getNumMapping(wireSetting, rev);
|
||||
this.posMapping = this.getPosMapping(rev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number mapping from the wireSetting (only different from wireSetting if rotor is reversed)
|
||||
*
|
||||
* @param {number[]} wireSetting - the wirings within the rotors
|
||||
* @param {bool} rev - true if reversed, false if not
|
||||
* @returns {number[]}
|
||||
*/
|
||||
getNumMapping(wireSetting, rev) {
|
||||
if (rev===false) {
|
||||
return wireSetting;
|
||||
} else {
|
||||
const length = wireSetting.length;
|
||||
const tempMapping = new Array(length);
|
||||
for (let i=0; i<length; i++) {
|
||||
tempMapping[wireSetting[i]] = i;
|
||||
}
|
||||
return tempMapping;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position mapping (how the position numbers map onto the numbers of the rotor)
|
||||
*
|
||||
* @param {bool} rev - true if reversed, false if not
|
||||
* @returns {number[]}
|
||||
*/
|
||||
getPosMapping(rev) {
|
||||
const length = this.numMapping.length;
|
||||
const posMapping = [];
|
||||
if (rev===false) {
|
||||
for (let i = this.state; i < this.state+length; i++) {
|
||||
let res = i%length;
|
||||
if (res<0) {
|
||||
res += length;
|
||||
}
|
||||
posMapping.push(res);
|
||||
}
|
||||
} else {
|
||||
for (let i = this.state; i > this.state-length; i--) {
|
||||
let res = i%length;
|
||||
if (res<0) {
|
||||
res += length;
|
||||
}
|
||||
posMapping.push(res);
|
||||
}
|
||||
}
|
||||
return posMapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt/decrypt data. This process is identical to the rotors of cipher machines such as Enigma or Typex.
|
||||
*
|
||||
* @param {number} inputPos - the input position of the signal (the data to encrypt/decrypt)
|
||||
* @param {string} direction - one of "leftToRight" and "rightToLeft", states the direction in which the signal passes through the rotor
|
||||
* @returns {number}
|
||||
*/
|
||||
cryptNum(inputPos, direction) {
|
||||
const inpNum = this.posMapping[inputPos];
|
||||
let outNum;
|
||||
if (direction === "leftToRight") {
|
||||
outNum = this.numMapping[inpNum];
|
||||
} else if (direction === "rightToLeft") {
|
||||
outNum = this.numMapping.indexOf(inpNum);
|
||||
}
|
||||
const outPos = this.posMapping.indexOf(outNum);
|
||||
return outPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Steps the rotor. The number at position 0 will be moved to position 1 etc.
|
||||
*/
|
||||
step() {
|
||||
const lastNum = this.posMapping.pop();
|
||||
this.posMapping.splice(0, 0, lastNum);
|
||||
this.state = this.posMapping[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A CRRotor is a cipher (C) or control (R) rotor. These rotors are identical and interchangeable. A C or R rotor consists of 26 contacts, one for each letter, and may be put into either a forwards of reversed orientation.
|
||||
*/
|
||||
export class CRRotor extends Rotor {
|
||||
|
||||
/**
|
||||
* CRRotor constructor
|
||||
*
|
||||
* @param {string} wireSetting - the rotor wirings (string of letters)
|
||||
* @param {char} key - initial state of rotor
|
||||
* @param {bool} rev - true if reversed, false if not
|
||||
*/
|
||||
constructor(wireSetting, key, rev=false) {
|
||||
wireSetting = wireSetting.split("").map(CRRotor.letterToNum);
|
||||
super(wireSetting, CRRotor.letterToNum(key), rev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static function which converts a letter into its number i.e. its offset from the letter "A"
|
||||
*
|
||||
* @param {char} letter - letter to convert to number
|
||||
* @returns {number}
|
||||
*/
|
||||
static letterToNum(letter) {
|
||||
return letter.charCodeAt()-65;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static function which converts a number (a letter's offset from "A") into its letter
|
||||
*
|
||||
* @param {number} num - number to convert to letter
|
||||
* @returns {char}
|
||||
*/
|
||||
static numToLetter(num) {
|
||||
return String.fromCharCode(num+65);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts/decrypts a letter.
|
||||
*
|
||||
* @param {char} inputPos - the input position of the signal ("A" refers to position 0 etc.)
|
||||
* @param {string} direction - one of "leftToRight" and "rightToLeft"
|
||||
* @returns {char}
|
||||
*/
|
||||
crypt(inputPos, direction) {
|
||||
inputPos = CRRotor.letterToNum(inputPos);
|
||||
const outPos = this.cryptNum(inputPos, direction);
|
||||
return CRRotor.numToLetter(outPos);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* An IRotor is an index rotor, which consists of 10 contacts each numbered from 0 to 9. Unlike C and R rotors, they cannot be put in the reversed orientation. The index rotors do not step at any point during encryption or decryption.
|
||||
*/
|
||||
export class IRotor extends Rotor {
|
||||
|
||||
/**
|
||||
* IRotor constructor
|
||||
*
|
||||
* @param {string} wireSetting - the rotor wirings (string of numbers)
|
||||
* @param {char} key - initial state of rotor
|
||||
*/
|
||||
constructor(wireSetting, key) {
|
||||
wireSetting = wireSetting.split("").map(Number);
|
||||
super(wireSetting, Number(key), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a number
|
||||
*
|
||||
* @param {number} inputPos - the input position of the signal
|
||||
* @returns {number}
|
||||
*/
|
||||
crypt(inputPos) {
|
||||
return this.cryptNum(inputPos, "leftToRight");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -87,8 +87,9 @@ class AESDecrypt extends Operation {
|
||||
},
|
||||
{
|
||||
"name": "Additional Authenticated Data",
|
||||
"type": "binaryString",
|
||||
"value": ""
|
||||
"type": "toggleString",
|
||||
"value": "",
|
||||
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -107,7 +108,7 @@ class AESDecrypt extends Operation {
|
||||
inputType = args[3],
|
||||
outputType = args[4],
|
||||
gcmTag = Utils.convertToByteString(args[5].string, args[5].option),
|
||||
aad = args[6];
|
||||
aad = Utils.convertToByteString(args[6].string, args[6].option);
|
||||
|
||||
if ([16, 24, 32].indexOf(key.length) < 0) {
|
||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||
|
||||
@@ -81,8 +81,9 @@ class AESEncrypt extends Operation {
|
||||
},
|
||||
{
|
||||
"name": "Additional Authenticated Data",
|
||||
"type": "binaryString",
|
||||
"value": ""
|
||||
"type": "toggleString",
|
||||
"value": "",
|
||||
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -100,7 +101,7 @@ class AESEncrypt extends Operation {
|
||||
mode = args[2],
|
||||
inputType = args[3],
|
||||
outputType = args[4],
|
||||
aad = args[5];
|
||||
aad = Utils.convertToByteString(args[5].string, args[5].option);
|
||||
|
||||
if ([16, 24, 32].indexOf(key.length) < 0) {
|
||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/**
|
||||
* Emulation of the Bombe machine.
|
||||
*
|
||||
* Tested against the Bombe Rebuild at Bletchley Park's TNMOC
|
||||
* using a variety of inputs and settings to confirm correctness.
|
||||
*
|
||||
* @author s2224834
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
|
||||
41
src/core/operations/CBORDecode.mjs
Normal file
41
src/core/operations/CBORDecode.mjs
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @author Danh4 [dan.h4@ncsc.gov.uk]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Cbor from "cbor";
|
||||
|
||||
/**
|
||||
* CBOR Decode operation
|
||||
*/
|
||||
class CBORDecode extends Operation {
|
||||
|
||||
/**
|
||||
* CBORDecode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "CBOR Decode";
|
||||
this.module = "Serialise";
|
||||
this.description = "Concise Binary Object Representation (CBOR) is a binary data serialization format loosely based on JSON. Like JSON it allows the transmission of data objects that contain name–value pairs, but in a more concise manner. This increases processing and transfer speeds at the cost of human readability. It is defined in IETF RFC 8949.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/CBOR";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "JSON";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {JSON}
|
||||
*/
|
||||
run(input, args) {
|
||||
return Cbor.decodeFirstSync(Buffer.from(input).toString("hex"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CBORDecode;
|
||||
41
src/core/operations/CBOREncode.mjs
Normal file
41
src/core/operations/CBOREncode.mjs
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @author Danh4 [dan.h4@ncsc.gov.uk]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Cbor from "cbor";
|
||||
|
||||
/**
|
||||
* CBOR Encode operation
|
||||
*/
|
||||
class CBOREncode extends Operation {
|
||||
|
||||
/**
|
||||
* CBOREncode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "CBOR Encode";
|
||||
this.module = "Serialise";
|
||||
this.description = "Concise Binary Object Representation (CBOR) is a binary data serialization format loosely based on JSON. Like JSON it allows the transmission of data objects that contain name–value pairs, but in a more concise manner. This increases processing and transfer speeds at the cost of human readability. It is defined in IETF RFC 8949.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/CBOR";
|
||||
this.inputType = "JSON";
|
||||
this.outputType = "ArrayBuffer";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {JSON} input
|
||||
* @param {Object[]} args
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
run(input, args) {
|
||||
return new Uint8Array(Cbor.encodeCanonical(input)).buffer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CBOREncode;
|
||||
@@ -1,6 +1,9 @@
|
||||
/**
|
||||
* Emulation of Colossus.
|
||||
*
|
||||
* Tested against the Colossus Rebuild at Bletchley Park's TNMOC
|
||||
* using a variety of inputs and settings to confirm correctness.
|
||||
*
|
||||
* @author VirtualColossus [martin@virtualcolossus.co.uk]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
|
||||
@@ -67,7 +67,7 @@ class DeriveEVPKey extends Operation {
|
||||
iterations = args[2],
|
||||
hasher = args[3],
|
||||
salt = Utils.convertToByteString(args[4].string, args[4].option),
|
||||
key = CryptoJS.EvpKDF(passphrase, salt, {
|
||||
key = CryptoJS.EvpKDF(passphrase, salt, { // lgtm [js/insufficient-password-hash]
|
||||
keySize: keySize,
|
||||
hasher: CryptoJS.algo[hasher],
|
||||
iterations: iterations,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/**
|
||||
* Emulation of the Enigma machine.
|
||||
*
|
||||
* Tested against various genuine Enigma machines using a variety of inputs
|
||||
* and settings to confirm correctness.
|
||||
*
|
||||
* @author s2224834
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
|
||||
89
src/core/operations/FromBase45.mjs
Normal file
89
src/core/operations/FromBase45.mjs
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* @author Thomas Weißschuh [thomas@t-8ch.de]
|
||||
* @copyright Crown Copyright 2021
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import {ALPHABET, highlightToBase45, highlightFromBase45} from "../lib/Base45.mjs";
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
|
||||
|
||||
/**
|
||||
* From Base45 operation
|
||||
*/
|
||||
class FromBase45 extends Operation {
|
||||
|
||||
/**
|
||||
* FromBase45 constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "From Base45";
|
||||
this.module = "Default";
|
||||
this.description = "Base45 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers. The high number base results in shorter strings than with the decimal or hexadecimal system. Base45 is optimized for usage with QR codes.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems";
|
||||
this.inputType = "string";
|
||||
this.outputType = "byteArray";
|
||||
this.args = [
|
||||
{
|
||||
name: "Alphabet",
|
||||
type: "string",
|
||||
value: ALPHABET
|
||||
}
|
||||
];
|
||||
|
||||
this.highlight = highlightFromBase45;
|
||||
this.highlightReverse = highlightToBase45;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
if (!input) return [];
|
||||
const alphabet = Utils.expandAlphRange(args[0]);
|
||||
|
||||
const res = [];
|
||||
|
||||
for (const triple of Utils.chunked(input, 3)) {
|
||||
triple.reverse();
|
||||
let b = 0;
|
||||
for (const c of triple) {
|
||||
const idx = alphabet.indexOf(c);
|
||||
if (idx === -1) {
|
||||
throw new OperationError(`Character not in alphabet: '${c}'`);
|
||||
}
|
||||
b *= 45;
|
||||
b += idx;
|
||||
}
|
||||
|
||||
if (b > 65535) {
|
||||
throw new OperationError(`Triplet too large: '${triple.join("")}'`);
|
||||
}
|
||||
|
||||
if (triple.length > 2) {
|
||||
/**
|
||||
* The last triple may only have 2 bytes so we push the MSB when we got 3 bytes
|
||||
* Pushing MSB
|
||||
*/
|
||||
res.push(b >> 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushing LSB
|
||||
*/
|
||||
res.push(b & 0xff);
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default FromBase45;
|
||||
53
src/core/operations/GetAllCasings.mjs
Normal file
53
src/core/operations/GetAllCasings.mjs
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @author n1073645 [n1073645@gmail.com]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
|
||||
/**
|
||||
* Permutate String operation
|
||||
*/
|
||||
class GetAllCasings extends Operation {
|
||||
|
||||
/**
|
||||
* GetAllCasings constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Get All Casings";
|
||||
this.module = "Default";
|
||||
this.description = "Outputs all possible casing variations of a string.";
|
||||
this.infoURL = "";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const length = input.length;
|
||||
const max = 1 << length;
|
||||
input = input.toLowerCase();
|
||||
let result = "";
|
||||
|
||||
for (let i = 0; i < max; i++) {
|
||||
const temp = input.split("");
|
||||
for (let j = 0; j < length; j++) {
|
||||
if (((i >> j) & 1) === 1) {
|
||||
temp[j] = temp[j].toUpperCase();
|
||||
}
|
||||
}
|
||||
result += temp.join("") + "\n";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export default GetAllCasings;
|
||||
166
src/core/operations/HASSHClientFingerprint.mjs
Normal file
166
src/core/operations/HASSHClientFingerprint.mjs
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2021
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* HASSH created by Salesforce
|
||||
* Ben Reardon (@benreardon)
|
||||
* Adel Karimi (@0x4d31)
|
||||
* and the JA3 crew:
|
||||
* John B. Althouse
|
||||
* Jeff Atkinson
|
||||
* Josh Atkins
|
||||
*
|
||||
* Algorithm released under the BSD-3-clause licence
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import Stream from "../lib/Stream.mjs";
|
||||
import {runHash} from "../lib/Hash.mjs";
|
||||
|
||||
/**
|
||||
* HASSH Client Fingerprint operation
|
||||
*/
|
||||
class HASSHClientFingerprint extends Operation {
|
||||
|
||||
/**
|
||||
* HASSHClientFingerprint constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "HASSH Client Fingerprint";
|
||||
this.module = "Crypto";
|
||||
this.description = "Generates a HASSH fingerprint to help identify SSH clients based on hashing together values from the Client Key Exchange Init message.<br><br>Input: A hex stream of the SSH_MSG_KEXINIT packet application layer from Client to Server.";
|
||||
this.infoURL = "https://engineering.salesforce.com/open-sourcing-hassh-abed3ae5044c";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Input format",
|
||||
type: "option",
|
||||
value: ["Hex", "Base64", "Raw"]
|
||||
},
|
||||
{
|
||||
name: "Output format",
|
||||
type: "option",
|
||||
value: ["Hash digest", "HASSH algorithms string", "Full details"]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [inputFormat, outputFormat] = args;
|
||||
|
||||
input = Utils.convertToByteArray(input, inputFormat);
|
||||
const s = new Stream(new Uint8Array(input));
|
||||
|
||||
// Length
|
||||
const length = s.readInt(4);
|
||||
if (s.length !== length + 4)
|
||||
throw new OperationError("Incorrect packet length.");
|
||||
|
||||
// Padding length
|
||||
const paddingLength = s.readInt(1);
|
||||
|
||||
// Message code
|
||||
const messageCode = s.readInt(1);
|
||||
if (messageCode !== 20)
|
||||
throw new OperationError("Not a Key Exchange Init.");
|
||||
|
||||
// Cookie
|
||||
s.moveForwardsBy(16);
|
||||
|
||||
// KEX Algorithms
|
||||
const kexAlgosLength = s.readInt(4);
|
||||
const kexAlgos = s.readString(kexAlgosLength);
|
||||
|
||||
// Server Host Key Algorithms
|
||||
const serverHostKeyAlgosLength = s.readInt(4);
|
||||
s.moveForwardsBy(serverHostKeyAlgosLength);
|
||||
|
||||
// Encryption Algorithms Client to Server
|
||||
const encAlgosC2SLength = s.readInt(4);
|
||||
const encAlgosC2S = s.readString(encAlgosC2SLength);
|
||||
|
||||
// Encryption Algorithms Server to Client
|
||||
const encAlgosS2CLength = s.readInt(4);
|
||||
s.moveForwardsBy(encAlgosS2CLength);
|
||||
|
||||
// MAC Algorithms Client to Server
|
||||
const macAlgosC2SLength = s.readInt(4);
|
||||
const macAlgosC2S = s.readString(macAlgosC2SLength);
|
||||
|
||||
// MAC Algorithms Server to Client
|
||||
const macAlgosS2CLength = s.readInt(4);
|
||||
s.moveForwardsBy(macAlgosS2CLength);
|
||||
|
||||
// Compression Algorithms Client to Server
|
||||
const compAlgosC2SLength = s.readInt(4);
|
||||
const compAlgosC2S = s.readString(compAlgosC2SLength);
|
||||
|
||||
// Compression Algorithms Server to Client
|
||||
const compAlgosS2CLength = s.readInt(4);
|
||||
s.moveForwardsBy(compAlgosS2CLength);
|
||||
|
||||
// Languages Client to Server
|
||||
const langsC2SLength = s.readInt(4);
|
||||
s.moveForwardsBy(langsC2SLength);
|
||||
|
||||
// Languages Server to Client
|
||||
const langsS2CLength = s.readInt(4);
|
||||
s.moveForwardsBy(langsS2CLength);
|
||||
|
||||
// First KEX packet follows
|
||||
s.moveForwardsBy(1);
|
||||
|
||||
// Reserved
|
||||
s.moveForwardsBy(4);
|
||||
|
||||
// Padding string
|
||||
s.moveForwardsBy(paddingLength);
|
||||
|
||||
// Output
|
||||
const hassh = [
|
||||
kexAlgos,
|
||||
encAlgosC2S,
|
||||
macAlgosC2S,
|
||||
compAlgosC2S
|
||||
];
|
||||
const hasshStr = hassh.join(";");
|
||||
const hasshHash = runHash("md5", Utils.strToArrayBuffer(hasshStr));
|
||||
|
||||
switch (outputFormat) {
|
||||
case "HASSH algorithms string":
|
||||
return hasshStr;
|
||||
case "Full details":
|
||||
return `Hash digest:
|
||||
${hasshHash}
|
||||
|
||||
Full HASSH algorithms string:
|
||||
${hasshStr}
|
||||
|
||||
Key Exchange Algorithms:
|
||||
${kexAlgos}
|
||||
Encryption Algorithms Client to Server:
|
||||
${encAlgosC2S}
|
||||
MAC Algorithms Client to Server:
|
||||
${macAlgosC2S}
|
||||
Compression Algorithms Client to Server:
|
||||
${compAlgosC2S}`;
|
||||
case "Hash digest":
|
||||
default:
|
||||
return hasshHash;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default HASSHClientFingerprint;
|
||||
166
src/core/operations/HASSHServerFingerprint.mjs
Normal file
166
src/core/operations/HASSHServerFingerprint.mjs
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2021
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* HASSH created by Salesforce
|
||||
* Ben Reardon (@benreardon)
|
||||
* Adel Karimi (@0x4d31)
|
||||
* and the JA3 crew:
|
||||
* John B. Althouse
|
||||
* Jeff Atkinson
|
||||
* Josh Atkins
|
||||
*
|
||||
* Algorithm released under the BSD-3-clause licence
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import Stream from "../lib/Stream.mjs";
|
||||
import {runHash} from "../lib/Hash.mjs";
|
||||
|
||||
/**
|
||||
* HASSH Server Fingerprint operation
|
||||
*/
|
||||
class HASSHServerFingerprint extends Operation {
|
||||
|
||||
/**
|
||||
* HASSHServerFingerprint constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "HASSH Server Fingerprint";
|
||||
this.module = "Crypto";
|
||||
this.description = "Generates a HASSH fingerprint to help identify SSH servers based on hashing together values from the Server Key Exchange Init message.<br><br>Input: A hex stream of the SSH_MSG_KEXINIT packet application layer from Server to Client.";
|
||||
this.infoURL = "https://engineering.salesforce.com/open-sourcing-hassh-abed3ae5044c";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Input format",
|
||||
type: "option",
|
||||
value: ["Hex", "Base64", "Raw"]
|
||||
},
|
||||
{
|
||||
name: "Output format",
|
||||
type: "option",
|
||||
value: ["Hash digest", "HASSH algorithms string", "Full details"]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [inputFormat, outputFormat] = args;
|
||||
|
||||
input = Utils.convertToByteArray(input, inputFormat);
|
||||
const s = new Stream(new Uint8Array(input));
|
||||
|
||||
// Length
|
||||
const length = s.readInt(4);
|
||||
if (s.length !== length + 4)
|
||||
throw new OperationError("Incorrect packet length.");
|
||||
|
||||
// Padding length
|
||||
const paddingLength = s.readInt(1);
|
||||
|
||||
// Message code
|
||||
const messageCode = s.readInt(1);
|
||||
if (messageCode !== 20)
|
||||
throw new OperationError("Not a Key Exchange Init.");
|
||||
|
||||
// Cookie
|
||||
s.moveForwardsBy(16);
|
||||
|
||||
// KEX Algorithms
|
||||
const kexAlgosLength = s.readInt(4);
|
||||
const kexAlgos = s.readString(kexAlgosLength);
|
||||
|
||||
// Server Host Key Algorithms
|
||||
const serverHostKeyAlgosLength = s.readInt(4);
|
||||
s.moveForwardsBy(serverHostKeyAlgosLength);
|
||||
|
||||
// Encryption Algorithms Client to Server
|
||||
const encAlgosC2SLength = s.readInt(4);
|
||||
s.moveForwardsBy(encAlgosC2SLength);
|
||||
|
||||
// Encryption Algorithms Server to Client
|
||||
const encAlgosS2CLength = s.readInt(4);
|
||||
const encAlgosS2C = s.readString(encAlgosS2CLength);
|
||||
|
||||
// MAC Algorithms Client to Server
|
||||
const macAlgosC2SLength = s.readInt(4);
|
||||
s.moveForwardsBy(macAlgosC2SLength);
|
||||
|
||||
// MAC Algorithms Server to Client
|
||||
const macAlgosS2CLength = s.readInt(4);
|
||||
const macAlgosS2C = s.readString(macAlgosS2CLength);
|
||||
|
||||
// Compression Algorithms Client to Server
|
||||
const compAlgosC2SLength = s.readInt(4);
|
||||
s.moveForwardsBy(compAlgosC2SLength);
|
||||
|
||||
// Compression Algorithms Server to Client
|
||||
const compAlgosS2CLength = s.readInt(4);
|
||||
const compAlgosS2C = s.readString(compAlgosS2CLength);
|
||||
|
||||
// Languages Client to Server
|
||||
const langsC2SLength = s.readInt(4);
|
||||
s.moveForwardsBy(langsC2SLength);
|
||||
|
||||
// Languages Server to Client
|
||||
const langsS2CLength = s.readInt(4);
|
||||
s.moveForwardsBy(langsS2CLength);
|
||||
|
||||
// First KEX packet follows
|
||||
s.moveForwardsBy(1);
|
||||
|
||||
// Reserved
|
||||
s.moveForwardsBy(4);
|
||||
|
||||
// Padding string
|
||||
s.moveForwardsBy(paddingLength);
|
||||
|
||||
// Output
|
||||
const hassh = [
|
||||
kexAlgos,
|
||||
encAlgosS2C,
|
||||
macAlgosS2C,
|
||||
compAlgosS2C
|
||||
];
|
||||
const hasshStr = hassh.join(";");
|
||||
const hasshHash = runHash("md5", Utils.strToArrayBuffer(hasshStr));
|
||||
|
||||
switch (outputFormat) {
|
||||
case "HASSH algorithms string":
|
||||
return hasshStr;
|
||||
case "Full details":
|
||||
return `Hash digest:
|
||||
${hasshHash}
|
||||
|
||||
Full HASSH algorithms string:
|
||||
${hasshStr}
|
||||
|
||||
Key Exchange Algorithms:
|
||||
${kexAlgos}
|
||||
Encryption Algorithms Server to Client:
|
||||
${encAlgosS2C}
|
||||
MAC Algorithms Server to Client:
|
||||
${macAlgosS2C}
|
||||
Compression Algorithms Server to Client:
|
||||
${compAlgosS2C}`;
|
||||
case "Hash digest":
|
||||
default:
|
||||
return hasshHash;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default HASSHServerFingerprint;
|
||||
205
src/core/operations/JA3Fingerprint.mjs
Normal file
205
src/core/operations/JA3Fingerprint.mjs
Normal file
@@ -0,0 +1,205 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2021
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* JA3 created by Salesforce
|
||||
* John B. Althouse
|
||||
* Jeff Atkinson
|
||||
* Josh Atkins
|
||||
*
|
||||
* Algorithm released under the BSD-3-clause licence
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import Stream from "../lib/Stream.mjs";
|
||||
import {runHash} from "../lib/Hash.mjs";
|
||||
|
||||
/**
|
||||
* JA3 Fingerprint operation
|
||||
*/
|
||||
class JA3Fingerprint extends Operation {
|
||||
|
||||
/**
|
||||
* JA3Fingerprint constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "JA3 Fingerprint";
|
||||
this.module = "Crypto";
|
||||
this.description = "Generates a JA3 fingerprint to help identify TLS clients based on hashing together values from the Client Hello.<br><br>Input: A hex stream of the TLS Client Hello packet application layer.";
|
||||
this.infoURL = "https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Input format",
|
||||
type: "option",
|
||||
value: ["Hex", "Base64", "Raw"]
|
||||
},
|
||||
{
|
||||
name: "Output format",
|
||||
type: "option",
|
||||
value: ["Hash digest", "JA3 string", "Full details"]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [inputFormat, outputFormat] = args;
|
||||
|
||||
input = Utils.convertToByteArray(input, inputFormat);
|
||||
const s = new Stream(new Uint8Array(input));
|
||||
|
||||
const handshake = s.readInt(1);
|
||||
if (handshake !== 0x16)
|
||||
throw new OperationError("Not handshake data.");
|
||||
|
||||
// Version
|
||||
s.moveForwardsBy(2);
|
||||
|
||||
// Length
|
||||
const length = s.readInt(2);
|
||||
if (s.length !== length + 5)
|
||||
throw new OperationError("Incorrect handshake length.");
|
||||
|
||||
// Handshake type
|
||||
const handshakeType = s.readInt(1);
|
||||
if (handshakeType !== 1)
|
||||
throw new OperationError("Not a Client Hello.");
|
||||
|
||||
// Handshake length
|
||||
const handshakeLength = s.readInt(3);
|
||||
if (s.length !== handshakeLength + 9)
|
||||
throw new OperationError("Not enough data in Client Hello.");
|
||||
|
||||
// Hello version
|
||||
const helloVersion = s.readInt(2);
|
||||
|
||||
// Random
|
||||
s.moveForwardsBy(32);
|
||||
|
||||
// Session ID
|
||||
const sessionIDLength = s.readInt(1);
|
||||
s.moveForwardsBy(sessionIDLength);
|
||||
|
||||
// Cipher suites
|
||||
const cipherSuitesLength = s.readInt(2);
|
||||
const cipherSuites = s.getBytes(cipherSuitesLength);
|
||||
const cs = new Stream(cipherSuites);
|
||||
const cipherSegment = parseJA3Segment(cs, 2);
|
||||
|
||||
// Compression Methods
|
||||
const compressionMethodsLength = s.readInt(1);
|
||||
s.moveForwardsBy(compressionMethodsLength);
|
||||
|
||||
// Extensions
|
||||
const extensionsLength = s.readInt(2);
|
||||
const extensions = s.getBytes(extensionsLength);
|
||||
const es = new Stream(extensions);
|
||||
let ecsLen, ecs, ellipticCurves = "", ellipticCurvePointFormats = "";
|
||||
const exts = [];
|
||||
while (es.hasMore()) {
|
||||
const type = es.readInt(2);
|
||||
const length = es.readInt(2);
|
||||
switch (type) {
|
||||
case 0x0a: // Elliptic curves
|
||||
ecsLen = es.readInt(2);
|
||||
ecs = new Stream(es.getBytes(ecsLen));
|
||||
ellipticCurves = parseJA3Segment(ecs, 2);
|
||||
break;
|
||||
case 0x0b: // Elliptic curve point formats
|
||||
ecsLen = es.readInt(1);
|
||||
ecs = new Stream(es.getBytes(ecsLen));
|
||||
ellipticCurvePointFormats = parseJA3Segment(ecs, 1);
|
||||
break;
|
||||
default:
|
||||
es.moveForwardsBy(length);
|
||||
}
|
||||
if (!GREASE_CIPHERSUITES.includes(type))
|
||||
exts.push(type);
|
||||
}
|
||||
|
||||
// Output
|
||||
const ja3 = [
|
||||
helloVersion.toString(),
|
||||
cipherSegment,
|
||||
exts.join("-"),
|
||||
ellipticCurves,
|
||||
ellipticCurvePointFormats
|
||||
];
|
||||
const ja3Str = ja3.join(",");
|
||||
const ja3Hash = runHash("md5", Utils.strToArrayBuffer(ja3Str));
|
||||
|
||||
switch (outputFormat) {
|
||||
case "JA3 string":
|
||||
return ja3Str;
|
||||
case "Full details":
|
||||
return `Hash digest:
|
||||
${ja3Hash}
|
||||
|
||||
Full JA3 string:
|
||||
${ja3Str}
|
||||
|
||||
TLS Version:
|
||||
${helloVersion.toString()}
|
||||
Cipher Suites:
|
||||
${cipherSegment}
|
||||
Extensions:
|
||||
${exts.join("-")}
|
||||
Elliptic Curves:
|
||||
${ellipticCurves}
|
||||
Elliptic Curve Point Formats:
|
||||
${ellipticCurvePointFormats}`;
|
||||
case "Hash digest":
|
||||
default:
|
||||
return ja3Hash;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a JA3 segment, returning a "-" separated list
|
||||
*
|
||||
* @param {Stream} stream
|
||||
* @returns {string}
|
||||
*/
|
||||
function parseJA3Segment(stream, size=2) {
|
||||
const segment = [];
|
||||
while (stream.hasMore()) {
|
||||
const element = stream.readInt(size);
|
||||
if (!GREASE_CIPHERSUITES.includes(element))
|
||||
segment.push(element);
|
||||
}
|
||||
return segment.join("-");
|
||||
}
|
||||
|
||||
const GREASE_CIPHERSUITES = [
|
||||
0x0a0a,
|
||||
0x1a1a,
|
||||
0x2a2a,
|
||||
0x3a3a,
|
||||
0x4a4a,
|
||||
0x5a5a,
|
||||
0x6a6a,
|
||||
0x7a7a,
|
||||
0x8a8a,
|
||||
0x9a9a,
|
||||
0xaaaa,
|
||||
0xbaba,
|
||||
0xcaca,
|
||||
0xdada,
|
||||
0xeaea,
|
||||
0xfafa
|
||||
];
|
||||
|
||||
export default JA3Fingerprint;
|
||||
145
src/core/operations/JA3SFingerprint.mjs
Normal file
145
src/core/operations/JA3SFingerprint.mjs
Normal file
@@ -0,0 +1,145 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2021
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* JA3S created by Salesforce
|
||||
* John B. Althouse
|
||||
* Jeff Atkinson
|
||||
* Josh Atkins
|
||||
*
|
||||
* Algorithm released under the BSD-3-clause licence
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import Stream from "../lib/Stream.mjs";
|
||||
import {runHash} from "../lib/Hash.mjs";
|
||||
|
||||
/**
|
||||
* JA3S Fingerprint operation
|
||||
*/
|
||||
class JA3SFingerprint extends Operation {
|
||||
|
||||
/**
|
||||
* JA3SFingerprint constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "JA3S Fingerprint";
|
||||
this.module = "Crypto";
|
||||
this.description = "Generates a JA3S fingerprint to help identify TLS servers based on hashing together values from the Server Hello.<br><br>Input: A hex stream of the TLS Server Hello record application layer.";
|
||||
this.infoURL = "https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Input format",
|
||||
type: "option",
|
||||
value: ["Hex", "Base64", "Raw"]
|
||||
},
|
||||
{
|
||||
name: "Output format",
|
||||
type: "option",
|
||||
value: ["Hash digest", "JA3S string", "Full details"]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [inputFormat, outputFormat] = args;
|
||||
|
||||
input = Utils.convertToByteArray(input, inputFormat);
|
||||
const s = new Stream(new Uint8Array(input));
|
||||
|
||||
const handshake = s.readInt(1);
|
||||
if (handshake !== 0x16)
|
||||
throw new OperationError("Not handshake data.");
|
||||
|
||||
// Version
|
||||
s.moveForwardsBy(2);
|
||||
|
||||
// Length
|
||||
const length = s.readInt(2);
|
||||
if (s.length !== length + 5)
|
||||
throw new OperationError("Incorrect handshake length.");
|
||||
|
||||
// Handshake type
|
||||
const handshakeType = s.readInt(1);
|
||||
if (handshakeType !== 2)
|
||||
throw new OperationError("Not a Server Hello.");
|
||||
|
||||
// Handshake length
|
||||
const handshakeLength = s.readInt(3);
|
||||
if (s.length !== handshakeLength + 9)
|
||||
throw new OperationError("Not enough data in Server Hello.");
|
||||
|
||||
// Hello version
|
||||
const helloVersion = s.readInt(2);
|
||||
|
||||
// Random
|
||||
s.moveForwardsBy(32);
|
||||
|
||||
// Session ID
|
||||
const sessionIDLength = s.readInt(1);
|
||||
s.moveForwardsBy(sessionIDLength);
|
||||
|
||||
// Cipher suite
|
||||
const cipherSuite = s.readInt(2);
|
||||
|
||||
// Compression Method
|
||||
s.moveForwardsBy(1);
|
||||
|
||||
// Extensions
|
||||
const extensionsLength = s.readInt(2);
|
||||
const extensions = s.getBytes(extensionsLength);
|
||||
const es = new Stream(extensions);
|
||||
const exts = [];
|
||||
while (es.hasMore()) {
|
||||
const type = es.readInt(2);
|
||||
const length = es.readInt(2);
|
||||
es.moveForwardsBy(length);
|
||||
exts.push(type);
|
||||
}
|
||||
|
||||
// Output
|
||||
const ja3s = [
|
||||
helloVersion.toString(),
|
||||
cipherSuite,
|
||||
exts.join("-")
|
||||
];
|
||||
const ja3sStr = ja3s.join(",");
|
||||
const ja3sHash = runHash("md5", Utils.strToArrayBuffer(ja3sStr));
|
||||
|
||||
switch (outputFormat) {
|
||||
case "JA3S string":
|
||||
return ja3sStr;
|
||||
case "Full details":
|
||||
return `Hash digest:
|
||||
${ja3sHash}
|
||||
|
||||
Full JA3S string:
|
||||
${ja3sStr}
|
||||
|
||||
TLS Version:
|
||||
${helloVersion.toString()}
|
||||
Cipher Suite:
|
||||
${cipherSuite}
|
||||
Extensions:
|
||||
${exts.join("-")}`;
|
||||
case "Hash digest":
|
||||
default:
|
||||
return ja3sHash;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default JA3SFingerprint;
|
||||
@@ -1,6 +1,9 @@
|
||||
/**
|
||||
* Emulation of the Lorenz SZ40/42a/42b cipher attachment.
|
||||
*
|
||||
* Tested against the Colossus Rebuild at Bletchley Park's TNMOC
|
||||
* using a variety of inputs and settings to confirm correctness.
|
||||
*
|
||||
* @author VirtualColossus [martin@virtualcolossus.co.uk]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
|
||||
@@ -165,6 +165,89 @@ class ParseIPv6Address extends Operation {
|
||||
// Multicast
|
||||
output += "\nThis is a reserved multicast address.";
|
||||
output += "\nMulticast addresses range: ff00::/8";
|
||||
|
||||
switch (ipv6[0]) {
|
||||
case 0xff01:
|
||||
output += "\n\nReserved Multicast Block for Interface Local Scope";
|
||||
break;
|
||||
case 0xff02:
|
||||
output += "\n\nReserved Multicast Block for Link Local Scope";
|
||||
break;
|
||||
case 0xff03:
|
||||
output += "\n\nReserved Multicast Block for Realm Local Scope";
|
||||
break;
|
||||
case 0xff04:
|
||||
output += "\n\nReserved Multicast Block for Admin Local Scope";
|
||||
break;
|
||||
case 0xff05:
|
||||
output += "\n\nReserved Multicast Block for Site Local Scope";
|
||||
break;
|
||||
case 0xff08:
|
||||
output += "\n\nReserved Multicast Block for Organisation Local Scope";
|
||||
break;
|
||||
case 0xff0e:
|
||||
output += "\n\nReserved Multicast Block for Global Scope";
|
||||
break;
|
||||
}
|
||||
|
||||
if (ipv6[6] === 1) {
|
||||
if (ipv6[7] === 2) {
|
||||
output += "\nReserved Multicast Address for 'All DHCP Servers and Relay Agents (defined in RFC3315)'";
|
||||
} else if (ipv6[7] === 3) {
|
||||
output += "\nReserved Multicast Address for 'All LLMNR Hosts (defined in RFC4795)'";
|
||||
}
|
||||
} else {
|
||||
switch (ipv6[7]) {
|
||||
case 1:
|
||||
output += "\nReserved Multicast Address for 'All nodes'";
|
||||
break;
|
||||
case 2:
|
||||
output += "\nReserved Multicast Address for 'All routers'";
|
||||
break;
|
||||
case 5:
|
||||
output += "\nReserved Multicast Address for 'OSPFv3 - All OSPF routers'";
|
||||
break;
|
||||
case 6:
|
||||
output += "\nReserved Multicast Address for 'OSPFv3 - All Designated Routers'";
|
||||
break;
|
||||
case 8:
|
||||
output += "\nReserved Multicast Address for 'IS-IS for IPv6 Routers'";
|
||||
break;
|
||||
case 9:
|
||||
output += "\nReserved Multicast Address for 'RIP Routers'";
|
||||
break;
|
||||
case 0xa:
|
||||
output += "\nReserved Multicast Address for 'EIGRP Routers'";
|
||||
break;
|
||||
case 0xc:
|
||||
output += "\nReserved Multicast Address for 'Simple Service Discovery Protocol'";
|
||||
break;
|
||||
case 0xd:
|
||||
output += "\nReserved Multicast Address for 'PIM Routers'";
|
||||
break;
|
||||
case 0x16:
|
||||
output += "\nReserved Multicast Address for 'MLDv2 Reports (defined in RFC3810)'";
|
||||
break;
|
||||
case 0x6b:
|
||||
output += "\nReserved Multicast Address for 'Precision Time Protocol v2 Peer Delay Measurement Messages'";
|
||||
break;
|
||||
case 0xfb:
|
||||
output += "\nReserved Multicast Address for 'Multicast DNS'";
|
||||
break;
|
||||
case 0x101:
|
||||
output += "\nReserved Multicast Address for 'Network Time Protocol'";
|
||||
break;
|
||||
case 0x108:
|
||||
output += "\nReserved Multicast Address for 'Network Information Service'";
|
||||
break;
|
||||
case 0x114:
|
||||
output += "\nReserved Multicast Address for 'Experiments'";
|
||||
break;
|
||||
case 0x181:
|
||||
output += "\nReserved Multicast Address for 'Precision Time Protocol v2 Messages (exc. Peer Delay)'";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,12 +20,30 @@ class ProtobufDecode extends Operation {
|
||||
super();
|
||||
|
||||
this.name = "Protobuf Decode";
|
||||
this.module = "Default";
|
||||
this.description = "Decodes any Protobuf encoded data to a JSON representation of the data using the field number as the field key.";
|
||||
this.module = "Protobuf";
|
||||
this.description = "Decodes any Protobuf encoded data to a JSON representation of the data using the field number as the field key.<br><br>If a .proto schema is defined, the encoded data will be decoded with reference to the schema. Only one message instance will be decoded. <br><br><u>Show Unknown Fields</u><br>When a schema is used, this option shows fields that are present in the input data but not defined in the schema.<br><br><u>Show Types</u><br>Show the type of a field next to its name. For undefined fields, the wiretype and example types are shown instead.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Protocol_Buffers";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "JSON";
|
||||
this.args = [];
|
||||
this.args = [
|
||||
{
|
||||
name: "Schema (.proto text)",
|
||||
type: "text",
|
||||
value: "",
|
||||
rows: 8,
|
||||
hint: "Drag and drop is enabled on this ingredient"
|
||||
},
|
||||
{
|
||||
name: "Show Unknown Fields",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "Show Types",
|
||||
type: "boolean",
|
||||
value: false
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,7 +54,7 @@ class ProtobufDecode extends Operation {
|
||||
run(input, args) {
|
||||
input = new Uint8Array(input);
|
||||
try {
|
||||
return Protobuf.decode(input);
|
||||
return Protobuf.decode(input, args);
|
||||
} catch (err) {
|
||||
throw new OperationError(err);
|
||||
}
|
||||
|
||||
54
src/core/operations/ProtobufEncode.mjs
Normal file
54
src/core/operations/ProtobufEncode.mjs
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @author GCHQ Contributor [3]
|
||||
* @copyright Crown Copyright 2021
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import Protobuf from "../lib/Protobuf.mjs";
|
||||
|
||||
/**
|
||||
* Protobuf Encode operation
|
||||
*/
|
||||
class ProtobufEncode extends Operation {
|
||||
|
||||
/**
|
||||
* ProtobufEncode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Protobuf Encode";
|
||||
this.module = "Protobuf";
|
||||
this.description = "Encodes a valid JSON object into a protobuf byte array using the input .proto schema.";
|
||||
this.infoURL = "https://developers.google.com/protocol-buffers/docs/encoding";
|
||||
this.inputType = "JSON";
|
||||
this.outputType = "ArrayBuffer";
|
||||
this.args = [
|
||||
{
|
||||
name: "Schema (.proto text)",
|
||||
type: "text",
|
||||
value: "",
|
||||
rows: 8,
|
||||
hint: "Drag and drop is enabled on this ingredient"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} input
|
||||
* @param {Object[]} args
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
run(input, args) {
|
||||
try {
|
||||
return Protobuf.encode(input, args);
|
||||
} catch (error) {
|
||||
throw new OperationError(error);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ProtobufEncode;
|
||||
287
src/core/operations/SIGABA.mjs
Normal file
287
src/core/operations/SIGABA.mjs
Normal file
@@ -0,0 +1,287 @@
|
||||
/**
|
||||
* Emulation of the SIGABA machine.
|
||||
*
|
||||
* @author hettysymes
|
||||
* @copyright hettysymes 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import {LETTERS} from "../lib/Enigma.mjs";
|
||||
import {NUMBERS, CR_ROTORS, I_ROTORS, SigabaMachine, CRRotor, IRotor} from "../lib/SIGABA.mjs";
|
||||
|
||||
/**
|
||||
* Sigaba operation
|
||||
*/
|
||||
class Sigaba extends Operation {
|
||||
|
||||
/**
|
||||
* Sigaba constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "SIGABA";
|
||||
this.module = "Bletchley";
|
||||
this.description = "Encipher/decipher with the WW2 SIGABA machine. <br><br>SIGABA, otherwise known as ECM Mark II, was used by the United States for message encryption during WW2 up to the 1950s. It was developed in the 1930s by the US Army and Navy, and has up to this day never been broken. Consisting of 15 rotors: 5 cipher rotors and 10 rotors (5 control rotors and 5 index rotors) controlling the stepping of the cipher rotors, the rotor stepping for SIGABA is much more complex than other rotor machines of its time, such as Enigma. All example rotor wirings are random example sets.<br><br>To configure rotor wirings, for the cipher and control rotors enter a string of letters which map from A to Z, and for the index rotors enter a sequence of numbers which map from 0 to 9. Note that encryption is not the same as decryption, so first choose the desired mode. <br><br> Note: Whilst this has been tested against other software emulators, it has not been tested against hardware.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/SIGABA";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "1st (left-hand) cipher rotor",
|
||||
type: "editableOption",
|
||||
value: CR_ROTORS,
|
||||
defaultIndex: 0
|
||||
},
|
||||
{
|
||||
name: "1st cipher rotor reversed",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "1st cipher rotor intial value",
|
||||
type: "option",
|
||||
value: LETTERS
|
||||
},
|
||||
{
|
||||
name: "2nd cipher rotor",
|
||||
type: "editableOption",
|
||||
value: CR_ROTORS,
|
||||
defaultIndex: 0
|
||||
},
|
||||
{
|
||||
name: "2nd cipher rotor reversed",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "2nd cipher rotor intial value",
|
||||
type: "option",
|
||||
value: LETTERS
|
||||
},
|
||||
{
|
||||
name: "3rd (middle) cipher rotor",
|
||||
type: "editableOption",
|
||||
value: CR_ROTORS,
|
||||
defaultIndex: 0
|
||||
},
|
||||
{
|
||||
name: "3rd cipher rotor reversed",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "3rd cipher rotor intial value",
|
||||
type: "option",
|
||||
value: LETTERS
|
||||
},
|
||||
{
|
||||
name: "4th cipher rotor",
|
||||
type: "editableOption",
|
||||
value: CR_ROTORS,
|
||||
defaultIndex: 0
|
||||
},
|
||||
{
|
||||
name: "4th cipher rotor reversed",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "4th cipher rotor intial value",
|
||||
type: "option",
|
||||
value: LETTERS
|
||||
},
|
||||
{
|
||||
name: "5th (right-hand) cipher rotor",
|
||||
type: "editableOption",
|
||||
value: CR_ROTORS,
|
||||
defaultIndex: 0
|
||||
},
|
||||
{
|
||||
name: "5th cipher rotor reversed",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "5th cipher rotor intial value",
|
||||
type: "option",
|
||||
value: LETTERS
|
||||
},
|
||||
{
|
||||
name: "1st (left-hand) control rotor",
|
||||
type: "editableOption",
|
||||
value: CR_ROTORS,
|
||||
defaultIndex: 0
|
||||
},
|
||||
{
|
||||
name: "1st control rotor reversed",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "1st control rotor intial value",
|
||||
type: "option",
|
||||
value: LETTERS
|
||||
},
|
||||
{
|
||||
name: "2nd control rotor",
|
||||
type: "editableOption",
|
||||
value: CR_ROTORS,
|
||||
defaultIndex: 0
|
||||
},
|
||||
{
|
||||
name: "2nd control rotor reversed",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "2nd control rotor intial value",
|
||||
type: "option",
|
||||
value: LETTERS
|
||||
},
|
||||
{
|
||||
name: "3rd (middle) control rotor",
|
||||
type: "editableOption",
|
||||
value: CR_ROTORS,
|
||||
defaultIndex: 0
|
||||
},
|
||||
{
|
||||
name: "3rd control rotor reversed",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "3rd control rotor intial value",
|
||||
type: "option",
|
||||
value: LETTERS
|
||||
},
|
||||
{
|
||||
name: "4th control rotor",
|
||||
type: "editableOption",
|
||||
value: CR_ROTORS,
|
||||
defaultIndex: 0
|
||||
},
|
||||
{
|
||||
name: "4th control rotor reversed",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "4th control rotor intial value",
|
||||
type: "option",
|
||||
value: LETTERS
|
||||
},
|
||||
{
|
||||
name: "5th (right-hand) control rotor",
|
||||
type: "editableOption",
|
||||
value: CR_ROTORS,
|
||||
defaultIndex: 0
|
||||
},
|
||||
{
|
||||
name: "5th control rotor reversed",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "5th control rotor intial value",
|
||||
type: "option",
|
||||
value: LETTERS
|
||||
},
|
||||
{
|
||||
name: "1st (left-hand) index rotor",
|
||||
type: "editableOption",
|
||||
value: I_ROTORS,
|
||||
defaultIndex: 0
|
||||
},
|
||||
{
|
||||
name: "1st index rotor intial value",
|
||||
type: "option",
|
||||
value: NUMBERS
|
||||
},
|
||||
{
|
||||
name: "2nd index rotor",
|
||||
type: "editableOption",
|
||||
value: I_ROTORS,
|
||||
defaultIndex: 0
|
||||
},
|
||||
{
|
||||
name: "2nd index rotor intial value",
|
||||
type: "option",
|
||||
value: NUMBERS
|
||||
},
|
||||
{
|
||||
name: "3rd (middle) index rotor",
|
||||
type: "editableOption",
|
||||
value: I_ROTORS,
|
||||
defaultIndex: 0
|
||||
},
|
||||
{
|
||||
name: "3rd index rotor intial value",
|
||||
type: "option",
|
||||
value: NUMBERS
|
||||
},
|
||||
{
|
||||
name: "4th index rotor",
|
||||
type: "editableOption",
|
||||
value: I_ROTORS,
|
||||
defaultIndex: 0
|
||||
},
|
||||
{
|
||||
name: "4th index rotor intial value",
|
||||
type: "option",
|
||||
value: NUMBERS
|
||||
},
|
||||
{
|
||||
name: "5th (right-hand) index rotor",
|
||||
type: "editableOption",
|
||||
value: I_ROTORS,
|
||||
defaultIndex: 0
|
||||
},
|
||||
{
|
||||
name: "5th index rotor intial value",
|
||||
type: "option",
|
||||
value: NUMBERS
|
||||
},
|
||||
{
|
||||
name: "SIGABA mode",
|
||||
type: "option",
|
||||
value: ["Encrypt", "Decrypt"]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const sigabaSwitch = args[40];
|
||||
const cipherRotors = [];
|
||||
const controlRotors = [];
|
||||
const indexRotors = [];
|
||||
for (let i=0; i<5; i++) {
|
||||
const rotorWiring = args[i*3];
|
||||
cipherRotors.push(new CRRotor(rotorWiring, args[i*3+2], args[i*3+1]));
|
||||
}
|
||||
for (let i=5; i<10; i++) {
|
||||
const rotorWiring = args[i*3];
|
||||
controlRotors.push(new CRRotor(rotorWiring, args[i*3+2], args[i*3+1]));
|
||||
}
|
||||
for (let i=15; i<20; i++) {
|
||||
const rotorWiring = args[i*2];
|
||||
indexRotors.push(new IRotor(rotorWiring, args[i*2+1]));
|
||||
}
|
||||
const sigaba = new SigabaMachine(cipherRotors, controlRotors, indexRotors);
|
||||
let result;
|
||||
if (sigabaSwitch === "Encrypt") {
|
||||
result = sigaba.encrypt(input);
|
||||
} else if (sigabaSwitch === "Decrypt") {
|
||||
result = sigaba.decrypt(input);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
export default Sigaba;
|
||||
@@ -87,7 +87,7 @@ class ScatterChart extends Operation {
|
||||
const recordDelimiter = Utils.charRep(args[0]),
|
||||
fieldDelimiter = Utils.charRep(args[1]),
|
||||
columnHeadingsAreIncluded = args[2],
|
||||
fillColour = args[5],
|
||||
fillColour = Utils.escapeHtml(args[5]),
|
||||
radius = args[6],
|
||||
colourInInput = args[7],
|
||||
dimension = 500;
|
||||
|
||||
@@ -72,7 +72,10 @@ class SeriesChart extends Operation {
|
||||
fieldDelimiter = Utils.charRep(args[1]),
|
||||
xLabel = args[2],
|
||||
pipRadius = args[3],
|
||||
seriesColours = args[4].split(","),
|
||||
// Escape HTML from all colours to prevent reflected XSS. See https://github.com/gchq/CyberChef/issues/1265
|
||||
seriesColours = args[4].split(",").map((colour) => {
|
||||
return Utils.escapeHtml(colour);
|
||||
}),
|
||||
svgWidth = 500,
|
||||
interSeriesPadding = 20,
|
||||
xAxisHeight = 50,
|
||||
|
||||
78
src/core/operations/ToBase45.mjs
Normal file
78
src/core/operations/ToBase45.mjs
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @author Thomas Weißschuh [thomas@t-8ch.de]
|
||||
* @copyright Crown Copyright 2021
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import {ALPHABET, highlightToBase45, highlightFromBase45} from "../lib/Base45.mjs";
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
|
||||
/**
|
||||
* To Base45 operation
|
||||
*/
|
||||
class ToBase45 extends Operation {
|
||||
|
||||
/**
|
||||
* ToBase45 constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "To Base45";
|
||||
this.module = "Default";
|
||||
this.description = "Base45 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers. The high number base results in shorter strings than with the decimal or hexadecimal system. Base45 is optimized for usage with QR codes.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Alphabet",
|
||||
type: "string",
|
||||
value: ALPHABET
|
||||
}
|
||||
];
|
||||
|
||||
this.highlight = highlightToBase45;
|
||||
this.highlightReverse = highlightFromBase45;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
input = new Uint8Array(input);
|
||||
const alphabet = Utils.expandAlphRange(args[0]);
|
||||
if (!input) return "";
|
||||
|
||||
const res = [];
|
||||
|
||||
for (const pair of Utils.chunked(input, 2)) {
|
||||
let b = 0;
|
||||
for (const e of pair) {
|
||||
b *= 256;
|
||||
b += e;
|
||||
}
|
||||
|
||||
let chars = 0;
|
||||
do {
|
||||
res.push(alphabet[b % 45]);
|
||||
chars++;
|
||||
b = Math.floor(b / 45);
|
||||
} while (b > 0);
|
||||
|
||||
if (chars < 2) {
|
||||
res.push("0");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return res.join("");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ToBase45;
|
||||
@@ -1,6 +1,9 @@
|
||||
/**
|
||||
* Emulation of the Typex machine.
|
||||
*
|
||||
* Tested against a genuine Typex machine using a variety of inputs
|
||||
* and settings to confirm correctness.
|
||||
*
|
||||
* @author s2224834
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import NodeDish from "./NodeDish.mjs";
|
||||
import NodeRecipe from "./NodeRecipe.mjs";
|
||||
import OperationConfig from "../core/config/OperationConfig.json";
|
||||
import OperationConfig from "../core/config/OperationConfig.json" assert {type: "json"};
|
||||
import { sanitise, removeSubheadingsFromArray, sentenceToCamelCase } from "./apiUtils.mjs";
|
||||
import ExcludedOperationError from "../core/errors/ExcludedOperationError.mjs";
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* Export the main ESM module as CommonJS
|
||||
*
|
||||
*
|
||||
* @author d98762656 [d98762625@gmail.com]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
/* eslint no-global-assign: ["off"] */
|
||||
require = require("esm")(module);
|
||||
module.exports = require("./index.mjs");
|
||||
module.exports.File = require("./File.mjs");
|
||||
@@ -41,7 +41,7 @@ let code = `/**
|
||||
import NodeDish from "./NodeDish.mjs";
|
||||
import { _wrap, help, bake, _explainExcludedFunction } from "./api.mjs";
|
||||
import File from "./File.mjs";
|
||||
import { OperationError, DishError, ExcludedOperationError } from "../core/errors/index";
|
||||
import { OperationError, DishError, ExcludedOperationError } from "../core/errors/index.mjs";
|
||||
import {
|
||||
// import as core_ to avoid name clashes after wrap.
|
||||
`;
|
||||
@@ -52,7 +52,7 @@ includedOperations.forEach((op) => {
|
||||
});
|
||||
|
||||
code +=`
|
||||
} from "../core/operations/index";
|
||||
} from "../core/operations/index.mjs";
|
||||
|
||||
global.File = File;
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
const chef = require("./cjs.js");
|
||||
const repl = require("repl");
|
||||
import chef from "./index.mjs";
|
||||
import repl from "repl";
|
||||
|
||||
|
||||
/* eslint no-console: ["off"] */
|
||||
11
src/node/wrapper.js
Normal file
11
src/node/wrapper.js
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Export the main ESM module as CommonJS
|
||||
*
|
||||
*
|
||||
* @author d98762656 [d98762625@gmail.com]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
module.exports = (async () => await import("./index.mjs"))();
|
||||
module.exports.File = (async () => await import("./File.mjs"))();
|
||||
@@ -29,7 +29,7 @@
|
||||
<meta name="description" content="The Cyber Swiss Army Knife - a web app for encryption, encoding, compression and data analysis" />
|
||||
<meta name="keywords" content="base64, hex, decode, encode, encrypt, decrypt, compress, decompress, regex, regular expressions, hash, crypt, hexadecimal, user agent, url, certificate, x.509, parser, JSON, gzip, md5, sha1, aes, des, blowfish, xor" />
|
||||
|
||||
<link rel="icon" type="image/ico" href="<%- require('../static/images/favicon.ico').default %>" />
|
||||
<link rel="icon" type="image/ico" href="<%- require('../static/images/favicon.ico') %>" />
|
||||
|
||||
<script type="application/javascript">
|
||||
"use strict";
|
||||
@@ -197,7 +197,7 @@
|
||||
</button>
|
||||
|
||||
<button type="button" class="mx-2 btn btn-lg btn-success btn-raised btn-block" id="bake">
|
||||
<img aria-hidden="true" src="<%- require('../static/images/cook_male-32x32.png').default %>" alt="Chef Icon"/>
|
||||
<img aria-hidden="true" src="<%- require('../static/images/cook_male-32x32.png') %>" alt="Chef Icon"/>
|
||||
<span>Bake!</span>
|
||||
</button>
|
||||
|
||||
@@ -271,7 +271,7 @@
|
||||
<div class="file-overlay" id="file-overlay"></div>
|
||||
<div style="position: relative; height: 100%;">
|
||||
<div class="io-card card">
|
||||
<img aria-hidden="true" src="<%- require('../static/images/file-128x128.png').default %>" alt="File icon" id="input-file-thumbnail"/>
|
||||
<img aria-hidden="true" src="<%- require('../static/images/file-128x128.png') %>" alt="File icon" id="input-file-thumbnail"/>
|
||||
<div class="card-body">
|
||||
<button type="button" class="close" id="input-file-close">×</button>
|
||||
Name: <span id="input-file-name"></span><br>
|
||||
@@ -346,12 +346,12 @@
|
||||
<div id="output-highlighter" class="no-select"></div>
|
||||
<div id="output-html"></div>
|
||||
<textarea id="output-text" readonly="readonly" spellcheck="false"></textarea>
|
||||
<img id="show-file-overlay" aria-hidden="true" src="<%- require('../static/images/file-32x32.png').default %>" alt="Show file overlay" title="Show file overlay"/>
|
||||
<img id="show-file-overlay" aria-hidden="true" src="<%- require('../static/images/file-32x32.png') %>" alt="Show file overlay" title="Show file overlay"/>
|
||||
<div id="output-file">
|
||||
<div class="file-overlay"></div>
|
||||
<div style="position: relative; height: 100%;">
|
||||
<div class="io-card card">
|
||||
<img aria-hidden="true" src="<%- require('../static/images/file-128x128.png').default %>" alt="File icon"/>
|
||||
<img aria-hidden="true" src="<%- require('../static/images/file-128x128.png') %>" alt="File icon"/>
|
||||
<div class="card-body">
|
||||
Size: <span id="output-file-size"></span><br>
|
||||
<button id="output-file-download" type="button" class="btn btn-primary btn-outline">Download</button>
|
||||
@@ -626,7 +626,7 @@
|
||||
<h5 class="modal-title">CyberChef - The Cyber Swiss Army Knife</h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<img aria-hidden="true" class="about-img-left" src="<%- require('../static/images/cyberchef-128x128.png').default %>" alt="CyberChef Logo"/>
|
||||
<img aria-hidden="true" class="about-img-left" src="<%- require('../static/images/cyberchef-128x128.png') %>" alt="CyberChef Logo"/>
|
||||
<p class="subtext">
|
||||
Version <%= htmlWebpackPlugin.options.version %><br>
|
||||
Compile time: <%= htmlWebpackPlugin.options.compileTime %>
|
||||
@@ -686,7 +686,7 @@
|
||||
<div class="collapse" id="faq-load-files">
|
||||
<p>Yes! Just drag your file over the input box and drop it.</p>
|
||||
<p>CyberChef can handle files up to around 2GB (depending on your browser), however some of the operations may take a very long time to run over this much data.</p>
|
||||
<p>If the output is larger than a certain threshold (default 1MiB), it will be presented to you as a file available for download. Slices of the file can be viewed in the output if you need to inspect them.</p>
|
||||
<p>If the output is larger than a certain threshold (default <a href="#recipe=Multiply('Line%20feed')Convert_data_units('Bytes%20(B)','Mebibytes%20(MiB)')&input=MTAyNAoxMDI0">1MiB</a>), it will be presented to you as a file available for download. Slices of the file can be viewed in the output if you need to inspect them.</p>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
@@ -749,7 +749,7 @@
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
<a href="https://github.com/gchq/CyberChef">
|
||||
<img aria-hidden="true" style="position: absolute; top: 0; right: 0; border: 0;" src="<%- require('../static/images/fork_me.png').default %>" alt="Fork me on GitHub">
|
||||
<img aria-hidden="true" style="position: absolute; top: 0; right: 0; border: 0;" src="<%- require('../static/images/fork_me.png') %>" alt="Fork me on GitHub">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,8 +17,8 @@ import * as CanvasComponents from "../core/lib/CanvasComponents.mjs";
|
||||
|
||||
// CyberChef
|
||||
import App from "./App.mjs";
|
||||
import Categories from "../core/config/Categories.json";
|
||||
import OperationConfig from "../core/config/OperationConfig.json";
|
||||
import Categories from "../core/config/Categories.json" assert {type: "json"};
|
||||
import OperationConfig from "../core/config/OperationConfig.json" assert {type: "json"};
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import sm from "sitemap";
|
||||
import OperationConfig from "../../core/config/OperationConfig.json";
|
||||
import OperationConfig from "../../core/config/OperationConfig.json" assert {type: "json"};
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -303,7 +303,7 @@
|
||||
|
||||
#stale-indicator {
|
||||
opacity: 1;
|
||||
visibility: visibile;
|
||||
visibility: visible;
|
||||
transition: margin 0s, opacity 0.3s;
|
||||
margin-left: 5px;
|
||||
cursor: help;
|
||||
@@ -316,7 +316,7 @@
|
||||
|
||||
#magic {
|
||||
opacity: 1;
|
||||
visibility: visibile;
|
||||
visibility: visible;
|
||||
transition: margin 0s 0.3s, opacity 0.3s 0.3s, visibility 0.3s 0.3s;
|
||||
margin-left: 5px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
@@ -71,7 +71,7 @@ module.exports = {
|
||||
.moveToElement(toHex, 10, 10)
|
||||
.useCss()
|
||||
.waitForElementVisible(".popover-body", 1000)
|
||||
.doubleClick();
|
||||
.doubleClick("xpath", toHex);
|
||||
|
||||
// Confirm that it has been added to the recipe
|
||||
browser
|
||||
@@ -90,7 +90,7 @@ module.exports = {
|
||||
browser
|
||||
.useCss()
|
||||
.waitForElementNotVisible("#stale-indicator", 1000)
|
||||
.expect.element("#output-text").to.have.value.that.equals("44 6f 6e 27 74 20 50 61 6e 69 63 2e");
|
||||
.expect.element("#output-text").to.have.property("value").that.equals("44 6f 6e 27 74 20 50 61 6e 69 63 2e");
|
||||
|
||||
// Clear recipe
|
||||
browser
|
||||
@@ -202,11 +202,11 @@ module.exports = {
|
||||
browser
|
||||
.getLocationInView(genUUID)
|
||||
.moveToElement(genUUID, 10, 10)
|
||||
.doubleClick()
|
||||
.doubleClick("xpath", genUUID)
|
||||
.useCss()
|
||||
.waitForElementVisible(".operation .op-title", 1000)
|
||||
.waitForElementNotVisible("#stale-indicator", 1000)
|
||||
.expect.element("#output-text").to.have.value.which.matches(/[\da-f-]{36}/);
|
||||
.expect.element("#output-text").to.have.property("value").which.matches(/[\da-f-]{36}/);
|
||||
|
||||
browser.click("#clr-recipe");
|
||||
},
|
||||
|
||||
@@ -393,13 +393,13 @@ function testOp(browser, opName, input, output, args=[]) {
|
||||
.click("#clr-recipe")
|
||||
.click("#clr-io")
|
||||
.waitForElementNotPresent("#rec-list li.operation")
|
||||
.expect.element("#input-text").to.have.value.that.equals("");
|
||||
.expect.element("#input-text").to.have.property("value").that.equals("");
|
||||
|
||||
browser
|
||||
.urlHash("recipe=" + recipeConfig)
|
||||
.setValue("#input-text", input)
|
||||
.waitForElementPresent("#rec-list li.operation")
|
||||
.expect.element("#input-text").to.have.value.that.equals(input);
|
||||
.expect.element("#input-text").to.have.property("value").that.equals(input);
|
||||
|
||||
browser
|
||||
.waitForElementVisible("#stale-indicator", 5000)
|
||||
@@ -410,8 +410,8 @@ function testOp(browser, opName, input, output, args=[]) {
|
||||
.waitForElementNotVisible("#output-loader", 5000);
|
||||
|
||||
if (typeof output === "string") {
|
||||
browser.expect.element("#output-text").to.have.value.that.equals(output);
|
||||
browser.expect.element("#output-text").to.have.property("value").that.equals(output);
|
||||
} else if (output instanceof RegExp) {
|
||||
browser.expect.element("#output-text").to.have.value.that.matches(output);
|
||||
browser.expect.element("#output-text").to.have.property("value").that.matches(output);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,24 +6,27 @@
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
const chef = require("cyberchef");
|
||||
const assert = require("assert");
|
||||
|
||||
const d = chef.bake("Testing, 1 2 3", [
|
||||
chef.toHex,
|
||||
chef.reverse,
|
||||
{
|
||||
op: chef.unique,
|
||||
args: {
|
||||
delimiter: "Space",
|
||||
}
|
||||
},
|
||||
{
|
||||
op: chef.multiply,
|
||||
args: {
|
||||
delimiter: "Space",
|
||||
}
|
||||
}
|
||||
]);
|
||||
require("cyberchef").then(chef => {
|
||||
|
||||
assert.equal(d.value, "630957449041920");
|
||||
const d = chef.bake("Testing, 1 2 3", [
|
||||
chef.toHex,
|
||||
chef.reverse,
|
||||
{
|
||||
op: chef.unique,
|
||||
args: {
|
||||
delimiter: "Space",
|
||||
}
|
||||
},
|
||||
{
|
||||
op: chef.multiply,
|
||||
args: {
|
||||
delimiter: "Space",
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
assert.equal(d.value, "630957449041920");
|
||||
|
||||
});
|
||||
|
||||
@@ -7,8 +7,28 @@
|
||||
*/
|
||||
import assert from "assert";
|
||||
import chef from "cyberchef";
|
||||
import { bake, toHex, reverse, unique, multiply } from "cyberchef";
|
||||
|
||||
const d = chef.bake("Testing, 1 2 3", [
|
||||
const a = bake("Testing, 1 2 3", [
|
||||
toHex,
|
||||
reverse,
|
||||
{
|
||||
op: unique,
|
||||
args: {
|
||||
delimiter: "Space",
|
||||
}
|
||||
},
|
||||
{
|
||||
op: multiply,
|
||||
args: {
|
||||
delimiter: "Space",
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
assert.equal(a.value, "630957449041920");
|
||||
|
||||
const b = chef.bake("Testing, 1 2 3", [
|
||||
chef.toHex,
|
||||
chef.reverse,
|
||||
{
|
||||
@@ -25,4 +45,4 @@ const d = chef.bake("Testing, 1 2 3", [
|
||||
}
|
||||
]);
|
||||
|
||||
assert.equal(d.value, "630957449041920");
|
||||
assert.equal(b.value, "630957449041920");
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* Tests to ensure that a consuming app can use named imports from deep import patch
|
||||
*
|
||||
* @author d98762625 [d98762625@gmail.com]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import assert from "assert";
|
||||
import { bake, toHex, reverse, unique, multiply } from "cyberchef/src/node/index.mjs";
|
||||
|
||||
const d = bake("Testing, 1 2 3", [
|
||||
toHex,
|
||||
reverse,
|
||||
{
|
||||
op: unique,
|
||||
args: {
|
||||
delimiter: "Space",
|
||||
}
|
||||
},
|
||||
{
|
||||
op: multiply,
|
||||
args: {
|
||||
delimiter: "Space",
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
assert.equal(d.value, "630957449041920");
|
||||
@@ -1,6 +1,6 @@
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
import Categories from "../../../src/core/config/Categories.json";
|
||||
import OperationConfig from "../../../src/core/config/OperationConfig.json";
|
||||
import Categories from "../../../src/core/config/Categories.json" assert {type: "json"};
|
||||
import OperationConfig from "../../../src/core/config/OperationConfig.json" assert {type: "json"};
|
||||
import it from "../assertionHandler.mjs";
|
||||
import assert from "assert";
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import {
|
||||
CSSMinify,
|
||||
toBase64,
|
||||
toHex
|
||||
} from "../../../src/node/index";
|
||||
} from "../../../src/node/index.mjs";
|
||||
import chef from "../../../src/node/index.mjs";
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
import File from "../../../src/node/File.mjs";
|
||||
@@ -685,8 +685,8 @@ Arguments:
|
||||
it("Parse user agent", () => {
|
||||
const result = chef.parseUserAgent("Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0 ");
|
||||
const expected = `Browser
|
||||
Name: Mozilla
|
||||
Version: 5.0
|
||||
Name: Firefox
|
||||
Version: 47.0
|
||||
Device
|
||||
Model: unknown
|
||||
Type: unknown
|
||||
|
||||
@@ -20,6 +20,7 @@ import TestRegister from "../lib/TestRegister.mjs";
|
||||
import "./tests/BCD.mjs";
|
||||
import "./tests/BSON.mjs";
|
||||
import "./tests/BaconCipher.mjs";
|
||||
import "./tests/Base45.mjs";
|
||||
import "./tests/Base58.mjs";
|
||||
import "./tests/Base64.mjs";
|
||||
import "./tests/Base62.mjs";
|
||||
@@ -102,6 +103,14 @@ import "./tests/Colossus.mjs";
|
||||
import "./tests/ParseObjectIDTimestamp.mjs";
|
||||
import "./tests/Unicode.mjs";
|
||||
import "./tests/RSA.mjs";
|
||||
import "./tests/CBOREncode.mjs";
|
||||
import "./tests/CBORDecode.mjs";
|
||||
import "./tests/JA3Fingerprint.mjs";
|
||||
import "./tests/JA3SFingerprint.mjs";
|
||||
import "./tests/HASSH.mjs";
|
||||
import "./tests/GetAllCasings.mjs";
|
||||
import "./tests/SIGABA.mjs";
|
||||
|
||||
|
||||
// Cannot test operations that use the File type yet
|
||||
// import "./tests/SplitColourChannels.mjs";
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import TestRegister from "../../lib/TestRegister";
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
* @copyright Karsten Silkenbäumer 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister";
|
||||
import { BACON_ALPHABETS, BACON_TRANSLATIONS } from "../../../src/core/lib/Bacon";
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
import { BACON_ALPHABETS, BACON_TRANSLATIONS } from "../../../src/core/lib/Bacon.mjs";
|
||||
|
||||
const alphabets = Object.keys(BACON_ALPHABETS);
|
||||
const translations = BACON_TRANSLATIONS;
|
||||
|
||||
103
tests/operations/tests/Base45.mjs
Normal file
103
tests/operations/tests/Base45.mjs
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Base45 tests.
|
||||
*
|
||||
* @author Thomas Weißschuh [thomas@t-8ch.de]
|
||||
*
|
||||
* @copyright Crown Copyright 2021
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
const defaultB45Alph = "0-9A-Z $%*+\\-./:";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "To Base45: nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base45",
|
||||
args: [defaultB45Alph],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Base45: Spec encoding example 1",
|
||||
input: "AB",
|
||||
expectedOutput: "BB8",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base45",
|
||||
args: [defaultB45Alph],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Base45: Spec encoding example 2",
|
||||
input: "Hello!!",
|
||||
expectedOutput: "%69 VD92EX0",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base45",
|
||||
args: [defaultB45Alph],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Base45: Spec encoding example 3",
|
||||
input: "base-45",
|
||||
expectedOutput: "UJCLQE7W581",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base45",
|
||||
args: [defaultB45Alph],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base45: nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Base45",
|
||||
args: [defaultB45Alph],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base45: Spec decoding example 1",
|
||||
input: "QED8WEX0",
|
||||
expectedOutput: "ietf!",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Base45",
|
||||
args: [defaultB45Alph],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base45: Invalid character",
|
||||
input: "!",
|
||||
expectedOutput: "Character not in alphabet: '!'",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Base45",
|
||||
args: [defaultB45Alph],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base45: Invalid triplet value",
|
||||
input: "ZZZ",
|
||||
expectedOutput: "Triplet too large: 'ZZZ'",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Base45",
|
||||
args: [defaultB45Alph],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
144
tests/operations/tests/CBORDecode.mjs
Normal file
144
tests/operations/tests/CBORDecode.mjs
Normal file
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* CBOR Decode Tests
|
||||
*
|
||||
* @author Danh4 [dan.h4@ncsc.gov.uk]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "CBOR Decode: Can decode integer",
|
||||
input: "0f",
|
||||
expectedOutput: "15",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "CBOR Decode",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "CBOR Decode: Can decode decimal",
|
||||
input: "f9 3e 00",
|
||||
expectedOutput: "1.5",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "CBOR Decode",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "From Hex: Can decode text",
|
||||
input: "64 54 65 78 74",
|
||||
expectedOutput: "\"Text\"",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "CBOR Decode",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "From Hex: Can decode boolean true",
|
||||
input: "f5",
|
||||
expectedOutput: "true",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "CBOR Decode",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "From Hex: Can decode boolean false",
|
||||
input: "f4",
|
||||
expectedOutput: "false",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "CBOR Decode",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "From Hex: Can decode map",
|
||||
input: "a3 61 61 01 61 62 02 61 63 03",
|
||||
expectedOutput: JSON.stringify({a: 1, b: 2, c: 3}),
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "CBOR Decode",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "From Hex: Can decode list",
|
||||
input: "83 00 01 02",
|
||||
expectedOutput: "[0,1,2]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "CBOR Decode",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "From Hex: Can round trip with encode",
|
||||
input: JSON.stringify({a: 1, b: false, c: [1, 2, 3]}),
|
||||
expectedOutput: JSON.stringify({a: 1, b: false, c: [1, 2, 3]}),
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "CBOR Encode",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "CBOR Decode",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
117
tests/operations/tests/CBOREncode.mjs
Normal file
117
tests/operations/tests/CBOREncode.mjs
Normal file
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* CBOR Encode Tests.
|
||||
*
|
||||
* @author Danh4 [dan.h4@ncsc.gov.uk]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "CBOR Encode: Can encode integer",
|
||||
input: "15",
|
||||
expectedOutput: "0f",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "CBOR Encode",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "To Hex",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "CBOR Decode: Can encode decimal",
|
||||
input: "1.5",
|
||||
expectedOutput: "f9 3e 00",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "CBOR Encode",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "To Hex",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "CBOR Encode: Can encode text",
|
||||
input: "\"Text\"",
|
||||
expectedOutput: "64 54 65 78 74",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "CBOR Encode",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "To Hex",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "CBOR Encode: Can encode boolean true",
|
||||
input: "true",
|
||||
expectedOutput: "f5",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "CBOR Encode",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "To Hex",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "CBOR Encode: Can encode boolean false",
|
||||
input: "false",
|
||||
expectedOutput: "f4",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "CBOR Encode",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "To Hex",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "CBOR Encode: Can encode map",
|
||||
input: JSON.stringify({a: 1, b: 2, c: 3}),
|
||||
expectedOutput: "a3 61 61 01 61 62 02 61 63 03",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "CBOR Encode",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "To Hex",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "CBOR Encode: Can encode list",
|
||||
input: "[0,1,2]",
|
||||
expectedOutput: "83 00 01 02",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "CBOR Encode",
|
||||
args: []
|
||||
},
|
||||
{
|
||||
op: "To Hex",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
@@ -73,7 +73,8 @@ The following algorithms will be used based on the size of the key:
|
||||
"args": [
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""},
|
||||
"CBC", "Raw", "Hex"
|
||||
"CBC", "Raw", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -88,7 +89,8 @@ The following algorithms will be used based on the size of the key:
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||
"CBC", "Raw", "Hex"
|
||||
"CBC", "Raw", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -103,7 +105,8 @@ The following algorithms will be used based on the size of the key:
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||
"CTR", "Raw", "Hex"
|
||||
"CTR", "Raw", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -118,7 +121,8 @@ The following algorithms will be used based on the size of the key:
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
"CBC", "Raw", "Hex"
|
||||
"CBC", "Raw", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -133,7 +137,8 @@ The following algorithms will be used based on the size of the key:
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
"CFB", "Raw", "Hex"
|
||||
"CFB", "Raw", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -148,7 +153,8 @@ The following algorithms will be used based on the size of the key:
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
"OFB", "Raw", "Hex"
|
||||
"OFB", "Raw", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -163,7 +169,8 @@ The following algorithms will be used based on the size of the key:
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
"CTR", "Raw", "Hex"
|
||||
"CTR", "Raw", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -178,7 +185,8 @@ The following algorithms will be used based on the size of the key:
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": ""},
|
||||
"ECB", "Raw", "Hex"
|
||||
"ECB", "Raw", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -195,7 +203,8 @@ Tag: 16a3e732a605cc9ca29108f742ca0743`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": ""},
|
||||
"GCM", "Raw", "Hex", ""
|
||||
"GCM", "Raw", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -212,7 +221,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": "ffeeddccbbaa99887766554433221100"},
|
||||
"GCM", "Raw", "Hex", "additional data"
|
||||
"GCM", "Raw", "Hex",
|
||||
{"option": "UTF8", "string": "additional data"}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -227,7 +237,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CBC", "Hex", "Hex"
|
||||
"CBC", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -242,7 +253,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CFB", "Hex", "Hex"
|
||||
"CFB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -257,7 +269,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"OFB", "Hex", "Hex"
|
||||
"OFB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -272,7 +285,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CTR", "Hex", "Hex"
|
||||
"CTR", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -289,7 +303,8 @@ Tag: 70fad2ca19412c20f40fd06918736e56`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"GCM", "Hex", "Hex", ""
|
||||
"GCM", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -306,7 +321,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"GCM", "Hex", "Hex", "additional data"
|
||||
"GCM", "Hex", "Hex",
|
||||
{"option": "UTF8", "string": "additional data"}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -321,7 +337,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"ECB", "Hex", "Hex"
|
||||
"ECB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -336,7 +353,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CBC", "Hex", "Hex"
|
||||
"CBC", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -351,7 +369,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CFB", "Hex", "Hex"
|
||||
"CFB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -366,7 +385,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"OFB", "Hex", "Hex"
|
||||
"OFB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -381,7 +401,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CTR", "Hex", "Hex"
|
||||
"CTR", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -398,7 +419,8 @@ Tag: 86db597d5302595223cadbd990f1309b`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"GCM", "Hex", "Hex", ""
|
||||
"GCM", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -415,7 +437,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"GCM", "Hex", "Hex", "additional data"
|
||||
"GCM", "Hex", "Hex",
|
||||
{"option": "UTF8", "string": "additional data"}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -430,7 +453,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"ECB", "Hex", "Hex"
|
||||
"ECB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -445,7 +469,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CBC", "Hex", "Hex"
|
||||
"CBC", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -460,7 +485,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CFB", "Hex", "Hex"
|
||||
"CFB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -475,7 +501,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"OFB", "Hex", "Hex"
|
||||
"OFB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -490,7 +517,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CTR", "Hex", "Hex"
|
||||
"CTR", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -507,7 +535,8 @@ Tag: 821b1e5f32dad052e502775a523d957a`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"GCM", "Hex", "Hex", ""
|
||||
"GCM", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -524,7 +553,8 @@ Tag: a8f04c4d93bbef82bef61a103371aef9`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"GCM", "Hex", "Hex", "additional data"
|
||||
"GCM", "Hex", "Hex",
|
||||
{"option": "UTF8", "string": "additional data"}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -539,7 +569,8 @@ Tag: a8f04c4d93bbef82bef61a103371aef9`,
|
||||
"args": [
|
||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"ECB", "Hex", "Hex"
|
||||
"ECB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -748,6 +779,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""},
|
||||
"CBC", "Hex", "Raw",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -764,6 +796,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||
"CBC", "Hex", "Raw",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -780,6 +813,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||
"CTR", "Hex", "Raw",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -796,6 +830,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
"CBC", "Hex", "Raw",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -812,6 +847,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
"CFB", "Hex", "Raw",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -828,6 +864,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
"OFB", "Hex", "Raw",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -844,6 +881,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
"CTR", "Hex", "Raw",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -860,6 +898,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "00112233445566778899aabbccddeeff"},
|
||||
{"option": "Hex", "string": ""},
|
||||
"ECB", "Hex", "Raw",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -877,7 +916,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": ""},
|
||||
"GCM", "Hex", "Raw",
|
||||
{"option": "Hex", "string": "16a3e732a605cc9ca29108f742ca0743"},
|
||||
""
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -894,7 +933,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "ffeeddccbbaa99887766554433221100"},
|
||||
"GCM", "Hex", "Raw",
|
||||
{"option": "Hex", "string": "3b5378917f67b0aade9891fc6c291646"},
|
||||
"additional data"
|
||||
{"option": "UTF8", "string": "additional data"}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -910,6 +949,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CBC", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -926,6 +966,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CFB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -942,6 +983,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"OFB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -958,6 +1000,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CTR", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -975,7 +1018,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"GCM", "Hex", "Hex",
|
||||
{"option": "Hex", "string": "70fad2ca19412c20f40fd06918736e56"},
|
||||
""
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -992,7 +1035,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"GCM", "Hex", "Hex",
|
||||
{"option": "Hex", "string": "61cc4b70809452b0b3e38f913fa0a109"},
|
||||
"additional data"
|
||||
{"option": "UTF8", "string": "additional data"}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -1008,6 +1051,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"ECB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -1024,6 +1068,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CBC", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -1040,6 +1085,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CFB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -1056,6 +1102,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"OFB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -1072,6 +1119,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CTR", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -1089,7 +1137,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"GCM", "Hex", "Hex",
|
||||
{"option": "Hex", "string": "86db597d5302595223cadbd990f1309b"},
|
||||
""
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -1106,7 +1154,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"GCM", "Hex", "Hex",
|
||||
{"option": "Hex", "string": "aeedf3e6ca4201577c0cf3e9ce58159d"},
|
||||
"additional data"
|
||||
{"option": "UTF8", "string": "additional data"}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -1122,6 +1170,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"ECB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -1138,6 +1187,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CBC", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -1154,6 +1204,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CFB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -1170,6 +1221,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"OFB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -1186,6 +1238,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"CTR", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
@@ -1203,7 +1256,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"GCM", "Hex", "Hex",
|
||||
{"option": "Hex", "string": "821b1e5f32dad052e502775a523d957a"},
|
||||
""
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -1220,7 +1273,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"GCM", "Hex", "Hex",
|
||||
{"option": "Hex", "string": "a8f04c4d93bbef82bef61a103371aef9"},
|
||||
"additional data"
|
||||
{"option": "UTF8", "string": "additional data"}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -1236,6 +1289,7 @@ The following algorithms will be used based on the size of the key:
|
||||
{"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"},
|
||||
{"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"},
|
||||
"ECB", "Hex", "Hex",
|
||||
{"option": "Hex", "string": ""},
|
||||
{"option": "Hex", "string": ""}
|
||||
]
|
||||
}
|
||||
|
||||
44
tests/operations/tests/GetAllCasings.mjs
Normal file
44
tests/operations/tests/GetAllCasings.mjs
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* GetAllCasings tests.
|
||||
*
|
||||
* @author n1073645 [n1073645@gmail.com]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "All casings of test",
|
||||
input: "test",
|
||||
expectedOutput: "test\nTest\ntEst\nTEst\nteSt\nTeSt\ntESt\nTESt\ntesT\nTesT\ntEsT\nTEsT\nteST\nTeST\ntEST\nTEST\n",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Get All Casings",
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "All casings of t",
|
||||
input: "t",
|
||||
expectedOutput: "t\nT\n",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Get All Casings",
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "All casings of null",
|
||||
input: "",
|
||||
expectedOutput: "\n",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Get All Casings",
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
33
tests/operations/tests/HASSH.mjs
Normal file
33
tests/operations/tests/HASSH.mjs
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* HASSH tests.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2021
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "HASSH Client Fingerprint",
|
||||
input: "000003140814c639665f5425dcb80bf9f0a048380a410000007e6469666669652d68656c6c6d616e2d67726f75702d65786368616e67652d7368613235362c6469666669652d68656c6c6d616e2d67726f75702d65786368616e67652d736861312c6469666669652d68656c6c6d616e2d67726f757031342d736861312c6469666669652d68656c6c6d616e2d67726f7570312d736861310000000f7373682d7273612c7373682d6473730000009d6165733132382d6374722c6165733139322d6374722c6165733235362d6374722c617263666f75723235362c617263666f75723132382c6165733132382d6362632c336465732d6362632c626c6f77666973682d6362632c636173743132382d6362632c6165733139322d6362632c6165733235362d6362632c617263666f75722c72696a6e6461656c2d636263406c797361746f722e6c69752e73650000009d6165733132382d6374722c6165733139322d6374722c6165733235362d6374722c617263666f75723235362c617263666f75723132382c6165733132382d6362632c336465732d6362632c626c6f77666973682d6362632c636173743132382d6362632c6165733139322d6362632c6165733235362d6362632c617263666f75722c72696a6e6461656c2d636263406c797361746f722e6c69752e736500000069686d61632d6d64352c686d61632d736861312c756d61632d3634406f70656e7373682e636f6d2c686d61632d726970656d643136302c686d61632d726970656d64313630406f70656e7373682e636f6d2c686d61632d736861312d39362c686d61632d6d64352d393600000069686d61632d6d64352c686d61632d736861312c756d61632d3634406f70656e7373682e636f6d2c686d61632d726970656d643136302c686d61632d726970656d64313630406f70656e7373682e636f6d2c686d61632d736861312d39362c686d61632d6d64352d39360000001a6e6f6e652c7a6c6962406f70656e7373682e636f6d2c7a6c69620000001a6e6f6e652c7a6c6962406f70656e7373682e636f6d2c7a6c6962000000000000000000000000000000000000000000",
|
||||
expectedOutput: "21b457a327ce7a2d4fce5ef2c42400bd",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HASSH Client Fingerprint",
|
||||
"args": ["Hex", "Hash digest"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "HASSH Server Fingerprint",
|
||||
input: "0000027c0b142c7bb93a1da21c9e54f5862e60a5597c000000596469666669652d68656c6c6d616e2d67726f75702d65786368616e67652d736861312c6469666669652d68656c6c6d616e2d67726f757031342d736861312c6469666669652d68656c6c6d616e2d67726f7570312d736861310000000f7373682d7273612c7373682d647373000000876165733132382d6362632c336465732d6362632c626c6f77666973682d6362632c636173743132382d6362632c617263666f75722c6165733139322d6362632c6165733235362d6362632c72696a6e6461656c2d636263406c797361746f722e6c69752e73652c6165733132382d6374722c6165733139322d6374722c6165733235362d637472000000876165733132382d6362632c336465732d6362632c626c6f77666973682d6362632c636173743132382d6362632c617263666f75722c6165733139322d6362632c6165733235362d6362632c72696a6e6461656c2d636263406c797361746f722e6c69752e73652c6165733132382d6374722c6165733139322d6374722c6165733235362d63747200000055686d61632d6d64352c686d61632d736861312c686d61632d726970656d643136302c686d61632d726970656d64313630406f70656e7373682e636f6d2c686d61632d736861312d39362c686d61632d6d64352d393600000055686d61632d6d64352c686d61632d736861312c686d61632d726970656d643136302c686d61632d726970656d64313630406f70656e7373682e636f6d2c686d61632d736861312d39362c686d61632d6d64352d3936000000096e6f6e652c7a6c6962000000096e6f6e652c7a6c6962000000000000000000000000000000000000000000000000",
|
||||
expectedOutput: "f430cd6761697a6a658ee1d45ed22e49",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HASSH Server Fingerprint",
|
||||
"args": ["Hex", "Hash digest"]
|
||||
}
|
||||
],
|
||||
}
|
||||
]);
|
||||
55
tests/operations/tests/JA3Fingerprint.mjs
Normal file
55
tests/operations/tests/JA3Fingerprint.mjs
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* JA3Fingerprint tests.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2021
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "JA3 Fingerprint: TLS 1.0",
|
||||
input: "16030100a4010000a00301543dd2dd48f517ca9a93b1e599f019fdece704a23e86c1dcac588427abbaddf200005cc014c00a0039003800880087c00fc00500350084c012c00800160013c00dc003000ac013c00900330032009a009900450044c00ec004002f009600410007c011c007c00cc002000500040015001200090014001100080006000300ff0100001b000b000403000102000a000600040018001700230000000f000101",
|
||||
expectedOutput: "503053a0c5b2bd9b9334bf7f3d3b8852",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "JA3 Fingerprint",
|
||||
"args": ["Hex", "Hash digest"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JA3 Fingerprint: TLS 1.1",
|
||||
input: "16030100a4010000a00302543dd2ed907e47d0086f34bee2c52dd6ccd8de63ba9387f5e810b09d9d49b38000005cc014c00a0039003800880087c00fc00500350084c012c00800160013c00dc003000ac013c00900330032009a009900450044c00ec004002f009600410007c011c007c00cc002000500040015001200090014001100080006000300ff0100001b000b000403000102000a000600040018001700230000000f000101",
|
||||
expectedOutput: "a314eb64cee6cb832aaaa372c8295bab",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "JA3 Fingerprint",
|
||||
"args": ["Hex", "Hash digest"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JA3 Fingerprint: TLS 1.2",
|
||||
input: "1603010102010000fe0303543dd3283283692d85f9416b5ccc65d2aafca45c6530b3c6eafbf6d371b6a015000094c030c02cc028c024c014c00a00a3009f006b006a0039003800880087c032c02ec02ac026c00fc005009d003d00350084c012c00800160013c00dc003000ac02fc02bc027c023c013c00900a2009e0067004000330032009a009900450044c031c02dc029c025c00ec004009c003c002f009600410007c011c007c00cc002000500040015001200090014001100080006000300ff01000041000b000403000102000a000600040018001700230000000d002200200601060206030501050205030401040204030301030203030201020202030101000f000101",
|
||||
expectedOutput: "c1a36e1a870786cc75edddc0009eaf3a",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "JA3 Fingerprint",
|
||||
"args": ["Hex", "Hash digest"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JA3 Fingerprint: TLS 1.3",
|
||||
input: "1603010200010001fc03034355d402c132771a9386b6e9994ae37069e0621af504c26673b1343843c21d8d0000264a4a130113021303c02bc02fc02cc030cca9cca8cc14cc13c013c014009c009d002f0035000a010001addada0000ff01000100000000180016000013626c6f672e636c6f7564666c6172652e636f6d0017000000230000000d00140012040308040401050308050501080606010201000500050100000000001200000010000e000c02683208687474702f312e3175500000000b000201000028002b00295a5a000100001d0020cf78b9167af054b922a96752b43973107b2a57766357dd288b2b42ab5df30e08002d00020101002b000b0acaca7f12030303020301000a000a00085a5a001d001700180a0a000100001500e4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
expectedOutput: "4826a90ec2daf4f7b4b64cc1c8bd343b",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "JA3 Fingerprint",
|
||||
"args": ["Hex", "Hash digest"]
|
||||
}
|
||||
],
|
||||
},
|
||||
]);
|
||||
57
tests/operations/tests/JA3SFingerprint.mjs
Normal file
57
tests/operations/tests/JA3SFingerprint.mjs
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* JA3SFingerprint tests.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2021
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "JA3S Fingerprint: TLS 1.0",
|
||||
input: "160301003d020000390301543dd2ddedbfe33895bd6bc676a3fa6b9fe5773a6e04d5476d1af3bcbc1dcbbb00c011000011ff01000100000b00040300010200230000",
|
||||
expectedOutput: "bed95e1b525d2f41db3a6d68fac5b566",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "JA3S Fingerprint",
|
||||
"args": ["Hex", "Hash digest"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JA3S Fingerprint: TLS 1.1",
|
||||
input: "160302003d020000390302543dd2ed88131999a0120d36c14a4139671d75aae3d7d7779081d3cf7dd7725a00c013000011ff01000100000b00040300010200230000",
|
||||
expectedOutput: "130fac2dc19b142500acb0abc63b6379",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "JA3S Fingerprint",
|
||||
"args": ["Hex", "Hash digest"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JA3S Fingerprint: TLS 1.2",
|
||||
input: "160303003d020000390303543dd328b38b445686739d58fab733fa23838f575e0e5ad9a1b9baace6cc3b4100c02f000011ff01000100000b00040300010200230000",
|
||||
expectedOutput: "ccc514751b175866924439bdbb5bba34",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "JA3S Fingerprint",
|
||||
"args": ["Hex", "Hash digest"]
|
||||
}
|
||||
],
|
||||
},
|
||||
// This Server Hello was based on draft 18 of the TLS1.3 spec which does not include a Session ID field, leading it to fail.
|
||||
// The published version of TLS1.3 does require a legacy Session ID field (even if it is empty).
|
||||
// {
|
||||
// name: "JA3S Fingerprint: TLS 1.3",
|
||||
// input: "16030100520200004e7f123ef1609fd3f4fa8668aac5822d500fb0639b22671d0fb7258597355795511bf61301002800280024001d0020ae0e282a3b7a463e71064ecbaf671586e979b0edbebf7a4735c31678c70f660c",
|
||||
// expectedOutput: "986ae432c402479fe7a0c6fbe02164c1",
|
||||
// recipeConfig: [
|
||||
// {
|
||||
// "op": "JA3S Fingerprint",
|
||||
// "args": ["Hex", "Hash digest"]
|
||||
// }
|
||||
// ],
|
||||
// },
|
||||
]);
|
||||
@@ -10,10 +10,10 @@ import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Protobuf Decode",
|
||||
name: "Protobuf Decode: no schema",
|
||||
input: "0d1c0000001203596f751a024d65202b2a0a0a066162633132331200",
|
||||
expectedOutput: JSON.stringify({
|
||||
"1": 469762048,
|
||||
"1": 28,
|
||||
"2": "You",
|
||||
"3": "Me",
|
||||
"4": 43,
|
||||
@@ -29,7 +29,277 @@ TestRegister.addTests([
|
||||
},
|
||||
{
|
||||
"op": "Protobuf Decode",
|
||||
"args": []
|
||||
"args": ["", false, false]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Protobuf Decode: partial schema, no unknown fields",
|
||||
input: "0d1c0000001203596f751a024d65202b2a0a0a066162633132331200",
|
||||
expectedOutput: JSON.stringify({
|
||||
"Apple": [
|
||||
28
|
||||
],
|
||||
"Banana": "You",
|
||||
"Carrot": [
|
||||
"Me"
|
||||
]
|
||||
}, null, 4),
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["Auto"]
|
||||
},
|
||||
{
|
||||
"op": "Protobuf Decode",
|
||||
"args": [
|
||||
`message Test {
|
||||
repeated fixed32 Apple = 1;
|
||||
optional string Banana = 2;
|
||||
repeated string Carrot = 3;
|
||||
}`,
|
||||
false,
|
||||
false
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Protobuf Decode: partial schema, show unknown fields",
|
||||
input: "0d1c0000001203596f751a024d65202b2a0a0a066162633132331200",
|
||||
expectedOutput: JSON.stringify({
|
||||
"Test": {
|
||||
"Apple": [
|
||||
28
|
||||
],
|
||||
"Banana": "You",
|
||||
"Carrot": [
|
||||
"Me"
|
||||
]
|
||||
},
|
||||
"Unknown Fields": {
|
||||
"4": 43,
|
||||
"5": {
|
||||
"1": "abc123",
|
||||
"2": {}
|
||||
}
|
||||
}
|
||||
}, null, 4),
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["Auto"]
|
||||
},
|
||||
{
|
||||
"op": "Protobuf Decode",
|
||||
"args": [
|
||||
`message Test {
|
||||
repeated fixed32 Apple = 1;
|
||||
optional string Banana = 2;
|
||||
repeated string Carrot = 3;
|
||||
}`,
|
||||
true,
|
||||
false
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Protobuf Decode: full schema, no unknown fields",
|
||||
input: "0d1c0000001203596f751a024d65202b2a0a0a06616263313233120031ff00000000000000",
|
||||
expectedOutput: JSON.stringify({
|
||||
"Apple": [
|
||||
28
|
||||
],
|
||||
"Banana": "You",
|
||||
"Carrot": [
|
||||
"Me"
|
||||
],
|
||||
"Date": 43,
|
||||
"Elderberry": {
|
||||
"Fig": "abc123",
|
||||
"Grape": {}
|
||||
},
|
||||
"Huckleberry": 255
|
||||
}, null, 4),
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["Auto"]
|
||||
},
|
||||
{
|
||||
"op": "Protobuf Decode",
|
||||
"args": [
|
||||
`message Test {
|
||||
repeated fixed32 Apple = 1;
|
||||
optional string Banana = 2;
|
||||
repeated string Carrot = 3;
|
||||
optional int32 Date = 4;
|
||||
optional subTest Elderberry = 5;
|
||||
optional fixed64 Huckleberry = 6;
|
||||
}
|
||||
message subTest {
|
||||
optional string Fig = 1;
|
||||
optional subSubTest Grape = 2;
|
||||
}
|
||||
message subSubTest {}`,
|
||||
false,
|
||||
false
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Protobuf Decode: partial schema, show unknown fields, show types",
|
||||
input: "0d1c0000001203596f751a024d65202b2a0a0a06616263313233120031ba32a96cc10200003801",
|
||||
expectedOutput: JSON.stringify({
|
||||
"Test": {
|
||||
"Banana (string)": "You",
|
||||
"Carrot (string)": [
|
||||
"Me"
|
||||
],
|
||||
"Date (int32)": 43,
|
||||
"Imbe (Options)": "Option1"
|
||||
},
|
||||
"Unknown Fields": {
|
||||
"field #1: 32-Bit (e.g. fixed32, float)": 28,
|
||||
"field #5: L-delim (e.g. string, message)": {
|
||||
"field #1: L-delim (e.g. string, message)": "abc123",
|
||||
"field #2: L-delim (e.g. string, message)": {}
|
||||
},
|
||||
"field #6: 64-Bit (e.g. fixed64, double)": 3029774971578
|
||||
}
|
||||
}, null, 4),
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["Auto"]
|
||||
},
|
||||
{
|
||||
"op": "Protobuf Decode",
|
||||
"args": [
|
||||
`message Test {
|
||||
optional string Banana = 2;
|
||||
repeated string Carrot = 3;
|
||||
optional int32 Date = 4;
|
||||
optional Options Imbe = 7;
|
||||
}
|
||||
message subTest {
|
||||
optional string Fig = 1;
|
||||
optional subSubTest Grape = 2;
|
||||
}
|
||||
message subSubTest {}
|
||||
enum Options {
|
||||
Option0 = 0;
|
||||
Option1 = 1;
|
||||
Option2 = 2;
|
||||
}`,
|
||||
true,
|
||||
true
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Protobuf Encode",
|
||||
input: JSON.stringify({
|
||||
"Apple": [
|
||||
28
|
||||
],
|
||||
"Banana": "You",
|
||||
"Carrot": [
|
||||
"Me"
|
||||
],
|
||||
"Date": 43,
|
||||
"Elderberry": {
|
||||
"Fig": "abc123",
|
||||
"Grape": {}
|
||||
},
|
||||
"Huckleberry": [3029774971578],
|
||||
"Imbe": 1
|
||||
}, null, 4),
|
||||
expectedOutput: "0d1c0000001203596f751a024d65202b2a0a0a06616263313233120031ba32a96cc10200003801",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Protobuf Encode",
|
||||
"args": [
|
||||
`message Test {
|
||||
repeated fixed32 Apple = 1;
|
||||
optional string Banana = 2;
|
||||
repeated string Carrot = 3;
|
||||
optional int32 Date = 4;
|
||||
optional subTest Elderberry = 5;
|
||||
repeated fixed64 Huckleberry = 6;
|
||||
optional Options Imbe = 7;
|
||||
}
|
||||
message subTest {
|
||||
optional string Fig = 1;
|
||||
optional subSubTest Grape = 2;
|
||||
}
|
||||
message subSubTest {}
|
||||
enum Options {
|
||||
Option0 = 0;
|
||||
Option1 = 1;
|
||||
Option2 = 2;
|
||||
}`
|
||||
]
|
||||
},
|
||||
{
|
||||
"op": "To Hex",
|
||||
"args": [
|
||||
"None",
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Protobuf Encode: incomplete schema",
|
||||
input: JSON.stringify({
|
||||
"Apple": [
|
||||
28
|
||||
],
|
||||
"Banana": "You",
|
||||
"Carrot": [
|
||||
"Me"
|
||||
],
|
||||
"Date": 43,
|
||||
"Elderberry": {
|
||||
"Fig": "abc123",
|
||||
"Grape": {}
|
||||
},
|
||||
"Huckleberry": [3029774971578],
|
||||
"Imbe": 1
|
||||
}, null, 4),
|
||||
expectedOutput: "1203596f75202b2a0a0a06616263313233120031ba32a96cc1020000",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Protobuf Encode",
|
||||
"args": [
|
||||
`message Test {
|
||||
optional string Banana = 2;
|
||||
optional int32 Date = 4;
|
||||
optional subTest Elderberry = 5;
|
||||
repeated fixed64 Huckleberry = 6;
|
||||
}
|
||||
message subTest {
|
||||
optional string Fig = 1;
|
||||
optional subSubTest Grape = 2;
|
||||
}
|
||||
message subSubTest {}
|
||||
enum Options {
|
||||
Option0 = 0;
|
||||
Option1 = 1;
|
||||
Option2 = 2;
|
||||
}`
|
||||
]
|
||||
},
|
||||
{
|
||||
"op": "To Hex",
|
||||
"args": [
|
||||
"None",
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -64,7 +64,10 @@ TestRegister.addTests([
|
||||
"option": "Hex",
|
||||
"string": ""
|
||||
},
|
||||
""
|
||||
{
|
||||
"option": "Hex",
|
||||
"string": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
91
tests/operations/tests/SIGABA.mjs
Normal file
91
tests/operations/tests/SIGABA.mjs
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* SIGABA machine tests
|
||||
*
|
||||
* @author hettysymes
|
||||
* @copyright hettysymes 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "SIGABA: encrypt test 1",
|
||||
input: "HELLO WORLD TESTING THE SIGABA MACHINE",
|
||||
expectedOutput: "ULBECJCZJBJFVUDWAVRGRBMPSQHOTTNVQEESKN",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "SIGABA",
|
||||
"args": [
|
||||
"BHKWECJDOVAYLFMITUGXRNSPZQ", true, "G",
|
||||
"CDTAKGQOZXLVJYHSWMIBPRUNEF", false, "L",
|
||||
"WAXHJZMBVDPOLTUYRCQFNSGKEI", false, "I",
|
||||
"HUSCWIMJQXDALVGBFTOYZKRPNE", false, "T",
|
||||
"RTLSMNKXFVWQUZGCHEJBYDAIPO", false, "B",
|
||||
"GHAQBRJWDMNZTSKLOUXYPFIECV", false, "N",
|
||||
"VFLGEMTCXZIQDYAKRPBONHWSUJ", true, "Q",
|
||||
"ZQCAYHRJNXPFLKIOTBUSVWMGDE", false, "B",
|
||||
"EZVSWPCTULGAOFDJNBIYMXKQHR", false, "J",
|
||||
"ELKSGDXMVYJUZNCAROQBPWHITF", false, "R",
|
||||
"3891625740", "3",
|
||||
"6297135408", "1",
|
||||
"2389715064", "8",
|
||||
"9264351708", "6",
|
||||
"9573086142", "6",
|
||||
"Encrypt"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SIGABA: encrypt test 2",
|
||||
input: "PCRPJZWSPNOHMWANBFBEIVZOXDQESPYDEFBNTHXLSICIRPKUATJVDUQFLZOKGHHHDUDIBRKUHVCGAGLBWVGFFXNDHKPFSPSCIIPCXUFRRHNYWIJFEJWQSGMSNJHWSLPKVXHUQUWIURHDIHIUTWGQFIYLTKEZAUESWYEKIWXUSSXWXBEHCXCUDQWKCISVPKXJVPOIJZWTUGKAORBMKBAQUZOPTSUSYZRROWQUYKNCLHVIHEGWCCONGVHEKCEXVYIPNILIXTXDELNGLJGMEQKKQJWZLPNXPOGIOSVAEAJYKWYJXXGKKPLVYAZGDCMNHMPLCYWDQSRBEMVVVZVFYJMRYGHJOTDOEQVRQOVXOGOVYGTXETFHAYELRYVDGWOFVGAOWPMHQYRZMNXVTAHWSKZLJDFVQPZGMHZWFNOBHSZHEDAEXIFCEEJYZDOEFOQWCXTKPJRUEITKHVCITCLKBUFNAFBYXELAYPBRGGGOCCAGLXXJXTSWCJHMHQPVUIBAGBDKAGEEEPKRGGICJQXSYHBNNAKGYODRAUWAEYHWCKHEQIBAONWQJYQCIFKDTOCTJMBJULWKMSNNMPXINHZQWUMJQLQKIPVZVRGYPCJJZMENWTFTUSPCSPRXHMZPCHCNQTUDCOUJHRKYQIUWWVEVVRYFDIYRQISNGPMQLNMCNMVBEWHNCUODHAGEVEUMKVZLEIKYAMPGVVSBYNRJMFCATDXTQCYXIBCXXKYEYHHYERQGQWZTWCEJBFQLRFFCIVVSZUKGLOTLNGLQNTIKTBBWVFMONUFKRLCJASEKUEEDDQDIVQMFRSJRNHYZJODFHSCJSDAIRUXOSDNFUFUFMNZYQIEGRUXKUPCHENUEZHRKYHDRJYSHLZNYRBWVXORMJMJRIRNSAJQRUMPCXUDFYRGKEAXQXJHPEWNIYIDURDGWIFEMSOFYYCFRZGMZXJNTLTJBBSZIULQSOMEVGCTCVXUHTIEHSPOPQYCJLPAJAPQPAQXE",
|
||||
expectedOutput: "GMEXPPCMFGKUVGXZHVTCKXRSTJUYWNOKFVELWAHHSJBXGOEXCMLOVSIMCDMGEYMWWTFDUMCDUJEZITNPVVBGQDJEVHJXSKJAAUZWBELMSPUTXCUYPDTJCQXEBGWPWRSQLSNFMASCTJZDSFNKDDTAXLRGUPKCBNXMZPADJSFGGNYKRPYBNTYPTGVPACBEINILNACWFVKMJPGCEZFROEYYKTGYSQYMFSGVDOJJONNYEYSCCIXWLKUSJZDRVAQSNUWHMDJVDNNMPGOYRGQRSBGSPQKGCTFZQWSOXBWSQZDCRQJQAWZDPQEILGMMABIMCDPNSKAFCLPQGIRJCMGQREBEUHBYREXFABFMVZTZBDUMASVNUMHIYRSZLGNZFMVAIABLCUZLJLKKZPWEXDHYZFVSNRLCLNDRKLKSWRHQVQJRTHCNFZXDEXSLAXXOGMFVSGCJGAWOLGDMTLWSFNTCUVCCEACINRZAZZOGLEHHXLPHVKILBBJDPOOCILQKKGODSXOBDPZZDXHJLLBOBVFCHJVMUBUZZIKGCWGCYGXVEHHIJGPEQERWEZLILQNHPHALFKFMGADNELGBKILKIUETGDCBQUEOECWVFNOXTJKUYPWBNEKYSIKMVSAMBZGLIKDAOELRSTKFASEKABTUCPSFEGXXQGDFPSPVOLBHGLZSLLWCABSRKZDQQRKVCKXDGTIHPDNMPDZEXYFYKXZTPJPLYOFNLWAGKJEOHOYLMZELXIDWWNXPKEPUCKNNNHJLFYHPQNHMMCGMUPHSUSYYIVWTIMFKKKTFPGFTLTWWSQBRBMGBTZXPVULKNZIIKVTYLJFISGPTLZFTCLGNZOMVKZOIMUDGXRDDSVFRHRYWBEWHYLCUISYMRWAZZAQPJYXZQQKZLILOSHXUTQJFPTXQSREKSUDZTLGUDLUGOJMQHJRJHXCHQTKJULTWWQOXIRFRQEYBPJPEKXFIRMNATWNFBADOSIJVZYRYDBHDAEDJUVDHLDAU",
|
||||
recipeConfig: [
|
||||
{ "op": "SIGABA",
|
||||
"args": [
|
||||
"YCHLQSUGBDIXNZKERPVJTAWFOM", true, "A",
|
||||
"INPXBWETGUYSAOCHVLDMQKZJFR", false, "B",
|
||||
"WNDRIOZPTAXHFJYQBMSVEKUCGL", false, "C",
|
||||
"TZGHOBKRVUXLQDMPNFWCJYEIAS", false, "D",
|
||||
"YWTAHRQJVLCEXUNGBIPZMSDFOK", true, "E",
|
||||
"QSLRBTEKOGAICFWYVMHJNXZUDP", false, "F",
|
||||
"CHJDQIGNBSAKVTUOXFWLEPRMZY", false, "G",
|
||||
"CDFAJXTIMNBEQHSUGRYLWZKVPO", true, "H",
|
||||
"XHFESZDNRBCGKQIJLTVMUOYAPW", false, "I",
|
||||
"EZJQXMOGYTCSFRIUPVNADLHWBK", false, "J",
|
||||
"7591482630", "0",
|
||||
"3810592764", "1",
|
||||
"4086153297", "2",
|
||||
"3980526174", "3",
|
||||
"6497135280", "4",
|
||||
"Encrypt"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "SIGABA: decrypt test",
|
||||
input: "AKDHFWAYSLHJDKXEVMJJHGKFTQBZPJPJILOVHMBYOAGBZVLLTQUOIKXFPUFNILBDPCAELMAPSXTLMUEGSDTNUDWGZDADBFELWWHKVPRZNDATDPYEHIDMTGAGPDEZYXFSASVKSBMXVOJQXRMHDBWUNZDTIIIVKHJYPIEUHAJCNBXNLGVFADEWIKXDJZBUTGOQBCQZWYKRVEENWRWWRYDNOAPGMODTPTUJZCLUCRDILJABNTBTWUEIJSJRQBUVCOUJJDWFMNNUHXBDFYXLGUMXQEAWSVHBXQGEOOGPYRVOAJLAIYIOHHEXACDTAWWCBGQRNPERSIKHTXPXKBUNACZLFZTRBMBBDDGKNBIQMFHZROCZZBGNZSJKDRRWPEQHLCFADNPWPWSLPIFNKBWQPMARUERGWUUODXSCOJQECGHIZRFRNRSXWSFWKISHHTUFRVXLHCQWGBMRDHCYDSVNIDDRSTODCGJSSBLUYOBGEWFOVKOZBJTYCAKMZECUGLJGTSZJNBOLTMUZRRSIGGRQHLRPMGLINASSMZOBNACKUMSFNIZAUFCPFXXOOTJQWWLZOFLGZLHJCWZJCRJKVOUDLNMKQATGVTOFHACAEKFLRWRTTMVRXHYGOTYPNBMUSKDAKXFCICUOVSWXGPQOYUUWTWRPQMEQCSDJMMJKELIHGEDYKWOVHVPUAIBFGAODXODXVFIIZIGWRZSBTIGXVHFABMMOPGVMLGHQQXNOEJRDLOBGUOWSELBHERZFSBLUODMOGIBNVGVGQYDBTKLOPNKZZNGLTTGZYYXIBAHZJDCILZXKNSJDHXWTYQLFHTUINTYSBPIXOPLOQHSAHGQPYUWYNPKMRBBBYIICCBBJRKWVLBIDBBEKJCXHLPUBMIGBUFYDPOCSRUNZOKMKJHMYFJZWFNHQZOGGRTNNUVLMRLDSAJIECTYCJKBYVNAXGCMGNVFJEDSATZQDQTYRBPLZKHAXMOVJZEDKINXKBUVWXXHTYUFO",
|
||||
expectedOutput: "KTSOYDGMLPMVXEAJIATXCNQFXHBNCBXIJOCQGCQBRQSBYFOOEVPVXACBMIUIRNVMJHREKRHBSXJFSMWCKTTCYXJOFSJCQECXXCHTEGPEYSMYDHCSMODUAVBNLILYUIBBIXJCXXNQPCERRSMJTPQLMOXSKTRPWOFUSWXOYRJLBIJGIOYTEAEJEGGYAGSXNHNQTETANPWEGATHSBFLHCVHVIJUAKDVGQCWUSIFFFVAJYPJAFUYDXSLGPGESOUAYXBQIIOXWTXNOXLNCGWSUKVIBMOUGNHORYLSNVNNJLKKFDUAEISOLBLCXYHMDGVBVVVIKDLTMTDVWWJBXWXROVTJBXXKXLEWTTISKIUMYSACVUGGNANMCGUMFNQUXDLTHJNYTFIQEPKQQQSSROYJOILJYQXICXACWGOHCSHENXJILOMIIFCIOUDXDCINIVKIRJCVHWXSFQXMNRBJJWTPXNJADEOPEJBLKHKXNTORIRVRLXUXXAMKMODBXNLQCVJXVOTBRHXBBVJHPFEQFCRXYRRXHXPTXXSUESUTHUGOWQYQPQFPXQPVGEIRPQNKXXMBHIPECRUWFEWJUTYIKSMJSRQIQAIAMXTGDXSJIABHIGKUPJBCHWMVYTMQNQYGDHCNMBSVTPXNFRELFXXQYIOLCDEXDXDVSINICOXRMNSPICPQMOBIDJCNBJKXFAVMUXOXHERJIBIXLMXXULDXKXXHAQDXEXIWXOEEUGKSUGCMRWJDPYCYKXTPCOXMURAJCPRXKFJAJALERWRHVMFHOGMFHXGSXQDPJCJNXRQFGHKRCYTEBJDHPCMYFEAPWSVVMMBVUJJMCAAYURHUPVQVJYDCSNMQEMNIFEXYXIIXBVRVILXAUCBDXRJHGPKPYXHPPPNVSBBCDRLVVIYPKAKYIXTJVYDGVPHXULWMADBEICNIFKWUOOHEFNANDKOXMCVBVORLQYNXLULOEGVGWNKNMOHYVRSYSOVYGAKCGAWKGAIAQNQR",
|
||||
recipeConfig: [
|
||||
{ "op": "SIGABA",
|
||||
"args": [
|
||||
"YCHLQSUGBDIXNZKERPVJTAWFOM", true, "A",
|
||||
"INPXBWETGUYSAOCHVLDMQKZJFR", false, "B",
|
||||
"WNDRIOZPTAXHFJYQBMSVEKUCGL", false, "C",
|
||||
"TZGHOBKRVUXLQDMPNFWCJYEIAS", false, "D",
|
||||
"YWTAHRQJVLCEXUNGBIPZMSDFOK", true, "E",
|
||||
"QSLRBTEKOGAICFWYVMHJNXZUDP", false, "F",
|
||||
"CHJDQIGNBSAKVTUOXFWLEPRMZY", false, "G",
|
||||
"CDFAJXTIMNBEQHSUGRYLWZKVPO", true, "H",
|
||||
"XHFESZDNRBCGKQIJLTVMUOYAPW", false, "I",
|
||||
"EZJQXMOGYTCSFRIUPVNADLHWBK", false, "J",
|
||||
"7591482630", "0",
|
||||
"3810592764", "1",
|
||||
"4086153297", "2",
|
||||
"3980526174", "3",
|
||||
"6497135280", "4",
|
||||
"Decrypt"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
@@ -36,7 +36,8 @@ const banner = `/**
|
||||
module.exports = {
|
||||
output: {
|
||||
publicPath: "",
|
||||
globalObject: "this"
|
||||
globalObject: "this",
|
||||
assetModuleFilename: "assets/[hash][ext][query]"
|
||||
},
|
||||
plugins: [
|
||||
new webpack.ProvidePlugin({
|
||||
@@ -122,7 +123,7 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
test: /prime.worker.min.js$/,
|
||||
use: "raw-loader"
|
||||
type: "asset/source"
|
||||
},
|
||||
{
|
||||
test: /bootstrap-material-design/,
|
||||
@@ -165,53 +166,33 @@ module.exports = {
|
||||
"sass-loader",
|
||||
]
|
||||
},
|
||||
/**
|
||||
* The limit for these files has been increased to 60,000 (60KB)
|
||||
* to ensure the material icons font is inlined.
|
||||
*
|
||||
* See: https://github.com/gchq/CyberChef/issues/612
|
||||
*/
|
||||
{
|
||||
test: /\.(ico|eot|ttf|woff|woff2)$/,
|
||||
loader: "url-loader",
|
||||
options: {
|
||||
limit: 60000,
|
||||
name: "[hash].[ext]",
|
||||
outputPath: "assets"
|
||||
}
|
||||
type: "asset/resource",
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
loader: "svg-url-loader",
|
||||
options: {
|
||||
encoding: "base64"
|
||||
}
|
||||
type: "asset/inline",
|
||||
},
|
||||
{ // Store font .fnt and .png files in a separate fonts folder
|
||||
test: /(\.fnt$|bmfonts\/.+\.png$)/,
|
||||
loader: "file-loader",
|
||||
options: {
|
||||
name: "[name].[ext]",
|
||||
outputPath: "assets/fonts"
|
||||
type: "asset/resource",
|
||||
generator: {
|
||||
filename: "assets/fonts/[name][ext]"
|
||||
}
|
||||
},
|
||||
{ // First party images are saved as files to be cached
|
||||
test: /\.(png|jpg|gif)$/,
|
||||
exclude: /(node_modules|bmfonts)/,
|
||||
loader: "file-loader",
|
||||
options: {
|
||||
name: "images/[name].[ext]"
|
||||
type: "asset/resource",
|
||||
generator: {
|
||||
filename: "images/[name][ext]"
|
||||
}
|
||||
},
|
||||
{ // Third party images are inlined
|
||||
test: /\.(png|jpg|gif)$/,
|
||||
exclude: /web\/static/,
|
||||
loader: "url-loader",
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: "[hash].[ext]",
|
||||
outputPath: "assets"
|
||||
}
|
||||
type: "asset/inline",
|
||||
},
|
||||
]
|
||||
},
|
||||
@@ -219,14 +200,15 @@ module.exports = {
|
||||
children: false,
|
||||
chunks: false,
|
||||
modules: false,
|
||||
entrypoints: false,
|
||||
warningsFilter: [
|
||||
/source-map/,
|
||||
/dependency is an expression/,
|
||||
/export 'default'/,
|
||||
/Can't resolve 'sodium'/
|
||||
],
|
||||
entrypoints: false
|
||||
},
|
||||
ignoreWarnings: [
|
||||
/source-map/,
|
||||
/source map/,
|
||||
/dependency is an expression/,
|
||||
/export 'default'/,
|
||||
/Can't resolve 'sodium'/
|
||||
],
|
||||
performance: {
|
||||
hints: false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user