mirror of
https://github.com/gchq/CyberChef
synced 2025-12-05 23:53:27 +00:00
Compare commits
206 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2325306db | ||
|
|
dfe31980b7 | ||
|
|
9734b78aeb | ||
|
|
4ee0800990 | ||
|
|
387008bd9c | ||
|
|
bf24547202 | ||
|
|
c2f6b8df66 | ||
|
|
d0e428b728 | ||
|
|
ae5128a33a | ||
|
|
ed25017e2d | ||
|
|
e5b2b84073 | ||
|
|
1953d9a4c8 | ||
|
|
b3113c109b | ||
|
|
8c3569ea63 | ||
|
|
ae28d476de | ||
|
|
01c4cfdc8d | ||
|
|
8c6c3a1c01 | ||
|
|
f367c1f78b | ||
|
|
13d87d397d | ||
|
|
ed2c886359 | ||
|
|
6337e84708 | ||
|
|
ae20a951be | ||
|
|
866dd546c8 | ||
|
|
2070e1a96b | ||
|
|
952f49e2e1 | ||
|
|
f600571c6d | ||
|
|
5d4c7244e1 | ||
|
|
b6bdcaa71f | ||
|
|
c8eab5d218 | ||
|
|
8ab56a29ac | ||
|
|
973b5f3f5c | ||
|
|
076a1f97c2 | ||
|
|
d96ef37d81 | ||
|
|
56f8302402 | ||
|
|
97e6a7cbd8 | ||
|
|
d89d79116c | ||
|
|
367d79e820 | ||
|
|
283d7f2159 | ||
|
|
dacb3ef6c3 | ||
|
|
22454ae842 | ||
|
|
79b9b63982 | ||
|
|
2f68bf30a4 | ||
|
|
50f078cc45 | ||
|
|
47a410d6ab | ||
|
|
31cbf8cccc | ||
|
|
88bd321e3e | ||
|
|
b4a586c0b9 | ||
|
|
63593f1b6c | ||
|
|
dcff8971e8 | ||
|
|
3f7059a235 | ||
|
|
71c743ff5a | ||
|
|
15fbe5a459 | ||
|
|
cd47394709 | ||
|
|
6f4ee8b7b6 | ||
|
|
8c5d05b611 | ||
|
|
3bdcf4d851 | ||
|
|
1d1c69ca51 | ||
|
|
c4c679021d | ||
|
|
c16d13e2c9 | ||
|
|
97613eb3c7 | ||
|
|
a946d04a72 | ||
|
|
cc35ec82eb | ||
|
|
d6604e0008 | ||
|
|
b9e63efc37 | ||
|
|
b458707921 | ||
|
|
6ec52c6cd2 | ||
|
|
79d7a5dd87 | ||
|
|
1653d0212a | ||
|
|
c378bcb00b | ||
|
|
215e7a5f5d | ||
|
|
6b686681d5 | ||
|
|
20ea050728 | ||
|
|
4b6132a2d7 | ||
|
|
4cf80e3ebb | ||
|
|
045747f543 | ||
|
|
b10c5e3256 | ||
|
|
69df2e4183 | ||
|
|
12ebd35c4d | ||
|
|
30c5f76cf0 | ||
|
|
3a979b6cda | ||
|
|
863bdffa84 | ||
|
|
42b956e402 | ||
|
|
4acf7b4e4f | ||
|
|
42e881326f | ||
|
|
3c4893d7c7 | ||
|
|
027aca4ab2 | ||
|
|
2d471f551f | ||
|
|
5c598b69b0 | ||
|
|
037300de79 | ||
|
|
6990dcae89 | ||
|
|
6e81d6dfcd | ||
|
|
cea30465d8 | ||
|
|
b301d16cb2 | ||
|
|
19c002fcdd | ||
|
|
ab3a73fe58 | ||
|
|
91fc2c28dc | ||
|
|
ca47ba3c7c | ||
|
|
e1b456c01c | ||
|
|
5eb7e00eac | ||
|
|
8bcf68c8a1 | ||
|
|
520eaedd9a | ||
|
|
4c5e664ce0 | ||
|
|
53c500eb1b | ||
|
|
253346a201 | ||
|
|
c5d82a76ab | ||
|
|
18a9dfffc7 | ||
|
|
38838e4dca | ||
|
|
5c151d727b | ||
|
|
2d5b157c91 | ||
|
|
10d3d27a33 | ||
|
|
1614442bd7 | ||
|
|
a3c5b1e107 | ||
|
|
3f0af9cdea | ||
|
|
f4de4de8c1 | ||
|
|
69033a7343 | ||
|
|
5a22106731 | ||
|
|
5155d0ed56 | ||
|
|
9be674103f | ||
|
|
ba24e12454 | ||
|
|
b76aa16143 | ||
|
|
8f7bb3a7c9 | ||
|
|
be2b466376 | ||
|
|
f957925aac | ||
|
|
1bf8d63d1a | ||
|
|
8875144307 | ||
|
|
d5c01f387a | ||
|
|
32709cd60f | ||
|
|
aaf0a91975 | ||
|
|
6cc6230b91 | ||
|
|
dd630f20f8 | ||
|
|
0c6efd95fa | ||
|
|
a276378887 | ||
|
|
98d861a639 | ||
|
|
3b3c27072f | ||
|
|
3089c39369 | ||
|
|
0cbb17f7ce | ||
|
|
54793f2b78 | ||
|
|
f1ffe19ec8 | ||
|
|
e638fb69b5 | ||
|
|
718a94b5e0 | ||
|
|
3079059ce3 | ||
|
|
d6c6981bc0 | ||
|
|
8aeb7b60a7 | ||
|
|
9197ac6510 | ||
|
|
b67ad3073c | ||
|
|
4a4f37f888 | ||
|
|
c55331f220 | ||
|
|
757ec98554 | ||
|
|
14309f2069 | ||
|
|
e6b89d571e | ||
|
|
d957198fd6 | ||
|
|
903bd22999 | ||
|
|
04ee2fb3e4 | ||
|
|
ac2466a304 | ||
|
|
ab4c9ef0d6 | ||
|
|
a69063de9b | ||
|
|
62b76777c0 | ||
|
|
32a91bda0a | ||
|
|
a15af602e0 | ||
|
|
ec9dfd2918 | ||
|
|
016086ef4e | ||
|
|
2e5ea968ee | ||
|
|
5dde1c1c04 | ||
|
|
be14d56eae | ||
|
|
100b097ace | ||
|
|
3833c5f9fe | ||
|
|
3470dd9f3b | ||
|
|
c5e8649284 | ||
|
|
a95f43aa4d | ||
|
|
0420aa8edb | ||
|
|
806b43dfec | ||
|
|
98f4fe4c2b | ||
|
|
0d63b3cbae | ||
|
|
7061c05f77 | ||
|
|
9b9a182f9f | ||
|
|
2d9e7fcc6d | ||
|
|
56946a66aa | ||
|
|
c9242e32fe | ||
|
|
22e8883934 | ||
|
|
552a18d89a | ||
|
|
6b725e9114 | ||
|
|
415beaa0b0 | ||
|
|
e9fe227ed7 | ||
|
|
c1be109592 | ||
|
|
88e603bbf1 | ||
|
|
c7b2095bb4 | ||
|
|
7396117d89 | ||
|
|
fd96bf345b | ||
|
|
2820660264 | ||
|
|
86145dbf67 | ||
|
|
135b17186e | ||
|
|
ce494339ef | ||
|
|
dd5af7eb10 | ||
|
|
3abe99078e | ||
|
|
edbd540c68 | ||
|
|
06d9302d96 | ||
|
|
032b4bed7f | ||
|
|
8559f5c8ea | ||
|
|
91133172d5 | ||
|
|
001f3f30cd | ||
|
|
a1b1059ad1 | ||
|
|
69a0122fea | ||
|
|
3d505b4248 | ||
|
|
70d4e3394c | ||
|
|
3905c01a0d | ||
|
|
2a49af1ec3 |
19
.babelrc
19
.babelrc
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
["env", {
|
||||
"targets": {
|
||||
"chrome": 40,
|
||||
"firefox": 35,
|
||||
"edge": 14,
|
||||
"node": "6.5"
|
||||
},
|
||||
"modules": false,
|
||||
"useBuiltIns": true
|
||||
}]
|
||||
],
|
||||
"plugins": [
|
||||
["babel-plugin-transform-builtin-extend", {
|
||||
"globals": ["Error"]
|
||||
}]
|
||||
]
|
||||
}
|
||||
@@ -36,7 +36,7 @@ deploy:
|
||||
skip_cleanup: true
|
||||
email: "n1474335@gmail.com"
|
||||
api_key:
|
||||
secure: "Z3FK6bm4RfQEIRXZ1lBNzQkVIoHpivThr9U+XBHmsBgIfdrK/XUnzs/slugo+NIz8nPiGmMx4gxyJonBCLHDGb1ysky2aEWTl26c0teaF4DeQEjWC1ZaGzv8MV1/GkUamnr1qouXjyUhyEAp33rd8ccN9Rq3QNYB/qLDcA9/FCme7JCW6sCd4zWO0LGEYMJEMc2FzAUkqhqsI05hegGhSDgKXRn5PmLARek4yHD+Hx7pstaTeQIy0WoGJjdzoB3iJIMmo/hWZGzZafktUOh223c5qzx4zMpDRNmMngBUw6R94nKd4KvplYRgB87Y3L/aiVU4CF+axwLmK8RPaC1wbJnlHf06zxHPdiFmsY/zKPpNel+nOnxzRrF5l2KMU4TU6gug3s9Jnzp9T5UMfhp0jW3YkxHGeuOPOeE1i0lTUWUGWrPHLQquAhLfkr2zxaU4ETk/y85hq9W4LAy0ENEDVXX2jP7FnI4Z1fdpmljpmVNJR+outPg6t+Coqgvil7v7XpMtDm8lKQanVYuxwmkb/ncOWFRWuM2j5zIEg3CHnFDcJ9bYrfKRg0b0tb/2BWD14pQnV76goVwzJQYVzdPc8TKIYJw2BZ1Nh9c0iruQVebe/6l1FX9fDCkz8VMmltni61/LxZrf8y0NT1YaU1raeNY2dH5UWvEa9p72FPMI6Eg="
|
||||
secure: "UnDQL3Kh+GK2toL0TK3FObO0ujVssU3Eg4BBuYdjwLB81GhiGE5/DTh7THdZPOpbLo6wQeOwfZDuMeKC1OU+0Uf4NsdYFu1aq6xMO20qBQ4qUfgsyiK4Qgywj9gk0p1+OFZdGAZ/j1CNRAaF71XQIY6iV84c+SO4WoizXYrNT0Jh4sr2DA4/97G2xmJtPi0qOzYrJ09R56ZUozmqeik5G0pMRIuJRbpjS/7bZXV+N7WV0ombZc9RkUaetbabEVOLQ+Xx5YAIVq+VuEeMe9VBSnxY/FfCLmy1wJsjGzpLCyBI9nbrG4nw8Wgc2m8NfK9rcpIvBTGner9r2j60NVDkZ8kLZPrqXhq6AZMwa+oz6K5UQCqRo2RRQzSGwXxg67HY5Tcq+oNmjd+DqpPg4LZ3eGlluyP5XfG+hpSr9Ya4d8q8SrUWLxkoLHI6ZKMtoKFbTCSSQPiluW5hsZxjz3yDkkjsJw64M/EM8UyJrgaXqDklQu+7rBGKLfsK6os7RDiqjBWpQ7gwpo8HvY0O8yqEAabPz+QGkanpjcCOZCXFbSkzWxYy37RMAPu88iINVZVlZE4l+WJenCpZY95ueyy0mG9cyMSzVRPyX6A+/n4H6VMFPFjpGDLTD588ACEjY1lmHfS/eXwXJcgqPPD2gW0XdRdUheU/ssqlfCfGWQMTDXs="
|
||||
on:
|
||||
tags: true
|
||||
branch: master
|
||||
|
||||
80
CHANGELOG.md
80
CHANGELOG.md
@@ -1,5 +1,45 @@
|
||||
# Changelog
|
||||
All notable changes to CyberChef will be documented in this file.
|
||||
All major and minor version changes will be documented in this file. Details of patch-level version changes can be found in [commit messages](https://github.com/gchq/CyberChef/commits/master).
|
||||
|
||||
|
||||
### [8.17.0] - 2018-12-25
|
||||
- 'Generate QR Code' and 'Parse QR Code' operations added [@j433866] | [#448]
|
||||
|
||||
### [8.16.0] - 2018-12-19
|
||||
- 'Play Media' operation added [@anthony-arnold] | [#446]
|
||||
|
||||
### [8.15.0] - 2018-12-18
|
||||
- 'Text Encoding Brute Force' operation added [@Cynser] | [#439]
|
||||
|
||||
### [8.14.0] - 2018-12-18
|
||||
- 'To Base62' and 'From Base62' operations added [@tcode2k16] | [#443]
|
||||
|
||||
### [8.13.0] - 2018-12-15
|
||||
- 'A1Z26 Cipher Encode' and 'A1Z26 Cipher Decode' operations added [@jarmovanlenthe] | [#441]
|
||||
|
||||
### [8.12.0] - 2018-11-21
|
||||
- 'Citrix CTX1 Encode' and 'Citrix CTX1 Decode' operations added [@bwhitn] | [#428]
|
||||
|
||||
### [8.11.0] - 2018-11-13
|
||||
- 'CSV to JSON' and 'JSON to CSV' operations added [@n1474335] | [#277]
|
||||
|
||||
### [8.10.0] - 2018-11-07
|
||||
- 'Remove Diacritics' operation added [@klaxon1] | [#387]
|
||||
|
||||
### [8.9.0] - 2018-11-07
|
||||
- 'Defang URL' operation added [@arnydo] | [#394]
|
||||
|
||||
### [8.8.0] - 2018-10-10
|
||||
- 'Parse TLV' operation added [@GCHQ77703] | [#351]
|
||||
|
||||
### [8.7.0] - 2018-08-31
|
||||
- 'JWT Sign', 'JWT Verify' and 'JWT Decode' operations added [@GCHQ77703] | [#348]
|
||||
|
||||
### [8.6.0] - 2018-08-29
|
||||
- 'To Geohash' and 'From Geohash' operations added [@GCHQ77703] | [#344]
|
||||
|
||||
### [8.5.0] - 2018-08-23
|
||||
- 'To Braille' and 'From Braille' operations added [@n1474335] | [#255]
|
||||
|
||||
### [8.4.0] - 2018-08-23
|
||||
- 'To Base85' and 'From Base85' operations added [@PenguinGeorge] | [#340]
|
||||
@@ -31,7 +71,7 @@ All notable changes to CyberChef will be documented in this file.
|
||||
- Added support for loading, processing and downloading files up to 500MB [@n1474335] | [#224]
|
||||
|
||||
## [6.0.0] - 2017-09-19
|
||||
- Threading support added. All recipe processing moved into a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) to increase performance and allowing long-running operations to be cancelled [@n1474335] | [#173]
|
||||
- Threading support added. All recipe processing moved into a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) to increase performance and to allow long-running operations to be cancelled [@n1474335] | [#173]
|
||||
- Module system created so that operations relying on large libraries can be downloaded separately as required, reducing the initial loading time for the app [@n1474335] | [#173]
|
||||
|
||||
## [5.0.0] - 2017-03-30
|
||||
@@ -41,6 +81,20 @@ All notable changes to CyberChef will be documented in this file.
|
||||
- Initial open source commit [@n1474335] | [b1d73a72](https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306)
|
||||
|
||||
|
||||
|
||||
[8.17.0]: https://github.com/gchq/CyberChef/releases/tag/v8.17.0
|
||||
[8.16.0]: https://github.com/gchq/CyberChef/releases/tag/v8.16.0
|
||||
[8.15.0]: https://github.com/gchq/CyberChef/releases/tag/v8.15.0
|
||||
[8.14.0]: https://github.com/gchq/CyberChef/releases/tag/v8.14.0
|
||||
[8.13.0]: https://github.com/gchq/CyberChef/releases/tag/v8.13.0
|
||||
[8.12.0]: https://github.com/gchq/CyberChef/releases/tag/v8.12.0
|
||||
[8.11.0]: https://github.com/gchq/CyberChef/releases/tag/v8.11.0
|
||||
[8.10.0]: https://github.com/gchq/CyberChef/releases/tag/v8.10.0
|
||||
[8.9.0]: https://github.com/gchq/CyberChef/releases/tag/v8.9.0
|
||||
[8.8.0]: https://github.com/gchq/CyberChef/releases/tag/v8.8.0
|
||||
[8.7.0]: https://github.com/gchq/CyberChef/releases/tag/v8.7.0
|
||||
[8.6.0]: https://github.com/gchq/CyberChef/releases/tag/v8.6.0
|
||||
[8.5.0]: https://github.com/gchq/CyberChef/releases/tag/v8.5.0
|
||||
[8.4.0]: https://github.com/gchq/CyberChef/releases/tag/v8.4.0
|
||||
[8.3.0]: https://github.com/gchq/CyberChef/releases/tag/v8.3.0
|
||||
[8.2.0]: https://github.com/gchq/CyberChef/releases/tag/v8.2.0
|
||||
@@ -53,18 +107,29 @@ All notable changes to CyberChef will be documented in this file.
|
||||
|
||||
[@n1474335]: https://github.com/n1474335
|
||||
[@d98762625]: https://github.com/d98762625
|
||||
[@j433866]: https://github.com/j433866
|
||||
[@GCHQ77703]: https://github.com/GCHQ77703
|
||||
[@artemisbot]: https://github.com/artemisbot
|
||||
[@picapi]: https://github.com/picapi
|
||||
[@Dachande663]: https://github.com/Dachande663
|
||||
[@JustAnotherMark]: https://github.com/JustAnotherMark
|
||||
[@sevzero]: https://github.com/sevzero
|
||||
[@PenguinGeorge]: https://github.com/PenguinGeorge
|
||||
[@arnydo]: https://github.com/arnydo
|
||||
[@klaxon1]: https://github.com/klaxon1
|
||||
[@bwhitn]: https://github.com/bwhitn
|
||||
[@jarmovanlenthe]: https://github.com/jarmovanlenthe
|
||||
[@tcode2k16]: https://github.com/tcode2k16
|
||||
[@Cynser]: https://github.com/Cynser
|
||||
[@anthony-arnold]: https://github.com/anthony-arnold
|
||||
|
||||
[#95]: https://github.com/gchq/CyberChef/pull/299
|
||||
[#173]: https://github.com/gchq/CyberChef/pull/173
|
||||
[#224]: https://github.com/gchq/CyberChef/pull/224
|
||||
[#239]: https://github.com/gchq/CyberChef/pull/239
|
||||
[#248]: https://github.com/gchq/CyberChef/pull/248
|
||||
[#255]: https://github.com/gchq/CyberChef/issues/255
|
||||
[#277]: https://github.com/gchq/CyberChef/issues/277
|
||||
[#281]: https://github.com/gchq/CyberChef/pull/281
|
||||
[#284]: https://github.com/gchq/CyberChef/pull/284
|
||||
[#294]: https://github.com/gchq/CyberChef/pull/294
|
||||
@@ -74,3 +139,14 @@ All notable changes to CyberChef will be documented in this file.
|
||||
[#325]: https://github.com/gchq/CyberChef/pull/325
|
||||
[#338]: https://github.com/gchq/CyberChef/pull/338
|
||||
[#340]: https://github.com/gchq/CyberChef/pull/340
|
||||
[#344]: https://github.com/gchq/CyberChef/pull/344
|
||||
[#348]: https://github.com/gchq/CyberChef/pull/348
|
||||
[#351]: https://github.com/gchq/CyberChef/pull/351
|
||||
[#387]: https://github.com/gchq/CyberChef/pull/387
|
||||
[#394]: https://github.com/gchq/CyberChef/pull/394
|
||||
[#428]: https://github.com/gchq/CyberChef/pull/428
|
||||
[#439]: https://github.com/gchq/CyberChef/pull/439
|
||||
[#441]: https://github.com/gchq/CyberChef/pull/441
|
||||
[#443]: https://github.com/gchq/CyberChef/pull/443
|
||||
[#446]: https://github.com/gchq/CyberChef/pull/446
|
||||
[#448]: https://github.com/gchq/CyberChef/pull/448
|
||||
|
||||
18
Gruntfile.js
18
Gruntfile.js
@@ -22,7 +22,7 @@ module.exports = function (grunt) {
|
||||
// Tasks
|
||||
grunt.registerTask("dev",
|
||||
"A persistent task which creates a development build whenever source files are modified.",
|
||||
["clean:dev", "exec:generateConfig", "concurrent:dev"]);
|
||||
["clean:dev", "clean:config", "exec:generateConfig", "concurrent:dev"]);
|
||||
|
||||
grunt.registerTask("node",
|
||||
"Compiles CyberChef into a single NodeJS module.",
|
||||
@@ -38,7 +38,7 @@ module.exports = function (grunt) {
|
||||
|
||||
grunt.registerTask("prod",
|
||||
"Creates a production-ready build. Use the --msg flag to add a compile message.",
|
||||
["eslint", "clean:prod", "exec:generateConfig", "webpack:web", "inline", "chmod"]);
|
||||
["eslint", "clean:prod", "clean:config", "exec:generateConfig", "webpack:web", "inline", "chmod"]);
|
||||
|
||||
grunt.registerTask("default",
|
||||
"Lints the code base",
|
||||
@@ -143,7 +143,7 @@ module.exports = function (grunt) {
|
||||
options: {
|
||||
configFile: "./.eslintrc.json"
|
||||
},
|
||||
configs: ["Gruntfile.js"],
|
||||
configs: ["*.js"],
|
||||
core: ["src/core/**/*.{js,mjs}", "!src/core/vendor/**/*", "!src/core/operations/legacy/**/*"],
|
||||
web: ["src/web/**/*.{js,mjs}"],
|
||||
node: ["src/node/**/*.{js,mjs}"],
|
||||
@@ -280,7 +280,11 @@ module.exports = function (grunt) {
|
||||
chunks: false,
|
||||
modules: false,
|
||||
entrypoints: false,
|
||||
warningsFilter: [/source-map/, /dependency is an expression/],
|
||||
warningsFilter: [
|
||||
/source-map/,
|
||||
/dependency is an expression/,
|
||||
/export 'default'/
|
||||
],
|
||||
}
|
||||
},
|
||||
start: {
|
||||
@@ -382,13 +386,13 @@ module.exports = function (grunt) {
|
||||
"mkdir -p src/core/config/modules",
|
||||
"echo 'export default {};\n' > src/core/config/modules/OpModules.mjs",
|
||||
"echo '[]\n' > src/core/config/OperationConfig.json",
|
||||
"node --experimental-modules src/core/config/scripts/generateOpsIndex.mjs",
|
||||
"node --experimental-modules src/core/config/scripts/generateConfig.mjs",
|
||||
"node --experimental-modules --no-warnings --no-deprecation src/core/config/scripts/generateOpsIndex.mjs",
|
||||
"node --experimental-modules --no-warnings --no-deprecation src/core/config/scripts/generateConfig.mjs",
|
||||
"echo '--- Config scripts finished. ---\n'"
|
||||
].join(";")
|
||||
},
|
||||
tests: {
|
||||
command: "node --experimental-modules test/index.mjs"
|
||||
command: "node --experimental-modules --no-warnings --no-deprecation test/index.mjs"
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
23
babel.config.js
Normal file
23
babel.config.js
Normal file
@@ -0,0 +1,23 @@
|
||||
module.exports = function(api) {
|
||||
api.cache.forever();
|
||||
|
||||
return {
|
||||
"presets": [
|
||||
["@babel/preset-env", {
|
||||
"targets": {
|
||||
"chrome": 40,
|
||||
"firefox": 35,
|
||||
"edge": 14,
|
||||
"node": "6.5"
|
||||
},
|
||||
"modules": false,
|
||||
"useBuiltIns": "entry"
|
||||
}]
|
||||
],
|
||||
"plugins": [
|
||||
["babel-plugin-transform-builtin-extend", {
|
||||
"globals": ["Error"]
|
||||
}]
|
||||
]
|
||||
};
|
||||
};
|
||||
6124
package-lock.json
generated
6124
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
77
package.json
77
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "8.4.3",
|
||||
"version": "8.17.0",
|
||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||
"author": "n1474335 <n1474335@gmail.com>",
|
||||
"homepage": "https://gchq.github.io/CyberChef",
|
||||
@@ -30,45 +30,44 @@
|
||||
"main": "build/node/CyberChef.js",
|
||||
"bugs": "https://github.com/gchq/CyberChef/issues",
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^9.1.0",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-loader": "^7.1.5",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"@babel/core": "^7.1.5",
|
||||
"@babel/preset-env": "^7.1.5",
|
||||
"autoprefixer": "^9.3.1",
|
||||
"babel-loader": "^8.0.4",
|
||||
"bootstrap": "^4.1.3",
|
||||
"colors": "^1.3.1",
|
||||
"css-loader": "^1.0.0",
|
||||
"eslint": "^5.3.0",
|
||||
"colors": "^1.3.2",
|
||||
"css-loader": "^1.0.1",
|
||||
"eslint": "^5.8.0",
|
||||
"exports-loader": "^0.7.0",
|
||||
"extract-text-webpack-plugin": "^4.0.0-alpha0",
|
||||
"file-loader": "^1.1.11",
|
||||
"file-loader": "^2.0.0",
|
||||
"grunt": "^1.0.3",
|
||||
"grunt-accessibility": "~6.0.0",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-concurrent": "^2.3.1",
|
||||
"grunt-contrib-clean": "~1.1.0",
|
||||
"grunt-contrib-clean": "~2.0.0",
|
||||
"grunt-contrib-copy": "~1.0.0",
|
||||
"grunt-contrib-watch": "^1.1.0",
|
||||
"grunt-eslint": "^21.0.0",
|
||||
"grunt-exec": "~3.0.0",
|
||||
"grunt-jsdoc": "^2.2.1",
|
||||
"grunt-webpack": "^3.1.2",
|
||||
"grunt-jsdoc": "^2.3.0",
|
||||
"grunt-webpack": "^3.1.3",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"imports-loader": "^0.8.0",
|
||||
"ink-docstrap": "^1.3.2",
|
||||
"js-to-mjs": "^0.2.0",
|
||||
"jsdoc-babel": "^0.4.0",
|
||||
"node-sass": "^4.9.2",
|
||||
"postcss-css-variables": "^0.9.0",
|
||||
"postcss-import": "^12.0.0",
|
||||
"postcss-loader": "^2.1.6",
|
||||
"jsdoc-babel": "^0.5.0",
|
||||
"node-sass": "^4.10.0",
|
||||
"postcss-css-variables": "^0.11.0",
|
||||
"postcss-import": "^12.0.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"prompt": "^1.0.0",
|
||||
"sass-loader": "^7.1.0",
|
||||
"sitemap": "^1.13.0",
|
||||
"style-loader": "^0.21.0",
|
||||
"url-loader": "^1.0.1",
|
||||
"sitemap": "^2.1.0",
|
||||
"style-loader": "^0.23.1",
|
||||
"url-loader": "^1.1.2",
|
||||
"web-resource-inliner": "^4.2.1",
|
||||
"webpack": "^4.16.4",
|
||||
"webpack-dev-server": "^3.1.5",
|
||||
"webpack": "^4.25.1",
|
||||
"webpack-dev-server": "^3.1.10",
|
||||
"webpack-node-externals": "^1.7.2",
|
||||
"worker-loader": "^2.0.0"
|
||||
},
|
||||
@@ -77,47 +76,52 @@
|
||||
"babel-plugin-transform-builtin-extend": "1.1.2",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"bignumber.js": "^7.2.1",
|
||||
"bignumber.js": "^8.0.1",
|
||||
"bootstrap-colorpicker": "^2.5.3",
|
||||
"bootstrap-material-design": "^4.1.1",
|
||||
"bson": "^3.0.2",
|
||||
"chi-squared": "^1.1.0",
|
||||
"crypto-api": "^0.8.0",
|
||||
"crypto-api": "^0.8.3",
|
||||
"crypto-js": "^3.1.9-1",
|
||||
"ctph.js": "0.0.5",
|
||||
"diff": "^3.5.0",
|
||||
"es6-promisify": "^6.0.0",
|
||||
"es6-promisify": "^6.0.1",
|
||||
"escodegen": "^1.11.0",
|
||||
"esmangle": "^1.0.1",
|
||||
"esprima": "^4.0.1",
|
||||
"exif-parser": "^0.1.12",
|
||||
"file-saver": "^1.3.8",
|
||||
"highlight.js": "^9.12.0",
|
||||
"file-saver": "^2.0.0-rc.4",
|
||||
"highlight.js": "^9.13.1",
|
||||
"jimp": "^0.6.0",
|
||||
"jquery": "^3.3.1",
|
||||
"js-crc": "^0.2.0",
|
||||
"js-sha3": "^0.7.0",
|
||||
"js-sha3": "^0.8.0",
|
||||
"jsbn": "^1.1.0",
|
||||
"jsesc": "^2.5.1",
|
||||
"jsonpath": "^1.0.0",
|
||||
"jsonwebtoken": "^8.3.0",
|
||||
"jsqr": "^1.1.1",
|
||||
"jsrsasign": "8.0.12",
|
||||
"kbpgp": "^2.0.77",
|
||||
"lodash": "^4.17.10",
|
||||
"kbpgp": "^2.0.82",
|
||||
"lodash": "^4.17.11",
|
||||
"loglevel": "^1.6.1",
|
||||
"loglevel-message-prefix": "^3.0.0",
|
||||
"moment": "^2.22.2",
|
||||
"moment-timezone": "^0.5.21",
|
||||
"node-forge": "^0.7.5",
|
||||
"moment-timezone": "^0.5.23",
|
||||
"ngeohash": "^0.6.0",
|
||||
"node-forge": "^0.7.6",
|
||||
"node-md6": "^0.1.0",
|
||||
"notepack.io": "^2.1.3",
|
||||
"nwmatcher": "^1.4.4",
|
||||
"otp": "^0.1.3",
|
||||
"popper.js": "^1.14.4",
|
||||
"qr-image": "^3.2.0",
|
||||
"scryptsy": "^2.0.0",
|
||||
"snackbarjs": "^1.1.0",
|
||||
"sortablejs": "^1.7.0",
|
||||
"split.js": "^1.3.5",
|
||||
"split.js": "^1.5.9",
|
||||
"ssdeep.js": "0.0.2",
|
||||
"ua-parser-js": "^0.7.18",
|
||||
"ua-parser-js": "^0.7.19",
|
||||
"utf8": "^3.0.0",
|
||||
"vkbeautify": "^0.99.3",
|
||||
"xmldom": "^0.1.27",
|
||||
@@ -131,7 +135,6 @@
|
||||
"test": "grunt test",
|
||||
"docs": "grunt docs",
|
||||
"lint": "grunt lint",
|
||||
"newop": "node --experimental-modules src/core/config/scripts/newOperation.mjs",
|
||||
"postinstall": "[ -f node_modules/crypto-api/src/crypto-api.mjs ] || npx j2m node_modules/crypto-api/src/crypto-api.js"
|
||||
"newop": "node --experimental-modules src/core/config/scripts/newOperation.mjs"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ class Dish {
|
||||
this.value = this.value instanceof BigNumber ? Utils.strToByteArray(this.value.toFixed()) : [];
|
||||
break;
|
||||
case Dish.JSON:
|
||||
this.value = this.value ? Utils.strToByteArray(JSON.stringify(this.value)) : [];
|
||||
this.value = this.value ? Utils.strToByteArray(JSON.stringify(this.value, null, 4)) : [];
|
||||
break;
|
||||
case Dish.FILE:
|
||||
this.value = await Utils.readFile(this.value);
|
||||
|
||||
@@ -25,6 +25,7 @@ class Ingredient {
|
||||
this.hint = "";
|
||||
this.toggleValues = [];
|
||||
this.target = null;
|
||||
this.defaultIndex = 0;
|
||||
|
||||
if (ingredientConfig) {
|
||||
this._parseConfig(ingredientConfig);
|
||||
@@ -46,6 +47,7 @@ class Ingredient {
|
||||
this.hint = ingredientConfig.hint || false;
|
||||
this.toggleValues = ingredientConfig.toggleValues;
|
||||
this.target = typeof ingredientConfig.target !== "undefined" ? ingredientConfig.target : null;
|
||||
this.defaultIndex = typeof ingredientConfig.defaultIndex !== "undefined" ? ingredientConfig.defaultIndex : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -181,6 +181,7 @@ class Operation {
|
||||
if (ing.hint) conf.hint = ing.hint;
|
||||
if (ing.disabled) conf.disabled = ing.disabled;
|
||||
if (ing.target) conf.target = ing.target;
|
||||
if (ing.defaultIndex) conf.defaultIndex = ing.defaultIndex;
|
||||
return conf;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import moment from "moment-timezone";
|
||||
import {fromBase64} from "./lib/Base64";
|
||||
import {fromHex} from "./lib/Hex";
|
||||
import {fromDecimal} from "./lib/Decimal";
|
||||
import {fromBinary} from "./lib/Binary";
|
||||
|
||||
|
||||
/**
|
||||
@@ -298,7 +299,7 @@ class Utils {
|
||||
* Accepts hex, Base64, UTF8 and Latin1 strings.
|
||||
*
|
||||
* @param {string} str
|
||||
* @param {string} type - One of "Hex", "Decimal", "Base64", "UTF8" or "Latin1"
|
||||
* @param {string} type - One of "Binary", "Hex", "Decimal", "Base64", "UTF8" or "Latin1"
|
||||
* @returns {byteArray}
|
||||
*
|
||||
* @example
|
||||
@@ -313,6 +314,8 @@ class Utils {
|
||||
*/
|
||||
static convertToByteArray(str, type) {
|
||||
switch (type.toLowerCase()) {
|
||||
case "binary":
|
||||
return fromBinary(str);
|
||||
case "hex":
|
||||
return fromHex(str);
|
||||
case "decimal":
|
||||
@@ -333,7 +336,7 @@ class Utils {
|
||||
* Accepts hex, Base64, UTF8 and Latin1 strings.
|
||||
*
|
||||
* @param {string} str
|
||||
* @param {string} type - One of "Hex", "Decimal", "Base64", "UTF8" or "Latin1"
|
||||
* @param {string} type - One of "Binary", "Hex", "Decimal", "Base64", "UTF8" or "Latin1"
|
||||
* @returns {string}
|
||||
*
|
||||
* @example
|
||||
@@ -348,6 +351,8 @@ class Utils {
|
||||
*/
|
||||
static convertToByteString(str, type) {
|
||||
switch (type.toLowerCase()) {
|
||||
case "binary":
|
||||
return Utils.byteArrayToChars(fromBinary(str));
|
||||
case "hex":
|
||||
return Utils.byteArrayToChars(fromHex(str));
|
||||
case "decimal":
|
||||
@@ -555,8 +560,6 @@ class Utils {
|
||||
if (renderNext) {
|
||||
cell += b;
|
||||
renderNext = false;
|
||||
} else if (b === "\\") {
|
||||
renderNext = true;
|
||||
} else if (b === "\"" && !inString) {
|
||||
inString = true;
|
||||
} else if (b === "\"" && inString) {
|
||||
@@ -570,6 +573,10 @@ class Utils {
|
||||
cell = "";
|
||||
lines.push(line);
|
||||
line = [];
|
||||
// Skip next byte if it is also a line delim (e.g. \r\n)
|
||||
if (lineDelims.indexOf(next) >= 0 && next !== b) {
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
cell += b;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
"From Base32",
|
||||
"To Base58",
|
||||
"From Base58",
|
||||
"To Base62",
|
||||
"From Base62",
|
||||
"To Base85",
|
||||
"From Base85",
|
||||
"To Base",
|
||||
@@ -49,9 +51,15 @@
|
||||
"Change IP format",
|
||||
"Encode text",
|
||||
"Decode text",
|
||||
"Text Encoding Brute Force",
|
||||
"Swap endianness",
|
||||
"To MessagePack",
|
||||
"From MessagePack"
|
||||
"From MessagePack",
|
||||
"To Braille",
|
||||
"From Braille",
|
||||
"Parse TLV",
|
||||
"CSV to JSON",
|
||||
"JSON to CSV"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -81,12 +89,19 @@
|
||||
"Bifid Cipher Decode",
|
||||
"Affine Cipher Encode",
|
||||
"Affine Cipher Decode",
|
||||
"A1Z26 Cipher Encode",
|
||||
"A1Z26 Cipher Decode",
|
||||
"Atbash Cipher",
|
||||
"Substitute",
|
||||
"Derive PBKDF2 key",
|
||||
"Derive EVP key",
|
||||
"Bcrypt",
|
||||
"Scrypt",
|
||||
"JWT Sign",
|
||||
"JWT Verify",
|
||||
"JWT Decode",
|
||||
"Citrix CTX1 Encode",
|
||||
"Citrix CTX1 Decode",
|
||||
"Pseudo-Random Number Generator"
|
||||
]
|
||||
},
|
||||
@@ -153,7 +168,8 @@
|
||||
"Change IP format",
|
||||
"Group IP addresses",
|
||||
"Encode NetBIOS Name",
|
||||
"Decode NetBIOS Name"
|
||||
"Decode NetBIOS Name",
|
||||
"Defang URL"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -161,6 +177,7 @@
|
||||
"ops": [
|
||||
"Encode text",
|
||||
"Decode text",
|
||||
"Remove Diacritics",
|
||||
"Unescape Unicode Characters"
|
||||
]
|
||||
},
|
||||
@@ -287,7 +304,9 @@
|
||||
"Adler-32 Checksum",
|
||||
"CRC-16 Checksum",
|
||||
"CRC-32 Checksum",
|
||||
"TCP/IP Checksum"
|
||||
"TCP/IP Checksum",
|
||||
"To Geohash",
|
||||
"From Geohash"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -322,23 +341,31 @@
|
||||
"From MessagePack"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Forensics",
|
||||
"ops": [
|
||||
"Detect File Type",
|
||||
"Scan for Embedded Files",
|
||||
"Remove EXIF",
|
||||
"Extract EXIF",
|
||||
"Render Image",
|
||||
"Play Media"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Other",
|
||||
"ops": [
|
||||
"Entropy",
|
||||
"Frequency distribution",
|
||||
"Chi Square",
|
||||
"Detect File Type",
|
||||
"Scan for Embedded Files",
|
||||
"Disassemble x86",
|
||||
"Pseudo-Random Number Generator",
|
||||
"Generate UUID",
|
||||
"Generate TOTP",
|
||||
"Generate HOTP",
|
||||
"Generate QR Code",
|
||||
"Parse QR Code",
|
||||
"Haversine distance",
|
||||
"Render Image",
|
||||
"Remove EXIF",
|
||||
"Extract EXIF",
|
||||
"Numberwang",
|
||||
"XKCD Random Number"
|
||||
]
|
||||
|
||||
@@ -126,14 +126,14 @@ export function fromBase64(data, alphabet="A-Za-z0-9+/=", returnType="string", r
|
||||
* Base64 alphabets.
|
||||
*/
|
||||
export const ALPHABET_OPTIONS = [
|
||||
{name: "Standard: A-Za-z0-9+/=", value: "A-Za-z0-9+/="},
|
||||
{name: "URL safe: A-Za-z0-9-_", value: "A-Za-z0-9-_"},
|
||||
{name: "Standard (RFC 4648): A-Za-z0-9+/=", value: "A-Za-z0-9+/="},
|
||||
{name: "URL safe (RFC 4648 \u00A75): A-Za-z0-9-_", value: "A-Za-z0-9-_"},
|
||||
{name: "Filename safe: A-Za-z0-9+-=", value: "A-Za-z0-9+\\-="},
|
||||
{name: "itoa64: ./0-9A-Za-z=", value: "./0-9A-Za-z="},
|
||||
{name: "XML: A-Za-z0-9_.", value: "A-Za-z0-9_."},
|
||||
{name: "y64: A-Za-z0-9._-", value: "A-Za-z0-9._-"},
|
||||
{name: "z64: 0-9a-zA-Z+/=", value: "0-9a-zA-Z+/="},
|
||||
{name: "Radix-64: 0-9A-Za-z+/=", value: "0-9A-Za-z+/="},
|
||||
{name: "Radix-64 (RFC 4880): 0-9A-Za-z+/=", value: "0-9A-Za-z+/="},
|
||||
{name: "Uuencoding: [space]-_", value: " -_"},
|
||||
{name: "Xxencoding: +-0-9A-Za-z", value: "+\\-0-9A-Za-z"},
|
||||
{name: "BinHex: !-,-0-689@A-NP-VX-Z[`a-fh-mp-r", value: "!-,-0-689@A-NP-VX-Z[`a-fh-mp-r"},
|
||||
|
||||
70
src/core/lib/Binary.mjs
Normal file
70
src/core/lib/Binary.mjs
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Binary functions.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Utils from "../Utils";
|
||||
|
||||
|
||||
/**
|
||||
* Convert a byte array into a binary string.
|
||||
*
|
||||
* @param {Uint8Array|byteArray} data
|
||||
* @param {string} [delim="Space"]
|
||||
* @param {number} [padding=8]
|
||||
* @returns {string}
|
||||
*
|
||||
* @example
|
||||
* // returns "00010000 00100000 00110000"
|
||||
* toBinary([10,20,30]);
|
||||
*
|
||||
* // returns "00010000 00100000 00110000"
|
||||
* toBinary([10,20,30], ":");
|
||||
*/
|
||||
export function toBinary(data, delim="Space", padding=8) {
|
||||
if (!data) return "";
|
||||
|
||||
delim = Utils.charRep(delim);
|
||||
let output = "";
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
output += data[i].toString(2).padStart(padding, "0") + delim;
|
||||
}
|
||||
|
||||
if (delim.length) {
|
||||
return output.slice(0, -delim.length);
|
||||
} else {
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a binary string into a byte array.
|
||||
*
|
||||
* @param {string} data
|
||||
* @param {string} [delim]
|
||||
* @param {number} [byteLen=8]
|
||||
* @returns {byteArray}
|
||||
*
|
||||
* @example
|
||||
* // returns [10,20,30]
|
||||
* fromBinary("00010000 00100000 00110000");
|
||||
*
|
||||
* // returns [10,20,30]
|
||||
* fromBinary("00010000:00100000:00110000", "Colon");
|
||||
*/
|
||||
export function fromBinary(data, delim="Space", byteLen=8) {
|
||||
const delimRegex = Utils.regexRep(delim);
|
||||
data = data.replace(delimRegex, "");
|
||||
|
||||
const output = [];
|
||||
for (let i = 0; i < data.length; i += byteLen) {
|
||||
output.push(parseInt(data.substr(i, byteLen), 2));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ export function bitOp (input, key, func, nullPreserving, scheme) {
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
k = key[i % key.length];
|
||||
if (scheme === "Cascade") k = input[i + 1] || 0;
|
||||
o = input[i];
|
||||
x = nullPreserving && (o === 0 || o === k) ? o : func(o, k);
|
||||
result.push(x);
|
||||
@@ -115,3 +116,9 @@ export function sub(operand, key) {
|
||||
const result = operand - key;
|
||||
return (result < 0) ? 256 + result : result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delimiter options for bitwise operations
|
||||
*/
|
||||
export const BITWISE_OP_DELIMS = ["Hex", "Decimal", "Binary", "Base64", "UTF8", "Latin1"];
|
||||
|
||||
15
src/core/lib/Braille.mjs
Normal file
15
src/core/lib/Braille.mjs
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Braille resources.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Braille lookup table.
|
||||
*/
|
||||
export const BRAILLE_LOOKUP = {
|
||||
ascii: " A1B'K2L@CIF/MSP\"E3H9O6R^DJG>NTQ,*5<-U8V.%[$+X!&;:4\\0Z7(_?W]#Y)=",
|
||||
dot6: "⠀⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿"
|
||||
};
|
||||
@@ -39,3 +39,21 @@ export function search (input, searchRegex, removeRegex, includeTotal) {
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* URL regular expression
|
||||
*/
|
||||
const protocol = "[A-Z]+://",
|
||||
hostname = "[-\\w]+(?:\\.\\w[-\\w]*)+",
|
||||
port = ":\\d+",
|
||||
path = "/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*" +
|
||||
"(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*";
|
||||
|
||||
export const URL_REGEX = new RegExp(protocol + hostname + "(?:" + port + ")?(?:" + path + ")?", "ig");
|
||||
|
||||
|
||||
/**
|
||||
* Domain name regular expression
|
||||
*/
|
||||
export const DOMAIN_REGEX = /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/ig;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* @author picapi
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @author Klaxon [klaxon@veyr.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
@@ -109,8 +110,8 @@ export function ipv6CidrRange(cidr, includeNetworkInfo) {
|
||||
* @returns {string}
|
||||
*/
|
||||
export function ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddresses, allowLargeList) {
|
||||
const ip1 = strToIpv4(range[1]),
|
||||
ip2 = strToIpv4(range[2]);
|
||||
const ip1 = strToIpv4(range[0].split("-")[0].trim()),
|
||||
ip2 = strToIpv4(range[0].split("-")[1].trim());
|
||||
|
||||
let output = "";
|
||||
|
||||
@@ -162,8 +163,8 @@ Total addresses in range: ${(((ip2 - ip1) >>> 0) + 1)}
|
||||
* @returns {string}
|
||||
*/
|
||||
export function ipv6HyphenatedRange(range, includeNetworkInfo) {
|
||||
const ip1 = strToIpv6(range[1]),
|
||||
ip2 = strToIpv6(range[14]),
|
||||
const ip1 = strToIpv6(range[0].split("-")[0].trim()),
|
||||
ip2 = strToIpv6(range[0].split("-")[1].trim()),
|
||||
total = new Array(128).fill();
|
||||
|
||||
let output = "",
|
||||
@@ -188,6 +189,93 @@ export function ipv6HyphenatedRange(range, includeNetworkInfo) {
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a list of IPv4 addresses separated by a new line (\n) and displays information
|
||||
* about it.
|
||||
*
|
||||
* @param {RegExp} list
|
||||
* @param {boolean} includeNetworkInfo
|
||||
* @param {boolean} enumerateAddresses
|
||||
* @param {boolean} allowLargeList
|
||||
* @returns {string}
|
||||
*/
|
||||
export function ipv4ListedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList) {
|
||||
|
||||
let ipv4List = match[0].split("\n");
|
||||
ipv4List = ipv4List.filter(Boolean);
|
||||
|
||||
const ipv4CidrList = ipv4List.filter(function(a) {
|
||||
return a.includes("/");
|
||||
});
|
||||
for (let i = 0; i < ipv4CidrList.length; i++) {
|
||||
const network = strToIpv4(ipv4CidrList[i].split("/")[0]);
|
||||
const cidrRange = parseInt(ipv4CidrList[i].split("/")[1], 10);
|
||||
if (cidrRange < 0 || cidrRange > 31) {
|
||||
return "IPv4 CIDR must be less than 32";
|
||||
}
|
||||
const mask = ~(0xFFFFFFFF >>> cidrRange),
|
||||
cidrIp1 = network & mask,
|
||||
cidrIp2 = cidrIp1 | ~mask;
|
||||
ipv4List.splice(ipv4List.indexOf(ipv4CidrList[i]), 1);
|
||||
ipv4List.push(ipv4ToStr(cidrIp1), ipv4ToStr(cidrIp2));
|
||||
}
|
||||
|
||||
ipv4List = ipv4List.sort(ipv4Compare);
|
||||
const ip1 = ipv4List[0];
|
||||
const ip2 = ipv4List[ipv4List.length - 1];
|
||||
const range = [ip1 + " - " + ip2];
|
||||
return ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddresses, allowLargeList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a list of IPv6 addresses separated by a new line (\n) and displays information
|
||||
* about it.
|
||||
*
|
||||
* @param {RegExp} list
|
||||
* @param {boolean} includeNetworkInfo
|
||||
* @returns {string}
|
||||
*/
|
||||
export function ipv6ListedRange(match, includeNetworkInfo) {
|
||||
|
||||
let ipv6List = match[0].split("\n");
|
||||
ipv6List = ipv6List.filter(function(str) {
|
||||
return str.trim();
|
||||
});
|
||||
for (let i =0; i < ipv6List.length; i++){
|
||||
ipv6List[i] = ipv6List[i].trim();
|
||||
}
|
||||
const ipv6CidrList = ipv6List.filter(function(a) {
|
||||
return a.includes("/");
|
||||
});
|
||||
|
||||
for (let i = 0; i < ipv6CidrList.length; i++) {
|
||||
|
||||
const network = strToIpv6(ipv6CidrList[i].split("/")[0]);
|
||||
const cidrRange = parseInt(ipv6CidrList[i].split("/")[1], 10);
|
||||
|
||||
if (cidrRange < 0 || cidrRange > 127) {
|
||||
return "IPv6 CIDR must be less than 128";
|
||||
}
|
||||
|
||||
const cidrIp1 = new Array(8),
|
||||
cidrIp2 = new Array(8);
|
||||
|
||||
const mask = genIpv6Mask(cidrRange);
|
||||
|
||||
for (let j = 0; j < 8; j++) {
|
||||
cidrIp1[j] = network[j] & mask[j];
|
||||
cidrIp2[j] = cidrIp1[j] | (~mask[j] & 0x0000FFFF);
|
||||
}
|
||||
ipv6List.splice(ipv6List.indexOf(ipv6CidrList[i]), 1);
|
||||
ipv6List.push(ipv6ToStr(cidrIp1), ipv6ToStr(cidrIp2));
|
||||
}
|
||||
ipv6List = ipv6List.sort(ipv6Compare);
|
||||
const ip1 = ipv6List[0];
|
||||
const ip2 = ipv6List[ipv6List.length - 1];
|
||||
const range = [ip1 + " - " + ip2];
|
||||
return ipv6HyphenatedRange(range, includeNetworkInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an IPv4 address from string format to numerical format.
|
||||
*
|
||||
@@ -391,6 +479,37 @@ export function genIpv6Mask(cidr) {
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparison operation for sorting of IPv4 addresses.
|
||||
*
|
||||
* @param {string} a
|
||||
* @param {string} b
|
||||
* @returns {number}
|
||||
*/
|
||||
export function ipv4Compare(a, b) {
|
||||
return strToIpv4(a) - strToIpv4(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparison operation for sorting of IPv6 addresses.
|
||||
*
|
||||
* @param {string} a
|
||||
* @param {string} b
|
||||
* @returns {number}
|
||||
*/
|
||||
export function ipv6Compare(a, b) {
|
||||
|
||||
const a_ = strToIpv6(a),
|
||||
b_ = strToIpv6(b);
|
||||
|
||||
for (let i = 0; i < a_.length; i++){
|
||||
if (a_[i] !== b_[i]){
|
||||
return a_[i] - b_[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const _LARGE_RANGE_ERROR = "The specified range contains more than 65,536 addresses. Running this query could crash your browser. If you want to run it, select the \"Allow large queries\" option. You are advised to turn off \"Auto Bake\" whilst editing large ranges.";
|
||||
|
||||
/**
|
||||
|
||||
@@ -265,9 +265,10 @@ class Magic {
|
||||
* performance)
|
||||
* @param {Object[]} [recipeConfig=[]] - The recipe configuration up to this point
|
||||
* @param {boolean} [useful=false] - Whether the current recipe should be scored highly
|
||||
* @param {string} [crib=null] - The regex crib provided by the user, for filtering the operation output
|
||||
* @returns {Object[]} - A sorted list of the recipes most likely to result in correct decoding
|
||||
*/
|
||||
async speculativeExecution(depth=0, extLang=false, intensive=false, recipeConfig=[], useful=false) {
|
||||
async speculativeExecution(depth=0, extLang=false, intensive=false, recipeConfig=[], useful=false, crib=null) {
|
||||
if (depth < 0) return [];
|
||||
|
||||
// Find any operations that can be run on this data
|
||||
@@ -284,9 +285,9 @@ class Magic {
|
||||
isUTF8: this.isUTF8(),
|
||||
entropy: this.calcEntropy(),
|
||||
matchingOps: matchingOps,
|
||||
useful: useful
|
||||
useful: useful,
|
||||
matchesCrib: crib && crib.test(this.inputStr)
|
||||
});
|
||||
|
||||
const prevOp = recipeConfig[recipeConfig.length - 1];
|
||||
|
||||
// Execute each of the matching operations, then recursively call the speculativeExecution()
|
||||
@@ -305,7 +306,7 @@ class Magic {
|
||||
|
||||
const magic = new Magic(output, this.opPatterns),
|
||||
speculativeResults = await magic.speculativeExecution(
|
||||
depth-1, extLang, intensive, [...recipeConfig, opConfig], op.useful);
|
||||
depth-1, extLang, intensive, [...recipeConfig, opConfig], op.useful, crib);
|
||||
|
||||
results = results.concat(speculativeResults);
|
||||
}));
|
||||
@@ -317,7 +318,7 @@ class Magic {
|
||||
await Promise.all(bfEncodings.map(async enc => {
|
||||
const magic = new Magic(enc.data, this.opPatterns),
|
||||
bfResults = await magic.speculativeExecution(
|
||||
depth-1, extLang, false, [...recipeConfig, enc.conf]);
|
||||
depth-1, extLang, false, [...recipeConfig, enc.conf], false, crib);
|
||||
|
||||
results = results.concat(bfResults);
|
||||
}));
|
||||
|
||||
78
src/core/lib/TLVParser.mjs
Normal file
78
src/core/lib/TLVParser.mjs
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Parser for Type-length-value data.
|
||||
*
|
||||
* @author gchq77703 []
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
const defaults = {
|
||||
location: 0,
|
||||
bytesInLength: 1,
|
||||
basicEncodingRules: false
|
||||
};
|
||||
|
||||
/**
|
||||
* TLVParser library
|
||||
*/
|
||||
export default class TLVParser {
|
||||
|
||||
/**
|
||||
* TLVParser constructor
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(input, options) {
|
||||
this.input = input;
|
||||
Object.assign(this, defaults, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
getLength() {
|
||||
if (this.basicEncodingRules) {
|
||||
const bit = this.input[this.location];
|
||||
if (bit & 0x80) {
|
||||
this.bytesInLength = bit & ~0x80;
|
||||
} else {
|
||||
this.location++;
|
||||
return bit & ~0x80;
|
||||
}
|
||||
}
|
||||
|
||||
let length = 0;
|
||||
|
||||
for (let i = 0; i < this.bytesInLength; i++) {
|
||||
length += this.input[this.location] * Math.pow(Math.pow(2, 8), i);
|
||||
this.location++;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} length
|
||||
* @returns {number[]}
|
||||
*/
|
||||
getValue(length) {
|
||||
const value = [];
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (this.location > this.input.length) return value;
|
||||
value.push(this.input[this.location]);
|
||||
this.location++;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
atEnd() {
|
||||
return this.input.length <= this.location;
|
||||
}
|
||||
}
|
||||
63
src/core/operations/A1Z26CipherDecode.mjs
Normal file
63
src/core/operations/A1Z26CipherDecode.mjs
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* @author Jarmo van Lenthe [github.com/jarmovanlenthe]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import Utils from "../Utils";
|
||||
import {DELIM_OPTIONS} from "../lib/Delim";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* A1Z26 Cipher Decode operation
|
||||
*/
|
||||
class A1Z26CipherDecode extends Operation {
|
||||
|
||||
/**
|
||||
* A1Z26CipherDecode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "A1Z26 Cipher Decode";
|
||||
this.module = "Ciphers";
|
||||
this.description = "Converts alphabet order numbers into their corresponding alphabet character.<br><br>e.g. <code>1</code> becomes <code>a</code> and <code>2</code> becomes <code>b</code>.";
|
||||
this.infoURL = "";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Delimiter",
|
||||
type: "option",
|
||||
value: DELIM_OPTIONS
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const delim = Utils.charRep(args[0] || "Space");
|
||||
|
||||
if (input.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const bites = input.split(delim);
|
||||
let latin1 = "";
|
||||
for (let i = 0; i < bites.length; i++) {
|
||||
if (bites[i] < 1 || bites[i] > 26) {
|
||||
throw new OperationError("Error: all numbers must be between 1 and 26.");
|
||||
}
|
||||
latin1 += Utils.chr(parseInt(bites[i], 10) + 96);
|
||||
}
|
||||
return latin1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default A1Z26CipherDecode;
|
||||
61
src/core/operations/A1Z26CipherEncode.mjs
Normal file
61
src/core/operations/A1Z26CipherEncode.mjs
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @author Jarmo van Lenthe [github.com/jarmovanlenthe]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import Utils from "../Utils";
|
||||
import {DELIM_OPTIONS} from "../lib/Delim";
|
||||
|
||||
/**
|
||||
* A1Z26 Cipher Encode operation
|
||||
*/
|
||||
class A1Z26CipherEncode extends Operation {
|
||||
|
||||
/**
|
||||
* A1Z26CipherEncode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "A1Z26 Cipher Encode";
|
||||
this.module = "Ciphers";
|
||||
this.description = "Converts alphabet characters into their corresponding alphabet order number.<br><br>e.g. <code>a</code> becomes <code>1</code> and <code>b</code> becomes <code>2</code>.<br><br>Non-alphabet characters are dropped.";
|
||||
this.infoURL = "";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Delimiter",
|
||||
type: "option",
|
||||
value: DELIM_OPTIONS
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const delim = Utils.charRep(args[0] || "Space");
|
||||
let output = "";
|
||||
|
||||
const sanitizedinput = input.toLowerCase(),
|
||||
charcode = Utils.strToCharcode(sanitizedinput);
|
||||
|
||||
for (let i = 0; i < charcode.length; i++) {
|
||||
const ordinal = charcode[i] - 96;
|
||||
|
||||
if (ordinal > 0 && ordinal <= 26) {
|
||||
output += ordinal.toString(10) + delim;
|
||||
}
|
||||
}
|
||||
return output.slice(0, -delim.length);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default A1Z26CipherEncode;
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import Operation from "../Operation";
|
||||
import Utils from "../Utils";
|
||||
import { bitOp, add } from "../lib/BitwiseOp";
|
||||
import { bitOp, add, BITWISE_OP_DELIMS } from "../lib/BitwiseOp";
|
||||
|
||||
/**
|
||||
* ADD operation
|
||||
@@ -30,7 +30,7 @@ class ADD extends Operation {
|
||||
"name": "Key",
|
||||
"type": "toggleString",
|
||||
"value": "",
|
||||
"toggleValues": ["Hex", "Decimal", "Base64", "UTF8", "Latin1"]
|
||||
"toggleValues": BITWISE_OP_DELIMS
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import Operation from "../Operation";
|
||||
import Utils from "../Utils";
|
||||
import { bitOp, and } from "../lib/BitwiseOp";
|
||||
import { bitOp, and, BITWISE_OP_DELIMS } from "../lib/BitwiseOp";
|
||||
|
||||
/**
|
||||
* AND operation
|
||||
@@ -30,7 +30,7 @@ class AND extends Operation {
|
||||
"name": "Key",
|
||||
"type": "toggleString",
|
||||
"value": "",
|
||||
"toggleValues": ["Hex", "Decimal", "Base64", "UTF8", "Latin1"]
|
||||
"toggleValues": BITWISE_OP_DELIMS
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import bzip2 from "../vendor/bzip2.js";
|
||||
import bzip2 from "../vendor/bzip2";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
|
||||
80
src/core/operations/CSVToJSON.mjs
Normal file
80
src/core/operations/CSVToJSON.mjs
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
import Utils from "../Utils";
|
||||
|
||||
/**
|
||||
* CSV to JSON operation
|
||||
*/
|
||||
class CSVToJSON extends Operation {
|
||||
|
||||
/**
|
||||
* CSVToJSON constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "CSV to JSON";
|
||||
this.module = "Default";
|
||||
this.description = "Converts a CSV file to JSON format.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Comma-separated_values";
|
||||
this.inputType = "string";
|
||||
this.outputType = "JSON";
|
||||
this.args = [
|
||||
{
|
||||
name: "Cell delimiters",
|
||||
type: "binaryShortString",
|
||||
value: ","
|
||||
},
|
||||
{
|
||||
name: "Row delimiters",
|
||||
type: "binaryShortString",
|
||||
value: "\\r\\n"
|
||||
},
|
||||
{
|
||||
name: "Format",
|
||||
type: "option",
|
||||
value: ["Array of dictionaries", "Array of arrays"]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {JSON}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [cellDelims, rowDelims, format] = args;
|
||||
let json, header;
|
||||
|
||||
try {
|
||||
json = Utils.parseCSV(input, cellDelims.split(""), rowDelims.split(""));
|
||||
} catch (err) {
|
||||
throw new OperationError("Unable to parse CSV: " + err);
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case "Array of dictionaries":
|
||||
header = json[0];
|
||||
return json.slice(1).map(row => {
|
||||
const obj = {};
|
||||
header.forEach((h, i) => {
|
||||
obj[h] = row[i];
|
||||
});
|
||||
return obj;
|
||||
});
|
||||
case "Array of arrays":
|
||||
default:
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CSVToJSON;
|
||||
58
src/core/operations/CitrixCTX1Decode.mjs
Normal file
58
src/core/operations/CitrixCTX1Decode.mjs
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @author bwhitn [brian.m.whitney@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
import cptable from "../vendor/js-codepage/cptable.js";
|
||||
|
||||
/**
|
||||
* Citrix CTX1 Decode operation
|
||||
*/
|
||||
class CitrixCTX1Decode extends Operation {
|
||||
|
||||
/**
|
||||
* CitrixCTX1Decode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Citrix CTX1 Decode";
|
||||
this.module = "Encodings";
|
||||
this.description = "Decodes strings in a Citrix CTX1 password format to plaintext.";
|
||||
this.infoURL = "https://www.reddit.com/r/AskNetsec/comments/1s3r6y/citrix_ctx1_hash_decoding/";
|
||||
this.inputType = "byteArray";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
if (input.length % 4 !== 0) {
|
||||
throw new OperationError("Incorrect hash length");
|
||||
}
|
||||
const revinput = input.reverse();
|
||||
const result = [];
|
||||
let temp = 0;
|
||||
for (let i = 0; i < revinput.length; i += 2) {
|
||||
if (i + 2 >= revinput.length) {
|
||||
temp = 0;
|
||||
} else {
|
||||
temp = ((revinput[i + 2] - 0x41) & 0xf) ^ (((revinput[i + 3]- 0x41) << 4) & 0xf0);
|
||||
}
|
||||
temp = (((revinput[i] - 0x41) & 0xf) ^ (((revinput[i + 1] - 0x41) << 4) & 0xf0)) ^ 0xa5 ^ temp;
|
||||
result.push(temp);
|
||||
}
|
||||
// Decodes a utf-16le string
|
||||
return cptable.utils.decode(1200, result.reverse());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CitrixCTX1Decode;
|
||||
50
src/core/operations/CitrixCTX1Encode.mjs
Normal file
50
src/core/operations/CitrixCTX1Encode.mjs
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @author bwhitn [brian.m.whitney@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import cptable from "../vendor/js-codepage/cptable.js";
|
||||
|
||||
/**
|
||||
* Citrix CTX1 Encode operation
|
||||
*/
|
||||
class CitrixCTX1Encode extends Operation {
|
||||
|
||||
/**
|
||||
* CitrixCTX1Encode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Citrix CTX1 Encode";
|
||||
this.module = "Encodings";
|
||||
this.description = "Encodes strings to Citrix CTX1 password format.";
|
||||
this.infoURL = "https://www.reddit.com/r/AskNetsec/comments/1s3r6y/citrix_ctx1_hash_decoding/";
|
||||
this.inputType = "string";
|
||||
this.outputType = "byteArray";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
const utf16pass = Array.from(cptable.utils.encode(1200, input));
|
||||
const result = [];
|
||||
let temp = 0;
|
||||
for (let i = 0; i < utf16pass.length; i++) {
|
||||
temp = utf16pass[i] ^ 0xa5 ^ temp;
|
||||
result.push(((temp >>> 4) & 0xf) + 0x41);
|
||||
result.push((temp & 0xf) + 0x41);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CitrixCTX1Encode;
|
||||
102
src/core/operations/DefangURL.mjs
Normal file
102
src/core/operations/DefangURL.mjs
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* @author arnydo [arnydo@protonmail.com]
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import {URL_REGEX, DOMAIN_REGEX} from "../lib/Extract";
|
||||
|
||||
/**
|
||||
* DefangURL operation
|
||||
*/
|
||||
class DefangURL extends Operation {
|
||||
|
||||
/**
|
||||
* DefangURL constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Defang URL";
|
||||
this.module = "Default";
|
||||
this.description = "Takes a Universal Resource Locator (URL) and 'Defangs' it; meaning the URL becomes invalid, neutralising the risk of accidentally clicking on a malicious link.<br><br>This is often used when dealing with malicious links or IOCs.<br><br>Works well when combined with the 'Extract URLs' operation.";
|
||||
this.infoURL = "https://isc.sans.edu/forums/diary/Defang+all+the+things/22744/";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Escape dots",
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "Escape http",
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "Escape ://",
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "Process",
|
||||
type: "option",
|
||||
value: ["Valid domains and full URLs", "Only full URLs", "Everything"]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [dots, http, slashes, process] = args;
|
||||
|
||||
switch (process) {
|
||||
case "Valid domains and full URLs":
|
||||
input = input.replace(URL_REGEX, x => {
|
||||
return defangURL(x, dots, http, slashes);
|
||||
});
|
||||
input = input.replace(DOMAIN_REGEX, x => {
|
||||
return defangURL(x, dots, http, slashes);
|
||||
});
|
||||
break;
|
||||
case "Only full URLs":
|
||||
input = input.replace(URL_REGEX, x => {
|
||||
return defangURL(x, dots, http, slashes);
|
||||
});
|
||||
break;
|
||||
case "Everything":
|
||||
input = defangURL(input, dots, http, slashes);
|
||||
break;
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defangs a given URL
|
||||
*
|
||||
* @param {string} url
|
||||
* @param {boolean} dots
|
||||
* @param {boolean} http
|
||||
* @param {boolean} slashes
|
||||
* @returns {string}
|
||||
*/
|
||||
function defangURL(url, dots, http, slashes) {
|
||||
if (dots) url = url.replace(/\./g, "[.]");
|
||||
if (http) url = url.replace(/http/gi, "hxxp");
|
||||
if (slashes) url = url.replace(/:\/\//g, "[://]");
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
export default DefangURL;
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import { search } from "../lib/Extract";
|
||||
import { search, DOMAIN_REGEX } from "../lib/Extract";
|
||||
|
||||
/**
|
||||
* Extract domains operation
|
||||
@@ -38,10 +38,8 @@ class ExtractDomains extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const displayTotal = args[0],
|
||||
regex = /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/ig;
|
||||
|
||||
return search(input, regex, null, displayTotal);
|
||||
const displayTotal = args[0];
|
||||
return search(input, DOMAIN_REGEX, null, displayTotal);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ class ExtractEmailAddresses extends Operation {
|
||||
*/
|
||||
run(input, args) {
|
||||
const displayTotal = args[0],
|
||||
regex = /\b\w[-.\w]*@[-\w]+(?:\.[-\w]+)*\.[A-Z]{2,4}\b/ig;
|
||||
|
||||
// email regex from: https://www.regextester.com/98066
|
||||
regex = /(?:[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9])?\.)+[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFF-a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/ig;
|
||||
return search(input, regex, null, displayTotal);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import { search } from "../lib/Extract";
|
||||
import { search, URL_REGEX } from "../lib/Extract";
|
||||
|
||||
/**
|
||||
* Extract URLs operation
|
||||
@@ -38,16 +38,8 @@ class ExtractURLs extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const displayTotal = args[0],
|
||||
protocol = "[A-Z]+://",
|
||||
hostname = "[-\\w]+(?:\\.\\w[-\\w]*)+",
|
||||
port = ":\\d+";
|
||||
let path = "/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*";
|
||||
|
||||
path += "(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*";
|
||||
const regex = new RegExp(protocol + hostname + "(?:" + port +
|
||||
")?(?:" + path + ")?", "ig");
|
||||
return search(input, regex, null, displayTotal);
|
||||
const displayTotal = args[0];
|
||||
return search(input, URL_REGEX, null, displayTotal);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -71,6 +71,11 @@ class FromBase58 extends Operation {
|
||||
|
||||
if (input.length === 0) return [];
|
||||
|
||||
let zeroPrefix = 0;
|
||||
for (let i = 0; i < input.length && input[i] === alphabet[0]; i++) {
|
||||
zeroPrefix++;
|
||||
}
|
||||
|
||||
[].forEach.call(input, function(c, charIndex) {
|
||||
const index = alphabet.indexOf(c);
|
||||
|
||||
@@ -98,6 +103,10 @@ class FromBase58 extends Operation {
|
||||
}
|
||||
});
|
||||
|
||||
while (zeroPrefix--) {
|
||||
result.push(0);
|
||||
}
|
||||
|
||||
return result.reverse();
|
||||
}
|
||||
|
||||
|
||||
58
src/core/operations/FromBase62.mjs
Normal file
58
src/core/operations/FromBase62.mjs
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @author tcode2k16 [tcode2k16@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import BigNumber from "bignumber.js";
|
||||
import Utils from "../Utils";
|
||||
|
||||
|
||||
/**
|
||||
* From Base62 operation
|
||||
*/
|
||||
class FromBase62 extends Operation {
|
||||
|
||||
/**
|
||||
* FromBase62 constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "From Base62";
|
||||
this.module = "Default";
|
||||
this.description = "Base62 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers. The high number base results in shorter strings than with the decimal or hexadecimal system.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems";
|
||||
this.inputType = "string";
|
||||
this.outputType = "byteArray";
|
||||
this.args = [
|
||||
{
|
||||
name: "Alphabet",
|
||||
type: "string",
|
||||
value: "0-9A-Za-z"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
if (input.length < 1) return [];
|
||||
const ALPHABET = Utils.expandAlphRange(args[0]).join("");
|
||||
const BN = BigNumber.clone({ ALPHABET });
|
||||
|
||||
const re = new RegExp("[^" + ALPHABET.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
|
||||
input = input.replace(re, "");
|
||||
|
||||
const number = new BN(input, 62);
|
||||
|
||||
return Utils.convertToByteArray(number.toString(16), "Hex");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default FromBase62;
|
||||
@@ -38,44 +38,44 @@ class FromBase64 extends Operation {
|
||||
];
|
||||
this.patterns = [
|
||||
{
|
||||
match: "^(?:[A-Z\\d+/]{4})+(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?$",
|
||||
match: "^\\s*(?:[A-Z\\d+/]{4})+(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?\\s*$",
|
||||
flags: "i",
|
||||
args: ["A-Za-z0-9+/=", false]
|
||||
args: ["A-Za-z0-9+/=", true]
|
||||
},
|
||||
{
|
||||
match: "^[A-Z\\d\\-_]{20,}$",
|
||||
match: "^\\s*[A-Z\\d\\-_]{20,}\\s*$",
|
||||
flags: "i",
|
||||
args: ["A-Za-z0-9-_", false]
|
||||
args: ["A-Za-z0-9-_", true]
|
||||
},
|
||||
{
|
||||
match: "^(?:[A-Z\\d+\\-]{4}){5,}(?:[A-Z\\d+\\-]{2}==|[A-Z\\d+\\-]{3}=)?$",
|
||||
match: "^\\s*(?:[A-Z\\d+\\-]{4}){5,}(?:[A-Z\\d+\\-]{2}==|[A-Z\\d+\\-]{3}=)?\\s*$",
|
||||
flags: "i",
|
||||
args: ["A-Za-z0-9+\\-=", false]
|
||||
args: ["A-Za-z0-9+\\-=", true]
|
||||
},
|
||||
{
|
||||
match: "^(?:[A-Z\\d./]{4}){5,}(?:[A-Z\\d./]{2}==|[A-Z\\d./]{3}=)?$",
|
||||
match: "^\\s*(?:[A-Z\\d./]{4}){5,}(?:[A-Z\\d./]{2}==|[A-Z\\d./]{3}=)?\\s*$",
|
||||
flags: "i",
|
||||
args: ["./0-9A-Za-z=", false]
|
||||
args: ["./0-9A-Za-z=", true]
|
||||
},
|
||||
{
|
||||
match: "^[A-Z\\d_.]{20,}$",
|
||||
match: "^\\s*[A-Z\\d_.]{20,}\\s*$",
|
||||
flags: "i",
|
||||
args: ["A-Za-z0-9_.", false]
|
||||
args: ["A-Za-z0-9_.", true]
|
||||
},
|
||||
{
|
||||
match: "^(?:[A-Z\\d._]{4}){5,}(?:[A-Z\\d._]{2}--|[A-Z\\d._]{3}-)?$",
|
||||
match: "^\\s*(?:[A-Z\\d._]{4}){5,}(?:[A-Z\\d._]{2}--|[A-Z\\d._]{3}-)?\\s*$",
|
||||
flags: "i",
|
||||
args: ["A-Za-z0-9._-", false]
|
||||
args: ["A-Za-z0-9._-", true]
|
||||
},
|
||||
{
|
||||
match: "^(?:[A-Z\\d+/]{4}){5,}(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?$",
|
||||
match: "^\\s*(?:[A-Z\\d+/]{4}){5,}(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?\\s*$",
|
||||
flags: "i",
|
||||
args: ["0-9a-zA-Z+/=", false]
|
||||
args: ["0-9a-zA-Z+/=", true]
|
||||
},
|
||||
{
|
||||
match: "^(?:[A-Z\\d+/]{4}){5,}(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?$",
|
||||
match: "^\\s*(?:[A-Z\\d+/]{4}){5,}(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?\\s*$",
|
||||
flags: "i",
|
||||
args: ["0-9A-Za-z+/=", false]
|
||||
args: ["0-9A-Za-z+/=", true]
|
||||
},
|
||||
{
|
||||
match: "^[ !\"#$%&'()*+,\\-./\\d:;<=>?@A-Z[\\\\\\]^_]{20,}$",
|
||||
@@ -83,24 +83,24 @@ class FromBase64 extends Operation {
|
||||
args: [" -_", false]
|
||||
},
|
||||
{
|
||||
match: "^[A-Z\\d+\\-]{20,}$",
|
||||
match: "^\\s*[A-Z\\d+\\-]{20,}\\s*$",
|
||||
flags: "i",
|
||||
args: ["+\\-0-9A-Za-z", false]
|
||||
args: ["+\\-0-9A-Za-z", true]
|
||||
},
|
||||
{
|
||||
match: "^[!\"#$%&'()*+,\\-0-689@A-NP-VX-Z[`a-fh-mp-r]{20,}$",
|
||||
match: "^\\s*[!\"#$%&'()*+,\\-0-689@A-NP-VX-Z[`a-fh-mp-r]{20,}\\s*$",
|
||||
flags: "",
|
||||
args: ["!-,-0-689@A-NP-VX-Z[`a-fh-mp-r", false]
|
||||
args: ["!-,-0-689@A-NP-VX-Z[`a-fh-mp-r", true]
|
||||
},
|
||||
{
|
||||
match: "^(?:[N-ZA-M\\d+/]{4}){5,}(?:[N-ZA-M\\d+/]{2}==|[N-ZA-M\\d+/]{3}=)?$",
|
||||
match: "^\\s*(?:[N-ZA-M\\d+/]{4}){5,}(?:[N-ZA-M\\d+/]{2}==|[N-ZA-M\\d+/]{3}=)?\\s*$",
|
||||
flags: "i",
|
||||
args: ["N-ZA-Mn-za-m0-9+/=", false]
|
||||
args: ["N-ZA-Mn-za-m0-9+/=", true]
|
||||
},
|
||||
{
|
||||
match: "^[A-Z\\d./]{20,}$",
|
||||
match: "^\\s*[A-Z\\d./]{20,}\\s*$",
|
||||
flags: "i",
|
||||
args: ["./0-9A-Za-z", false]
|
||||
args: ["./0-9A-Za-z", true]
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import Operation from "../Operation";
|
||||
import Utils from "../Utils";
|
||||
import {BIN_DELIM_OPTIONS} from "../lib/Delim";
|
||||
import {fromBinary} from "../lib/Binary";
|
||||
|
||||
/**
|
||||
* From Binary operation
|
||||
@@ -77,15 +78,7 @@ class FromBinary extends Operation {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
const delimRegex = Utils.regexRep(args[0] || "Space");
|
||||
input = input.replace(delimRegex, "");
|
||||
|
||||
const output = [];
|
||||
const byteLen = 8;
|
||||
for (let i = 0; i < input.length; i += byteLen) {
|
||||
output.push(parseInt(input.substr(i, byteLen), 2));
|
||||
}
|
||||
return output;
|
||||
return fromBinary(input, args[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
70
src/core/operations/FromBraille.mjs
Normal file
70
src/core/operations/FromBraille.mjs
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import {BRAILLE_LOOKUP} from "../lib/Braille";
|
||||
|
||||
/**
|
||||
* From Braille operation
|
||||
*/
|
||||
class FromBraille extends Operation {
|
||||
|
||||
/**
|
||||
* FromBraille constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "From Braille";
|
||||
this.module = "Default";
|
||||
this.description = "Converts six-dot braille symbols to text.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Braille";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
return input.split("").map(b => {
|
||||
const idx = BRAILLE_LOOKUP.dot6.indexOf(b);
|
||||
return idx < 0 ? b : BRAILLE_LOOKUP.ascii[idx];
|
||||
}).join("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight From Braille
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlight(pos, args) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight From Braille in reverse
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightReverse(pos, args) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default FromBraille;
|
||||
@@ -29,38 +29,43 @@ class FromDecimal extends Operation {
|
||||
"name": "Delimiter",
|
||||
"type": "option",
|
||||
"value": DELIM_OPTIONS
|
||||
},
|
||||
{
|
||||
"name": "Support signed values",
|
||||
"type": "boolean",
|
||||
"value": false
|
||||
}
|
||||
];
|
||||
this.patterns = [
|
||||
{
|
||||
match: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?: (?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$",
|
||||
flags: "",
|
||||
args: ["Space"]
|
||||
args: ["Space", false]
|
||||
},
|
||||
{
|
||||
match: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?:,(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$",
|
||||
flags: "",
|
||||
args: ["Comma"]
|
||||
args: ["Comma", false]
|
||||
},
|
||||
{
|
||||
match: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?:;(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$",
|
||||
flags: "",
|
||||
args: ["Semi-colon"]
|
||||
args: ["Semi-colon", false]
|
||||
},
|
||||
{
|
||||
match: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?::(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$",
|
||||
flags: "",
|
||||
args: ["Colon"]
|
||||
args: ["Colon", false]
|
||||
},
|
||||
{
|
||||
match: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?:\\n(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$",
|
||||
flags: "",
|
||||
args: ["Line feed"]
|
||||
args: ["Line feed", false]
|
||||
},
|
||||
{
|
||||
match: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?:\\r\\n(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$",
|
||||
flags: "",
|
||||
args: ["CRLF"]
|
||||
args: ["CRLF", false]
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -71,7 +76,11 @@ class FromDecimal extends Operation {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
return fromDecimal(input, args[0]);
|
||||
let data = fromDecimal(input, args[0]);
|
||||
if (args[1]) { // Convert negatives
|
||||
data = data.map(v => v < 0 ? 0xFF + v + 1 : v);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
44
src/core/operations/FromGeohash.mjs
Normal file
44
src/core/operations/FromGeohash.mjs
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @author gchq77703 []
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import geohash from "ngeohash";
|
||||
|
||||
/**
|
||||
* From Geohash operation
|
||||
*/
|
||||
class FromGeohash extends Operation {
|
||||
|
||||
/**
|
||||
* FromGeohash constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "From Geohash";
|
||||
this.module = "Hashing";
|
||||
this.description = "Converts Geohash strings into Lat/Long coordinates. For example, <code>ww8p1r4t8</code> becomes <code>37.8324,112.5584</code>.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Geohash";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
return input.split("\n").map(line => {
|
||||
const coords = geohash.decode(line);
|
||||
return [coords.latitude, coords.longitude].join(",");
|
||||
}).join("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default FromGeohash;
|
||||
@@ -30,7 +30,7 @@ class FromQuotedPrintable extends Operation {
|
||||
this.args = [];
|
||||
this.patterns = [
|
||||
{
|
||||
match: "^[\\x21-\\x3d\\x3f-\\x7e \\t]*(?:=[\\da-f]{2}|=\\r?\\n)(?:[\\x21-\\x3d\\x3f-\\x7e \\t]|=[\\da-f]{2}|=\\r?\\n)*$",
|
||||
match: "^[\\x21-\\x3d\\x3f-\\x7e \\t]{0,76}(?:=[\\da-f]{2}|=\\r?\\n)(?:[\\x21-\\x3d\\x3f-\\x7e \\t]|=[\\da-f]{2}|=\\r?\\n)*$",
|
||||
flags: "i",
|
||||
args: []
|
||||
},
|
||||
|
||||
119
src/core/operations/GenerateQRCode.mjs
Normal file
119
src/core/operations/GenerateQRCode.mjs
Normal file
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* @author j433866 [j433866@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
import qr from "qr-image";
|
||||
import { toBase64 } from "../lib/Base64";
|
||||
import Magic from "../lib/Magic";
|
||||
import Utils from "../Utils";
|
||||
|
||||
/**
|
||||
* Generate QR Code operation
|
||||
*/
|
||||
class GenerateQRCode extends Operation {
|
||||
|
||||
/**
|
||||
* GenerateQRCode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Generate QR Code";
|
||||
this.module = "Image";
|
||||
this.description = "Generates a Quick Response (QR) code from the input text.<br><br>A QR code is a type of matrix barcode (or two-dimensional barcode) first designed in 1994 for the automotive industry in Japan. A barcode is a machine-readable optical label that contains information about the item to which it is attached.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/QR_code";
|
||||
this.inputType = "string";
|
||||
this.outputType = "byteArray";
|
||||
this.presentType = "html";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Image Format",
|
||||
"type": "option",
|
||||
"value": ["PNG", "SVG", "EPS", "PDF"]
|
||||
},
|
||||
{
|
||||
"name": "Module size (px)",
|
||||
"type": "number",
|
||||
"value": 5
|
||||
},
|
||||
{
|
||||
"name": "Margin (num modules)",
|
||||
"type": "number",
|
||||
"value": 2
|
||||
},
|
||||
{
|
||||
"name": "Error correction",
|
||||
"type": "option",
|
||||
"value": ["Low", "Medium", "Quartile", "High"],
|
||||
"defaultIndex": 1
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [format, size, margin, errorCorrection] = args;
|
||||
|
||||
// Create new QR image from the input data, and convert it to a buffer
|
||||
const qrImage = qr.imageSync(input, {
|
||||
type: format,
|
||||
size: size,
|
||||
margin: margin,
|
||||
"ec_level": errorCorrection.charAt(0).toUpperCase()
|
||||
});
|
||||
|
||||
if (qrImage == null) {
|
||||
throw new OperationError("Error generating QR code.");
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case "SVG":
|
||||
case "EPS":
|
||||
case "PDF":
|
||||
return [...Buffer.from(qrImage)];
|
||||
case "PNG":
|
||||
// Return the QR image buffer as a byte array
|
||||
return [...qrImage];
|
||||
default:
|
||||
throw new OperationError("Unsupported QR code format.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the QR image using HTML for web apps
|
||||
*
|
||||
* @param {byteArray} data
|
||||
* @returns {html}
|
||||
*/
|
||||
present(data, args) {
|
||||
if (!data.length) return "";
|
||||
|
||||
const [format] = args;
|
||||
|
||||
if (format === "PNG") {
|
||||
let dataURI = "data:";
|
||||
const type = Magic.magicFileType(data);
|
||||
if (type && type.mime.indexOf("image") === 0){
|
||||
dataURI += type.mime + ";";
|
||||
} else {
|
||||
throw new OperationError("Invalid PNG file generated by QR image");
|
||||
}
|
||||
dataURI += "base64," + toBase64(data);
|
||||
|
||||
return `<img src="${dataURI}">`;
|
||||
}
|
||||
|
||||
return Utils.byteArrayToChars(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default GenerateQRCode;
|
||||
@@ -28,8 +28,9 @@ class HMAC extends Operation {
|
||||
this.args = [
|
||||
{
|
||||
"name": "Key",
|
||||
"type": "binaryString",
|
||||
"value": ""
|
||||
"type": "toggleString",
|
||||
"value": "",
|
||||
"toggleValues": ["Hex", "Decimal", "Base64", "UTF8", "Latin1"]
|
||||
},
|
||||
{
|
||||
"name": "Hashing function",
|
||||
@@ -66,19 +67,12 @@ class HMAC extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const key = args[0],
|
||||
const key = Utils.convertToByteString(args[0].string || "", args[0].option),
|
||||
hashFunc = args[1].toLowerCase(),
|
||||
msg = Utils.arrayBufferToStr(input, false),
|
||||
hasher = CryptoApi.getHasher(hashFunc);
|
||||
|
||||
// Horrible shim to fix constructor bug. Reported in nf404/crypto-api#8
|
||||
hasher.reset = () => {
|
||||
hasher.state = {};
|
||||
const tmp = new hasher.constructor();
|
||||
hasher.state = tmp.state;
|
||||
};
|
||||
|
||||
const mac = CryptoApi.getHmac(CryptoApi.encoder.fromUtf(key), hasher);
|
||||
const mac = CryptoApi.getHmac(key, hasher);
|
||||
mac.update(msg);
|
||||
return CryptoApi.encoder.toHex(mac.finalize());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @author Phillip Nordwall [phillip.nordwall@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
@@ -27,7 +28,12 @@ class JSONBeautify extends Operation {
|
||||
{
|
||||
"name": "Indent string",
|
||||
"type": "binaryShortString",
|
||||
"value": "\\t"
|
||||
"value": " "
|
||||
},
|
||||
{
|
||||
"name": "Sort Object Keys",
|
||||
"type": "boolean",
|
||||
"value": false
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -38,11 +44,35 @@ class JSONBeautify extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const indentStr = args[0];
|
||||
const [indentStr, sortBool] = args;
|
||||
|
||||
if (!input) return "";
|
||||
if (sortBool) {
|
||||
input = JSON.stringify(JSONBeautify._sort(JSON.parse(input)));
|
||||
}
|
||||
return vkbeautify.json(input, indentStr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sort JSON representation of an object
|
||||
*
|
||||
* @author Phillip Nordwall [phillip.nordwall@gmail.com]
|
||||
* @private
|
||||
* @param {object} o
|
||||
* @returns {object}
|
||||
*/
|
||||
static _sort(o) {
|
||||
if (Array.isArray(o)) {
|
||||
return o.map(JSONBeautify._sort);
|
||||
} else if ("[object Object]" === Object.prototype.toString.call(o)) {
|
||||
return Object.keys(o).sort().reduce(function(a, k) {
|
||||
a[k] = JSONBeautify._sort(o[k]);
|
||||
return a;
|
||||
}, {});
|
||||
}
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
export default JSONBeautify;
|
||||
|
||||
111
src/core/operations/JSONToCSV.mjs
Normal file
111
src/core/operations/JSONToCSV.mjs
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* JSON to CSV operation
|
||||
*/
|
||||
class JSONToCSV extends Operation {
|
||||
|
||||
/**
|
||||
* JSONToCSV constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "JSON to CSV";
|
||||
this.module = "Default";
|
||||
this.description = "Converts JSON data to a CSV based on the definition in RFC 4180.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Comma-separated_values";
|
||||
this.inputType = "JSON";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Cell delimiter",
|
||||
type: "binaryShortString",
|
||||
value: ","
|
||||
},
|
||||
{
|
||||
name: "Row delimiter",
|
||||
type: "binaryShortString",
|
||||
value: "\\r\\n"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {JSON} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [cellDelim, rowDelim] = args;
|
||||
|
||||
// Record values so they don't have to be passed to other functions explicitly
|
||||
this.cellDelim = cellDelim;
|
||||
this.rowDelim = rowDelim;
|
||||
const self = this;
|
||||
|
||||
try {
|
||||
// If the JSON is an array of arrays, this is easy
|
||||
if (input[0] instanceof Array) {
|
||||
return input
|
||||
.map(row => row
|
||||
.map(self.escapeCellContents.bind(self))
|
||||
.join(cellDelim)
|
||||
)
|
||||
.join(rowDelim) +
|
||||
rowDelim;
|
||||
}
|
||||
|
||||
// If it's an array of dictionaries...
|
||||
const header = Object.keys(input[0]);
|
||||
return header
|
||||
.map(self.escapeCellContents.bind(self))
|
||||
.join(cellDelim) +
|
||||
rowDelim +
|
||||
input
|
||||
.map(row => header
|
||||
.map(h => row[h])
|
||||
.map(self.escapeCellContents.bind(self))
|
||||
.join(cellDelim)
|
||||
)
|
||||
.join(rowDelim) +
|
||||
rowDelim;
|
||||
} catch (err) {
|
||||
throw new OperationError("Unable to parse JSON to CSV: " + err.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Correctly escapes a cell's contents based on the cell and row delimiters.
|
||||
*
|
||||
* @param {string} data
|
||||
* @returns {string}
|
||||
*/
|
||||
escapeCellContents(data) {
|
||||
// Double quotes should be doubled up
|
||||
data = data.replace(/"/g, '""');
|
||||
|
||||
// If the cell contains a cell or row delimiter or a double quote, it mut be enclosed in double quotes
|
||||
if (
|
||||
data.indexOf(this.cellDelim) >= 0 ||
|
||||
data.indexOf(this.rowDelim) >= 0 ||
|
||||
data.indexOf("\n") >= 0 ||
|
||||
data.indexOf("\r") >= 0 ||
|
||||
data.indexOf('"') >= 0
|
||||
) {
|
||||
data = `"${data}"`;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default JSONToCSV;
|
||||
51
src/core/operations/JWTDecode.mjs
Normal file
51
src/core/operations/JWTDecode.mjs
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @author gchq77703 []
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import jwt from "jsonwebtoken";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* JWT Decode operation
|
||||
*/
|
||||
class JWTDecode extends Operation {
|
||||
|
||||
/**
|
||||
* JWTDecode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "JWT Decode";
|
||||
this.module = "Crypto";
|
||||
this.description = "Decodes a JSON Web Token <b>without</b> checking whether the provided secret / private key is valid. Use 'JWT Verify' to check if the signature is valid as well.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/JSON_Web_Token";
|
||||
this.inputType = "string";
|
||||
this.outputType = "JSON";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {JSON}
|
||||
*/
|
||||
run(input, args) {
|
||||
try {
|
||||
const decoded = jwt.decode(input, {
|
||||
json: true,
|
||||
complete: true
|
||||
});
|
||||
|
||||
return decoded.payload;
|
||||
} catch (err) {
|
||||
throw new OperationError(err);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default JWTDecode;
|
||||
74
src/core/operations/JWTSign.mjs
Normal file
74
src/core/operations/JWTSign.mjs
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* @author gchq77703 []
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import jwt from "jsonwebtoken";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* JWT Sign operation
|
||||
*/
|
||||
class JWTSign extends Operation {
|
||||
|
||||
/**
|
||||
* JWTSign constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "JWT Sign";
|
||||
this.module = "Crypto";
|
||||
this.description = "Signs a JSON object as a JSON Web Token using a provided secret / private key.<br><br>The key should be either the secret for HMAC algorithms or the PEM-encoded private key for RSA and ECDSA.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/JSON_Web_Token";
|
||||
this.inputType = "JSON";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Private/Secret Key",
|
||||
type: "text",
|
||||
value: "secret"
|
||||
},
|
||||
{
|
||||
name: "Signing algorithm",
|
||||
type: "option",
|
||||
value: [
|
||||
"HS256",
|
||||
"HS384",
|
||||
"HS512",
|
||||
"RS256",
|
||||
"RS384",
|
||||
"RS512",
|
||||
"ES256",
|
||||
"ES384",
|
||||
"ES512",
|
||||
"None"
|
||||
]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {JSON} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [key, algorithm] = args;
|
||||
|
||||
try {
|
||||
return jwt.sign(input, key, {
|
||||
algorithm: algorithm === "None" ? "none" : algorithm
|
||||
});
|
||||
} catch (err) {
|
||||
throw new OperationError(`Error: Have you entered the key correctly? The key should be either the secret for HMAC algorithms or the PEM-encoded private key for RSA and ECDSA.
|
||||
|
||||
${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default JWTSign;
|
||||
65
src/core/operations/JWTVerify.mjs
Normal file
65
src/core/operations/JWTVerify.mjs
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @author gchq77703 []
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import jwt from "jsonwebtoken";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* JWT Verify operation
|
||||
*/
|
||||
class JWTVerify extends Operation {
|
||||
|
||||
/**
|
||||
* JWTVerify constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "JWT Verify";
|
||||
this.module = "Crypto";
|
||||
this.description = "Verifies that a JSON Web Token is valid and has been signed with the provided secret / private key.<br><br>The key should be either the secret for HMAC algorithms or the PEM-encoded private key for RSA and ECDSA.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/JSON_Web_Token";
|
||||
this.inputType = "string";
|
||||
this.outputType = "JSON";
|
||||
this.args = [
|
||||
{
|
||||
name: "Private/Secret Key",
|
||||
type: "text",
|
||||
value: "secret"
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [key] = args;
|
||||
|
||||
try {
|
||||
const verified = jwt.verify(input, key, { algorithms: [
|
||||
"HS256",
|
||||
"HS384",
|
||||
"HS512",
|
||||
"none"
|
||||
]});
|
||||
|
||||
if (verified.hasOwnProperty("name") && verified.name === "JsonWebTokenError") {
|
||||
throw new OperationError(verified.message);
|
||||
}
|
||||
|
||||
return verified;
|
||||
} catch (err) {
|
||||
throw new OperationError(err);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default JWTVerify;
|
||||
@@ -23,7 +23,7 @@ class Magic extends Operation {
|
||||
this.name = "Magic";
|
||||
this.flowControl = true;
|
||||
this.module = "Default";
|
||||
this.description = "The Magic operation attempts to detect various properties of the input data and suggests which operations could help to make more sense of it.<br><br><b>Options</b><br><u>Depth:</u> If an operation appears to match the data, it will be run and the result will be analysed further. This argument controls the maximum number of levels of recursion.<br><br><u>Intensive mode:</u> When this is turned on, various operations like XOR, bit rotates, and character encodings are brute-forced to attempt to detect valid data underneath. To improve performance, only the first 100 bytes of the data is brute-forced.<br><br><u>Extensive language support:</u> At each stage, the relative byte frequencies of the data will be compared to average frequencies for a number of languages. The default set consists of ~40 of the most commonly used languages on the Internet. The extensive list consists of 284 languages and can result in many languages matching the data if their byte frequencies are similar.";
|
||||
this.description = "The Magic operation attempts to detect various properties of the input data and suggests which operations could help to make more sense of it.<br><br><b>Options</b><br><u>Depth:</u> If an operation appears to match the data, it will be run and the result will be analysed further. This argument controls the maximum number of levels of recursion.<br><br><u>Intensive mode:</u> When this is turned on, various operations like XOR, bit rotates, and character encodings are brute-forced to attempt to detect valid data underneath. To improve performance, only the first 100 bytes of the data is brute-forced.<br><br><u>Extensive language support:</u> At each stage, the relative byte frequencies of the data will be compared to average frequencies for a number of languages. The default set consists of ~40 of the most commonly used languages on the Internet. The extensive list consists of 284 languages and can result in many languages matching the data if their byte frequencies are similar.<br><br>Optionally enter a regular expression to match a string you expect to find to filter results (crib).";
|
||||
this.infoURL = "https://github.com/gchq/CyberChef/wiki/Automatic-detection-of-encoded-data-using-CyberChef-Magic";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "JSON";
|
||||
@@ -43,6 +43,11 @@ class Magic extends Operation {
|
||||
"name": "Extensive language support",
|
||||
"type": "boolean",
|
||||
"value": false
|
||||
},
|
||||
{
|
||||
"name": "Crib (known plaintext string or regex)",
|
||||
"type": "string",
|
||||
"value": ""
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -56,10 +61,16 @@ class Magic extends Operation {
|
||||
*/
|
||||
async run(state) {
|
||||
const ings = state.opList[state.progress].ingValues,
|
||||
[depth, intensive, extLang] = ings,
|
||||
[depth, intensive, extLang, crib] = ings,
|
||||
dish = state.dish,
|
||||
magic = new MagicLib(await dish.get(Dish.ARRAY_BUFFER)),
|
||||
options = await magic.speculativeExecution(depth, extLang, intensive);
|
||||
cribRegex = (crib && crib.length) ? new RegExp(crib, "i") : null;
|
||||
let options = await magic.speculativeExecution(depth, extLang, intensive, [], false, cribRegex);
|
||||
|
||||
// Filter down to results which matched the crib
|
||||
if (cribRegex) {
|
||||
options = options.filter(option => option.matchesCrib);
|
||||
}
|
||||
|
||||
// Record the current state for use when presenting
|
||||
this.state = state;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import Operation from "../Operation";
|
||||
import Utils from "../Utils";
|
||||
import { bitOp, or } from "../lib/BitwiseOp";
|
||||
import { bitOp, or, BITWISE_OP_DELIMS } from "../lib/BitwiseOp";
|
||||
|
||||
/**
|
||||
* OR operation
|
||||
@@ -30,7 +30,7 @@ class OR extends Operation {
|
||||
"name": "Key",
|
||||
"type": "toggleString",
|
||||
"value": "",
|
||||
"toggleValues": ["Hex", "Decimal", "Base64", "UTF8", "Latin1"]
|
||||
"toggleValues": BITWISE_OP_DELIMS
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @author Klaxon [klaxon@veyr.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
import {ipv4CidrRange, ipv4HyphenatedRange, ipv6CidrRange, ipv6HyphenatedRange} from "../lib/IP";
|
||||
import {ipv4CidrRange, ipv4HyphenatedRange, ipv4ListedRange, ipv6CidrRange, ipv6HyphenatedRange, ipv6ListedRange} from "../lib/IP";
|
||||
|
||||
/**
|
||||
* Parse IP range operation
|
||||
@@ -21,7 +22,7 @@ class ParseIPRange extends Operation {
|
||||
|
||||
this.name = "Parse IP range";
|
||||
this.module = "JSBN";
|
||||
this.description = "Given a CIDR range (e.g. <code>10.0.0.0/24</code>) or a hyphenated range (e.g. <code>10.0.0.0 - 10.0.1.0</code>), this operation provides network information and enumerates all IP addresses in the range.<br><br>IPv6 is supported but will not be enumerated.";
|
||||
this.description = "Given a CIDR range (e.g. <code>10.0.0.0/24</code>), hyphenated range (e.g. <code>10.0.0.0 - 10.0.1.0</code>), or a list of IPs and/or CIDR ranges (separated by a new line), this operation provides network information and enumerates all IP addresses in the range.<br><br>IPv6 is supported but will not be enumerated.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Subnetwork";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
@@ -59,18 +60,24 @@ class ParseIPRange extends Operation {
|
||||
// Check what type of input we are looking at
|
||||
const ipv4CidrRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\/(\d\d?)\s*$/,
|
||||
ipv4RangeRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*-\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/,
|
||||
ipv4ListRegex = /^\s*(((?:\d{1,3}\.){3}\d{1,3})(\/(\d\d?))?(\n|$)(\n*))+\s*$/,
|
||||
ipv6CidrRegex = /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\/(\d\d?\d?)\s*$/i,
|
||||
ipv6RangeRegex = /^\s*(((?=.*::)(?!.*::[^-]+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*-\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\17)::|:\b|(?![\dA-F])))|(?!\16\17)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i;
|
||||
ipv6RangeRegex = /^\s*(((?=.*::)(?!.*::[^-]+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*-\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\17)::|:\b|(?![\dA-F])))|(?!\16\17)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i,
|
||||
ipv6ListRegex = /^\s*((((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))(\/(\d\d?\d?))?(\n|$)(\n*))+\s*$/i;
|
||||
let match;
|
||||
|
||||
if ((match = ipv4CidrRegex.exec(input))) {
|
||||
return ipv4CidrRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList);
|
||||
} else if ((match = ipv4RangeRegex.exec(input))) {
|
||||
return ipv4HyphenatedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList);
|
||||
} else if ((match = ipv4ListRegex.exec(input))) {
|
||||
return ipv4ListedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList);
|
||||
} else if ((match = ipv6CidrRegex.exec(input))) {
|
||||
return ipv6CidrRange(match, includeNetworkInfo);
|
||||
} else if ((match = ipv6RangeRegex.exec(input))) {
|
||||
return ipv6HyphenatedRange(match, includeNetworkInfo);
|
||||
} else if ((match = ipv6ListRegex.exec(input))) {
|
||||
return ipv6ListedRange(match, includeNetworkInfo);
|
||||
} else {
|
||||
throw new OperationError("Invalid input.\n\nEnter either a CIDR range (e.g. 10.0.0.0/24) or a hyphenated range (e.g. 10.0.0.0 - 10.0.1.0). IPv6 also supported.");
|
||||
}
|
||||
|
||||
107
src/core/operations/ParseQRCode.mjs
Normal file
107
src/core/operations/ParseQRCode.mjs
Normal file
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @author j433866 [j433866@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
import Magic from "../lib/Magic";
|
||||
import jsqr from "jsqr";
|
||||
import jimp from "jimp";
|
||||
|
||||
/**
|
||||
* Parse QR Code operation
|
||||
*/
|
||||
class ParseQRCode extends Operation {
|
||||
|
||||
/**
|
||||
* ParseQRCode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Parse QR Code";
|
||||
this.module = "Image";
|
||||
this.description = "Reads an image file and attempts to detect and read a Quick Response (QR) code from the image.<br><br><u>Normalise Image</u><br>Attempts to normalise the image before parsing it to improve detection of a QR code.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/QR_code";
|
||||
this.inputType = "byteArray";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Normalise image",
|
||||
"type": "boolean",
|
||||
"value": false
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
async run(input, args) {
|
||||
const type = Magic.magicFileType(input);
|
||||
const [normalise] = args;
|
||||
|
||||
// Make sure that the input is an image
|
||||
if (type && type.mime.indexOf("image") === 0) {
|
||||
let image = input;
|
||||
|
||||
if (normalise) {
|
||||
// Process the image to be easier to read by jsqr
|
||||
// Disables the alpha channel
|
||||
// Sets the image default background to white
|
||||
// Normalises the image colours
|
||||
// Makes the image greyscale
|
||||
// Converts image to a JPEG
|
||||
image = await new Promise((resolve, reject) => {
|
||||
jimp.read(Buffer.from(input))
|
||||
.then(image => {
|
||||
image
|
||||
.rgba(false)
|
||||
.background(0xFFFFFFFF)
|
||||
.normalize()
|
||||
.greyscale()
|
||||
.getBuffer(jimp.MIME_JPEG, (error, result) => {
|
||||
resolve(result);
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
reject(new OperationError("Error reading the image file."));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (image instanceof OperationError) {
|
||||
throw image;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
jimp.read(Buffer.from(image))
|
||||
.then(image => {
|
||||
if (image.bitmap != null) {
|
||||
const qrData = jsqr(image.bitmap.data, image.getWidth(), image.getHeight());
|
||||
if (qrData != null) {
|
||||
resolve(qrData.data);
|
||||
} else {
|
||||
reject(new OperationError("Couldn't read a QR code from the image."));
|
||||
}
|
||||
} else {
|
||||
reject(new OperationError("Error reading the image file."));
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
reject(new OperationError("Error reading the image file."));
|
||||
});
|
||||
});
|
||||
} else {
|
||||
throw new OperationError("Invalid file type.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ParseQRCode;
|
||||
76
src/core/operations/ParseTLV.mjs
Normal file
76
src/core/operations/ParseTLV.mjs
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* @author gchq77703 []
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import TLVParser from "../lib/TLVParser";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* Parse TLV operation
|
||||
*/
|
||||
class ParseTLV extends Operation {
|
||||
|
||||
/**
|
||||
* ParseTLV constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Parse TLV";
|
||||
this.module = "Default";
|
||||
this.description = "Converts a Type-Length-Value (TLV) encoded string into a JSON object. Can optionally include a <code>Key</code> / <code>Type</code> entry. <br><br>Tags: Key-Length-Value, KLV, Length-Value, LV";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Type-length-value";
|
||||
this.inputType = "byteArray";
|
||||
this.outputType = "JSON";
|
||||
this.args = [
|
||||
{
|
||||
name: "Type/Key size",
|
||||
type: "number",
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
name: "Length size",
|
||||
type: "number",
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
name: "Use BER",
|
||||
type: "boolean",
|
||||
value: false
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [bytesInKey, bytesInLength, basicEncodingRules] = args;
|
||||
|
||||
if (bytesInKey <= 0 && bytesInLength <= 0)
|
||||
throw new OperationError("Type or Length size must be greater than 0");
|
||||
|
||||
const tlv = new TLVParser(input, { bytesInLength, basicEncodingRules });
|
||||
|
||||
const data = [];
|
||||
|
||||
while (!tlv.atEnd()) {
|
||||
const key = bytesInKey ? tlv.getValue(bytesInKey) : undefined;
|
||||
const length = tlv.getLength();
|
||||
const value = tlv.getValue(length);
|
||||
|
||||
data.push({ key, length, value });
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ParseTLV;
|
||||
102
src/core/operations/PlayMedia.mjs
Normal file
102
src/core/operations/PlayMedia.mjs
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* @author anthony-arnold [anthony.arnold@uqconnect.edu.au]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import { fromBase64, toBase64 } from "../lib/Base64";
|
||||
import { fromHex } from "../lib/Hex";
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
import Utils from "../Utils";
|
||||
import Magic from "../lib/Magic";
|
||||
|
||||
/**
|
||||
* PlayMedia operation
|
||||
*/
|
||||
class PlayMedia extends Operation {
|
||||
|
||||
/**
|
||||
* PlayMedia constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Play Media";
|
||||
this.module = "Default";
|
||||
this.description = "Plays the input as audio or video depending on the type.<br><br>Tags: sound, movie, mp3, mp4, mov, webm, wav, ogg";
|
||||
this.infoURL = "";
|
||||
this.inputType = "string";
|
||||
this.outputType = "byteArray";
|
||||
this.presentType = "html";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Input format",
|
||||
"type": "option",
|
||||
"value": ["Raw", "Base64", "Hex"]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray} The multimedia data as bytes.
|
||||
*/
|
||||
run(input, args) {
|
||||
const [inputFormat] = args;
|
||||
|
||||
if (!input.length) return [];
|
||||
|
||||
// Convert input to raw bytes
|
||||
switch (inputFormat) {
|
||||
case "Hex":
|
||||
input = fromHex(input);
|
||||
break;
|
||||
case "Base64":
|
||||
// Don't trust the Base64 entered by the user.
|
||||
// Unwrap it first, then re-encode later.
|
||||
input = fromBase64(input, undefined, "byteArray");
|
||||
break;
|
||||
case "Raw":
|
||||
default:
|
||||
input = Utils.strToByteArray(input);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Determine file type
|
||||
const type = Magic.magicFileType(input);
|
||||
if (!(type && /^audio|video/.test(type.mime))) {
|
||||
throw new OperationError("Invalid or unrecognised file type");
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays an audio or video element that may be able to play the media
|
||||
* file.
|
||||
*
|
||||
* @param data {byteArray} Data containing an audio or video file.
|
||||
* @returns {string} Markup to display a media player.
|
||||
*/
|
||||
async present(data) {
|
||||
if (!data.length) return "";
|
||||
|
||||
const type = Magic.magicFileType(data);
|
||||
const matches = /^audio|video/.exec(type.mime);
|
||||
if (!matches) {
|
||||
throw new OperationError("Invalid file type");
|
||||
}
|
||||
const dataURI = `data:${type.mime};base64,${toBase64(data)}`;
|
||||
const element = matches[0];
|
||||
|
||||
let html = `<${element} src='${dataURI}' type='${type.mime}' controls>`;
|
||||
html += "<p>Unsupported media type.</p>";
|
||||
html += `</${element}>`;
|
||||
return html;
|
||||
}
|
||||
}
|
||||
|
||||
export default PlayMedia;
|
||||
@@ -227,6 +227,7 @@ function regexList (input, regex, displayTotal, matches, captureGroups) {
|
||||
*/
|
||||
function regexHighlight (input, regex, displayTotal) {
|
||||
let output = "",
|
||||
title = "",
|
||||
m,
|
||||
hl = 1,
|
||||
i = 0,
|
||||
@@ -241,8 +242,16 @@ function regexHighlight (input, regex, displayTotal) {
|
||||
// Add up to match
|
||||
output += Utils.escapeHtml(input.slice(i, m.index));
|
||||
|
||||
title = `Offset: ${m.index}\n`;
|
||||
if (m.length > 1) {
|
||||
title += "Groups:\n";
|
||||
for (let n = 1; n < m.length; ++n) {
|
||||
title += `\t${n}: ${m[n]}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
// Add match with highlighting
|
||||
output += "<span class='hl"+hl+"'>" + Utils.escapeHtml(m[0]) + "</span>";
|
||||
output += "<span class='hl"+hl+"' title='"+title+"'>" + Utils.escapeHtml(m[0]) + "</span>";
|
||||
|
||||
// Switch highlight
|
||||
hl = hl === 1 ? 2 : 1;
|
||||
|
||||
41
src/core/operations/RemoveDiacritics.mjs
Normal file
41
src/core/operations/RemoveDiacritics.mjs
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @author Klaxon [klaxon@veyr.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
|
||||
/**
|
||||
* Remove Diacritics operation
|
||||
*/
|
||||
class RemoveDiacritics extends Operation {
|
||||
|
||||
/**
|
||||
* RemoveDiacritics constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Remove Diacritics";
|
||||
this.module = "Default";
|
||||
this.description = "Replaces accented characters with their latin character equivalent.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Diacritic";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
// reference: https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript/37511463
|
||||
return input.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RemoveDiacritics;
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import Operation from "../Operation";
|
||||
import Utils from "../Utils";
|
||||
import { bitOp, sub } from "../lib/BitwiseOp";
|
||||
import { bitOp, sub, BITWISE_OP_DELIMS } from "../lib/BitwiseOp";
|
||||
|
||||
/**
|
||||
* SUB operation
|
||||
@@ -30,7 +30,7 @@ class SUB extends Operation {
|
||||
"name": "Key",
|
||||
"type": "toggleString",
|
||||
"value": "",
|
||||
"toggleValues": ["Hex", "Decimal", "Base64", "UTF8", "Latin1"]
|
||||
"toggleValues": BITWISE_OP_DELIMS
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class Scrypt extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const salt = Utils.convertToByteString(args[0].string || "", args[0].option),
|
||||
const salt = Buffer.from(Utils.convertToByteArray(args[0].string || "", args[0].option)),
|
||||
iterations = args[1],
|
||||
memFactor = args[2],
|
||||
parallelFactor = args[3],
|
||||
|
||||
@@ -38,7 +38,7 @@ class Sort extends Operation {
|
||||
{
|
||||
"name": "Order",
|
||||
"type": "option",
|
||||
"value": ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric"]
|
||||
"value": ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric", "Numeric (hexadecimal)"]
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -62,6 +62,8 @@ class Sort extends Operation {
|
||||
sorted = sorted.sort(Sort._ipSort);
|
||||
} else if (order === "Numeric") {
|
||||
sorted = sorted.sort(Sort._numericSort);
|
||||
} else if (order === "Numeric (hexadecimal)") {
|
||||
sorted = sorted.sort(Sort._hexadecimalSort);
|
||||
}
|
||||
|
||||
if (sortReverse) sorted.reverse();
|
||||
@@ -131,6 +133,44 @@ class Sort extends Operation {
|
||||
return a.localeCompare(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparison operation for sorting of hexadecimal values.
|
||||
*
|
||||
* @author Chris van Marle
|
||||
* @private
|
||||
* @param {string} a
|
||||
* @param {string} b
|
||||
* @returns {number}
|
||||
*/
|
||||
static _hexadecimalSort(a, b) {
|
||||
let a_ = a.split(/([^\da-f]+)/i),
|
||||
b_ = b.split(/([^\da-f]+)/i);
|
||||
|
||||
a_ = a_.map(v => {
|
||||
const t = parseInt(v, 16);
|
||||
return isNaN(t) ? v : t;
|
||||
});
|
||||
|
||||
b_ = b_.map(v => {
|
||||
const t = parseInt(v, 16);
|
||||
return isNaN(t) ? v : t;
|
||||
});
|
||||
|
||||
for (let i = 0; i < a_.length && i < b.length; ++i) {
|
||||
if (isNaN(a_[i]) && !isNaN(b_[i])) return 1; // Numbers after non-numbers
|
||||
if (!isNaN(a_[i]) && isNaN(b_[i])) return -1;
|
||||
if (isNaN(a_[i]) && isNaN(b_[i])) {
|
||||
const ret = a_[i].localeCompare(b_[i]); // Compare strings
|
||||
if (ret !== 0) return ret;
|
||||
}
|
||||
if (!isNaN(a_[i]) && !isNaN(a_[i])) { // Compare numbers
|
||||
if (a_[i] - b_[i] !== 0) return a_[i] - b_[i];
|
||||
}
|
||||
}
|
||||
|
||||
return a.localeCompare(b);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Sort;
|
||||
|
||||
@@ -20,7 +20,7 @@ class Substitute extends Operation {
|
||||
|
||||
this.name = "Substitute";
|
||||
this.module = "Default";
|
||||
this.description = "A substitution cipher allowing you to specify bytes to replace with other byte values. This can be used to create Caesar ciphers but is more powerful as any byte value can be substituted, not just letters, and the substitution values need not be in order.<br><br>Enter the bytes you want to replace in the Plaintext field and the bytes to replace them with in the Ciphertext field.<br><br>Non-printable bytes can be specified using string escape notation. For example, a line feed character can be written as either <code>\n</code> or <code>\x0a</code>.<br><br>Byte ranges can be specified using a hyphen. For example, the sequence <code>0123456789</code> can be written as <code>0-9</code>.";
|
||||
this.description = "A substitution cipher allowing you to specify bytes to replace with other byte values. This can be used to create Caesar ciphers but is more powerful as any byte value can be substituted, not just letters, and the substitution values need not be in order.<br><br>Enter the bytes you want to replace in the Plaintext field and the bytes to replace them with in the Ciphertext field.<br><br>Non-printable bytes can be specified using string escape notation. For example, a line feed character can be written as either <code>\\n</code> or <code>\\x0a</code>.<br><br>Byte ranges can be specified using a hyphen. For example, the sequence <code>0123456789</code> can be written as <code>0-9</code>.<br><br>Note that blackslash characters are used to escape special characters, so will need to be escaped themselves if you want to use them on their own (e.g.<code>\\\\</code>).";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Substitution_cipher";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
|
||||
92
src/core/operations/TextEncodingBruteForce.mjs
Normal file
92
src/core/operations/TextEncodingBruteForce.mjs
Normal file
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* @author Cynser
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import Utils from "../Utils";
|
||||
import cptable from "../vendor/js-codepage/cptable.js";
|
||||
import {IO_FORMAT} from "../lib/ChrEnc";
|
||||
|
||||
/**
|
||||
* Text Encoding Brute Force operation
|
||||
*/
|
||||
class TextEncodingBruteForce extends Operation {
|
||||
|
||||
/**
|
||||
* TextEncodingBruteForce constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Text Encoding Brute Force";
|
||||
this.module = "CharEnc";
|
||||
this.description = [
|
||||
"Enumerates all supported text encodings for the input, allowing you to quickly spot the correct one.",
|
||||
"<br><br>",
|
||||
"Supported charsets are:",
|
||||
"<ul>",
|
||||
Object.keys(IO_FORMAT).map(e => `<li>${e}</li>`).join("\n"),
|
||||
"</ul>"
|
||||
].join("\n");
|
||||
this.infoURL = "https://wikipedia.org/wiki/Character_encoding";
|
||||
this.inputType = "string";
|
||||
this.outputType = "json";
|
||||
this.presentType = "html";
|
||||
this.args = [
|
||||
{
|
||||
name: "Mode",
|
||||
type: "option",
|
||||
value: ["Encode", "Decode"]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {json}
|
||||
*/
|
||||
run(input, args) {
|
||||
const output = {},
|
||||
charsets = Object.keys(IO_FORMAT),
|
||||
mode = args[0];
|
||||
|
||||
charsets.forEach(charset => {
|
||||
try {
|
||||
if (mode === "Decode") {
|
||||
output[charset] = cptable.utils.decode(IO_FORMAT[charset], input);
|
||||
} else {
|
||||
output[charset] = Utils.arrayBufferToStr(cptable.utils.encode(IO_FORMAT[charset], input));
|
||||
}
|
||||
} catch (err) {
|
||||
output[charset] = "Could not decode.";
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the encodings in an HTML table for web apps.
|
||||
*
|
||||
* @param {Object[]} encodings
|
||||
* @returns {html}
|
||||
*/
|
||||
present(encodings) {
|
||||
let table = "<table class='table table-hover table-sm table-bordered table-nonfluid'><tr><th>Encoding</th><th>Value</th></tr>";
|
||||
|
||||
for (const enc in encodings) {
|
||||
const value = Utils.printable(encodings[enc], true);
|
||||
table += `<tr><td>${enc}</td><td>${value}</td></tr>`;
|
||||
}
|
||||
|
||||
table += "<table>";
|
||||
return table;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default TextEncodingBruteForce;
|
||||
@@ -53,6 +53,11 @@ class ToBase58 extends Operation {
|
||||
|
||||
if (input.length === 0) return "";
|
||||
|
||||
let zeroPrefix = 0;
|
||||
for (let i = 0; i < input.length && input[i] === 0; i++) {
|
||||
zeroPrefix++;
|
||||
}
|
||||
|
||||
input.forEach(function(b) {
|
||||
let carry = (result[0] << 8) + b;
|
||||
result[0] = carry % 58;
|
||||
@@ -74,7 +79,7 @@ class ToBase58 extends Operation {
|
||||
return alphabet[b];
|
||||
}).reverse().join("");
|
||||
|
||||
while (result.length < input.length) {
|
||||
while (zeroPrefix--) {
|
||||
result = alphabet[0] + result;
|
||||
}
|
||||
|
||||
|
||||
58
src/core/operations/ToBase62.mjs
Normal file
58
src/core/operations/ToBase62.mjs
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @author tcode2k16 [tcode2k16@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import BigNumber from "bignumber.js";
|
||||
import Utils from "../Utils";
|
||||
import {toHexFast} from "../lib/Hex";
|
||||
|
||||
/**
|
||||
* To Base62 operation
|
||||
*/
|
||||
class ToBase62 extends Operation {
|
||||
|
||||
/**
|
||||
* ToBase62 constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "To Base62";
|
||||
this.module = "Default";
|
||||
this.description = "Base62 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers. The high number base results in shorter strings than with the decimal or hexadecimal system.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems";
|
||||
this.inputType = "byteArray";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Alphabet",
|
||||
type: "string",
|
||||
value: "0-9A-Za-z"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
if (input.length < 1) return "";
|
||||
|
||||
const ALPHABET = Utils.expandAlphRange(args[0]).join("");
|
||||
const BN = BigNumber.clone({ ALPHABET });
|
||||
|
||||
input = toHexFast(input).toUpperCase();
|
||||
|
||||
const number = new BN(input, 16);
|
||||
|
||||
return number.toString(62);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ToBase62;
|
||||
@@ -7,6 +7,7 @@
|
||||
import Operation from "../Operation";
|
||||
import Utils from "../Utils";
|
||||
import {BIN_DELIM_OPTIONS} from "../lib/Delim";
|
||||
import {toBinary} from "../lib/Binary";
|
||||
|
||||
/**
|
||||
* To Binary operation
|
||||
@@ -40,19 +41,7 @@ class ToBinary extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const delim = Utils.charRep(args[0] || "Space"),
|
||||
padding = 8;
|
||||
let output = "";
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
output += input[i].toString(2).padStart(padding, "0") + delim;
|
||||
}
|
||||
|
||||
if (delim.length) {
|
||||
return output.slice(0, -delim.length);
|
||||
} else {
|
||||
return output;
|
||||
}
|
||||
return toBinary(input, args[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
70
src/core/operations/ToBraille.mjs
Normal file
70
src/core/operations/ToBraille.mjs
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import {BRAILLE_LOOKUP} from "../lib/Braille";
|
||||
|
||||
/**
|
||||
* To Braille operation
|
||||
*/
|
||||
class ToBraille extends Operation {
|
||||
|
||||
/**
|
||||
* ToBraille constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "To Braille";
|
||||
this.module = "Default";
|
||||
this.description = "Converts text to six-dot braille symbols.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Braille";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
return input.split("").map(c => {
|
||||
const idx = BRAILLE_LOOKUP.ascii.indexOf(c.toUpperCase());
|
||||
return idx < 0 ? c : BRAILLE_LOOKUP.dot6[idx];
|
||||
}).join("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight To Braille
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlight(pos, args) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight To Braille in reverse
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightReverse(pos, args) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ToBraille;
|
||||
@@ -30,6 +30,11 @@ class ToDecimal extends Operation {
|
||||
"name": "Delimiter",
|
||||
"type": "option",
|
||||
"value": DELIM_OPTIONS
|
||||
},
|
||||
{
|
||||
"name": "Support signed values",
|
||||
"type": "boolean",
|
||||
"value": false
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -40,7 +45,11 @@ class ToDecimal extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const delim = Utils.charRep(args[0]);
|
||||
const delim = Utils.charRep(args[0]),
|
||||
signed = args[1];
|
||||
if (signed) {
|
||||
input = input.map(v => v > 0x7F ? v - 0xFF - 1 : v);
|
||||
}
|
||||
return input.join(delim);
|
||||
}
|
||||
|
||||
|
||||
53
src/core/operations/ToGeohash.mjs
Normal file
53
src/core/operations/ToGeohash.mjs
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @author gchq77703 []
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import geohash from "ngeohash";
|
||||
|
||||
/**
|
||||
* To Geohash operation
|
||||
*/
|
||||
class ToGeohash extends Operation {
|
||||
|
||||
/**
|
||||
* ToGeohash constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "To Geohash";
|
||||
this.module = "Hashing";
|
||||
this.description = "Converts Lat/Long coordinates into a Geohash string. For example, <code>37.8324,112.5584</code> becomes <code>ww8p1r4t8</code>.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Geohash";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Precision",
|
||||
type: "number",
|
||||
value: 9
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [precision] = args;
|
||||
|
||||
return input.split("\n").map(line => {
|
||||
line = line.replace(/ /g, "");
|
||||
if (line === "") return "";
|
||||
return geohash.encode(...line.split(",").map(num => parseFloat(num)), precision);
|
||||
}).join("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ToGeohash;
|
||||
@@ -33,7 +33,7 @@ class ToTable extends Operation {
|
||||
{
|
||||
"name": "Row delimiters",
|
||||
"type": "binaryShortString",
|
||||
"value": "\\n\\r"
|
||||
"value": "\\r\\n"
|
||||
},
|
||||
{
|
||||
"name": "Make first row header",
|
||||
|
||||
@@ -20,7 +20,7 @@ class Whirlpool extends Operation {
|
||||
|
||||
this.name = "Whirlpool";
|
||||
this.module = "Hashing";
|
||||
this.description = "Whirlpool is a cryptographic hash function designed by Vincent Rijmen (co-creator of AES) and Paulo S. L. M. Barreto, who first described it in 2000.<br><br>Several variants exist:<ul><li>Whirlpool-0 is the original version released in 2000.</li><li>Whirlpool-T is the first revision, released in 2001, improving the generation of the s-box.</li><li>Wirlpool is the latest revision, released in 2003, fixing a flaw in the difusion matrix.</li></ul>";
|
||||
this.description = "Whirlpool is a cryptographic hash function designed by Vincent Rijmen (co-creator of AES) and Paulo S. L. M. Barreto, who first described it in 2000.<br><br>Several variants exist:<ul><li>Whirlpool-0 is the original version released in 2000.</li><li>Whirlpool-T is the first revision, released in 2001, improving the generation of the s-box.</li><li>Whirlpool is the latest revision, released in 2003, fixing a flaw in the difusion matrix.</li></ul>";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Whirlpool_(cryptography)";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "string";
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import Operation from "../Operation";
|
||||
import Utils from "../Utils";
|
||||
import { bitOp, xor } from "../lib/BitwiseOp";
|
||||
import { bitOp, xor, BITWISE_OP_DELIMS } from "../lib/BitwiseOp";
|
||||
|
||||
/**
|
||||
* XOR operation
|
||||
@@ -21,7 +21,7 @@ class XOR extends Operation {
|
||||
|
||||
this.name = "XOR";
|
||||
this.module = "Default";
|
||||
this.description = "XOR the input with the given key.<br>e.g. <code>fe023da5</code><br><br><strong>Options</strong><br><u>Null preserving:</u> If the current byte is 0x00 or the same as the key, skip it.<br><br><u>Scheme:</u><ul><li>Standard - key is unchanged after each round</li><li>Input differential - key is set to the value of the previous unprocessed byte</li><li>Output differential - key is set to the value of the previous processed byte</li></ul>";
|
||||
this.description = "XOR the input with the given key.<br>e.g. <code>fe023da5</code><br><br><strong>Options</strong><br><u>Null preserving:</u> If the current byte is 0x00 or the same as the key, skip it.<br><br><u>Scheme:</u><ul><li>Standard - key is unchanged after each round</li><li>Input differential - key is set to the value of the previous unprocessed byte</li><li>Output differential - key is set to the value of the previous processed byte</li><li>Cascade - key is set to the input byte shifted by one</li></ul>";
|
||||
this.infoURL = "https://wikipedia.org/wiki/XOR";
|
||||
this.inputType = "byteArray";
|
||||
this.outputType = "byteArray";
|
||||
@@ -30,12 +30,12 @@ class XOR extends Operation {
|
||||
"name": "Key",
|
||||
"type": "toggleString",
|
||||
"value": "",
|
||||
"toggleValues": ["Hex", "Decimal", "Base64", "UTF8", "Latin1"]
|
||||
"toggleValues": BITWISE_OP_DELIMS
|
||||
},
|
||||
{
|
||||
"name": "Scheme",
|
||||
"type": "option",
|
||||
"value": ["Standard", "Input differential", "Output differential"]
|
||||
"value": ["Standard", "Input differential", "Output differential", "Cascade"]
|
||||
},
|
||||
{
|
||||
"name": "Null preserving",
|
||||
|
||||
@@ -262,4 +262,4 @@ bzip2.decompress = function(bits, size, len){
|
||||
return output;
|
||||
}
|
||||
|
||||
module.exports = bzip2;
|
||||
export default bzip2;
|
||||
@@ -67,6 +67,7 @@ class BackgroundWorkerWaiter {
|
||||
log.debug("Background ChefWorker loaded");
|
||||
break;
|
||||
case "optionUpdate":
|
||||
case "statusMessage":
|
||||
// Ignore these messages
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -26,6 +26,7 @@ class HTMLIngredient {
|
||||
this.disabled = config.disabled || false;
|
||||
this.hint = config.hint || false;
|
||||
this.target = config.target;
|
||||
this.defaultIndex = config.defaultIndex || 0;
|
||||
this.toggleValues = config.toggleValues;
|
||||
this.id = "ing-" + this.app.nextIngId();
|
||||
}
|
||||
@@ -133,7 +134,7 @@ class HTMLIngredient {
|
||||
} else if ((m = this.value[i].match(/\[\/([a-z0-9 -()^]+)\]/i))) {
|
||||
html += "</optgroup>";
|
||||
} else {
|
||||
html += `<option>${this.value[i]}</option>`;
|
||||
html += `<option ${this.defaultIndex === i ? "selected" : ""}>${this.value[i]}</option>`;
|
||||
}
|
||||
}
|
||||
html += `</select>
|
||||
@@ -170,7 +171,7 @@ class HTMLIngredient {
|
||||
class="form-control arg inline"
|
||||
id="${this.id}"
|
||||
arg-name="${this.name}"
|
||||
value="${this.value[0].value}"
|
||||
value="${this.value[this.defaultIndex].value}"
|
||||
${this.disabled ? "disabled" : ""}>
|
||||
${this.hint ? "<span class='bmd-help'>" + this.hint + "</span>" : ""}
|
||||
<div class="input-group-append inline">
|
||||
|
||||
@@ -131,14 +131,16 @@ class HTMLOperation {
|
||||
*/
|
||||
function titleFromWikiLink(url) {
|
||||
const splitURL = url.split("/");
|
||||
if (splitURL.indexOf("wiki") < 0) {
|
||||
if (splitURL.indexOf("wikipedia.org") < 0 && splitURL.indexOf("forensicswiki.org") < 0) {
|
||||
// Not a wiki link, return full URL
|
||||
return `<a href='${url}' target='_blank'>More Information<i class='material-icons inline-icon'>open_in_new</i></a>`;
|
||||
}
|
||||
|
||||
const wikiName = splitURL.indexOf("forensicswiki.org") < 0 ? "Wikipedia" : "Forensics Wiki";
|
||||
|
||||
const pageTitle = decodeURIComponent(splitURL[splitURL.length - 1])
|
||||
.replace(/_/g, " ");
|
||||
return `<a href='${url}' target='_blank'>${pageTitle}<i class='material-icons inline-icon'>open_in_new</i></a> on Wikipedia`;
|
||||
return `<a href='${url}' target='_blank'>${pageTitle}<i class='material-icons inline-icon'>open_in_new</i></a> on ${wikiName}`;
|
||||
}
|
||||
|
||||
export default HTMLOperation;
|
||||
|
||||
@@ -116,6 +116,13 @@ div.toggle-string {
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
.operation label.bmd-label-floating {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
width: calc(100% - 13px);
|
||||
}
|
||||
|
||||
.operation .bmd-form-group .bmd-help {
|
||||
margin-top: -17px;
|
||||
}
|
||||
@@ -172,6 +179,7 @@ div.toggle-string {
|
||||
background-color: var(--fc-operation-border-colour);
|
||||
font-family: var(--fixed-width-font-family);
|
||||
padding: 10px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.op-icon {
|
||||
|
||||
@@ -24,46 +24,64 @@ global.ENVIRONMENT_IS_WEB = function() {
|
||||
};
|
||||
|
||||
import TestRegister from "./TestRegister";
|
||||
import "./tests/operations/BCD";
|
||||
import "./tests/operations/BSON";
|
||||
import "./tests/operations/Base58";
|
||||
import "./tests/operations/Base64";
|
||||
import "./tests/operations/BCD";
|
||||
import "./tests/operations/Base62";
|
||||
import "./tests/operations/BitwiseOp";
|
||||
import "./tests/operations/BSON";
|
||||
import "./tests/operations/ByteRepr";
|
||||
import "./tests/operations/CartesianProduct";
|
||||
import "./tests/operations/CharEnc";
|
||||
import "./tests/operations/Ciphers";
|
||||
import "./tests/operations/Checksum";
|
||||
import "./tests/operations/Ciphers";
|
||||
import "./tests/operations/Code";
|
||||
import "./tests/operations/Compress";
|
||||
import "./tests/operations/Crypt";
|
||||
import "./tests/operations/DateTime";
|
||||
import "./tests/operations/Fork";
|
||||
import "./tests/operations/Jump";
|
||||
import "./tests/operations/ConditionalJump";
|
||||
import "./tests/operations/Register";
|
||||
import "./tests/operations/Comment";
|
||||
import "./tests/operations/Compress";
|
||||
import "./tests/operations/ConditionalJump";
|
||||
import "./tests/operations/Crypt";
|
||||
import "./tests/operations/CSV";
|
||||
import "./tests/operations/DateTime";
|
||||
import "./tests/operations/ExtractEmailAddresses";
|
||||
import "./tests/operations/Fork";
|
||||
import "./tests/operations/FromDecimal";
|
||||
import "./tests/operations/FromGeohash";
|
||||
import "./tests/operations/Hash";
|
||||
import "./tests/operations/HaversineDistance";
|
||||
import "./tests/operations/Hexdump";
|
||||
import "./tests/operations/Image";
|
||||
import "./tests/operations/MorseCode";
|
||||
import "./tests/operations/Jump";
|
||||
import "./tests/operations/JSONBeautify";
|
||||
import "./tests/operations/JSONMinify";
|
||||
import "./tests/operations/JWTDecode";
|
||||
import "./tests/operations/JWTSign";
|
||||
import "./tests/operations/JWTVerify";
|
||||
import "./tests/operations/MS";
|
||||
import "./tests/operations/PGP";
|
||||
import "./tests/operations/PHP";
|
||||
import "./tests/operations/Magic";
|
||||
import "./tests/operations/MorseCode";
|
||||
import "./tests/operations/NetBIOS";
|
||||
import "./tests/operations/OTP";
|
||||
import "./tests/operations/PGP";
|
||||
import "./tests/operations/PHP";
|
||||
import "./tests/operations/ParseIPRange";
|
||||
import "./tests/operations/ParseQRCode";
|
||||
import "./tests/operations/PowerSet";
|
||||
import "./tests/operations/Regex";
|
||||
import "./tests/operations/Register";
|
||||
import "./tests/operations/RemoveDiacritics";
|
||||
import "./tests/operations/Rotate";
|
||||
import "./tests/operations/StrUtils";
|
||||
import "./tests/operations/SeqUtils";
|
||||
import "./tests/operations/SetDifference";
|
||||
import "./tests/operations/SetIntersection";
|
||||
import "./tests/operations/SetUnion";
|
||||
import "./tests/operations/StrUtils";
|
||||
import "./tests/operations/SymmetricDifference";
|
||||
import "./tests/operations/TextEncodingBruteForce";
|
||||
import "./tests/operations/ToGeohash.mjs";
|
||||
import "./tests/operations/TranslateDateTimeFormat";
|
||||
import "./tests/operations/Magic";
|
||||
import "./tests/operations/ParseTLV";
|
||||
import "./tests/operations/Media";
|
||||
|
||||
let allTestsPassing = true;
|
||||
const testStatusCounts = {
|
||||
@@ -115,12 +133,12 @@ function handleTestResult(testResult) {
|
||||
|
||||
|
||||
/**
|
||||
* Fail if the process takes longer than 10 seconds.
|
||||
* Fail if the process takes longer than 60 seconds.
|
||||
*/
|
||||
setTimeout(function() {
|
||||
console.log("Tests took longer than 10 seconds to run, returning.");
|
||||
console.log("Tests took longer than 60 seconds to run, returning.");
|
||||
process.exit(1);
|
||||
}, 10 * 1000);
|
||||
}, 60 * 1000);
|
||||
|
||||
|
||||
TestRegister.runTests()
|
||||
@@ -142,4 +160,3 @@ TestRegister.runTests()
|
||||
|
||||
process.exit(allTestsPassing ? 0 : 1);
|
||||
});
|
||||
|
||||
|
||||
@@ -53,6 +53,28 @@ TestRegister.addTests([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Base58 with null prefix and suffix",
|
||||
input: "\0\0\0Hello\0\0\0",
|
||||
expectedOutput: "111D7LMXYjHjTu",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base58",
|
||||
args: ["123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base58 with null prefix and suffix",
|
||||
input: "111D7LMXYjHjTu",
|
||||
expectedOutput: "\0\0\0Hello\0\0\0",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Base58",
|
||||
args: ["123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base58 (Bitcoin): 'StV1DL6CwTryKyV'",
|
||||
input: "StV1DL6CwTryKyV",
|
||||
|
||||
79
test/tests/operations/Base62.mjs
Normal file
79
test/tests/operations/Base62.mjs
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Base62 tests.
|
||||
*
|
||||
* @author tcode2k16 [tcode2k16@gmail.com]
|
||||
*
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "To Base62: nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base62",
|
||||
args: ["0-9A-Za-z"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Base62: Hello, World!",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "1wJfrzvdbtXUOlUjUf",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base62",
|
||||
args: ["0-9A-Za-z"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Base62: UTF-8",
|
||||
input: "ნუ პანიკას",
|
||||
expectedOutput: "BPDNbjoGvDCDzHbKT77eWg0vGQrJuWRXltuRVZ",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base62",
|
||||
args: ["0-9A-Za-z"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base62: nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Base62",
|
||||
args: ["0-9A-Za-z"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base62: Hello, World!",
|
||||
input: "1wJfrzvdbtXUOlUjUf",
|
||||
expectedOutput: "Hello, World!",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Base62",
|
||||
args: ["0-9A-Za-z"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base62: UTF-8",
|
||||
input: "BPDNbjoGvDCDzHbKT77eWg0vGQrJuWRXltuRVZ",
|
||||
expectedOutput: "ნუ პანიკას",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Base62",
|
||||
args: ["0-9A-Za-z"],
|
||||
},
|
||||
],
|
||||
}
|
||||
]);
|
||||
179
test/tests/operations/CSV.mjs
Normal file
179
test/tests/operations/CSV.mjs
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* CSV tests.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
*
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
const EXAMPLE_CSV = `A,B,C,D,E,F\r
|
||||
1,2,3,4,5,6\r
|
||||
",",;,',"""",,\r
|
||||
"""hello""","a""1","multi\r
|
||||
line",,,end\r
|
||||
`;
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "CSV to JSON: Array of dictionaries",
|
||||
input: EXAMPLE_CSV,
|
||||
expectedOutput: JSON.stringify([
|
||||
{
|
||||
"A": "1",
|
||||
"B": "2",
|
||||
"C": "3",
|
||||
"D": "4",
|
||||
"E": "5",
|
||||
"F": "6"
|
||||
},
|
||||
{
|
||||
"A": ",",
|
||||
"B": ";",
|
||||
"C": "'",
|
||||
"D": "\"",
|
||||
"E": "",
|
||||
"F": ""
|
||||
},
|
||||
{
|
||||
"A": "\"hello\"",
|
||||
"B": "a\"1",
|
||||
"C": "multi\r\nline",
|
||||
"D": "",
|
||||
"E": "",
|
||||
"F": "end"
|
||||
}
|
||||
], null, 4),
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "CSV to JSON",
|
||||
args: [",", "\r\n", "Array of dictionaries"],
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "CSV to JSON: Array of arrays",
|
||||
input: EXAMPLE_CSV,
|
||||
expectedOutput: JSON.stringify([
|
||||
[
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E",
|
||||
"F"
|
||||
],
|
||||
[
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6"
|
||||
],
|
||||
[
|
||||
",",
|
||||
";",
|
||||
"'",
|
||||
"\"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
[
|
||||
"\"hello\"",
|
||||
"a\"1",
|
||||
"multi\r\nline",
|
||||
"",
|
||||
"",
|
||||
"end"
|
||||
]
|
||||
], null, 4),
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "CSV to JSON",
|
||||
args: [",", "\r\n", "Array of arrays"],
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON to CSV: Array of dictionaries",
|
||||
input: JSON.stringify([
|
||||
{
|
||||
"A": "1",
|
||||
"B": "2",
|
||||
"C": "3",
|
||||
"D": "4",
|
||||
"E": "5",
|
||||
"F": "6"
|
||||
},
|
||||
{
|
||||
"A": ",",
|
||||
"B": ";",
|
||||
"C": "'",
|
||||
"D": "\"",
|
||||
"E": "",
|
||||
"F": ""
|
||||
},
|
||||
{
|
||||
"A": "\"hello\"",
|
||||
"B": "a\"1",
|
||||
"C": "multi\r\nline",
|
||||
"D": "",
|
||||
"E": "",
|
||||
"F": "end"
|
||||
}
|
||||
]),
|
||||
expectedOutput: EXAMPLE_CSV,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON to CSV",
|
||||
args: [",", "\r\n"],
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON to CSV: Array of arrays",
|
||||
input: JSON.stringify([
|
||||
[
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E",
|
||||
"F"
|
||||
],
|
||||
[
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6"
|
||||
],
|
||||
[
|
||||
",",
|
||||
";",
|
||||
"'",
|
||||
"\"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
[
|
||||
"\"hello\"",
|
||||
"a\"1",
|
||||
"multi\r\nline",
|
||||
"",
|
||||
"",
|
||||
"end"
|
||||
]
|
||||
]),
|
||||
expectedOutput: EXAMPLE_CSV,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON to CSV",
|
||||
args: [",", "\r\n"],
|
||||
}
|
||||
],
|
||||
},
|
||||
]);
|
||||
@@ -110,6 +110,39 @@ TestRegister.addTests([
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "A1Z26 Encode: normal",
|
||||
input: "This is the test sentence.",
|
||||
expectedOutput: "20 8 9 19 9 19 20 8 5 20 5 19 20 19 5 14 20 5 14 3 5",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "A1Z26 Cipher Encode",
|
||||
args: ["Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "A1Z26 Decode: normal",
|
||||
input: "20 8 9 19 9 19 20 8 5 20 5 19 20 19 5 14 20 5 14 3 5",
|
||||
expectedOutput: "thisisthetestsentence",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "A1Z26 Cipher Decode",
|
||||
args: ["Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "A1Z26 Decode: error",
|
||||
input: "20 8 9 27",
|
||||
expectedOutput: "Error: all numbers must be between 1 and 26.",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "A1Z26 Cipher Decode",
|
||||
args: ["Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Atbash: no input",
|
||||
input: "",
|
||||
@@ -220,6 +253,39 @@ TestRegister.addTests([
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Citrix CTX1 Encode",
|
||||
input: "Password1",
|
||||
expectedOutput: "PFFAJEDBOHECJEDBODEGIMCJPOFLJKDPKLAO",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Citrix CTX1 Encode",
|
||||
"args": []
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Citrix CTX1 Decode: normal",
|
||||
input: "PFFAJEDBOHECJEDBODEGIMCJPOFLJKDPKLAO",
|
||||
expectedOutput: "Password1",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Citrix CTX1 Decode",
|
||||
"args": []
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Citrix CTX1 Decode: invalid length",
|
||||
input: "PFFAJEDBOHECJEDBODEGIMCJPOFLJKDPKLA",
|
||||
expectedOutput: "Incorrect hash length",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Citrix CTX1 Decode",
|
||||
"args": []
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Vigenère Encode: no input",
|
||||
input: "",
|
||||
|
||||
@@ -380,7 +380,7 @@ TestRegister.addTests([
|
||||
{
|
||||
name: "From MessagePack: valid msgpack",
|
||||
input: "81 a5 73 74 6f 72 65 83 a4 62 6f 6f 6b 94 84 a8 63 61 74 65 67 6f 72 79 a9 72 65 66 65 72 65 6e 63 65 a6 61 75 74 68 6f 72 aa 4e 69 67 65 6c 20 52 65 65 73 a5 74 69 74 6c 65 b6 53 61 79 69 6e 67 73 20 6f 66 20 74 68 65 20 43 65 6e 74 75 72 79 a5 70 72 69 63 65 cb 40 21 e6 66 66 66 66 66 84 a8 63 61 74 65 67 6f 72 79 a7 66 69 63 74 69 6f 6e a6 61 75 74 68 6f 72 ac 45 76 65 6c 79 6e 20 57 61 75 67 68 a5 74 69 74 6c 65 af 53 77 6f 72 64 20 6f 66 20 48 6f 6e 6f 75 72 a5 70 72 69 63 65 cb 40 29 fa e1 47 ae 14 7b 85 a8 63 61 74 65 67 6f 72 79 a7 66 69 63 74 69 6f 6e a6 61 75 74 68 6f 72 af 48 65 72 6d 61 6e 20 4d 65 6c 76 69 6c 6c 65 a5 74 69 74 6c 65 a9 4d 6f 62 79 20 44 69 63 6b a4 69 73 62 6e ad 30 2d 35 35 33 2d 32 31 33 31 31 2d 33 a5 70 72 69 63 65 cb 40 21 fa e1 47 ae 14 7b 85 a8 63 61 74 65 67 6f 72 79 a7 66 69 63 74 69 6f 6e a6 61 75 74 68 6f 72 b0 4a 2e 20 52 2e 20 52 2e 20 54 6f 6c 6b 69 65 6e a5 74 69 74 6c 65 b5 54 68 65 20 4c 6f 72 64 20 6f 66 20 74 68 65 20 52 69 6e 67 73 a4 69 73 62 6e ad 30 2d 33 39 35 2d 31 39 33 39 35 2d 38 a5 70 72 69 63 65 cb 40 36 fd 70 a3 d7 0a 3d a7 62 69 63 79 63 6c 65 82 a5 63 6f 6c 6f 72 a3 72 65 64 a5 70 72 69 63 65 cb 40 33 f3 33 33 33 33 33 a9 6e 65 77 73 70 61 70 65 72 92 83 a6 66 6f 72 6d 61 74 aa 62 72 6f 61 64 73 68 65 65 74 a5 74 69 74 6c 65 af 46 69 6e 61 6e 63 69 61 6c 20 54 69 6d 65 73 a5 70 72 69 63 65 cb 40 06 00 00 00 00 00 00 83 a6 66 6f 72 6d 61 74 a7 74 61 62 6c 6f 69 64 a5 74 69 74 6c 65 ac 54 68 65 20 47 75 61 72 64 69 61 6e a5 70 72 69 63 65 02",
|
||||
expectedOutput: JSON.stringify(JSON_TEST_DATA),
|
||||
expectedOutput: JSON.stringify(JSON_TEST_DATA, null, 4),
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
|
||||
55
test/tests/operations/ExtractEmailAddresses.mjs
Normal file
55
test/tests/operations/ExtractEmailAddresses.mjs
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* extract email address tests.
|
||||
*
|
||||
* @author Klaxon [klaxon@veyr.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Extract email address",
|
||||
input: "email@example.com\nfirstname.lastname@example.com\nemail@subdomain.example.com\nfirstname+lastname@example.com\n1234567890@example.com\nemail@example-one.com\n_______@example.com email@example.name\nemail@example.museum email@example.co.jp firstname-lastname@example.com",
|
||||
expectedOutput: "email@example.com\nfirstname.lastname@example.com\nemail@subdomain.example.com\nfirstname+lastname@example.com\n1234567890@example.com\nemail@example-one.com\n_______@example.com\nemail@example.name\nemail@example.museum\nemail@example.co.jp\nfirstname-lastname@example.com\n",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Extract email addresses",
|
||||
"args": [false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Extract email address - Display total",
|
||||
input: "email@example.com\nfirstname.lastname@example.com\nemail@subdomain.example.com\nfirstname+lastname@example.com\n1234567890@example.com\nemail@example-one.com\n_______@example.com email@example.name\nemail@example.museum email@example.co.jp firstname-lastname@example.com",
|
||||
expectedOutput: "Total found: 11\n\nemail@example.com\nfirstname.lastname@example.com\nemail@subdomain.example.com\nfirstname+lastname@example.com\n1234567890@example.com\nemail@example-one.com\n_______@example.com\nemail@example.name\nemail@example.museum\nemail@example.co.jp\nfirstname-lastname@example.com\n",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Extract email addresses",
|
||||
"args": [true]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Extract email address (Internationalized)",
|
||||
input: "\u4f0a\u662d\u5091@\u90f5\u4ef6.\u5546\u52d9 \u093e\u092e@\u092e\u094b\u0939\u0928.\u0908\u0928\u094d\u092b\u094b\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c \u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc Jos\u1ec5Silv\u1ec5@googl\u1ec5.com\nJos\u1ec5Silv\u1ec5@google.com and Jos\u1ec5Silva@google.com\nFoO@BaR.CoM, john@192.168.10.100\ng\xf3mez@junk.br and Abc.123@example.com.\nuser+mailbox/department=shipping@example.com\n\u7528\u6237@\u4f8b\u5b50.\u5e7f\u544a\n\u0909\u092a\u092f\u094b\u0917\u0915\u0930\u094d\u0924\u093e@\u0909\u0926\u093e\u0939\u0930\u0923.\u0915\u0949\u092e\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nD\xf6rte@S\xf6rensen.example.com\n\u0430\u0434\u0436\u0430\u0439@\u044d\u043a\u0437\u0430\u043c\u043f\u043b.\u0440\u0443\u0441\ntest@xn--bcher-kva.com",
|
||||
expectedOutput: "\u4f0a\u662d\u5091@\u90f5\u4ef6.\u5546\u52d9\n\u093e\u092e@\u092e\u094b\u0939\u0928.\u0908\u0928\u094d\u092b\u094b\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nJos\u1ec5Silv\u1ec5@googl\u1ec5.com\nJos\u1ec5Silv\u1ec5@google.com\nJos\u1ec5Silva@google.com\nFoO@BaR.CoM\njohn@192.168.10.100\ng\xf3mez@junk.br\nAbc.123@example.com\nuser+mailbox/department=shipping@example.com\n\u7528\u6237@\u4f8b\u5b50.\u5e7f\u544a\n\u0909\u092a\u092f\u094b\u0917\u0915\u0930\u094d\u0924\u093e@\u0909\u0926\u093e\u0939\u0930\u0923.\u0915\u0949\u092e\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nD\xf6rte@S\xf6rensen.example.com\n\u0430\u0434\u0436\u0430\u0439@\u044d\u043a\u0437\u0430\u043c\u043f\u043b.\u0440\u0443\u0441\ntest@xn--bcher-kva.com\n",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Extract email addresses",
|
||||
"args": [false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Extract email address - Display total (Internationalized)",
|
||||
input: "\u4f0a\u662d\u5091@\u90f5\u4ef6.\u5546\u52d9 \u093e\u092e@\u092e\u094b\u0939\u0928.\u0908\u0928\u094d\u092b\u094b\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c \u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc Jos\u1ec5Silv\u1ec5@googl\u1ec5.com\nJos\u1ec5Silv\u1ec5@google.com and Jos\u1ec5Silva@google.com\nFoO@BaR.CoM, john@192.168.10.100\ng\xf3mez@junk.br and Abc.123@example.com.\nuser+mailbox/department=shipping@example.com\n\u7528\u6237@\u4f8b\u5b50.\u5e7f\u544a\n\u0909\u092a\u092f\u094b\u0917\u0915\u0930\u094d\u0924\u093e@\u0909\u0926\u093e\u0939\u0930\u0923.\u0915\u0949\u092e\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nD\xf6rte@S\xf6rensen.example.com\n\u0430\u0434\u0436\u0430\u0439@\u044d\u043a\u0437\u0430\u043c\u043f\u043b.\u0440\u0443\u0441\ntest@xn--bcher-kva.com",
|
||||
expectedOutput: "Total found: 19\n\n\u4f0a\u662d\u5091@\u90f5\u4ef6.\u5546\u52d9\n\u093e\u092e@\u092e\u094b\u0939\u0928.\u0908\u0928\u094d\u092b\u094b\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nJos\u1ec5Silv\u1ec5@googl\u1ec5.com\nJos\u1ec5Silv\u1ec5@google.com\nJos\u1ec5Silva@google.com\nFoO@BaR.CoM\njohn@192.168.10.100\ng\xf3mez@junk.br\nAbc.123@example.com\nuser+mailbox/department=shipping@example.com\n\u7528\u6237@\u4f8b\u5b50.\u5e7f\u544a\n\u0909\u092a\u092f\u094b\u0917\u0915\u0930\u094d\u0924\u093e@\u0909\u0926\u093e\u0939\u0930\u0923.\u0915\u0949\u092e\n\u044e\u0437\u0435\u0440@\u0435\u043a\u0437\u0430\u043c\u043f\u043b.\u043a\u043e\u043c\n\u03b8\u03c3\u03b5\u03c1@\u03b5\u03c7\u03b1\u03bc\u03c0\u03bb\u03b5.\u03c8\u03bf\u03bc\nD\xf6rte@S\xf6rensen.example.com\n\u0430\u0434\u0436\u0430\u0439@\u044d\u043a\u0437\u0430\u043c\u043f\u043b.\u0440\u0443\u0441\ntest@xn--bcher-kva.com\n",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Extract email addresses",
|
||||
"args": [true]
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
33
test/tests/operations/FromDecimal.mjs
Normal file
33
test/tests/operations/FromDecimal.mjs
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* From Decimal tests
|
||||
*
|
||||
* @author qistoph
|
||||
* @copyright Crown Copyright 2018
|
||||
* @licence Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "From Decimal",
|
||||
input: "83 97 109 112 108 101 32 84 101 120 116",
|
||||
expectedOutput: "Sample Text",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Decimal",
|
||||
args: ["Space", false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Decimal with negatives",
|
||||
input: "-130,-140,-152,-151,115,33,0,-1",
|
||||
expectedOutput: "~this!\u0000\u00ff",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Decimal",
|
||||
args: ["Comma", true]
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
55
test/tests/operations/FromGeohash.mjs
Normal file
55
test/tests/operations/FromGeohash.mjs
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* To Geohash tests
|
||||
*
|
||||
* @author gchq77703
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "From Geohash",
|
||||
input: "ww8p1r4t8",
|
||||
expectedOutput: "37.83238649368286,112.55838632583618",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Geohash",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Geohash",
|
||||
input: "ww8p1r",
|
||||
expectedOutput: "37.83416748046875,112.5604248046875",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Geohash",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Geohash",
|
||||
input: "ww8",
|
||||
expectedOutput: "37.265625,113.203125",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Geohash",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Geohash",
|
||||
input: "w",
|
||||
expectedOutput: "22.5,112.5",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Geohash",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
@@ -405,13 +405,309 @@ TestRegister.addTests([
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC SHA256",
|
||||
name: "HMAC: SHA256",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "52589bd80ccfa4acbb3f9512dfaf4f700fa5195008aae0b77a9e47dcca75beac",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": ["test", "SHA256"]
|
||||
"args": [{"option": "Latin1", "string": "test"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 1 SHA-224",
|
||||
input: "Hi There",
|
||||
expectedOutput: "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"}, "SHA224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 1 SHA-256",
|
||||
input: "Hi There",
|
||||
expectedOutput: "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 1 SHA-384",
|
||||
input: "Hi There",
|
||||
expectedOutput: "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"}, "SHA384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 1 SHA-512",
|
||||
input: "Hi There",
|
||||
expectedOutput: "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"}, "SHA512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 2 SHA-224",
|
||||
input: "what do ya want for nothing?",
|
||||
expectedOutput: "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "4a656665"}, "SHA224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 2 SHA-256",
|
||||
input: "what do ya want for nothing?",
|
||||
expectedOutput: "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "4a656665"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 2 SHA-384",
|
||||
input: "what do ya want for nothing?",
|
||||
expectedOutput: "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "4a656665"}, "SHA384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 2 SHA-512",
|
||||
input: "what do ya want for nothing?",
|
||||
expectedOutput: "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "4a656665"}, "SHA512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 3 SHA-224",
|
||||
input: "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
|
||||
expectedOutput: "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 3 SHA-256",
|
||||
input: "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
|
||||
expectedOutput: "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 3 SHA-384",
|
||||
input: "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
|
||||
expectedOutput: "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 3 SHA-512",
|
||||
input: "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
|
||||
expectedOutput: "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 4 SHA-224",
|
||||
input: "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
|
||||
expectedOutput: "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0102030405060708090a0b0c0d0e0f10111213141516171819"}, "SHA224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 4 SHA-256",
|
||||
input: "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
|
||||
expectedOutput: "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0102030405060708090a0b0c0d0e0f10111213141516171819"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 4 SHA-384",
|
||||
input: "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
|
||||
expectedOutput: "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0102030405060708090a0b0c0d0e0f10111213141516171819"}, "SHA384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 4 SHA-512",
|
||||
input: "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
|
||||
expectedOutput: "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0102030405060708090a0b0c0d0e0f10111213141516171819"}, "SHA512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 6 SHA-224",
|
||||
input: "Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
expectedOutput: "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 6 SHA-256",
|
||||
input: "Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
expectedOutput: "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 6 SHA-384",
|
||||
input: "Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
expectedOutput: "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 6 SHA-512",
|
||||
input: "Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
expectedOutput: "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 7 SHA-224",
|
||||
input: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
|
||||
expectedOutput: "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 7 SHA-256",
|
||||
input: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
|
||||
expectedOutput: "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 7 SHA-384",
|
||||
input: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
|
||||
expectedOutput: "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 7 SHA-512",
|
||||
input: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
|
||||
expectedOutput: "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
122
test/tests/operations/JSONBeautify.mjs
Normal file
122
test/tests/operations/JSONBeautify.mjs
Normal file
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* JSONBeautify tests.
|
||||
*
|
||||
* @author Phillip Nordwall [Phillip.Nordwall@gmail.com]
|
||||
*
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "JSON Beautify: space, ''",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: space, number",
|
||||
input: "42",
|
||||
expectedOutput: "42",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: space, string",
|
||||
input: "\"string\"",
|
||||
expectedOutput: "\"string\"",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: space, boolean",
|
||||
input: "false",
|
||||
expectedOutput: "false",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: space, emptyList",
|
||||
input: "[]",
|
||||
expectedOutput: "[]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: space, list",
|
||||
input: "[2,1]",
|
||||
expectedOutput: "[\n 2,\n 1\n]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: tab, list",
|
||||
input: "[2,1]",
|
||||
expectedOutput: "[\n\t2,\n\t1\n]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: ["\t", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: space, object",
|
||||
input: "{\"second\":2,\"first\":3}",
|
||||
expectedOutput: "{\n \"second\": 2,\n \"first\": 3\n}",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: tab, nested",
|
||||
input: "[2,{\"second\":2,\"first\":3,\"beginning\":{\"j\":\"3\",\"i\":[2,3,false]}},1,2,3]",
|
||||
expectedOutput: "[\n\t2,\n\t{\n\t\t\"second\": 2,\n\t\t\"first\": 3,\n\t\t\"beginning\": {\n\t\t\t\"j\": \"3\",\n\t\t\t\"i\": [\n\t\t\t\t2,\n\t\t\t\t3,\n\t\t\t\tfalse\n\t\t\t]\n\t\t}\n\t},\n\t1,\n\t2,\n\t3\n]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: ["\t", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: tab, nested, sorted",
|
||||
input: "[2,{\"second\":2,\"first\":3,\"beginning\":{\"j\":\"3\",\"i\":[2,3,false]}},1,2,3]",
|
||||
expectedOutput: "[\n\t2,\n\t{\n\t\t\"beginning\": {\n\t\t\t\"i\": [\n\t\t\t\t2,\n\t\t\t\t3,\n\t\t\t\tfalse\n\t\t\t],\n\t\t\t\"j\": \"3\"\n\t\t},\n\t\t\"first\": 3,\n\t\t\"second\": 2\n\t},\n\t1,\n\t2,\n\t3\n]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: ["\t", true],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
111
test/tests/operations/JSONMinify.mjs
Normal file
111
test/tests/operations/JSONMinify.mjs
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* JSONMinify tests.
|
||||
*
|
||||
* @author Phillip Nordwall [Phillip.Nordwall@gmail.com]
|
||||
*
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "JSON Minify: ''",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: number",
|
||||
input: "42",
|
||||
expectedOutput: "42",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: number",
|
||||
input: "4.2",
|
||||
expectedOutput: "4.2",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: string",
|
||||
input: "\"string\"",
|
||||
expectedOutput: "\"string\"",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: boolean",
|
||||
input: "false",
|
||||
expectedOutput: "false",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: emptyList",
|
||||
input: "[\n \n \t]",
|
||||
expectedOutput: "[]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: list",
|
||||
input: "[2,\n \t1]",
|
||||
expectedOutput: "[2,1]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: object",
|
||||
input: "{\n \"second\": 2,\n \"first\": 3\n}",
|
||||
expectedOutput: "{\"second\":2,\"first\":3}",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: tab, nested",
|
||||
input: "[\n\t2,\n\t{\n\t\t\"second\": 2,\n\t\t\"first\": 3,\n\t\t\"beginning\": {\n\t\t\t\"j\": \"3\",\n\t\t\t\"i\": [\n\t\t\t\t2,\n\t\t\t\t3,\n\t\t\t\tfalse\n\t\t\t]\n\t\t}\n\t},\n\t1,\n\t2,\n\t3\n]",
|
||||
expectedOutput: "[2,{\"second\":2,\"first\":3,\"beginning\":{\"j\":\"3\",\"i\":[2,3,false]}},1,2,3]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
51
test/tests/operations/JWTDecode.mjs
Normal file
51
test/tests/operations/JWTDecode.mjs
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* JWT Decode tests
|
||||
*
|
||||
* @author gchq77703 []
|
||||
*
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
const outputObject = JSON.stringify({
|
||||
String: "SomeString",
|
||||
Number: 42,
|
||||
iat: 1
|
||||
}, null, 4);
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "JWT Decode: HS",
|
||||
input: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJTdHJpbmciOiJTb21lU3RyaW5nIiwiTnVtYmVyIjo0MiwiaWF0IjoxfQ.0ha6-j4FwvEIKPVZ-hf3S_R9Hy_UtXzq4dnedXcUrXk",
|
||||
expectedOutput: outputObject,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Decode",
|
||||
args: [],
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JWT Decode: RS",
|
||||
input: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJTdHJpbmciOiJTb21lU3RyaW5nIiwiTnVtYmVyIjo0MiwiaWF0IjoxfQ.MjEJhtZk2nXzigi24piMzANmrj3mILHJcDl0xOjl5a8EgdKVL1oaMEjTkMQp5RA8YrqeRBFaX-BGGCKOXn5zPY1DJwWsBUyN9C-wGR2Qye0eogH_3b4M9EW00TPCUPXm2rx8URFj7Wg9VlsmrGzLV2oKkPgkVxuFSxnpO3yjn1Y",
|
||||
expectedOutput: outputObject,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Decode",
|
||||
args: [],
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JWT Decode: ES",
|
||||
input: "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJTdHJpbmciOiJTb21lU3RyaW5nIiwiTnVtYmVyIjo0MiwiaWF0IjoxfQ.WkECT51jSfpRkcpQ4x0h5Dwe7CFBI6u6Et2gWp91HC7mpN_qCFadRpsvJLtKubm6cJTLa68xtei0YrDD8fxIUA",
|
||||
expectedOutput: outputObject,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Decode",
|
||||
args: [],
|
||||
}
|
||||
],
|
||||
}
|
||||
]);
|
||||
163
test/tests/operations/JWTSign.mjs
Normal file
163
test/tests/operations/JWTSign.mjs
Normal file
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* JWT Sign tests
|
||||
*
|
||||
* @author gchq77703 []
|
||||
*
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
const inputObject = JSON.stringify({
|
||||
String: "SomeString",
|
||||
Number: 42,
|
||||
iat: 1
|
||||
}, null, 4);
|
||||
|
||||
const hsKey = "secret_cat";
|
||||
const rsKey = `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICWwIBAAKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw
|
||||
33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW
|
||||
+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB
|
||||
AoGAD+onAtVye4ic7VR7V50DF9bOnwRwNXrARcDhq9LWNRrRGElESYYTQ6EbatXS
|
||||
3MCyjjX2eMhu/aF5YhXBwkppwxg+EOmXeh+MzL7Zh284OuPbkglAaGhV9bb6/5Cp
|
||||
uGb1esyPbYW+Ty2PC0GSZfIXkXs76jXAu9TOBvD0ybc2YlkCQQDywg2R/7t3Q2OE
|
||||
2+yo382CLJdrlSLVROWKwb4tb2PjhY4XAwV8d1vy0RenxTB+K5Mu57uVSTHtrMK0
|
||||
GAtFr833AkEA6avx20OHo61Yela/4k5kQDtjEf1N0LfI+BcWZtxsS3jDM3i1Hp0K
|
||||
Su5rsCPb8acJo5RO26gGVrfAsDcIXKC+bQJAZZ2XIpsitLyPpuiMOvBbzPavd4gY
|
||||
6Z8KWrfYzJoI/Q9FuBo6rKwl4BFoToD7WIUS+hpkagwWiz+6zLoX1dbOZwJACmH5
|
||||
fSSjAkLRi54PKJ8TFUeOP15h9sQzydI8zJU+upvDEKZsZc/UhT/SySDOxQ4G/523
|
||||
Y0sz/OZtSWcol/UMgQJALesy++GdvoIDLfJX5GBQpuFgFenRiRDabxrE9MNUZ2aP
|
||||
FaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw==
|
||||
-----END RSA PRIVATE KEY-----`;
|
||||
const esKey = `-----BEGIN PRIVATE KEY-----
|
||||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgevZzL1gdAFr88hb2
|
||||
OF/2NxApJCzGCEDdfSp6VQO30hyhRANCAAQRWz+jn65BtOMvdyHKcvjBeBSDZH2r
|
||||
1RTwjmYSi9R/zpBnuQ4EiMnCqfMPWiZqB4QdbAd0E7oH50VpuZ1P087G
|
||||
-----END PRIVATE KEY-----`;
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "JWT Sign: HS256",
|
||||
input: inputObject,
|
||||
expectedOutput: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJTdHJpbmciOiJTb21lU3RyaW5nIiwiTnVtYmVyIjo0MiwiaWF0IjoxfQ.0ha6-j4FwvEIKPVZ-hf3S_R9Hy_UtXzq4dnedXcUrXk",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Sign",
|
||||
args: [hsKey, "HS256"],
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JWT Sign: HS384",
|
||||
input: inputObject,
|
||||
expectedOutput: "eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJTdHJpbmciOiJTb21lU3RyaW5nIiwiTnVtYmVyIjo0MiwiaWF0IjoxfQ._bPK-Y3mIACConbJqkGFMQ_L3vbxgKXy9gSxtL9hA5XTganozTSXxD0vX0N1yT5s",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Sign",
|
||||
args: [hsKey, "HS384"],
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JWT Sign: HS512",
|
||||
input: inputObject,
|
||||
expectedOutput: "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJTdHJpbmciOiJTb21lU3RyaW5nIiwiTnVtYmVyIjo0MiwiaWF0IjoxfQ.vZIJU4XYMFt3FLE1V_RZOxEetmV4RvxtPZQGzJthK_d47pjwlEb6pQE23YxHFmOj8H5RLEdqqLPw4jNsOyHRzA",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Sign",
|
||||
args: [hsKey, "HS512"],
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JWT Sign: ES256",
|
||||
input: inputObject,
|
||||
expectedOutput: inputObject,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Sign",
|
||||
args: [esKey, "ES256"],
|
||||
},
|
||||
{
|
||||
op: "JWT Decode",
|
||||
args: []
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JWT Sign: ES384",
|
||||
input: inputObject,
|
||||
expectedOutput: inputObject,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Sign",
|
||||
args: [esKey, "ES384"],
|
||||
},
|
||||
{
|
||||
op: "JWT Decode",
|
||||
args: []
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JWT Sign: ES512",
|
||||
input: inputObject,
|
||||
expectedOutput: inputObject,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Sign",
|
||||
args: [esKey, "ES512"],
|
||||
},
|
||||
{
|
||||
op: "JWT Decode",
|
||||
args: []
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JWT Sign: RS256",
|
||||
input: inputObject,
|
||||
expectedOutput: inputObject,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Sign",
|
||||
args: [rsKey, "RS256"],
|
||||
},
|
||||
{
|
||||
op: "JWT Decode",
|
||||
args: []
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JWT Sign: RS384",
|
||||
input: inputObject,
|
||||
expectedOutput: inputObject,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Sign",
|
||||
args: [rsKey, "RS384"],
|
||||
},
|
||||
{
|
||||
op: "JWT Decode",
|
||||
args: []
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JWT Sign: RS512",
|
||||
input: inputObject,
|
||||
expectedOutput: inputObject,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Sign",
|
||||
args: [esKey, "RS512"],
|
||||
},
|
||||
{
|
||||
op: "JWT Decode",
|
||||
args: []
|
||||
}
|
||||
],
|
||||
}
|
||||
]);
|
||||
75
test/tests/operations/JWTVerify.mjs
Normal file
75
test/tests/operations/JWTVerify.mjs
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* JWT Verify tests
|
||||
*
|
||||
* @author gchq77703 []
|
||||
*
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
const outputObject = JSON.stringify({
|
||||
String: "SomeString",
|
||||
Number: 42,
|
||||
iat: 1
|
||||
}, null, 4);
|
||||
|
||||
const invalidAlgorithm = "JsonWebTokenError: invalid algorithm";
|
||||
|
||||
const hsKey = "secret_cat";
|
||||
const rsKey = `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICWwIBAAKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw
|
||||
33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW
|
||||
+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB
|
||||
AoGAD+onAtVye4ic7VR7V50DF9bOnwRwNXrARcDhq9LWNRrRGElESYYTQ6EbatXS
|
||||
3MCyjjX2eMhu/aF5YhXBwkppwxg+EOmXeh+MzL7Zh284OuPbkglAaGhV9bb6/5Cp
|
||||
uGb1esyPbYW+Ty2PC0GSZfIXkXs76jXAu9TOBvD0ybc2YlkCQQDywg2R/7t3Q2OE
|
||||
2+yo382CLJdrlSLVROWKwb4tb2PjhY4XAwV8d1vy0RenxTB+K5Mu57uVSTHtrMK0
|
||||
GAtFr833AkEA6avx20OHo61Yela/4k5kQDtjEf1N0LfI+BcWZtxsS3jDM3i1Hp0K
|
||||
Su5rsCPb8acJo5RO26gGVrfAsDcIXKC+bQJAZZ2XIpsitLyPpuiMOvBbzPavd4gY
|
||||
6Z8KWrfYzJoI/Q9FuBo6rKwl4BFoToD7WIUS+hpkagwWiz+6zLoX1dbOZwJACmH5
|
||||
fSSjAkLRi54PKJ8TFUeOP15h9sQzydI8zJU+upvDEKZsZc/UhT/SySDOxQ4G/523
|
||||
Y0sz/OZtSWcol/UMgQJALesy++GdvoIDLfJX5GBQpuFgFenRiRDabxrE9MNUZ2aP
|
||||
FaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw==
|
||||
-----END RSA PRIVATE KEY-----`;
|
||||
const esKey = `-----BEGIN PRIVATE KEY-----
|
||||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgevZzL1gdAFr88hb2
|
||||
OF/2NxApJCzGCEDdfSp6VQO30hyhRANCAAQRWz+jn65BtOMvdyHKcvjBeBSDZH2r
|
||||
1RTwjmYSi9R/zpBnuQ4EiMnCqfMPWiZqB4QdbAd0E7oH50VpuZ1P087G
|
||||
-----END PRIVATE KEY-----`;
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "JWT Verify: HS",
|
||||
input: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJTdHJpbmciOiJTb21lU3RyaW5nIiwiTnVtYmVyIjo0MiwiaWF0IjoxfQ.0ha6-j4FwvEIKPVZ-hf3S_R9Hy_UtXzq4dnedXcUrXk",
|
||||
expectedOutput: outputObject,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Verify",
|
||||
args: [hsKey],
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JWT Verify: RS",
|
||||
input: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJTdHJpbmciOiJTb21lU3RyaW5nIiwiTnVtYmVyIjo0MiwiaWF0IjoxfQ.MjEJhtZk2nXzigi24piMzANmrj3mILHJcDl0xOjl5a8EgdKVL1oaMEjTkMQp5RA8YrqeRBFaX-BGGCKOXn5zPY1DJwWsBUyN9C-wGR2Qye0eogH_3b4M9EW00TPCUPXm2rx8URFj7Wg9VlsmrGzLV2oKkPgkVxuFSxnpO3yjn1Y",
|
||||
expectedOutput: invalidAlgorithm,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Verify",
|
||||
args: [rsKey],
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JWT Verify: ES",
|
||||
input: "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJTdHJpbmciOiJTb21lU3RyaW5nIiwiTnVtYmVyIjo0MiwiaWF0IjoxfQ.WkECT51jSfpRkcpQ4x0h5Dwe7CFBI6u6Et2gWp91HC7mpN_qCFadRpsvJLtKubm6cJTLa68xtei0YrDD8fxIUA",
|
||||
expectedOutput: invalidAlgorithm,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Verify",
|
||||
args: [esKey],
|
||||
}
|
||||
],
|
||||
}
|
||||
]);
|
||||
43
test/tests/operations/Media.mjs
Normal file
43
test/tests/operations/Media.mjs
Normal file
File diff suppressed because one or more lines are too long
132
test/tests/operations/ParseIPRange.mjs
Normal file
132
test/tests/operations/ParseIPRange.mjs
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* Parse IP Range tests.
|
||||
*
|
||||
* @author Klaxon [klaxon@veyr.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Parse IPv4 CIDR",
|
||||
input: "10.0.0.0/30",
|
||||
expectedOutput: "Network: 10.0.0.0\nCIDR: 30\nMask: 255.255.255.252\nRange: 10.0.0.0 - 10.0.0.3\nTotal addresses in range: 4\n\n10.0.0.0\n10.0.0.1\n10.0.0.2\n10.0.0.3",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse IP range",
|
||||
"args": [true, true, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Parse IPv4 hyphenated",
|
||||
input: "10.0.0.0 - 10.0.0.3",
|
||||
expectedOutput: "Minimum subnet required to hold this range:\n\tNetwork: 10.0.0.0\n\tCIDR: 30\n\tMask: 255.255.255.252\n\tSubnet range: 10.0.0.0 - 10.0.0.3\n\tTotal addresses in subnet: 4\n\nRange: 10.0.0.0 - 10.0.0.3\nTotal addresses in range: 4\n\n10.0.0.0\n10.0.0.1\n10.0.0.2\n10.0.0.3",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse IP range",
|
||||
"args": [true, true, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Parse IPv4 list",
|
||||
input: "10.0.0.8\n10.0.0.5/30\n10.0.0.1\n10.0.0.3",
|
||||
expectedOutput: "Minimum subnet required to hold this range:\n\tNetwork: 10.0.0.0\n\tCIDR: 28\n\tMask: 255.255.255.240\n\tSubnet range: 10.0.0.0 - 10.0.0.15\n\tTotal addresses in subnet: 16\n\nRange: 10.0.0.1 - 10.0.0.8\nTotal addresses in range: 8\n\n10.0.0.1\n10.0.0.2\n10.0.0.3\n10.0.0.4\n10.0.0.5\n10.0.0.6\n10.0.0.7\n10.0.0.8",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse IP range",
|
||||
"args": [true, true, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Parse IPv6 CIDR - full",
|
||||
input: "2404:6800:4001:0000:0000:0000:0000:0000/48",
|
||||
expectedOutput: "Network: 2404:6800:4001:0000:0000:0000:0000:0000\nShorthand: 2404:6800:4001::\nCIDR: 48\nMask: ffff:ffff:ffff:0000:0000:0000:0000:0000\nRange: 2404:6800:4001:0000:0000:0000:0000:0000 - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nTotal addresses in range: 1.2089258196146292e+24\n\n",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse IP range",
|
||||
"args": [true, true, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Parse IPv6 CIDR - collapsed",
|
||||
input: "2404:6800:4001::/48",
|
||||
expectedOutput: "Network: 2404:6800:4001:0000:0000:0000:0000:0000\nShorthand: 2404:6800:4001::\nCIDR: 48\nMask: ffff:ffff:ffff:0000:0000:0000:0000:0000\nRange: 2404:6800:4001:0000:0000:0000:0000:0000 - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nTotal addresses in range: 1.2089258196146292e+24\n\n",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse IP range",
|
||||
"args": [true, true, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Parse IPv6 hyphenated",
|
||||
input: "2404:6800:4001:: - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff",
|
||||
expectedOutput: "Range: 2404:6800:4001:0000:0000:0000:0000:0000 - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nShorthand range: 2404:6800:4001:: - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nTotal addresses in range: 1.2089258196146292e+24\n\n",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse IP range",
|
||||
"args": [true, true, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Parse IPv6 list",
|
||||
input: "2404:6800:4001:ffff:ffff:ffff:ffff:ffff\n2404:6800:4001::ffff\n2404:6800:4001:ffff:ffff::1111\n2404:6800:4001::/64",
|
||||
expectedOutput: "Range: 2404:6800:4001:0000:0000:0000:0000:0000 - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nShorthand range: 2404:6800:4001:: - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nTotal addresses in range: 1.2089258196146292e+24\n\n",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse IP range",
|
||||
"args": [true, true, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "IPv4 subnet out of range error",
|
||||
input: "10.1.1.1/34",
|
||||
expectedOutput: "IPv4 CIDR must be less than 32",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse IP range",
|
||||
"args": [true, true, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "invalid IPv4 address error",
|
||||
input: "444.1.1.1/30",
|
||||
expectedOutput: "Block out of range.",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse IP range",
|
||||
"args": [true, true, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "IPv6 subnet out of range error",
|
||||
input: "2404:6800:4001::/129",
|
||||
expectedOutput: "IPv6 CIDR must be less than 128",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse IP range",
|
||||
"args": [true, true, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "invalid IPv6 address error",
|
||||
input: "2404:6800:4001:/12",
|
||||
expectedOutput: "Invalid input.\n\nEnter either a CIDR range (e.g. 10.0.0.0/24) or a hyphenated range (e.g. 10.0.0.0 - 10.0.1.0). IPv6 also supported.",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse IP range",
|
||||
"args": [true, true, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
71
test/tests/operations/ParseQRCode.mjs
Normal file
71
test/tests/operations/ParseQRCode.mjs
Normal file
File diff suppressed because one or more lines are too long
56
test/tests/operations/ParseTLV.mjs
Normal file
56
test/tests/operations/ParseTLV.mjs
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Parse TLV tests.
|
||||
*
|
||||
* @author gchq77703 []
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Parse TLV: LengthValue",
|
||||
input: "\x05\x48\x6f\x75\x73\x65\x04\x72\x6f\x6f\x6d\x04\x64\x6f\x6f\x72",
|
||||
expectedOutput: JSON.stringify([{"length": 5, "value": [72, 111, 117, 115, 101]}, {"length": 4, "value": [114, 111, 111, 109]}, {"length": 4, "value": [100, 111, 111, 114]}], null, 4),
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse TLV",
|
||||
"args": [0, 1, false]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Parse TLV: LengthValue with BER",
|
||||
input: "\x05\x48\x6f\x75\x73\x65\x04\x72\x6f\x6f\x6d\x04\x64\x6f\x6f\x72",
|
||||
expectedOutput: JSON.stringify([{"length": 5, "value": [72, 111, 117, 115, 101]}, {"length": 4, "value": [114, 111, 111, 109]}, {"length": 4, "value": [100, 111, 111, 114]}], null, 4),
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse TLV",
|
||||
"args": [0, 4, true] // length value is patently wrong, should be ignored by BER.
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Parse TLV: KeyLengthValue",
|
||||
input: "\x04\x05\x48\x6f\x75\x73\x65\x05\x04\x72\x6f\x6f\x6d\x42\x04\x64\x6f\x6f\x72",
|
||||
expectedOutput: JSON.stringify([{"key": [4], "length": 5, "value": [72, 111, 117, 115, 101]}, {"key": [5], "length": 4, "value": [114, 111, 111, 109]}, {"key": [66], "length": 4, "value": [100, 111, 111, 114]}], null, 4),
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse TLV",
|
||||
"args": [1, 1, false]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Parse TLV: KeyLengthValue with BER",
|
||||
input: "\x04\x05\x48\x6f\x75\x73\x65\x05\x04\x72\x6f\x6f\x6d\x42\x04\x64\x6f\x6f\x72",
|
||||
expectedOutput: JSON.stringify([{"key": [4], "length": 5, "value": [72, 111, 117, 115, 101]}, {"key": [5], "length": 4, "value": [114, 111, 111, 109]}, {"key": [66], "length": 4, "value": [100, 111, 111, 114]}], null, 4),
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse TLV",
|
||||
"args": [1, 4, true] // length value is patently wrong, should be ignored by BER.
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
22
test/tests/operations/RemoveDiacritics.mjs
Normal file
22
test/tests/operations/RemoveDiacritics.mjs
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Remove Diacritics tests.
|
||||
*
|
||||
* @author Klaxon [klaxon@veyr.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Remove Diacritics",
|
||||
input: "\xe0, \xe8, \xec, \xf2, \xf9 \xc0, \xc8, \xcc, \xd2, \xd9\n\xe1, \xe9, \xed, \xf3, \xfa, \xfd \xc1, \xc9, \xcd, \xd3, \xda, \xdd\n\xe2, \xea, \xee, \xf4, \xfb \xc2, \xca, \xce, \xd4, \xdb\n\xe3, \xf1, \xf5 \xc3, \xd1, \xd5\n\xe4, \xeb, \xef, \xf6, \xfc, \xff \xc4, \xcb, \xcf, \xd6, \xdc, \u0178\n\xe5, \xc5",
|
||||
expectedOutput: "a, e, i, o, u A, E, I, O, U\na, e, i, o, u, y A, E, I, O, U, Y\na, e, i, o, u A, E, I, O, U\na, n, o A, N, O\na, e, i, o, u, y A, E, I, O, U, Y\na, A",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Remove Diacritics",
|
||||
"args": []
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
@@ -30,4 +30,15 @@ TestRegister.addTests([
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "SeqUtils - Hexadecimal sort",
|
||||
input: "06,08,0a,0d,0f,1,10,11,12,13,14,15,16,17,18,19,1a,1b,1c,1d,1e,1f,2,3,4,5,7,9,b,c,e",
|
||||
expectedOutput: "1,2,3,4,5,06,7,08,9,0a,b,c,0d,e,0f,10,11,12,13,14,15,16,17,18,19,1a,1b,1c,1d,1e,1f",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Sort",
|
||||
"args": ["Comma", false, "Numeric (hexadecimal)"]
|
||||
}
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
35
test/tests/operations/TextEncodingBruteForce.mjs
Normal file
35
test/tests/operations/TextEncodingBruteForce.mjs
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Text Encoding Brute Force tests.
|
||||
*
|
||||
* @author Cynser
|
||||
*
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Text Encoding Brute Force - Encode",
|
||||
input: "Булкі праз ляніва сабаку.",
|
||||
expectedMatch: /Windows-1251 Cyrillic \(1251\).{1,10}Булкі праз ляніва сабаку\./,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text Encoding Brute Force",
|
||||
args: ["Encode"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text Encoding Brute Force - Decode",
|
||||
input: "Áóëê³ ïðàç ëÿí³âà ñàáàêó.",
|
||||
expectedMatch: /Windows-1251 Cyrillic \(1251\).{1,10}Булкі праз ляніва сабаку\./,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text Encoding Brute Force",
|
||||
args: ["Decode"],
|
||||
},
|
||||
],
|
||||
}
|
||||
]);
|
||||
|
||||
55
test/tests/operations/ToGeohash.mjs
Normal file
55
test/tests/operations/ToGeohash.mjs
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* To Geohash tests
|
||||
*
|
||||
* @author gchq77703
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "To Geohash",
|
||||
input: "37.8324,112.5584",
|
||||
expectedOutput: "ww8p1r4t8",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Geohash",
|
||||
args: [9],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Geohash",
|
||||
input: "37.9324,-112.2584",
|
||||
expectedOutput: "9w8pv3ruj",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Geohash",
|
||||
args: [9],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Geohash",
|
||||
input: "37.8324,112.5584",
|
||||
expectedOutput: "ww8",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Geohash",
|
||||
args: [3],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Geohash",
|
||||
input: "37.9324,-112.2584",
|
||||
expectedOutput: "9w8pv3rujxy5b99",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Geohash",
|
||||
args: [15],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
@@ -1,5 +1,6 @@
|
||||
const webpack = require("webpack");
|
||||
const ExtractTextPlugin = require("extract-text-webpack-plugin");
|
||||
const path = require("path");
|
||||
|
||||
/**
|
||||
* Webpack configuration details for use with Grunt.
|
||||
@@ -30,6 +31,9 @@ const banner = `/**
|
||||
* limitations under the License.
|
||||
*/`;
|
||||
|
||||
const vendorCSS = new ExtractTextPlugin("vendor.css");
|
||||
const projectCSS = new ExtractTextPlugin("styles.css");
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
new webpack.ProvidePlugin({
|
||||
@@ -42,7 +46,11 @@ module.exports = {
|
||||
raw: true,
|
||||
entryOnly: true
|
||||
}),
|
||||
new ExtractTextPlugin("styles.css")
|
||||
new webpack.DefinePlugin({
|
||||
"process.browser": "true"
|
||||
}),
|
||||
vendorCSS,
|
||||
projectCSS
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
@@ -54,8 +62,13 @@ module.exports = {
|
||||
{
|
||||
test: /\.m?js$/,
|
||||
exclude: /node_modules\/(?!jsesc|crypto-api)/,
|
||||
options: {
|
||||
configFile: path.resolve(__dirname, "babel.config.js"),
|
||||
cacheDirectory: true,
|
||||
compact: false
|
||||
},
|
||||
type: "javascript/auto",
|
||||
loader: "babel-loader?compact=false"
|
||||
loader: "babel-loader"
|
||||
},
|
||||
{
|
||||
test: /forge.min.js$/,
|
||||
@@ -67,7 +80,7 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ExtractTextPlugin.extract({
|
||||
use: projectCSS.extract({
|
||||
use: [
|
||||
{ loader: "css-loader" },
|
||||
{ loader: "postcss-loader" },
|
||||
@@ -76,7 +89,7 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: ExtractTextPlugin.extract({
|
||||
use: vendorCSS.extract({
|
||||
use: [
|
||||
{ loader: "css-loader" },
|
||||
{ loader: "sass-loader" }
|
||||
@@ -113,7 +126,11 @@ module.exports = {
|
||||
chunks: false,
|
||||
modules: false,
|
||||
entrypoints: false,
|
||||
warningsFilter: [/source-map/, /dependency is an expression/],
|
||||
warningsFilter: [
|
||||
/source-map/,
|
||||
/dependency is an expression/,
|
||||
/export 'default'/
|
||||
],
|
||||
},
|
||||
node: {
|
||||
fs: "empty"
|
||||
|
||||
Reference in New Issue
Block a user