mirror of
https://github.com/gchq/CyberChef
synced 2024-11-15 00:57:08 +00:00
Merge remote-tracking branch 'origin/master' into v10
This commit is contained in:
commit
2e201c747a
48 changed files with 2767 additions and 70 deletions
36
CHANGELOG.md
36
CHANGELOG.md
|
@ -13,6 +13,27 @@ All major and minor version changes will be documented in this file. Details of
|
||||||
|
|
||||||
## Details
|
## Details
|
||||||
|
|
||||||
|
### [9.55.0] - 2022-12-09
|
||||||
|
- Added 'AMF Encode' and 'AMF Decode' operations [@n1474335] | [760eff4]
|
||||||
|
|
||||||
|
### [9.54.0] - 2022-11-25
|
||||||
|
- Added 'Rabbit' operation [@mikecat] | [#1450]
|
||||||
|
|
||||||
|
### [9.53.0] - 2022-11-25
|
||||||
|
- Added 'AES Key Wrap' and 'AES Key Unwrap' operations [@mikecat] | [#1456]
|
||||||
|
|
||||||
|
### [9.52.0] - 2022-11-25
|
||||||
|
- Added 'ChaCha' operation [@joostrijneveld] | [#1466]
|
||||||
|
|
||||||
|
### [9.51.0] - 2022-11-25
|
||||||
|
- Added 'CMAC' operation [@mikecat] | [#1457]
|
||||||
|
|
||||||
|
### [9.50.0] - 2022-11-25
|
||||||
|
- Added 'Shuffle' operation [@mikecat] | [#1472]
|
||||||
|
|
||||||
|
### [9.49.0] - 2022-11-11
|
||||||
|
- Added 'LZ4 Compress' and 'LZ4 Decompress' operations [@n1474335] | [31a7f83]
|
||||||
|
|
||||||
### [9.48.0] - 2022-10-14
|
### [9.48.0] - 2022-10-14
|
||||||
- Added 'LM Hash' and 'NT Hash' operations [@n1474335] [@brun0ne] | [#1427]
|
- Added 'LM Hash' and 'NT Hash' operations [@n1474335] [@brun0ne] | [#1427]
|
||||||
|
|
||||||
|
@ -321,6 +342,13 @@ All major and minor version changes will be documented in this file. Details of
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[9.55.0]: https://github.com/gchq/CyberChef/releases/tag/v9.55.0
|
||||||
|
[9.54.0]: https://github.com/gchq/CyberChef/releases/tag/v9.54.0
|
||||||
|
[9.53.0]: https://github.com/gchq/CyberChef/releases/tag/v9.53.0
|
||||||
|
[9.52.0]: https://github.com/gchq/CyberChef/releases/tag/v9.52.0
|
||||||
|
[9.51.0]: https://github.com/gchq/CyberChef/releases/tag/v9.51.0
|
||||||
|
[9.50.0]: https://github.com/gchq/CyberChef/releases/tag/v9.50.0
|
||||||
|
[9.49.0]: https://github.com/gchq/CyberChef/releases/tag/v9.49.0
|
||||||
[9.48.0]: https://github.com/gchq/CyberChef/releases/tag/v9.48.0
|
[9.48.0]: https://github.com/gchq/CyberChef/releases/tag/v9.48.0
|
||||||
[9.47.0]: https://github.com/gchq/CyberChef/releases/tag/v9.47.0
|
[9.47.0]: https://github.com/gchq/CyberChef/releases/tag/v9.47.0
|
||||||
[9.46.0]: https://github.com/gchq/CyberChef/releases/tag/v9.46.0
|
[9.46.0]: https://github.com/gchq/CyberChef/releases/tag/v9.46.0
|
||||||
|
@ -459,6 +487,7 @@ All major and minor version changes will be documented in this file. Details of
|
||||||
[@thomasleplus]: https://github.com/thomasleplus
|
[@thomasleplus]: https://github.com/thomasleplus
|
||||||
[@valdelaseras]: https://github.com/valdelaseras
|
[@valdelaseras]: https://github.com/valdelaseras
|
||||||
[@brun0ne]: https://github.com/brun0ne
|
[@brun0ne]: https://github.com/brun0ne
|
||||||
|
[@joostrijneveld]: https://github.com/joostrijneveld
|
||||||
|
|
||||||
[8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
|
[8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
|
||||||
[9a33498]: https://github.com/gchq/CyberChef/commit/9a33498fed26a8df9c9f35f39a78a174bf50a513
|
[9a33498]: https://github.com/gchq/CyberChef/commit/9a33498fed26a8df9c9f35f39a78a174bf50a513
|
||||||
|
@ -466,6 +495,8 @@ All major and minor version changes will be documented in this file. Details of
|
||||||
[e9ca4dc]: https://github.com/gchq/CyberChef/commit/e9ca4dc9caf98f33fd986431cd400c88082a42b8
|
[e9ca4dc]: https://github.com/gchq/CyberChef/commit/e9ca4dc9caf98f33fd986431cd400c88082a42b8
|
||||||
[dd18e52]: https://github.com/gchq/CyberChef/commit/dd18e529939078b89867297b181a584e8b2cc7da
|
[dd18e52]: https://github.com/gchq/CyberChef/commit/dd18e529939078b89867297b181a584e8b2cc7da
|
||||||
[a895d1d]: https://github.com/gchq/CyberChef/commit/a895d1d82a2f92d440a0c5eca2bc7c898107b737
|
[a895d1d]: https://github.com/gchq/CyberChef/commit/a895d1d82a2f92d440a0c5eca2bc7c898107b737
|
||||||
|
[31a7f83]: https://github.com/gchq/CyberChef/commit/31a7f83b82e78927f89689f323fcb9185144d6ff
|
||||||
|
[760eff4]: https://github.com/gchq/CyberChef/commit/760eff49b5307aaa3104c5e5b437ffe62299acd1
|
||||||
|
|
||||||
[#95]: https://github.com/gchq/CyberChef/pull/299
|
[#95]: https://github.com/gchq/CyberChef/pull/299
|
||||||
[#173]: https://github.com/gchq/CyberChef/pull/173
|
[#173]: https://github.com/gchq/CyberChef/pull/173
|
||||||
|
@ -563,4 +594,9 @@ All major and minor version changes will be documented in this file. Details of
|
||||||
[#1308]: https://github.com/gchq/CyberChef/pull/1308
|
[#1308]: https://github.com/gchq/CyberChef/pull/1308
|
||||||
[#1421]: https://github.com/gchq/CyberChef/pull/1421
|
[#1421]: https://github.com/gchq/CyberChef/pull/1421
|
||||||
[#1427]: https://github.com/gchq/CyberChef/pull/1427
|
[#1427]: https://github.com/gchq/CyberChef/pull/1427
|
||||||
|
[#1472]: https://github.com/gchq/CyberChef/pull/1472
|
||||||
|
[#1457]: https://github.com/gchq/CyberChef/pull/1457
|
||||||
|
[#1466]: https://github.com/gchq/CyberChef/pull/1466
|
||||||
|
[#1456]: https://github.com/gchq/CyberChef/pull/1456
|
||||||
|
[#1450]: https://github.com/gchq/CyberChef/pull/1450
|
||||||
|
|
||||||
|
|
67
package-lock.json
generated
67
package-lock.json
generated
|
@ -1,15 +1,16 @@
|
||||||
{
|
{
|
||||||
"name": "cyberchef",
|
"name": "cyberchef",
|
||||||
"version": "9.48.0",
|
"version": "9.55.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "cyberchef",
|
"name": "cyberchef",
|
||||||
"version": "9.48.0",
|
"version": "9.55.0",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@astronautlabs/amf": "^0.0.6",
|
||||||
"@babel/polyfill": "^7.12.1",
|
"@babel/polyfill": "^7.12.1",
|
||||||
"@blu3r4y/lzma": "^2.3.3",
|
"@blu3r4y/lzma": "^2.3.3",
|
||||||
"arrive": "^2.4.1",
|
"arrive": "^2.4.1",
|
||||||
|
@ -58,6 +59,7 @@
|
||||||
"loglevel": "^1.8.0",
|
"loglevel": "^1.8.0",
|
||||||
"loglevel-message-prefix": "^3.0.0",
|
"loglevel-message-prefix": "^3.0.0",
|
||||||
"lz-string": "^1.4.4",
|
"lz-string": "^1.4.4",
|
||||||
|
"lz4js": "^0.2.0",
|
||||||
"markdown-it": "^13.0.1",
|
"markdown-it": "^13.0.1",
|
||||||
"moment": "^2.29.3",
|
"moment": "^2.29.3",
|
||||||
"moment-timezone": "^0.5.34",
|
"moment-timezone": "^0.5.34",
|
||||||
|
@ -74,6 +76,7 @@
|
||||||
"process": "^0.11.10",
|
"process": "^0.11.10",
|
||||||
"protobufjs": "^6.11.3",
|
"protobufjs": "^6.11.3",
|
||||||
"qr-image": "^3.2.0",
|
"qr-image": "^3.2.0",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
"scryptsy": "^2.1.0",
|
"scryptsy": "^2.1.0",
|
||||||
"snackbarjs": "^1.1.0",
|
"snackbarjs": "^1.1.0",
|
||||||
"sortablejs": "^1.15.0",
|
"sortablejs": "^1.15.0",
|
||||||
|
@ -154,6 +157,25 @@
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@astronautlabs/amf": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@astronautlabs/amf/-/amf-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-cJgbXW45TIDLQf2hiHqDoRfmeRy5u9Z4npr7sZfBThvbp5cbqDieTWaJTu91cUAj35/u87OHZijLTbMO18ZIow==",
|
||||||
|
"dependencies": {
|
||||||
|
"@astronautlabs/bitstream": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@astronautlabs/bitstream": {
|
||||||
|
"version": "4.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@astronautlabs/bitstream/-/bitstream-4.1.3.tgz",
|
||||||
|
"integrity": "sha512-4X5cmrB5I5g/ifKXwoVc5JwAYgn372kS0AsTdVQYY+OzlSZ92ANEHj6W5MW5haYSQbbBZ9XK55rdy6NnXOyRgA==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"reflect-metadata": "^0.1.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/code-frame": {
|
"node_modules/@babel/code-frame": {
|
||||||
"version": "7.16.7",
|
"version": "7.16.7",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -8825,6 +8847,11 @@
|
||||||
"lz-string": "bin/bin.js"
|
"lz-string": "bin/bin.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lz4js": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lz4js/-/lz4js-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-gY2Ia9Lm7Ep8qMiuGRhvUq0Q7qUereeldZPP1PMEJxPtEWHJLqw9pgX68oHajBH0nzJK4MaZEA/YNV3jT8u8Bg=="
|
||||||
|
},
|
||||||
"node_modules/make-dir": {
|
"node_modules/make-dir": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -10798,6 +10825,8 @@
|
||||||
},
|
},
|
||||||
"node_modules/queue-microtask": {
|
"node_modules/queue-microtask": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -10812,8 +10841,7 @@
|
||||||
"type": "consulting",
|
"type": "consulting",
|
||||||
"url": "https://feross.org/support"
|
"url": "https://feross.org/support"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/randombytes": {
|
"node_modules/randombytes": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
|
@ -10908,6 +10936,11 @@
|
||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/reflect-metadata": {
|
||||||
|
"version": "0.1.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
|
||||||
|
"integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
|
||||||
|
},
|
||||||
"node_modules/regenerate": {
|
"node_modules/regenerate": {
|
||||||
"version": "1.4.2",
|
"version": "1.4.2",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -13115,6 +13148,20 @@
|
||||||
"@jridgewell/trace-mapping": "^0.3.0"
|
"@jridgewell/trace-mapping": "^0.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@astronautlabs/amf": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@astronautlabs/amf/-/amf-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-cJgbXW45TIDLQf2hiHqDoRfmeRy5u9Z4npr7sZfBThvbp5cbqDieTWaJTu91cUAj35/u87OHZijLTbMO18ZIow==",
|
||||||
|
"requires": {
|
||||||
|
"@astronautlabs/bitstream": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@astronautlabs/bitstream": {
|
||||||
|
"version": "4.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@astronautlabs/bitstream/-/bitstream-4.1.3.tgz",
|
||||||
|
"integrity": "sha512-4X5cmrB5I5g/ifKXwoVc5JwAYgn372kS0AsTdVQYY+OzlSZ92ANEHj6W5MW5haYSQbbBZ9XK55rdy6NnXOyRgA==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"@babel/code-frame": {
|
"@babel/code-frame": {
|
||||||
"version": "7.16.7",
|
"version": "7.16.7",
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -18784,6 +18831,11 @@
|
||||||
"lz-string": {
|
"lz-string": {
|
||||||
"version": "1.4.4"
|
"version": "1.4.4"
|
||||||
},
|
},
|
||||||
|
"lz4js": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lz4js/-/lz4js-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-gY2Ia9Lm7Ep8qMiuGRhvUq0Q7qUereeldZPP1PMEJxPtEWHJLqw9pgX68oHajBH0nzJK4MaZEA/YNV3jT8u8Bg=="
|
||||||
|
},
|
||||||
"make-dir": {
|
"make-dir": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -20042,6 +20094,8 @@
|
||||||
},
|
},
|
||||||
"queue-microtask": {
|
"queue-microtask": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"randombytes": {
|
"randombytes": {
|
||||||
|
@ -20111,6 +20165,11 @@
|
||||||
"resolve": "^1.9.0"
|
"resolve": "^1.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"reflect-metadata": {
|
||||||
|
"version": "0.1.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
|
||||||
|
"integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
|
||||||
|
},
|
||||||
"regenerate": {
|
"regenerate": {
|
||||||
"version": "1.4.2",
|
"version": "1.4.2",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "cyberchef",
|
"name": "cyberchef",
|
||||||
"version": "9.48.0",
|
"version": "9.55.0",
|
||||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||||
"author": "n1474335 <n1474335@gmail.com>",
|
"author": "n1474335 <n1474335@gmail.com>",
|
||||||
"homepage": "https://gchq.github.io/CyberChef",
|
"homepage": "https://gchq.github.io/CyberChef",
|
||||||
|
@ -91,6 +91,7 @@
|
||||||
"worker-loader": "^3.0.8"
|
"worker-loader": "^3.0.8"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@astronautlabs/amf": "^0.0.6",
|
||||||
"@babel/polyfill": "^7.12.1",
|
"@babel/polyfill": "^7.12.1",
|
||||||
"@blu3r4y/lzma": "^2.3.3",
|
"@blu3r4y/lzma": "^2.3.3",
|
||||||
"arrive": "^2.4.1",
|
"arrive": "^2.4.1",
|
||||||
|
@ -139,6 +140,7 @@
|
||||||
"loglevel": "^1.8.0",
|
"loglevel": "^1.8.0",
|
||||||
"loglevel-message-prefix": "^3.0.0",
|
"loglevel-message-prefix": "^3.0.0",
|
||||||
"lz-string": "^1.4.4",
|
"lz-string": "^1.4.4",
|
||||||
|
"lz4js": "^0.2.0",
|
||||||
"markdown-it": "^13.0.1",
|
"markdown-it": "^13.0.1",
|
||||||
"moment": "^2.29.3",
|
"moment": "^2.29.3",
|
||||||
"moment-timezone": "^0.5.34",
|
"moment-timezone": "^0.5.34",
|
||||||
|
@ -155,6 +157,7 @@
|
||||||
"process": "^0.11.10",
|
"process": "^0.11.10",
|
||||||
"protobufjs": "^6.11.3",
|
"protobufjs": "^6.11.3",
|
||||||
"qr-image": "^3.2.0",
|
"qr-image": "^3.2.0",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
"scryptsy": "^2.1.0",
|
"scryptsy": "^2.1.0",
|
||||||
"snackbarjs": "^1.1.0",
|
"snackbarjs": "^1.1.0",
|
||||||
"sortablejs": "^1.15.0",
|
"sortablejs": "^1.15.0",
|
||||||
|
|
|
@ -27,6 +27,7 @@ class Ingredient {
|
||||||
this.toggleValues = [];
|
this.toggleValues = [];
|
||||||
this.target = null;
|
this.target = null;
|
||||||
this.defaultIndex = 0;
|
this.defaultIndex = 0;
|
||||||
|
this.maxLength = null;
|
||||||
this.min = null;
|
this.min = null;
|
||||||
this.max = null;
|
this.max = null;
|
||||||
this.step = 1;
|
this.step = 1;
|
||||||
|
@ -53,6 +54,7 @@ class Ingredient {
|
||||||
this.toggleValues = ingredientConfig.toggleValues;
|
this.toggleValues = ingredientConfig.toggleValues;
|
||||||
this.target = typeof ingredientConfig.target !== "undefined" ? ingredientConfig.target : null;
|
this.target = typeof ingredientConfig.target !== "undefined" ? ingredientConfig.target : null;
|
||||||
this.defaultIndex = typeof ingredientConfig.defaultIndex !== "undefined" ? ingredientConfig.defaultIndex : 0;
|
this.defaultIndex = typeof ingredientConfig.defaultIndex !== "undefined" ? ingredientConfig.defaultIndex : 0;
|
||||||
|
this.maxLength = ingredientConfig.maxLength || null;
|
||||||
this.min = ingredientConfig.min;
|
this.min = ingredientConfig.min;
|
||||||
this.max = ingredientConfig.max;
|
this.max = ingredientConfig.max;
|
||||||
this.step = ingredientConfig.step;
|
this.step = ingredientConfig.step;
|
||||||
|
|
|
@ -184,6 +184,7 @@ class Operation {
|
||||||
if (ing.disabled) conf.disabled = ing.disabled;
|
if (ing.disabled) conf.disabled = ing.disabled;
|
||||||
if (ing.target) conf.target = ing.target;
|
if (ing.target) conf.target = ing.target;
|
||||||
if (ing.defaultIndex) conf.defaultIndex = ing.defaultIndex;
|
if (ing.defaultIndex) conf.defaultIndex = ing.defaultIndex;
|
||||||
|
if (ing.maxLength) conf.maxLength = ing.maxLength;
|
||||||
if (typeof ing.min === "number") conf.min = ing.min;
|
if (typeof ing.min === "number") conf.min = ing.min;
|
||||||
if (typeof ing.max === "number") conf.max = ing.max;
|
if (typeof ing.max === "number") conf.max = ing.max;
|
||||||
if (ing.step) conf.step = ing.step;
|
if (ing.step) conf.step = ing.step;
|
||||||
|
|
|
@ -393,6 +393,70 @@ class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a byte array to an integer.
|
||||||
|
*
|
||||||
|
* @param {byteArray} byteArray
|
||||||
|
* @param {string} byteorder - "little" or "big"
|
||||||
|
* @returns {integer}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // returns 67305985
|
||||||
|
* Utils.byteArrayToInt([1, 2, 3, 4], "little");
|
||||||
|
*
|
||||||
|
* // returns 16909060
|
||||||
|
* Utils.byteArrayToInt([1, 2, 3, 4], "big");
|
||||||
|
*/
|
||||||
|
static byteArrayToInt(byteArray, byteorder) {
|
||||||
|
let value = 0;
|
||||||
|
if (byteorder === "big") {
|
||||||
|
for (let i = 0; i < byteArray.length; i++) {
|
||||||
|
value = (value * 256) + byteArray[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = byteArray.length - 1; i >= 0; i--) {
|
||||||
|
value = (value * 256) + byteArray[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an integer to a byte array of {length} bytes.
|
||||||
|
*
|
||||||
|
* @param {integer} value
|
||||||
|
* @param {integer} length
|
||||||
|
* @param {string} byteorder - "little" or "big"
|
||||||
|
* @returns {byteArray}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // returns [5, 255, 109, 1]
|
||||||
|
* Utils.intToByteArray(23985925, 4, "little");
|
||||||
|
*
|
||||||
|
* // returns [1, 109, 255, 5]
|
||||||
|
* Utils.intToByteArray(23985925, 4, "big");
|
||||||
|
*
|
||||||
|
* // returns [0, 0, 0, 0, 1, 109, 255, 5]
|
||||||
|
* Utils.intToByteArray(23985925, 8, "big");
|
||||||
|
*/
|
||||||
|
static intToByteArray(value, length, byteorder) {
|
||||||
|
const arr = new Array(length);
|
||||||
|
if (byteorder === "little") {
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
arr[i] = value & 0xFF;
|
||||||
|
value = value >>> 8;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = length - 1; i >= 0; i--) {
|
||||||
|
arr[i] = value & 0xFF;
|
||||||
|
value = value >>> 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a string to an ArrayBuffer.
|
* Converts a string to an ArrayBuffer.
|
||||||
* Treats the string as UTF-8 if any values are over 255.
|
* Treats the string as UTF-8 if any values are over 255.
|
||||||
|
|
|
@ -46,6 +46,8 @@
|
||||||
"From Quoted Printable",
|
"From Quoted Printable",
|
||||||
"To Punycode",
|
"To Punycode",
|
||||||
"From Punycode",
|
"From Punycode",
|
||||||
|
"AMF Encode",
|
||||||
|
"AMF Decode",
|
||||||
"To Hex Content",
|
"To Hex Content",
|
||||||
"From Hex Content",
|
"From Hex Content",
|
||||||
"PEM to Hex",
|
"PEM to Hex",
|
||||||
|
@ -85,6 +87,8 @@
|
||||||
"RC2 Decrypt",
|
"RC2 Decrypt",
|
||||||
"RC4",
|
"RC4",
|
||||||
"RC4 Drop",
|
"RC4 Drop",
|
||||||
|
"ChaCha",
|
||||||
|
"Rabbit",
|
||||||
"SM4 Encrypt",
|
"SM4 Encrypt",
|
||||||
"SM4 Decrypt",
|
"SM4 Decrypt",
|
||||||
"ROT13",
|
"ROT13",
|
||||||
|
@ -124,6 +128,8 @@
|
||||||
"JWT Decode",
|
"JWT Decode",
|
||||||
"Citrix CTX1 Encode",
|
"Citrix CTX1 Encode",
|
||||||
"Citrix CTX1 Decode",
|
"Citrix CTX1 Decode",
|
||||||
|
"AES Key Wrap",
|
||||||
|
"AES Key Unwrap",
|
||||||
"Pseudo-Random Number Generator",
|
"Pseudo-Random Number Generator",
|
||||||
"Enigma",
|
"Enigma",
|
||||||
"Bombe",
|
"Bombe",
|
||||||
|
@ -249,6 +255,7 @@
|
||||||
"To Table",
|
"To Table",
|
||||||
"Reverse",
|
"Reverse",
|
||||||
"Sort",
|
"Sort",
|
||||||
|
"Shuffle",
|
||||||
"Unique",
|
"Unique",
|
||||||
"Split",
|
"Split",
|
||||||
"Filter",
|
"Filter",
|
||||||
|
@ -333,7 +340,9 @@
|
||||||
"LZString Decompress",
|
"LZString Decompress",
|
||||||
"LZString Compress",
|
"LZString Compress",
|
||||||
"LZMA Decompress",
|
"LZMA Decompress",
|
||||||
"LZMA Compress"
|
"LZMA Compress",
|
||||||
|
"LZ4 Decompress",
|
||||||
|
"LZ4 Compress"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -365,6 +374,7 @@
|
||||||
"Compare SSDEEP hashes",
|
"Compare SSDEEP hashes",
|
||||||
"Compare CTPH hashes",
|
"Compare CTPH hashes",
|
||||||
"HMAC",
|
"HMAC",
|
||||||
|
"CMAC",
|
||||||
"Bcrypt",
|
"Bcrypt",
|
||||||
"Bcrypt compare",
|
"Bcrypt compare",
|
||||||
"Bcrypt parse",
|
"Bcrypt parse",
|
||||||
|
|
|
@ -136,7 +136,7 @@ const getFeature = function() {
|
||||||
|
|
||||||
fs.writeFileSync(path.join(process.cwd(), "CHANGELOG.md"), changelogData);
|
fs.writeFileSync(path.join(process.cwd(), "CHANGELOG.md"), changelogData);
|
||||||
|
|
||||||
console.log("Written CHANGELOG.md");
|
console.log("Written CHANGELOG.md\nCommit changes and then run `npm version minor`.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -105,13 +105,17 @@ export function fromHex(data, delim="Auto", byteLen=2) {
|
||||||
throw new OperationError("Byte length must be a positive integer");
|
throw new OperationError("Byte length must be a positive integer");
|
||||||
|
|
||||||
if (delim !== "None") {
|
if (delim !== "None") {
|
||||||
const delimRegex = delim === "Auto" ? /[^a-f\d]|(0x)/gi : Utils.regexRep(delim);
|
const delimRegex = delim === "Auto" ? /[^a-f\d]|0x/gi : Utils.regexRep(delim);
|
||||||
data = data.replace(delimRegex, "");
|
data = data.split(delimRegex);
|
||||||
|
} else {
|
||||||
|
data = [data];
|
||||||
}
|
}
|
||||||
|
|
||||||
const output = [];
|
const output = [];
|
||||||
for (let i = 0; i < data.length; i += byteLen) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
output.push(parseInt(data.substr(i, byteLen), 16));
|
for (let j = 0; j < data[i].length; j += byteLen) {
|
||||||
|
output.push(parseInt(data[i].substr(j, byteLen), 16));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,3 +103,15 @@ export function hexadecimalSort(a, b) {
|
||||||
|
|
||||||
return a.localeCompare(b);
|
return a.localeCompare(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comparison operation for sorting by length
|
||||||
|
*
|
||||||
|
* @param {string} a
|
||||||
|
* @param {string} b
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
export function lengthSort(a, b) {
|
||||||
|
return a.length - b.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
128
src/core/operations/AESKeyUnwrap.mjs
Normal file
128
src/core/operations/AESKeyUnwrap.mjs
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import { toHexFast } from "../lib/Hex.mjs";
|
||||||
|
import forge from "node-forge";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES Key Unwrap operation
|
||||||
|
*/
|
||||||
|
class AESKeyUnwrap extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AESKeyUnwrap constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "AES Key Unwrap";
|
||||||
|
this.module = "Ciphers";
|
||||||
|
this.description = "Decryptor for a key wrapping algorithm defined in RFC3394, which is used to protect keys in untrusted storage or communications, using AES.<br><br>This algorithm uses an AES key (KEK: key-encryption key) and a 64-bit IV to decrypt 64-bit blocks.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Key_wrap";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Key (KEK)",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "IV",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "a6a6a6a6a6a6a6a6",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Input",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Hex", "Raw"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Output",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Hex", "Raw"]
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const kek = Utils.convertToByteString(args[0].string, args[0].option),
|
||||||
|
iv = Utils.convertToByteString(args[1].string, args[1].option),
|
||||||
|
inputType = args[2],
|
||||||
|
outputType = args[3];
|
||||||
|
|
||||||
|
if (kek.length !== 16 && kek.length !== 24 && kek.length !== 32) {
|
||||||
|
throw new OperationError("KEK must be either 16, 24, or 32 bytes (currently " + kek.length + " bytes)");
|
||||||
|
}
|
||||||
|
if (iv.length !== 8) {
|
||||||
|
throw new OperationError("IV must be 8 bytes (currently " + iv.length + " bytes)");
|
||||||
|
}
|
||||||
|
const inputData = Utils.convertToByteString(input, inputType);
|
||||||
|
if (inputData.length % 8 !== 0 || inputData.length < 24) {
|
||||||
|
throw new OperationError("input must be 8n (n>=3) bytes (currently " + inputData.length + " bytes)");
|
||||||
|
}
|
||||||
|
|
||||||
|
const cipher = forge.cipher.createCipher("AES-ECB", kek);
|
||||||
|
cipher.start();
|
||||||
|
cipher.update(forge.util.createBuffer(""));
|
||||||
|
cipher.finish();
|
||||||
|
const paddingBlock = cipher.output.getBytes();
|
||||||
|
|
||||||
|
const decipher = forge.cipher.createDecipher("AES-ECB", kek);
|
||||||
|
|
||||||
|
let A = inputData.substring(0, 8);
|
||||||
|
const R = [];
|
||||||
|
for (let i = 8; i < inputData.length; i += 8) {
|
||||||
|
R.push(inputData.substring(i, i + 8));
|
||||||
|
}
|
||||||
|
let cntLower = R.length >>> 0;
|
||||||
|
let cntUpper = (R.length / ((1 << 30) * 4)) >>> 0;
|
||||||
|
cntUpper = cntUpper * 6 + ((cntLower * 6 / ((1 << 30) * 4)) >>> 0);
|
||||||
|
cntLower = cntLower * 6 >>> 0;
|
||||||
|
for (let j = 5; j >= 0; j--) {
|
||||||
|
for (let i = R.length - 1; i >= 0; i--) {
|
||||||
|
const aBuffer = Utils.strToArrayBuffer(A);
|
||||||
|
const aView = new DataView(aBuffer);
|
||||||
|
aView.setUint32(0, aView.getUint32(0) ^ cntUpper);
|
||||||
|
aView.setUint32(4, aView.getUint32(4) ^ cntLower);
|
||||||
|
A = Utils.arrayBufferToStr(aBuffer, false);
|
||||||
|
decipher.start();
|
||||||
|
decipher.update(forge.util.createBuffer(A + R[i] + paddingBlock));
|
||||||
|
decipher.finish();
|
||||||
|
const B = decipher.output.getBytes();
|
||||||
|
A = B.substring(0, 8);
|
||||||
|
R[i] = B.substring(8, 16);
|
||||||
|
cntLower--;
|
||||||
|
if (cntLower < 0) {
|
||||||
|
cntUpper--;
|
||||||
|
cntLower = 0xffffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (A !== iv) {
|
||||||
|
throw new OperationError("IV mismatch");
|
||||||
|
}
|
||||||
|
const P = R.join("");
|
||||||
|
|
||||||
|
if (outputType === "Hex") {
|
||||||
|
return toHexFast(Utils.strToArrayBuffer(P));
|
||||||
|
}
|
||||||
|
return P;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AESKeyUnwrap;
|
115
src/core/operations/AESKeyWrap.mjs
Normal file
115
src/core/operations/AESKeyWrap.mjs
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import { toHexFast } from "../lib/Hex.mjs";
|
||||||
|
import forge from "node-forge";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES Key Wrap operation
|
||||||
|
*/
|
||||||
|
class AESKeyWrap extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AESKeyWrap constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "AES Key Wrap";
|
||||||
|
this.module = "Ciphers";
|
||||||
|
this.description = "A key wrapping algorithm defined in RFC3394, which is used to protect keys in untrusted storage or communications, using AES.<br><br>This algorithm uses an AES key (KEK: key-encryption key) and a 64-bit IV to encrypt 64-bit blocks.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Key_wrap";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Key (KEK)",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "IV",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "a6a6a6a6a6a6a6a6",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Input",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Hex", "Raw"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Output",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Hex", "Raw"]
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const kek = Utils.convertToByteString(args[0].string, args[0].option),
|
||||||
|
iv = Utils.convertToByteString(args[1].string, args[1].option),
|
||||||
|
inputType = args[2],
|
||||||
|
outputType = args[3];
|
||||||
|
|
||||||
|
if (kek.length !== 16 && kek.length !== 24 && kek.length !== 32) {
|
||||||
|
throw new OperationError("KEK must be either 16, 24, or 32 bytes (currently " + kek.length + " bytes)");
|
||||||
|
}
|
||||||
|
if (iv.length !== 8) {
|
||||||
|
throw new OperationError("IV must be 8 bytes (currently " + iv.length + " bytes)");
|
||||||
|
}
|
||||||
|
const inputData = Utils.convertToByteString(input, inputType);
|
||||||
|
if (inputData.length % 8 !== 0 || inputData.length < 16) {
|
||||||
|
throw new OperationError("input must be 8n (n>=2) bytes (currently " + inputData.length + " bytes)");
|
||||||
|
}
|
||||||
|
|
||||||
|
const cipher = forge.cipher.createCipher("AES-ECB", kek);
|
||||||
|
|
||||||
|
let A = iv;
|
||||||
|
const R = [];
|
||||||
|
for (let i = 0; i < inputData.length; i += 8) {
|
||||||
|
R.push(inputData.substring(i, i + 8));
|
||||||
|
}
|
||||||
|
let cntLower = 1, cntUpper = 0;
|
||||||
|
for (let j = 0; j < 6; j++) {
|
||||||
|
for (let i = 0; i < R.length; i++) {
|
||||||
|
cipher.start();
|
||||||
|
cipher.update(forge.util.createBuffer(A + R[i]));
|
||||||
|
cipher.finish();
|
||||||
|
const B = cipher.output.getBytes();
|
||||||
|
const msbBuffer = Utils.strToArrayBuffer(B.substring(0, 8));
|
||||||
|
const msbView = new DataView(msbBuffer);
|
||||||
|
msbView.setUint32(0, msbView.getUint32(0) ^ cntUpper);
|
||||||
|
msbView.setUint32(4, msbView.getUint32(4) ^ cntLower);
|
||||||
|
A = Utils.arrayBufferToStr(msbBuffer, false);
|
||||||
|
R[i] = B.substring(8, 16);
|
||||||
|
cntLower++;
|
||||||
|
if (cntLower > 0xffffffff) {
|
||||||
|
cntUpper++;
|
||||||
|
cntLower = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const C = A + R.join("");
|
||||||
|
|
||||||
|
if (outputType === "Hex") {
|
||||||
|
return toHexFast(Utils.strToArrayBuffer(C));
|
||||||
|
}
|
||||||
|
return C;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AESKeyWrap;
|
52
src/core/operations/AMFDecode.mjs
Normal file
52
src/core/operations/AMFDecode.mjs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import "reflect-metadata"; // Required as a shim for the amf library
|
||||||
|
import { AMF0, AMF3 } from "@astronautlabs/amf";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMF Decode operation
|
||||||
|
*/
|
||||||
|
class AMFDecode extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMFDecode constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "AMF Decode";
|
||||||
|
this.module = "Encodings";
|
||||||
|
this.description = "Action Message Format (AMF) is a binary format used to serialize object graphs such as ActionScript objects and XML, or send messages between an Adobe Flash client and a remote service, usually a Flash Media Server or third party alternatives.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Action_Message_Format";
|
||||||
|
this.inputType = "ArrayBuffer";
|
||||||
|
this.outputType = "JSON";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Format",
|
||||||
|
type: "option",
|
||||||
|
value: ["AMF0", "AMF3"],
|
||||||
|
defaultIndex: 1
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {JSON}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const [format] = args;
|
||||||
|
const handler = format === "AMF0" ? AMF0 : AMF3;
|
||||||
|
const encoded = new Uint8Array(input);
|
||||||
|
return handler.Value.deserialize(encoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AMFDecode;
|
52
src/core/operations/AMFEncode.mjs
Normal file
52
src/core/operations/AMFEncode.mjs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import "reflect-metadata"; // Required as a shim for the amf library
|
||||||
|
import { AMF0, AMF3 } from "@astronautlabs/amf";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMF Encode operation
|
||||||
|
*/
|
||||||
|
class AMFEncode extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMFEncode constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "AMF Encode";
|
||||||
|
this.module = "Encodings";
|
||||||
|
this.description = "Action Message Format (AMF) is a binary format used to serialize object graphs such as ActionScript objects and XML, or send messages between an Adobe Flash client and a remote service, usually a Flash Media Server or third party alternatives.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Action_Message_Format";
|
||||||
|
this.inputType = "JSON";
|
||||||
|
this.outputType = "ArrayBuffer";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Format",
|
||||||
|
type: "option",
|
||||||
|
value: ["AMF0", "AMF3"],
|
||||||
|
defaultIndex: 1
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {JSON} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {ArrayBuffer}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const [format] = args;
|
||||||
|
const handler = format === "AMF0" ? AMF0 : AMF3;
|
||||||
|
const output = handler.Value.any(input).serialize();
|
||||||
|
return output.buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AMFEncode;
|
149
src/core/operations/CMAC.mjs
Normal file
149
src/core/operations/CMAC.mjs
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import forge from "node-forge";
|
||||||
|
import { toHexFast } from "../lib/Hex.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CMAC operation
|
||||||
|
*/
|
||||||
|
class CMAC extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CMAC constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "CMAC";
|
||||||
|
this.module = "Crypto";
|
||||||
|
this.description = "CMAC is a block-cipher based message authentication code algorithm.<br><br>RFC4493 defines AES-CMAC that uses AES encryption with a 128-bit key.<br>NIST SP 800-38B suggests usages of AES with other key lengths and Triple DES.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/CMAC";
|
||||||
|
this.inputType = "ArrayBuffer";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Key",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Encryption algorithm",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["AES", "Triple DES"]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const key = Utils.convertToByteString(args[0].string, args[0].option);
|
||||||
|
const algo = args[1];
|
||||||
|
|
||||||
|
const info = (function() {
|
||||||
|
switch (algo) {
|
||||||
|
case "AES":
|
||||||
|
if (key.length !== 16 && key.length !== 24 && key.length !== 32) {
|
||||||
|
throw new OperationError("The key for AES must be either 16, 24, or 32 bytes (currently " + key.length + " bytes)");
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
"algorithm": "AES-ECB",
|
||||||
|
"key": key,
|
||||||
|
"blockSize": 16,
|
||||||
|
"Rb": new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x87]),
|
||||||
|
};
|
||||||
|
case "Triple DES":
|
||||||
|
if (key.length !== 16 && key.length !== 24) {
|
||||||
|
throw new OperationError("The key for Triple DES must be 16 or 24 bytes (currently " + key.length + " bytes)");
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
"algorithm": "3DES-ECB",
|
||||||
|
"key": key.length === 16 ? key + key.substring(0, 8) : key,
|
||||||
|
"blockSize": 8,
|
||||||
|
"Rb": new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0x1b]),
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
throw new OperationError("Undefined encryption algorithm");
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
const xor = function(a, b, out) {
|
||||||
|
if (!out) out = new Uint8Array(a.length);
|
||||||
|
for (let i = 0; i < a.length; i++) {
|
||||||
|
out[i] = a[i] ^ b[i];
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
const leftShift1 = function(a) {
|
||||||
|
const out = new Uint8Array(a.length);
|
||||||
|
let carry = 0;
|
||||||
|
for (let i = a.length - 1; i >= 0; i--) {
|
||||||
|
out[i] = (a[i] << 1) | carry;
|
||||||
|
carry = a[i] >> 7;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
const cipher = forge.cipher.createCipher(info.algorithm, info.key);
|
||||||
|
const encrypt = function(a, out) {
|
||||||
|
if (!out) out = new Uint8Array(a.length);
|
||||||
|
cipher.start();
|
||||||
|
cipher.update(forge.util.createBuffer(a));
|
||||||
|
cipher.finish();
|
||||||
|
const cipherText = cipher.output.getBytes();
|
||||||
|
for (let i = 0; i < a.length; i++) {
|
||||||
|
out[i] = cipherText.charCodeAt(i);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
const L = encrypt(new Uint8Array(info.blockSize));
|
||||||
|
const K1 = leftShift1(L);
|
||||||
|
if (L[0] & 0x80) xor(K1, info.Rb, K1);
|
||||||
|
const K2 = leftShift1(K1);
|
||||||
|
if (K1[0] & 0x80) xor(K2, info.Rb, K2);
|
||||||
|
|
||||||
|
const n = Math.ceil(input.byteLength / info.blockSize);
|
||||||
|
const lastBlock = (function() {
|
||||||
|
if (n === 0) {
|
||||||
|
const data = new Uint8Array(K2);
|
||||||
|
data[0] ^= 0x80;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
const inputLast = new Uint8Array(input, info.blockSize * (n - 1));
|
||||||
|
if (inputLast.length === info.blockSize) {
|
||||||
|
return xor(inputLast, K1, inputLast);
|
||||||
|
} else {
|
||||||
|
const data = new Uint8Array(info.blockSize);
|
||||||
|
data.set(inputLast, 0);
|
||||||
|
data[inputLast.length] = 0x80;
|
||||||
|
return xor(data, K2, data);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
const X = new Uint8Array(info.blockSize);
|
||||||
|
const Y = new Uint8Array(info.blockSize);
|
||||||
|
for (let i = 0; i < n - 1; i++) {
|
||||||
|
xor(X, new Uint8Array(input, info.blockSize * i, info.blockSize), Y);
|
||||||
|
encrypt(Y, X);
|
||||||
|
}
|
||||||
|
xor(lastBlock, X, Y);
|
||||||
|
const T = encrypt(Y);
|
||||||
|
return toHexFast(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CMAC;
|
234
src/core/operations/ChaCha.mjs
Normal file
234
src/core/operations/ChaCha.mjs
Normal file
|
@ -0,0 +1,234 @@
|
||||||
|
/**
|
||||||
|
* @author joostrijneveld [joost@joostrijneveld.nl]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import { toHex } from "../lib/Hex.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the ChaCha block function
|
||||||
|
*
|
||||||
|
* @param {byteArray} key
|
||||||
|
* @param {byteArray} nonce
|
||||||
|
* @param {byteArray} counter
|
||||||
|
* @param {integer} rounds
|
||||||
|
* @returns {byteArray}
|
||||||
|
*/
|
||||||
|
function chacha(key, nonce, counter, rounds) {
|
||||||
|
const tau = "expand 16-byte k";
|
||||||
|
const sigma = "expand 32-byte k";
|
||||||
|
|
||||||
|
let state, c;
|
||||||
|
if (key.length === 16) {
|
||||||
|
c = Utils.strToByteArray(tau);
|
||||||
|
state = c.concat(key).concat(key);
|
||||||
|
} else {
|
||||||
|
c = Utils.strToByteArray(sigma);
|
||||||
|
state = c.concat(key);
|
||||||
|
}
|
||||||
|
state = state.concat(counter).concat(nonce);
|
||||||
|
|
||||||
|
const x = Array();
|
||||||
|
for (let i = 0; i < 64; i += 4) {
|
||||||
|
x.push(Utils.byteArrayToInt(state.slice(i, i + 4), "little"));
|
||||||
|
}
|
||||||
|
const a = [...x];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Macro to compute a 32-bit rotate-left operation
|
||||||
|
*
|
||||||
|
* @param {integer} x
|
||||||
|
* @param {integer} n
|
||||||
|
* @returns {integer}
|
||||||
|
*/
|
||||||
|
function ROL32(x, n) {
|
||||||
|
return ((x << n) & 0xFFFFFFFF) | (x >>> (32 - n));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Macro to compute a single ChaCha quarterround operation
|
||||||
|
*
|
||||||
|
* @param {integer} x
|
||||||
|
* @param {integer} a
|
||||||
|
* @param {integer} b
|
||||||
|
* @param {integer} c
|
||||||
|
* @param {integer} d
|
||||||
|
* @returns {integer}
|
||||||
|
*/
|
||||||
|
function quarterround(x, a, b, c, d) {
|
||||||
|
x[a] = ((x[a] + x[b]) & 0xFFFFFFFF); x[d] = ROL32(x[d] ^ x[a], 16);
|
||||||
|
x[c] = ((x[c] + x[d]) & 0xFFFFFFFF); x[b] = ROL32(x[b] ^ x[c], 12);
|
||||||
|
x[a] = ((x[a] + x[b]) & 0xFFFFFFFF); x[d] = ROL32(x[d] ^ x[a], 8);
|
||||||
|
x[c] = ((x[c] + x[d]) & 0xFFFFFFFF); x[b] = ROL32(x[b] ^ x[c], 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < rounds / 2; i++) {
|
||||||
|
quarterround(x, 0, 4, 8, 12);
|
||||||
|
quarterround(x, 1, 5, 9, 13);
|
||||||
|
quarterround(x, 2, 6, 10, 14);
|
||||||
|
quarterround(x, 3, 7, 11, 15);
|
||||||
|
quarterround(x, 0, 5, 10, 15);
|
||||||
|
quarterround(x, 1, 6, 11, 12);
|
||||||
|
quarterround(x, 2, 7, 8, 13);
|
||||||
|
quarterround(x, 3, 4, 9, 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < 16; i++) {
|
||||||
|
x[i] = (x[i] + a[i]) & 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = Array();
|
||||||
|
for (let i = 0; i < 16; i++) {
|
||||||
|
output = output.concat(Utils.intToByteArray(x[i], 4, "little"));
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ChaCha operation
|
||||||
|
*/
|
||||||
|
class ChaCha extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ChaCha constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "ChaCha";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "ChaCha is a stream cipher designed by Daniel J. Bernstein. It is a variant of the Salsa stream cipher. Several parameterizations exist; 'ChaCha' may refer to the original construction, or to the variant as described in RFC-8439. ChaCha is often used with Poly1305, in the ChaCha20-Poly1305 AEAD construction.<br><br><b>Key:</b> ChaCha uses a key of 16 or 32 bytes (128 or 256 bits).<br><br><b>Nonce:</b> ChaCha uses a nonce of 8 or 12 bytes (64 or 96 bits).<br><br><b>Counter:</b> ChaCha uses a counter of 4 or 8 bytes (32 or 64 bits); together, the nonce and counter must add up to 16 bytes. The counter starts at zero at the start of the keystream, and is incremented at every 64 bytes.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Salsa20#ChaCha_variant";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Key",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Nonce",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64", "Integer"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Counter",
|
||||||
|
"type": "number",
|
||||||
|
"value": 0,
|
||||||
|
"min": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Rounds",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["20", "12", "8"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Input",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Hex", "Raw"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Output",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Raw", "Hex"]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const key = Utils.convertToByteArray(args[0].string, args[0].option),
|
||||||
|
nonceType = args[1].option,
|
||||||
|
rounds = parseInt(args[3], 10),
|
||||||
|
inputType = args[4],
|
||||||
|
outputType = args[5];
|
||||||
|
|
||||||
|
if (key.length !== 16 && key.length !== 32) {
|
||||||
|
throw new OperationError(`Invalid key length: ${key.length} bytes.
|
||||||
|
|
||||||
|
ChaCha uses a key of 16 or 32 bytes (128 or 256 bits).`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let counter, nonce, counterLength;
|
||||||
|
if (nonceType === "Integer") {
|
||||||
|
nonce = Utils.intToByteArray(parseInt(args[1].string, 10), 12, "little");
|
||||||
|
counterLength = 4;
|
||||||
|
} else {
|
||||||
|
nonce = Utils.convertToByteArray(args[1].string, args[1].option);
|
||||||
|
if (!(nonce.length === 12 || nonce.length === 8)) {
|
||||||
|
throw new OperationError(`Invalid nonce length: ${nonce.length} bytes.
|
||||||
|
|
||||||
|
ChaCha uses a nonce of 8 or 12 bytes (64 or 96 bits).`);
|
||||||
|
}
|
||||||
|
counterLength = 16 - nonce.length;
|
||||||
|
}
|
||||||
|
counter = Utils.intToByteArray(args[2], counterLength, "little");
|
||||||
|
|
||||||
|
const output = [];
|
||||||
|
input = Utils.convertToByteArray(input, inputType);
|
||||||
|
|
||||||
|
let counterAsInt = Utils.byteArrayToInt(counter, "little");
|
||||||
|
for (let i = 0; i < input.length; i += 64) {
|
||||||
|
counter = Utils.intToByteArray(counterAsInt, counterLength, "little");
|
||||||
|
const stream = chacha(key, nonce, counter, rounds);
|
||||||
|
for (let j = 0; j < 64 && i + j < input.length; j++) {
|
||||||
|
output.push(input[i + j] ^ stream[j]);
|
||||||
|
}
|
||||||
|
counterAsInt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outputType === "Hex") {
|
||||||
|
return toHex(output);
|
||||||
|
} else {
|
||||||
|
return Utils.arrayBufferToStr(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlight ChaCha
|
||||||
|
*
|
||||||
|
* @param {Object[]} pos
|
||||||
|
* @param {number} pos[].start
|
||||||
|
* @param {number} pos[].end
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {Object[]} pos
|
||||||
|
*/
|
||||||
|
highlight(pos, args) {
|
||||||
|
const inputType = args[4],
|
||||||
|
outputType = args[5];
|
||||||
|
if (inputType === "Raw" && outputType === "Raw") {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlight ChaCha in reverse
|
||||||
|
*
|
||||||
|
* @param {Object[]} pos
|
||||||
|
* @param {number} pos[].start
|
||||||
|
* @param {number} pos[].end
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {Object[]} pos
|
||||||
|
*/
|
||||||
|
highlightReverse(pos, args) {
|
||||||
|
const inputType = args[4],
|
||||||
|
outputType = args[5];
|
||||||
|
if (inputType === "Raw" && outputType === "Raw") {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ChaCha;
|
|
@ -35,10 +35,18 @@ class Fletcher32Checksum extends Operation {
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
let a = 0,
|
let a = 0,
|
||||||
b = 0;
|
b = 0;
|
||||||
input = new Uint8Array(input);
|
if (ArrayBuffer.isView(input)) {
|
||||||
|
input = new DataView(input.buffer, input.byteOffset, input.byteLength);
|
||||||
|
} else {
|
||||||
|
input = new DataView(input);
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.byteLength - 1; i += 2) {
|
||||||
a = (a + input[i]) % 0xffff;
|
a = (a + input.getUint16(i, true)) % 0xffff;
|
||||||
|
b = (b + a) % 0xffff;
|
||||||
|
}
|
||||||
|
if (input.byteLength % 2 !== 0) {
|
||||||
|
a = (a + input.getUint8(input.byteLength - 1)) % 0xffff;
|
||||||
b = (b + a) % 0xffff;
|
b = (b + a) % 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,22 @@ class Fletcher64Checksum extends Operation {
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
let a = 0,
|
let a = 0,
|
||||||
b = 0;
|
b = 0;
|
||||||
input = new Uint8Array(input);
|
if (ArrayBuffer.isView(input)) {
|
||||||
|
input = new DataView(input.buffer, input.byteOffset, input.byteLength);
|
||||||
|
} else {
|
||||||
|
input = new DataView(input);
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.byteLength - 3; i += 4) {
|
||||||
a = (a + input[i]) % 0xffffffff;
|
a = (a + input.getUint32(i, true)) % 0xffffffff;
|
||||||
|
b = (b + a) % 0xffffffff;
|
||||||
|
}
|
||||||
|
if (input.byteLength % 4 !== 0) {
|
||||||
|
let lastValue = 0;
|
||||||
|
for (let i = 0; i < input.byteLength % 4; i++) {
|
||||||
|
lastValue = (lastValue << 8) | input.getUint8(input.byteLength - 1 - i);
|
||||||
|
}
|
||||||
|
a = (a + lastValue) % 0xffffffff;
|
||||||
b = (b + a) % 0xffffffff;
|
b = (b + a) % 0xffffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import {alphabetName, ALPHABET_OPTIONS} from "../lib/Base85.mjs";
|
import {ALPHABET_OPTIONS} from "../lib/Base85.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* From Base85 operation
|
* From Base85 operation
|
||||||
|
@ -37,6 +37,12 @@ class FromBase85 extends Operation {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: true
|
value: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "All-zero group char",
|
||||||
|
type: "binaryShortString",
|
||||||
|
value: "z",
|
||||||
|
maxLength: 1
|
||||||
|
}
|
||||||
];
|
];
|
||||||
this.checks = [
|
this.checks = [
|
||||||
{
|
{
|
||||||
|
@ -76,8 +82,8 @@ class FromBase85 extends Operation {
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const alphabet = Utils.expandAlphRange(args[0]).join(""),
|
const alphabet = Utils.expandAlphRange(args[0]).join(""),
|
||||||
encoding = alphabetName(alphabet),
|
|
||||||
removeNonAlphChars = args[1],
|
removeNonAlphChars = args[1],
|
||||||
|
allZeroGroupChar = typeof args[2] === "string" ? args[2].slice(0, 1) : "",
|
||||||
result = [];
|
result = [];
|
||||||
|
|
||||||
if (alphabet.length !== 85 ||
|
if (alphabet.length !== 85 ||
|
||||||
|
@ -85,14 +91,21 @@ class FromBase85 extends Operation {
|
||||||
throw new OperationError("Alphabet must be of length 85");
|
throw new OperationError("Alphabet must be of length 85");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allZeroGroupChar && alphabet.includes(allZeroGroupChar)) {
|
||||||
|
throw new OperationError("The all-zero group char cannot appear in the alphabet");
|
||||||
|
}
|
||||||
|
|
||||||
// Remove delimiters if present
|
// Remove delimiters if present
|
||||||
const matches = input.match(/^<~(.+?)~>$/);
|
const matches = input.match(/^<~(.+?)~>$/);
|
||||||
if (matches !== null) input = matches[1];
|
if (matches !== null) input = matches[1];
|
||||||
|
|
||||||
// Remove non-alphabet characters
|
// Remove non-alphabet characters
|
||||||
if (removeNonAlphChars) {
|
if (removeNonAlphChars) {
|
||||||
const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
|
const re = new RegExp("[^~" + allZeroGroupChar +alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
|
||||||
input = input.replace(re, "");
|
input = input.replace(re, "");
|
||||||
|
// Remove delimiters again if present (incase of non-alphabet characters in front/behind delimiters)
|
||||||
|
const matches = input.match(/^<~(.+?)~>$/);
|
||||||
|
if (matches !== null) input = matches[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.length === 0) return [];
|
if (input.length === 0) return [];
|
||||||
|
@ -100,7 +113,7 @@ class FromBase85 extends Operation {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let block, blockBytes;
|
let block, blockBytes;
|
||||||
while (i < input.length) {
|
while (i < input.length) {
|
||||||
if (encoding === "Standard" && input[i] === "z") {
|
if (input[i] === allZeroGroupChar) {
|
||||||
result.push(0, 0, 0, 0);
|
result.push(0, 0, 0, 0);
|
||||||
i++;
|
i++;
|
||||||
} else {
|
} else {
|
||||||
|
@ -110,7 +123,7 @@ class FromBase85 extends Operation {
|
||||||
.split("")
|
.split("")
|
||||||
.map((chr, idx) => {
|
.map((chr, idx) => {
|
||||||
const digit = alphabet.indexOf(chr);
|
const digit = alphabet.indexOf(chr);
|
||||||
if (digit < 0 || digit > 84) {
|
if ((digit < 0 || digit > 84) && chr !== allZeroGroupChar) {
|
||||||
throw `Invalid character '${chr}' at index ${i + idx}`;
|
throw `Invalid character '${chr}' at index ${i + idx}`;
|
||||||
}
|
}
|
||||||
return digit;
|
return digit;
|
||||||
|
|
|
@ -44,7 +44,7 @@ class GenerateQRCode extends Operation {
|
||||||
{
|
{
|
||||||
"name": "Margin (num modules)",
|
"name": "Margin (num modules)",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"value": 2,
|
"value": 4,
|
||||||
"min": 0
|
"min": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
43
src/core/operations/LZ4Compress.mjs
Normal file
43
src/core/operations/LZ4Compress.mjs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import lz4 from "lz4js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LZ4 Compress operation
|
||||||
|
*/
|
||||||
|
class LZ4Compress extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LZ4Compress constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "LZ4 Compress";
|
||||||
|
this.module = "Compression";
|
||||||
|
this.description = "LZ4 is a lossless data compression algorithm that is focused on compression and decompression speed. It belongs to the LZ77 family of byte-oriented compression schemes.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/LZ4_(compression_algorithm)";
|
||||||
|
this.inputType = "ArrayBuffer";
|
||||||
|
this.outputType = "ArrayBuffer";
|
||||||
|
this.args = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {ArrayBuffer}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const inBuf = new Uint8Array(input);
|
||||||
|
const compressed = lz4.compress(inBuf);
|
||||||
|
return compressed.buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LZ4Compress;
|
43
src/core/operations/LZ4Decompress.mjs
Normal file
43
src/core/operations/LZ4Decompress.mjs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import lz4 from "lz4js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LZ4 Decompress operation
|
||||||
|
*/
|
||||||
|
class LZ4Decompress extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LZ4Decompress constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "LZ4 Decompress";
|
||||||
|
this.module = "Compression";
|
||||||
|
this.description = "LZ4 is a lossless data compression algorithm that is focused on compression and decompression speed. It belongs to the LZ77 family of byte-oriented compression schemes.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/LZ4_(compression_algorithm)";
|
||||||
|
this.inputType = "ArrayBuffer";
|
||||||
|
this.outputType = "ArrayBuffer";
|
||||||
|
this.args = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {ArrayBuffer}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const inBuf = new Uint8Array(input);
|
||||||
|
const decompressed = lz4.decompress(inBuf);
|
||||||
|
return decompressed.buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LZ4Decompress;
|
|
@ -45,8 +45,8 @@ class ParseASN1HexString extends Operation {
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const [index, truncateLen] = args;
|
const [index, truncateLen] = args;
|
||||||
return r.ASN1HEX.dump(input.replace(/\s/g, ""), {
|
return r.ASN1HEX.dump(input.replace(/\s/g, "").toLowerCase(), {
|
||||||
"ommitLongOctet": truncateLen
|
"ommit_long_octet": truncateLen
|
||||||
}, index);
|
}, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,23 +57,29 @@ class ParseX509Certificate extends Operation {
|
||||||
const cert = new r.X509(),
|
const cert = new r.X509(),
|
||||||
inputFormat = args[0];
|
inputFormat = args[0];
|
||||||
|
|
||||||
switch (inputFormat) {
|
let undefinedInputFormat = false;
|
||||||
case "DER Hex":
|
try {
|
||||||
input = input.replace(/\s/g, "");
|
switch (inputFormat) {
|
||||||
cert.readCertHex(input);
|
case "DER Hex":
|
||||||
break;
|
input = input.replace(/\s/g, "").toLowerCase();
|
||||||
case "PEM":
|
cert.readCertHex(input);
|
||||||
cert.readCertPEM(input);
|
break;
|
||||||
break;
|
case "PEM":
|
||||||
case "Base64":
|
cert.readCertPEM(input);
|
||||||
cert.readCertHex(toHex(fromBase64(input, null, "byteArray"), ""));
|
break;
|
||||||
break;
|
case "Base64":
|
||||||
case "Raw":
|
cert.readCertHex(toHex(fromBase64(input, null, "byteArray"), ""));
|
||||||
cert.readCertHex(toHex(Utils.strToByteArray(input), ""));
|
break;
|
||||||
break;
|
case "Raw":
|
||||||
default:
|
cert.readCertHex(toHex(Utils.strToByteArray(input), ""));
|
||||||
throw "Undefined input format";
|
break;
|
||||||
|
default:
|
||||||
|
undefinedInputFormat = true;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
throw "Certificate load error (non-certificate input?)";
|
||||||
}
|
}
|
||||||
|
if (undefinedInputFormat) throw "Undefined input format";
|
||||||
|
|
||||||
const sn = cert.getSerialNumberHex(),
|
const sn = cert.getSerialNumberHex(),
|
||||||
issuer = cert.getIssuer(),
|
issuer = cert.getIssuer(),
|
||||||
|
|
|
@ -52,8 +52,12 @@ class PseudoRandomNumberGenerator extends Operation {
|
||||||
let bytes;
|
let bytes;
|
||||||
|
|
||||||
if (isWorkerEnvironment() && self.crypto) {
|
if (isWorkerEnvironment() && self.crypto) {
|
||||||
bytes = self.crypto.getRandomValues(new Uint8Array(numBytes));
|
bytes = new ArrayBuffer(numBytes);
|
||||||
bytes = Utils.arrayBufferToStr(bytes.buffer);
|
const CHUNK_SIZE = 65536;
|
||||||
|
for (let i = 0; i < numBytes; i += CHUNK_SIZE) {
|
||||||
|
self.crypto.getRandomValues(new Uint8Array(bytes, i, Math.min(numBytes - i, CHUNK_SIZE)));
|
||||||
|
}
|
||||||
|
bytes = Utils.arrayBufferToStr(bytes);
|
||||||
} else {
|
} else {
|
||||||
bytes = forge.random.getBytesSync(numBytes);
|
bytes = forge.random.getBytesSync(numBytes);
|
||||||
}
|
}
|
||||||
|
|
247
src/core/operations/Rabbit.mjs
Normal file
247
src/core/operations/Rabbit.mjs
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import { toHexFast } from "../lib/Hex.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rabbit operation
|
||||||
|
*/
|
||||||
|
class Rabbit extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rabbit constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "Rabbit";
|
||||||
|
this.module = "Ciphers";
|
||||||
|
this.description = "Rabbit is a high-speed stream cipher introduced in 2003 and defined in RFC 4503.<br><br>The cipher uses a 128-bit key and an optional 64-bit initialization vector (IV).<br><br>big-endian: based on RFC4503 and RFC3447<br>little-endian: compatible with Crypto++";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Rabbit_(cipher)";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Key",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "IV",
|
||||||
|
"type": "toggleString",
|
||||||
|
"value": "",
|
||||||
|
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Endianness",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Big", "Little"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Input",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Raw", "Hex"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Output",
|
||||||
|
"type": "option",
|
||||||
|
"value": ["Raw", "Hex"]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const key = Utils.convertToByteArray(args[0].string, args[0].option),
|
||||||
|
iv = Utils.convertToByteArray(args[1].string, args[1].option),
|
||||||
|
endianness = args[2],
|
||||||
|
inputType = args[3],
|
||||||
|
outputType = args[4];
|
||||||
|
|
||||||
|
const littleEndian = endianness === "Little";
|
||||||
|
|
||||||
|
if (key.length !== 16) {
|
||||||
|
throw new OperationError(`Invalid key length: ${key.length} bytes (expected: 16)`);
|
||||||
|
}
|
||||||
|
if (iv.length !== 0 && iv.length !== 8) {
|
||||||
|
throw new OperationError(`Invalid IV length: ${iv.length} bytes (expected: 0 or 8)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inner State
|
||||||
|
const X = new Uint32Array(8), C = new Uint32Array(8);
|
||||||
|
let b = 0;
|
||||||
|
|
||||||
|
// Counter System
|
||||||
|
const A = [
|
||||||
|
0x4d34d34d, 0xd34d34d3, 0x34d34d34, 0x4d34d34d,
|
||||||
|
0xd34d34d3, 0x34d34d34, 0x4d34d34d, 0xd34d34d3
|
||||||
|
];
|
||||||
|
const counterUpdate = function() {
|
||||||
|
for (let j = 0; j < 8; j++) {
|
||||||
|
const temp = C[j] + A[j] + b;
|
||||||
|
b = (temp / ((1 << 30) * 4)) >>> 0;
|
||||||
|
C[j] = temp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Next-State Function
|
||||||
|
const g = function(u, v) {
|
||||||
|
const uv = (u + v) >>> 0;
|
||||||
|
const upper = uv >>> 16, lower = uv & 0xffff;
|
||||||
|
const upperUpper = upper * upper;
|
||||||
|
const upperLower2 = 2 * upper * lower;
|
||||||
|
const lowerLower = lower * lower;
|
||||||
|
const mswTemp = upperUpper + ((upperLower2 / (1 << 16)) >>> 0);
|
||||||
|
const lswTemp = lowerLower + (upperLower2 & 0xffff) * (1 << 16);
|
||||||
|
const msw = mswTemp + ((lswTemp / ((1 << 30) * 4)) >>> 0);
|
||||||
|
const lsw = lswTemp >>> 0;
|
||||||
|
return lsw ^ msw;
|
||||||
|
};
|
||||||
|
const leftRotate = function(value, width) {
|
||||||
|
return (value << width) | (value >>> (32 - width));
|
||||||
|
};
|
||||||
|
const nextStateHelper1 = function(v0, v1, v2) {
|
||||||
|
return v0 + leftRotate(v1, 16) + leftRotate(v2, 16);
|
||||||
|
};
|
||||||
|
const nextStateHelper2 = function(v0, v1, v2) {
|
||||||
|
return v0 + leftRotate(v1, 8) + v2;
|
||||||
|
};
|
||||||
|
const G = new Uint32Array(8);
|
||||||
|
const nextState = function() {
|
||||||
|
for (let j = 0; j < 8; j++) {
|
||||||
|
G[j] = g(X[j], C[j]);
|
||||||
|
}
|
||||||
|
X[0] = nextStateHelper1(G[0], G[7], G[6]);
|
||||||
|
X[1] = nextStateHelper2(G[1], G[0], G[7]);
|
||||||
|
X[2] = nextStateHelper1(G[2], G[1], G[0]);
|
||||||
|
X[3] = nextStateHelper2(G[3], G[2], G[1]);
|
||||||
|
X[4] = nextStateHelper1(G[4], G[3], G[2]);
|
||||||
|
X[5] = nextStateHelper2(G[5], G[4], G[3]);
|
||||||
|
X[6] = nextStateHelper1(G[6], G[5], G[4]);
|
||||||
|
X[7] = nextStateHelper2(G[7], G[6], G[5]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Key Setup Scheme
|
||||||
|
const K = new Uint16Array(8);
|
||||||
|
if (littleEndian) {
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
K[i] = (key[1 + 2 * i] << 8) | key[2 * i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
K[i] = (key[14 - 2 * i] << 8) | key[15 - 2 * i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let j = 0; j < 8; j++) {
|
||||||
|
if (j % 2 === 0) {
|
||||||
|
X[j] = (K[(j + 1) % 8] << 16) | K[j];
|
||||||
|
C[j] = (K[(j + 4) % 8] << 16) | K[(j + 5) % 8];
|
||||||
|
} else {
|
||||||
|
X[j] = (K[(j + 5) % 8] << 16) | K[(j + 4) % 8];
|
||||||
|
C[j] = (K[j] << 16) | K[(j + 1) % 8];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
counterUpdate();
|
||||||
|
nextState();
|
||||||
|
}
|
||||||
|
for (let j = 0; j < 8; j++) {
|
||||||
|
C[j] = C[j] ^ X[(j + 4) % 8];
|
||||||
|
}
|
||||||
|
|
||||||
|
// IV Setup Scheme
|
||||||
|
if (iv.length === 8) {
|
||||||
|
const getIVValue = function(a, b, c, d) {
|
||||||
|
if (littleEndian) {
|
||||||
|
return (iv[a] << 24) | (iv[b] << 16) |
|
||||||
|
(iv[c] << 8) | iv[d];
|
||||||
|
} else {
|
||||||
|
return (iv[7 - a] << 24) | (iv[7 - b] << 16) |
|
||||||
|
(iv[7 - c] << 8) | iv[7 - d];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
C[0] = C[0] ^ getIVValue(3, 2, 1, 0);
|
||||||
|
C[1] = C[1] ^ getIVValue(7, 6, 3, 2);
|
||||||
|
C[2] = C[2] ^ getIVValue(7, 6, 5, 4);
|
||||||
|
C[3] = C[3] ^ getIVValue(5, 4, 1, 0);
|
||||||
|
C[4] = C[4] ^ getIVValue(3, 2, 1, 0);
|
||||||
|
C[5] = C[5] ^ getIVValue(7, 6, 3, 2);
|
||||||
|
C[6] = C[6] ^ getIVValue(7, 6, 5, 4);
|
||||||
|
C[7] = C[7] ^ getIVValue(5, 4, 1, 0);
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
counterUpdate();
|
||||||
|
nextState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extraction Scheme
|
||||||
|
const S = new Uint8Array(16);
|
||||||
|
const extract = function() {
|
||||||
|
let pos = 0;
|
||||||
|
const addPart = function(value) {
|
||||||
|
S[pos++] = value >>> 8;
|
||||||
|
S[pos++] = value & 0xff;
|
||||||
|
};
|
||||||
|
counterUpdate();
|
||||||
|
nextState();
|
||||||
|
addPart((X[6] >>> 16) ^ (X[1] & 0xffff));
|
||||||
|
addPart((X[6] & 0xffff) ^ (X[3] >>> 16));
|
||||||
|
addPart((X[4] >>> 16) ^ (X[7] & 0xffff));
|
||||||
|
addPart((X[4] & 0xffff) ^ (X[1] >>> 16));
|
||||||
|
addPart((X[2] >>> 16) ^ (X[5] & 0xffff));
|
||||||
|
addPart((X[2] & 0xffff) ^ (X[7] >>> 16));
|
||||||
|
addPart((X[0] >>> 16) ^ (X[3] & 0xffff));
|
||||||
|
addPart((X[0] & 0xffff) ^ (X[5] >>> 16));
|
||||||
|
if (littleEndian) {
|
||||||
|
for (let i = 0, j = S.length - 1; i < j;) {
|
||||||
|
const temp = S[i];
|
||||||
|
S[i] = S[j];
|
||||||
|
S[j] = temp;
|
||||||
|
i++;
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const data = Utils.convertToByteString(input, inputType);
|
||||||
|
const result = new Uint8Array(data.length);
|
||||||
|
for (let i = 0; i <= data.length - 16; i += 16) {
|
||||||
|
extract();
|
||||||
|
for (let j = 0; j < 16; j++) {
|
||||||
|
result[i + j] = data.charCodeAt(i + j) ^ S[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data.length % 16 !== 0) {
|
||||||
|
const offset = data.length - data.length % 16;
|
||||||
|
const length = data.length - offset;
|
||||||
|
extract();
|
||||||
|
if (littleEndian) {
|
||||||
|
for (let j = 0; j < length; j++) {
|
||||||
|
result[offset + j] = data.charCodeAt(offset + j) ^ S[j];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let j = 0; j < length; j++) {
|
||||||
|
result[offset + j] = data.charCodeAt(offset + j) ^ S[16 - length + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outputType === "Hex") {
|
||||||
|
return toHexFast(result);
|
||||||
|
}
|
||||||
|
return Utils.byteArrayToChars(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Rabbit;
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse operation
|
* Reverse operation
|
||||||
|
@ -26,7 +27,8 @@ class Reverse extends Operation {
|
||||||
{
|
{
|
||||||
"name": "By",
|
"name": "By",
|
||||||
"type": "option",
|
"type": "option",
|
||||||
"value": ["Character", "Line"]
|
"value": ["Byte", "Character", "Line"],
|
||||||
|
"defaultIndex": 1
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -57,6 +59,24 @@ class Reverse extends Operation {
|
||||||
result.push(0x0a);
|
result.push(0x0a);
|
||||||
}
|
}
|
||||||
return result.slice(0, input.length);
|
return result.slice(0, input.length);
|
||||||
|
} else if (args[0] === "Character") {
|
||||||
|
const inputString = Utils.byteArrayToUtf8(input);
|
||||||
|
let result = "";
|
||||||
|
for (let i = inputString.length - 1; i >= 0; i--) {
|
||||||
|
const c = inputString.charCodeAt(i);
|
||||||
|
if (i > 0 && 0xdc00 <= c && c <= 0xdfff) {
|
||||||
|
const c2 = inputString.charCodeAt(i - 1);
|
||||||
|
if (0xd800 <= c2 && c2 <= 0xdbff) {
|
||||||
|
// surrogates
|
||||||
|
result += inputString.charAt(i - 1);
|
||||||
|
result += inputString.charAt(i);
|
||||||
|
i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result += inputString.charAt(i);
|
||||||
|
}
|
||||||
|
return Utils.strToUtf8ByteArray(result);
|
||||||
} else {
|
} else {
|
||||||
return input.reverse();
|
return input.reverse();
|
||||||
}
|
}
|
||||||
|
|
78
src/core/operations/Shuffle.mjs
Normal file
78
src/core/operations/Shuffle.mjs
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuffle operation
|
||||||
|
*/
|
||||||
|
class Shuffle extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuffle constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "Shuffle";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Randomly reorders input elements.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Shuffling";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Delimiter",
|
||||||
|
type: "option",
|
||||||
|
value: INPUT_DELIM_OPTIONS
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const delim = Utils.charRep(args[0]);
|
||||||
|
if (input.length === 0) return input;
|
||||||
|
|
||||||
|
// return a random number in [0, 1)
|
||||||
|
const rng = (typeof crypto) !== "undefined" && crypto.getRandomValues ? (function() {
|
||||||
|
const buf = new Uint32Array(2);
|
||||||
|
return function() {
|
||||||
|
// generate 53-bit random integer: 21 + 32 bits
|
||||||
|
crypto.getRandomValues(buf);
|
||||||
|
const value = (buf[0] >>> (32 - 21)) * ((1 << 30) * 4) + buf[1];
|
||||||
|
return value / ((1 << 23) * (1 << 30));
|
||||||
|
};
|
||||||
|
})() : Math.random;
|
||||||
|
|
||||||
|
// return a random integer in [0, max)
|
||||||
|
const randint = function(max) {
|
||||||
|
return Math.floor(rng() * max);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Split input into shuffleable sections
|
||||||
|
const toShuffle = input.split(delim);
|
||||||
|
|
||||||
|
// shuffle elements
|
||||||
|
for (let i = toShuffle.length - 1; i > 0; i--) {
|
||||||
|
const idx = randint(i + 1);
|
||||||
|
const tmp = toShuffle[idx];
|
||||||
|
toShuffle[idx] = toShuffle[i];
|
||||||
|
toShuffle[i] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return toShuffle.join(delim);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Shuffle;
|
|
@ -7,7 +7,7 @@
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs";
|
import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs";
|
||||||
import {caseInsensitiveSort, ipSort, numericSort, hexadecimalSort} from "../lib/Sort.mjs";
|
import {caseInsensitiveSort, ipSort, numericSort, hexadecimalSort, lengthSort} from "../lib/Sort.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort operation
|
* Sort operation
|
||||||
|
@ -39,7 +39,7 @@ class Sort extends Operation {
|
||||||
{
|
{
|
||||||
"name": "Order",
|
"name": "Order",
|
||||||
"type": "option",
|
"type": "option",
|
||||||
"value": ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric", "Numeric (hexadecimal)"]
|
"value": ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric", "Numeric (hexadecimal)", "Length"]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,8 @@ class Sort extends Operation {
|
||||||
sorted = sorted.sort(numericSort);
|
sorted = sorted.sort(numericSort);
|
||||||
} else if (order === "Numeric (hexadecimal)") {
|
} else if (order === "Numeric (hexadecimal)") {
|
||||||
sorted = sorted.sort(hexadecimalSort);
|
sorted = sorted.sort(hexadecimalSort);
|
||||||
|
} else if (order === "Length") {
|
||||||
|
sorted = sorted.sort(lengthSort);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sortReverse) sorted.reverse();
|
if (sortReverse) sorted.reverse();
|
||||||
|
|
|
@ -34,10 +34,50 @@ class Substitute extends Operation {
|
||||||
"name": "Ciphertext",
|
"name": "Ciphertext",
|
||||||
"type": "binaryString",
|
"type": "binaryString",
|
||||||
"value": "XYZABCDEFGHIJKLMNOPQRSTUVW"
|
"value": "XYZABCDEFGHIJKLMNOPQRSTUVW"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ignore case",
|
||||||
|
"type": "boolean",
|
||||||
|
"value": false
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a single character using the dictionary, if ignoreCase is true then
|
||||||
|
* check in the dictionary for both upper and lower case versions of the character.
|
||||||
|
* In output the input character case is preserved.
|
||||||
|
* @param {string} char
|
||||||
|
* @param {Object} dict
|
||||||
|
* @param {boolean} ignoreCase
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
cipherSingleChar(char, dict, ignoreCase) {
|
||||||
|
if (!ignoreCase)
|
||||||
|
return dict[char] || char;
|
||||||
|
|
||||||
|
const isUpperCase = char === char.toUpperCase();
|
||||||
|
|
||||||
|
// convert using the dictionary keeping the case of the input character
|
||||||
|
|
||||||
|
if (dict[char] !== undefined) {
|
||||||
|
// if the character is in the dictionary return the value with the input case
|
||||||
|
return isUpperCase ? dict[char].toUpperCase() : dict[char].toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for the other case, if it is in the dictionary return the value with the right case
|
||||||
|
if (isUpperCase) {
|
||||||
|
if (dict[char.toLowerCase()] !== undefined)
|
||||||
|
return dict[char.toLowerCase()].toUpperCase();
|
||||||
|
} else {
|
||||||
|
if (dict[char.toUpperCase()] !== undefined)
|
||||||
|
return dict[char.toUpperCase()].toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
return char;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} input
|
* @param {string} input
|
||||||
* @param {Object[]} args
|
* @param {Object[]} args
|
||||||
|
@ -45,17 +85,23 @@ class Substitute extends Operation {
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const plaintext = Utils.expandAlphRange([...args[0]]),
|
const plaintext = Utils.expandAlphRange([...args[0]]),
|
||||||
ciphertext = Utils.expandAlphRange([...args[1]]);
|
ciphertext = Utils.expandAlphRange([...args[1]]),
|
||||||
let output = "",
|
ignoreCase = args[2];
|
||||||
index = -1;
|
let output = "";
|
||||||
|
|
||||||
if (plaintext.length !== ciphertext.length) {
|
if (plaintext.length !== ciphertext.length) {
|
||||||
output = "Warning: Plaintext and Ciphertext lengths differ\n\n";
|
output = "Warning: Plaintext and Ciphertext lengths differ\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create dictionary for conversion
|
||||||
|
const dict = {};
|
||||||
|
for (let i = 0; i < Math.min(ciphertext.length, plaintext.length); i++) {
|
||||||
|
dict[plaintext[i]] = ciphertext[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// map every letter with the conversion function
|
||||||
for (const character of input) {
|
for (const character of input) {
|
||||||
index = plaintext.indexOf(character);
|
output += this.cipherSingleChar(character, dict, ignoreCase);
|
||||||
output += index > -1 && index < ciphertext.length ? ciphertext[index] : character;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
|
|
|
@ -20,7 +20,7 @@ class ToTable extends Operation {
|
||||||
|
|
||||||
this.name = "To Table";
|
this.name = "To Table";
|
||||||
this.module = "Default";
|
this.module = "Default";
|
||||||
this.description = "Data can be split on different characters and rendered as an HTML or ASCII table with an optional header row.<br><br>Supports the CSV (Comma Separated Values) file format by default. Change the cell delimiter argument to <code>\\t</code> to support TSV (Tab Separated Values) or <code>|</code> for PSV (Pipe Separated Values).<br><br>You can enter as many delimiters as you like. Each character will be treat as a separate possible delimiter.";
|
this.description = "Data can be split on different characters and rendered as an HTML, ASCII or Markdown table with an optional header row.<br><br>Supports the CSV (Comma Separated Values) file format by default. Change the cell delimiter argument to <code>\\t</code> to support TSV (Tab Separated Values) or <code>|</code> for PSV (Pipe Separated Values).<br><br>You can enter as many delimiters as you like. Each character will be treat as a separate possible delimiter.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Comma-separated_values";
|
this.infoURL = "https://wikipedia.org/wiki/Comma-separated_values";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "html";
|
this.outputType = "html";
|
||||||
|
@ -43,7 +43,7 @@ class ToTable extends Operation {
|
||||||
{
|
{
|
||||||
"name": "Format",
|
"name": "Format",
|
||||||
"type": "option",
|
"type": "option",
|
||||||
"value": ["ASCII", "HTML"]
|
"value": ["ASCII", "HTML", "Markdown"]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,9 @@ class ToTable extends Operation {
|
||||||
case "ASCII":
|
case "ASCII":
|
||||||
return asciiOutput(tableData);
|
return asciiOutput(tableData);
|
||||||
case "HTML":
|
case "HTML":
|
||||||
|
return htmlOutput(tableData);
|
||||||
|
case "Markdown":
|
||||||
|
return markdownOutput(tableData);
|
||||||
default:
|
default:
|
||||||
return htmlOutput(tableData);
|
return htmlOutput(tableData);
|
||||||
}
|
}
|
||||||
|
@ -183,6 +186,59 @@ class ToTable extends Operation {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outputs an array of data as a Markdown table.
|
||||||
|
*
|
||||||
|
* @param {string[][]} tableData
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function markdownOutput(tableData) {
|
||||||
|
const headerDivider = "-";
|
||||||
|
const verticalBorder = "|";
|
||||||
|
|
||||||
|
let output = "";
|
||||||
|
const longestCells = [];
|
||||||
|
|
||||||
|
// Find longestCells value per column to pad cells equally.
|
||||||
|
tableData.forEach(function(row, index) {
|
||||||
|
row.forEach(function(cell, cellIndex) {
|
||||||
|
if (longestCells[cellIndex] === undefined || cell.length > longestCells[cellIndex]) {
|
||||||
|
longestCells[cellIndex] = cell.length;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ignoring the checkbox, as current Mardown renderer in CF doesn't handle table without headers
|
||||||
|
const row = tableData.shift();
|
||||||
|
output += outputRow(row, longestCells);
|
||||||
|
let rowOutput = verticalBorder;
|
||||||
|
row.forEach(function(cell, index) {
|
||||||
|
rowOutput += " " + headerDivider + " " + verticalBorder;
|
||||||
|
});
|
||||||
|
output += rowOutput += "\n";
|
||||||
|
|
||||||
|
// Add the rest of the table rows.
|
||||||
|
tableData.forEach(function(row, index) {
|
||||||
|
output += outputRow(row, longestCells);
|
||||||
|
});
|
||||||
|
|
||||||
|
return output;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outputs a row of correctly padded cells.
|
||||||
|
*/
|
||||||
|
function outputRow(row, longestCells) {
|
||||||
|
let rowOutput = verticalBorder;
|
||||||
|
row.forEach(function(cell, index) {
|
||||||
|
rowOutput += " " + cell + " ".repeat(longestCells[index] - cell.length) + " " + verticalBorder;
|
||||||
|
});
|
||||||
|
rowOutput += "\n";
|
||||||
|
return rowOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ class TripleDESDecrypt extends Operation {
|
||||||
inputType = args[3],
|
inputType = args[3],
|
||||||
outputType = args[4];
|
outputType = args[4];
|
||||||
|
|
||||||
if (key.length !== 24) {
|
if (key.length !== 24 && key.length !== 16) {
|
||||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||||
|
|
||||||
Triple DES uses a key length of 24 bytes (192 bits).
|
Triple DES uses a key length of 24 bytes (192 bits).
|
||||||
|
@ -85,7 +85,8 @@ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
|
||||||
|
|
||||||
input = Utils.convertToByteString(input, inputType);
|
input = Utils.convertToByteString(input, inputType);
|
||||||
|
|
||||||
const decipher = forge.cipher.createDecipher("3DES-" + mode, key);
|
const decipher = forge.cipher.createDecipher("3DES-" + mode,
|
||||||
|
key.length === 16 ? key + key.substring(0, 8) : key);
|
||||||
|
|
||||||
/* Allow for a "no padding" mode */
|
/* Allow for a "no padding" mode */
|
||||||
if (noPadding) {
|
if (noPadding) {
|
||||||
|
|
|
@ -69,7 +69,7 @@ class TripleDESEncrypt extends Operation {
|
||||||
inputType = args[3],
|
inputType = args[3],
|
||||||
outputType = args[4];
|
outputType = args[4];
|
||||||
|
|
||||||
if (key.length !== 24) {
|
if (key.length !== 24 && key.length !== 16) {
|
||||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||||
|
|
||||||
Triple DES uses a key length of 24 bytes (192 bits).
|
Triple DES uses a key length of 24 bytes (192 bits).
|
||||||
|
@ -84,7 +84,8 @@ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
|
||||||
|
|
||||||
input = Utils.convertToByteString(input, inputType);
|
input = Utils.convertToByteString(input, inputType);
|
||||||
|
|
||||||
const cipher = forge.cipher.createCipher("3DES-" + mode, key);
|
const cipher = forge.cipher.createCipher("3DES-" + mode,
|
||||||
|
key.length === 16 ? key + key.substring(0, 8) : key);
|
||||||
cipher.start({iv: iv});
|
cipher.start({iv: iv});
|
||||||
cipher.update(forge.util.createBuffer(input));
|
cipher.update(forge.util.createBuffer(input));
|
||||||
cipher.finish();
|
cipher.finish();
|
||||||
|
|
|
@ -79,6 +79,9 @@ class UNIXTimestampToWindowsFiletime extends Operation {
|
||||||
flipped += result.charAt(i);
|
flipped += result.charAt(i);
|
||||||
flipped += result.charAt(i + 1);
|
flipped += result.charAt(i + 1);
|
||||||
}
|
}
|
||||||
|
if (result.length % 2 !== 0) {
|
||||||
|
flipped += "0" + result.charAt(0);
|
||||||
|
}
|
||||||
result = flipped;
|
result = flipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ class ViewBitPlane extends Operation {
|
||||||
* @returns {html}
|
* @returns {html}
|
||||||
*/
|
*/
|
||||||
present(data) {
|
present(data) {
|
||||||
if (!data.length) return "";
|
if (!data.byteLength) return "";
|
||||||
const type = isImage(data);
|
const type = isImage(data);
|
||||||
|
|
||||||
return `<img src="data:${type};base64,${toBase64(data)}">`;
|
return `<img src="data:${type};base64,${toBase64(data)}">`;
|
||||||
|
|
|
@ -52,7 +52,10 @@ class WindowsFiletimeToUNIXTimestamp extends Operation {
|
||||||
if (format === "Hex (little endian)") {
|
if (format === "Hex (little endian)") {
|
||||||
// Swap endianness
|
// Swap endianness
|
||||||
let result = "";
|
let result = "";
|
||||||
for (let i = input.length - 2; i >= 0; i -= 2) {
|
if (input.length % 2 !== 0) {
|
||||||
|
result += input.charAt(input.length - 1);
|
||||||
|
}
|
||||||
|
for (let i = input.length - input.length % 2 - 2; i >= 0; i -= 2) {
|
||||||
result += input.charAt(i);
|
result += input.charAt(i);
|
||||||
result += input.charAt(i + 1);
|
result += input.charAt(i + 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ class HTMLIngredient {
|
||||||
this.rows = config.rows || false;
|
this.rows = config.rows || false;
|
||||||
this.target = config.target;
|
this.target = config.target;
|
||||||
this.defaultIndex = config.defaultIndex || 0;
|
this.defaultIndex = config.defaultIndex || 0;
|
||||||
|
this.maxLength = config.maxLength || null;
|
||||||
this.toggleValues = config.toggleValues;
|
this.toggleValues = config.toggleValues;
|
||||||
this.ingId = this.app.nextIngId();
|
this.ingId = this.app.nextIngId();
|
||||||
this.id = "ing-" + this.ingId;
|
this.id = "ing-" + this.ingId;
|
||||||
|
@ -63,7 +64,8 @@ class HTMLIngredient {
|
||||||
tabindex="${this.tabIndex}"
|
tabindex="${this.tabIndex}"
|
||||||
arg-name="${this.name}"
|
arg-name="${this.name}"
|
||||||
value="${this.value}"
|
value="${this.value}"
|
||||||
${this.disabled ? "disabled" : ""}>
|
${this.disabled ? "disabled" : ""}
|
||||||
|
${this.maxLength ? `maxlength="${this.maxLength}"` : ""}>
|
||||||
</div>`;
|
</div>`;
|
||||||
break;
|
break;
|
||||||
case "shortString":
|
case "shortString":
|
||||||
|
@ -78,7 +80,8 @@ class HTMLIngredient {
|
||||||
tabindex="${this.tabIndex}"
|
tabindex="${this.tabIndex}"
|
||||||
arg-name="${this.name}"
|
arg-name="${this.name}"
|
||||||
value="${this.value}"
|
value="${this.value}"
|
||||||
${this.disabled ? "disabled" : ""}>
|
${this.disabled ? "disabled" : ""}
|
||||||
|
${this.maxLength ? `maxlength="${this.maxLength}"` : ""}>
|
||||||
</div>`;
|
</div>`;
|
||||||
break;
|
break;
|
||||||
case "toggleString":
|
case "toggleString":
|
||||||
|
@ -93,7 +96,8 @@ class HTMLIngredient {
|
||||||
tabindex="${this.tabIndex}"
|
tabindex="${this.tabIndex}"
|
||||||
arg-name="${this.name}"
|
arg-name="${this.name}"
|
||||||
value="${this.value}"
|
value="${this.value}"
|
||||||
${this.disabled ? "disabled" : ""}>
|
${this.disabled ? "disabled" : ""}
|
||||||
|
${this.maxLength ? `maxlength="${this.maxLength}"` : ""}>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group-append">
|
<div class="input-group-append">
|
||||||
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">${this.toggleValues[0]}</button>
|
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">${this.toggleValues[0]}</button>
|
||||||
|
|
|
@ -45,10 +45,10 @@ TestRegister.addApiTests([
|
||||||
const result = chef.ADD("sample input", {
|
const result = chef.ADD("sample input", {
|
||||||
key: {
|
key: {
|
||||||
string: "some key",
|
string: "some key",
|
||||||
option: "Hex"
|
option: "utf8"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
assert.equal(result.toString(), "aO[^ZS\u000eW\\^cb");
|
assert.equal(result.toString(), "\xe6\xd0\xda\xd5\x8c\xd0\x85\xe2\xe1\xdf\xe2\xd9");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
@ -121,10 +121,10 @@ Tiger-128`;
|
||||||
const result = chef.AND("Scot-free", {
|
const result = chef.AND("Scot-free", {
|
||||||
key: {
|
key: {
|
||||||
string: "Raining Cats and Dogs",
|
string: "Raining Cats and Dogs",
|
||||||
option: "Hex",
|
option: "utf8",
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
assert.strictEqual(result.toString(), "\u0000\"M$(D E");
|
assert.strictEqual(result.toString(), "Raid)fb A");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("atBash Cipher", () => {
|
it("atBash Cipher", () => {
|
||||||
|
@ -371,10 +371,10 @@ color: white;
|
||||||
},
|
},
|
||||||
salt: {
|
salt: {
|
||||||
string: "Market",
|
string: "Market",
|
||||||
option: "Hex",
|
option: "utf8",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
assert.strictEqual(result.toString(), "7c21a9f5063a4d62fb1050068245c181");
|
assert.strictEqual(result.toString(), "4930d5d200e80f18c96b5550d13c6af8");
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("Derive PBKDF2 Key", () => {
|
it("Derive PBKDF2 Key", () => {
|
||||||
|
|
|
@ -30,6 +30,7 @@ import "./tests/ByteRepr.mjs";
|
||||||
import "./tests/CartesianProduct.mjs";
|
import "./tests/CartesianProduct.mjs";
|
||||||
import "./tests/CetaceanCipherEncode.mjs";
|
import "./tests/CetaceanCipherEncode.mjs";
|
||||||
import "./tests/CetaceanCipherDecode.mjs";
|
import "./tests/CetaceanCipherDecode.mjs";
|
||||||
|
import "./tests/ChaCha.mjs";
|
||||||
import "./tests/CharEnc.mjs";
|
import "./tests/CharEnc.mjs";
|
||||||
import "./tests/ChangeIPFormat.mjs";
|
import "./tests/ChangeIPFormat.mjs";
|
||||||
import "./tests/Charts.mjs";
|
import "./tests/Charts.mjs";
|
||||||
|
@ -124,6 +125,11 @@ import "./tests/UnescapeString.mjs";
|
||||||
import "./tests/LS47.mjs";
|
import "./tests/LS47.mjs";
|
||||||
import "./tests/LZString.mjs";
|
import "./tests/LZString.mjs";
|
||||||
import "./tests/NTLM.mjs";
|
import "./tests/NTLM.mjs";
|
||||||
|
import "./tests/Shuffle.mjs";
|
||||||
|
import "./tests/FletcherChecksum.mjs";
|
||||||
|
import "./tests/CMAC.mjs";
|
||||||
|
import "./tests/AESKeyWrap.mjs";
|
||||||
|
import "./tests/Rabbit.mjs";
|
||||||
|
|
||||||
// Cannot test operations that use the File type yet
|
// Cannot test operations that use the File type yet
|
||||||
// import "./tests/SplitColourChannels.mjs";
|
// import "./tests/SplitColourChannels.mjs";
|
||||||
|
|
324
tests/operations/tests/AESKeyWrap.mjs
Normal file
324
tests/operations/tests/AESKeyWrap.mjs
Normal file
|
@ -0,0 +1,324 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: RFC Test Vector, 128-bit data, 128-bit KEK",
|
||||||
|
"input": "00112233445566778899aabbccddeeff",
|
||||||
|
"expectedOutput": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: RFC Test Vector, 128-bit data, 192-bit KEK",
|
||||||
|
"input": "00112233445566778899aabbccddeeff",
|
||||||
|
"expectedOutput": "96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f1011121314151617"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: RFC Test Vector, 128-bit data, 256-bit KEK",
|
||||||
|
"input": "00112233445566778899aabbccddeeff",
|
||||||
|
"expectedOutput": "64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: RFC Test Vector, 192-bit data, 192-bit KEK",
|
||||||
|
"input": "00112233445566778899aabbccddeeff0001020304050607",
|
||||||
|
"expectedOutput": "031d33264e15d33268f24ec260743edce1c6c7ddee725a936ba814915c6762d2",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f1011121314151617"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: RFC Test Vector, 192-bit data, 256-bit KEK",
|
||||||
|
"input": "00112233445566778899aabbccddeeff0001020304050607",
|
||||||
|
"expectedOutput": "a8f9bc1612c68b3ff6e6f4fbe30e71e4769c8b80a32cb8958cd5d17d6b254da1",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: RFC Test Vector, 256-bit data, 256-bit KEK",
|
||||||
|
"input": "00112233445566778899aabbccddeeff000102030405060708090a0b0c0d0e0f",
|
||||||
|
"expectedOutput": "28c9f404c4b810f4cbccb35cfb87f8263f5786e2d80ed326cbc7f0e71a99f43bfb988b9b7a02dd21",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: RFC Test Vector, 128-bit data, 128-bit KEK",
|
||||||
|
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5",
|
||||||
|
"expectedOutput": "00112233445566778899aabbccddeeff",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: RFC Test Vector, 128-bit data, 192-bit KEK",
|
||||||
|
"input": "96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d",
|
||||||
|
"expectedOutput": "00112233445566778899aabbccddeeff",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f1011121314151617"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: RFC Test Vector, 128-bit data, 256-bit KEK",
|
||||||
|
"input": "64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7",
|
||||||
|
"expectedOutput": "00112233445566778899aabbccddeeff",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: RFC Test Vector, 192-bit data, 192-bit KEK",
|
||||||
|
"input": "031d33264e15d33268f24ec260743edce1c6c7ddee725a936ba814915c6762d2",
|
||||||
|
"expectedOutput": "00112233445566778899aabbccddeeff0001020304050607",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f1011121314151617"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: RFC Test Vector, 192-bit data, 256-bit KEK",
|
||||||
|
"input": "a8f9bc1612c68b3ff6e6f4fbe30e71e4769c8b80a32cb8958cd5d17d6b254da1",
|
||||||
|
"expectedOutput": "00112233445566778899aabbccddeeff0001020304050607",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: RFC Test Vector, 256-bit data, 256-bit KEK",
|
||||||
|
"input": "28c9f404c4b810f4cbccb35cfb87f8263f5786e2d80ed326cbc7f0e71a99f43bfb988b9b7a02dd21",
|
||||||
|
"expectedOutput": "00112233445566778899aabbccddeeff000102030405060708090a0b0c0d0e0f",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: invalid KEK length",
|
||||||
|
"input": "00112233445566778899aabbccddeeff",
|
||||||
|
"expectedOutput": "KEK must be either 16, 24, or 32 bytes (currently 10 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00010203040506070809"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: invalid IV length",
|
||||||
|
"input": "00112233445566778899aabbccddeeff",
|
||||||
|
"expectedOutput": "IV must be 8 bytes (currently 6 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: input length not multiple of 8",
|
||||||
|
"input": "00112233445566778899aabbccddeeff0102",
|
||||||
|
"expectedOutput": "input must be 8n (n>=2) bytes (currently 18 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap: input too short",
|
||||||
|
"input": "0011223344556677",
|
||||||
|
"expectedOutput": "input must be 8n (n>=2) bytes (currently 8 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: invalid KEK length",
|
||||||
|
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5",
|
||||||
|
"expectedOutput": "KEK must be either 16, 24, or 32 bytes (currently 10 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00010203040506070809"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: invalid IV length",
|
||||||
|
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5",
|
||||||
|
"expectedOutput": "IV must be 8 bytes (currently 6 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: input length not multiple of 8",
|
||||||
|
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5e621",
|
||||||
|
"expectedOutput": "input must be 8n (n>=3) bytes (currently 26 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: input too short",
|
||||||
|
"input": "1fa68b0a8112b447aef34bd8fb5a7b82",
|
||||||
|
"expectedOutput": "input must be 8n (n>=3) bytes (currently 16 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap: corrupted input",
|
||||||
|
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe6",
|
||||||
|
"expectedOutput": "IV mismatch",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
|
@ -16,6 +16,10 @@ DIb:@FD,*)+C]U=@3BN#EcYf8ATD3s@q?d$AftVqCh[NqF<G:8+EV:.+Cf>-FD5W8ARlolDIal(\
|
||||||
DId<j@<?3r@:F%a+D58'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G>u\
|
DId<j@<?3r@:F%a+D58'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G>u\
|
||||||
D.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c";
|
D.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c";
|
||||||
|
|
||||||
|
const allZeroExample = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";
|
||||||
|
|
||||||
|
const allZeroOutput = "zz!!*-'\"9eu7#RLhG$k3[W&.oNg'GVB\"(`=52*$$(B+<_pR,UFcb-n-Vr/1iJ-0JP==1c70M3&s#]4?Ykm5X@_(6q'R884cEH9MJ8X:f1+h<)lt#=BSg3>[:ZC?t!MSA7]@cBPD3sCi+'.E,fo>FEMbNG^4U^I!pHnJ:W<)KS>/9Ll%\"IN/`jYOHG]iPa.Q$R$jD4S=Q7DTV8*TUnsrdW2ZetXKAY/Yd(L?['d?O\\@K2_]Y2%o^qmn*`5Ta:aN;TJbg\"GZd*^:jeCE.%f\\,!5gtgiEi8N\\UjQ5OekiqBum-X60nF?)@o_%qPq\"ad`r;HWp";
|
||||||
|
|
||||||
TestRegister.addTests([
|
TestRegister.addTests([
|
||||||
{
|
{
|
||||||
name: "To Base85",
|
name: "To Base85",
|
||||||
|
@ -45,4 +49,22 @@ TestRegister.addTests([
|
||||||
"args": ["!-u", false] }
|
"args": ["!-u", false] }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "To Base85",
|
||||||
|
input: allZeroExample,
|
||||||
|
expectedOutput: allZeroOutput,
|
||||||
|
recipeConfig: [
|
||||||
|
{ "op": "To Base85",
|
||||||
|
"args": ["!-u"] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "From Base85",
|
||||||
|
input: allZeroOutput,
|
||||||
|
expectedOutput: allZeroExample,
|
||||||
|
recipeConfig: [
|
||||||
|
{ "op": "From Base85",
|
||||||
|
"args": ["!-u", true, "z"] }
|
||||||
|
]
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
314
tests/operations/tests/CMAC.mjs
Normal file
314
tests/operations/tests/CMAC.mjs
Normal file
|
@ -0,0 +1,314 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
// values in "NIST's CSRC" testcases are taken from here:
|
||||||
|
// https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES128 NIST's CSRC Example #1",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "bb1d6929e95937287fa37d129b756746",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "2b7e151628aed2a6abf7158809cf4f3c"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES128 NIST's CSRC Example #2",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172a",
|
||||||
|
"expectedOutput": "070a16b46b4d4144f79bdd9dd04a287c",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "2b7e151628aed2a6abf7158809cf4f3c"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES128 NIST's CSRC Example #3",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a57",
|
||||||
|
"expectedOutput": "7d85449ea6ea19c823a7bf78837dfade",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "2b7e151628aed2a6abf7158809cf4f3c"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES128 NIST's CSRC Example #4",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
|
||||||
|
"expectedOutput": "51f0bebf7e3b9d92fc49741779363cfe",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "2b7e151628aed2a6abf7158809cf4f3c"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES192 NIST's CSRC Example #1",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "d17ddf46adaacde531cac483de7a9367",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES192 NIST's CSRC Example #2",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172a",
|
||||||
|
"expectedOutput": "9e99a7bf31e710900662f65e617c5184",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES192 NIST's CSRC Example #3",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a57",
|
||||||
|
"expectedOutput": "3d75c194ed96070444a9fa7ec740ecf8",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES192 NIST's CSRC Example #4",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
|
||||||
|
"expectedOutput": "a1d5df0eed790f794d77589659f39a11",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES256 NIST's CSRC Example #1",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "028962f61b7bf89efc6b551f4667d983",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES256 NIST's CSRC Example #2",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172a",
|
||||||
|
"expectedOutput": "28a7023f452e8f82bd4bf28d8c37c35c",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES256 NIST's CSRC Example #3",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a57",
|
||||||
|
"expectedOutput": "156727dc0878944a023c1fe03bad6d93",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES256 NIST's CSRC Example #4",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
|
||||||
|
"expectedOutput": "e1992190549f6ed5696a2c056c315410",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (1) NIST's CSRC Sample #1",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "7db0d37df936c550",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef01456789abcdef0123"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (1) NIST's CSRC Sample #2",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172a",
|
||||||
|
"expectedOutput": "30239cf1f52e6609",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef01456789abcdef0123"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (1) NIST's CSRC Sample #3",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a57",
|
||||||
|
"expectedOutput": "6c9f3ee4923f6be2",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef01456789abcdef0123"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (1) NIST's CSRC Sample #4",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51",
|
||||||
|
"expectedOutput": "99429bd0bf7904e5",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef01456789abcdef0123"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (2) NIST's CSRC Sample #1",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "79ce52a7f786a960",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef010123456789abcdef"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (2) NIST's CSRC Sample #2",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172a",
|
||||||
|
"expectedOutput": "cc18a0b79af2413b",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef010123456789abcdef"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (2) NIST's CSRC Sample #3",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a57",
|
||||||
|
"expectedOutput": "c06d377ecd101969",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef010123456789abcdef"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES (2) NIST's CSRC Sample #4",
|
||||||
|
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51",
|
||||||
|
"expectedOutput": "9cd33580f9b64dfb",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef010123456789abcdef"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-AES: invalid key length",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "The key for AES must be either 16, 24, or 32 bytes (currently 20 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "00112233445566778899aabbccddeeff01234567"}, "AES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CMAC-TDES: invalid key length",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "The key for Triple DES must be 16 or 24 bytes (currently 20 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "CMAC",
|
||||||
|
"args": [{"option": "Hex", "string": "00112233445566778899aabbccddeeff01234567"}, "Triple DES"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]);
|
151
tests/operations/tests/ChaCha.mjs
Normal file
151
tests/operations/tests/ChaCha.mjs
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/**
|
||||||
|
* ChaCha tests.
|
||||||
|
*
|
||||||
|
* @author joostrijneveld [joost@joostrijneveld.nl]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "ChaCha: no key",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: `Invalid key length: 0 bytes.
|
||||||
|
|
||||||
|
ChaCha uses a key of 16 or 32 bytes (128 or 256 bits).`,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
0, "20", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: no nonce",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: `Invalid nonce length: 0 bytes.
|
||||||
|
|
||||||
|
ChaCha uses a nonce of 8 or 12 bytes (64 or 96 bits).`,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
0, "20", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: RFC8439",
|
||||||
|
input: "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.",
|
||||||
|
expectedOutput: "6e 2e 35 9a 25 68 f9 80 41 ba 07 28 dd 0d 69 81 e9 7e 7a ec 1d 43 60 c2 0a 27 af cc fd 9f ae 0b f9 1b 65 c5 52 47 33 ab 8f 59 3d ab cd 62 b3 57 16 39 d6 24 e6 51 52 ab 8f 53 0c 35 9f 08 61 d8 07 ca 0d bf 50 0d 6a 61 56 a3 8e 08 8a 22 b6 5e 52 bc 51 4d 16 cc f8 06 81 8c e9 1a b7 79 37 36 5a f9 0b bf 74 a3 5b e6 b4 0b 8e ed f2 78 5e 42 87 4d",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f"},
|
||||||
|
{"option": "Hex", "string": "00:00:00:00:00:00:00:4a:00:00:00:00"},
|
||||||
|
1, "20", "Raw", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: draft-strombergson-chacha-test-vectors-01 TC7.1",
|
||||||
|
input: "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
||||||
|
expectedOutput: "29 56 0d 28 0b 45 28 40 0a 8f 4b 79 53 69 fb 3a 01 10 55 99 e9 f1 ed 58 27 9c fc 9e ce 2d c5 f9 9f 1c 2e 52 c9 82 38 f5 42 a5 c0 a8 81 d8 50 b6 15 d3 ac d9 fb db 02 6e 93 68 56 5d a5 0e 0d 49 dd 5b e8 ef 74 24 8b 3e 25 1d 96 5d 8f cb 21 e7 cf e2 04 d4 00 78 06 fb ee 3c e9 4c 74 bf ba d2 c1 1c 62 1b a0 48 14 7c 5c aa 94 d1 82 cc ff 6f d5 cf 44 ad f9 6e 3d 68 28 1b b4 96 76 af 87 e7",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff"},
|
||||||
|
{"option": "Hex", "string": "0f 1e 2d 3c 4b 5a 69 78"},
|
||||||
|
0, "8", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: draft-strombergson-chacha-test-vectors-01 TC7.2",
|
||||||
|
input: "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
||||||
|
expectedOutput: "5e dd c2 d9 42 8f ce ee c5 0a 52 a9 64 ea e0 ff b0 4b 2d e0 06 a9 b0 4c ff 36 8f fa 92 11 16 b2 e8 e2 64 ba bd 2e fa 0d e4 3e f2 e3 b6 d0 65 e8 f7 c0 a1 78 37 b0 a4 0e b0 e2 c7 a3 74 2c 87 53 ed e5 f3 f6 d1 9b e5 54 67 5e 50 6a 77 5c 63 f0 94 d4 96 5c 31 93 19 dc d7 50 6f 45 7b 11 7b 84 b1 0b 24 6e 95 6c 2d a8 89 8a 65 6c ee f3 f7 b7 16 45 b1 9f 70 1d b8 44 85 ce 51 21 f0 f6 17 ef",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff"},
|
||||||
|
{"option": "Hex", "string": "0f 1e 2d 3c 4b 5a 69 78"},
|
||||||
|
0, "12", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: draft-strombergson-chacha-test-vectors-01 TC7.3",
|
||||||
|
input: "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
||||||
|
expectedOutput: "d1 ab f6 30 46 7e b4 f6 7f 1c fb 47 cd 62 6a ae 8a fe db be 4f f8 fc 5f e9 cf ae 30 7e 74 ed 45 1f 14 04 42 5a d2 b5 45 69 d5 f1 81 48 93 99 71 ab b8 fa fc 88 ce 4a c7 fe 1c 3d 1f 7a 1e b7 ca e7 6c a8 7b 61 a9 71 35 41 49 77 60 dd 9a e0 59 35 0c ad 0d ce df aa 80 a8 83 11 9a 1a 6f 98 7f d1 ce 91 fd 8e e0 82 80 34 b4 11 20 0a 97 45 a2 85 55 44 75 d1 2a fc 04 88 7f ef 35 16 d1 2a 2c",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff"},
|
||||||
|
{"option": "Hex", "string": "0f 1e 2d 3c 4b 5a 69 78"},
|
||||||
|
0, "20", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: draft-strombergson-chacha-test-vectors-01 TC7.4",
|
||||||
|
input: "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
||||||
|
expectedOutput: "db 43 ad 9d 1e 84 2d 12 72 e4 53 0e 27 6b 3f 56 8f 88 59 b3 f7 cf 6d 9d 2c 74 fa 53 80 8c b5 15 7a 8e bf 46 ad 3d cc 4b 6c 7d ad de 13 17 84 b0 12 0e 0e 22 f6 d5 f9 ff a7 40 7d 4a 21 b6 95 d9 c5 dd 30 bf 55 61 2f ab 9b dd 11 89 20 c1 98 16 47 0c 7f 5d cd 42 32 5d bb ed 8c 57 a5 62 81 c1 44 cb 0f 03 e8 1b 30 04 62 4e 06 50 a1 ce 5a fa f9 a7 cd 81 63 f6 db d7 26 02 25 7d d9 6e 47 1e",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff ff ee dd cc bb aa 99 88 77 66 55 44 33 22 11 00"},
|
||||||
|
{"option": "Hex", "string": "0f 1e 2d 3c 4b 5a 69 78"},
|
||||||
|
0, "8", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: draft-strombergson-chacha-test-vectors-01 TC7.5",
|
||||||
|
input: "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
||||||
|
expectedOutput: "7e d1 2a 3a 63 91 2a e9 41 ba 6d 4c 0d 5e 86 2e 56 8b 0e 55 89 34 69 35 50 5f 06 4b 8c 26 98 db f7 d8 50 66 7d 8e 67 be 63 9f 3b 4f 6a 16 f9 2e 65 ea 80 f6 c7 42 94 45 da 1f c2 c1 b9 36 50 40 e3 2e 50 c4 10 6f 3b 3d a1 ce 7c cb 1e 71 40 b1 53 49 3c 0f 3a d9 a9 bc ff 07 7e c4 59 6f 1d 0f 29 bf 9c ba a5 02 82 0f 73 2a f5 a9 3c 49 ee e3 3d 1c 4f 12 af 3b 42 97 af 91 fe 41 ea 9e 94 a2",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff ff ee dd cc bb aa 99 88 77 66 55 44 33 22 11 00"},
|
||||||
|
{"option": "Hex", "string": "0f 1e 2d 3c 4b 5a 69 78"},
|
||||||
|
0, "12", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ChaCha: draft-strombergson-chacha-test-vectors-01 TC7.6",
|
||||||
|
input: "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
||||||
|
expectedOutput: "9f ad f4 09 c0 08 11 d0 04 31 d6 7e fb d8 8f ba 59 21 8d 5d 67 08 b1 d6 85 86 3f ab bb 0e 96 1e ea 48 0f d6 fb 53 2b fd 49 4b 21 51 01 50 57 42 3a b6 0a 63 fe 4f 55 f7 a2 12 e2 16 7c ca b9 31 fb fd 29 cf 7b c1 d2 79 ed df 25 dd 31 6b b8 84 3d 6e de e0 bd 1e f1 21 d1 2f a1 7c bc 2c 57 4c cc ab 5e 27 51 67 b0 8b d6 86 f8 a0 9d f8 7e c3 ff b3 53 61 b9 4e bf a1 3f ec 0e 48 89 d1 8d a5",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "ChaCha",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff ff ee dd cc bb aa 99 88 77 66 55 44 33 22 11 00"},
|
||||||
|
{"option": "Hex", "string": "0f 1e 2d 3c 4b 5a 69 78"},
|
||||||
|
0, "20", "Hex", "Hex",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
|
@ -75,4 +75,34 @@ TestRegister.addTests([
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "LZ4 Compress",
|
||||||
|
input: "The cat sat on the mat.",
|
||||||
|
expectedOutput: "04224d184070df170000805468652063617420736174206f6e20746865206d61742e00000000",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "LZ4 Compress",
|
||||||
|
"args": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "To Hex",
|
||||||
|
"args": ["None", 0]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "LZ4 Decompress",
|
||||||
|
input: "04224d184070df170000805468652063617420736174206f6e20746865206d61742e00000000",
|
||||||
|
expectedOutput: "The cat sat on the mat.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "LZ4 Decompress",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
108
tests/operations/tests/FletcherChecksum.mjs
Normal file
108
tests/operations/tests/FletcherChecksum.mjs
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Fletcher-16 Checksum: abcde",
|
||||||
|
input: "abcde",
|
||||||
|
expectedOutput: "c8f0",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-16 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-16 Checksum: abcdef",
|
||||||
|
input: "abcdef",
|
||||||
|
expectedOutput: "2057",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-16 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-16 Checksum: abcdefgh",
|
||||||
|
input: "abcdefgh",
|
||||||
|
expectedOutput: "0627",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-16 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-32 Checksum: abcde",
|
||||||
|
input: "abcde",
|
||||||
|
expectedOutput: "f04fc729",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-32 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-32 Checksum: abcdef",
|
||||||
|
input: "abcdef",
|
||||||
|
expectedOutput: "56502d2a",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-32 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-32 Checksum: abcdefgh",
|
||||||
|
input: "abcdefgh",
|
||||||
|
expectedOutput: "ebe19591",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-32 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-64 Checksum: abcde",
|
||||||
|
input: "abcde",
|
||||||
|
expectedOutput: "c8c6c527646362c6",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-64 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-64 Checksum: abcdef",
|
||||||
|
input: "abcdef",
|
||||||
|
expectedOutput: "c8c72b276463c8c6",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-64 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-64 Checksum: abcdefgh",
|
||||||
|
input: "abcdefgh",
|
||||||
|
expectedOutput: "312e2b28cccac8c6",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-64 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
|
@ -58,8 +58,8 @@ CTPH: A:E:E
|
||||||
Checksums:
|
Checksums:
|
||||||
Fletcher-8: 3d
|
Fletcher-8: 3d
|
||||||
Fletcher-16: 5dc1
|
Fletcher-16: 5dc1
|
||||||
Fletcher-32: 045901c0
|
Fletcher-32: 3f5cd9e7
|
||||||
Fletcher-64: 00000459000001c0
|
Fletcher-64: 7473657474736574
|
||||||
Adler-32: 045d01c1
|
Adler-32: 045d01c1
|
||||||
CRC-8: b9
|
CRC-8: b9
|
||||||
CRC-16: f82e
|
CRC-16: f82e
|
||||||
|
|
177
tests/operations/tests/Rabbit.mjs
Normal file
177
tests/operations/tests/Rabbit.mjs
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Rabbit: RFC Test vector, without IV 1",
|
||||||
|
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
expectedOutput: "b15754f036a5d6ecf56b45261c4af70288e8d815c59c0c397b696c4789c68aa7f416a1c3700cd451da68d1881673d696",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: RFC Test vector, without IV 2",
|
||||||
|
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
expectedOutput: "3d2df3c83ef627a1e97fc38487e2519cf576cd61f4405b8896bf53aa8554fc19e5547473fbdb43508ae53b20204d4c5e",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "912813292e3d36fe3bfc62f1dc51c3ac"},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: RFC Test vector, without IV 3",
|
||||||
|
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
expectedOutput: "0cb10dcda041cdac32eb5cfd02d0609b95fc9fca0f17015a7b7092114cff3ead9649e5de8bfc7f3f924147ad3a947428",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "8395741587e0c733e9e9ab01c09b0043"},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: RFC Test vector, with IV 1",
|
||||||
|
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
expectedOutput: "c6a7275ef85495d87ccd5d376705b7ed5f29a6ac04f5efd47b8f293270dc4a8d2ade822b29de6c1ee52bdb8a47bf8f66",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": "0000000000000000"},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: RFC Test vector, with IV 2",
|
||||||
|
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
expectedOutput: "1fcd4eb9580012e2e0dccc9222017d6da75f4e10d12125017b2499ffed936f2eebc112c393e738392356bdd012029ba7",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": "c373f575c1267e59"},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: RFC Test vector, with IV 3",
|
||||||
|
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
expectedOutput: "445ad8c805858dbf70b6af23a151104d96c8f27947f42c5baeae67c6acc35b039fcbfc895fa71c17313df034f01551cb",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": "a6eb561ad2f41727"},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: generated stream should be XORed with the input",
|
||||||
|
input: "cedda96c054e3ddd93da7ed05e2a4b7bdb0c00fe214f03502e2708b2c2bfc77aa2311b0b9af8aa78d119f92b26db0a6b",
|
||||||
|
expectedOutput: "7f8afd9c33ebeb3166b13bf64260bc7953e4d8ebe4d30f69554e64f54b794ddd5627bac8eaf47e290b7128a330a8dcfd",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: least significant bits should be used for the last block",
|
||||||
|
input: "0000000000000000",
|
||||||
|
expectedOutput: "f56b45261c4af702",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: invalid key length",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: "Invalid key length: 8 bytes (expected: 16)",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "0000000000000000"},
|
||||||
|
{"option": "Hex", "string": ""},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rabbit: invalid IV length",
|
||||||
|
input: "",
|
||||||
|
expectedOutput: "Invalid IV length: 4 bytes (expected: 0 or 8)",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||||
|
{"option": "Hex", "string": "00000000"},
|
||||||
|
"Big", "Hex", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// this testcase is taken from the first example on Crypto++ Wiki
|
||||||
|
// https://www.cryptopp.com/wiki/Rabbit
|
||||||
|
name: "Rabbit: little-endian mode (Crypto++ compatible)",
|
||||||
|
input: "Rabbit stream cipher test",
|
||||||
|
expectedOutput: "1ae2d4edcf9b6063b00fd6fda0b223aded157e77031cf0440b",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Rabbit",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "23c2731e8b5469fd8dabb5bc592a0f3a"},
|
||||||
|
{"option": "Hex", "string": "712906405ef03201"},
|
||||||
|
"Little", "Raw", "Hex"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]);
|
54
tests/operations/tests/Shuffle.mjs
Normal file
54
tests/operations/tests/Shuffle.mjs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
"name": "Shuffle empty",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "Shuffle",
|
||||||
|
"args": ["Comma"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Shuffle bytes",
|
||||||
|
"input": "12345678",
|
||||||
|
"expectedOutput": "31 32 33 34 35 36 37 38",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "Shuffle",
|
||||||
|
"args": ["Nothing (separate chars)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "To Hex",
|
||||||
|
"args": ["Space", 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "Sort",
|
||||||
|
"args": ["Space", false, "Alphabetical (case sensitive)"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Shuffle lines",
|
||||||
|
"input": "1\n2\n3\n4\n5\n6\n7\n8\n9\na\nb\nc\nd\ne\nf\n",
|
||||||
|
"expectedOutput": "\n1\n2\n3\n4\n5\n6\n7\n8\n9\na\nb\nc\nd\ne\nf",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "Shuffle",
|
||||||
|
"args": ["Line feed"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "Sort",
|
||||||
|
"args": ["Line feed", false, "Alphabetical (case sensitive)"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]);
|
Loading…
Reference in a new issue