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

Compare commits

...

267 Commits

Author SHA1 Message Date
n1474335
8148c1a8a8 8.24.2 2019-02-11 18:45:27 +00:00
n1474335
ce61bcc078 Merge branch 'd98762625-dynamic-import' 2019-02-11 18:45:00 +00:00
n1474335
49e2b05a11 Dynamic module loading is now cached and Webpack includes the import in the main chunk. 2019-02-11 18:44:41 +00:00
d98762625
481f2a4717 Merge branch 'master' of github.com:gchq/CyberChef into dynamic-import 2019-02-11 16:54:31 +00:00
d98762625
c01c076561 try/catch to allow chef to run from prod file 2019-02-11 16:51:23 +00:00
d98762625
2391e08ac1 tidy up 2019-02-11 15:47:28 +00:00
d98762625
a7a2fe243a prod working with mini css webpack plugin 2019-02-11 15:40:18 +00:00
n1474335
b5c655dd70 8.24.1 2019-02-11 14:48:45 +00:00
n1474335
d84a61d108 Merge branch 'j433866-open-file-button' 2019-02-11 14:48:38 +00:00
n1474335
13abbd2c5d Abstracted out loadFile logic to separate function 2019-02-11 14:48:25 +00:00
d98762625
d22eac9f35 WIP getting prod working with minicss webpack plugin 2019-02-11 14:29:29 +00:00
n1474335
d71aa8d7e2 Merge branch 'open-file-button' of https://github.com/j433866/CyberChef into j433866-open-file-button 2019-02-11 14:28:32 +00:00
n1474335
7a4e0301d2 8.24.0 2019-02-08 18:07:10 +00:00
n1474335
42826e542d Updated changelog 2019-02-08 18:07:03 +00:00
n1474335
42d1c9403c Merge branch 'h345983745-dnsoverhttps' 2019-02-08 18:02:39 +00:00
n1474335
ab43635583 Tidied up 'DNS over HTTPS' operation and fixed manualBake flag. 2019-02-08 18:02:13 +00:00
n1474335
b8ecd83bfd Merge branch 'dnsoverhttps' of https://github.com/h345983745/CyberChef into h345983745-dnsoverhttps 2019-02-08 17:34:33 +00:00
n1474335
0db0ced1ab 8.23.4 2019-02-08 17:28:16 +00:00
n1474335
3d20833d42 Fixed populateOption HTML escape bug. Closes #490 2019-02-08 17:28:10 +00:00
n1474335
7d09ba5669 8.23.3 2019-02-08 17:06:42 +00:00
n1474335
310ff30278 Merge branch 'j433866-xss_fixes' 2019-02-08 17:06:32 +00:00
n1474335
821bc9405c Merge branch 'xss_fixes' of https://github.com/j433866/CyberChef into j433866-xss_fixes 2019-02-08 17:05:51 +00:00
n1474335
d54d66cffc 8.23.2 2019-02-08 16:54:11 +00:00
n1474335
d2b4c40357 Fixed BigNumber/XRegExp incompatibility. CLoses #481 2019-02-08 16:54:04 +00:00
n1474335
f48af97ddc 8.23.1 2019-02-08 15:53:42 +00:00
n1474335
f1264d6310 Update package-lock.json 2019-02-08 15:53:40 +00:00
n1474335
4dc5a1499a Merge branch 'j433866-coords-fix' 2019-02-08 15:52:40 +00:00
d98762625
58a8af20a6 Highligting for Recipe now working. Discovered bug when highlighting on a test case 2019-02-08 14:28:53 +00:00
h345983745
75a58f465c Removed jpath import 2019-02-07 21:05:07 +00:00
h345983745
613cbaa556 Fixing Formating Issues 2019-02-07 08:28:23 +00:00
h345983745
0d0a634255 Added More Request Types 2019-02-06 23:27:27 +00:00
h345983745
105090db60 Spelling Check 2019-02-06 22:50:46 +00:00
h345983745
3e9c75f735 Added to Categories 2019-02-06 22:34:43 +00:00
h345983745
d42075072b Small Updates 2019-02-06 20:54:06 +00:00
h345983745
6a099f0813 Inital Commit 2019-02-06 20:20:20 +00:00
d98762625
9af5e40071 update linting to allow dybnamic import. Recipe highlight still broken 2019-02-01 14:05:48 +00:00
d98762625
4bf2a29070 WIP: bundle all css into main.css with mini-css-extract. Cannot split into vendor and styles without breaking at the moment. 2019-02-01 13:45:47 +00:00
d98762625
069d0e48c1 WIP: use mini-css-extract-plugin instead of extract-text, to work with dynamic import. Currently outputting only one css and recipe highlight doesnt work 2019-02-01 12:00:45 +00:00
d98762625
c8cb2692dd WIP: Recipe refactored to use dynamic import 2019-02-01 10:52:21 +00:00
j433866
74a22bcf9c Swap ordering of truncating and escaping 2019-01-31 15:22:25 +00:00
j433866
8b44927cb6 Fix XSS for To Table operation and Magic button 2019-01-31 15:18:37 +00:00
j433866
3209c94622 Fix conversion breaking when compass directions are used as delimiters 2019-01-21 12:50:30 +00:00
n1474335
6f8a5ea1be Merge branch 'j433866-coordinates' 2019-01-18 17:14:39 +00:00
n1474335
69837837b0 Tidied up co-ordinate operation 2019-01-18 17:14:25 +00:00
n1474335
03d8bf2836 Merge branch 'coordinates' of https://github.com/j433866/CyberChef into j433866-coordinates 2019-01-18 16:05:44 +00:00
n1474335
eca2c142f3 8.23.0 2019-01-18 15:37:42 +00:00
n1474335
715f7bbbc2 Lint 2019-01-18 15:37:25 +00:00
n1474335
291ebd5c12 Merge branch 'artemisbot-features/yara' 2019-01-18 15:35:14 +00:00
n1474335
ba04cac7ac Tidied up YARA operation 2019-01-18 15:34:56 +00:00
j433866
acb8c0b5af Change icon from folder to input 2019-01-18 15:12:03 +00:00
j433866
0c14bacea7 Add button to input to allow opening of files using the file prompt. 2019-01-18 15:07:19 +00:00
n1474335
4cabb849f3 Merge branch 'features/yara' of https://github.com/artemisbot/CyberChef into artemisbot-features/yara 2019-01-18 14:56:26 +00:00
n1474335
445a85798b 8.22.1 2019-01-18 14:50:00 +00:00
n1474335
55775f48e9 Merge branch 'picapi-b64-description-fix' 2019-01-18 14:49:53 +00:00
j433866
4bd923dc06 Improved handling of negative numbers and weirder inputs.
Negative numbers shouldn't make it go weird any more.
Automatic detection of input formats should be more reliable.
2019-01-17 13:53:42 +00:00
j433866
439654ed7f Add tests for new co-ordinate conversion module.
Removed To/From geohash tests
2019-01-17 13:49:36 +00:00
j433866
69797e58cb Add better error handling.
Also now doesn't do anything if there's no input
2019-01-16 16:57:58 +00:00
Matt
d1961ca3fa Marginally reduced size of libyara-wasm 2019-01-16 01:15:51 +00:00
Matt
2e9b1e079c Merge remote-tracking branch 'upstream/master' into features/yara 2019-01-15 23:46:49 +00:00
Matt
3dfaaf4c25 Update libyara for test pass 2019-01-15 23:45:40 +00:00
Matt
fcc39a0397 Added File upload support to textarea 2019-01-15 23:42:05 +00:00
Matt
0602f457ce Added initial tests & counts support 2019-01-15 16:24:29 +00:00
j433866
d00b0f4c0e Basically rewrote the whole thing using the new geodesy module 2019-01-15 15:55:49 +00:00
j433866
5e68959c03 Catch when OS grid references aren't calculated 2019-01-15 10:25:49 +00:00
j433866
ad4451a757 Rewrite MGRS to use new Geodesy module.
Added Ordnance Survey grid reference support
2019-01-15 10:13:11 +00:00
Callum Fraser
4d8127a7d9 Modified description of ToBase64 operation
Addresses #472
2019-01-14 22:25:49 +00:00
j433866
ee360521bb Remove MGRS npm module 2019-01-14 16:41:06 +00:00
j433866
04b0b8c723 Tidy up code 2019-01-14 14:58:41 +00:00
j433866
b3ac8d0835 Removed some debug logging 2019-01-14 13:49:49 +00:00
j433866
1a88a0164c Fix delimiter breaking Geohash detection 2019-01-14 13:00:14 +00:00
j433866
8b77ad7748 Stop delimiters breaking MGRS conversion 2019-01-14 12:49:28 +00:00
j433866
8d1f668fc5 Remove old Geohash modules 2019-01-14 11:56:27 +00:00
j433866
68fbbb64db Add new Convert co-ordinate format module.
Also added autodetect of co-ordinate format / delimiter
2019-01-14 11:49:57 +00:00
Matt
8bba4b2973 More speedrun stats (literally 10x faster) 2019-01-12 00:20:25 +00:00
j433866
abdd70c6fa Add ConvertCoordinates to lib folder 2019-01-11 11:59:13 +00:00
n1474335
9787ab04cd 8.22.0 2019-01-10 15:44:02 +00:00
n1474335
79d3c90026 Merge branch 'j433866-subsection' 2019-01-10 15:43:05 +00:00
n1474335
c2068b343b Tidied up and added global matching to Subsection operation 2019-01-10 15:42:48 +00:00
j433866
9e63e40dab Add new MGRS module and update webpack-dev-server 2019-01-10 15:24:29 +00:00
n1474335
6424839731 Merge branch 'subsection' of https://github.com/j433866/CyberChef into j433866-subsection 2019-01-10 15:11:34 +00:00
n1474335
863a525625 8.21.0 2019-01-10 15:02:26 +00:00
n1474335
f82a727e24 Merge branch 'masq-insense' 2019-01-10 15:01:22 +00:00
n1474335
995fcab071 Tidied up Case Insensitive Regex ops 2019-01-10 15:01:01 +00:00
n1474335
c5270d75a1 Merge branch 'insense' of https://github.com/masq/CyberChef into masq-insense 2019-01-10 14:53:21 +00:00
n1474335
324c409ff1 8.20.0 2019-01-09 16:38:53 +00:00
n1474335
1db8e6dddc Merge branch 'klaxon1-feature/lorem-ipsum-generator' 2019-01-09 16:38:46 +00:00
n1474335
c49a770c59 Tidied up Lorem Ipsum op 2019-01-09 16:36:34 +00:00
Matt
dd9ba4d250 Fixed problems flagged by n's review 2019-01-09 15:28:50 +00:00
n1474335
0e601d5b5f Merge branch 'feature/lorem-ipsum-generator' of https://github.com/klaxon1/CyberChef into klaxon1-feature/lorem-ipsum-generator 2019-01-09 14:50:48 +00:00
Matt
ebb632e888 Added metadata, string identifiers and operation args 2019-01-09 14:29:14 +00:00
Matt
4db2335107 Speedrunning strats (increased speed on big files) 2019-01-09 11:45:11 +00:00
Matt
26a2fb6662 Increased size of rule inp & expanded memory for wasm 2019-01-09 09:56:55 +00:00
Matt
4c1521a98e No data matches & warnings support 2019-01-08 23:26:14 +00:00
Matt
df8abb099c Added code argtype 2019-01-08 22:23:14 +00:00
n1474335
fe1332f18e 8.19.7 2019-01-08 18:29:14 +00:00
n1474335
cb9ab7a2c9 Fixed 'Maximise output' button functionality 2019-01-08 18:29:07 +00:00
n1474335
3a6b2875d5 8.19.6 2019-01-08 17:51:47 +00:00
n1474335
766de7e6fa Fixed bug in 'Regular expression' operation when highlighting lookaheads 2019-01-08 17:51:43 +00:00
Matt
13439e100e Merge remote-tracking branch 'upstream/master' into features/yara 2019-01-08 16:28:14 +00:00
Matt
5ac469b174 Added yara rule support 2019-01-08 16:19:58 +00:00
j433866
8ac5b48493 Update operation description 2019-01-08 11:51:33 +00:00
j433866
1a827ef44f Add Subsection to Flow Control category 2019-01-08 11:17:06 +00:00
j433866
0f0e346a02 Add new Subsection operation 2019-01-08 11:12:02 +00:00
n1474335
c82971f8db 8.19.5 2019-01-01 20:49:24 +00:00
n1474335
cb2c376c63 Increasing Node memory limit from 1G to 2G 2019-01-01 20:27:38 +00:00
n1474335
bc00fa0694 8.19.4 2019-01-01 20:15:29 +00:00
n1474335
c86007da71 Removed increase-memory-limit plugin in favour of NODE_OPTIONS environment variable. 2019-01-01 20:15:16 +00:00
n1474335
1bf513ca74 8.19.3 2019-01-01 19:56:20 +00:00
n1474335
29411c903f Added increase-memory-limit plugin to TravisCI build process to reduce 'JavaScript heap out of memory' errors. 2019-01-01 19:56:12 +00:00
n1474335
017dde364c 8.19.2 2019-01-01 19:22:10 +00:00
n1474335
c123d7370a Merge branch 'edwardwall-patch-2' 2019-01-01 19:21:11 +00:00
n1474335
76f1e5e8f3 Merge branch 'patch-2' of https://github.com/edwardwall/CyberChef into edwardwall-patch-2 2019-01-01 19:20:07 +00:00
n1474335
4e466c7886 8.19.1 2019-01-01 19:19:16 +00:00
n1474335
d469fb9c58 Updated dependencies 2019-01-01 19:19:07 +00:00
Edward Wall
050ab03448 Simplify to improve readability 2018-12-30 17:06:48 +00:00
Edward Wall
40acf751a8 Update to understand Generalized / UTC Time
Future proofing for when certificates with dates after 2049 begin being issued.
These certificates' dates will be in Generalized Time not UTC Time as per RFC 5280
2018-12-30 16:46:18 +00:00
Spencer Walden
126ad585c0 Registers tests for 'To/From Case Insensitive Regex' operations 2018-12-30 03:26:44 -08:00
Spencer Walden
1d04b649e0 Adds 'To/From Case Insensitive Regex' operations under 'Utils' 2018-12-30 03:26:44 -08:00
Spencer Walden
b750006cf0 Adds tests for 'To/From Case Insensitive Regex' operations 2018-12-30 03:26:44 -08:00
Spencer Walden
3c16b839b6 Adds 'From Case Insensitive Regex' operation 2018-12-30 03:26:44 -08:00
Spencer Walden
32aea6b86c Adds 'To Case Insensitive Regex' operation 2018-12-30 03:26:44 -08:00
Edward Wall
688c2d0df5 Update ParseX509Certificate.mjs 2018-12-30 03:15:07 +00:00
n1474335
0cea56dc62 8.19.0 2018-12-30 01:07:54 +00:00
n1474335
bb44268c30 Merge branch 'feature-browser-testsuite' 2018-12-30 01:07:42 +00:00
n1474335
19b3dcf1c2 Updated CHANGELOG 2018-12-30 01:07:26 +00:00
n1474335
71e0a4e0ce Increased UI test timeouts 2018-12-30 00:47:10 +00:00
n1474335
7f2e879e24 Added explicit bake after input added in test suite. 2018-12-30 00:37:44 +00:00
n1474335
840e44deac Tidied up UI tests 2018-12-30 00:26:28 +00:00
n1474335
f7707faece Added Chrome to TravisCI config 2018-12-30 00:02:41 +00:00
n1474335
b631e3fef6 Added nightwatch tests to TravisCI build process for prod and inline versions. 2018-12-29 23:46:13 +00:00
n1474335
b0fb9db4b8 Added nightwatch.js test suite for confirming that the app loads correctly and can run operations from each module. Currently only support the latest version of Chrome. 2018-12-29 02:58:05 +00:00
n1474335
c7e9115994 Restructured tests directory 2018-12-28 21:49:40 +00:00
Klaxon
f2d115ee4d add lorem ipsum generator 2018-12-29 00:44:59 +10:00
n1474335
a1b161493c 8.18.1 2018-12-26 16:50:36 +00:00
n1474335
5acee80463 'editableOption's are now full width. 'editableOptionShort' type added to replace the old style. 2018-12-26 16:50:32 +00:00
n1474335
e6932401ad 8.18.0 2018-12-26 16:35:34 +00:00
n1474335
7a4eff0f5c Merge branch 'artemisbot-features/colour-channel' 2018-12-26 16:33:26 +00:00
n1474335
8b533e9893 Tidied up 'Split Colour Channels' operation and added 'Multimedia' category 2018-12-26 16:33:10 +00:00
n1474335
02b92c7977 Merge branch 'features/colour-channel' of https://github.com/artemisbot/CyberChef into artemisbot-features/colour-channel 2018-12-26 16:10:44 +00:00
n1474335
e386863bdb 8.17.2 2018-12-26 00:39:38 +00:00
n1474335
16be7cb28a Fixed grunt-webpack circular reference issue 2018-12-26 00:39:30 +00:00
n1474335
f6d97c19d9 8.17.1 2018-12-26 00:01:21 +00:00
n1474335
8fef01d961 Fixed bundle analyzer filepath 2018-12-26 00:01:12 +00:00
n1474335
43dcd544f2 Added webpack-bundle-analyzer to production build. Refactored some modules to improve performance. Removed moment-timezone from Utils to drastically reduce module size. 2018-12-25 23:58:00 +00:00
n1474335
b29bb6fdd7 Added 'DishError' and refined test results. 2018-12-25 22:38:53 +00:00
n1474335
d2325306db 8.17.0 2018-12-25 21:55:51 +00:00
n1474335
dfe31980b7 Merge branch 'j433866-qrcodes' 2018-12-25 21:55:35 +00:00
n1474335
9734b78aeb Tidied up QR code operations 2018-12-25 21:54:38 +00:00
n1474335
4ee0800990 Merge branch 'qrcodes' of https://github.com/j433866/CyberChef into j433866-qrcodes 2018-12-25 19:07:59 +00:00
n1474335
387008bd9c 8.16.1 2018-12-25 19:02:13 +00:00
n1474335
bf24547202 The 'option' and 'editableOption' arguments can now specify a 'defaultIndex' to populate, instead of using the first in the provided list. 2018-12-25 19:02:05 +00:00
Matt C
454ef0076b Disabled tests 2018-12-21 17:19:33 +00:00
Matt C
18693d2471 Add tests, however non-functional due to lack of File in Node
Also add jimp to package.json
2018-12-21 17:17:11 +00:00
Matt C
5a9583c970 Add to categories 2018-12-21 17:15:30 +00:00
Matt C
0046f7e3d7 Added colour channel splitting support 2018-12-21 17:08:09 +00:00
j433866
c2f6b8df66 Add tests for Parse QR Code module 2018-12-21 11:26:03 +00:00
j433866
d0e428b728 Improve image normalising 2018-12-21 11:24:31 +00:00
j433866
ae5128a33a Always generate a PNG if the format isn't SVG 2018-12-21 11:23:51 +00:00
j433866
ed25017e2d Add process.browser to webpack config, so we don't include stuff we don't need 2018-12-20 14:46:24 +00:00
j433866
e5b2b84073 Add new ParseQRCode operation 2018-12-20 14:45:23 +00:00
j433866
1953d9a4c8 Add Jimp and jsqr modules 2018-12-20 14:42:32 +00:00
j433866
b3113c109b Change module to Image, change default format value to PNG 2018-12-20 14:42:12 +00:00
n1474335
8c3569ea63 8.16.0 2018-12-19 17:59:55 +00:00
n1474335
ae28d476de Merge branch 'anthony-arnold-play-media' 2018-12-19 17:58:51 +00:00
n1474335
01c4cfdc8d Tidied up 'Play Media' operation 2018-12-19 17:58:38 +00:00
n1474335
8c6c3a1c01 Merge branch 'play-media' of https://github.com/anthony-arnold/CyberChef into anthony-arnold-play-media 2018-12-19 17:39:07 +00:00
n1474335
f367c1f78b 8.15.1 2018-12-19 17:25:05 +00:00
n1474335
13d87d397d Merge branch 'j433866-master' 2018-12-19 17:24:52 +00:00
n1474335
ed2c886359 Magic crib now only applies after all branches have been explored. 2018-12-19 17:24:38 +00:00
n1474335
6337e84708 Merge branch 'master' of https://github.com/j433866/CyberChef into j433866-master 2018-12-19 16:38:34 +00:00
j433866
ae20a951be Add customisation arguments.
Add presentation of QR code in HTML.
2018-12-19 14:43:31 +00:00
Anthony Arnold
866dd546c8 Add the Play Media operation and place it under a new "Multimedia" category. Move the Render Image to this new category as well. 2018-12-20 00:05:10 +10:00
j433866
2070e1a96b Add new Generate QR Code module 2018-12-19 13:27:45 +00:00
j433866
952f49e2e1 Add qr-image to package 2018-12-19 13:27:18 +00:00
j433866
f600571c6d Fix to make the filter work when intensive mode was turned on. 2018-12-19 09:42:09 +00:00
j433866
5d4c7244e1 Add note about crib to operation description 2018-12-18 16:52:09 +00:00
j433866
b6bdcaa71f Rename output filter argument to Crib 2018-12-18 14:19:52 +00:00
j433866
c8eab5d218 Commenting 2018-12-18 14:06:39 +00:00
n1474335
8ab56a29ac 8.15.0 2018-12-18 13:50:30 +00:00
n1474335
973b5f3f5c Merge branch 'Cynser-text-brute-force' 2018-12-18 13:50:23 +00:00
n1474335
076a1f97c2 Tidied up 'Text Encoding Brute Force' operations and updated CHANGELOG 2018-12-18 13:50:10 +00:00
n1474335
d96ef37d81 Merge branch 'text-brute-force' of https://github.com/Cynser/CyberChef into Cynser-text-brute-force 2018-12-18 12:28:27 +00:00
n1474335
56f8302402 8.14.0 2018-12-18 12:20:03 +00:00
n1474335
97e6a7cbd8 Merge branch 'tcode2k16-master' 2018-12-18 12:19:56 +00:00
n1474335
d89d79116c Cleaned up Base62 ops and updated CHANGELOG 2018-12-18 12:19:42 +00:00
j433866
367d79e820 Fix filtering to work on all the data and not just the result snippet 2018-12-18 11:55:49 +00:00
j433866
283d7f2159 Add Output Filter option to Magic operation 2018-12-18 10:40:18 +00:00
Cynser
dacb3ef6c3 Added decode option 2018-12-17 19:39:12 +00:00
tcode2k16
22454ae842 Add "To Base62" and "From Base62" operations 2018-12-17 12:37:00 +08:00
n1474335
79b9b63982 8.13.0 2018-12-15 00:26:41 +00:00
n1474335
2f68bf30a4 Merge branch 'jarmovanlenthe-master' 2018-12-15 00:26:31 +00:00
n1474335
50f078cc45 Updated CHANGELOG 2018-12-15 00:26:15 +00:00
n1474335
47a410d6ab Merge branch 'master' of https://github.com/jarmovanlenthe/CyberChef into jarmovanlenthe-master 2018-12-15 00:19:16 +00:00
n1474335
31cbf8cccc 8.12.4 2018-12-15 00:16:23 +00:00
n1474335
88bd321e3e Merge branch 'imhotepisinvisible-master' 2018-12-15 00:16:13 +00:00
Jarmo van Lenthe
b4a586c0b9 Some lets to consts and removing of trailing spaces from grunt lint 2018-12-14 22:35:43 +01:00
Oliver Grubin
63593f1b6c Fix HMAC operation when hex key has bytes >= 0x80 (#437)
Add test vectors from RFC4231
2018-12-14 21:32:44 +00:00
Jarmo van Lenthe
dcff8971e8 Added simple A1Z26 'cipher' 2018-12-14 22:29:51 +01:00
Cynser
3f7059a235 Remove unnecessary escape character 2018-12-12 17:49:11 +00:00
Cynser
71c743ff5a Add Text Encoding Brute Force operation 2018-12-12 17:34:45 +00:00
n1474335
15fbe5a459 8.12.3 2018-11-23 16:07:30 +00:00
n1474335
cd47394709 Merge branch 'PhillipNordwall-JSON_Object_Sort' 2018-11-23 16:07:21 +00:00
n1474335
6f4ee8b7b6 Tidied JSON Beautify op. Changed default indent to 4 spaces instead of a tab. 2018-11-23 16:05:51 +00:00
n1474335
8c5d05b611 Merge branch 'JSON_Object_Sort' of https://github.com/PhillipNordwall/CyberChef into PhillipNordwall-JSON_Object_Sort 2018-11-23 15:56:59 +00:00
n1474335
3bdcf4d851 8.12.2 2018-11-23 14:58:38 +00:00
n1474335
1d1c69ca51 Updated magic pattern matches for QP and B64 encodings to handle whitespace better 2018-11-23 14:58:30 +00:00
Phillip Nordwall
c4c679021d Adding Sort Object Keys, and tests for it. 2018-11-22 11:10:10 -08:00
Phillip Nordwall
c16d13e2c9 Adding test cases for JSON Minify 2018-11-22 11:07:48 -08:00
Phillip Nordwall
97613eb3c7 Adding test cases for JSON Beautify 2018-11-22 10:31:22 -08:00
n1474335
a946d04a72 8.12.1 2018-11-21 17:48:03 +00:00
n1474335
cc35ec82eb Fixed babel transpilation of jsesc and crypto-api 2018-11-21 17:47:56 +00:00
n1474335
d6604e0008 Updated CHANGELOG 2018-11-21 12:48:27 +00:00
n1474335
b9e63efc37 Fixed version links in CHANGELOG 2018-11-21 12:40:55 +00:00
n1474335
b458707921 8.12.0 2018-11-21 12:29:25 +00:00
n1474335
6ec52c6cd2 Merge branch 'bwhitn-citrix' 2018-11-21 12:28:36 +00:00
n1474335
79d7a5dd87 Tidied up Citrix CTX1 operations and updated CHANGELOG 2018-11-21 12:28:19 +00:00
n1474335
1653d0212a Merge branch 'citrix' of https://github.com/bwhitn/CyberChef into bwhitn-citrix 2018-11-21 10:23:39 +00:00
Brian Whitney
c378bcb00b Fixed lint issues 2018-11-20 11:24:50 -05:00
Brian Whitney
215e7a5f5d Citrix CTX1 encoding/decoding 2018-11-20 11:09:52 -05:00
bwhitn
6b686681d5 Encoding ctx1 2018-11-19 23:48:33 -05:00
n1474335
20ea050728 Updated description for 'Substitute' to include note about escaping backslashes. 2018-11-19 14:54:37 +00:00
n1474335
4b6132a2d7 8.11.2 2018-11-19 14:34:56 +00:00
n1474335
4cf80e3ebb Added RFC numbers to relevant Base64 alphabets. Closes #410 2018-11-19 14:34:52 +00:00
n1474335
045747f543 8.11.1 2018-11-14 12:27:55 +00:00
n1474335
b10c5e3256 Fixed faulty package-lock.json 2018-11-14 12:27:47 +00:00
n1474335
69df2e4183 Updated comments 2018-11-13 18:05:52 +00:00
n1474335
12ebd35c4d 8.11.0 2018-11-13 17:56:46 +00:00
n1474335
30c5f76cf0 Updated changelog 2018-11-13 17:56:40 +00:00
n1474335
3a979b6cda 'JSON to CSV' operation now escapes characters correctly. Added tests for CSV/JSON operations. 2018-11-13 17:54:43 +00:00
n1474335
863bdffa84 Added 'CSV to JSON' and 'JSON to CSV' operations. Closes #277 2018-11-09 17:40:19 +00:00
n1474335
42b956e402 Fixed JSDoc comment 2018-11-09 15:28:47 +00:00
n1474335
4acf7b4e4f 8.10.2 2018-11-09 15:25:22 +00:00
n1474335
42e881326f Added 'Binary' key option to all bitwise operations. Closes #398 2018-11-09 15:25:16 +00:00
n1474335
3c4893d7c7 8.10.1 2018-11-07 15:20:51 +00:00
n1474335
027aca4ab2 Merge branch 'qistoph-NumSortHex' 2018-11-07 15:20:43 +00:00
n1474335
2d471f551f Lint 2018-11-07 15:20:09 +00:00
n1474335
5c598b69b0 Merge branch 'NumSortHex' of https://github.com/qistoph/CyberChef into qistoph-NumSortHex 2018-11-07 15:15:39 +00:00
n1474335
037300de79 8.10.0 2018-11-07 15:10:57 +00:00
n1474335
6990dcae89 Updated changelog 2018-11-07 15:10:25 +00:00
n1474335
6e81d6dfcd Merge branch 'klaxon1-feature/remove-letter-accents' 2018-11-07 15:08:09 +00:00
n1474335
cea30465d8 Changed 'Remove Letter Accents' to 'Remove Diacritics' 2018-11-07 15:07:54 +00:00
n1474335
b301d16cb2 Merge branch 'feature/remove-letter-accents' of https://github.com/klaxon1/CyberChef into klaxon1-feature/remove-letter-accents 2018-11-07 14:57:05 +00:00
n1474335
19c002fcdd 8.9.2 2018-11-07 14:40:13 +00:00
n1474335
ab3a73fe58 Merge branch 'qistoph-FromNegs' 2018-11-07 14:39:51 +00:00
n1474335
91fc2c28dc Added signed feature to 'To Decimal' 2018-11-07 14:39:33 +00:00
n1474335
ca47ba3c7c Merge branch 'FromNegs' of https://github.com/qistoph/CyberChef into qistoph-FromNegs 2018-11-07 14:23:39 +00:00
n1474335
e1b456c01c 8.9.1 2018-11-07 14:21:26 +00:00
n1474335
5eb7e00eac Merge branch 'qistoph-HmacToggleStr' 2018-11-07 14:21:18 +00:00
n1474335
8bcf68c8a1 Merge branch 'HmacToggleStr' of https://github.com/qistoph/CyberChef into qistoph-HmacToggleStr 2018-11-07 14:18:24 +00:00
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
Chris van Marle
3f0af9cdea Add tests for From Decimal 2018-10-22 17:51:26 +08: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
Chris van Marle
ba24e12454 Update hexadecimal sort after review
- Use Array.map instead of for-loop
- Add test case
2018-10-12 15:39:06 +02:00
Chris van Marle
b76aa16143 Fix Hash test 2018-10-12 13:54:40 +02:00
Chris van Marle
be2b466376 Use toggleString for Key in HMAC #263 2018-10-12 13:05:32 +02:00
Chris van Marle
a276378887 Enable parsing of negative decimals #176 2018-10-12 10:08:24 +02:00
Chris van Marle
3b3c27072f Fix lint errors 2018-10-11 15:50:58 +02:00
Klaxon
3089c39369 add test 2018-10-11 22:26:44 +10:00
Chris van Marle
0cbb17f7ce Support hexadecimal and other bases in numeric sorting 2018-10-11 14:23:05 +02:00
Klaxon
54793f2b78 update operation 2018-10-11 21:52:49 +10:00
Klaxon
f1ffe19ec8 Merge branch 'master' into feature/remove-letter-accents 2018-10-11 21:28:04 +10:00
Klaxon
04ee2fb3e4 add function to replace accent chars with latin chars 2018-10-03 13:26:01 +10:00
Klaxon
ac2466a304 create operation from npm run newop 2018-10-03 13:11:22 +10:00
199 changed files with 9119 additions and 2276 deletions

View File

@@ -1,19 +0,0 @@
{
"presets": [
["@babel/preset-env", {
"targets": {
"chrome": 40,
"firefox": 35,
"edge": 14,
"node": "6.5"
},
"modules": false,
"useBuiltIns": "entry"
}]
],
"plugins": [
["babel-plugin-transform-builtin-extend", {
"globals": ["Error"]
}]
]
}

View File

@@ -9,6 +9,6 @@ trim_trailing_whitespace = true
indent_style = space
indent_size = 4
[{package.json,.travis.yml}]
[{package.json,.travis.yml,nightwatch.json}]
indent_style = space
indent_size = 2

View File

@@ -1,10 +1,12 @@
{
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 9,
"ecmaFeatures": {
"impliedStrict": true
},
"sourceType": "module"
"sourceType": "module",
"allowImportExportEverywhere": true
},
"env": {
"browser": true,
@@ -87,6 +89,15 @@
"no-var": "error",
"prefer-const": "error"
},
"overrides": [
{
"files": "tests/**/*",
"rules": {
"no-unused-expressions": "off",
"no-console": "off"
}
}
],
"globals": {
"$": false,
"jQuery": false,

1
.gitignore vendored
View File

@@ -9,4 +9,5 @@ docs/*
src/core/config/modules/*
src/core/config/OperationConfig.json
src/core/operations/index.mjs
tests/browser/output/*

View File

@@ -1,15 +1,19 @@
language: node_js
node_js:
- node
addons:
chrome: stable
install: npm install
before_script:
- npm install -g grunt
- export NODE_OPTIONS=--max_old_space_size=2048
script:
- grunt lint
- grunt test
- grunt docs
- grunt node
- grunt prod --msg="$COMPILE_MSG"
- xvfb-run --server-args="-screen 0 1200x800x24" grunt testui
before_deploy:
- grunt exec:sitemap
- grunt copy:ghPages

View File

@@ -1,5 +1,57 @@
# Changelog
All notable changes to CyberChef will be documented in this file.
All major and minor version changes will be documented in this file. Details of patch-level version changes can be found in [commit messages](https://github.com/gchq/CyberChef/commits/master).
### [8.24.0] - 2019-02-08
- 'DNS over HTTPS' operation added [@h345983745] | [#489]
### [8.23.1] - 2019-01-18
- 'Convert co-ordinate format' operation added [@j433866] | [#476]
### [8.23.0] - 2019-01-18
- 'YARA Rules' operation added [@artemisbot] | [#468]
### [8.22.0] - 2019-01-10
- 'Subsection' operation added [@j433866] | [#467]
### [8.21.0] - 2019-01-10
- 'To Case Insensitive Regex' and 'From Case Insensitive Regex' operations added [@masq] | [#461]
### [8.20.0] - 2019-01-09
- 'Generate Lorem Ipsum' operation added [@klaxon1] | [#455]
### [8.19.0] - 2018-12-30
- UI test suite added to confirm that the app loads correctly in a reasonable time and that various operations from each module can be run [@n1474335] | [#458]
### [8.18.0] - 2018-12-26
- 'Split Colour Channels' operation added [@artemisbot] | [#449]
### [8.17.0] - 2018-12-25
- 'Generate QR Code' and 'Parse QR Code' operations added [@j433866] | [#448]
### [8.16.0] - 2018-12-19
- 'Play Media' operation added [@anthony-arnold] | [#446]
### [8.15.0] - 2018-12-18
- 'Text Encoding Brute Force' operation added [@Cynser] | [#439]
### [8.14.0] - 2018-12-18
- 'To Base62' and 'From Base62' operations added [@tcode2k16] | [#443]
### [8.13.0] - 2018-12-15
- 'A1Z26 Cipher Encode' and 'A1Z26 Cipher Decode' operations added [@jarmovanlenthe] | [#441]
### [8.12.0] - 2018-11-21
- 'Citrix CTX1 Encode' and 'Citrix CTX1 Decode' operations added [@bwhitn] | [#428]
### [8.11.0] - 2018-11-13
- 'CSV to JSON' and 'JSON to CSV' operations added [@n1474335] | [#277]
### [8.10.0] - 2018-11-07
- 'Remove Diacritics' operation added [@klaxon1] | [#387]
### [8.9.0] - 2018-11-07
- 'Defang URL' operation added [@arnydo] | [#394]
### [8.8.0] - 2018-10-10
- 'Parse TLV' operation added [@GCHQ77703] | [#351]
@@ -43,7 +95,7 @@ All notable changes to CyberChef will be documented in this file.
- Added support for loading, processing and downloading files up to 500MB [@n1474335] | [#224]
## [6.0.0] - 2017-09-19
- Threading support added. All recipe processing moved into a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) to increase performance and allowing long-running operations to be cancelled [@n1474335] | [#173]
- Threading support added. All recipe processing moved into a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) to increase performance and to allow long-running operations to be cancelled [@n1474335] | [#173]
- Module system created so that operations relying on large libraries can be downloaded separately as required, reducing the initial loading time for the app [@n1474335] | [#173]
## [5.0.0] - 2017-03-30
@@ -53,6 +105,24 @@ All notable changes to CyberChef will be documented in this file.
- Initial open source commit [@n1474335] | [b1d73a72](https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306)
[8.24.0]: https://github.com/gchq/CyberChef/releases/tag/v8.24.0
[8.23.1]: https://github.com/gchq/CyberChef/releases/tag/v8.23.1
[8.23.0]: https://github.com/gchq/CyberChef/releases/tag/v8.23.0
[8.22.0]: https://github.com/gchq/CyberChef/releases/tag/v8.22.0
[8.21.0]: https://github.com/gchq/CyberChef/releases/tag/v8.21.0
[8.20.0]: https://github.com/gchq/CyberChef/releases/tag/v8.20.0
[8.19.0]: https://github.com/gchq/CyberChef/releases/tag/v8.19.0
[8.18.0]: https://github.com/gchq/CyberChef/releases/tag/v8.18.0
[8.17.0]: https://github.com/gchq/CyberChef/releases/tag/v8.17.0
[8.16.0]: https://github.com/gchq/CyberChef/releases/tag/v8.16.0
[8.15.0]: https://github.com/gchq/CyberChef/releases/tag/v8.15.0
[8.14.0]: https://github.com/gchq/CyberChef/releases/tag/v8.14.0
[8.13.0]: https://github.com/gchq/CyberChef/releases/tag/v8.13.0
[8.12.0]: https://github.com/gchq/CyberChef/releases/tag/v8.12.0
[8.11.0]: https://github.com/gchq/CyberChef/releases/tag/v8.11.0
[8.10.0]: https://github.com/gchq/CyberChef/releases/tag/v8.10.0
[8.9.0]: https://github.com/gchq/CyberChef/releases/tag/v8.9.0
[8.8.0]: https://github.com/gchq/CyberChef/releases/tag/v8.8.0
[8.7.0]: https://github.com/gchq/CyberChef/releases/tag/v8.7.0
[8.6.0]: https://github.com/gchq/CyberChef/releases/tag/v8.6.0
@@ -69,13 +139,23 @@ All notable changes to CyberChef will be documented in this file.
[@n1474335]: https://github.com/n1474335
[@d98762625]: https://github.com/d98762625
[@j433866]: https://github.com/j433866
[@GCHQ77703]: https://github.com/GCHQ77703
[@h345983745]: https://github.com/h345983745
[@artemisbot]: https://github.com/artemisbot
[@picapi]: https://github.com/picapi
[@Dachande663]: https://github.com/Dachande663
[@JustAnotherMark]: https://github.com/JustAnotherMark
[@sevzero]: https://github.com/sevzero
[@PenguinGeorge]: https://github.com/PenguinGeorge
[@arnydo]: https://github.com/arnydo
[@klaxon1]: https://github.com/klaxon1
[@bwhitn]: https://github.com/bwhitn
[@jarmovanlenthe]: https://github.com/jarmovanlenthe
[@tcode2k16]: https://github.com/tcode2k16
[@Cynser]: https://github.com/Cynser
[@anthony-arnold]: https://github.com/anthony-arnold
[@masq]: https://github.com/masq
[#95]: https://github.com/gchq/CyberChef/pull/299
[#173]: https://github.com/gchq/CyberChef/pull/173
@@ -83,6 +163,7 @@ All notable changes to CyberChef will be documented in this file.
[#239]: https://github.com/gchq/CyberChef/pull/239
[#248]: https://github.com/gchq/CyberChef/pull/248
[#255]: https://github.com/gchq/CyberChef/issues/255
[#277]: https://github.com/gchq/CyberChef/issues/277
[#281]: https://github.com/gchq/CyberChef/pull/281
[#284]: https://github.com/gchq/CyberChef/pull/284
[#294]: https://github.com/gchq/CyberChef/pull/294
@@ -95,3 +176,19 @@ All notable changes to CyberChef will be documented in this file.
[#344]: https://github.com/gchq/CyberChef/pull/344
[#348]: https://github.com/gchq/CyberChef/pull/348
[#351]: https://github.com/gchq/CyberChef/pull/351
[#387]: https://github.com/gchq/CyberChef/pull/387
[#394]: https://github.com/gchq/CyberChef/pull/394
[#428]: https://github.com/gchq/CyberChef/pull/428
[#439]: https://github.com/gchq/CyberChef/pull/439
[#441]: https://github.com/gchq/CyberChef/pull/441
[#443]: https://github.com/gchq/CyberChef/pull/443
[#446]: https://github.com/gchq/CyberChef/pull/446
[#448]: https://github.com/gchq/CyberChef/pull/448
[#449]: https://github.com/gchq/CyberChef/pull/449
[#455]: https://github.com/gchq/CyberChef/pull/455
[#458]: https://github.com/gchq/CyberChef/pull/458
[#461]: https://github.com/gchq/CyberChef/pull/461
[#467]: https://github.com/gchq/CyberChef/pull/467
[#468]: https://github.com/gchq/CyberChef/pull/468
[#476]: https://github.com/gchq/CyberChef/pull/476
[#489]: https://github.com/gchq/CyberChef/pull/489

View File

@@ -2,6 +2,7 @@
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
const NodeExternals = require("webpack-node-externals");
const Inliner = require("web-resource-inliner");
const glob = require("glob");
@@ -29,8 +30,12 @@ module.exports = function (grunt) {
["clean:node", "clean:config", "exec:generateConfig", "webpack:node", "chmod:build"]);
grunt.registerTask("test",
"A task which runs all the tests in test/tests.",
["exec:generateConfig", "exec:tests"]);
"A task which runs all the operation tests in the tests directory.",
["exec:generateConfig", "exec:opTests"]);
grunt.registerTask("testui",
"A task which runs all the UI tests in the tests directory. The prod task must already have been run.",
["connect:prod", "exec:browserTests"]);
grunt.registerTask("docs",
"Compiles documentation in the /docs directory.",
@@ -66,6 +71,7 @@ module.exports = function (grunt) {
grunt.loadNpmTasks("grunt-exec");
grunt.loadNpmTasks("grunt-accessibility");
grunt.loadNpmTasks("grunt-concurrent");
grunt.loadNpmTasks("grunt-contrib-connect");
// Project configuration
@@ -143,11 +149,11 @@ module.exports = function (grunt) {
options: {
configFile: "./.eslintrc.json"
},
configs: ["Gruntfile.js"],
configs: ["*.{js,mjs}"],
core: ["src/core/**/*.{js,mjs}", "!src/core/vendor/**/*", "!src/core/operations/legacy/**/*"],
web: ["src/web/**/*.{js,mjs}"],
node: ["src/node/**/*.{js,mjs}"],
tests: ["test/**/*.{js,mjs}"],
tests: ["tests/**/*.{js,mjs}"],
},
jsdoc: {
options: {
@@ -179,7 +185,8 @@ module.exports = function (grunt) {
},
webpack: {
options: webpackConfig,
web: {
web: () => {
return {
mode: "production",
target: "web",
entry: Object.assign({
@@ -187,7 +194,8 @@ module.exports = function (grunt) {
sitemap: "./src/web/static/sitemap.js"
}, moduleEntryPoints),
output: {
path: __dirname + "/build/prod"
path: __dirname + "/build/prod",
globalObject: "this"
},
resolve: {
alias: {
@@ -209,7 +217,13 @@ module.exports = function (grunt) {
minifyCSS: true
}
}),
new BundleAnalyzerPlugin({
analyzerMode: "static",
reportFilename: "BundleAnalyzerReport.html",
openAnalyzer: false
}),
]
};
},
webInline: {
mode: "production",
@@ -238,19 +252,6 @@ module.exports = function (grunt) {
}),
]
},
tests: {
mode: "development",
target: "node",
entry: "./test/index.mjs",
externals: [NodeExternals()],
output: {
filename: "index.js",
path: __dirname + "/build/test"
},
plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS)
]
},
node: {
mode: "production",
target: "node",
@@ -299,6 +300,9 @@ module.exports = function (grunt) {
"./config/modules/OpModules": "./config/modules/Default"
}
},
output: {
globalObject: "this",
},
plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS),
new HtmlWebpackPlugin({
@@ -312,6 +316,14 @@ module.exports = function (grunt) {
}
}
},
connect: {
prod: {
options: {
port: 8000,
base: "build/prod/"
}
}
},
copy: {
ghPages: {
options: {
@@ -383,16 +395,17 @@ module.exports = function (grunt) {
generateConfig: {
command: [
"echo '\n--- Regenerating config files. ---'",
"mkdir -p src/core/config/modules",
"echo 'export default {};\n' > src/core/config/modules/OpModules.mjs",
"echo '[]\n' > src/core/config/OperationConfig.json",
"echo [] > src/core/config/OperationConfig.json",
"node --experimental-modules --no-warnings --no-deprecation src/core/config/scripts/generateOpsIndex.mjs",
"node --experimental-modules --no-warnings --no-deprecation src/core/config/scripts/generateConfig.mjs",
"echo '--- Config scripts finished. ---\n'"
].join(";")
},
tests: {
command: "node --experimental-modules --no-warnings --no-deprecation test/index.mjs"
opTests: {
command: "node --experimental-modules --no-warnings --no-deprecation tests/operations/index.mjs"
},
browserTests: {
command: "./node_modules/.bin/nightwatch --env prod,inline"
}
},
});

24
babel.config.js Normal file
View File

@@ -0,0 +1,24 @@
module.exports = function(api) {
api.cache.forever();
return {
"presets": [
["@babel/preset-env", {
"targets": {
"chrome": 40,
"firefox": 35,
"edge": 14,
"node": "6.5"
},
"modules": false,
"useBuiltIns": "entry"
}]
],
"plugins": [
"babel-plugin-syntax-dynamic-import",
["babel-plugin-transform-builtin-extend", {
"globals": ["Error"]
}]
]
};
};

34
nightwatch.json Normal file
View File

@@ -0,0 +1,34 @@
{
"src_folders": ["tests/browser"],
"output_folder": "tests/browser/output",
"test_settings": {
"default": {
"launch_url": "http://localhost:8080",
"webdriver": {
"start_process": true,
"server_path": "./node_modules/.bin/chromedriver",
"port": 9515,
"log_path": false
},
"desiredCapabilities": {
"browserName": "chrome"
}
},
"dev": {
"launch_url": "http://localhost:8080"
},
"prod": {
"launch_url": "http://localhost:8000/index.html"
},
"inline": {
"launch_url": "http://localhost:8000/cyberchef.htm"
}
}
}

5088
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "8.8.8",
"version": "8.24.2",
"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,22 +30,25 @@
"main": "build/node/CyberChef.js",
"bugs": "https://github.com/gchq/CyberChef/issues",
"devDependencies": {
"@babel/core": "^7.1.5",
"@babel/preset-env": "^7.1.5",
"autoprefixer": "^9.3.1",
"@babel/core": "^7.2.2",
"@babel/preset-env": "^7.2.3",
"autoprefixer": "^9.4.3",
"babel-eslint": "^10.0.1",
"babel-loader": "^8.0.4",
"bootstrap": "^4.1.3",
"colors": "^1.3.2",
"css-loader": "^1.0.1",
"eslint": "^5.8.0",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"bootstrap": "^4.2.1",
"chromedriver": "^2.45.0",
"colors": "^1.3.3",
"css-loader": "^2.1.0",
"eslint": "^5.12.1",
"exports-loader": "^0.7.0",
"extract-text-webpack-plugin": "^4.0.0-alpha0",
"file-loader": "^2.0.0",
"file-loader": "^3.0.1",
"grunt": "^1.0.3",
"grunt-accessibility": "~6.0.0",
"grunt-chmod": "~1.1.1",
"grunt-concurrent": "^2.3.1",
"grunt-contrib-clean": "~2.0.0",
"grunt-contrib-connect": "^2.0.0",
"grunt-contrib-copy": "~1.0.0",
"grunt-contrib-watch": "^1.1.0",
"grunt-eslint": "^21.0.0",
@@ -56,7 +59,9 @@
"imports-loader": "^0.8.0",
"ink-docstrap": "^1.3.2",
"jsdoc-babel": "^0.5.0",
"node-sass": "^4.10.0",
"mini-css-extract-plugin": "^0.5.0",
"nightwatch": "^1.0.18",
"node-sass": "^4.11.0",
"postcss-css-variables": "^0.11.0",
"postcss-import": "^12.0.1",
"postcss-loader": "^3.0.0",
@@ -66,8 +71,9 @@
"style-loader": "^0.23.1",
"url-loader": "^1.1.2",
"web-resource-inliner": "^4.2.1",
"webpack": "^4.25.1",
"webpack-dev-server": "^3.1.10",
"webpack": "^4.28.3",
"webpack-bundle-analyzer": "^3.0.3",
"webpack-dev-server": "^3.1.14",
"webpack-node-externals": "^1.7.2",
"worker-loader": "^2.0.0"
},
@@ -76,10 +82,10 @@
"babel-plugin-transform-builtin-extend": "1.1.2",
"babel-polyfill": "^6.26.0",
"bcryptjs": "^2.4.3",
"bignumber.js": "^8.0.1",
"bignumber.js": "^8.0.2",
"bootstrap-colorpicker": "^2.5.3",
"bootstrap-material-design": "^4.1.1",
"bson": "^3.0.2",
"bson": "^4.0.1",
"chi-squared": "^1.1.0",
"crypto-api": "^0.8.3",
"crypto-js": "^3.1.9-1",
@@ -90,46 +96,51 @@
"esmangle": "^1.0.1",
"esprima": "^4.0.1",
"exif-parser": "^0.1.12",
"file-saver": "^2.0.0-rc.4",
"file-saver": "^2.0.0",
"geodesy": "^1.1.3",
"highlight.js": "^9.13.1",
"jimp": "^0.6.0",
"jquery": "^3.3.1",
"js-crc": "^0.2.0",
"js-sha3": "^0.8.0",
"jsbn": "^1.1.0",
"jsesc": "^2.5.1",
"jsesc": "^2.5.2",
"jsonpath": "^1.0.0",
"jsonwebtoken": "^8.3.0",
"jsonwebtoken": "^8.4.0",
"jsqr": "^1.1.1",
"jsrsasign": "8.0.12",
"kbpgp": "^2.0.82",
"libyara-wasm": "0.0.11",
"lodash": "^4.17.11",
"loglevel": "^1.6.1",
"loglevel-message-prefix": "^3.0.0",
"moment": "^2.22.2",
"moment": "^2.23.0",
"moment-timezone": "^0.5.23",
"ngeohash": "^0.6.0",
"ngeohash": "^0.6.3",
"node-forge": "^0.7.6",
"node-md6": "^0.1.0",
"notepack.io": "^2.1.3",
"notepack.io": "^2.2.0",
"nwmatcher": "^1.4.4",
"otp": "^0.1.3",
"popper.js": "^1.14.4",
"popper.js": "^1.14.6",
"qr-image": "^3.2.0",
"scryptsy": "^2.0.0",
"snackbarjs": "^1.1.0",
"sortablejs": "^1.7.0",
"split.js": "^1.5.9",
"sortablejs": "^1.8.0-rc1",
"split.js": "^1.5.10",
"ssdeep.js": "0.0.2",
"ua-parser-js": "^0.7.19",
"utf8": "^3.0.0",
"vkbeautify": "^0.99.3",
"xmldom": "^0.1.27",
"xpath": "0.0.27",
"xregexp": "^4.2.0",
"xregexp": "^4.2.4",
"zlibjs": "^0.3.1"
},
"scripts": {
"start": "grunt dev",
"build": "grunt prod",
"test": "grunt test",
"testui": "grunt testui",
"docs": "grunt docs",
"lint": "grunt lint",
"newop": "node --experimental-modules src/core/config/scripts/newOperation.mjs"

View File

@@ -157,9 +157,9 @@ class Chef {
* @param {number} pos.end - The end offset.
* @returns {Object}
*/
calculateHighlights(recipeConfig, direction, pos) {
async calculateHighlights(recipeConfig, direction, pos) {
const recipe = new Recipe(recipeConfig);
const highlights = recipe.generateHighlightList();
const highlights = await recipe.generateHighlightList();
if (!highlights) return false;

View File

@@ -157,8 +157,8 @@ async function getDishAs(data) {
* @param {number} pos.start - The start offset.
* @param {number} pos.end - The end offset.
*/
function calculateHighlights(recipeConfig, direction, pos) {
pos = self.chef.calculateHighlights(recipeConfig, direction, pos);
async function calculateHighlights(recipeConfig, direction, pos) {
pos = await self.chef.calculateHighlights(recipeConfig, direction, pos);
self.postMessage({
action: "highlightsCalculated",

View File

@@ -6,6 +6,7 @@
*/
import Utils from "./Utils";
import DishError from "./errors/DishError";
import BigNumber from "bignumber.js";
import log from "loglevel";
@@ -61,7 +62,7 @@ class Dish {
case "list<file>":
return Dish.LIST_FILE;
default:
throw "Invalid data type string. No matching enum.";
throw new DishError("Invalid data type string. No matching enum.");
}
}
@@ -93,7 +94,7 @@ class Dish {
case Dish.LIST_FILE:
return "List<File>";
default:
throw "Invalid data type enum. No matching type.";
throw new DishError("Invalid data type enum. No matching type.");
}
}
@@ -117,7 +118,7 @@ class Dish {
if (!this.valid()) {
const sample = Utils.truncate(JSON.stringify(this.value), 13);
throw "Data is not a valid " + Dish.enumLookup(type) + ": " + sample;
throw new DishError(`Data is not a valid ${Dish.enumLookup(type)}: ${sample}`);
}
}
@@ -151,6 +152,7 @@ class Dish {
const byteArrayToStr = notUTF8 ? Utils.byteArrayToChars : Utils.byteArrayToUtf8;
// Convert data to intermediate byteArray type
try {
switch (this.type) {
case Dish.STRING:
this.value = this.value ? Utils.strToByteArray(this.value) : [];
@@ -166,7 +168,7 @@ class Dish {
this.value = Array.prototype.slice.call(new Uint8Array(this.value));
break;
case Dish.BIG_NUMBER:
this.value = this.value instanceof BigNumber ? Utils.strToByteArray(this.value.toFixed()) : [];
this.value = BigNumber.isBigNumber(this.value) ? Utils.strToByteArray(this.value.toFixed()) : [];
break;
case Dish.JSON:
this.value = this.value ? Utils.strToByteArray(JSON.stringify(this.value, null, 4)) : [];
@@ -183,10 +185,14 @@ class Dish {
default:
break;
}
} catch (err) {
throw new DishError(`Error translating from ${Dish.enumLookup(this.type)} to byteArray: ${err}`);
}
this.type = Dish.BYTE_ARRAY;
// Convert from byteArray to toType
try {
switch (toType) {
case Dish.STRING:
case Dish.HTML:
@@ -223,6 +229,9 @@ class Dish {
default:
break;
}
} catch (err) {
throw new DishError(`Error translating from byteArray to ${Dish.enumLookup(toType)}: ${err}`);
}
}
@@ -256,7 +265,7 @@ class Dish {
case Dish.ARRAY_BUFFER:
return this.value instanceof ArrayBuffer;
case Dish.BIG_NUMBER:
return this.value instanceof BigNumber;
return BigNumber.isBigNumber(this.value);
case Dish.JSON:
// All values can be serialised in some manner, so we return true in all cases
return true;
@@ -357,7 +366,7 @@ class Dish {
);
break;
default:
throw new Error("Cannot clone Dish, unknown type");
throw new DishError("Cannot clone Dish, unknown type");
}
return newDish;

View File

@@ -23,8 +23,10 @@ class Ingredient {
this._value = null;
this.disabled = false;
this.hint = "";
this.rows = 0;
this.toggleValues = [];
this.target = null;
this.defaultIndex = 0;
if (ingredientConfig) {
this._parseConfig(ingredientConfig);
@@ -44,8 +46,10 @@ class Ingredient {
this.defaultValue = ingredientConfig.value;
this.disabled = !!ingredientConfig.disabled;
this.hint = ingredientConfig.hint || false;
this.rows = ingredientConfig.rows || false;
this.toggleValues = ingredientConfig.toggleValues;
this.target = typeof ingredientConfig.target !== "undefined" ? ingredientConfig.target : null;
this.defaultIndex = typeof ingredientConfig.defaultIndex !== "undefined" ? ingredientConfig.defaultIndex : 0;
}
@@ -93,6 +97,7 @@ class Ingredient {
case "binaryString":
case "binaryShortString":
case "editableOption":
case "editableOptionShort":
return Utils.parseEscapedChars(data);
case "byteArray":
if (typeof data == "string") {

View File

@@ -23,6 +23,7 @@ class Operation {
this._breakpoint = false;
this._disabled = false;
this._flowControl = false;
this._manualBake = false;
this._ingList = [];
// Public fields
@@ -179,8 +180,10 @@ class Operation {
if (ing.toggleValues) conf.toggleValues = ing.toggleValues;
if (ing.hint) conf.hint = ing.hint;
if (ing.rows) conf.rows = ing.rows;
if (ing.disabled) conf.disabled = ing.disabled;
if (ing.target) conf.target = ing.target;
if (ing.defaultIndex) conf.defaultIndex = ing.defaultIndex;
return conf;
});
}
@@ -280,6 +283,7 @@ class Operation {
return this._flowControl;
}
/**
* Set whether this Operation is a flowcontrol op.
*
@@ -289,6 +293,26 @@ class Operation {
this._flowControl = !!value;
}
/**
* Returns true if this Operation should not trigger AutoBake.
*
* @returns {boolean}
*/
get manualBake() {
return this._manualBake;
}
/**
* Set whether this Operation should trigger AutoBake.
*
* @param {boolean} value
*/
set manualBake(value) {
this._manualBake = !!value;
}
}
export default Operation;

View File

@@ -4,12 +4,15 @@
* @license Apache-2.0
*/
// import Operation from "./Operation.js";
import OpModules from "./config/modules/OpModules";
import OperationConfig from "./config/OperationConfig.json";
import OperationError from "./errors/OperationError";
import Operation from "./Operation";
import DishError from "./errors/DishError";
import log from "loglevel";
// Cache container for modules
let modules = null;
/**
* The Recipe controls a list of Operations and the Dish they operate on.
*/
@@ -36,16 +39,43 @@ class Recipe {
* @param {Object} recipeConfig
*/
_parseConfig(recipeConfig) {
for (let c = 0; c < recipeConfig.length; c++) {
const operationName = recipeConfig[c].op;
const opConf = OperationConfig[operationName];
const opObj = OpModules[opConf.module][operationName];
const operation = new opObj();
operation.ingValues = recipeConfig[c].args;
operation.breakpoint = recipeConfig[c].breakpoint;
operation.disabled = recipeConfig[c].disabled;
this.addOperation(operation);
recipeConfig.forEach(c => {
this.opList.push({
name: c.op,
module: OperationConfig[c.op].module,
ingValues: c.args,
breakpoint: c.breakpoint,
disabled: c.disabled,
});
});
}
/**
* Populate elements of opList with operation instances.
* Dynamic import here removes top-level cyclic dependency issue.
*
* @private
*/
async _hydrateOpList() {
if (!modules) {
// Using Webpack Magic Comments to force the dynamic import to be included in the main chunk
// https://webpack.js.org/api/module-methods/
modules = await import(/* webpackMode: "eager" */ "./config/modules/OpModules");
modules = modules.default;
}
this.opList = this.opList.map(o => {
if (o instanceof Operation) {
return o;
} else {
const op = new modules[o.module][o.name]();
op.ingValues = o.ingValues;
op.breakpoint = o.breakpoint;
op.disabled = o.disabled;
return op;
}
});
}
@@ -55,7 +85,10 @@ class Recipe {
* @returns {Object[]}
*/
get config() {
return this.opList.map(op => op.config);
return this.opList.map(op => ({
op: op.name,
args: op.ingValues,
}));
}
@@ -75,7 +108,19 @@ class Recipe {
* @param {Operation[]} operations
*/
addOperations(operations) {
this.opList = this.opList.concat(operations);
operations.forEach(o => {
if (o instanceof Operation) {
this.opList.push(o);
} else {
this.opList.push({
name: o.name,
module: o.module,
ingValues: o.args,
breakpoint: o.breakpoint,
disabled: o.disabled,
});
}
});
}
@@ -108,7 +153,7 @@ class Recipe {
/**
* Returns true if there is an Flow Control Operation in this Recipe.
* Returns true if there is a Flow Control Operation in this Recipe.
*
* @returns {boolean}
*/
@@ -137,6 +182,8 @@ class Recipe {
if (startFrom === 0) this.lastRunOp = null;
await this._hydrateOpList();
log.debug(`[*] Executing recipe of ${this.opList.length} operations, starting at ${startFrom}`);
for (let i = startFrom; i < this.opList.length; i++) {
@@ -183,6 +230,10 @@ class Recipe {
// native types is not fully supported yet.
dish.set(err.message, "string");
return i;
} else if (err instanceof DishError ||
(err.type && err.type === "DishError")) {
dish.set(err.message, "string");
return i;
} else {
const e = typeof err == "string" ? { message: err } : err;
@@ -250,7 +301,8 @@ class Recipe {
* @returns {function} highlights[].b
* @returns {Object[]} highlights[].args
*/
generateHighlightList() {
async generateHighlightList() {
await this._hydrateOpList();
const highlights = [];
for (let i = 0; i < this.opList.length; i++) {

View File

@@ -5,10 +5,10 @@
*/
import utf8 from "utf8";
import moment from "moment-timezone";
import {fromBase64} from "./lib/Base64";
import {fromBase64, toBase64} from "./lib/Base64";
import {fromHex} from "./lib/Hex";
import {fromDecimal} from "./lib/Decimal";
import {fromBinary} from "./lib/Binary";
/**
@@ -298,7 +298,7 @@ class Utils {
* Accepts hex, Base64, UTF8 and Latin1 strings.
*
* @param {string} str
* @param {string} type - One of "Hex", "Decimal", "Base64", "UTF8" or "Latin1"
* @param {string} type - One of "Binary", "Hex", "Decimal", "Base64", "UTF8" or "Latin1"
* @returns {byteArray}
*
* @example
@@ -313,6 +313,8 @@ class Utils {
*/
static convertToByteArray(str, type) {
switch (type.toLowerCase()) {
case "binary":
return fromBinary(str);
case "hex":
return fromHex(str);
case "decimal":
@@ -333,7 +335,7 @@ class Utils {
* Accepts hex, Base64, UTF8 and Latin1 strings.
*
* @param {string} str
* @param {string} type - One of "Hex", "Decimal", "Base64", "UTF8" or "Latin1"
* @param {string} type - One of "Binary", "Hex", "Decimal", "Base64", "UTF8" or "Latin1"
* @returns {string}
*
* @example
@@ -348,6 +350,8 @@ class Utils {
*/
static convertToByteString(str, type) {
switch (type.toLowerCase()) {
case "binary":
return Utils.byteArrayToChars(fromBinary(str));
case "hex":
return Utils.byteArrayToChars(fromHex(str));
case "decimal":
@@ -568,6 +572,10 @@ class Utils {
cell = "";
lines.push(line);
line = [];
// Skip next byte if it is also a line delim (e.g. \r\n)
if (lineDelims.indexOf(next) >= 0 && next !== b) {
i++;
}
} else {
cell += b;
}
@@ -788,38 +796,6 @@ class Utils {
}
/**
* Expresses a number of milliseconds in a human readable format.
*
* Range | Sample Output
* -----------------------------|-------------------------------
* 0 to 45 seconds | a few seconds ago
* 45 to 90 seconds | a minute ago
* 90 seconds to 45 minutes | 2 minutes ago ... 45 minutes ago
* 45 to 90 minutes | an hour ago
* 90 minutes to 22 hours | 2 hours ago ... 22 hours ago
* 22 to 36 hours | a day ago
* 36 hours to 25 days | 2 days ago ... 25 days ago
* 25 to 45 days | a month ago
* 45 to 345 days | 2 months ago ... 11 months ago
* 345 to 545 days (1.5 years) | a year ago
* 546 days+ | 2 years ago ... 20 years ago
*
* @param {number} ms
* @returns {string}
*
* @example
* // returns "3 minutes"
* Utils.fuzzyTime(152435);
*
* // returns "5 days"
* Utils.fuzzyTime(456851321);
*/
static fuzzyTime(ms) {
return moment.duration(ms, "milliseconds").humanize();
}
/**
* Formats a list of files or directories.
*
@@ -841,6 +817,17 @@ class Utils {
return html;
};
const formatContent = function (buff, type) {
if (type.startsWith("image")) {
let dataURI = "data:";
dataURI += type + ";";
dataURI += "base64," + toBase64(buff);
return "<img style='max-width: 100%;' src='" + dataURI + "'>";
} else {
return `<pre>${Utils.escapeHtml(Utils.arrayBufferToStr(buff.buffer))}</pre>`;
}
};
const formatFile = async function(file, i) {
const buff = await Utils.readFile(file);
const blob = new Blob(
@@ -870,7 +857,7 @@ class Utils {
</div>
<div id='collapse${i}' class='collapse' aria-labelledby='heading${i}' data-parent="#files">
<div class='card-body'>
<pre>${Utils.escapeHtml(Utils.arrayBufferToStr(buff.buffer))}</pre>
${formatContent(buff, file.type)}
</div>
</div>
</div>`;

View File

@@ -25,6 +25,8 @@
"From Base32",
"To Base58",
"From Base58",
"To Base62",
"From Base62",
"To Base85",
"From Base85",
"To Base",
@@ -49,12 +51,15 @@
"Change IP format",
"Encode text",
"Decode text",
"Text Encoding Brute Force",
"Swap endianness",
"To MessagePack",
"From MessagePack",
"To Braille",
"From Braille",
"Parse TLV"
"Parse TLV",
"CSV to JSON",
"JSON to CSV"
]
},
{
@@ -84,6 +89,8 @@
"Bifid Cipher Decode",
"Affine Cipher Encode",
"Affine Cipher Decode",
"A1Z26 Cipher Encode",
"A1Z26 Cipher Decode",
"Atbash Cipher",
"Substitute",
"Derive PBKDF2 key",
@@ -93,6 +100,8 @@
"JWT Sign",
"JWT Verify",
"JWT Decode",
"Citrix CTX1 Encode",
"Citrix CTX1 Decode",
"Pseudo-Random Number Generator"
]
},
@@ -146,6 +155,7 @@
"name": "Networking",
"ops": [
"HTTP request",
"DNS over HTTPS",
"Strip HTTP headers",
"Dechunk HTTP response",
"Parse User Agent",
@@ -159,7 +169,8 @@
"Change IP format",
"Group IP addresses",
"Encode NetBIOS Name",
"Decode NetBIOS Name"
"Decode NetBIOS Name",
"Defang URL"
]
},
{
@@ -167,6 +178,7 @@
"ops": [
"Encode text",
"Decode text",
"Remove Diacritics",
"Unescape Unicode Characters"
]
},
@@ -178,6 +190,8 @@
"Remove null bytes",
"To Upper case",
"To Lower case",
"To Case Insensitive Regex",
"From Case Insensitive Regex",
"Add line numbers",
"Remove line numbers",
"To Table",
@@ -202,6 +216,7 @@
"Convert mass",
"Convert speed",
"Convert data units",
"Convert co-ordinate format",
"Parse UNIX file permissions",
"Swap endianness",
"Parse colour code",
@@ -293,9 +308,7 @@
"Adler-32 Checksum",
"CRC-16 Checksum",
"CRC-32 Checksum",
"TCP/IP Checksum",
"To Geohash",
"From Geohash"
"TCP/IP Checksum"
]
},
{
@@ -330,23 +343,40 @@
"From MessagePack"
]
},
{
"name": "Forensics",
"ops": [
"Detect File Type",
"Scan for Embedded Files",
"Remove EXIF",
"Extract EXIF"
]
},
{
"name": "Multimedia",
"ops": [
"Render Image",
"Play Media",
"Remove EXIF",
"Extract EXIF",
"Split Colour Channels"
]
},
{
"name": "Other",
"ops": [
"Entropy",
"Frequency distribution",
"Chi Square",
"Detect File Type",
"Scan for Embedded Files",
"Disassemble x86",
"Pseudo-Random Number Generator",
"Generate UUID",
"Generate TOTP",
"Generate HOTP",
"Generate QR Code",
"Parse QR Code",
"Haversine distance",
"Render Image",
"Remove EXIF",
"Extract EXIF",
"Generate Lorem Ipsum",
"Numberwang",
"XKCD Random Number"
]
@@ -356,6 +386,7 @@
"ops": [
"Magic",
"Fork",
"Subsection",
"Merge",
"Register",
"Label",

View File

@@ -41,6 +41,7 @@ for (const opObj in Ops) {
inputType: op.inputType,
outputType: op.presentType,
flowControl: op.flowControl,
manualBake: op.manualBake,
args: op.args
};

View File

@@ -222,7 +222,7 @@ export default ${moduleName};
console.log(`\nNext steps:
1. Add your operation to ${colors.green("src/core/config/Categories.json")}
2. Write your operation code.
3. Write tests in ${colors.green("test/tests/operations/")}
3. Write tests in ${colors.green("tests/operations/tests/")}
4. Run ${colors.cyan("npm run lint")} and ${colors.cyan("npm run test")}
5. Submit a Pull Request to get your operation added to the official CyberChef repository.`);

View File

@@ -0,0 +1,26 @@
/**
* Custom error type for handling Dish type errors.
* i.e. where the Dish cannot be successfully translated between types
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
class DishError extends Error {
/**
* Standard error constructor. Adds no new behaviour.
*
* @param args - Standard error args
*/
constructor(...args) {
super(...args);
this.type = "DishError";
if (Error.captureStackTrace) {
Error.captureStackTrace(this, DishError);
}
}
}
export default DishError;

View File

@@ -126,14 +126,14 @@ export function fromBase64(data, alphabet="A-Za-z0-9+/=", returnType="string", r
* Base64 alphabets.
*/
export const ALPHABET_OPTIONS = [
{name: "Standard: A-Za-z0-9+/=", value: "A-Za-z0-9+/="},
{name: "URL safe: A-Za-z0-9-_", value: "A-Za-z0-9-_"},
{name: "Standard (RFC 4648): A-Za-z0-9+/=", value: "A-Za-z0-9+/="},
{name: "URL safe (RFC 4648 \u00A75): A-Za-z0-9-_", value: "A-Za-z0-9-_"},
{name: "Filename safe: A-Za-z0-9+-=", value: "A-Za-z0-9+\\-="},
{name: "itoa64: ./0-9A-Za-z=", value: "./0-9A-Za-z="},
{name: "XML: A-Za-z0-9_.", value: "A-Za-z0-9_."},
{name: "y64: A-Za-z0-9._-", value: "A-Za-z0-9._-"},
{name: "z64: 0-9a-zA-Z+/=", value: "0-9a-zA-Z+/="},
{name: "Radix-64: 0-9A-Za-z+/=", value: "0-9A-Za-z+/="},
{name: "Radix-64 (RFC 4880): 0-9A-Za-z+/=", value: "0-9A-Za-z+/="},
{name: "Uuencoding: [space]-_", value: " -_"},
{name: "Xxencoding: +-0-9A-Za-z", value: "+\\-0-9A-Za-z"},
{name: "BinHex: !-,-0-689@A-NP-VX-Z[`a-fh-mp-r", value: "!-,-0-689@A-NP-VX-Z[`a-fh-mp-r"},

70
src/core/lib/Binary.mjs Normal file
View File

@@ -0,0 +1,70 @@
/**
* Binary functions.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Utils from "../Utils";
/**
* Convert a byte array into a binary string.
*
* @param {Uint8Array|byteArray} data
* @param {string} [delim="Space"]
* @param {number} [padding=8]
* @returns {string}
*
* @example
* // returns "00010000 00100000 00110000"
* toBinary([10,20,30]);
*
* // returns "00010000 00100000 00110000"
* toBinary([10,20,30], ":");
*/
export function toBinary(data, delim="Space", padding=8) {
if (!data) return "";
delim = Utils.charRep(delim);
let output = "";
for (let i = 0; i < data.length; i++) {
output += data[i].toString(2).padStart(padding, "0") + delim;
}
if (delim.length) {
return output.slice(0, -delim.length);
} else {
return output;
}
}
/**
* Convert a binary string into a byte array.
*
* @param {string} data
* @param {string} [delim]
* @param {number} [byteLen=8]
* @returns {byteArray}
*
* @example
* // returns [10,20,30]
* fromBinary("00010000 00100000 00110000");
*
* // returns [10,20,30]
* fromBinary("00010000:00100000:00110000", "Colon");
*/
export function fromBinary(data, delim="Space", byteLen=8) {
const delimRegex = Utils.regexRep(delim);
data = data.replace(delimRegex, "");
const output = [];
for (let i = 0; i < data.length; i += byteLen) {
output.push(parseInt(data.substr(i, byteLen), 2));
}
return output;
}

View File

@@ -116,3 +116,9 @@ export function sub(operand, key) {
const result = operand - key;
return (result < 0) ? 256 + result : result;
}
/**
* Delimiter options for bitwise operations
*/
export const BITWISE_OP_DELIMS = ["Hex", "Decimal", "Binary", "Base64", "UTF8", "Latin1"];

View File

@@ -0,0 +1,655 @@
/**
* Co-ordinate conversion resources.
*
* @author j433866 [j433866@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import geohash from "ngeohash";
import geodesy from "geodesy";
import OperationError from "../errors/OperationError";
/**
* Co-ordinate formats
*/
export const FORMATS = [
"Degrees Minutes Seconds",
"Degrees Decimal Minutes",
"Decimal Degrees",
"Geohash",
"Military Grid Reference System",
"Ordnance Survey National Grid",
"Universal Transverse Mercator"
];
/**
* Formats that should be passed to the conversion module as-is
*/
const NO_CHANGE = [
"Geohash",
"Military Grid Reference System",
"Ordnance Survey National Grid",
"Universal Transverse Mercator",
];
/**
* Convert a given latitude and longitude into a different format.
*
* @param {string} input - Input string to be converted
* @param {string} inFormat - Format of the input coordinates
* @param {string} inDelim - The delimiter splitting the lat/long of the input
* @param {string} outFormat - Format to convert to
* @param {string} outDelim - The delimiter to separate the output with
* @param {string} includeDir - Whether or not to include the compass direction in the output
* @param {number} precision - Precision of the result
* @returns {string} A formatted string of the converted co-ordinates
*/
export function convertCoordinates (input, inFormat, inDelim, outFormat, outDelim, includeDir, precision) {
let isPair = false,
split,
latlon,
convLat,
convLon,
conv,
hash,
utm,
mgrs,
osng,
splitLat,
splitLong,
lat,
lon;
// Can't have a precision less than 0!
if (precision < 0) {
precision = 0;
}
if (inDelim === "Auto") {
// Try to detect a delimiter in the input.
inDelim = findDelim(input);
if (inDelim === null) {
throw new OperationError("Unable to detect the input delimiter automatically.");
}
} else if (!inDelim.includes("Direction")) {
// Convert the delimiter argument value to the actual character
inDelim = realDelim(inDelim);
}
if (inFormat === "Auto") {
// Try to detect the format of the input data
inFormat = findFormat(input, inDelim);
if (inFormat === null) {
throw new OperationError("Unable to detect the input format automatically.");
}
}
// Convert the output delimiter argument to the real character
outDelim = realDelim(outDelim);
if (!NO_CHANGE.includes(inFormat)) {
if (inDelim.includes("Direction")) {
// Split on directions
split = input.split(/[NnEeSsWw]/g);
if (split[0] === "") {
// Remove first element if direction preceding
split = split.slice(1);
}
} else {
split = input.split(inDelim);
}
// Replace any co-ordinate symbols with spaces so we can split on them later
for (let i = 0; i < split.length; i++) {
split[i] = split[i].replace(/[°˝´'"]/g, " ");
}
if (split.length > 1) {
isPair = true;
}
} else {
// Remove any delimiters from the input
input = input.replace(inDelim, "");
isPair = true;
}
// Conversions from the input format into a geodesy latlon object
switch (inFormat) {
case "Geohash":
hash = geohash.decode(input.replace(/[^A-Za-z0-9]/g, ""));
latlon = new geodesy.LatLonEllipsoidal(hash.latitude, hash.longitude);
break;
case "Military Grid Reference System":
utm = geodesy.Mgrs.parse(input.replace(/[^A-Za-z0-9]/g, "")).toUtm();
latlon = utm.toLatLonE();
break;
case "Ordnance Survey National Grid":
osng = geodesy.OsGridRef.parse(input.replace(/[^A-Za-z0-9]/g, ""));
latlon = geodesy.OsGridRef.osGridToLatLon(osng);
break;
case "Universal Transverse Mercator":
// Geodesy needs a space between the first 2 digits and the next letter
if (/^[\d]{2}[A-Za-z]/.test(input)) {
input = input.slice(0, 2) + " " + input.slice(2);
}
utm = geodesy.Utm.parse(input);
latlon = utm.toLatLonE();
break;
case "Degrees Minutes Seconds":
if (isPair) {
// Split up the lat/long into degrees / minutes / seconds values
splitLat = splitInput(split[0]);
splitLong = splitInput(split[1]);
if (splitLat.length >= 3 && splitLong.length >= 3) {
lat = convDMSToDD(splitLat[0], splitLat[1], splitLat[2], 10);
lon = convDMSToDD(splitLong[0], splitLong[1], splitLong[2], 10);
latlon = new geodesy.LatLonEllipsoidal(lat.degrees, lon.degrees);
} else {
throw new OperationError("Invalid co-ordinate format for Degrees Minutes Seconds");
}
} else {
// Not a pair, so only try to convert one set of co-ordinates
splitLat = splitInput(split[0]);
if (splitLat.length >= 3) {
lat = convDMSToDD(splitLat[0], splitLat[1], splitLat[2]);
latlon = new geodesy.LatLonEllipsoidal(lat.degrees, lat.degrees);
} else {
throw new OperationError("Invalid co-ordinate format for Degrees Minutes Seconds");
}
}
break;
case "Degrees Decimal Minutes":
if (isPair) {
splitLat = splitInput(split[0]);
splitLong = splitInput(split[1]);
if (splitLat.length !== 2 || splitLong.length !== 2) {
throw new OperationError("Invalid co-ordinate format for Degrees Decimal Minutes.");
}
// Convert to decimal degrees, and then convert to a geodesy object
lat = convDDMToDD(splitLat[0], splitLat[1], 10);
lon = convDDMToDD(splitLong[0], splitLong[1], 10);
latlon = new geodesy.LatLonEllipsoidal(lat.degrees, lon.degrees);
} else {
// Not a pair, so only try to convert one set of co-ordinates
splitLat = splitInput(input);
if (splitLat.length !== 2) {
throw new OperationError("Invalid co-ordinate format for Degrees Decimal Minutes.");
}
lat = convDDMToDD(splitLat[0], splitLat[1], 10);
latlon = new geodesy.LatLonEllipsoidal(lat.degrees, lat.degrees);
}
break;
case "Decimal Degrees":
if (isPair) {
splitLat = splitInput(split[0]);
splitLong = splitInput(split[1]);
if (splitLat.length !== 1 || splitLong.length !== 1) {
throw new OperationError("Invalid co-ordinate format for Decimal Degrees.");
}
latlon = new geodesy.LatLonEllipsoidal(splitLat[0], splitLong[0]);
} else {
// Not a pair, so only try to convert one set of co-ordinates
splitLat = splitInput(split[0]);
if (splitLat.length !== 1) {
throw new OperationError("Invalid co-ordinate format for Decimal Degrees.");
}
latlon = new geodesy.LatLonEllipsoidal(splitLat[0], splitLat[0]);
}
break;
default:
throw new OperationError(`Unknown input format '${inFormat}'`);
}
// Everything is now a geodesy latlon object
// These store the latitude and longitude as decimal
if (inFormat.includes("Degrees")) {
// If the input string contains directions, we need to check if they're S or W.
// If either of the directions are, we should make the decimal value negative
const dirs = input.toUpperCase().match(/[NESW]/g);
if (dirs && dirs.length >= 1) {
// Make positive lat/lon values with S/W directions into negative values
if (dirs[0] === "S" || dirs[0] === "W" && latlon.lat > 0) {
latlon.lat = -latlon.lat;
}
if (dirs.length >= 2) {
if (dirs[1] === "S" || dirs[1] === "W" && latlon.lon > 0) {
latlon.lon = -latlon.lon;
}
}
}
}
// Try to find the compass directions of the lat and long
const [latDir, longDir] = findDirs(latlon.lat + "," + latlon.lon, ",");
// Output conversions for each output format
switch (outFormat) {
case "Decimal Degrees":
// We could use the built in latlon.toString(),
// but this makes adjusting the output harder
lat = convDDToDD(latlon.lat, precision);
lon = convDDToDD(latlon.lon, precision);
convLat = lat.string;
convLon = lon.string;
break;
case "Degrees Decimal Minutes":
lat = convDDToDDM(latlon.lat, precision);
lon = convDDToDDM(latlon.lon, precision);
convLat = lat.string;
convLon = lon.string;
break;
case "Degrees Minutes Seconds":
lat = convDDToDMS(latlon.lat, precision);
lon = convDDToDMS(latlon.lon, precision);
convLat = lat.string;
convLon = lon.string;
break;
case "Geohash":
convLat = geohash.encode(latlon.lat, latlon.lon, precision);
break;
case "Military Grid Reference System":
utm = latlon.toUtm();
mgrs = utm.toMgrs();
// MGRS wants a precision that's an even number between 2 and 10
if (precision % 2 !== 0) {
precision = precision + 1;
}
if (precision > 10) {
precision = 10;
}
convLat = mgrs.toString(precision);
break;
case "Ordnance Survey National Grid":
osng = geodesy.OsGridRef.latLonToOsGrid(latlon);
if (osng.toString() === "") {
throw new OperationError("Could not convert co-ordinates to OS National Grid. Are the co-ordinates in range?");
}
// OSNG wants a precision that's an even number between 2 and 10
if (precision % 2 !== 0) {
precision = precision + 1;
}
if (precision > 10) {
precision = 10;
}
convLat = osng.toString(precision);
break;
case "Universal Transverse Mercator":
utm = latlon.toUtm();
convLat = utm.toString(precision);
break;
}
if (convLat === undefined) {
throw new OperationError("Error converting co-ordinates.");
}
if (outFormat.includes("Degrees")) {
// Format DD/DDM/DMS for output
// If we're outputting a compass direction, remove the negative sign
if (latDir === "S" && includeDir !== "None") {
convLat = convLat.replace("-", "");
}
if (longDir === "W" && includeDir !== "None") {
convLon = convLon.replace("-", "");
}
let outConv = "";
if (includeDir === "Before") {
outConv += latDir + " ";
}
outConv += convLat;
if (includeDir === "After") {
outConv += " " + latDir;
}
outConv += outDelim;
if (isPair) {
if (includeDir === "Before") {
outConv += longDir + " ";
}
outConv += convLon;
if (includeDir === "After") {
outConv += " " + longDir;
}
outConv += outDelim;
}
conv = outConv;
} else {
conv = convLat + outDelim;
}
return conv;
}
/**
* Split up the input using a space or degrees signs, and sanitise the result
*
* @param {string} input - The input data to be split
* @returns {number[]} An array of the different items in the string, stored as floats
*/
function splitInput (input){
const split = [];
input.split(/\s+/).forEach(item => {
// Remove any character that isn't a digit, decimal point or negative sign
item = item.replace(/[^0-9.-]/g, "");
if (item.length > 0){
// Turn the item into a float
split.push(parseFloat(item));
}
});
return split;
}
/**
* Convert Degrees Minutes Seconds to Decimal Degrees
*
* @param {number} degrees - The degrees of the input co-ordinates
* @param {number} minutes - The minutes of the input co-ordinates
* @param {number} seconds - The seconds of the input co-ordinates
* @param {number} precision - The precision the result should be rounded to
* @returns {{string: string, degrees: number}} An object containing the raw converted value (obj.degrees), and a formatted string version (obj.string)
*/
function convDMSToDD (degrees, minutes, seconds, precision){
const absDegrees = Math.abs(degrees);
let conv = absDegrees + (minutes / 60) + (seconds / 3600);
let outString = round(conv, precision) + "°";
if (isNegativeZero(degrees) || degrees < 0) {
conv = -conv;
outString = "-" + outString;
}
return {
"degrees": conv,
"string": outString
};
}
/**
* Convert Decimal Degrees Minutes to Decimal Degrees
*
* @param {number} degrees - The input degrees to be converted
* @param {number} minutes - The input minutes to be converted
* @param {number} precision - The precision which the result should be rounded to
* @returns {{string: string, degrees: number}} An object containing the raw converted value (obj.degrees), and a formatted string version (obj.string)
*/
function convDDMToDD (degrees, minutes, precision) {
const absDegrees = Math.abs(degrees);
let conv = absDegrees + minutes / 60;
let outString = round(conv, precision) + "°";
if (isNegativeZero(degrees) || degrees < 0) {
conv = -conv;
outString = "-" + outString;
}
return {
"degrees": conv,
"string": outString
};
}
/**
* Convert Decimal Degrees to Decimal Degrees
*
* Doesn't affect the input, just puts it into an object
* @param {number} degrees - The input degrees to be converted
* @param {number} precision - The precision which the result should be rounded to
* @returns {{string: string, degrees: number}} An object containing the raw converted value (obj.degrees), and a formatted string version (obj.string)
*/
function convDDToDD (degrees, precision) {
return {
"degrees": degrees,
"string": round(degrees, precision) + "°"
};
}
/**
* Convert Decimal Degrees to Degrees Minutes Seconds
*
* @param {number} decDegrees - The input data to be converted
* @param {number} precision - The precision which the result should be rounded to
* @returns {{string: string, degrees: number, minutes: number, seconds: number}} An object containing the raw converted value as separate numbers (.degrees, .minutes, .seconds), and a formatted string version (obj.string)
*/
function convDDToDMS (decDegrees, precision) {
const absDegrees = Math.abs(decDegrees);
let degrees = Math.floor(absDegrees);
const minutes = Math.floor(60 * (absDegrees - degrees)),
seconds = round(3600 * (absDegrees - degrees) - 60 * minutes, precision);
let outString = degrees + "° " + minutes + "' " + seconds + "\"";
if (isNegativeZero(decDegrees) || decDegrees < 0) {
degrees = -degrees;
outString = "-" + outString;
}
return {
"degrees": degrees,
"minutes": minutes,
"seconds": seconds,
"string": outString
};
}
/**
* Convert Decimal Degrees to Degrees Decimal Minutes
*
* @param {number} decDegrees - The input degrees to be converted
* @param {number} precision - The precision the input data should be rounded to
* @returns {{string: string, degrees: number, minutes: number}} An object containing the raw converted value as separate numbers (.degrees, .minutes), and a formatted string version (obj.string)
*/
function convDDToDDM (decDegrees, precision) {
const absDegrees = Math.abs(decDegrees);
let degrees = Math.floor(absDegrees);
const minutes = absDegrees - degrees,
decMinutes = round(minutes * 60, precision);
let outString = degrees + "° " + decMinutes + "'";
if (decDegrees < 0 || isNegativeZero(decDegrees)) {
degrees = -degrees;
outString = "-" + outString;
}
return {
"degrees": degrees,
"minutes": decMinutes,
"string": outString,
};
}
/**
* Finds and returns the compass directions in an input string
*
* @param {string} input - The input co-ordinates containing the direction
* @param {string} delim - The delimiter separating latitide and longitude
* @returns {string[]} String array containing the latitude and longitude directions
*/
export function findDirs(input, delim) {
const upperInput = input.toUpperCase();
const dirExp = new RegExp(/[NESW]/g);
const dirs = upperInput.match(dirExp);
if (dirs) {
// If there's actually compass directions
// in the input, use these to work out the direction
if (dirs.length <= 2 && dirs.length >= 1) {
return dirs.length === 2 ? [dirs[0], dirs[1]] : [dirs[0], ""];
}
}
// Nothing was returned, so guess the directions
let lat = upperInput,
long,
latDir = "",
longDir = "";
if (!delim.includes("Direction")) {
if (upperInput.includes(delim)) {
const split = upperInput.split(delim);
if (split.length >= 1) {
if (split[0] !== "") {
lat = split[0];
}
if (split.length >= 2 && split[1] !== "") {
long = split[1];
}
}
}
} else {
const split = upperInput.split(dirExp);
if (split.length > 1) {
lat = split[0] === "" ? split[1] : split[0];
if (split.length > 2 && split[2] !== "") {
long = split[2];
}
}
}
if (lat) {
lat = parseFloat(lat);
latDir = lat < 0 ? "S" : "N";
}
if (long) {
long = parseFloat(long);
longDir = long < 0 ? "W" : "E";
}
return [latDir, longDir];
}
/**
* Detects the co-ordinate format of the input data
*
* @param {string} input - The input data whose format we need to detect
* @param {string} delim - The delimiter separating the data in input
* @returns {string} The input format
*/
export function findFormat (input, delim) {
let testData;
const mgrsPattern = new RegExp(/^[0-9]{2}\s?[C-HJ-NP-X]{1}\s?[A-HJ-NP-Z][A-HJ-NP-V]\s?[0-9\s]+/),
osngPattern = new RegExp(/^[A-HJ-Z]{2}\s+[0-9\s]+$/),
geohashPattern = new RegExp(/^[0123456789BCDEFGHJKMNPQRSTUVWXYZ]+$/),
utmPattern = new RegExp(/^[0-9]{2}\s?[C-HJ-NP-X]\s[0-9.]+\s?[0-9.]+$/),
degPattern = new RegExp(/[°'"]/g);
input = input.trim();
if (delim !== null && delim.includes("Direction")) {
const split = input.split(/[NnEeSsWw]/);
if (split.length > 1) {
testData = split[0] === "" ? split[1] : split[0];
}
} else if (delim !== null && delim !== "") {
if (input.includes(delim)) {
const split = input.split(delim);
if (split.length > 1) {
testData = split[0] === "" ? split[1] : split[0];
}
} else {
testData = input;
}
}
// Test non-degrees formats
if (!degPattern.test(input)) {
const filteredInput = input.toUpperCase().replace(delim, "");
if (utmPattern.test(filteredInput)) {
return "Universal Transverse Mercator";
}
if (mgrsPattern.test(filteredInput)) {
return "Military Grid Reference System";
}
if (osngPattern.test(filteredInput)) {
return "Ordnance Survey National Grid";
}
if (geohashPattern.test(filteredInput)) {
return "Geohash";
}
}
// Test DMS/DDM/DD formats
if (testData !== undefined) {
const split = splitInput(testData);
switch (split.length){
case 3:
return "Degrees Minutes Seconds";
case 2:
return "Degrees Decimal Minutes";
case 1:
return "Decimal Degrees";
}
}
return null;
}
/**
* Automatically find the delimeter type from the given input
*
* @param {string} input
* @returns {string} Delimiter type
*/
export function findDelim (input) {
input = input.trim();
const delims = [",", ";", ":"];
const testDir = input.match(/[NnEeSsWw]/g);
if (testDir !== null && testDir.length > 0 && testDir.length < 3) {
// Possibly contains a direction
const splitInput = input.split(/[NnEeSsWw]/);
if (splitInput.length <= 3 && splitInput.length > 0) {
// If there's 3 splits (one should be empty), then assume we have directions
if (splitInput[0] === "") {
return "Direction Preceding";
} else if (splitInput[splitInput.length - 1] === "") {
return "Direction Following";
}
}
}
// Loop through the standard delimiters, and try to find them in the input
for (let i = 0; i < delims.length; i++) {
const delim = delims[i];
if (input.includes(delim)) {
const splitInput = input.split(delim);
if (splitInput.length <= 3 && splitInput.length > 0) {
// Don't want to try and convert more than 2 co-ordinates
return delim;
}
}
}
return null;
}
/**
* Gets the real string for a delimiter name.
*
* @param {string} delim The delimiter to be matched
* @returns {string}
*/
export function realDelim (delim) {
return {
"Auto": "Auto",
"Space": " ",
"\\n": "\n",
"Comma": ",",
"Semi-colon": ";",
"Colon": ":"
}[delim];
}
/**
* Returns true if a zero is negative
*
* @param {number} zero
* @returns {boolean}
*/
function isNegativeZero(zero) {
return zero === 0 && (1/zero < 0);
}
/**
* Rounds a number to a specified number of decimal places
*
* @param {number} input - The number to be rounded
* @param {precision} precision - The number of decimal places the number should be rounded to
* @returns {number}
*/
function round(input, precision) {
precision = Math.pow(10, precision);
return Math.round(input * precision) / precision;
}

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;

230
src/core/lib/LoremIpsum.mjs Normal file
View File

@@ -0,0 +1,230 @@
/**
* Lorem Ipsum generator.
*
* @author Klaxon [klaxon@veyr.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
/**
* Generate lorem ipsum paragraphs.
*
* @param {number} length
* @returns {string}
*/
export function GenerateParagraphs(length=3) {
const paragraphs = [];
while (paragraphs.length < length) {
const paragraphLength = getRandomLength(PARAGRAPH_LENGTH_MEAN, PARAGRAPH_LENGTH_STD_DEV);
const sentences = [];
while (sentences.length < paragraphLength) {
const sentenceLength = getRandomLength(SENTENCE_LENGTH_MEAN, SENTENCE_LENGTH_STD_DEV);
const sentence = getWords(sentenceLength);
sentences.push(formatSentence(sentence));
}
paragraphs.push(formatParagraph(sentences));
}
paragraphs[paragraphs.length-1] = paragraphs[paragraphs.length-1].slice(0, -2);
paragraphs[0] = replaceStart(paragraphs[0]);
return paragraphs.join("");
}
/**
* Generate lorem ipsum sentences.
*
* @param {number} length
* @returns {string}
*/
export function GenerateSentences(length=3) {
const sentences = [];
while (sentences.length < length) {
const sentenceLength = getRandomLength(SENTENCE_LENGTH_MEAN, SENTENCE_LENGTH_STD_DEV);
const sentence = getWords(sentenceLength);
sentences.push(formatSentence(sentence));
}
const paragraphs = sentencesToParagraphs(sentences);
return paragraphs.join("");
}
/**
* Generate lorem ipsum words.
*
* @param {number} length
* @returns {string}
*/
export function GenerateWords(length=3) {
const words = getWords(length);
const sentences = wordsToSentences(words);
const paragraphs = sentencesToParagraphs(sentences);
return paragraphs.join("");
}
/**
* Generate lorem ipsum bytes.
*
* @param {number} length
* @returns {string}
*/
export function GenerateBytes(length=3) {
const str = GenerateWords(length/3);
return str.slice(0, length);
}
/**
* Get array of randomly selected words from the lorem ipsum wordList.
*
* @param {number} length
* @returns {string[]}
* @private
*/
function getWords(length=3) {
const words = [];
let word;
let previousWord;
while (words.length < length){
do {
word = wordList[Math.floor(Math.random() * wordList.length)];
} while (previousWord === word);
words.push(word);
previousWord = word;
}
return words;
}
/**
* Convert an array of words into an array of sentences
*
* @param {string[]} words
* @returns {string[]}
* @private
*/
function wordsToSentences(words) {
const sentences = [];
while (words.length > 0) {
const sentenceLength = getRandomLength(SENTENCE_LENGTH_MEAN, SENTENCE_LENGTH_STD_DEV);
if (sentenceLength <= words.length) {
sentences.push(formatSentence(words.splice(0, sentenceLength)));
} else {
sentences.push(formatSentence(words.splice(0, words.length)));
}
}
return sentences;
}
/**
* Convert an array of sentences into an array of paragraphs
*
* @param {string[]} sentences
* @returns {string[]}
* @private
*/
function sentencesToParagraphs(sentences) {
const paragraphs = [];
while (sentences.length > 0) {
const paragraphLength = getRandomLength(PARAGRAPH_LENGTH_MEAN, PARAGRAPH_LENGTH_STD_DEV);
paragraphs.push(formatParagraph(sentences.splice(0, paragraphLength)));
}
paragraphs[paragraphs.length-1] = paragraphs[paragraphs.length-1].slice(0, -1);
paragraphs[0] = replaceStart(paragraphs[0]);
return paragraphs;
}
/**
* Format an array of words into a sentence.
*
* @param {string[]} words
* @returns {string}
* @private
*/
function formatSentence(words) {
// 0.35 chance of a comma being added randomly to the sentence.
if (Math.random() < PROBABILITY_OF_A_COMMA) {
const pos = Math.round(Math.random()*(words.length-1));
words[pos] +=",";
}
let sentence = words.join(" ");
sentence = sentence.charAt(0).toUpperCase() + sentence.slice(1);
sentence += ".";
return sentence;
}
/**
* Format an array of sentences into a paragraph.
*
* @param {string[]} sentences
* @returns {string}
* @private
*/
function formatParagraph(sentences) {
let paragraph = sentences.join(" ");
paragraph += "\n\n";
return paragraph;
}
/**
* Get a random number based on a mean and standard deviation.
*
* @param {number} mean
* @param {number} stdDev
* @returns {number}
* @private
*/
function getRandomLength(mean, stdDev) {
let length;
do {
length = Math.round((Math.random()*2-1)+(Math.random()*2-1)+(Math.random()*2-1)*stdDev+mean);
} while (length <= 0);
return length;
}
/**
* Replace first 5 words with "Lorem ipsum dolor sit amet"
*
* @param {string[]} str
* @returns {string[]}
* @private
*/
function replaceStart(str) {
let words = str.split(" ");
if (words.length > 5) {
words.splice(0, 5, "Lorem", "ipsum", "dolor", "sit", "amet");
return words.join(" ");
} else {
const lorem = ["Lorem", "ipsum", "dolor", "sit", "amet"];
words = lorem.slice(0, words.length);
str = words.join(" ");
str += ".";
return str;
}
}
const SENTENCE_LENGTH_MEAN = 15;
const SENTENCE_LENGTH_STD_DEV = 9;
const PARAGRAPH_LENGTH_MEAN = 5;
const PARAGRAPH_LENGTH_STD_DEV = 2;
const PROBABILITY_OF_A_COMMA = 0.35;
const wordList = [
"ad", "adipisicing", "aliqua", "aliquip", "amet", "anim",
"aute", "cillum", "commodo", "consectetur", "consequat", "culpa",
"cupidatat", "deserunt", "do", "dolor", "dolore", "duis",
"ea", "eiusmod", "elit", "enim", "esse", "est",
"et", "eu", "ex", "excepteur", "exercitation", "fugiat",
"id", "in", "incididunt", "ipsum", "irure", "labore",
"laboris", "laborum", "Lorem", "magna", "minim", "mollit",
"nisi", "non", "nostrud", "nulla", "occaecat", "officia",
"pariatur", "proident", "qui", "quis", "reprehenderit", "sint",
"sit", "sunt", "tempor", "ullamco", "ut", "velit",
"veniam", "voluptate",
];

View File

@@ -265,9 +265,10 @@ class Magic {
* performance)
* @param {Object[]} [recipeConfig=[]] - The recipe configuration up to this point
* @param {boolean} [useful=false] - Whether the current recipe should be scored highly
* @param {string} [crib=null] - The regex crib provided by the user, for filtering the operation output
* @returns {Object[]} - A sorted list of the recipes most likely to result in correct decoding
*/
async speculativeExecution(depth=0, extLang=false, intensive=false, recipeConfig=[], useful=false) {
async speculativeExecution(depth=0, extLang=false, intensive=false, recipeConfig=[], useful=false, crib=null) {
if (depth < 0) return [];
// Find any operations that can be run on this data
@@ -284,9 +285,9 @@ class Magic {
isUTF8: this.isUTF8(),
entropy: this.calcEntropy(),
matchingOps: matchingOps,
useful: useful
useful: useful,
matchesCrib: crib && crib.test(this.inputStr)
});
const prevOp = recipeConfig[recipeConfig.length - 1];
// Execute each of the matching operations, then recursively call the speculativeExecution()
@@ -305,7 +306,7 @@ class Magic {
const magic = new Magic(output, this.opPatterns),
speculativeResults = await magic.speculativeExecution(
depth-1, extLang, intensive, [...recipeConfig, opConfig], op.useful);
depth-1, extLang, intensive, [...recipeConfig, opConfig], op.useful, crib);
results = results.concat(speculativeResults);
}));
@@ -317,7 +318,7 @@ class Magic {
await Promise.all(bfEncodings.map(async enc => {
const magic = new Magic(enc.data, this.opPatterns),
bfResults = await magic.speculativeExecution(
depth-1, extLang, false, [...recipeConfig, enc.conf]);
depth-1, extLang, false, [...recipeConfig, enc.conf], false, crib);
results = results.concat(bfResults);
}));

View File

@@ -0,0 +1,63 @@
/**
* @author Jarmo van Lenthe [github.com/jarmovanlenthe]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import Utils from "../Utils";
import {DELIM_OPTIONS} from "../lib/Delim";
import OperationError from "../errors/OperationError";
/**
* A1Z26 Cipher Decode operation
*/
class A1Z26CipherDecode extends Operation {
/**
* A1Z26CipherDecode constructor
*/
constructor() {
super();
this.name = "A1Z26 Cipher Decode";
this.module = "Ciphers";
this.description = "Converts alphabet order numbers into their corresponding alphabet character.<br><br>e.g. <code>1</code> becomes <code>a</code> and <code>2</code> becomes <code>b</code>.";
this.infoURL = "";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Delimiter",
type: "option",
value: DELIM_OPTIONS
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const delim = Utils.charRep(args[0] || "Space");
if (input.length === 0) {
return [];
}
const bites = input.split(delim);
let latin1 = "";
for (let i = 0; i < bites.length; i++) {
if (bites[i] < 1 || bites[i] > 26) {
throw new OperationError("Error: all numbers must be between 1 and 26.");
}
latin1 += Utils.chr(parseInt(bites[i], 10) + 96);
}
return latin1;
}
}
export default A1Z26CipherDecode;

View File

@@ -0,0 +1,61 @@
/**
* @author Jarmo van Lenthe [github.com/jarmovanlenthe]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import Utils from "../Utils";
import {DELIM_OPTIONS} from "../lib/Delim";
/**
* A1Z26 Cipher Encode operation
*/
class A1Z26CipherEncode extends Operation {
/**
* A1Z26CipherEncode constructor
*/
constructor() {
super();
this.name = "A1Z26 Cipher Encode";
this.module = "Ciphers";
this.description = "Converts alphabet characters into their corresponding alphabet order number.<br><br>e.g. <code>a</code> becomes <code>1</code> and <code>b</code> becomes <code>2</code>.<br><br>Non-alphabet characters are dropped.";
this.infoURL = "";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Delimiter",
type: "option",
value: DELIM_OPTIONS
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const delim = Utils.charRep(args[0] || "Space");
let output = "";
const sanitizedinput = input.toLowerCase(),
charcode = Utils.strToCharcode(sanitizedinput);
for (let i = 0; i < charcode.length; i++) {
const ordinal = charcode[i] - 96;
if (ordinal > 0 && ordinal <= 26) {
output += ordinal.toString(10) + delim;
}
}
return output.slice(0, -delim.length);
}
}
export default A1Z26CipherEncode;

View File

@@ -6,7 +6,7 @@
import Operation from "../Operation";
import Utils from "../Utils";
import { bitOp, add } from "../lib/BitwiseOp";
import { bitOp, add, BITWISE_OP_DELIMS } from "../lib/BitwiseOp";
/**
* ADD operation
@@ -30,7 +30,7 @@ class ADD extends Operation {
"name": "Key",
"type": "toggleString",
"value": "",
"toggleValues": ["Hex", "Decimal", "Base64", "UTF8", "Latin1"]
"toggleValues": BITWISE_OP_DELIMS
}
];
}

View File

@@ -6,7 +6,7 @@
import Operation from "../Operation";
import Utils from "../Utils";
import { bitOp, and } from "../lib/BitwiseOp";
import { bitOp, and, BITWISE_OP_DELIMS } from "../lib/BitwiseOp";
/**
* AND operation
@@ -30,7 +30,7 @@ class AND extends Operation {
"name": "Key",
"type": "toggleString",
"value": "",
"toggleValues": ["Hex", "Decimal", "Base64", "UTF8", "Latin1"]
"toggleValues": BITWISE_OP_DELIMS
}
];
}

View File

@@ -19,7 +19,7 @@ class Adler32Checksum extends Operation {
super();
this.name = "Adler-32 Checksum";
this.module = "Hashing";
this.module = "Crypto";
this.description = "Adler-32 is a checksum algorithm which was invented by Mark Adler in 1995, and is a modification of the Fletcher checksum. Compared to a cyclic redundancy check of the same length, it trades reliability for speed (preferring the latter).<br><br>Adler-32 is more reliable than Fletcher-16, and slightly less reliable than Fletcher-32.";
this.infoURL = "https://wikipedia.org/wiki/Adler-32";
this.inputType = "byteArray";

View File

@@ -19,7 +19,7 @@ class AnalyseHash extends Operation {
super();
this.name = "Analyse hash";
this.module = "Hashing";
this.module = "Crypto";
this.description = "Tries to determine information about a given hash and suggests which algorithm may have been used to generate it based on its length.";
this.infoURL = "https://wikipedia.org/wiki/Comparison_of_cryptographic_hash_functions";
this.inputType = "string";

View File

@@ -5,7 +5,7 @@
*/
import Operation from "../Operation";
import bsonjs from "bson";
import bson from "bson";
import OperationError from "../errors/OperationError";
/**
@@ -36,8 +36,6 @@ class BSONDeserialise extends Operation {
run(input, args) {
if (!input.byteLength) return "";
const bson = new bsonjs();
try {
const data = bson.deserialize(new Buffer(input));
return JSON.stringify(data, null, 2);

View File

@@ -5,7 +5,7 @@
*/
import Operation from "../Operation";
import bsonjs from "bson";
import bson from "bson";
import OperationError from "../errors/OperationError";
/**
@@ -36,8 +36,6 @@ class BSONSerialise extends Operation {
run(input, args) {
if (!input) return new ArrayBuffer();
const bson = new bsonjs();
try {
const data = JSON.parse(input);
return bson.serialize(data).buffer;

View File

@@ -19,7 +19,7 @@ class Bcrypt extends Operation {
super();
this.name = "Bcrypt";
this.module = "Hashing";
this.module = "Crypto";
this.description = "bcrypt is a password hashing function designed by Niels Provos and David Mazi\xe8res, based on the Blowfish cipher, and presented at USENIX in 1999. Besides incorporating a salt to protect against rainbow table attacks, bcrypt is an adaptive function: over time, the iteration count (rounds) can be increased to make it slower, so it remains resistant to brute-force search attacks even with increasing computation power.<br><br>Enter the password in the input to generate its hash.";
this.infoURL = "https://wikipedia.org/wiki/Bcrypt";
this.inputType = "string";

View File

@@ -19,7 +19,7 @@ class BcryptCompare extends Operation {
super();
this.name = "Bcrypt compare";
this.module = "Hashing";
this.module = "Crypto";
this.description = "Tests whether the input matches the given bcrypt hash. To test multiple possible passwords, use the 'Fork' operation.";
this.infoURL = "https://wikipedia.org/wiki/Bcrypt";
this.inputType = "string";

View File

@@ -20,7 +20,7 @@ class BcryptParse extends Operation {
super();
this.name = "Bcrypt parse";
this.module = "Hashing";
this.module = "Crypto";
this.description = "Parses a bcrypt hash to determine the number of rounds used, the salt, and the password hash.";
this.infoURL = "https://wikipedia.org/wiki/Bcrypt";
this.inputType = "string";

View File

@@ -19,7 +19,7 @@ class CRC16Checksum extends Operation {
super();
this.name = "CRC-16 Checksum";
this.module = "Hashing";
this.module = "Crypto";
this.description = "A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data.<br><br>The CRC was invented by W. Wesley Peterson in 1961.";
this.infoURL = "https://wikipedia.org/wiki/Cyclic_redundancy_check";
this.inputType = "ArrayBuffer";

View File

@@ -19,7 +19,7 @@ class CRC32Checksum extends Operation {
super();
this.name = "CRC-32 Checksum";
this.module = "Hashing";
this.module = "Crypto";
this.description = "A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data.<br><br>The CRC was invented by W. Wesley Peterson in 1961; the 32-bit CRC function of Ethernet and many other standards is the work of several researchers and was published in 1975.";
this.infoURL = "https://wikipedia.org/wiki/Cyclic_redundancy_check";
this.inputType = "ArrayBuffer";

View File

@@ -0,0 +1,80 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Utils from "../Utils";
/**
* CSV to JSON operation
*/
class CSVToJSON extends Operation {
/**
* CSVToJSON constructor
*/
constructor() {
super();
this.name = "CSV to JSON";
this.module = "Default";
this.description = "Converts a CSV file to JSON format.";
this.infoURL = "https://wikipedia.org/wiki/Comma-separated_values";
this.inputType = "string";
this.outputType = "JSON";
this.args = [
{
name: "Cell delimiters",
type: "binaryShortString",
value: ","
},
{
name: "Row delimiters",
type: "binaryShortString",
value: "\\r\\n"
},
{
name: "Format",
type: "option",
value: ["Array of dictionaries", "Array of arrays"]
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {JSON}
*/
run(input, args) {
const [cellDelims, rowDelims, format] = args;
let json, header;
try {
json = Utils.parseCSV(input, cellDelims.split(""), rowDelims.split(""));
} catch (err) {
throw new OperationError("Unable to parse CSV: " + err);
}
switch (format) {
case "Array of dictionaries":
header = json[0];
return json.slice(1).map(row => {
const obj = {};
header.forEach((h, i) => {
obj[h] = row[i];
});
return obj;
});
case "Array of arrays":
default:
return json;
}
}
}
export default CSVToJSON;

View File

@@ -19,7 +19,7 @@ class CTPH extends Operation {
super();
this.name = "CTPH";
this.module = "Hashing";
this.module = "Crypto";
this.description = "Context Triggered Piecewise Hashing, also called Fuzzy Hashing, can match inputs that have homologies. Such inputs have sequences of identical bytes in the same order, although bytes in between these sequences may be different in both content and length.<br><br>CTPH was originally based on the work of Dr. Andrew Tridgell and a spam email detector called SpamSum. This method was adapted by Jesse Kornblum and published at the DFRWS conference in 2006 in a paper 'Identifying Almost Identical Files Using Context Triggered Piecewise Hashing'.";
this.infoURL = "https://forensicswiki.org/wiki/Context_Triggered_Piecewise_Hashing";
this.inputType = "string";

View File

@@ -0,0 +1,58 @@
/**
* @author bwhitn [brian.m.whitney@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import cptable from "../vendor/js-codepage/cptable.js";
/**
* Citrix CTX1 Decode operation
*/
class CitrixCTX1Decode extends Operation {
/**
* CitrixCTX1Decode constructor
*/
constructor() {
super();
this.name = "Citrix CTX1 Decode";
this.module = "Encodings";
this.description = "Decodes strings in a Citrix CTX1 password format to plaintext.";
this.infoURL = "https://www.reddit.com/r/AskNetsec/comments/1s3r6y/citrix_ctx1_hash_decoding/";
this.inputType = "byteArray";
this.outputType = "string";
this.args = [];
}
/**
* @param {byteArray} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
if (input.length % 4 !== 0) {
throw new OperationError("Incorrect hash length");
}
const revinput = input.reverse();
const result = [];
let temp = 0;
for (let i = 0; i < revinput.length; i += 2) {
if (i + 2 >= revinput.length) {
temp = 0;
} else {
temp = ((revinput[i + 2] - 0x41) & 0xf) ^ (((revinput[i + 3]- 0x41) << 4) & 0xf0);
}
temp = (((revinput[i] - 0x41) & 0xf) ^ (((revinput[i + 1] - 0x41) << 4) & 0xf0)) ^ 0xa5 ^ temp;
result.push(temp);
}
// Decodes a utf-16le string
return cptable.utils.decode(1200, result.reverse());
}
}
export default CitrixCTX1Decode;

View File

@@ -0,0 +1,50 @@
/**
* @author bwhitn [brian.m.whitney@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import cptable from "../vendor/js-codepage/cptable.js";
/**
* Citrix CTX1 Encode operation
*/
class CitrixCTX1Encode extends Operation {
/**
* CitrixCTX1Encode constructor
*/
constructor() {
super();
this.name = "Citrix CTX1 Encode";
this.module = "Encodings";
this.description = "Encodes strings to Citrix CTX1 password format.";
this.infoURL = "https://www.reddit.com/r/AskNetsec/comments/1s3r6y/citrix_ctx1_hash_decoding/";
this.inputType = "string";
this.outputType = "byteArray";
this.args = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {byteArray}
*/
run(input, args) {
const utf16pass = Array.from(cptable.utils.encode(1200, input));
const result = [];
let temp = 0;
for (let i = 0; i < utf16pass.length; i++) {
temp = utf16pass[i] ^ 0xa5 ^ temp;
result.push(((temp >>> 4) & 0xf) + 0x41);
result.push((temp & 0xf) + 0x41);
}
return result;
}
}
export default CitrixCTX1Encode;

View File

@@ -22,7 +22,7 @@ class CompareCTPHHashes extends Operation {
super();
this.name = "Compare CTPH hashes";
this.module = "Hashing";
this.module = "Crypto";
this.description = "Compares two Context Triggered Piecewise Hashing (CTPH) fuzzy hashes to determine the similarity between them on a scale of 0 to 100.";
this.infoURL = "https://forensicswiki.org/wiki/Context_Triggered_Piecewise_Hashing";
this.inputType = "string";

View File

@@ -22,7 +22,7 @@ class CompareSSDEEPHashes extends Operation {
super();
this.name = "Compare SSDEEP hashes";
this.module = "Hashing";
this.module = "Crypto";
this.description = "Compares two SSDEEP fuzzy hashes to determine the similarity between them on a scale of 0 to 100.";
this.infoURL = "https://forensicswiki.org/wiki/Ssdeep";
this.inputType = "string";

View File

@@ -0,0 +1,95 @@
/**
* @author j433866 [j433866@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation";
import {FORMATS, convertCoordinates} from "../lib/ConvertCoordinates";
/**
* Convert co-ordinate format operation
*/
class ConvertCoordinateFormat extends Operation {
/**
* ConvertCoordinateFormat constructor
*/
constructor() {
super();
this.name = "Convert co-ordinate format";
this.module = "Hashing";
this.description = "Converts geographical coordinates between different formats.<br><br>Supported formats:<ul><li>Degrees Minutes Seconds (DMS)</li><li>Degrees Decimal Minutes (DDM)</li><li>Decimal Degrees (DD)</li><li>Geohash</li><li>Military Grid Reference System (MGRS)</li><li>Ordnance Survey National Grid (OSNG)</li><li>Universal Transverse Mercator (UTM)</li></ul><br>The operation can try to detect the input co-ordinate format and delimiter automatically, but this may not always work correctly.";
this.infoURL = "https://wikipedia.org/wiki/Geographic_coordinate_conversion";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
"name": "Input Format",
"type": "option",
"value": ["Auto"].concat(FORMATS)
},
{
"name": "Input Delimiter",
"type": "option",
"value": [
"Auto",
"Direction Preceding",
"Direction Following",
"\\n",
"Comma",
"Semi-colon",
"Colon"
]
},
{
"name": "Output Format",
"type": "option",
"value": FORMATS
},
{
"name": "Output Delimiter",
"type": "option",
"value": [
"Space",
"\\n",
"Comma",
"Semi-colon",
"Colon"
]
},
{
"name": "Include Compass Directions",
"type": "option",
"value": [
"None",
"Before",
"After"
]
},
{
"name": "Precision",
"type": "number",
"value": 3
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
if (input.replace(/[\s+]/g, "") !== "") {
const [inFormat, inDelim, outFormat, outDelim, incDirection, precision] = args;
const result = convertCoordinates(input, inFormat, inDelim, outFormat, outDelim, incDirection, precision);
return result;
} else {
return input;
}
}
}
export default ConvertCoordinateFormat;

View File

@@ -0,0 +1,125 @@
/**
* @author h345983745
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
/**
* DNS over HTTPS operation
*/
class DNSOverHTTPS extends Operation {
/**
* DNSOverHTTPS constructor
*/
constructor() {
super();
this.name = "DNS over HTTPS";
this.module = "Default";
this.description = [
"Takes a single domain name and performs a DNS lookup using DNS over HTTPS.",
"<br><br>",
"By default, <a href='https://developers.cloudflare.com/1.1.1.1/dns-over-https/'>Cloudflare</a> and <a href='https://developers.google.com/speed/public-dns/docs/dns-over-https'>Google</a> DNS over HTTPS services are supported.",
"<br><br>",
"Can be used with any service that supports the GET parameters <code>name</code> and <code>type</code>."
].join("\n");
this.infoURL = "https://wikipedia.org/wiki/DNS_over_HTTPS";
this.inputType = "string";
this.outputType = "JSON";
this.manualBake = true;
this.args = [
{
name: "Resolver",
type: "editableOption",
value: [
{
name: "Google",
value: "https://dns.google.com/resolve"
},
{
name: "Cloudflare",
value: "https://cloudflare-dns.com/dns-query"
}
]
},
{
name: "Request Type",
type: "option",
value: [
"A",
"AAAA",
"TXT",
"MX",
"DNSKEY",
"NS"
]
},
{
name: "Answer Data Only",
type: "boolean",
value: false
},
{
name: "Validate DNSSEC",
type: "boolean",
value: true
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {JSON}
*/
run(input, args) {
const [resolver, requestType, justAnswer, DNSSEC] = args;
let url = URL;
try {
url = new URL(resolver);
} catch (error) {
throw new OperationError(error.toString() +
"\n\nThis error could be caused by one of the following:\n" +
" - An invalid Resolver URL\n");
}
const params = {name: input, type: requestType, cd: DNSSEC};
url.search = new URLSearchParams(params);
return fetch(url, {headers: {"accept": "application/dns-json"}}).then(response => {
return response.json();
}).then(data => {
if (justAnswer) {
return extractData(data.Answer);
}
return data;
}).catch(e => {
throw new OperationError(`Error making request to ${url}\n${e.toString()}`);
});
}
}
/**
* Construct an array of just data from a DNS Answer section
*
* @private
* @param {JSON} data
* @returns {JSON}
*/
function extractData(data) {
if (typeof(data) == "undefined"){
return [];
} else {
const dataValues = [];
data.forEach(element => {
dataValues.push(element.data);
});
return dataValues;
}
}
export default DNSOverHTTPS;

View File

@@ -20,7 +20,7 @@ class DecodeText extends Operation {
super();
this.name = "Decode text";
this.module = "CharEnc";
this.module = "Encodings";
this.description = [
"Decodes text from the chosen character encoding.",
"<br><br>",

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

@@ -43,7 +43,7 @@ class Divide extends Operation {
*/
run(input, args) {
const val = div(createNumArray(input, args[0]));
return val instanceof BigNumber ? val : new BigNumber(NaN);
return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN);
}
}

View File

@@ -20,7 +20,7 @@ class EncodeText extends Operation {
super();
this.name = "Encode text";
this.module = "CharEnc";
this.module = "Encodings";
this.description = [
"Encodes text into the chosen character encoding.",
"<br><br>",

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

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

@@ -19,7 +19,7 @@ class Fletcher16Checksum extends Operation {
super();
this.name = "Fletcher-16 Checksum";
this.module = "Hashing";
this.module = "Crypto";
this.description = "The Fletcher checksum is an algorithm for computing a position-dependent checksum devised by John Gould Fletcher at Lawrence Livermore Labs in the late 1970s.<br><br>The objective of the Fletcher checksum was to provide error-detection properties approaching those of a cyclic redundancy check but with the lower computational effort associated with summation techniques.";
this.infoURL = "https://wikipedia.org/wiki/Fletcher%27s_checksum#Fletcher-16";
this.inputType = "byteArray";

View File

@@ -19,7 +19,7 @@ class Fletcher32Checksum extends Operation {
super();
this.name = "Fletcher-32 Checksum";
this.module = "Hashing";
this.module = "Crypto";
this.description = "The Fletcher checksum is an algorithm for computing a position-dependent checksum devised by John Gould Fletcher at Lawrence Livermore Labs in the late 1970s.<br><br>The objective of the Fletcher checksum was to provide error-detection properties approaching those of a cyclic redundancy check but with the lower computational effort associated with summation techniques.";
this.infoURL = "https://wikipedia.org/wiki/Fletcher%27s_checksum#Fletcher-32";
this.inputType = "byteArray";

View File

@@ -19,7 +19,7 @@ class Fletcher64Checksum extends Operation {
super();
this.name = "Fletcher-64 Checksum";
this.module = "Hashing";
this.module = "Crypto";
this.description = "The Fletcher checksum is an algorithm for computing a position-dependent checksum devised by John Gould Fletcher at Lawrence Livermore Labs in the late 1970s.<br><br>The objective of the Fletcher checksum was to provide error-detection properties approaching those of a cyclic redundancy check but with the lower computational effort associated with summation techniques.";
this.infoURL = "https://wikipedia.org/wiki/Fletcher%27s_checksum#Fletcher-64";
this.inputType = "byteArray";

View File

@@ -19,7 +19,7 @@ class Fletcher8Checksum extends Operation {
super();
this.name = "Fletcher-8 Checksum";
this.module = "Hashing";
this.module = "Crypto";
this.description = "The Fletcher checksum is an algorithm for computing a position-dependent checksum devised by John Gould Fletcher at Lawrence Livermore Labs in the late 1970s.<br><br>The objective of the Fletcher checksum was to provide error-detection properties approaching those of a cyclic redundancy check but with the lower computational effort associated with summation techniques.";
this.infoURL = "https://wikipedia.org/wiki/Fletcher%27s_checksum";
this.inputType = "byteArray";

View File

@@ -0,0 +1,58 @@
/**
* @author tcode2k16 [tcode2k16@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import BigNumber from "bignumber.js";
import Utils from "../Utils";
/**
* From Base62 operation
*/
class FromBase62 extends Operation {
/**
* FromBase62 constructor
*/
constructor() {
super();
this.name = "From Base62";
this.module = "Default";
this.description = "Base62 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers. The high number base results in shorter strings than with the decimal or hexadecimal system.";
this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems";
this.inputType = "string";
this.outputType = "byteArray";
this.args = [
{
name: "Alphabet",
type: "string",
value: "0-9A-Za-z"
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {byteArray}
*/
run(input, args) {
if (input.length < 1) return [];
const ALPHABET = Utils.expandAlphRange(args[0]).join("");
const BN = BigNumber.clone({ ALPHABET });
const re = new RegExp("[^" + ALPHABET.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
input = input.replace(re, "");
const number = new BN(input, 62);
return Utils.convertToByteArray(number.toString(16), "Hex");
}
}
export default FromBase62;

View File

@@ -38,44 +38,44 @@ class FromBase64 extends Operation {
];
this.patterns = [
{
match: "^(?:[A-Z\\d+/]{4})+(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?$",
match: "^\\s*(?:[A-Z\\d+/]{4})+(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?\\s*$",
flags: "i",
args: ["A-Za-z0-9+/=", false]
args: ["A-Za-z0-9+/=", true]
},
{
match: "^[A-Z\\d\\-_]{20,}$",
match: "^\\s*[A-Z\\d\\-_]{20,}\\s*$",
flags: "i",
args: ["A-Za-z0-9-_", false]
args: ["A-Za-z0-9-_", true]
},
{
match: "^(?:[A-Z\\d+\\-]{4}){5,}(?:[A-Z\\d+\\-]{2}==|[A-Z\\d+\\-]{3}=)?$",
match: "^\\s*(?:[A-Z\\d+\\-]{4}){5,}(?:[A-Z\\d+\\-]{2}==|[A-Z\\d+\\-]{3}=)?\\s*$",
flags: "i",
args: ["A-Za-z0-9+\\-=", false]
args: ["A-Za-z0-9+\\-=", true]
},
{
match: "^(?:[A-Z\\d./]{4}){5,}(?:[A-Z\\d./]{2}==|[A-Z\\d./]{3}=)?$",
match: "^\\s*(?:[A-Z\\d./]{4}){5,}(?:[A-Z\\d./]{2}==|[A-Z\\d./]{3}=)?\\s*$",
flags: "i",
args: ["./0-9A-Za-z=", false]
args: ["./0-9A-Za-z=", true]
},
{
match: "^[A-Z\\d_.]{20,}$",
match: "^\\s*[A-Z\\d_.]{20,}\\s*$",
flags: "i",
args: ["A-Za-z0-9_.", false]
args: ["A-Za-z0-9_.", true]
},
{
match: "^(?:[A-Z\\d._]{4}){5,}(?:[A-Z\\d._]{2}--|[A-Z\\d._]{3}-)?$",
match: "^\\s*(?:[A-Z\\d._]{4}){5,}(?:[A-Z\\d._]{2}--|[A-Z\\d._]{3}-)?\\s*$",
flags: "i",
args: ["A-Za-z0-9._-", false]
args: ["A-Za-z0-9._-", true]
},
{
match: "^(?:[A-Z\\d+/]{4}){5,}(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?$",
match: "^\\s*(?:[A-Z\\d+/]{4}){5,}(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?\\s*$",
flags: "i",
args: ["0-9a-zA-Z+/=", false]
args: ["0-9a-zA-Z+/=", true]
},
{
match: "^(?:[A-Z\\d+/]{4}){5,}(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?$",
match: "^\\s*(?:[A-Z\\d+/]{4}){5,}(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?\\s*$",
flags: "i",
args: ["0-9A-Za-z+/=", false]
args: ["0-9A-Za-z+/=", true]
},
{
match: "^[ !\"#$%&'()*+,\\-./\\d:;<=>?@A-Z[\\\\\\]^_]{20,}$",
@@ -83,24 +83,24 @@ class FromBase64 extends Operation {
args: [" -_", false]
},
{
match: "^[A-Z\\d+\\-]{20,}$",
match: "^\\s*[A-Z\\d+\\-]{20,}\\s*$",
flags: "i",
args: ["+\\-0-9A-Za-z", false]
args: ["+\\-0-9A-Za-z", true]
},
{
match: "^[!\"#$%&'()*+,\\-0-689@A-NP-VX-Z[`a-fh-mp-r]{20,}$",
match: "^\\s*[!\"#$%&'()*+,\\-0-689@A-NP-VX-Z[`a-fh-mp-r]{20,}\\s*$",
flags: "",
args: ["!-,-0-689@A-NP-VX-Z[`a-fh-mp-r", false]
args: ["!-,-0-689@A-NP-VX-Z[`a-fh-mp-r", true]
},
{
match: "^(?:[N-ZA-M\\d+/]{4}){5,}(?:[N-ZA-M\\d+/]{2}==|[N-ZA-M\\d+/]{3}=)?$",
match: "^\\s*(?:[N-ZA-M\\d+/]{4}){5,}(?:[N-ZA-M\\d+/]{2}==|[N-ZA-M\\d+/]{3}=)?\\s*$",
flags: "i",
args: ["N-ZA-Mn-za-m0-9+/=", false]
args: ["N-ZA-Mn-za-m0-9+/=", true]
},
{
match: "^[A-Z\\d./]{20,}$",
match: "^\\s*[A-Z\\d./]{20,}\\s*$",
flags: "i",
args: ["./0-9A-Za-z", false]
args: ["./0-9A-Za-z", true]
},
];
}

View File

@@ -7,6 +7,7 @@
import Operation from "../Operation";
import Utils from "../Utils";
import {BIN_DELIM_OPTIONS} from "../lib/Delim";
import {fromBinary} from "../lib/Binary";
/**
* From Binary operation
@@ -77,15 +78,7 @@ class FromBinary extends Operation {
* @returns {byteArray}
*/
run(input, args) {
const delimRegex = Utils.regexRep(args[0] || "Space");
input = input.replace(delimRegex, "");
const output = [];
const byteLen = 8;
for (let i = 0; i < input.length; i += byteLen) {
output.push(parseInt(input.substr(i, byteLen), 2));
}
return output;
return fromBinary(input, args[0]);
}
/**

View File

@@ -0,0 +1,39 @@
/**
* @author masq [github.cyberchef@masq.cc]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
/**
* From Case Insensitive Regex operation
*/
class FromCaseInsensitiveRegex extends Operation {
/**
* FromCaseInsensitiveRegex constructor
*/
constructor() {
super();
this.name = "From Case Insensitive Regex";
this.module = "Default";
this.description = "Converts a case-insensitive regex string to a case sensitive regex string (no guarantee on it being the proper original casing) in case the i flag wasn't available at the time but now is, or you need it to be case-sensitive again.<br><br>e.g. <code>[mM][oO][zZ][iI][lL][lL][aA]/[0-9].[0-9] .*</code> becomes <code>Mozilla/[0-9].[0-9] .*</code>";
this.infoURL = "https://wikipedia.org/wiki/Regular_expression";
this.inputType = "string";
this.outputType = "string";
this.args = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
return input.replace(/\[[a-z]{2}\]/ig, m => m[1].toUpperCase() === m[2].toUpperCase() ? m[1] : m);
}
}
export default FromCaseInsensitiveRegex;

View File

@@ -29,38 +29,43 @@ class FromDecimal extends Operation {
"name": "Delimiter",
"type": "option",
"value": DELIM_OPTIONS
},
{
"name": "Support signed values",
"type": "boolean",
"value": false
}
];
this.patterns = [
{
match: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?: (?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$",
flags: "",
args: ["Space"]
args: ["Space", false]
},
{
match: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?:,(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$",
flags: "",
args: ["Comma"]
args: ["Comma", false]
},
{
match: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?:;(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$",
flags: "",
args: ["Semi-colon"]
args: ["Semi-colon", false]
},
{
match: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?::(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$",
flags: "",
args: ["Colon"]
args: ["Colon", false]
},
{
match: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?:\\n(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$",
flags: "",
args: ["Line feed"]
args: ["Line feed", false]
},
{
match: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?:\\r\\n(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$",
flags: "",
args: ["CRLF"]
args: ["CRLF", false]
},
];
}
@@ -71,7 +76,11 @@ class FromDecimal extends Operation {
* @returns {byteArray}
*/
run(input, args) {
return fromDecimal(input, args[0]);
let data = fromDecimal(input, args[0]);
if (args[1]) { // Convert negatives
data = data.map(v => v < 0 ? 0xFF + v + 1 : v);
}
return data;
}
}

View File

@@ -1,44 +0,0 @@
/**
* @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

@@ -30,7 +30,7 @@ class FromQuotedPrintable extends Operation {
this.args = [];
this.patterns = [
{
match: "^[\\x21-\\x3d\\x3f-\\x7e \\t]*(?:=[\\da-f]{2}|=\\r?\\n)(?:[\\x21-\\x3d\\x3f-\\x7e \\t]|=[\\da-f]{2}|=\\r?\\n)*$",
match: "^[\\x21-\\x3d\\x3f-\\x7e \\t]{0,76}(?:=[\\da-f]{2}|=\\r?\\n)(?:[\\x21-\\x3d\\x3f-\\x7e \\t]|=[\\da-f]{2}|=\\r?\\n)*$",
flags: "i",
args: []
},

View File

@@ -41,7 +41,7 @@ class GenerateAllHashes extends Operation {
super();
this.name = "Generate all hashes";
this.module = "Hashing";
this.module = "Crypto";
this.description = "Generates all available hashes and checksums for the input.";
this.infoURL = "https://wikipedia.org/wiki/Comparison_of_cryptographic_hash_functions";
this.inputType = "ArrayBuffer";

View File

@@ -0,0 +1,70 @@
/**
* @author klaxon [klaxon@veyr.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import { GenerateParagraphs, GenerateSentences, GenerateWords, GenerateBytes } from "../lib/LoremIpsum";
/**
* Generate Lorem Ipsum operation
*/
class GenerateLoremIpsum extends Operation {
/**
* GenerateLoremIpsum constructor
*/
constructor() {
super();
this.name = "Generate Lorem Ipsum";
this.module = "Default";
this.description = "Generate varying length lorem ipsum placeholder text.";
this.infoURL = "https://wikipedia.org/wiki/Lorem_ipsum";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
"name": "Length",
"type": "number",
"value": "3"
},
{
"name": "Length in",
"type": "option",
"value": ["Paragraphs", "Sentences", "Words", "Bytes"]
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const [length, lengthType] = args;
if (length < 1){
throw new OperationError("Length must be greater than 0");
}
switch (lengthType) {
case "Paragraphs":
return GenerateParagraphs(length);
case "Sentences":
return GenerateSentences(length);
case "Words":
return GenerateWords(length);
case "Bytes":
return GenerateBytes(length);
default:
throw new OperationError("Invalid length type");
}
}
}
export default GenerateLoremIpsum;

View File

@@ -0,0 +1,119 @@
/**
* @author j433866 [j433866@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import qr from "qr-image";
import { toBase64 } from "../lib/Base64";
import Magic from "../lib/Magic";
import Utils from "../Utils";
/**
* Generate QR Code operation
*/
class GenerateQRCode extends Operation {
/**
* GenerateQRCode constructor
*/
constructor() {
super();
this.name = "Generate QR Code";
this.module = "Image";
this.description = "Generates a Quick Response (QR) code from the input text.<br><br>A QR code is a type of matrix barcode (or two-dimensional barcode) first designed in 1994 for the automotive industry in Japan. A barcode is a machine-readable optical label that contains information about the item to which it is attached.";
this.infoURL = "https://wikipedia.org/wiki/QR_code";
this.inputType = "string";
this.outputType = "byteArray";
this.presentType = "html";
this.args = [
{
"name": "Image Format",
"type": "option",
"value": ["PNG", "SVG", "EPS", "PDF"]
},
{
"name": "Module size (px)",
"type": "number",
"value": 5
},
{
"name": "Margin (num modules)",
"type": "number",
"value": 2
},
{
"name": "Error correction",
"type": "option",
"value": ["Low", "Medium", "Quartile", "High"],
"defaultIndex": 1
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {byteArray}
*/
run(input, args) {
const [format, size, margin, errorCorrection] = args;
// Create new QR image from the input data, and convert it to a buffer
const qrImage = qr.imageSync(input, {
type: format,
size: size,
margin: margin,
"ec_level": errorCorrection.charAt(0).toUpperCase()
});
if (qrImage == null) {
throw new OperationError("Error generating QR code.");
}
switch (format) {
case "SVG":
case "EPS":
case "PDF":
return [...Buffer.from(qrImage)];
case "PNG":
// Return the QR image buffer as a byte array
return [...qrImage];
default:
throw new OperationError("Unsupported QR code format.");
}
}
/**
* Displays the QR image using HTML for web apps
*
* @param {byteArray} data
* @returns {html}
*/
present(data, args) {
if (!data.length) return "";
const [format] = args;
if (format === "PNG") {
let dataURI = "data:";
const type = Magic.magicFileType(data);
if (type && type.mime.indexOf("image") === 0){
dataURI += type.mime + ";";
} else {
throw new OperationError("Invalid PNG file generated by QR image");
}
dataURI += "base64," + toBase64(data);
return `<img src="${dataURI}">`;
}
return Utils.byteArrayToChars(data);
}
}
export default GenerateQRCode;

View File

@@ -22,7 +22,7 @@ class GroupIPAddresses extends Operation {
super();
this.name = "Group IP addresses";
this.module = "JSBN";
this.module = "Default";
this.description = "Groups a list of IP addresses into subnets. Supports both IPv4 and IPv6 addresses.";
this.infoURL = "https://wikipedia.org/wiki/Subnetwork";
this.inputType = "string";

View File

@@ -19,7 +19,7 @@ class HAS160 extends Operation {
super();
this.name = "HAS-160";
this.module = "Hashing";
this.module = "Crypto";
this.description = "HAS-160 is a cryptographic hash function designed for use with the Korean KCDSA digital signature algorithm. It is derived from SHA-1, with assorted changes intended to increase its security. It produces a 160-bit output.<br><br>HAS-160 is used in the same way as SHA-1. First it divides input in blocks of 512 bits each and pads the final block. A digest function updates the intermediate hash value by processing the input blocks in turn.<br><br>The message digest algorithm consists of 80 rounds.";
this.infoURL = "https://wikipedia.org/wiki/HAS-160";
this.inputType = "ArrayBuffer";

View File

@@ -20,7 +20,7 @@ class HMAC extends Operation {
super();
this.name = "HMAC";
this.module = "Hashing";
this.module = "Crypto";
this.description = "Keyed-Hash Message Authentication Codes (HMAC) are a mechanism for message authentication using cryptographic hash functions.";
this.infoURL = "https://wikipedia.org/wiki/HMAC";
this.inputType = "ArrayBuffer";
@@ -28,8 +28,9 @@ class HMAC extends Operation {
this.args = [
{
"name": "Key",
"type": "binaryString",
"value": ""
"type": "toggleString",
"value": "",
"toggleValues": ["Hex", "Decimal", "Base64", "UTF8", "Latin1"]
},
{
"name": "Hashing function",
@@ -66,12 +67,12 @@ class HMAC extends Operation {
* @returns {string}
*/
run(input, args) {
const key = args[0],
const key = Utils.convertToByteString(args[0].string || "", args[0].option),
hashFunc = args[1].toLowerCase(),
msg = Utils.arrayBufferToStr(input, false),
hasher = CryptoApi.getHasher(hashFunc);
const mac = CryptoApi.getHmac(CryptoApi.encoder.fromUtf(key), hasher);
const mac = CryptoApi.getHmac(key, hasher);
mac.update(msg);
return CryptoApi.encoder.toHex(mac.finalize());
}

View File

@@ -1,5 +1,6 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @author Phillip Nordwall [phillip.nordwall@gmail.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*/
@@ -27,7 +28,12 @@ class JSONBeautify extends Operation {
{
"name": "Indent string",
"type": "binaryShortString",
"value": "\\t"
"value": " "
},
{
"name": "Sort Object Keys",
"type": "boolean",
"value": false
}
];
}
@@ -38,11 +44,35 @@ class JSONBeautify extends Operation {
* @returns {string}
*/
run(input, args) {
const indentStr = args[0];
const [indentStr, sortBool] = args;
if (!input) return "";
if (sortBool) {
input = JSON.stringify(JSONBeautify._sort(JSON.parse(input)));
}
return vkbeautify.json(input, indentStr);
}
/**
* Sort JSON representation of an object
*
* @author Phillip Nordwall [phillip.nordwall@gmail.com]
* @private
* @param {object} o
* @returns {object}
*/
static _sort(o) {
if (Array.isArray(o)) {
return o.map(JSONBeautify._sort);
} else if ("[object Object]" === Object.prototype.toString.call(o)) {
return Object.keys(o).sort().reduce(function(a, k) {
a[k] = JSONBeautify._sort(o[k]);
return a;
}, {});
}
return o;
}
}
export default JSONBeautify;

View File

@@ -0,0 +1,111 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
/**
* JSON to CSV operation
*/
class JSONToCSV extends Operation {
/**
* JSONToCSV constructor
*/
constructor() {
super();
this.name = "JSON to CSV";
this.module = "Default";
this.description = "Converts JSON data to a CSV based on the definition in RFC 4180.";
this.infoURL = "https://wikipedia.org/wiki/Comma-separated_values";
this.inputType = "JSON";
this.outputType = "string";
this.args = [
{
name: "Cell delimiter",
type: "binaryShortString",
value: ","
},
{
name: "Row delimiter",
type: "binaryShortString",
value: "\\r\\n"
}
];
}
/**
* @param {JSON} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const [cellDelim, rowDelim] = args;
// Record values so they don't have to be passed to other functions explicitly
this.cellDelim = cellDelim;
this.rowDelim = rowDelim;
const self = this;
try {
// If the JSON is an array of arrays, this is easy
if (input[0] instanceof Array) {
return input
.map(row => row
.map(self.escapeCellContents.bind(self))
.join(cellDelim)
)
.join(rowDelim) +
rowDelim;
}
// If it's an array of dictionaries...
const header = Object.keys(input[0]);
return header
.map(self.escapeCellContents.bind(self))
.join(cellDelim) +
rowDelim +
input
.map(row => header
.map(h => row[h])
.map(self.escapeCellContents.bind(self))
.join(cellDelim)
)
.join(rowDelim) +
rowDelim;
} catch (err) {
throw new OperationError("Unable to parse JSON to CSV: " + err.toString());
}
}
/**
* Correctly escapes a cell's contents based on the cell and row delimiters.
*
* @param {string} data
* @returns {string}
*/
escapeCellContents(data) {
// Double quotes should be doubled up
data = data.replace(/"/g, '""');
// If the cell contains a cell or row delimiter or a double quote, it mut be enclosed in double quotes
if (
data.indexOf(this.cellDelim) >= 0 ||
data.indexOf(this.rowDelim) >= 0 ||
data.indexOf("\n") >= 0 ||
data.indexOf("\r") >= 0 ||
data.indexOf('"') >= 0
) {
data = `"${data}"`;
}
return data;
}
}
export default JSONToCSV;

View File

@@ -20,7 +20,7 @@ class Keccak extends Operation {
super();
this.name = "Keccak";
this.module = "Hashing";
this.module = "Crypto";
this.description = "The Keccak hash algorithm was designed by Guido Bertoni, Joan Daemen, Micha\xebl Peeters, and Gilles Van Assche, building upon RadioGat\xfan. It was selected as the winner of the SHA-3 design competition.<br><br>This version of the algorithm is Keccak[c=2d] and differs from the SHA-3 specification.";
this.infoURL = "https://wikipedia.org/wiki/SHA-3";
this.inputType = "ArrayBuffer";

View File

@@ -19,7 +19,7 @@ class MD2 extends Operation {
super();
this.name = "MD2";
this.module = "Hashing";
this.module = "Crypto";
this.description = "The MD2 (Message-Digest 2) algorithm is a cryptographic hash function developed by Ronald Rivest in 1989. The algorithm is optimized for 8-bit computers.<br><br>Although MD2 is no longer considered secure, even as of 2014, it remains in use in public key infrastructures as part of certificates generated with MD2 and RSA.";
this.infoURL = "https://wikipedia.org/wiki/MD2_(cryptography)";
this.inputType = "ArrayBuffer";

View File

@@ -19,7 +19,7 @@ class MD4 extends Operation {
super();
this.name = "MD4";
this.module = "Hashing";
this.module = "Crypto";
this.description = "The MD4 (Message-Digest 4) algorithm is a cryptographic hash function developed by Ronald Rivest in 1990. The digest length is 128 bits. The algorithm has influenced later designs, such as the MD5, SHA-1 and RIPEMD algorithms.<br><br>The security of MD4 has been severely compromised.";
this.infoURL = "https://wikipedia.org/wiki/MD4";
this.inputType = "ArrayBuffer";

View File

@@ -19,7 +19,7 @@ class MD5 extends Operation {
super();
this.name = "MD5";
this.module = "Hashing";
this.module = "Crypto";
this.description = "MD5 (Message-Digest 5) is a widely used hash function. It has been used in a variety of security applications and is also commonly used to check the integrity of files.<br><br>However, MD5 is not collision resistant and it isn't suitable for applications like SSL/TLS certificates or digital signatures that rely on this property.";
this.infoURL = "https://wikipedia.org/wiki/MD5";
this.inputType = "ArrayBuffer";

View File

@@ -20,7 +20,7 @@ class MD6 extends Operation {
super();
this.name = "MD6";
this.module = "Hashing";
this.module = "Crypto";
this.description = "The MD6 (Message-Digest 6) algorithm is a cryptographic hash function. It uses a Merkle tree-like structure to allow for immense parallel computation of hashes for very long inputs.";
this.infoURL = "https://wikipedia.org/wiki/MD6";
this.inputType = "string";

View File

@@ -23,7 +23,7 @@ class Magic extends Operation {
this.name = "Magic";
this.flowControl = true;
this.module = "Default";
this.description = "The Magic operation attempts to detect various properties of the input data and suggests which operations could help to make more sense of it.<br><br><b>Options</b><br><u>Depth:</u> If an operation appears to match the data, it will be run and the result will be analysed further. This argument controls the maximum number of levels of recursion.<br><br><u>Intensive mode:</u> When this is turned on, various operations like XOR, bit rotates, and character encodings are brute-forced to attempt to detect valid data underneath. To improve performance, only the first 100 bytes of the data is brute-forced.<br><br><u>Extensive language support:</u> At each stage, the relative byte frequencies of the data will be compared to average frequencies for a number of languages. The default set consists of ~40 of the most commonly used languages on the Internet. The extensive list consists of 284 languages and can result in many languages matching the data if their byte frequencies are similar.";
this.description = "The Magic operation attempts to detect various properties of the input data and suggests which operations could help to make more sense of it.<br><br><b>Options</b><br><u>Depth:</u> If an operation appears to match the data, it will be run and the result will be analysed further. This argument controls the maximum number of levels of recursion.<br><br><u>Intensive mode:</u> When this is turned on, various operations like XOR, bit rotates, and character encodings are brute-forced to attempt to detect valid data underneath. To improve performance, only the first 100 bytes of the data is brute-forced.<br><br><u>Extensive language support:</u> At each stage, the relative byte frequencies of the data will be compared to average frequencies for a number of languages. The default set consists of ~40 of the most commonly used languages on the Internet. The extensive list consists of 284 languages and can result in many languages matching the data if their byte frequencies are similar.<br><br>Optionally enter a regular expression to match a string you expect to find to filter results (crib).";
this.infoURL = "https://github.com/gchq/CyberChef/wiki/Automatic-detection-of-encoded-data-using-CyberChef-Magic";
this.inputType = "ArrayBuffer";
this.outputType = "JSON";
@@ -43,6 +43,11 @@ class Magic extends Operation {
"name": "Extensive language support",
"type": "boolean",
"value": false
},
{
"name": "Crib (known plaintext string or regex)",
"type": "string",
"value": ""
}
];
}
@@ -56,10 +61,16 @@ class Magic extends Operation {
*/
async run(state) {
const ings = state.opList[state.progress].ingValues,
[depth, intensive, extLang] = ings,
[depth, intensive, extLang, crib] = ings,
dish = state.dish,
magic = new MagicLib(await dish.get(Dish.ARRAY_BUFFER)),
options = await magic.speculativeExecution(depth, extLang, intensive);
cribRegex = (crib && crib.length) ? new RegExp(crib, "i") : null;
let options = await magic.speculativeExecution(depth, extLang, intensive, [], false, cribRegex);
// Filter down to results which matched the crib
if (cribRegex) {
options = options.filter(option => option.matchesCrib);
}
// Record the current state for use when presenting
this.state = state;

View File

@@ -43,7 +43,7 @@ class Mean extends Operation {
*/
run(input, args) {
const val = mean(createNumArray(input, args[0]));
return val instanceof BigNumber ? val : new BigNumber(NaN);
return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN);
}
}

View File

@@ -43,7 +43,7 @@ class Median extends Operation {
*/
run(input, args) {
const val = median(createNumArray(input, args[0]));
return val instanceof BigNumber ? val : new BigNumber(NaN);
return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN);
}
}

View File

@@ -44,7 +44,7 @@ class Multiply extends Operation {
*/
run(input, args) {
const val = multi(createNumArray(input, args[0]));
return val instanceof BigNumber ? val : new BigNumber(NaN);
return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN);
}
}

View File

@@ -6,7 +6,7 @@
import Operation from "../Operation";
import Utils from "../Utils";
import { bitOp, or } from "../lib/BitwiseOp";
import { bitOp, or, BITWISE_OP_DELIMS } from "../lib/BitwiseOp";
/**
* OR operation
@@ -30,7 +30,7 @@ class OR extends Operation {
"name": "Key",
"type": "toggleString",
"value": "",
"toggleValues": ["Hex", "Decimal", "Base64", "UTF8", "Latin1"]
"toggleValues": BITWISE_OP_DELIMS
}
];
}

View File

@@ -21,7 +21,7 @@ class ParseIPRange extends Operation {
super();
this.name = "Parse IP range";
this.module = "JSBN";
this.module = "Default";
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";

View File

@@ -23,7 +23,7 @@ class ParseIPv4Header extends Operation {
super();
this.name = "Parse IPv4 header";
this.module = "JSBN";
this.module = "Default";
this.description = "Given an IPv4 header, this operations parses and displays each field in an easily readable format.";
this.infoURL = "https://wikipedia.org/wiki/IPv4#Header";
this.inputType = "string";

View File

@@ -8,7 +8,7 @@ import Operation from "../Operation";
import Utils from "../Utils";
import OperationError from "../errors/OperationError";
import {strToIpv6, ipv6ToStr, ipv4ToStr, IPV6_REGEX} from "../lib/IP";
import BigInteger from "jsbn";
import BigNumber from "bignumber.js";
/**
* Parse IPv6 address operation
@@ -22,7 +22,7 @@ class ParseIPv6Address extends Operation {
super();
this.name = "Parse IPv6 address";
this.module = "JSBN";
this.module = "Default";
this.description = "Displays the longhand and shorthand versions of a valid IPv6 address.<br><br>Recognises all reserved ranges and parses encapsulated or tunnelled addresses including Teredo and 6to4.";
this.infoURL = "https://wikipedia.org/wiki/IPv6_address";
this.inputType = "string";
@@ -147,7 +147,7 @@ class ParseIPv6Address extends Operation {
const v4Addr = ipv4ToStr((ipv6[1] << 16) + ipv6[2]),
slaId = ipv6[3],
interfaceIdStr = ipv6[4].toString(16) + ipv6[5].toString(16) + ipv6[6].toString(16) + ipv6[7].toString(16),
interfaceId = new BigInteger(interfaceIdStr, 16);
interfaceId = new BigNumber(interfaceIdStr, 16);
output += "\n\nEncapsulated IPv4 address: " + v4Addr +
"\nSLA ID: " + slaId +

View File

@@ -0,0 +1,107 @@
/**
* @author j433866 [j433866@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Magic from "../lib/Magic";
import jsqr from "jsqr";
import jimp from "jimp";
/**
* Parse QR Code operation
*/
class ParseQRCode extends Operation {
/**
* ParseQRCode constructor
*/
constructor() {
super();
this.name = "Parse QR Code";
this.module = "Image";
this.description = "Reads an image file and attempts to detect and read a Quick Response (QR) code from the image.<br><br><u>Normalise Image</u><br>Attempts to normalise the image before parsing it to improve detection of a QR code.";
this.infoURL = "https://wikipedia.org/wiki/QR_code";
this.inputType = "byteArray";
this.outputType = "string";
this.args = [
{
"name": "Normalise image",
"type": "boolean",
"value": false
}
];
}
/**
* @param {byteArray} input
* @param {Object[]} args
* @returns {string}
*/
async run(input, args) {
const type = Magic.magicFileType(input);
const [normalise] = args;
// Make sure that the input is an image
if (type && type.mime.indexOf("image") === 0) {
let image = input;
if (normalise) {
// Process the image to be easier to read by jsqr
// Disables the alpha channel
// Sets the image default background to white
// Normalises the image colours
// Makes the image greyscale
// Converts image to a JPEG
image = await new Promise((resolve, reject) => {
jimp.read(Buffer.from(input))
.then(image => {
image
.rgba(false)
.background(0xFFFFFFFF)
.normalize()
.greyscale()
.getBuffer(jimp.MIME_JPEG, (error, result) => {
resolve(result);
});
})
.catch(err => {
reject(new OperationError("Error reading the image file."));
});
});
}
if (image instanceof OperationError) {
throw image;
}
return new Promise((resolve, reject) => {
jimp.read(Buffer.from(image))
.then(image => {
if (image.bitmap != null) {
const qrData = jsqr(image.bitmap.data, image.getWidth(), image.getHeight());
if (qrData != null) {
resolve(qrData.data);
} else {
reject(new OperationError("Couldn't read a QR code from the image."));
}
} else {
reject(new OperationError("Error reading the image file."));
}
})
.catch(err => {
reject(new OperationError("Error reading the image file."));
});
});
} else {
throw new OperationError("Invalid file type.");
}
}
}
export default ParseQRCode;

View File

@@ -181,8 +181,8 @@ class ParseX509Certificate extends Operation {
Serial number: ${new r.BigInteger(sn, 16).toString()} (0x${sn})
Algorithm ID: ${cert.getSignatureAlgorithmField()}
Validity
Not Before: ${nbDate} (dd-mm-yy hh:mm:ss) (${cert.getNotBefore()})
Not After: ${naDate} (dd-mm-yy hh:mm:ss) (${cert.getNotAfter()})
Not Before: ${nbDate} (dd-mm-yyyy hh:mm:ss) (${cert.getNotBefore()})
Not After: ${naDate} (dd-mm-yyyy hh:mm:ss) (${cert.getNotAfter()})
Issuer
${issuerStr}
Subject
@@ -206,12 +206,15 @@ ${extensions}`;
* @returns {string}
*/
function formatDate (dateStr) {
return dateStr[4] + dateStr[5] + "/" +
dateStr[2] + dateStr[3] + "/" +
dateStr[0] + dateStr[1] + " " +
dateStr[6] + dateStr[7] + ":" +
if (dateStr.length === 13) { // UTC Time
dateStr = (dateStr[0] < "5" ? "20" : "19") + dateStr;
}
return dateStr[6] + dateStr[7] + "/" +
dateStr[4] + dateStr[5] + "/" +
dateStr[0] + dateStr[1] + dateStr[2] + dateStr[3] + " " +
dateStr[8] + dateStr[9] + ":" +
dateStr[10] + dateStr[11];
dateStr[10] + dateStr[11] + ":" +
dateStr[12] + dateStr[13];
}
export default ParseX509Certificate;

View File

@@ -0,0 +1,102 @@
/**
* @author anthony-arnold [anthony.arnold@uqconnect.edu.au]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import { fromBase64, toBase64 } from "../lib/Base64";
import { fromHex } from "../lib/Hex";
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Utils from "../Utils";
import Magic from "../lib/Magic";
/**
* PlayMedia operation
*/
class PlayMedia extends Operation {
/**
* PlayMedia constructor
*/
constructor() {
super();
this.name = "Play Media";
this.module = "Default";
this.description = "Plays the input as audio or video depending on the type.<br><br>Tags: sound, movie, mp3, mp4, mov, webm, wav, ogg";
this.infoURL = "";
this.inputType = "string";
this.outputType = "byteArray";
this.presentType = "html";
this.args = [
{
"name": "Input format",
"type": "option",
"value": ["Raw", "Base64", "Hex"]
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {byteArray} The multimedia data as bytes.
*/
run(input, args) {
const [inputFormat] = args;
if (!input.length) return [];
// Convert input to raw bytes
switch (inputFormat) {
case "Hex":
input = fromHex(input);
break;
case "Base64":
// Don't trust the Base64 entered by the user.
// Unwrap it first, then re-encode later.
input = fromBase64(input, undefined, "byteArray");
break;
case "Raw":
default:
input = Utils.strToByteArray(input);
break;
}
// Determine file type
const type = Magic.magicFileType(input);
if (!(type && /^audio|video/.test(type.mime))) {
throw new OperationError("Invalid or unrecognised file type");
}
return input;
}
/**
* Displays an audio or video element that may be able to play the media
* file.
*
* @param data {byteArray} Data containing an audio or video file.
* @returns {string} Markup to display a media player.
*/
async present(data) {
if (!data.length) return "";
const type = Magic.magicFileType(data);
const matches = /^audio|video/.exec(type.mime);
if (!matches) {
throw new OperationError("Invalid file type");
}
const dataURI = `data:${type.mime};base64,${toBase64(data)}`;
const element = matches[0];
let html = `<${element} src='${dataURI}' type='${type.mime}' controls>`;
html += "<p>Unsupported media type.</p>";
html += `</${element}>`;
return html;
}
}
export default PlayMedia;

View File

@@ -19,7 +19,7 @@ class RIPEMD extends Operation {
super();
this.name = "RIPEMD";
this.module = "Hashing";
this.module = "Crypto";
this.description = "RIPEMD (RACE Integrity Primitives Evaluation Message Digest) is a family of cryptographic hash functions developed in Leuven, Belgium, by Hans Dobbertin, Antoon Bosselaers and Bart Preneel at the COSIC research group at the Katholieke Universiteit Leuven, and first published in 1996.<br><br>RIPEMD was based upon the design principles used in MD4, and is similar in performance to the more popular SHA-1.<br><br>";
this.infoURL = "https://wikipedia.org/wiki/RIPEMD";
this.inputType = "ArrayBuffer";

View File

@@ -228,40 +228,29 @@ function regexList (input, regex, displayTotal, matches, captureGroups) {
function regexHighlight (input, regex, displayTotal) {
let output = "",
title = "",
m,
hl = 1,
i = 0,
total = 0;
while ((m = regex.exec(input))) {
// Moves pointer when an empty string is matched (prevents infinite loop)
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
output = input.replace(regex, (match, ...args) => {
args.pop(); // Throw away full string
const offset = args.pop(),
groups = args;
// Add up to match
output += Utils.escapeHtml(input.slice(i, m.index));
title = `Offset: ${m.index}\n`;
if (m.length > 1) {
title = `Offset: ${offset}\n`;
if (groups.length) {
title += "Groups:\n";
for (let n = 1; n < m.length; ++n) {
title += `\t${n}: ${m[n]}\n`;
for (let i = 0; i < groups.length; i++) {
title += `\t${i+1}: ${Utils.escapeHtml(groups[i] || "")}\n`;
}
}
// Add match with highlighting
output += "<span class='hl"+hl+"' title='"+title+"'>" + Utils.escapeHtml(m[0]) + "</span>";
// Switch highlight
hl = hl === 1 ? 2 : 1;
i = regex.lastIndex;
total++;
}
// Add all after final match
output += Utils.escapeHtml(input.slice(i, input.length));
return `<span class='hl${hl}' title='${title}'>${Utils.escapeHtml(match)}</span>`;
});
if (displayTotal)
output = "Total found: " + total + "\n\n" + output;

View File

@@ -0,0 +1,41 @@
/**
* @author Klaxon [klaxon@veyr.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
/**
* Remove Diacritics operation
*/
class RemoveDiacritics extends Operation {
/**
* RemoveDiacritics constructor
*/
constructor() {
super();
this.name = "Remove Diacritics";
this.module = "Default";
this.description = "Replaces accented characters with their latin character equivalent.";
this.infoURL = "https://wikipedia.org/wiki/Diacritic";
this.inputType = "string";
this.outputType = "string";
this.args = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
// reference: https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript/37511463
return input.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
}
}
export default RemoveDiacritics;

View File

@@ -19,7 +19,7 @@ class SHA0 extends Operation {
super();
this.name = "SHA0";
this.module = "Hashing";
this.module = "Crypto";
this.description = "SHA-0 is a retronym applied to the original version of the 160-bit hash function published in 1993 under the name 'SHA'. It was withdrawn shortly after publication due to an undisclosed 'significant flaw' and replaced by the slightly revised version SHA-1.";
this.infoURL = "https://wikipedia.org/wiki/SHA-1#SHA-0";
this.inputType = "ArrayBuffer";

View File

@@ -19,7 +19,7 @@ class SHA1 extends Operation {
super();
this.name = "SHA1";
this.module = "Hashing";
this.module = "Crypto";
this.description = "The SHA (Secure Hash Algorithm) hash functions were designed by the NSA. SHA-1 is the most established of the existing SHA hash functions and it is used in a variety of security applications and protocols.<br><br>However, SHA-1's collision resistance has been weakening as new attacks are discovered or improved.";
this.infoURL = "https://wikipedia.org/wiki/SHA-1";
this.inputType = "ArrayBuffer";

View File

@@ -19,7 +19,7 @@ class SHA2 extends Operation {
super();
this.name = "SHA2";
this.module = "Hashing";
this.module = "Crypto";
this.description = "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.<br><br><ul><li>SHA-512 operates on 64-bit words.</li><li>SHA-256 operates on 32-bit words.</li><li>SHA-384 is largely identical to SHA-512 but is truncated to 384 bytes.</li><li>SHA-224 is largely identical to SHA-256 but is truncated to 224 bytes.</li><li>SHA-512/224 and SHA-512/256 are truncated versions of SHA-512, but the initial values are generated using the method described in Federal Information Processing Standards (FIPS) PUB 180-4.</li></ul>";
this.infoURL = "https://wikipedia.org/wiki/SHA-2";
this.inputType = "ArrayBuffer";

View File

@@ -20,7 +20,7 @@ class SHA3 extends Operation {
super();
this.name = "SHA3";
this.module = "Hashing";
this.module = "Crypto";
this.description = "The SHA-3 (Secure Hash Algorithm 3) hash functions were released by NIST on August 5, 2015. Although part of the same series of standards, SHA-3 is internally quite different from the MD5-like structure of SHA-1 and SHA-2.<br><br>SHA-3 is a subset of the broader cryptographic primitive family Keccak designed by Guido Bertoni, Joan Daemen, Micha\xebl Peeters, and Gilles Van Assche, building upon RadioGat\xfan.";
this.infoURL = "https://wikipedia.org/wiki/SHA-3";
this.inputType = "ArrayBuffer";

View File

@@ -19,7 +19,7 @@ class SSDEEP extends Operation {
super();
this.name = "SSDEEP";
this.module = "Hashing";
this.module = "Crypto";
this.description = "SSDEEP is a program for computing context triggered piecewise hashes (CTPH). Also called fuzzy hashes, CTPH can match inputs that have homologies. Such inputs have sequences of identical bytes in the same order, although bytes in between these sequences may be different in both content and length.<br><br>SSDEEP hashes are now widely used for simple identification purposes (e.g. the 'Basic Properties' section in VirusTotal). Although 'better' fuzzy hashes are available, SSDEEP is still one of the primary choices because of its speed and being a de facto standard.<br><br>This operation is fundamentally the same as the CTPH operation, however their outputs differ in format.";
this.infoURL = "https://forensicswiki.org/wiki/Ssdeep";
this.inputType = "string";

View File

@@ -6,7 +6,7 @@
import Operation from "../Operation";
import Utils from "../Utils";
import { bitOp, sub } from "../lib/BitwiseOp";
import { bitOp, sub, BITWISE_OP_DELIMS } from "../lib/BitwiseOp";
/**
* SUB operation
@@ -30,7 +30,7 @@ class SUB extends Operation {
"name": "Key",
"type": "toggleString",
"value": "",
"toggleValues": ["Hex", "Decimal", "Base64", "UTF8", "Latin1"]
"toggleValues": BITWISE_OP_DELIMS
}
];
}

Some files were not shown because too many files have changed in this diff Show More