2
0
mirror of https://github.com/gchq/CyberChef synced 2025-12-05 23:53:27 +00:00

Compare commits

...

117 Commits

Author SHA1 Message Date
n1474335
520eaedd9a 8.9.0 2018-11-07 13:23:26 +00:00
n1474335
4c5e664ce0 Merge branch 'arnydo-add_url_defang' 2018-11-07 13:23:17 +00:00
n1474335
53c500eb1b Added various options to the 'Defang URL' operation. 2018-11-07 13:23:05 +00:00
n1474335
253346a201 Merge branch 'add_url_defang' of https://github.com/arnydo/CyberChef into arnydo-add_url_defang 2018-11-07 12:29:58 +00:00
n1474335
c5d82a76ab 8.8.8 2018-11-07 12:29:32 +00:00
n1474335
18a9dfffc7 Updated dependencies. Removed shim from HMAC op and postinstall js-to-mjs step due to CryptoAPI fixes. 2018-11-07 12:29:23 +00:00
n1474335
38838e4dca 8.8.7 2018-11-06 18:52:31 +00:00
n1474335
5c151d727b Merge branch 'bwhitn-bugfixes' 2018-11-06 18:52:17 +00:00
n1474335
2d5b157c91 Merge branch 'bugfixes' of https://github.com/bwhitn/CyberChef into bwhitn-bugfixes 2018-11-06 18:51:40 +00:00
n1474335
10d3d27a33 8.8.6 2018-11-05 12:48:29 +00:00
n1474335
1614442bd7 Fixed theming issues 2018-11-05 12:48:22 +00:00
bwhitn
a3c5b1e107 Simplified while loop in FromBase58 to match ToBase58 2018-10-28 18:37:00 -04:00
Brian Whitney
f4de4de8c1 Fixing the babel, scrypt, and base58 issues 2018-10-21 21:10:49 -04:00
arnydo
69033a7343 Add Defang URL 2018-10-16 15:03:29 -04:00
arnydo
5a22106731 Create DefangURL.mjs 2018-10-16 15:02:39 -04:00
d98762625
5155d0ed56 Merge branch 'qistoph-RegexTooltip' 2018-10-12 15:44:17 +01:00
Chris van Marle
9be674103f Tooltip regex matches #279
Tooltip shows offset and matched groups
2018-10-12 15:42:44 +01:00
d98762625
8f7bb3a7c9 Merge pull request #371 from OllieGeek/master
CSS label / register-list Aesthetics
2018-10-12 12:12:48 +01:00
n1474335
f957925aac 8.8.5 2018-10-12 10:51:01 +00:00
n1474335
1bf8d63d1a Merge branch 'Cynser-fix-wiki-urls' 2018-10-12 10:50:27 +00:00
n1474335
8875144307 Merge branch 'fix-wiki-urls' of https://github.com/Cynser/CyberChef into Cynser-fix-wiki-urls 2018-10-12 10:45:54 +00:00
n1474335
d5c01f387a 8.8.4 2018-10-12 10:43:01 +00:00
n1474335
32709cd60f Merge branch 'klaxon1-feature/improve-email-extract' 2018-10-12 10:42:21 +00:00
n1474335
aaf0a91975 Fixed populateOption overflows 2018-10-12 10:42:03 +00:00
n1474335
6cc6230b91 Merge branch 'feature/improve-email-extract' of https://github.com/klaxon1/CyberChef into klaxon1-feature/improve-email-extract 2018-10-12 10:34:00 +00:00
n1474335
dd630f20f8 8.8.3 2018-10-12 10:28:23 +00:00
n1474335
0c6efd95fa Modified bzip2 library export to use ES6 syntax. Fixes #382. 2018-10-12 10:28:15 +00:00
Cynser
98d861a639 Add check for Forensics Wiki URLs 2018-10-11 17:27:51 +01:00
Klaxon
e638fb69b5 fix comment 2018-10-11 20:52:12 +10:00
Klaxon
718a94b5e0 add tests for internationalized email addresses 2018-10-11 20:42:16 +10:00
Klaxon
3079059ce3 Update regex to support a wider variety of email addresses. 2018-10-11 18:25:05 +10:00
n1474335
d6c6981bc0 8.8.2 2018-10-10 15:49:11 +00:00
n1474335
8aeb7b60a7 Updated dependencies 2018-10-10 15:49:07 +00:00
n1474335
9197ac6510 8.8.1 2018-10-10 14:08:32 +00:00
n1474335
b67ad3073c Merge branch 'Cynser-csv-escape' 2018-10-10 14:08:20 +00:00
n1474335
4a4f37f888 Merge branch 'csv-escape' of https://github.com/Cynser/CyberChef into Cynser-csv-escape 2018-10-10 14:06:49 +00:00
n1474335
c55331f220 8.8.0 2018-10-10 13:59:37 +00:00
n1474335
757ec98554 Updated CHANGELOG 2018-10-10 13:59:28 +00:00
n1474335
14309f2069 Merge branch 'GCHQ77703-tlv' 2018-10-10 13:56:47 +00:00
n1474335
e6b89d571e Tidied up TLV operation and tests 2018-10-10 13:56:20 +00:00
Cynser
d957198fd6 Make the check for Wikipedia URLs slightly stricter 2018-10-07 22:52:08 +01:00
Cynser
903bd22999 Stop treating backslashes in CSV as escape character 2018-10-07 22:20:43 +01:00
Klaxon
ab4c9ef0d6 fix comment 2018-10-02 15:12:51 +10:00
Klaxon
a69063de9b add tests 2018-10-02 13:51:55 +10:00
Klaxon
62b76777c0 update regex to match more email address variations 2018-10-02 13:40:47 +10:00
OllieGeek
32a91bda0a CSS label / register-list Aesthetics
Occasionally depending on the page width and the operation used, the label.bmd-label-floating's wraps and covers the input - CSS to hide the wrap

On register-list, if the regex match is not a word and longer than the div, it'll over run - CSS of word-break: break-all
2018-09-24 22:56:38 +01:00
n1474335
a15af602e0 Merge branch 'tlv' of https://github.com/GCHQ77703/CyberChef into GCHQ77703-tlv 2018-08-31 15:12:54 +00:00
n1474335
ec9dfd2918 Updated NPM token 2018-08-31 14:08:18 +00:00
n1474335
016086ef4e 8.7.0 2018-08-31 14:00:29 +00:00
n1474335
2e5ea968ee Updated CHANGELOG 2018-08-31 14:00:24 +00:00
n1474335
5dde1c1c04 Merge branch 'GCHQ77703-jwt' 2018-08-31 13:58:33 +00:00
n1474335
be14d56eae Tidied up JWT operations 2018-08-31 13:58:06 +00:00
n1474335
100b097ace Merge branch 'jwt' of https://github.com/GCHQ77703/CyberChef into GCHQ77703-jwt 2018-08-31 12:20:37 +00:00
GCHQ 77703
3833c5f9fe Rename operation, add working tests, add info URL 2018-08-31 13:20:28 +01:00
n1474335
3470dd9f3b Merge branch 'GCHQ77703-alphabetical' 2018-08-31 11:41:43 +00:00
GCHQ 77703
c5e8649284 alphabetically sort tests 2018-08-29 22:48:47 +01:00
GCHQ 77703
a95f43aa4d Implement tests, fix options argument 2018-08-29 22:43:10 +01:00
n1474335
0420aa8edb Merge branch 'Sam-Dowling-patch-1' 2018-08-29 19:09:53 +00:00
n1474335
806b43dfec Merge branch 'patch-1' of https://github.com/Sam-Dowling/CyberChef into Sam-Dowling-patch-1 2018-08-29 19:09:19 +00:00
n1474335
98f4fe4c2b 8.6.2 2018-08-29 19:06:02 +00:00
n1474335
0d63b3cbae JSON output is now indented by default. Closes #350. 2018-08-29 19:05:58 +00:00
n1474335
7061c05f77 8.6.1 2018-08-29 18:58:01 +00:00
n1474335
9b9a182f9f Merge branch 'klaxon1-feature/improve-parse-ip-range' 2018-08-29 18:57:08 +00:00
n1474335
2d9e7fcc6d Added full stop to operation description 2018-08-29 18:56:50 +00:00
n1474335
56946a66aa Merge branch 'feature/improve-parse-ip-range' of https://github.com/klaxon1/CyberChef into klaxon1-feature/improve-parse-ip-range 2018-08-29 18:48:29 +00:00
n1474335
c9242e32fe Auto-generated configs and modules are now cleaned when starting a new dev or prod task 2018-08-29 18:21:46 +00:00
n1474335
22e8883934 8.6.0 2018-08-29 18:04:55 +00:00
n1474335
552a18d89a Updated CHANGELOG 2018-08-29 18:04:49 +00:00
n1474335
6b725e9114 Merge branch 'GCHQ77703-master' 2018-08-29 18:00:06 +00:00
n1474335
415beaa0b0 Tidied up Geohash operations 2018-08-29 17:59:48 +00:00
n1474335
e9fe227ed7 Merge branch 'master' of https://github.com/GCHQ77703/CyberChef into GCHQ77703-master 2018-08-29 17:48:23 +00:00
n1474335
c1be109592 8.5.1 2018-08-29 17:36:05 +00:00
n1474335
88e603bbf1 Merge branch 'PenguinGeorge-cascadexor-new' 2018-08-29 17:35:13 +00:00
n1474335
c7b2095bb4 Updated package-lock.json 2018-08-29 17:34:47 +00:00
n1474335
7396117d89 Merge branch 'cascadexor-new' of https://github.com/PenguinGeorge/CyberChef into PenguinGeorge-cascadexor-new 2018-08-29 17:31:59 +00:00
Sam Dowling
fd96bf345b Fixed typo
Fixed typo in operation description.
Wirlpool -> Whirlpool
2018-08-29 17:15:52 +01:00
Klaxon
2820660264 fix regex issues and ESlint errors and warnings
fix comment

fix ESlint errors and warnings

fix regex

add author
2018-08-28 23:07:53 +10:00
Klaxon
86145dbf67 add tests 2018-08-28 23:07:48 +10:00
Klaxon
135b17186e update description 2018-08-28 23:07:40 +10:00
Klaxon
ce494339ef add parse IPv6 list 2018-08-28 23:07:32 +10:00
Klaxon
dd5af7eb10 add parse IPv4 list 2018-08-28 23:07:04 +10:00
GCHQ 77703
3abe99078e Fix linting 2018-08-27 16:03:15 +01:00
GCHQ 77703
edbd540c68 Add Dysfunctional Test 2018-08-27 15:42:07 +01:00
GCHQ 77703
06d9302d96 Implement TLV / KLV 2018-08-27 14:57:24 +01:00
GCHQ 77703
032b4bed7f Add Length Value Decoder Operatoin 2018-08-27 01:17:06 +01:00
GCHQ 77703
8559f5c8ea Add JWT Verify, Decode and Sign 2018-08-26 23:16:13 +01:00
GCHQ 77703
91133172d5 Remove subdomain from Wikipedia 2018-08-26 18:51:52 +01:00
GCHQ 77703
001f3f30cd Remove multi-line operations 2018-08-26 18:06:02 +01:00
GCHQ 77703
a1b1059ad1 Revert package-lock.json changes 2018-08-26 17:39:33 +01:00
GCHQ 77703
69a0122fea Fix "From Geohash" test 2018-08-26 17:20:50 +01:00
GCHQ 77703
3d505b4248 Add ToGeohash and FromGeohash operations 2018-08-26 14:27:15 +01:00
George J
70d4e3394c Updated XOR to include Cascade scheme 2018-08-24 22:33:24 +01:00
n1474335
3905c01a0d 8.5.0 2018-08-24 01:07:56 +01:00
n1474335
2a49af1ec3 'To Braille' and 'From Braille' operations added. Closes #255 2018-08-24 01:07:51 +01:00
n1474335
3d4f54e8bc 8.4.3 2018-08-24 00:32:57 +01:00
n1474335
61f2f2d2e3 'Show Base64 offsets' operation show supports base64 input. Closes #276 2018-08-24 00:32:52 +01:00
n1474335
00058bd5c7 8.4.2 2018-08-23 23:24:05 +01:00
n1474335
383fe50fc9 Support for negative values in 'Drop bytes' and 'Take bytes'. Closes #266 2018-08-23 23:23:00 +01:00
n1474335
e4fdadc573 8.4.1 2018-08-23 22:56:46 +01:00
n1474335
032f8808ef Fixed typo in Z85 alphabet 2018-08-23 22:56:18 +01:00
n1474335
10cf0d13c2 8.4.0 2018-08-23 22:10:23 +01:00
n1474335
6c9fea97ef Updated CHANGELOG 2018-08-23 22:10:15 +01:00
n1474335
4c2d612bdd Merge branch 'PenguinGeorge-ascii85-new' 2018-08-23 22:05:44 +01:00
n1474335
8e9fece77d Tidied up Base85 ops 2018-08-23 22:05:31 +01:00
n1474335
c818370123 Merge branch 'ascii85-new' of https://github.com/PenguinGeorge/CyberChef into PenguinGeorge-ascii85-new 2018-08-23 21:46:41 +01:00
n1474335
bf2643802a 8.3.1 2018-08-23 21:42:04 +01:00
n1474335
1ad079fbd4 'Find/Replace', 'Filter' and 'Register' now used XRegExp 2018-08-23 21:41:57 +01:00
George J
2d9e8773f5 Updated Base85 operations for latest CyberChef version 2018-08-22 20:24:32 +01:00
n1474335
5aa13f2428 Changelog improved 2018-08-22 03:26:02 +01:00
n1474335
38f5fcde86 8.3.0 2018-08-21 19:29:51 +01:00
n1474335
f99ab87ca1 Merge branch 'artemisbot-features/messagepack' 2018-08-21 19:29:39 +01:00
n1474335
d3d230a76d Tweaked MessagePack operations 2018-08-21 19:29:19 +01:00
n1474335
e7c6a05e9f Merge branch 'features/messagepack' of https://github.com/artemisbot/CyberChef into artemisbot-features/messagepack 2018-08-21 19:22:10 +01:00
Matt C
36e16d9925 Fixed linting issues 2018-08-20 19:14:19 +01:00
Matt C
84eaaf4819 Tests now work
Also they'll work in the node API too now
2018-08-20 19:08:01 +01:00
Matt C
821dd9c48c Added messagepack tests but they don't work
and i'm too burnt out to figure out why
2018-08-20 00:20:04 +01:00
Matt C
0c06e64051 Added MessagePack operations 2018-08-09 11:09:28 +01:00
64 changed files with 4505 additions and 2093 deletions

View File

@@ -1,6 +1,6 @@
{
"presets": [
["env", {
["@babel/preset-env", {
"targets": {
"chrome": 40,
"firefox": 35,
@@ -8,7 +8,7 @@
"node": "6.5"
},
"modules": false,
"useBuiltIns": true
"useBuiltIns": "entry"
}]
],
"plugins": [

View File

@@ -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

View File

@@ -1,40 +1,67 @@
# Changelog
All notable changes to this project will be documented in this file.
All notable changes to CyberChef will be documented in this file.
### [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]
### [8.3.0] - 2018-08-21
- 'To MessagePack' and 'From MessagePack' operations added [@artemisbot] | [#338]
### [8.2.0] - 2018-08-21
- Added information links to most operations, accessible in the description popover @PenguinGeorge #298
- Information links added to most operations, accessible in the description popover [@PenguinGeorge] | [#298]
### [8.1.0] - 2018-08-19
- 'Dechunk HTTP response' operation added @sevzero #311
- 'Dechunk HTTP response' operation added [@sevzero] | [#311]
## [8.0.0] - 2018-08-05
- Codebase rewritten using [ES modules](https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/) and [classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) #284
- Operation architecture restructured to make adding new operations a lot simpler #284
- A script has been added to aid in the creation of new operations by running `npm run newop` @n1474335 #284
- 'Magic' operation added - [automated detection of encoded data](https://github.com/gchq/CyberChef/wiki/Automatic-detection-of-encoded-data-using-CyberChef-Magic) @n1474335 #239
- UI updated to use [Bootstrap Material Design](https://fezvrasta.github.io/bootstrap-material-design/) @n1474335 #248
- `JSON`, `File` and `List<File>` Dish types added @n1474335 #284
- `OperationError` type added for better handling of errors thrown by operations @d98762625 #296
- A `present()` method has been added, allowing operations to pass machine-friendly data to subsequent operations whilst presenting human-friendly data to the user @n1474335 #284
- Set operations added @d98762625 #281
- 'To Table' operation added @JustAnotherMark #294
- 'Haversine distance' operation added @Dachande663 #325
- Started keeping a changelog @n1474335
- Codebase rewritten using [ES modules](https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/) and [classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) [@n1474335] [@d98762625] [@artemisbot] [@picapi] | [#284]
- Operation architecture restructured to make adding new operations a lot simpler [@n1474335] | [#284]
- A script has been added to aid in the creation of new operations by running `npm run newop` [@n1474335] | [#284]
- 'Magic' operation added - [automated detection of encoded data](https://github.com/gchq/CyberChef/wiki/Automatic-detection-of-encoded-data-using-CyberChef-Magic) [@n1474335] | [#239]
- UI updated to use [Bootstrap Material Design](https://fezvrasta.github.io/bootstrap-material-design/) [@n1474335] | [#248]
- `JSON`, `File` and `List<File>` Dish types added [@n1474335] | [#284]
- `OperationError` type added for better handling of errors thrown by operations [@d98762625] | [#296]
- A `present()` method has been added, allowing operations to pass machine-friendly data to subsequent operations whilst presenting human-friendly data to the user [@n1474335] | [#284]
- Set operations added [@d98762625] | [#281]
- 'To Table' operation added [@JustAnotherMark] | [#294]
- 'Haversine distance' operation added [@Dachande663] | [#325]
- Started keeping a changelog [@n1474335]
## [7.0.0] - 2017-12-28
- Added support for loading, processing and downloading files up to 500MB @n1474335 #224
- Added support for loading, processing and downloading files up to 500MB [@n1474335] | [#224]
## [6.0.0] - 2017-09-19
- Added threading support, moving all recipe processing into a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) to increase performance and allow long-running operations to be cancelled @n1474335 #173
- Created modules so that operations relying on large libraries can be downloaded separately as required, reducing the initial loading time for the app @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 allowing 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
- Configured Webpack build process, Babel transpilation and ES6 imports and exports @n1474335 #95
- Webpack build process configured with Babel transpilation and ES6 imports and exports [@n1474335] | [#95]
## [4.0.0] - 2016-11-28
- Initial open source commit @n1474335
- Initial open source commit [@n1474335] | [b1d73a72](https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306)
[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
[8.1.0]: https://github.com/gchq/CyberChef/releases/tag/v8.1.0
[8.0.0]: https://github.com/gchq/CyberChef/releases/tag/v8.0.0
@@ -42,3 +69,34 @@ All notable changes to this project will be documented in this file.
[6.0.0]: https://github.com/gchq/CyberChef/releases/tag/v6.0.0
[5.0.0]: https://github.com/gchq/CyberChef/releases/tag/v5.0.0
[4.0.0]: https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306
[@n1474335]: https://github.com/n1474335
[@d98762625]: https://github.com/d98762625
[@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
[#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
[#281]: https://github.com/gchq/CyberChef/pull/281
[#284]: https://github.com/gchq/CyberChef/pull/284
[#294]: https://github.com/gchq/CyberChef/pull/294
[#296]: https://github.com/gchq/CyberChef/pull/296
[#298]: https://github.com/gchq/CyberChef/pull/298
[#311]: https://github.com/gchq/CyberChef/pull/311
[#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
[#394]: https://github.com/gchq/CyberChef/pull/394

View File

@@ -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",
@@ -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"
}
},
});

4161
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "8.2.0",
"version": "8.9.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,46 +76,49 @@
"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",
"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",
"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",
"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",
@@ -130,7 +132,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"
}
}

View File

@@ -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);

View File

@@ -555,8 +555,6 @@ class Utils {
if (renderNext) {
cell += b;
renderNext = false;
} else if (b === "\\") {
renderNext = true;
} else if (b === "\"" && !inString) {
inString = true;
} else if (b === "\"" && inString) {

View File

@@ -25,6 +25,8 @@
"From Base32",
"To Base58",
"From Base58",
"To Base85",
"From Base85",
"To Base",
"From Base",
"To BCD",
@@ -47,7 +49,12 @@
"Change IP format",
"Encode text",
"Decode text",
"Swap endianness"
"Swap endianness",
"To MessagePack",
"From MessagePack",
"To Braille",
"From Braille",
"Parse TLV"
]
},
{
@@ -83,6 +90,9 @@
"Derive EVP key",
"Bcrypt",
"Scrypt",
"JWT Sign",
"JWT Verify",
"JWT Decode",
"Pseudo-Random Number Generator"
]
},
@@ -149,7 +159,8 @@
"Change IP format",
"Group IP addresses",
"Encode NetBIOS Name",
"Decode NetBIOS Name"
"Decode NetBIOS Name",
"Defang URL"
]
},
{
@@ -283,7 +294,9 @@
"Adler-32 Checksum",
"CRC-16 Checksum",
"CRC-32 Checksum",
"TCP/IP Checksum"
"TCP/IP Checksum",
"To Geohash",
"From Geohash"
]
},
{
@@ -313,7 +326,9 @@
"To Camel case",
"To Kebab case",
"BSON serialise",
"BSON deserialise"
"BSON deserialise",
"To MessagePack",
"From MessagePack"
]
},
{

View File

@@ -81,6 +81,7 @@ export function fromBase64(data, alphabet="A-Za-z0-9+/=", returnType="string", r
return returnType === "string" ? "" : [];
}
alphabet = alphabet || "A-Za-z0-9+/=";
alphabet = Utils.expandAlphRange(alphabet).join("");
const output = [];

45
src/core/lib/Base85.mjs Normal file
View File

@@ -0,0 +1,45 @@
/**
* Base85 resources.
*
* @author PenguinGeorge [george@penguingeorge.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
/**
* Base85 alphabet options.
*/
export const ALPHABET_OPTIONS = [
{
name: "Standard",
value: "!-u",
},
{
name: "Z85 (ZeroMQ)",
value: "0-9a-zA-Z.\\-:+=^!/*?&<>()[]{}@%$#",
},
{
name: "IPv6",
value: "0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|~}",
}
];
/**
* Returns the name of the alphabet, when given the alphabet.
*
* @param {string} alphabet
* @returns {string}
*/
export function alphabetName(alphabet) {
alphabet = alphabet.replace("'", "&apos;");
alphabet = alphabet.replace("\"", "&quot;");
alphabet = alphabet.replace("\\", "&bsol;");
let name;
ALPHABET_OPTIONS.forEach(function(a) {
if (escape(alphabet) === escape(a.value)) name = a.name;
});
return name;
}

View File

@@ -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);

15
src/core/lib/Braille.mjs Normal file
View 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: "⠀⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿"
};

View File

@@ -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;

View File

@@ -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.";
/**

View 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;
}
}

View File

@@ -5,7 +5,7 @@
*/
import Operation from "../Operation";
import bzip2 from "../vendor/bzip2.js";
import bzip2 from "../vendor/bzip2";
import OperationError from "../errors/OperationError";
/**

View 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;

View File

@@ -5,7 +5,6 @@
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
/**
* Drop bytes operation
@@ -20,7 +19,7 @@ class DropBytes extends Operation {
this.name = "Drop bytes";
this.module = "Default";
this.description = "Cuts a slice of the specified number of bytes out of the data.";
this.description = "Cuts a slice of the specified number of bytes out of the data. Negative values are allowed.";
this.inputType = "ArrayBuffer";
this.outputType = "ArrayBuffer";
this.args = [
@@ -50,14 +49,25 @@ class DropBytes extends Operation {
* @throws {OperationError} if invalid input
*/
run(input, args) {
const start = args[0],
length = args[1],
applyToEachLine = args[2];
if (start < 0 || length < 0)
throw new OperationError("Error: Invalid value");
let start = args[0],
length = args[1];
const applyToEachLine = args[2];
if (!applyToEachLine) {
if (start < 0) { // Take from the end
start = input.byteLength + start;
}
if (length < 0) { // Flip start point
start = start + length;
if (start < 0) {
start = input.byteLength + start;
length = start - length;
} else {
length = -length;
}
}
const left = input.slice(0, start),
right = input.slice(start + length, input.byteLength);
const result = new Uint8Array(left.byteLength + right.byteLength);
@@ -82,10 +92,28 @@ class DropBytes extends Operation {
}
lines.push(line);
let output = [];
let output = [],
s = start,
l = length;
for (i = 0; i < lines.length; i++) {
output = output.concat(lines[i].slice(0, start).concat(lines[i].slice(start+length, lines[i].length)));
if (s < 0) { // Take from the end
s = lines[i].length + s;
}
if (l < 0) { // Flip start point
s = s + l;
if (s < 0) {
s = lines[i].length + s;
l = s - l;
} else {
l = -l;
}
}
output = output.concat(lines[i].slice(0, s).concat(lines[i].slice(s+l, lines[i].length)));
output.push(0x0a);
s = start;
l = length;
}
return new Uint8Array(output.slice(0, output.length-1)).buffer;
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -8,6 +8,7 @@ import Operation from "../Operation";
import Utils from "../Utils";
import {INPUT_DELIM_OPTIONS} from "../lib/Delim";
import OperationError from "../errors/OperationError";
import XRegExp from "xregexp";
/**
* Filter operation
@@ -21,7 +22,7 @@ class Filter extends Operation {
super();
this.name = "Filter";
this.module = "Default";
this.module = "Regex";
this.description = "Splits up the input using the specified delimiter and then filters each branch based on a regular expression.";
this.inputType = "string";
this.outputType = "string";
@@ -55,7 +56,7 @@ class Filter extends Operation {
let regex;
try {
regex = new RegExp(args[1]);
regex = new XRegExp(args[1]);
} catch (err) {
throw new OperationError(`Invalid regex. Details: ${err.message}`);
}

View File

@@ -6,6 +6,7 @@
import Operation from "../Operation";
import Utils from "../Utils";
import XRegExp from "xregexp";
/**
* Find / Replace operation
@@ -50,6 +51,11 @@ class FindReplace extends Operation {
"name": "Multiline matching",
"type": "boolean",
"value": true
},
{
"name": "Dot matches all",
"type": "boolean",
"value": false
}
];
}
@@ -60,16 +66,17 @@ class FindReplace extends Operation {
* @returns {string}
*/
run(input, args) {
const [{option: type}, replace, g, i, m] = args;
const [{option: type}, replace, g, i, m, s] = args;
let find = args[0].string,
modifiers = "";
if (g) modifiers += "g";
if (i) modifiers += "i";
if (m) modifiers += "m";
if (s) modifiers += "s";
if (type === "Regex") {
find = new RegExp(find, modifiers);
find = new XRegExp(find, modifiers);
return input.replace(find, replace);
}
@@ -77,7 +84,7 @@ class FindReplace extends Operation {
find = Utils.parseEscapedChars(find);
}
find = new RegExp(Utils.escapeRegex(find), modifiers);
find = new XRegExp(Utils.escapeRegex(find), modifiers);
return input.replace(find, replace);
}

View File

@@ -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();
}

View File

@@ -0,0 +1,105 @@
/**
* @author PenguinGeorge [george@penguingeorge.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Utils from "../Utils";
import {alphabetName, ALPHABET_OPTIONS} from "../lib/Base85";
/**
* From Base85 operation
*/
class FromBase85 extends Operation {
/**
* From Base85 constructor
*/
constructor() {
super();
this.name = "From Base85";
this.module = "Default";
this.description = "Base85 (also called Ascii85) is a notation for encoding arbitrary byte data. It is usually more efficient that Base64.<br><br>This operation decodes data from an ASCII string (with an alphabet of your choosing, presets included).<br><br>e.g. <code>BOu!rD]j7BEbo7</code> becomes <code>hello world</code><br><br>Base85 is commonly used in Adobe's PostScript and PDF file formats.";
this.infoURL = "https://wikipedia.org/wiki/Ascii85";
this.inputType = "string";
this.outputType = "byteArray";
this.args = [
{
name: "Alphabet",
type: "editableOption",
value: ALPHABET_OPTIONS
},
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {byteArray}
*/
run(input, args) {
const alphabet = Utils.expandAlphRange(args[0]).join(""),
encoding = alphabetName(alphabet),
result = [];
if (alphabet.length !== 85 ||
[].unique.call(alphabet).length !== 85) {
throw new OperationError("Alphabet must be of length 85");
}
if (input.length === 0) return [];
const matches = input.match(/<~(.+?)~>/);
if (matches !== null) input = matches[1];
let i = 0;
let block, blockBytes;
while (i < input.length) {
if (encoding === "Standard" && input[i] === "z") {
result.push(0, 0, 0, 0);
i++;
} else {
let digits = [];
digits = input
.substr(i, 5)
.split("")
.map((chr, idx) => {
const digit = alphabet.indexOf(chr);
if (digit < 0 || digit > 84) {
throw `Invalid character '${chr}' at index ${idx}`;
}
return digit;
});
block =
digits[0] * 52200625 +
digits[1] * 614125 +
(i + 2 < input.length ? digits[2] : 84) * 7225 +
(i + 3 < input.length ? digits[3] : 84) * 85 +
(i + 4 < input.length ? digits[4] : 84);
blockBytes = [
(block >> 24) & 0xff,
(block >> 16) & 0xff,
(block >> 8) & 0xff,
block & 0xff
];
if (input.length < i + 5) {
blockBytes.splice(input.length - (i + 5), 5);
}
result.push.apply(result, blockBytes);
i += 5;
}
}
return result;
}
}
export default FromBase85;

View 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;

View 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;

View File

@@ -0,0 +1,47 @@
/**
* @author Matt C [matt@artemisbot.uk]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import notepack from "notepack.io";
/**
* From MessagePack operation
*/
class FromMessagePack extends Operation {
/**
* FromMessagePack constructor
*/
constructor() {
super();
this.name = "From MessagePack";
this.module = "Code";
this.description = "Converts MessagePack encoded data to JSON. MessagePack is a computer data interchange format. It is a binary form for representing simple data structures like arrays and associative arrays.";
this.infoURL = "https://wikipedia.org/wiki/MessagePack";
this.inputType = "ArrayBuffer";
this.outputType = "JSON";
this.args = [];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {JSON}
*/
run(input, args) {
try {
const buf = Buffer.from(new Uint8Array(input));
return notepack.decode(buf);
} catch (err) {
throw new OperationError(`Could not decode MessagePack to JSON: ${err}`);
}
}
}
export default FromMessagePack;

View File

@@ -71,13 +71,6 @@ class HMAC extends Operation {
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);
mac.update(msg);
return CryptoApi.encoder.toHex(mac.finalize());

View 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;

View 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;

View 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;

View File

@@ -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.");
}

View 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;

View File

@@ -6,6 +6,7 @@
import Operation from "../Operation";
import Dish from "../Dish";
import XRegExp from "xregexp";
/**
* Register operation
@@ -20,7 +21,7 @@ class Register extends Operation {
this.name = "Register";
this.flowControl = true;
this.module = "Default";
this.module = "Regex";
this.description = "Extract data from the input and store it in registers which can then be passed into subsequent operations as arguments. Regular expression capture groups are used to select the data to extract.<br><br>To use registers in arguments, refer to them using the notation <code>$Rn</code> where n is the register number, starting at 0.<br><br>For example:<br>Input: <code>Test</code><br>Extractor: <code>(.*)</code><br>Argument: <code>$R0</code> becomes <code>Test</code><br><br>Registers can be escaped in arguments using a backslash. e.g. <code>\\$R0</code> would become <code>$R0</code> rather than <code>Test</code>.";
this.infoURL = "https://wikipedia.org/wiki/Regular_expression#Syntax";
this.inputType = "string";
@@ -40,6 +41,11 @@ class Register extends Operation {
"name": "Multiline matching",
"type": "boolean",
"value": false
},
{
"name": "Dot matches all",
"type": "boolean",
"value": false
}
];
}
@@ -53,13 +59,14 @@ class Register extends Operation {
*/
async run(state) {
const ings = state.opList[state.progress].ingValues;
const [extractorStr, i, m] = ings;
const [extractorStr, i, m, s] = ings;
let modifiers = "";
if (i) modifiers += "i";
if (m) modifiers += "m";
if (s) modifiers += "s";
const extractor = new RegExp(extractorStr, modifiers),
const extractor = new XRegExp(extractorStr, modifiers),
input = await state.dish.get(Dish.STRING),
registers = input.match(extractor);

View File

@@ -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;

View File

@@ -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],

View File

@@ -36,6 +36,11 @@ class ShowBase64Offsets extends Operation {
name: "Show variable chars and padding",
type: "boolean",
value: true
},
{
name: "Input format",
type: "option",
value: ["Raw", "Base64"]
}
];
}
@@ -46,7 +51,11 @@ class ShowBase64Offsets extends Operation {
* @returns {html}
*/
run(input, args) {
const [alphabet, showVariable] = args;
const [alphabet, showVariable, format] = args;
if (format === "Base64") {
input = fromBase64(Utils.byteArrayToUtf8(input), null, "byteArray");
}
let offset0 = toBase64(input, alphabet),
offset1 = toBase64([0].concat(input), alphabet),

View File

@@ -5,7 +5,6 @@
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
/**
* Take bytes operation
@@ -20,7 +19,7 @@ class TakeBytes extends Operation {
this.name = "Take bytes";
this.module = "Default";
this.description = "Takes a slice of the specified number of bytes from the data.";
this.description = "Takes a slice of the specified number of bytes from the data. Negative values are allowed.";
this.inputType = "ArrayBuffer";
this.outputType = "ArrayBuffer";
this.args = [
@@ -50,15 +49,27 @@ class TakeBytes extends Operation {
* @throws {OperationError} if invalid value
*/
run(input, args) {
const start = args[0],
length = args[1],
applyToEachLine = args[2];
let start = args[0],
length = args[1];
const applyToEachLine = args[2];
if (start < 0 || length < 0)
throw new OperationError("Error: Invalid value");
if (!applyToEachLine) {
if (start < 0) { // Take from the end
start = input.byteLength + start;
}
if (length < 0) { // Flip start point
start = start + length;
if (start < 0) {
start = input.byteLength + start;
length = start - length;
} else {
length = -length;
}
}
if (!applyToEachLine)
return input.slice(start, start+length);
}
// Split input into lines
const data = new Uint8Array(input);
@@ -77,9 +88,26 @@ class TakeBytes extends Operation {
lines.push(line);
let output = [];
let s = start,
l = length;
for (i = 0; i < lines.length; i++) {
output = output.concat(lines[i].slice(start, start+length));
if (s < 0) { // Take from the end
s = lines[i].length + s;
}
if (l < 0) { // Flip start point
s = s + l;
if (s < 0) {
s = lines[i].length + s;
l = s - l;
} else {
l = -l;
}
}
output = output.concat(lines[i].slice(s, s+l));
output.push(0x0a);
s = start;
l = length;
}
return new Uint8Array(output.slice(0, output.length-1)).buffer;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,93 @@
/**
* @author PenguinGeorge [george@penguingeorge.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Utils from "../Utils";
import {alphabetName, ALPHABET_OPTIONS} from "../lib/Base85";
/**
* To Base85 operation
*/
class ToBase85 extends Operation {
/**
* To Base85 constructor
*/
constructor() {
super();
this.name = "To Base85";
this.module = "Default";
this.description = "Base85 (also called Ascii85) is a notation for encoding arbitrary byte data. It is usually more efficient that Base64.<br><br>This operation encodes data in an ASCII string (with an alphabet of your choosing, presets included).<br><br>e.g. <code>hello world</code> becomes <code>BOu!rD]j7BEbo7</code><br><br>Base85 is commonly used in Adobe's PostScript and PDF file formats.<br><br><strong>Options</strong><br><u>Alphabet</u><ul><li>Standard - The standard alphabet, referred to as Ascii85</li><li>Z85 (ZeroMQ) - A string-safe variant of Base85, which avoids quote marks and backslash characters</li><li>IPv6 - A variant of Base85 suitable for encoding IPv6 addresses (RFC 1924)</li></ul><u>Include delimiter</u><br>Adds a '<~' and '~>' delimiter to the start and end of the data. This is standard for Adobe's implementation of Base85.";
this.infoURL = "https://wikipedia.org/wiki/Ascii85";
this.inputType = "byteArray";
this.outputType = "string";
this.args = [
{
name: "Alphabet",
type: "editableOption",
value: ALPHABET_OPTIONS
},
{
name: "Include delimeter",
type: "boolean",
value: false
}
];
}
/**
* @param {byteArray} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const alphabet = Utils.expandAlphRange(args[0]).join(""),
encoding = alphabetName(alphabet),
includeDelim = args[1];
let result = "";
if (alphabet.length !== 85 ||
[].unique.call(alphabet).length !== 85) {
throw new OperationError("Error: Alphabet must be of length 85");
}
if (input.length === 0) return "";
let block;
for (let i = 0; i < input.length; i += 4) {
block = (
((input[i]) << 24) +
((input[i + 1] || 0) << 16) +
((input[i + 2] || 0) << 8) +
((input[i + 3] || 0))
) >>> 0;
if (encoding !== "Standard" || block > 0) {
let digits = [];
for (let j = 0; j < 5; j++) {
digits.push(block % 85);
block = Math.floor(block / 85);
}
digits = digits.reverse();
if (input.length < i + 4) {
digits.splice(input.length - (i + 4), 4);
}
result += digits.map(digit => alphabet[digit]).join("");
} else {
result += (encoding === "Standard") ? "z" : null;
}
}
return includeDelim ? `<~${result}~>` : result;
}
}
export default ToBase85;

View 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;

View 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;

View File

@@ -0,0 +1,50 @@
/**
* @author Matt C [matt@artemisbot.uk]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError.mjs";
import notepack from "notepack.io";
/**
* To MessagePack operation
*/
class ToMessagePack extends Operation {
/**
* ToMessagePack constructor
*/
constructor() {
super();
this.name = "To MessagePack";
this.module = "Code";
this.description = "Converts JSON to MessagePack encoded byte buffer. MessagePack is a computer data interchange format. It is a binary form for representing simple data structures like arrays and associative arrays.";
this.infoURL = "https://wikipedia.org/wiki/MessagePack";
this.inputType = "JSON";
this.outputType = "ArrayBuffer";
this.args = [];
}
/**
* @param {JSON} input
* @param {Object[]} args
* @returns {ArrayBuffer}
*/
run(input, args) {
try {
if (ENVIRONMENT_IS_WORKER()) {
return notepack.encode(input);
} else {
return notepack.encode(input).buffer;
}
} catch (err) {
throw new OperationError(`Could not encode JSON to MessagePack: ${err}`);
}
}
}
export default ToMessagePack;

View File

@@ -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";

View File

@@ -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";
@@ -35,7 +35,7 @@ class XOR extends Operation {
{
"name": "Scheme",
"type": "option",
"value": ["Standard", "Input differential", "Output differential"]
"value": ["Standard", "Input differential", "Output differential", "Cascade"]
},
{
"name": "Null preserving",

View File

@@ -262,4 +262,4 @@ bzip2.decompress = function(bits, size, len){
return output;
}
module.exports = bzip2;
export default bzip2;

View File

@@ -67,6 +67,7 @@ class BackgroundWorkerWaiter {
log.debug("Background ChefWorker loaded");
break;
case "optionUpdate":
case "statusMessage":
// Ignore these messages
break;
default:

View File

@@ -154,7 +154,7 @@ class HTMLIngredient {
} else if ((m = this.value[i].name.match(/\[\/([a-z0-9 -()^]+)\]/i))) {
html += "</optgroup>";
} else {
html += `<option populate-value="${this.value[i].value}">${this.value[i].name}</option>`;
html += `<option populate-value='${this.value[i].value}'>${this.value[i].name}</option>`;
}
}
html += `</select>

View File

@@ -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;

View File

@@ -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 {

View File

@@ -24,46 +24,55 @@ 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/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/Comment";
import "./tests/operations/Compress";
import "./tests/operations/ConditionalJump";
import "./tests/operations/Crypt";
import "./tests/operations/DateTime";
import "./tests/operations/ExtractEmailAddresses";
import "./tests/operations/Fork";
import "./tests/operations/Jump";
import "./tests/operations/ConditionalJump";
import "./tests/operations/Register";
import "./tests/operations/Comment";
import "./tests/operations/FromGeohash.mjs";
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/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/PowerSet";
import "./tests/operations/Regex";
import "./tests/operations/Register";
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/ToGeohash.mjs";
import "./tests/operations/TranslateDateTimeFormat";
import "./tests/operations/Magic";
import "./tests/operations/ParseTLV";
let allTestsPassing = true;
const testStatusCounts = {
@@ -142,4 +151,3 @@ TestRegister.runTests()
process.exit(allTestsPassing ? 0 : 1);
});

View File

@@ -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",

View File

@@ -9,7 +9,7 @@
*/
import TestRegister from "../../TestRegister";
const JPATH_TEST_DATA = {
const JSON_TEST_DATA = {
"store": {
"book": [{
"category": "reference",
@@ -184,7 +184,7 @@ TestRegister.addTests([
},
{
name: "JPath Expression: Empty expression",
input: JSON.stringify(JPATH_TEST_DATA),
input: JSON.stringify(JSON_TEST_DATA),
expectedOutput: "Invalid JPath expression: we need a path",
recipeConfig: [
{
@@ -195,7 +195,7 @@ TestRegister.addTests([
},
{
name: "JPath Expression: Fetch of values from specific object",
input: JSON.stringify(JPATH_TEST_DATA),
input: JSON.stringify(JSON_TEST_DATA),
expectedOutput: [
"\"Nigel Rees\"",
"\"Evelyn Waugh\"",
@@ -211,7 +211,7 @@ TestRegister.addTests([
},
{
name: "JPath Expression: Fetch of all values with matching key",
input: JSON.stringify(JPATH_TEST_DATA),
input: JSON.stringify(JSON_TEST_DATA),
expectedOutput: [
"\"Sayings of the Century\"",
"\"Sword of Honour\"",
@@ -229,7 +229,7 @@ TestRegister.addTests([
},
{
name: "JPath Expression: All data in object",
input: JSON.stringify(JPATH_TEST_DATA),
input: JSON.stringify(JSON_TEST_DATA),
expectedOutput: [
"[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}]",
"{\"color\":\"red\",\"price\":19.95}",
@@ -244,7 +244,7 @@ TestRegister.addTests([
},
{
name: "JPath Expression: Last element in array",
input: JSON.stringify(JPATH_TEST_DATA),
input: JSON.stringify(JSON_TEST_DATA),
expectedOutput: "{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}",
recipeConfig: [
{
@@ -255,7 +255,7 @@ TestRegister.addTests([
},
{
name: "JPath Expression: First 2 elements in array",
input: JSON.stringify(JPATH_TEST_DATA),
input: JSON.stringify(JSON_TEST_DATA),
expectedOutput: [
"{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95}",
"{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99}"
@@ -269,7 +269,7 @@ TestRegister.addTests([
},
{
name: "JPath Expression: All elements in array with property",
input: JSON.stringify(JPATH_TEST_DATA),
input: JSON.stringify(JSON_TEST_DATA),
expectedOutput: [
"{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99}",
"{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}"
@@ -283,7 +283,7 @@ TestRegister.addTests([
},
{
name: "JPath Expression: All elements in array which meet condition",
input: JSON.stringify(JPATH_TEST_DATA),
input: JSON.stringify(JSON_TEST_DATA),
expectedOutput: [
"{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99}",
"{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99}",
@@ -298,7 +298,7 @@ TestRegister.addTests([
},
{
name: "JPath Expression: All elements in object",
input: JSON.stringify(JPATH_TEST_DATA),
input: JSON.stringify(JSON_TEST_DATA),
expectedOutput: [
"{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95}",
"{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99}"
@@ -331,5 +331,65 @@ TestRegister.addTests([
"args": ["/div/p[@class=\"a\"]", "\\n"]
}
]
},
{
name: "To MessagePack: no content",
input: "",
expectedError: true,
recipeConfig: [
{
"op": "To MessagePack",
"args": []
},
{
"op": "To Hex",
"args": ["Space"]
}
]
},
{
name: "From MessagePack: no content",
input: "",
expectedOutput: "Could not decode MessagePack to JSON: Error: Could not parse",
recipeConfig: [
{
"op": "From Hex",
"args": ["Space"]
},
{
"op": "From MessagePack",
"args": []
}
]
},
{
name: "To MessagePack: valid json",
input: JSON.stringify(JSON_TEST_DATA),
expectedOutput: "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",
recipeConfig: [
{
"op": "To MessagePack",
"args": []
},
{
"op": "To Hex",
"args": ["Space"]
}
]
},
{
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, null, 4),
recipeConfig: [
{
"op": "From Hex",
"args": ["Space"]
},
{
"op": "From MessagePack",
"args": []
}
]
}
]);

View 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]
},
],
},
]);

View 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: [],
},
],
},
]);

View 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: [],
}
],
}
]);

View 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: []
}
],
}
]);

View 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],
}
],
}
]);

View 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]
},
],
},
]);

View 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.
}
]
}
]);

View 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],
},
],
},
]);

View File

@@ -30,6 +30,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 +45,8 @@ module.exports = {
raw: true,
entryOnly: true
}),
new ExtractTextPlugin("styles.css")
vendorCSS,
projectCSS
],
resolve: {
alias: {
@@ -67,7 +71,7 @@ module.exports = {
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: projectCSS.extract({
use: [
{ loader: "css-loader" },
{ loader: "postcss-loader" },
@@ -76,7 +80,7 @@ module.exports = {
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
use: vendorCSS.extract({
use: [
{ loader: "css-loader" },
{ loader: "sass-loader" }
@@ -113,7 +117,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"