Compare commits

..
Author SHA1 Message Date
C85297 188b25d7a3 Build for ARM on pull requests 2026-02-03 15:37:44 +00:00
Alex Gustafsson 967f93aa63 Use recommended GitHub actions to build image
- The redhat actions no longer provide anything not provided by the
  official docker action
- The redhat action creates OCI images that are not following best
  practices from the OCI specification
2025-05-26 17:53:27 +02:00
jg42526andGitHub c57556f49f Merge pull request #2021 from kendallgoto/kgoto/add-handlebar
Add new operation: Template
2025-05-16 11:22:50 +01:00
jg42526andGitHub 18e5b9f6ec Merge branch 'master' into kgoto/add-handlebar 2025-05-16 11:03:44 +01:00
a3957273andGitHub 411f78d27a Merge pull request #2011 from bartvanandel/feat/1216-1531-upgrade-uuid 2025-05-12 16:44:22 +01:00
a3957273andGitHub 7ed7fca3ad Merge branch 'master' into feat/1216-1531-upgrade-uuid 2025-05-12 16:24:53 +01:00
a3957273andGitHub 5d3353189b Merge pull request #2015 from bartvanandel/fix/use-default-index-in-option-transform 2025-05-12 16:24:35 +01:00
a3957273andGitHub f92238bf04 Merge pull request #2023 from xumptex/feature/add-BLAKE3 2025-05-12 16:14:00 +01:00
a3957273andGitHub 2b1ceef6a3 Merge pull request #2025 from ericli-splunk/patch-1 2025-05-12 16:06:53 +01:00
a3957273andGitHub f4e73eef54 Merge pull request #1986 from Odyhibit/master 2025-05-12 16:05:42 +01:00
gchqdev364andGitHub d751117219 Merge pull request #2041 from gchq/octal-ip-addresses
Addresses bug report #2008
Added explicit support for octal IP addresses.
Changed approach to IPv4 regex to be string manipulation generated.
Added some unit tests for IP address parsing - probably not full coverage.
Added lookahead and lookbehind tricks to resolve warned issue that 1.2.3.256 would still be extracted as 1.2.3.25. Now only accepts valid IP addresses. Warning replaced with clause about infinite length dotted decimal forms.
2025-05-12 15:51:03 +01:00
a3957273andGitHub a55075fdb6 Merge pull request #2042 from Sma-Das/patch-1 2025-05-12 15:45:26 +01:00
gchqdev364 288cd8f063 Updated warning now that original issue has been resolved. 2025-05-12 14:24:07 +00:00
Sma DasandGitHub a7443778b8 update: dockerfile
Updated Dockerfile to correctly build on ARM64 platforms. The previous version failed.
2025-05-12 10:22:22 -04:00
gchqdev364 e9b182d33b Added look ahead and look behind to avoid over capture. 2025-05-12 14:18:01 +00:00
gchqdev364 0c01c6a7c3 Added important tests that need to pass before merge. 2025-05-12 14:07:21 +00:00
a3957273andGitHub 06f1982acf Merge pull request #2038 from GCHQDeveloper94872/Issue-2036-Safari-load-bug 2025-05-12 15:04:14 +01:00
es45411andGitHub 761173bce7 Merge pull request #2040 from gchq/feature/add-toggle-plus-to-urldecode
Add toggle "+" character to URLDecode operation
2025-05-12 14:42:15 +01:00
gchqdev364 bfec582aee Using code to generate regex string procedurally to improve readability. 2025-05-12 13:35:39 +00:00
es45411 3a55b34214 Add tests for URLDecode and URLEncode 2025-05-12 13:09:59 +00:00
es45411 95d5fd1789 Add treat space as plus URLDecode option 2025-05-12 13:09:49 +00:00
gchqdev364 159b80e853 Added explicit tests for IPv4 addresses in decimal or octal. 2025-05-12 13:02:29 +00:00
GCHQDeveloper94872andGitHub f24bd92e34 Merge branch 'master' into Issue-2036-Safari-load-bug 2025-05-12 13:51:00 +01:00
GCHQDeveloper94872 e4f4d9c1c5 Workaround for Safari load bug 2025-05-12 12:15:41 +00:00
es45411andGitHub 7ecf8dfdaa Merge pull request #2037 from gchq/bugfix/update-generateallchecksums-infourl
Update GenerateAllChecksums infoURL
2025-05-12 12:35:23 +01:00
es45411 1bc3105002 Update GenerateAllChecksums infoURL 2025-05-12 11:34:15 +00:00
es45411andGitHub 66d445c5ef Add GenerateAllChecksums operation
* Add GenerateAllChecksums operation
* Remove checksums from GenerateAllHashes operation
2025-05-12 12:29:33 +01:00
jg42526andGitHub b2045e5bd8 Merge pull request #2035 from jg42526/checksum/xor
XOR Checksum operation added
2025-05-12 12:01:29 +01:00
a3957273andGitHub 64a4bfeadf Merge pull request #1897 from sw5678/master 2025-05-12 12:00:34 +01:00
jg42526andGitHub 46762a2af7 Merge branch 'gchq:master' into checksum/xor 2025-05-12 11:29:54 +01:00
sw5678 bd9e0142bc Fix linting errors 2025-05-12 11:24:29 +01:00
a3957273andGitHub da922a45cf Merge pull request #2027 from r4mos/ecdsa-verify-message-format 2025-05-12 11:22:42 +01:00
sw5678 9538320928 Fix linting errors 2025-05-12 11:20:42 +01:00
sw5678 b156fc9929 Fixed bug where spaces were causing the text to not be correct 2025-05-12 11:14:23 +01:00
jg42526 dda5814c30 Merged master and followed naming convention updates 2025-05-12 10:11:15 +00:00
sw5678andGitHub 7ca472279c Merge branch 'gchq:master' into master 2025-05-12 09:42:30 +01:00
a3957273andGitHub 670721f1f6 Merge pull request #2031 from PathToLife/patch-1 2025-05-12 09:25:34 +01:00
a3957273andGitHub 3c5eea5dfb Merge pull request #1587 from jonking-ajar/feat/jsonata-operation 2025-05-12 09:24:54 +01:00
a3957273andGitHub 497e2a9d45 Merge pull request #1992 from kenduguay1/push-input-through-postmessage 2025-05-12 09:23:53 +01:00
sw5678andGitHub e4a59c6990 Merge branch 'gchq:master' into master 2025-05-12 09:02:32 +01:00
kenduguay1andGitHub 85a3a18570 Merge branch 'master' into push-input-through-postmessage 2025-05-09 10:29:09 -04:00
Ken Duguay a150137c4b Merge branch 'push-input-through-postmessage' of github.com:kenduguay1/CyberChef into push-input-through-postmessage 2025-05-09 14:22:11 +00:00
Ken Duguay c6ece4292b Update the postMessage format to be consistent with cyberchef's internal functions 2025-05-09 14:20:13 +00:00
PathToLifeandGitHub c475a24854 Re-enable Npm Release in github workflows 2025-05-02 15:04:17 +12:00
r4mos 1089c6bfb8 Add All Checksums Operation 2025-04-29 17:25:29 +02:00
r4mos 4085a4c219 Remove Checksums from All Hashes 2025-04-28 16:43:22 +02:00
r4mos a2665ba213 Add to ECDSA Verify the message format 2025-04-25 13:56:10 +02:00
Josh BloomandGitHub 0a94c4a7c9 Merge branch 'master' into master 2025-04-22 23:33:28 -05:00
ericli-splunkandGitHub 64355c9dde Fix email regex 2025-04-17 15:46:37 -07:00
Jeremy Giudicelli bd8906f46b fix : add Categories and index 2025-04-17 13:40:01 +02:00
Jeremy Giudicelli 26d8fa51b0 fix : delete space and add new line 2025-04-17 13:27:45 +02:00
Jeremy Giudicelli ad91099d5e feat : add Blake3 hashing
import hash-wasm to hash inputs in utf-8 with optional key also in utf-8 and outputs in Hex
2025-04-17 11:37:35 +02:00
Kendall Goto 361a3b2929 Add Template operation for basic JSON rendering 2025-04-09 15:54:39 -07:00
Bart van Andel b9ed1fde62 fix: use defaultIndex instead of 0 in transformArgs 2025-04-05 23:01:52 +02:00
Bart van Andel a0ade26505 fix: improve UUID description
- Link to uuid package at npmjs
- Briefly explain supported UUID versions for generation
2025-04-05 22:59:03 +02:00
Bart van Andel 575eade84d fix: simplify UUID argument names, use hint for more info 2025-04-05 22:51:59 +02:00
Bart van Andel 2cf3642493 fix: use UUID v4 by default, for backward compatibility 2025-04-05 22:49:54 +02:00
a3957273andGitHub 7c8be12d52 Merge pull request #1548 from brun0ne/add-php-serialization
Add new operation: PHP Serialize
2025-04-05 19:06:23 +01:00
a3957273andGitHub e849569b10 Merge pull request #2013 from plvie/master
Add ECB/NoPadding and CBC/NoPadding support to AES encryption
2025-04-05 19:04:08 +01:00
Paul Vié fa559fdbed split edit 2025-04-05 14:28:14 +02:00
a3957273andGitHub 74d631c71e Merge pull request #1991 from peterc-s/master
Add Base32 Hex Extended Alphabet and Base32 Tests.
2025-04-05 05:57:56 +01:00
a3957273andGitHub 305a02c8a2 Merge pull request #1974 from PathToLife/feature/docker-multiplatform-build
Docker multiplatform build support
2025-04-05 05:42:01 +01:00
a3957273andGitHub 5a3b7bc4c0 Merge pull request #2014 from 0xh3xa/master
Fix(RecipeWaiter): sanitize user input in addOperation to prevent XSS
2025-04-05 05:14:58 +01:00
heaprc c83e1ac4fb Fix(RecipeWaiter): eslint format error 2025-04-05 00:42:37 +02:00
heaprc 857576dbe4 fix(RecipeWaiter): sanitize user input in addOperation to prevent XSS 2025-04-05 00:18:54 +02:00
Paul Vié e00a636fc0 fix semicolon 2025-04-04 18:40:27 +02:00
GarabandGitHub 6f4cbd8688 Merge branch 'gchq:master' into master 2025-04-04 18:32:40 +02:00
Bart van Andel de5b03f854 chore: fix class name for analyse UUID operation 2025-04-04 10:24:46 +02:00
Bart van Andel 457d28fc55 feat: support UUID v1, v3, v4, v5, v6, v7
- Add v6 and v7 as valid options
- Add unit tests for generating and analyzing all supported versions
2025-04-04 10:24:46 +02:00
victorlpgazolliandBart van Andel e0bdde89c4 testing only class default value 2025-04-04 10:24:46 +02:00
victorlpgazolliandBart van Andel 68db8e93b7 ref assert validation uuid tests 2025-04-04 10:24:46 +02:00
victorlpgazolliandBart van Andel 9069d8e3ec ref uuid tests 2025-04-04 10:24:46 +02:00
victorlpgazolliandBart van Andel e146636250 add more uuid tests 2025-04-04 10:24:45 +02:00
victorlpgazolliandBart van Andel c0af2a9eb5 add analyse uuid category 2025-04-04 10:24:45 +02:00
victorlpgazolliandBart van Andel ae5648ede1 add analyse uuid version 2025-04-04 10:24:45 +02:00
victorlpgazolliandBart van Andel 197d6735d2 ref generate uuid versions v1, v3, v4 and v5 2025-04-04 10:24:45 +02:00
victorlpgazolliandBart van Andel 75b52bef6d add uuid dependency 2025-04-04 10:24:45 +02:00
a3957273andGitHub 848660f8e1 Merge pull request #2006 from 0xh3xa/master
Bug Fix: selected theme not loading when refreshing
2025-04-03 19:15:02 +01:00
heaprc 0e7b1f7c78 resolve conflict in applyPreferredColorScheme method 2025-04-03 09:31:53 +02:00
0xh3xaandGitHub bbb211d819 Merge branch 'master' into master 2025-04-03 09:23:39 +02:00
0xh3xaandGitHub 9ca0152aac Merge branch 'master' into master 2025-04-03 09:22:38 +02:00
a3957273andGitHub 4b72484ca4 Merge pull request #1993 from r4mos/master
Add CRC Operation
2025-04-03 08:22:11 +01:00
a3957273andGitHub e469f00fc7 Merge pull request #1286 from ccarpo/master
Added a JSON to YAML and a YAML to JSON operation
2025-04-03 08:19:20 +01:00
a3957273andGitHub 75e3f35932 Merge pull request #1863 from JSCU-CNI/x509_fingerprints
Add fingerprints to the 'Parse X.509 certificate' operation
2025-04-03 08:18:04 +01:00
a3957273andGitHub 9a8804ab94 Merge pull request #1604 from zhzy0077/jq
Support jq as an operation.
2025-04-03 08:15:35 +01:00
a3957273andGitHub f5b5227e53 Merge pull request #1909 from flakjacket95/master
Add SM2 Encrypt and Decrypt Operations
2025-04-03 08:14:23 +01:00
a3957273andGitHub 14472d3b40 Merge pull request #2007 from 0xh3xa/bugfix/invalid-theme-option
Load the user's preferred color scheme if the URL contains an invalid theme
2025-04-03 08:00:39 +01:00
heaprc 9f30dd0e7a fix invalid theme error 2025-03-29 04:40:29 +01:00
0xh3xaandGitHub 49d69a293b Fix selected theme not loading when refreshing 2025-03-29 01:27:38 +01:00
Paul Vié 23de98f892 Add ECB/NoPadding and CBC/NoPadding Encryption 2025-03-26 11:46:47 +01:00
Dan FlackandGitHub 8852712f0d Merge branch 'master' into master 2025-03-16 00:44:31 -04:00
zhzy0077 b62def3d3e making it a seperate module. 2025-03-12 20:15:23 +08:00
zhzy0077 464c92e7bf Rename to "Jq" 2025-03-12 20:15:09 +08:00
zhzy0077 95044ab767 Making it depending on 0.5.1 version. 2025-03-12 20:15:00 +08:00
CCarpo a809321b63 renamed function for clarity 2025-03-10 20:55:35 +01:00
Computer Network InvestigationandGitHub b6f0f9b200 Merge branch 'master' into x509_fingerprints 2025-03-10 16:44:41 +01:00
PathToLife a42c7de112 test buildah platforms flag environment variables 2025-03-10 18:00:49 +13:00
PathToLife b85036b78f Dockerfile manual architecture selection for multiplatform build. Disable NPM Publish for testing 2025-03-10 17:28:20 +13:00
PathToLife 3b75e13287 ci release error fix, apply detect chrome driver version npm install env var 2025-03-10 12:46:34 +13:00
CCarpoandGitHub 98ef5d0110 Merge branch 'master' into master 2025-03-07 15:03:33 +01:00
ccarpo 2c21d72a6a Merge branch 'master' of https://github.com/ccarpo/CyberChef 2025-03-07 12:39:30 +01:00
r4mos 42efc0187c Fixed Test for non-working buttons 2025-03-04 08:46:41 +01:00
r4mos d5f007deea Fixed non-working buttons 2025-03-04 08:43:16 +01:00
r4mos 566b423065 Correct forgotten test 2025-03-03 17:33:54 +01:00
r4mos 1b4760c447 Add Custom CRC 2025-03-03 17:15:26 +01:00
r4mos 3025391821 Browser test changed to adapt to new CRC operation 2025-03-03 09:19:01 +01:00
r4mos 4e62aa6e1d The CRC Operation is implemented natively with all currently known CRC's. Old Operations (CRC8, CRC16 and CRC32) and their dependencies are removed 2025-03-02 01:51:09 +01:00
r4mos fcecd029c7 The CRC Operation is implemented natively with all currently known CRC's. Old Operations (CRC8, CRC16 and CRC32) and their dependencies are removed 2025-03-02 01:41:12 +01:00
kenduguay1andGitHub f4988328be Merge branch 'master' into push-input-through-postmessage 2025-02-28 14:45:20 -05:00
ken 7710c5ef49 Add event listener for message events
Add handler for message events
2025-02-28 19:44:04 +00:00
peterc-s 3057a20791 Add Base32 Hex Extended option. 2025-02-28 16:52:15 +00:00
PathToLifeandGitHub b2981d3cc7 Merge branch 'master' into feature/docker-multiplatform-build 2025-02-24 04:47:35 +00:00
Odyhibit 2c32a64bfe Remove trim from rail fence. 2025-02-21 20:40:37 -06:00
a3957273andGitHub d3357d2acd Merge pull request #1981 from bartblaze/master 2025-02-21 22:12:47 +00:00
Jon King 91125f00e7 updated Jsonata Query tests header title 2025-02-17 10:19:38 -07:00
Jon King 4c6b4cd4e7 added Jsonata Query tests 2025-02-17 10:15:35 -07:00
Jon King c4574ff042 fix: properly handle undefined results 2025-02-17 10:15:13 -07:00
bartblaze 7babef6f93 Preserve uppercase
This will preserve uppercase.
2025-02-17 17:35:22 +01:00
Jon King 2b2435210b chore: update return type from JSON to string 2025-02-17 07:41:59 -07:00
Jon King 4a428e802e feat: add to category 2025-02-17 07:41:59 -07:00
Jon King 5b15e75479 feat: add jsonata query operation 2025-02-17 07:41:58 -07:00
Brunon BlokandGitHub a40aed2b47 Merge branch 'master' into add-php-serialization 2025-02-17 14:09:03 +01:00
CCarpo 5cef2b13a3 fixed typo in categories. 2025-02-17 08:46:28 +01:00
CCarpo c2936a6f2c removed old data format 2025-02-17 08:44:42 +01:00
CCarpo 06b7f0129f fixed linter issues. 2025-02-17 08:42:14 +01:00
CCarpoandGitHub e44e6fed35 Merge branch 'master' into master 2025-02-17 08:36:14 +01:00
Zhiyuan Zheng a74e2e585e add lock. 2025-02-17 13:49:17 +08:00
Zhiyuan Zheng d602897221 Merge branch 'master' into jq 2025-02-17 13:47:34 +08:00
a3957273andGitHub 1b8c229df2 Merge pull request #1976 from evenstensberg/feat/cspell
chore(root): add cspell
2025-02-16 18:48:31 +00:00
a3957273andGitHub aa7bbc1a62 Merge pull request #1977 from depperm/CC-1889
CC-1889 add _ option
2025-02-16 18:37:00 +00:00
David Marshall 6ccbc892c7 CC-1889 2025-02-16 09:03:46 -05:00
Even Stensberg 7b3980a5e2 chore(root): add cspell 2025-02-16 13:53:36 +01:00
a3957273andGitHub 7906f9d560 Merge pull request #630 from MShwed/feature/mime-rfc2047
Feature: MIME RFC2047 Decoding
2025-02-16 12:11:02 +00:00
mshwed 2ae923b73e Updated category and fixed imports 2025-02-15 23:03:05 -05:00
mshwed 15bbed093c fixed formatting 2025-02-15 22:23:49 -05:00
mshwedandmshwed 23faeadea2 Fixed linting issues 2025-02-15 22:20:42 -05:00
mshwedandmshwed 50c0d4bcd6 Added test case for ISO and ASCII 2025-02-15 22:20:42 -05:00
mshwedandmshwed 7f97afd3e0 Added parsing of headers. 2025-02-15 22:20:41 -05:00
mshwedandmshwed c3994aa8e3 Added support for converting hex characters 2025-02-15 22:16:58 -05:00
mshwedandmshwed 8166f981ae in progress 2025-02-15 22:16:58 -05:00
a3957273andGitHub 1cfbc2babb Merge pull request #1105 from linuxgemini/linuxgemini-patch-modhex
Introduce Yubico's Modhex for Conversion
2025-02-16 02:18:30 +00:00
a3957273andGitHub eb912547ac Merge branch 'master' into linuxgemini-patch-modhex 2025-02-16 01:55:11 +00:00
a3957273andGitHub bcf62ec73d Merge pull request #1903 from FranciscoPombal/rot13_numbers_negative_shift_amount
fix: ROT13 - shifting numbers by negative amounts
2025-02-16 01:47:09 +00:00
a3957273andGitHub 004ef7f5dc Merge pull request #1904 from FranciscoPombal/des_triple_des_error_message
fix: DES/Triple DES - misleading error messages
2025-02-16 01:43:36 +00:00
a3957273andGitHub 9ab990ff59 Merge pull request #1921 from vs4vijay/theme-auto-detection
automatically theme mode based on user preference
2025-02-16 01:36:28 +00:00
a3957273andGitHub fb8e1be9f0 Merge pull request #1933 from k3ach/master
Updated luhn checksum operation to work with different bases
2025-02-16 01:30:37 +00:00
PathToLifeandGitHub 324560aeae Merge branch 'gchq:master' into feature/docker-multiplatform-build 2025-02-16 00:54:09 +00:00
a3957273andGitHub 95c6406d05 Merge pull request #1966 from exactlyaron/fix/generate-totp-issue-1964
Fix Generate TOTP & HOPT
2025-02-15 23:06:55 +00:00
a3957273andGitHub 51b9fe644b Merge pull request #1971 from bartblaze/master
Add Leet Speak
2025-02-15 22:55:52 +00:00
a3957273andGitHub fed10f3ee6 Merge pull request #1915 from Oshawk/take-nth-bytes
Add 'Take nth bytes' operation
2025-02-14 15:45:27 +00:00
a3957273andGitHub 7cc3e5804b Merge branch 'master' into take-nth-bytes 2025-02-14 15:44:12 +00:00
a3957273andGitHub dcf0bbb02b Merge pull request #1914 from Oshawk/drop-nth-bytes
Add 'Drop nth bytes' operation
2025-02-14 15:43:41 +00:00
PathToLife f8b613b4e7 Docker multiplatform build support. Pending CI workflow test 2025-02-13 20:57:45 +13:00
a3957273andGitHub e48fc4c8d8 Merge pull request #1902 from FranciscoPombal/blowfish_ecr_iv
fix: Blowfish - ignore IV length in ECB mode
2025-02-12 22:37:31 +00:00
a3957273andGitHub 1b53b8d23f Merge pull request #1780 from jb30795/master
IPv6 Transition Operation
2025-02-12 22:35:29 +00:00
a3957273andGitHub 355566736a Merge branch 'master' into blowfish_ecr_iv 2025-02-12 20:08:47 +00:00
a3957273andGitHub b99a76f9a6 Merge branch 'master' into master 2025-02-12 20:08:43 +00:00
a3957273andGitHub 912bbe54aa Merge branch 'master' into drop-nth-bytes 2025-02-12 20:08:30 +00:00
a3957273andGitHub 26a16b6945 Merge branch 'master' into take-nth-bytes 2025-02-12 20:08:24 +00:00
a3957273andGitHub feaf3dd119 Merge branch 'master' into theme-auto-detection 2025-02-12 19:59:44 +00:00
a3957273andGitHub 3187ff6322 Merge branch 'master' into master 2025-02-12 19:53:55 +00:00
a3957273andGitHub 13f94a23f8 Merge pull request #1899 from c65722/strip_ipv4_header
Add Strip IPv4 header operation
2025-02-12 19:53:34 +00:00
a3957273andGitHub 592e660deb Merge pull request #1973 from gchq/bug/disable-loading-from-url
Disable flakey URL test
2025-02-12 19:53:24 +00:00
a3957273andGitHub 3cdbdf4223 Merge branch 'master' into master 2025-02-12 19:51:20 +00:00
c65722andGitHub 8cd875d06a Merge branch 'master' into strip_ipv4_header 2025-02-11 10:11:18 +00:00
a3957273andGitHub bf36fe8143 Merge pull request #1866 from Adamkadaban/master
add offset field to 'Add Line Numbers' operation
2025-02-11 00:50:03 +00:00
a3957273 d3ee16f38b Disable flakey URL test 2025-02-11 00:49:14 +00:00
a3957273andGitHub 41c5403700 Merge branch 'master' into master 2025-02-11 00:46:18 +00:00
a3957273andGitHub e1d3af26da Merge pull request #1955 from max0x53/compress
Webpack compress with gzip and brotli
2025-02-11 00:43:36 +00:00
a3957273andGitHub 5a7cb9e047 Merge branch 'master' into fix/generate-totp-issue-1964 2025-02-11 00:42:41 +00:00
a3957273andGitHub a41068e633 Merge branch 'master' into master 2025-02-11 00:40:26 +00:00
a3957273andGitHub bce04609a5 Merge branch 'master' into theme-auto-detection 2025-02-11 00:40:11 +00:00
a3957273andGitHub d4da81fa91 Merge branch 'master' into master 2025-02-11 00:39:40 +00:00
a3957273andGitHub d3e31890ae Merge branch 'master' into strip_ipv4_header 2025-02-11 00:38:21 +00:00
a3957273andGitHub 9d014aeaa5 Merge pull request #1898 from c65722/strip_tcp_header
Add Strip TCP header operation
2025-02-11 00:38:01 +00:00
a3957273andGitHub 156de53dc1 Merge branch 'master' into strip_tcp_header 2025-02-11 00:27:38 +00:00
a3957273andGitHub 9f2527d736 Merge branch 'master' into strip_ipv4_header 2025-02-11 00:27:19 +00:00
a3957273andGitHub 7ecc235b31 Merge pull request #1900 from c65722/strip_udp_header
Add Strip UDP header operation
2025-02-11 00:26:59 +00:00
a3957273andGitHub 51ed3b2fc1 Merge branch 'master' into strip_tcp_header 2025-02-11 00:26:52 +00:00
a3957273andGitHub 306e29da76 Merge pull request #1972 from gchq/feature/detect-chromedriver
Automatically detect chrome driver version
2025-02-11 00:23:11 +00:00
a3957273andGitHub 9cc84b1c62 Merge branch 'master' into feature/detect-chromedriver 2025-02-11 00:23:00 +00:00
a3957273andGitHub f02b3f22ad Merge pull request #1936 from c65722/parse_tls_record
Add Parse TLS record operation
2025-02-11 00:22:12 +00:00
a3957273andGitHub e9b8163626 Merge pull request #1957 from RandomByte/jwt-sign/add-header-option
Add 'header' ingredient to JWT Sign operation
2025-02-11 00:13:56 +00:00
a3957273andGitHub 20390ae08e Merge pull request #1959 from simonarnell/patch-1
Corrected path to generateNodeIndex.mjs
2025-02-11 00:08:24 +00:00
a3957273andGitHub fcdcce7ee4 Merge pull request #1961 from GuilhermoReadonly/patch-1
Fix typo in description of JWT Sign recipe
2025-02-11 00:06:21 +00:00
a3957273 3d017d5f84 Add it to the correct file. 2025-02-11 00:02:39 +00:00
Alexander 5455061e15 Atomatically detect chrome driver version 2025-02-10 23:53:55 +00:00
a3957273andGitHub caa373c1be Merge branch 'master' into master 2025-02-10 23:38:41 +00:00
a3957273andGitHub f4995dbc30 Merge pull request #1887 from robinsandhu/feature/parse-crl
Add operation for parsing X.509 CRLs
2025-02-10 23:35:58 +00:00
bartblaze f14c423c64 Add Leet Speak
Not too many use cases, but something I thought of (and have seen in a few skiddie malware samples).

Will also resolve #1234
2025-02-05 18:34:59 +01:00
exactlyaron 6f63de81b1 style: fix linting 2025-01-23 11:46:01 +00:00
exactlyaron 75991321de tests: fix tests 2025-01-23 11:41:26 +00:00
exactlyaron b560d74b8e tests: comment out Generate HOTP test 2025-01-23 11:28:24 +00:00
exactlyaron 90133e3f90 fix: refactor GenerateHOTP to use optauth 2025-01-23 11:28:13 +00:00
exactlyaron 672cb5dea4 fix: refactor GenerateTOTP to use optauth 2025-01-23 11:28:04 +00:00
exactlyaron 7eb9e08ad2 build(deps): use optauth instead of opt 2025-01-23 11:27:45 +00:00
exactlyaron 2007b26d57 build(deps): update otp 0.1.3 → 1.1.2 2025-01-23 00:25:59 +00:00
exactlyaron e804555278 fix: refactor GenerateTOTP 2025-01-23 00:24:20 +00:00
Adamkadaban 6b75ba8903 fix bug where no input leads to error in console 2025-01-13 15:48:18 -05:00
Adam HassanandGitHub 54e559c5a6 Merge branch 'master' into master 2025-01-13 12:24:45 -05:00
Guilhem RadondeandGitHub cc7cc7f8fd misc: typo 2025-01-10 09:32:41 +01:00
Simon ArnellandGitHub 6a92f922cb corrected path to generateNodeIndex.mjs 2025-01-09 12:32:57 +02:00
Merlin Beutlberger 71c8c8aac0 Add 'header' ingredient to JWT Sign operation
Expose the 'header' option of the jsonwebtoken module [1] as an ingredient.
This allows for adding and overwriting JWT header fields such as 'type' or 'kid'.

[1]: https://github.com/auth0/node-jsonwebtoken?tab=readme-ov-file#usage
2025-01-04 18:31:24 +01:00
Max S 304266020d Webpack compress with gzip and brotli 2024-12-28 17:20:15 +00:00
Vijay SoniandGitHub 02f45e545d Merge branch 'master' into theme-auto-detection 2024-12-27 13:41:39 +05:30
Robin SandhuandGitHub 3deb121043 Merge branch 'master' into feature/parse-crl 2024-12-01 16:04:01 +00:00
k3a.ch bab0a7ffed fixed typo 2024-11-30 20:57:56 +01:00
c65722 1fcc365d9e Add Parse TLS record operation 2024-11-02 16:58:19 +00:00
Pascal Burri b92c1e7da0 fixed code format, added tests 2024-10-27 22:36:53 +01:00
k3achandGitHub 0c6c45b152 Merge branch 'gchq:master' into master 2024-10-26 15:50:30 +02:00
Pascal Burri 802c576c60 Updated luhn checksum to to work with base 2-36 2024-10-26 15:49:24 +02:00
n1474335 3822c6c520 10.19.4 2024-10-23 16:10:44 +01:00
n1474335 47c85a105d Added message format arg to RSA Verify operation 2024-10-23 16:02:08 +01:00
n1474335 d3adfc7c3e Updated chromedriver 2024-10-23 15:53:07 +01:00
n1474335 270a333179 10.19.3 2024-10-23 14:03:18 +01:00
n1474335 895a929925 Fixed RSA Sign and Verify character encodings 2024-10-23 14:03:09 +01:00
Vijay Soni e484d426fe automatically theme mode based on user preference
Related to #1901

Implemented automatic dark theme change based on user preference using the `prefers-color-scheme` media query.
2024-10-07 01:28:46 +05:30
Oshawk 4c6dcf182d Merge remote-tracking branch 'upstream/master' into take-nth-bytes 2024-09-25 18:57:20 +01:00
Oshawk 4bb1e335ea Merge remote-tracking branch 'upstream/master' into drop-nth-bytes 2024-09-25 18:14:57 +01:00
Dan Flack ae9054dc37 Remove highlighting and correct one module mismatch 2024-09-22 18:58:36 +02:00
Dan Flack f61bdf06c6 Additional linter corrections 2024-09-21 12:00:37 +02:00
Dan Flack 0f16fa0ce1 Updates for linter 2024-09-21 11:47:01 +02:00
flackjacket95 84ce8e6f30 Add tests 2024-09-21 11:40:57 +02:00
Dan Flack 9eff9e5018 Set default paramater indices 2024-09-21 11:40:32 +02:00
Dan Flack 857d3b6d17 Fully functional encrypt/decrypt 2024-09-21 11:40:32 +02:00
Dan Flack 54cfb17145 Initial migration to library; add decryption operation 2024-09-21 11:40:32 +02:00
Dan Flack 99ba6b487c Add comments, docs, and some additional restructuring 2024-09-21 11:40:32 +02:00
flakjacket a1647b02cb Initial SM2 changes 2024-09-21 11:40:12 +02:00
jb30795andGitHub b15322467b Merge branch 'master' into master 2024-09-20 10:59:28 +01:00
jb30795andjb30795 9229fe9ac7 Remove console.log statement 2024-09-20 10:49:13 +01:00
jb30795andjb30795 488c458720 updates to operation and addition of more tests 2024-09-20 10:46:09 +01:00
Francisco Pombal 784b2631a8 fix: DES/Triple DES - failing tests 2024-09-16 15:44:28 +01:00
Francisco Pombal 3eb1af0278 fix: DES/Triple DES - misleading error messages
Fixes https://github.com/gchq/CyberChef/issues/1843.
2024-09-16 15:36:57 +01:00
Francisco Pombal 7e5eb01a5e fix: ROT13 - shifting numbers by negative amounts
Fixes https://github.com/gchq/CyberChef/issues/1886.
2024-09-15 23:51:48 +01:00
Francisco Pombal 1fce8e5112 fix: Blowfish - ignore IV length in ECB mode
Fixes https://github.com/gchq/CyberChef/issues/1895.
2024-09-15 22:21:10 +01:00
c65722 748379f0b0 Add Strip TCP header operation 2024-09-15 18:49:17 +01:00
c65722 da74d9b22d Add Strip UDP header operation 2024-09-15 18:14:21 +01:00
c65722 738e6feda0 Add Strip IPv4 header operation 2024-09-15 17:46:47 +01:00
sw5678 95f6c4c5d5 Added alternating caps functionality 2024-09-12 15:40:54 +01:00
Robin Sandhu 1fde2fba29 Add basic tests for Parse X.509 CRL operations 2024-08-25 14:28:55 +01:00
Robin Sandhu a50d4d63eb Format issuerAltName CRL extension 2024-08-25 14:15:00 +01:00
Robin Sandhu dbc90090cf Add support for multiple input format
i.e. DER Hex, Base64, Raw
2024-08-25 05:47:29 +01:00
Robin Sandhu e65869a10b Add operation for parsing X.509 CRLs
Signed-off-by: Robin Sandhu <er.robinsandhu@gmail.com>
2024-08-25 05:02:59 +01:00
Computer Network InvestigationandGitHub 7877a0d7d0 Merge branch 'master' into x509_fingerprints 2024-08-15 18:03:58 +02:00
n1474335 d635cca210 10.19.2 2024-08-14 15:35:17 +01:00
n1474335 0e82e4b7c6 Updated chromedriver 2024-08-14 15:35:12 +01:00
n1474335 5f88ae44ec 10.19.1 2024-08-14 15:22:06 +01:00
n1474335 7a5225c961 Fixed JA4 version fallback value 2024-08-14 15:21:57 +01:00
jb30795andjb30795 a80b1568ac Lint errors 2024-08-09 14:32:31 +01:00
jb30795andjb30795 a616e46b50 Handling of /24 ranges 2024-08-09 14:28:50 +01:00
jb30795andjb30795 752ce789c2 Updating tests 2024-08-07 21:19:13 +01:00
jb30795andjb30795 660069865a Updating description 2024-08-07 21:02:00 +01:00
jb30795andjb30795 9169254fff minor wording update 2024-08-07 19:13:44 +01:00
jb30795andjb30795 e12b00485e Merge branch 'master' of ssh://github.com/jb30795/CyberChef-IPv6-Transition 2024-08-07 18:50:13 +01:00
jb30795andjb30795 51a07a27db Formatting updates 2024-08-07 18:49:58 +01:00
jb30795andGitHub c8c9e572a6 Merge branch 'master' into master 2024-08-07 18:42:08 +01:00
jb30795andjb30795 7fb4824cd6 Merge branch 'master' of ssh://github.com/jb30795/CyberChef-IPv6-Transition 2024-08-07 18:39:08 +01:00
jb30795andjb30795 5e763b86dc Option to remove headers and ignore blank input rows 2024-08-07 18:17:00 +01:00
jb30795andjb30795 b090ce0428 Update to accept multiple inputs 2024-08-07 17:06:15 +01:00
Adamkadaban 3dddb516c9 add offset field to 'Add Line Numbers' operation 2024-07-27 20:06:18 -07:00
JSCU-CNI fb3c36af85 Add fingerprints to 'Parse X.509 certificate' operation 2024-07-24 14:23:40 +02:00
n1474335 a477f47aec Merge branch 'master' of github.com:gchq/CyberChef 2024-06-21 14:14:59 +01:00
n1474335 965570d250 10.18.9 2024-06-21 14:12:36 +01:00
n1474335 ab37c1e562 Fixed Optical Character Recognition and added tests 2024-06-21 14:12:28 +01:00
a3957273 40fda00db4 Bump to 10.19.0 2024-06-21 08:09:53 +00:00
a3957273andGitHub d5374454f4 Merge pull request #1828 from robinsandhu/feat/support-other-keys-in-parse-csr 2024-06-21 09:00:12 +01:00
İlteriş Yağıztegin Eroğlu edd22372d8 feat(Modhex): Introduce basic Modhex conversion
Signed-off-by: İlteriş Yağıztegin Eroğlu <ilteris@asenkron.com.tr>
2024-06-17 23:58:58 +00:00
a3957273andGitHub 4c5577ddeb Merge pull request #1834 from eltociear/patch-1 2024-06-18 00:35:50 +01:00
Ikko Eltociear AshimineandGitHub 534ab23d9b chore: update SIGABA.mjs
intial -> initial
2024-06-14 00:38:25 +09:00
Robin Sandhu fe9f4fa7a9 Fix linting errors 2024-06-12 19:00:35 +01:00
Robin SandhuandGitHub a8b1050d75 Merge branch 'master' into feat/support-other-keys-in-parse-csr 2024-06-12 18:57:04 +01:00
Robin Sandhu e80d3d59bc Refactor code 2024-06-12 18:54:04 +01:00
a3957273andGitHub 1efbd9dfd1 Merge pull request #1200 from AlfredBerg/master 2024-06-12 00:01:11 +01:00
a3957273andGitHub 6c30c9c6b8 Merge branch 'master' into master 2024-06-11 23:49:11 +01:00
a3957273andGitHub 4528a1bdb6 Merge branch 'master' into feat/support-other-keys-in-parse-csr 2024-06-11 22:51:32 +01:00
n1474335 c23a8de5a0 Merge branch 'master' of github.com:gchq/CyberChef 2024-06-11 18:07:33 +01:00
n1474335 0cd4d41cdc 10.18.8 2024-06-11 18:07:28 +01:00
n1474335 2b275f0897 Updated eslint, Jimp, and other dependencies 2024-06-11 18:07:22 +01:00
a3957273andGitHub 63913f4d45 Merge pull request #1829 from piguagua/master 2024-06-11 11:26:42 +01:00
piguagua b6c95492f1 chore: remove repeat words
Signed-off-by: piguagua <piguagua@aliyun.com>
2024-06-10 17:36:17 +08:00
Robin Sandhu ae03e34489 Add support for ECDSA and DSA keys to Parse CSR operation 2024-06-09 01:00:20 +01:00
n1474335 7eb887ca51 10.18.7 2024-06-06 17:08:58 +01:00
n1474335 74d0166682 Fixed GOST sBox arg bug 2024-06-06 17:08:37 +01:00
n1474335 18159ce806 10.18.6 2024-05-16 18:09:22 +01:00
n1474335 86d59783fa Improved GOST algorithm naming and block size selection 2024-05-16 18:09:12 +01:00
n1474335 fb818c3149 10.18.5 2024-05-16 14:29:46 +01:00
n1474335 37398188f9 Improved testing to account for race conditions 2024-05-16 14:29:32 +01:00
n1474335 d1a0da3f8d 10.18.4 2024-05-13 17:48:41 +01:00
n1474335 57c8c6dbc6 Added operation counts to categories and ops list with option to hide by default for categories. 2024-05-13 17:48:09 +01:00
n1474335 bbebba6481 Added pause after setting complex input to avoid race conditions 2024-04-25 18:10:59 +01:00
n1474335 f0a49fefa4 Extended time for autoBake to trigger in a test 2024-04-25 17:51:31 +01:00
n1474335 48f3bf9ea7 10.18.3 2024-04-24 18:09:21 +01:00
n1474335 b7a7eebc78 More test tweaks 2024-04-24 18:09:15 +01:00
n1474335 2e76e44a5a Tweaked UI test 2024-04-24 17:40:16 +01:00
n1474335 718ce9ea11 10.18.2 2024-04-24 17:13:57 +01:00
n1474335 a79be1e3ef Removed autoBakePause flag and statechange trigger in InputWaiter.set() as they are redundant. 2024-04-24 17:13:44 +01:00
n1474335 0a709acafe Merge branch 'zb3-fix-testui-race-condition' 2024-04-24 16:43:38 +01:00
n1474335 29efd77eaf Merge branch 'fix-testui-race-condition' of https://github.com/zb3/CyberChef into zb3-fix-testui-race-condition 2024-04-24 16:35:12 +01:00
n1474335 2d6ac8023e 10.18.1 2024-04-24 13:27:07 +01:00
n1474335 2f42f515b0 Updated chromedriver 2024-04-24 13:26:57 +01:00
n1474335 f304f0832b 10.18.0 2024-04-24 13:11:20 +01:00
n1474335 801f3a578d Updated CHANGELOG 2024-04-24 13:11:16 +01:00
n1474335 0a353eeb37 Improved XXTEA operations. Added XXTEA Decrypt. 2024-04-24 13:09:17 +01:00
n1474335 2e2490ce47 10.17.1 2024-04-23 18:29:43 +01:00
n1474335 361a35b44c Removed trailing spaces from RAKE 2024-04-23 18:29:04 +01:00
n1474335 e61d64f618 Wording and stats improvements 2024-04-23 18:28:08 +01:00
a3957273andGitHub 42ad9a49f3 Merge pull request #1786 from zb3/fix-overwritten-output 2024-04-15 01:17:49 +01:00
a3957273andGitHub 7538be68c5 Merge pull request #1275 from cplussharp/ec-asn1 2024-04-15 01:15:36 +01:00
CPlusSharp 21ac516248 ECDSA JSON Web Signature format
used e.g. by JWT
2024-04-14 17:18:06 +02:00
CPlusSharp 7e7195c291 ECDSA: Output keys as JSONWebKeySet instead of two JWK 2024-04-14 16:53:09 +02:00
CPlusSharp 1fbc7e03f0 make the ECDSA JSON signature parsing more robust
also rename the format to "Raw JSON"
as I will later introduce "JSON Web Signature"
2024-04-14 16:46:55 +02:00
CPlusSharp 7b54d9e873 ECDSA rename signature format "Concat HEX" to "P1363 HEX"
this format name is more specific and easier to search for on the internet
2024-04-14 15:20:41 +02:00
a3957273 8ab2256b88 v10.17.0 2024-04-13 22:15:03 +00:00
a3957273andGitHub 6e8c759dde Merge pull request #1788 from EvieHarv/master 2024-04-13 22:24:10 +01:00
a3957273andGitHub a429902d41 Merge pull request #1751 from sw5678/master 2024-04-13 22:20:53 +01:00
a3957273andGitHub f6c5a04088 Merge branch 'master' into master 2024-04-13 22:04:53 +01:00
a3957273andGitHub edc23a860d Merge pull request #1642 from cplussharp/pubkey-from-cert 2024-04-13 21:24:27 +01:00
a3957273andGitHub 67195f65e7 Merge pull request #1277 from cplussharp/jwk 2024-04-13 20:54:38 +01:00
a3957273andGitHub 4619a511d4 Merge pull request #541 from TheZ3ro/hide-recipe-options 2024-04-13 20:22:31 +01:00
CPlusSharp cbf990fab9 JWK conversion from/to PEM 2024-04-13 13:30:46 +02:00
CPlusSharp 8f182e4a9b Sign/Verify Operations for ECDSA
also an Operation for ECDSA signature conversion,
as there could be multiple formats of the signature
2024-04-13 12:57:14 +02:00
CPlusSharp 7a2c9ddbc4 Operation: Generate ECDSA Key Pair 2024-04-13 12:55:21 +02:00
CPlusSharp 28e2a391b8 Public Key from Private Key 2024-04-13 12:39:58 +02:00
CPlusSharp f86817bc86 Public Key from Certificate 2024-04-13 12:38:14 +02:00
n1474335 cc28c6af1a 10.16.0 2024-04-12 14:55:21 +01:00
n1474335 d21a6c8598 Updated CHANGELOG 2024-04-12 14:55:13 +01:00
n1474335 7b2d572902 Added 'JA4Server Fingerprint' operation 2024-04-12 14:41:00 +01:00
sw5678 0cfb67bd06 Improved readability and efficiency of RAKE 2024-04-12 11:27:29 +01:00
sw5678andGitHub f606d4b25f Merge branch 'gchq:master' into master 2024-04-12 10:43:52 +01:00
sw5678 2191d20fb5 Removed trailing whitespace 2024-04-12 10:40:33 +01:00
a3957273andGitHub d13218caaf Merge pull request #1739 from e218736/options-dialog-keyboard-navigation 2024-04-11 15:24:57 +01:00
Ethan Harvey 00f7914c5c Fix affine encode testcase 2024-04-10 23:57:53 +00:00
Ethan Harvey a09f8451fd Require (a, 26) to be coprime in affine encode 2024-04-10 23:19:50 +00:00
TheZ3roandGitHub 670c370b90 Merge branch 'master' into hide-recipe-options 2024-04-09 09:22:03 +02:00
a3957273andGitHub b2e400f474 Merge pull request #1743 from e218736/button-aria-labels 2024-04-09 00:44:48 +01:00
jb30795andGitHub 66d3b6e9ed Merge branch 'master' into master 2024-04-08 11:06:45 +01:00
a3957273andGitHub 8c283c7b19 Merge pull request #1783 from zb3/fix-expectOutput 2024-04-07 21:59:30 +01:00
zb3 db331e94ee fix ui test code style 2024-04-07 01:20:11 +02:00
zb3 2e284d3842 Fix autobake ui test 2024-04-07 00:37:09 +02:00
zb3 a81b2064d4 Abort the previous bake when attempting the next autobake 2024-04-07 00:23:17 +02:00
zb3andGitHub a23e47d8f9 Merge branch 'master' into fix-expectOutput 2024-04-06 13:35:28 +02:00
zb3 e3033173d7 Merge branch 'master' into fix-testui-race-condition 2024-04-06 13:33:59 +02:00
TheZ3roandGitHub 1fbf6c94cd Merge branch 'master' into hide-recipe-options 2024-04-06 11:48:59 +02:00
thez3ro bf9066ae2e fix: make the linter happy 2024-04-06 09:30:52 +00:00
n1474335 33a473c09b 10.15.1 2024-04-05 18:12:26 +01:00
n1474335 409e795ce9 Moved UUID regex in list 2024-04-05 18:12:06 +01:00
n1474335 6ca60cb013 Improvements to HEIF file signature and GIF file extractor 2024-04-05 18:11:51 +01:00
n1474335 ef52195167 Fixed and improved some infoURLs 2024-04-05 18:10:57 +01:00
n1474335 ed930d2364 Moved ops to different modules 2024-04-05 18:10:14 +01:00
n1474335 1b870e559e Updated copyright declarations to a range up to the latest commit 2024-04-05 18:09:07 +01:00
n1474335 d3fb8bd6e9 Fixed typos 2024-04-05 18:08:21 +01:00
zb3 1adc2ff930 Make loadURIParams set input non-silently
Silent input changes might be overwritten due to the debounce logic present inside inputChange.
2024-04-05 18:52:50 +02:00
zb3 fc40580dce Avoid calling inputChange when setting encoding inside loadURIParams
Otherwise the debounce logic sometimes causes the input to be overriden by the previous value.
2024-04-05 18:48:45 +02:00
zb3 4652608297 Fix character encoding io test
Since the output encoding autodetection was introduced, this test was no longer correct.
That wasn't detected because of the expectOutput bug.
2024-04-05 17:14:05 +02:00
zb3 0f0efefbf7 Make expectOutput actually check the output 2024-04-05 17:13:05 +02:00
n1474335 ab0493f53a Update CHANGELOG 2024-04-05 15:56:31 +01:00
TheZ3roandGitHub a1892d4411 Merge branch 'master' into hide-recipe-options 2024-04-05 13:23:28 +02:00
jb30795andjb30795 036f80d734 indentation 2024-04-04 17:00:14 +01:00
jb30795 3ca4c2fd45 Initial commit for new IPv6 Transition operation 2024-04-04 15:54:43 +01:00
a3957273andGitHub 016825d4de Update CHANGELOG.md 2024-04-02 22:27:15 +01:00
a3957273 c35557aea5 Merge branch 'master' of https://github.com/gchq/CyberChef 2024-04-02 20:40:19 +00:00
a3957273 b5959c6f01 10.15.0 2024-04-02 20:40:09 +00:00
a3957273andGitHub 2000938040 Merge pull request #1732 from tomgond/date-delta 2024-04-02 21:38:18 +01:00
a3957273 c795271502 Change output to 'html' 2024-04-02 20:27:48 +00:00
a3957273andGitHub 1d4c810554 Merge pull request #512 from MShwed/feature/extract-hashes 2024-04-02 21:22:51 +01:00
a3957273andGitHub ccd3839a9b Merge pull request #1504 from jkataja/parse-csr 2024-04-02 21:17:51 +01:00
Janne Kataja fda77cf37a add option to show Parse CSR only supports RSA 2024-04-02 21:30:59 +02:00
a3957273andGitHub dc8c185c39 Merge pull request #1769 from gchq/revert-1753-jsonwebtoken-vuln 2024-04-02 18:10:01 +01:00
a3957273andGitHub 99efcb521d Revert "Updated jsonwebtoken dependency to 9+" 2024-04-02 18:09:48 +01:00
Matt ShwedandGitHub d2bd397e8c Merge branch 'master' into feature/extract-hashes 2024-04-02 09:13:16 -04:00
a3957273andGitHub 944810614a Merge pull request #1767 from zb3/fix-evpkey 2024-04-02 10:59:05 +01:00
Matt ShwedandGitHub 21e5641196 Merge branch 'master' into feature/extract-hashes 2024-04-01 22:30:46 -04:00
mshwed 077b11e33b Fixed op name in test 2024-04-01 22:30:18 -04:00
mshwed 8d4ad6ae75 Minor changes. Added test cases. 2024-04-01 22:22:43 -04:00
zb3 ab47b3557f Fix CryptoJS argument passing in DeriveEVPKey
CryptoJS treats strings as Utf8, so for binary strings, Latin1 needs to be used.
2024-04-01 23:04:00 +02:00
Janne Kataja c5e5ed2b4d add Certificate Signing Request (CSR) parse action 2024-04-01 22:41:21 +02:00
tomgondandGitHub dd2cfe8bac Merge branch 'master' into date-delta 2024-04-01 23:32:13 +03:00
a3957273andGitHub 8a17abae45 Merge pull request #1765 from zb3/fix-ciphersaber2 2024-04-01 18:05:32 +01:00
tomgondandGitHub dfedfa9f4c Fix test to fit new time-delta format 2024-04-01 19:42:56 +03:00
tomgondandGitHub 56f92afbf4 Change time-delta argument to be per time unit
Day, hour, minute, second. Instead of a single string.
2024-04-01 19:41:44 +03:00
zb3 52709f0ecb Fix Ciphersaber2 key concatenation
The concat method does not handle typed arrays as arguments.
2024-04-01 18:40:00 +02:00
a3957273andGitHub df140b5098 Merge pull request #1764 from gchq/bug/disable-extract-tests 2024-04-01 17:11:19 +01:00
a3957273 6b95ba7dd6 Fix regular expresion crash in extract hashes 2024-04-01 16:10:42 +00:00
a3957273 61295a968e Lower case 'hash' 2024-04-01 16:01:48 +00:00
a3957273 0717407bea Disable 'Extract ID3' Nightwatch tests 2024-04-01 15:59:49 +00:00
a3957273andGitHub c46660a0d9 Merge pull request #1763 from zb3/fix-base58 2024-04-01 16:55:45 +01:00
zb3 4c6200f233 Fix Base58 handling of strings with only null characters 2024-04-01 17:31:36 +02:00
mshwed 3983e1a8e2 Updated imports 2024-03-31 10:57:03 -04:00
mshwedandmshwed a6b774da81 Fixed issues with const/let and changed default character length 2024-03-31 10:44:40 -04:00
mshwedandmshwed de8ed6962d Improved description of operation 2024-03-31 10:44:40 -04:00
mshwedandmshwed 98edef389c Corrected module type 2024-03-31 10:44:40 -04:00
mshwedandmshwed 1b16c26699 Operation: Added extract hash feature 2024-03-31 10:44:36 -04:00
a3957273 866c9a94ae 10.14.0 2024-03-31 02:24:39 +00:00
a3957273 6677317e27 update x86 disassembly tests 2024-03-31 01:21:17 +00:00
a3957273andGitHub 5c563c2bdf Merge pull request #1361 from devcydo/xxtea_encryption 2024-03-31 00:45:36 +00:00
a3957273andGitHub 8647b50cca Merge pull request #933 from cbeuw/blowfish-keyfix 2024-03-31 00:39:33 +00:00
a3957273andGitHub 21dc5d9de0 Merge pull request #1197 from evanreichard/disassembler_update 2024-03-31 00:37:50 +00:00
a3957273andGitHub e258e5a783 Merge pull request #1606 from joostrijneveld/fix/chacha-raw 2024-03-30 19:08:18 +00:00
a3957273andGitHub 75a28b558e Merge pull request #1762 from gchq/feature/floats 2024-03-30 18:34:07 +00:00
a3957273 6efa2ddfa4 Merge branch 'master' into tcode2k16/master 2024-03-30 17:05:33 +00:00
a3957273 b88fbcc960 Merge branch 'master' of https://github.com/gchq/CyberChef 2024-03-30 14:34:19 +00:00
a3957273 7ccf8cbacd 10.13.0 2024-03-30 14:34:12 +00:00
a3957273andGitHub a1f6960d4e Merge pull request #1761 from gchq/origin/add_fangurl 2024-03-30 14:31:45 +00:00
a3957273 2784978eb5 Fix slash regular expression bug 2024-03-30 14:20:28 +00:00
a3957273 b4133a0afd Merge branch 'master' into addfangurl-master 2024-03-30 14:16:01 +00:00
tomgondandGitHub d59ebdd0dc Merge branch 'master' into date-delta 2024-03-29 12:47:42 +03:00
Joost RijneveldandGitHub 3b5225a94f Merge branch 'master' into fix/chacha-raw 2024-03-29 05:52:06 +01:00
a3957273 acce7ca717 Bump package version 2024-03-29 02:36:56 +00:00
a3957273 d29dbe78d3 Merge branch 'master' of https://github.com/gchq/CyberChef 2024-03-29 02:35:04 +00:00
a3957273 4fdea84534 10.12.0 2024-03-29 02:34:49 +00:00
a3957273andGitHub 0f14d23599 Merge pull request #1750 from joostrijneveld/feature/salsa20 2024-03-29 02:33:20 +00:00
a3957273 877c83eae7 Fix changelog links 2024-03-29 02:03:21 +00:00
a3957273 27b7e3c4d6 Release v10.11.0 2024-03-29 02:02:00 +00:00
a3957273andGitHub 77b7d7ee0b Merge pull request #1752 from chriswhite199/xmldom-upgrade 2024-03-29 00:58:04 +00:00
a3957273andGitHub 6edf731d46 Merge pull request #1753 from chriswhite199/jsonwebtoken-vuln 2024-03-29 00:56:17 +00:00
n1474335 6fd00e2598 Merge branch 'master' of github.com:gchq/CyberChef 2024-03-27 18:32:05 +00:00
n1474335 862cfdf0ae 10.10.0 2024-03-27 18:29:13 +00:00
n1474335 943d01c208 Updated CHANGELOG 2024-03-27 18:28:41 +00:00
n1474335 ef59634c15 Added 'JA4 Fingerprint' operation 2024-03-27 18:02:17 +00:00
a3957273andGitHub 674c8c7c87 Merge pull request #1757 from simonw/heic-heif 2024-03-27 11:24:48 +00:00
Simon Willison 953861ab30 File signatures for heic/heif, refs #1613 2024-03-26 16:26:17 -07:00
n1474335 0026d77b7b More test tweaking 2024-03-26 16:34:36 +00:00
n1474335 ee77e0a1e4 More test tweaking 2024-03-26 16:10:44 +00:00
n1474335 f1dcc339b3 More test tweaking 2024-03-26 15:42:21 +00:00
n1474335 1f316a2f32 More test tweaking 2024-03-26 15:37:18 +00:00
n1474335 a5f9a8726b Fixed erroring test 2024-03-26 15:19:35 +00:00
n1474335 64111b8b7b Downgrade chromedriver version for GitHub Actions 2024-03-26 14:57:58 +00:00
n1474335 762cf3ca41 10.9.0 2024-03-26 14:40:39 +00:00
n1474335 70ff3a52ca Updated CHANGELOG 2024-03-26 14:40:33 +00:00
n1474335 e4077fb63b Lint and dependency update 2024-03-26 14:38:27 +00:00
n1474335 65ffd8d65d Automatically detect UTF8 character encoding in output 2024-03-26 13:44:59 +00:00
n1474335 16dfb3fac6 Automatically detect EOL from paste events and output setting 2024-03-26 13:44:58 +00:00
Chris White ef5ff5bec6 Updated jsonwebtoken dependency to 9+
updated JWTSign operation for backwards compatibility with insecure keys and invalid asym key types
2024-03-13 10:26:23 -07:00
Chris White e1c73a64ad Updated xmldom package to new namespace for vuln remediation 2024-03-13 09:51:22 -07:00
sw5678 81e1abd682 Improving efficency of RAKE 2024-03-11 16:57:28 +00:00
Joost Rijneveld 9068b6c17a Add Salsa20 and XSalsa20 operation 2024-03-10 17:05:19 +01:00
Joost RijneveldandGitHub 5992ba12f1 Merge branch 'master' into fix/chacha-raw 2024-03-08 16:06:31 +01:00
e218736 bf833a39fc favourites button aria label 2024-02-29 14:32:47 +00:00
e218736 fccc3584d8 aria labels/aria hidden to input/output buttons 2024-02-29 12:11:41 +00:00
e218736 963e2839ce add css styling on focus 2024-02-27 14:41:07 +00:00
tomgondandGitHub e85acee509 Update DateTimeDelta.mjs
Another commit for re-build
2024-02-23 07:09:04 +02:00
tomgondandGitHub 4e9567f539 Update DateTimeDelta.mjs
Some change to re-run tests.
2024-02-22 21:49:24 +02:00
tomgondandGitHub a9c00a5856 Merge branch 'master' into date-delta 2024-02-22 18:33:30 +02:00
a3957273andGitHub c4e7c41a6e Merge pull request #501 from kassi/fernet
Add Fernet encryption/decryption operation
2024-02-22 01:15:24 +00:00
a3957273 210186e754 Fix tests 2024-02-22 01:00:11 +00:00
a3957273 b4c14219b6 Fix encrypt 2024-02-22 00:42:30 +00:00
a3957273 299a3c48a1 Update imports from Fernet module 2024-02-22 00:26:32 +00:00
a3957273 cd0aee7626 Remove deprecated code 2024-02-22 00:22:19 +00:00
a3957273 bc82f590d4 Merge branch 'master' into fernet 2024-02-22 00:20:40 +00:00
a3957273 bebb216df2 Bump CyberChef to v10.8.2 2024-02-21 21:14:23 +00:00
tomgondandGitHub 6331c20306 Add code for DateTime Delta to calculate operation 2024-02-21 19:58:13 +02:00
tomgondandGitHub 4dc4c7edd2 Update Categories.json
Add DateTime Delta to categories
2024-02-21 19:56:42 +02:00
tomgondandGitHub d2ff03cea4 Update DateTime.mjs
Add test for time-delta
2024-02-21 19:55:09 +02:00
a3957273andGitHub 61d587a4a5 Merge pull request #1704 from mattnotmitt/add-dev-container
Add devcontainer configuration and .gitattributes
2024-02-18 03:53:43 +00:00
Matt C 85da5f83b5 Add gh-cli, add extensions, node_modules as a volume 2024-02-17 10:06:19 +00:00
AndrewandMatt C 6c0c53d00f Add dev container config file 2024-02-17 10:06:19 +00:00
a3957273andGitHub 196bce04cc Merge pull request #1715 from sw5678/RAKE
Rake
2024-02-16 00:35:33 +00:00
a3957273andGitHub ba82941cef Merge pull request #1719 from GoForceX/master
Fix JSON folder folding in Firefox
2024-02-15 01:01:18 +00:00
GoForceXandGitHub 63449872da Fix JSON folder folding in Firefox 2024-02-14 11:09:14 +00:00
a3957273andGitHub 14ee3f0f4b Merge pull request #1695 from Kalkran/master
Add Caret/M-decode Operation
2024-02-13 13:51:48 +00:00
sw5678 774828823c Adding RAKE test import back after merge conflict 2024-02-13 11:52:19 +00:00
sw5678 9e73e2555b Merging master into branch 2024-02-13 11:50:28 +00:00
Ted Kruijff dc68b7d9bf add to tests, fix test, fix a comma 2024-02-13 10:22:54 +01:00
a3957273andGitHub 7a38504015 Merge branch 'master' into master 2024-02-13 01:37:53 +00:00
a3957273andGitHub 26fa5f3d1d Merge pull request #1623 from jlaundry/master
change Diff to output <ins>, <del>
2024-02-13 01:04:25 +00:00
a3957273 112d52cb99 Remove specified permissions 2024-02-13 00:42:41 +00:00
a3957273 47f1f4c549 Bump to 10.8.0 2024-02-13 00:18:08 +00:00
a3957273andGitHub 4b9d5a7685 Merge pull request #1699 from AshCorr/ash/Containers!
Bundle CyberChef into a container and publish to GCHR
2024-02-13 00:12:18 +00:00
a3957273andGitHub fc7c6312e6 Merge pull request #1714 from sw5678/master
Adding and removing tests
2024-02-12 23:54:52 +00:00
sw5678andGitHub 8b5b17b8e0 Merge branch 'gchq:master' into RAKE 2024-02-12 17:06:10 +00:00
sw5678 c7377da37f Adding and removing tests 2024-02-12 16:52:43 +00:00
sw5678 7cfb5e0b2a Added RAKE functionality into CC 2024-02-12 14:52:46 +00:00
Ashleigh Carr 62dfa8f9dd Point to the correct workflow in the README for Container releases. 2024-02-12 10:46:28 +00:00
Ashleigh Carr 7582abfa27 Fix PR workflow, Buildah requires atleast an image name if no tags specified 2024-02-12 10:46:28 +00:00
Ashleigh Carr 3f89a94df2 Remove image property from Container build & push actions 2024-02-12 10:46:28 +00:00
Ashleigh Carr c5e880628a Fix CI using Containerfile 2024-02-12 10:46:28 +00:00
Ashleigh Carr abd9024097 Add a .dockerignore file 2024-02-12 10:46:28 +00:00
Ashleigh Carr 314b925ec9 Add a comment to the README about using Docker 2024-02-12 10:46:28 +00:00
Ashleigh Carr d700d1d459 Switch to using Dockerfile 2024-02-12 10:46:28 +00:00
Ashleigh Carr 1a2207a045 Swtich to nginx for container 2024-02-12 10:46:28 +00:00
Ashleigh Carr 2b85336c71 Remove ARM64 Container build from release workflow 2024-02-12 10:46:28 +00:00
Ashleigh Carr 4b95ab2477 Increase nofile limit to 10,000 when building container on PR workflow too 2024-02-12 10:46:28 +00:00
Ashleigh Carr a0729304d1 Add packages write permission 2024-02-12 10:46:28 +00:00
Ashleigh Carr dbdcb460e5 Remove unecessary if: success() from Github release workflow 2024-02-12 10:46:28 +00:00
Ashleigh Carr 7588e50f9f Remove unecessary QEMU install step 2024-02-12 10:46:28 +00:00
Ashleigh Carr 40a4872f70 Generate prod build inside container 2024-02-12 10:46:28 +00:00
Ashleigh Carr 3b265322e0 Build container on PR (but don't publish) to verify Containerfile syntax 2024-02-12 10:46:28 +00:00
Ashleigh Carr 0da30813da Add new steps to publish a containerized CyberChef to GHCR 2024-02-12 10:46:28 +00:00
Jed Laundry e973ea6f08 update Diff sanity check test 2024-02-11 01:18:52 +00:00
Jed LaundryandGitHub a942fe92fd Merge branch 'master' into master 2024-02-11 13:31:58 +13:00
a3957273andGitHub 9829b419b9 Merge pull request #1709 from dougburks/patch-1
Fix typo in FileTree.mjs
2024-02-09 16:00:46 +00:00
Doug BurksandGitHub 19194a7eb0 Fix typo in FileTree.mjs 2024-02-09 07:41:32 -05:00
a3957273andGitHub c13997bdb1 Merge pull request #1553 from sg5506844/base92
Feature: Add Base92 operations
2024-02-09 00:42:05 +00:00
a3957273 35c2d437fa Merge branch 'master' of https://github.com/gchq/CyberChef 2024-02-09 00:37:51 +00:00
a3957273 a54522f796 10.7.0 2024-02-09 00:37:15 +00:00
a3957273andGitHub 6c971876de Merge pull request #1667 from sw5678/master
Added file tree functionality
2024-02-09 00:31:48 +00:00
a3957273andGitHub d8be3dfa27 Merge pull request #1555 from sg5506844/rison-operation
RISON operation
2024-02-09 00:30:53 +00:00
a3957273 2b57f94ccd Merge branch 'master' into rison-operation 2024-02-09 00:23:01 +00:00
a3957273andGitHub a3944fe1d1 Merge pull request #1694 from AliceGrey/master
Add MurmurHash3 Operation
2024-02-08 18:15:41 +00:00
Alice cfc8a506f7 Fix calculation bug and add Convert to Signed
A signed output is often needed for Shodan and other favicon searches.
2024-02-06 15:21:39 -05:00
AllieandGitHub afcf46561a Rename Murmurhash3.mjs to MurmurHash3.mjs 2024-02-06 13:13:43 -05:00
AliceandAllie 59b97bfccb Add MurmurHash3 Tests and normalize filename 2024-02-06 13:04:09 -05:00
AliceandAllie 20db43c0a8 Add MIT License 2024-02-06 13:04:09 -05:00
AliceandAllie dc7760247b Add MurmurHash3 2024-02-06 13:04:09 -05:00
a3957273andGitHub 56a8e02bb8 Merge pull request #1705 from gchq/chore/update-packages
Update node packages
2024-02-04 23:25:56 +00:00
a3957273andGitHub e532248701 Merge branch 'master' into chore/update-packages 2024-02-04 15:20:50 +00:00
a3957273 73100896d4 Downgrade Jimp 2024-02-04 02:14:27 +00:00
a3957273 a95be3b4c5 Downgrade bootstrap version 2024-02-04 02:04:11 +00:00
a3957273andGitHub 75c4e196fa Merge pull request #1549 from brun0ne/fix-xss
Fixed xss in addOperation
2024-02-04 01:41:56 +00:00
a3957273andGitHub 0359a2eccf Merge branch 'master' into fix-xss 2024-02-04 01:33:02 +00:00
a3957273andGitHub b118932451 Merge branch 'master' into base92 2024-02-04 01:31:34 +00:00
a3957273andGitHub fd77152343 Merge pull request #1554 from sg5506844/Bcrypt-hash-detection-to-Analyse-hash
Add Bcrypt hash detection to "Analyse hash"
2024-02-04 01:19:30 +00:00
a3957273 5afecdb11a Update node packages 2024-02-04 01:08:15 +00:00
a3957273andGitHub 1916137c3c Merge branch 'master' into rison-operation 2024-02-04 01:04:24 +00:00
a3957273andGitHub c3b89efd9a Merge branch 'master' into master 2024-02-04 00:45:33 +00:00
a3957273 0f3cd72dd3 Add links to Changelog 2024-02-04 00:34:24 +00:00
a3957273andGitHub ed59f6a67a Merge pull request #1658 from cnotin/patch-1
Describe that "Parse ASN.1 hex string" operation requires an hex string input
2024-02-03 16:44:33 +00:00
a3957273andGitHub 592745f380 Merge pull request #1661 from BlacAmDK/BlacAmDK-patch-1
Fix ExtractIPAddresses IPv6 regexp
2024-02-03 16:44:00 +00:00
a3957273andGitHub 10b0d91bdc Merge branch 'master' into BlacAmDK-patch-1 2024-02-03 16:11:01 +00:00
a3957273andGitHub dea2b3a2c0 Merge branch 'master' into patch-1 2024-02-03 16:07:31 +00:00
a3957273 df151eabf9 10.6.0 2024-02-03 14:19:50 +00:00
Clément Notin 22a873c73e Describe that "Parse ASN.1 hex string" operation requires an hex string input
Just in case the title of the operation doesn't make it clear enough
2024-02-03 15:07:57 +01:00
a3957273andGitHub c6da0c623d Merge pull request #1678 from cnotin/patch-3
Add UUID regex to 'Regular expression' operation
2024-02-03 14:06:23 +00:00
a3957273andGitHub 44b566789f Merge pull request #1675 from 0xThiebaut/LZNT1
Add support for LZNT1 decompression.
2024-02-03 13:31:13 +00:00
a3957273andGitHub 940f78a8a7 Merge branch 'master' into LZNT1 2024-02-03 13:08:03 +00:00
a3957273andGitHub 06c912be72 Merge branch 'master' into patch-3 2024-02-03 13:05:42 +00:00
a3957273andGitHub 91639ee836 Merge pull request #1703 from gchq/feature/update-forensic-wiki-address
Update forensics wiki address
2024-02-03 02:19:54 +00:00
a3957273 b78533bb02 Update forensics wiki address 2024-02-03 02:02:13 +00:00
a3957273andGitHub b5e3a6c5a3 Merge branch 'master' into master 2024-02-03 01:25:55 +00:00
a3957273andGitHub a045c4ffec Merge pull request #1541 from KevinSJ/fix/baking-time-info
fix: incorrect hover on baking info
2024-02-03 00:54:17 +00:00
a3957273andGitHub 856ba1cf50 Merge pull request #1702 from gchq/chore/can-i-use-update
Update 'can-i-use' browser list targets
2024-02-03 00:21:53 +00:00
a3957273 6510773789 Update 'can-i-use' browser list targets 2024-02-03 00:11:50 +00:00
a3957273andGitHub 7b280b3369 Merge pull request #1701 from gchq/sec/fix-forensics-url
Update 'ExtractFiles' information URL
2024-02-03 00:04:00 +00:00
a3957273 1618e112e1 Update 'ExtractFiles' information URL 2024-02-02 23:56:27 +00:00
a3957273andGitHub c08a7dc6ce Merge pull request #1700 from gchq/chore/update-chromedriver
Update chrome driver version
2024-02-02 23:54:11 +00:00
a3957273 57731706b3 Revert 'can-i-use' upgrade 2024-02-02 23:46:36 +00:00
a3957273 e9e926d054 Update 'can-i-use' to pass tests 2024-02-02 23:37:07 +00:00
a3957273 5fa3d691cf Update chrome driver version 2024-02-02 22:35:42 +00:00
a3957273andGitHub d022dbc406 Merge pull request #1676 from cnotin/patch-2
Add links to wiki pages
2024-02-02 22:06:43 +00:00
a3957273andGitHub f96607c81b Merge pull request #1656 from pandaninjas/patch-3
Update chromedriver to v119 so that it is compatible with the chrome …
2024-02-02 18:21:29 +00:00
Ted Kruijff 24cd4033c4 Add Caret/M-decode Operation 2024-01-26 15:52:41 +01:00
Clément NotinandGitHub 0bf7852e83 Add UUID regex to 'Regular expression' operation
I use this one often so I'm sure others will like it too :)
2023-12-26 15:59:32 +01:00
Clément NotinandGitHub aaff2e687d Add links to wiki pages 2023-12-26 15:43:49 +01:00
Maxime THIEBAUT 77042abc23 Add support for LZNT1 decompression. 2023-12-25 23:06:11 +01:00
sw5678 ac18b74e66 Fixed linting issues 2023-12-13 09:38:26 +00:00
sw5678 76ba630d59 Added file tree functionality 2023-12-13 09:19:16 +00:00
BlacAmDKandGitHub 362755b22f Fix ExtractIPAddresses IPv6 regexp
IPv6 regexp shouldn't match IPv4 address.
2023-12-05 14:40:37 +08:00
ccarpo cc21fe18ca fixed typo. 2023-11-21 09:24:54 +01:00
ccarpo 4255d8d543 Renamed JSON to Yaml to Beautify JSON 2023-11-21 09:19:58 +01:00
ccarpo 7353315baa Renamed JSON to Yaml to Beautify JSON 2023-11-21 08:56:20 +01:00
Jocelyn CastellanoandGitHub 6c63302d62 Update chromedriver to v119 so that it is compatible with the chrome version in CI 2023-11-20 11:01:00 -08:00
Jed Laundry efda16b039 change Diff to output <ins>, <del> 2023-08-31 03:20:20 +00:00
Joost Rijneveld cb98672549 Fix ChaCha operation Raw output
Previously, an array type error prevented any output when selecting
the 'Raw' output option for the ChaCha operation. This did not
show up in tests, as they all compared to hex values.

This also adds a test (relying on the 'To Hex' operation) that
catches this.
2023-07-30 17:02:36 +02:00
zhzy0077 721061d054 fix typo. 2023-07-25 14:48:03 +08:00
zhzy0077 d2da11c79a Support jq. 2023-07-25 14:42:43 +08:00
n1474335 6ed9d4554a 10.5.2 2023-07-14 19:01:41 +01:00
n1474335 2dcd345349 Updated chromedriver 2023-07-14 19:01:35 +01:00
n1474335 81924b4a7e 10.5.1 2023-07-14 18:54:03 +01:00
n1474335 5a0c3a3b47 Fixed webpack config 2023-07-14 18:53:56 +01:00
n1474335 7b599fe7f7 10.5.0 2023-07-14 18:41:44 +01:00
n1474335 4faaa07188 Updated CHANGELOG 2023-07-14 18:41:32 +01:00
n1474335 fa228b2571 Added a range of GOST operations 2023-07-14 18:37:02 +01:00
sg5506844 9a216dc1bf RISON operation 2023-04-12 15:09:07 +05:30
sg5506844 0e0bafdeb6 Add Bcrypt hash detection to "Analyse hash" 2023-04-12 11:20:18 +05:30
sg5506844 5f0f037c46 Feature: Add Base92 operations 2023-04-12 10:37:16 +05:30
Brunon Blok c0e84dcd50 change comments 2023-04-09 19:06:59 +00:00
Brunon BlokandGitHub 6b01cf0c1a Merge pull request #1 from brun0ne/test-xss
different fix which does not break any tests
2023-04-07 14:50:50 +02:00
Brunon Blok 30f9286ce9 different fix 2023-04-07 12:36:10 +00:00
Brunon Blok e9ff8707ed comply with eslint 2023-04-07 01:02:33 +00:00
Brunon Blok 12082ba3cc escape only angle brackets 2023-04-07 00:59:51 +00:00
Brunon Blok 6d3ca3f56c fix xss in addOperation 2023-04-06 23:31:45 +00:00
Brunon Blok 15b426ebb6 clean up code formatting and fix missing entries 2023-04-06 21:03:46 +00:00
Brunon Blok bf1e708a4c added PHP Serialize operation 2023-04-06 20:32:50 +00:00
Kevin Jiang 4262e6f6f7 fix: incorrect hover on baking info 2023-03-28 22:06:08 +13:00
n1474335 1bc88728f0 10.4.0 2023-03-24 22:41:40 +00:00
n1474335 7bb0649b27 Updated CHANGELOG 2023-03-24 22:41:24 +00:00
n1474335 e46a7448d9 Fixed De Bruijn test import 2023-03-24 22:40:07 +00:00
n1474335 d102e1b15c Tidied 'Generate De Bruijn Sequence' operation 2023-03-24 22:39:08 +00:00
n1474335 0a0217cb66 Merge branch 'debruijn' of https://github.com/GCHQ77703/CyberChef 2023-03-24 22:33:43 +00:00
n1474335 3faa9d3a1e 10.3.0 2023-03-24 22:17:19 +00:00
n1474335 d902c7e30c Updated CHANGELOG 2023-03-24 22:17:11 +00:00
n1474335 25fe7bba67 Tidied up Argon2 operations 2023-03-24 22:15:21 +00:00
n1474335 ca340cdd7b Merge branch 'feature/add-argon2-operation' of https://github.com/Xenonym/CyberChef 2023-03-24 20:48:42 +00:00
Matt CoomberandGitHub 266fbab8fd Fix loading messages
Missing comma in array
2023-03-24 09:57:06 +00:00
Tan Zhen Yong bca4c34b3a Add Argon2 hash compare operation 2023-03-12 00:33:28 +08:00
Tan Zhen Yong 2fab1028c5 Add Argon2 hash operation 2023-03-12 00:32:46 +08:00
Thomas Weißschuh 3e8c5d945c Add "XOR Checksum" operation 2023-02-27 15:12:38 +00:00
Luis Martinez 1dfb231033 xxtea bug fix 2022-07-11 19:42:30 -05:00
Luis MartinezandGitHub 4f0fa2a299 Merge branch 'gchq:master' into xxtea_encryption 2022-07-11 19:41:02 -05:00
Luis Martinez c14098a27c tests added and XXTEA not working correctly fixed 2022-07-11 19:38:59 -05:00
Luis Martinez 653af6a300 xxtea encryption added 2022-07-11 18:59:53 -05:00
Luis Martinez 893b84d042 xxtea encryption added 2022-07-11 18:59:53 -05:00
Luis Martinez 19423cc437 xxtea encryption added 2022-05-28 00:20:51 -05:00
Luis Martinez 3ea12a2e1b xxtea encryption added 2022-05-28 00:17:59 -05:00
Philipp Arnold 23763363ba Added a JSON to YAML and a YALM to JSON operation 2021-12-10 23:22:57 +01:00
Alfred Berg 5001adf221 Xpath accept slightly malformed xml (html) 2021-05-13 17:36:50 +02:00
Evan Reichard cd4e70b24b Fixed right shift 32 problem 2021-05-03 21:07:58 -04:00
thezero ed7baf57f0 replace "options" with "arguments", invert global hide-icon if needed 2020-10-21 00:26:30 +02:00
thezero 3bb6a40f82 add button to hide all recipe options 2020-10-19 21:18:02 +02:00
thezero 6b76b7004a add button to hide recipe's options 2020-10-19 21:18:02 +02:00
Andy Wang 81605b2222 Grammar typo 2020-01-11 10:47:40 +00:00
Andy Wang 9e17825b53 Add variable key size tests 2020-01-09 15:15:01 +00:00
Andy Wang c689cf7f13 Fix #930 by allowing variable key sizes 2020-01-09 15:14:33 +00:00
Oshawk 518b336431 Add tests to index
Added tests to index.
2019-10-21 21:01:33 +01:00
Oshawk b125f82784 Add tests
Added tests for 'Drop nth bytes' operation.
2019-10-21 20:59:04 +01:00
Oshawk 30349dbcb9 Add operation
Added 'Drop nth bytes' operation.
2019-10-21 20:44:57 +01:00
Oshawk 02f6537973 Add tests
Added tests for the 'Take nth byte' operation.
2019-10-21 20:16:14 +01:00
Oshawk 502f126986 Fix linting
Fixed linting.
2019-10-21 20:15:45 +01:00
Oshawk 7c7d1823ca Fix formatting issue
Fixed issue where new lines were truncated.
2019-10-21 19:53:57 +01:00
Oshawk ce6d38860d Add operation
Added 'Take nth bytes' operation.
2019-10-21 19:39:01 +01:00
Kyle ParrishandGitHub 3546ee30a2 Update escaped chars 2019-10-07 16:09:22 -04:00
Alan C 794e0effba Add "To Float" and "From Float" operations 2019-10-07 20:02:28 +08:00
Kyle ParrishandGitHub cd15a8c406 Create FangURL.mjs 2019-10-02 09:58:28 -04:00
Kyle ParrishandGitHub be2080259e Add Fang URL to categories 2019-10-02 09:57:50 -04:00
Karsten Silkenbäumer 55cac17456 Change author URL 2019-03-03 17:19:07 +01:00
Karsten Silkenbäumer 846e84d3a4 Add fernet encryption/decryption operation 2019-03-03 16:41:00 +01:00
GCHQ 77703 822a4fab86 Fix operation linting 2019-02-19 10:16:51 +00:00
GCHQ 77703 44a164ed28 Fix test script linter 2019-02-19 09:56:38 +00:00
GCHQ 77703 1f09c03d48 Add De Bruijn Operation 2019-02-15 14:23:16 +00:00
276 changed files with 34149 additions and 14861 deletions
+17
View File
@@ -0,0 +1,17 @@
{
"version": "0.2",
"language": "en,en-gb",
"words": [],
"dictionaries": [
"npm",
"softwareTerms",
"node",
"html",
"css",
"bash",
"en-gb",
"misc"
],
"ignorePaths": ["package.json", "package-lock.json", "node_modules"]
}
+41
View File
@@ -0,0 +1,41 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node
{
"name": "CyberChef",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/javascript-node:1-18-bookworm",
// Features to add to the dev container. More info: https://containers.dev/features.
"features": {
"ghcr.io/devcontainers/features/github-cli": "latest"
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [8080],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": {
"npm": "bash -c \"sudo chown node node_modules && npm install\""
},
"containerEnv": {
"DISPLAY": ":99"
},
"mounts": [
"source=${localWorkspaceFolderBasename}-node_modules,target=${containerWorkspaceFolder}/node_modules,type=volume"
],
// Configure tool-specific properties.
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"GitHub.vscode-github-actions"
]
}
}
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
+2
View File
@@ -0,0 +1,2 @@
node_modules
build
-1
View File
@@ -1 +0,0 @@
src/core/vendor/**
-116
View File
@@ -1,116 +0,0 @@
{
"parser": "@babel/eslint-parser",
"parserOptions": {
"ecmaVersion": 2022,
"ecmaFeatures": {
"impliedStrict": true
},
"sourceType": "module",
"allowImportExportEverywhere": true
},
"env": {
"browser": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"rules": {
// enable additional rules
"no-eval": "error",
"no-implied-eval": "error",
"dot-notation": "error",
"eqeqeq": ["error", "smart"],
"no-caller": "error",
"no-extra-bind": "error",
"no-unused-expressions": "error",
"no-useless-call": "error",
"no-useless-return": "error",
"radix": "warn",
// modify rules from base configurations
"no-unused-vars": ["error", {
"args": "none",
"vars": "all"
}],
"no-empty": ["error", {
"allowEmptyCatch": true
}],
// disable rules from base configurations
"no-control-regex": "off",
"require-atomic-updates": "off",
"no-async-promise-executor": "off",
// stylistic conventions
"brace-style": ["error", "1tbs"],
"space-before-blocks": ["error", "always"],
"block-spacing": "error",
"array-bracket-spacing": "error",
"comma-spacing": "error",
"spaced-comment": ["error", "always", { "exceptions": ["/"] } ],
"comma-style": "error",
"computed-property-spacing": "error",
"no-trailing-spaces": "warn",
"eol-last": "error",
"func-call-spacing": "error",
"key-spacing": ["warn", {
"mode": "minimum"
}],
"indent": ["error", 4, {
"ignoreComments": true,
"ArrayExpression": "first",
"SwitchCase": 1
}],
"linebreak-style": ["error", "unix"],
"quotes": ["error", "double", {
"avoidEscape": true,
"allowTemplateLiterals": true
}],
"camelcase": ["error", {
"properties": "always"
}],
"semi": ["error", "always"],
"unicode-bom": "error",
"require-jsdoc": ["error", {
"require": {
"FunctionDeclaration": true,
"MethodDefinition": true,
"ClassDeclaration": true,
"ArrowFunctionExpression": true
}
}],
"keyword-spacing": ["error", {
"before": true,
"after": true
}],
"no-multiple-empty-lines": ["warn", {
"max": 2,
"maxEOF": 1,
"maxBOF": 0
}],
"no-whitespace-before-property": "error",
"operator-linebreak": ["error", "after"],
"space-in-parens": "error",
"no-var": "error",
"prefer-const": "error"
},
"overrides": [
{
"files": "tests/**/*",
"rules": {
"no-unused-expressions": "off",
"no-console": "off"
}
}
],
"globals": {
"$": false,
"jQuery": false,
"log": false,
"app": false,
"COMPILE_TIME": false,
"COMPILE_MSG": false,
"PKG_VERSION": false
}
}
+1
View File
@@ -0,0 +1 @@
* text=auto eol=lf
+1
View File
@@ -19,6 +19,7 @@ jobs:
- name: Install
run: |
export DETECT_CHROMEDRIVER_VERSION=true
npm install
npm run setheapsize
+15
View File
@@ -18,6 +18,7 @@ jobs:
- name: Install
run: |
export DETECT_CHROMEDRIVER_VERSION=true
npm install
npm run setheapsize
@@ -33,6 +34,20 @@ jobs:
if: success()
run: npx grunt prod
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Production Image Build
if: success()
id: build-image
uses: docker/build-push-action@v6
with:
# Not being uploaded to any registry, use a simple name to allow Buildah to build correctly.
image: cyberchef
platforms: linux/amd64,linux/arm64
- name: UI Tests
if: success()
run: |
+40 -5
View File
@@ -6,6 +6,12 @@ on:
tags:
- 'v*'
env:
REGISTRY: ghcr.io
REGISTRY_USER: ${{ github.actor }}
REGISTRY_PASSWORD: ${{ github.token }}
IMAGE_NAME: ${{ github.repository }}
jobs:
main:
runs-on: ubuntu-latest
@@ -19,7 +25,8 @@ jobs:
- name: Install
run: |
npm install
export DETECT_CHROMEDRIVER_VERSION=true
npm ci
npm run setheapsize
- name: Lint
@@ -31,17 +38,46 @@ jobs:
npm run testnodeconsumer
- name: Production Build
if: success()
run: npx grunt prod
- name: UI Tests
if: success()
run: |
sudo apt-get install xvfb
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Image Metadata
id: image-metadata
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{major}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{version}}
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ env.REGISTRY_USER }}
password: ${{ env.REGISTRY_PASSWORD }}
- name: Publish to GHCR
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.image-metadata.outputs.tags }}
labels: ${{ steps.image-metadata.outputs.labels }}
platforms: linux/amd64,linux/arm64
- name: Upload Release Assets
if: success()
id: upload-release-assets
uses: svenstaro/upload-release-action@v2
with:
@@ -53,7 +89,6 @@ jobs:
body: "See the [CHANGELOG](https://github.com/gchq/CyberChef/blob/master/CHANGELOG.md) and [commit messages](https://github.com/gchq/CyberChef/commits/master) for details."
- name: Publish to NPM
if: success()
uses: JS-DevTools/npm-publish@v1
with:
token: ${{ secrets.NPM_TOKEN }}
+1
View File
@@ -3,6 +3,7 @@ npm-debug.log
travis.log
build
.vscode
.idea
.*.swp
src/core/config/modules/*
src/core/config/OperationConfig.json
+151 -2
View File
@@ -13,6 +13,83 @@ All major and minor version changes will be documented in this file. Details of
## Details
### [10.19.0] - 2024-06-21
- Add support for ECDSA and DSA in 'Parse CSR' [@robinsandhu] | [#1828]
- Fix typos in SIGABA.mjs [@eltociear] | [#1834]
### [10.18.0] - 2024-04-24
- Added 'XXTEA Encrypt' and 'XXTEA Decrypt' operations [@n1474335] | [0a353ee]
### [10.17.0] - 2024-04-13
- Fix unit test 'expectOutput' implementation [@zb3] | [#1783]
- Add accessibility labels for icons [@e218736] | [#1743]
- Add focus styling for keyboard navigation [@e218736] | [#1739]
- Add support for operation option hiding [@TheZ3ro] | [#541]
- Improve efficiency of RAKE implementation [@sw5678] | [#1751]
- Require (a, 26) to be coprime in 'Affine Encode' [@EvieHarv] | [#1788]
- Added 'JWK to PEM' operation [@cplussharp] | [#1277]
- Added 'PEM to JWK' operation [@cplussharp] | [#1277]
- Added 'Public Key from Certificate' operation [@cplussharp] | [#1642]
- Added 'Public Key from Private Key' operation [@cplussharp] | [#1642]
### [10.16.0] - 2024-04-12
- Added 'JA4Server Fingerprint' operation [@n1474335] | [#1789]
### [10.15.0] - 2024-04-02
- Fix Ciphersaber2 key concatenation [@zb3] | [#1765]
- Fix DeriveEVPKey's array parsing [@zb3] | [#1767]
- Fix JWT operations [@a3957273] | [#1769]
- Added 'Parse Certificate Signing Request' operation [@jkataja] | [#1504]
- Added 'Extract Hash Values' operation [@MShwed] | [#512]
- Added 'DateTime Delta' operation [@tomgond] | [#1732]
### [10.14.0] - 2024-03-31
- Added 'To Float' and 'From Float' operations [@tcode2k16] | [#1762]
- Fix ChaCha raw export option [@joostrijneveld] | [#1606]
- Update x86 disassembler vendor library [@evanreichard] | [#1197]
- Allow variable Blowfish key sizes [@cbeuw] | [#933]
- Added 'XXTEA' operation [@devcydo] | [#1361]
### [10.13.0] - 2024-03-30
- Added 'FangURL' operation [@breakersall] [@arnydo] | [#1591] [#654]
### [10.12.0] - 2024-03-29
- Added 'Salsa20' and 'XSalsa20' operation [@joostrijneveld] | [#1750]
### [10.11.0] - 2024-03-29
- Add HEIC/HEIF file signatures [@simonw] | [#1757]
- Update xmldom to fix medium security vulnerability [@chriswhite199] | [#1752]
- Update JSONWebToken to fix medium security vulnerability [@chriswhite199] | [#1753]
### [10.10.0] - 2024-03-27
- Added 'JA4 Fingerprint' operation [@n1474335] | [#1759]
### [10.9.0] - 2024-03-26
- Line ending sequences and UTF-8 character encoding are now detected automatically [@n1474335] | [65ffd8d]
### [10.8.0] - 2024-02-13
- Add official Docker images [@AshCorr] | [#1699]
### [10.7.0] - 2024-02-09
- Added 'File Tree' operation [@sw5678] | [#1667]
- Added 'RISON' operation [@sg5506844] | [#1555]
- Added 'MurmurHash3' operation [@AliceGrey] | [#1694]
### [10.6.0] - 2024-02-03
- Updated 'Forensics Wiki' URLs to new domain [@a3957273] | [#1703]
- Added 'LZNT1 Decompress' operation [@0xThiebaut] | [#1675]
- Updated 'Regex Expression' UUID matcher [@cnotin] | [#1678]
- Removed duplicate 'hover' message within baking info [@KevinSJ] | [#1541]
### [10.5.0] - 2023-07-14
- Added GOST Encrypt, Decrypt, Sign, Verify, Key Wrap, and Key Unwrap operations [@n1474335] | [#592]
### [10.4.0] - 2023-03-24
- Added 'Generate De Bruijn Sequence' operation [@gchq77703] | [#493]
### [10.3.0] - 2023-03-24
- Added 'Argon2' and 'Argon2 compare' operations [@Xenonym] | [#661]
### [10.2.0] - 2023-03-23
- Added 'Derive HKDF key' operation [@mikecat] | [#1528]
@@ -363,8 +440,23 @@ All major and minor version changes will be documented in this file. Details of
## [4.0.0] - 2016-11-28
- Initial open source commit [@n1474335] | [b1d73a72](https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306)
[10.19.0]: https://github.com/gchq/CyberChef/releases/tag/v10.19.0
[10.18.0]: https://github.com/gchq/CyberChef/releases/tag/v10.18.0
[10.17.0]: https://github.com/gchq/CyberChef/releases/tag/v10.17.0
[10.16.0]: https://github.com/gchq/CyberChef/releases/tag/v10.16.0
[10.15.0]: https://github.com/gchq/CyberChef/releases/tag/v10.15.0
[10.14.0]: https://github.com/gchq/CyberChef/releases/tag/v10.14.0
[10.13.0]: https://github.com/gchq/CyberChef/releases/tag/v10.13.0
[10.12.0]: https://github.com/gchq/CyberChef/releases/tag/v10.12.0
[10.11.0]: https://github.com/gchq/CyberChef/releases/tag/v10.11.0
[10.10.0]: https://github.com/gchq/CyberChef/releases/tag/v10.10.0
[10.9.0]: https://github.com/gchq/CyberChef/releases/tag/v10.9.0
[10.8.0]: https://github.com/gchq/CyberChef/releases/tag/v10.7.0
[10.7.0]: https://github.com/gchq/CyberChef/releases/tag/v10.7.0
[10.6.0]: https://github.com/gchq/CyberChef/releases/tag/v10.6.0
[10.5.0]: https://github.com/gchq/CyberChef/releases/tag/v10.5.0
[10.4.0]: https://github.com/gchq/CyberChef/releases/tag/v10.4.0
[10.3.0]: https://github.com/gchq/CyberChef/releases/tag/v10.3.0
[10.2.0]: https://github.com/gchq/CyberChef/releases/tag/v10.2.0
[10.1.0]: https://github.com/gchq/CyberChef/releases/tag/v10.1.0
[10.0.0]: https://github.com/gchq/CyberChef/releases/tag/v10.0.0
@@ -514,6 +606,31 @@ All major and minor version changes will be documented in this file. Details of
[@valdelaseras]: https://github.com/valdelaseras
[@brun0ne]: https://github.com/brun0ne
[@joostrijneveld]: https://github.com/joostrijneveld
[@Xenonym]: https://github.com/Xenonym
[@gchq77703]: https://github.com/gchq77703
[@a3957273]: https://github.com/a3957273
[@0xThiebaut]: https://github.com/0xThiebaut
[@cnotin]: https://github.com/cnotin
[@KevinSJ]: https://github.com/KevinSJ
[@sw5678]: https://github.com/sw5678
[@sg5506844]: https://github.com/sg5506844
[@AliceGrey]: https://github.com/AliceGrey
[@AshCorr]: https://github.com/AshCorr
[@simonw]: https://github.com/simonw
[@chriswhite199]: https://github.com/chriswhite199
[@breakersall]: https://github.com/breakersall
[@evanreichard]: https://github.com/evanreichard
[@devcydo]: https://github.com/devcydo
[@zb3]: https://github.com/zb3
[@jkataja]: https://github.com/jkataja
[@tomgond]: https://github.com/tomgond
[@e218736]: https://github.com/e218736
[@TheZ3ro]: https://github.com/TheZ3ro
[@EvieHarv]: https://github.com/EvieHarv
[@cplussharp]: https://github.com/cplussharp
[@robinsandhu]: https://github.com/robinsandhu
[@eltociear]: https://github.com/eltociear
[8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
[9a33498]: https://github.com/gchq/CyberChef/commit/9a33498fed26a8df9c9f35f39a78a174bf50a513
@@ -523,6 +640,8 @@ All major and minor version changes will be documented in this file. Details of
[a895d1d]: https://github.com/gchq/CyberChef/commit/a895d1d82a2f92d440a0c5eca2bc7c898107b737
[31a7f83]: https://github.com/gchq/CyberChef/commit/31a7f83b82e78927f89689f323fcb9185144d6ff
[760eff4]: https://github.com/gchq/CyberChef/commit/760eff49b5307aaa3104c5e5b437ffe62299acd1
[65ffd8d]: https://github.com/gchq/CyberChef/commit/65ffd8d65d88eb369f6f61a5d1d0f807179bffb7
[0a353ee]: https://github.com/gchq/CyberChef/commit/0a353eeb378b9ca5d49e23c7dfc175ae07107b08
[#95]: https://github.com/gchq/CyberChef/pull/299
[#173]: https://github.com/gchq/CyberChef/pull/173
@@ -629,4 +748,34 @@ All major and minor version changes will be documented in this file. Details of
[#1498]: https://github.com/gchq/CyberChef/pull/1498
[#1499]: https://github.com/gchq/CyberChef/pull/1499
[#1528]: https://github.com/gchq/CyberChef/pull/1528
[#661]: https://github.com/gchq/CyberChef/pull/661
[#493]: https://github.com/gchq/CyberChef/pull/493
[#592]: https://github.com/gchq/CyberChef/issues/592
[#1703]: https://github.com/gchq/CyberChef/issues/1703
[#1675]: https://github.com/gchq/CyberChef/issues/1675
[#1678]: https://github.com/gchq/CyberChef/issues/1678
[#1541]: https://github.com/gchq/CyberChef/issues/1541
[#1667]: https://github.com/gchq/CyberChef/issues/1667
[#1555]: https://github.com/gchq/CyberChef/issues/1555
[#1694]: https://github.com/gchq/CyberChef/issues/1694
[#1699]: https://github.com/gchq/CyberChef/issues/1699
[#1757]: https://github.com/gchq/CyberChef/issues/1757
[#1752]: https://github.com/gchq/CyberChef/issues/1752
[#1753]: https://github.com/gchq/CyberChef/issues/1753
[#1750]: https://github.com/gchq/CyberChef/issues/1750
[#1591]: https://github.com/gchq/CyberChef/issues/1591
[#654]: https://github.com/gchq/CyberChef/issues/654
[#1762]: https://github.com/gchq/CyberChef/issues/1762
[#1606]: https://github.com/gchq/CyberChef/issues/1606
[#1197]: https://github.com/gchq/CyberChef/issues/1197
[#933]: https://github.com/gchq/CyberChef/issues/933
[#1361]: https://github.com/gchq/CyberChef/issues/1361
[#1765]: https://github.com/gchq/CyberChef/issues/1765
[#1767]: https://github.com/gchq/CyberChef/issues/1767
[#1769]: https://github.com/gchq/CyberChef/issues/1769
[#1759]: https://github.com/gchq/CyberChef/issues/1759
[#1504]: https://github.com/gchq/CyberChef/issues/1504
[#512]: https://github.com/gchq/CyberChef/issues/512
[#1732]: https://github.com/gchq/CyberChef/issues/1732
[#1789]: https://github.com/gchq/CyberChef/issues/1789
+32
View File
@@ -0,0 +1,32 @@
#####################################
# Build the app to a static website #
#####################################
# Modifier --platform=$BUILDPLATFORM limits the platform to "BUILDPLATFORM" during buildx multi-platform builds
# This is because npm "chromedriver" package is not compatiable with all platforms
# For more info see: https://docs.docker.com/build/building/multi-platform/#cross-compilation
FROM --platform=$BUILDPLATFORM node:18-alpine AS builder
WORKDIR /app
COPY package.json .
COPY package-lock.json .
# Install dependencies
# --ignore-scripts prevents postinstall script (which runs grunt) as it depends on files other than package.json
RUN npm ci --ignore-scripts
# Copy files needed for postinstall and build
COPY . .
# npm postinstall runs grunt, which depends on files other than package.json
RUN npm run postinstall
# Build the app
RUN npm run build
#########################################
# Package static build files into nginx #
#########################################
FROM nginx:stable-alpine AS cyberchef
COPY --from=builder /app/build/prod /usr/share/nginx/html/
+18 -1
View File
@@ -86,10 +86,12 @@ module.exports = function (grunt) {
// Project configuration
const compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC",
const compileYear = grunt.template.today("UTC:yyyy"),
compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC",
pkg = grunt.file.readJSON("package.json"),
webpackConfig = require("./webpack.config.js"),
BUILD_CONSTANTS = {
COMPILE_YEAR: JSON.stringify(compileYear),
COMPILE_TIME: JSON.stringify(compileTime),
COMPILE_MSG: JSON.stringify(grunt.option("compile-msg") || grunt.option("msg") || ""),
PKG_VERSION: JSON.stringify(pkg.version),
@@ -125,6 +127,7 @@ module.exports = function (grunt) {
filename: "index.html",
template: "./src/web/html/index.html",
chunks: ["main"],
compileYear: compileYear,
compileTime: compileTime,
version: pkg.version,
minify: {
@@ -197,6 +200,7 @@ module.exports = function (grunt) {
},
webpack: {
options: webpackConfig,
myConfig: webpackConfig,
web: webpackProdConf(),
},
"webpack-dev-server": {
@@ -226,6 +230,7 @@ module.exports = function (grunt) {
filename: "index.html",
template: "./src/web/html/index.html",
chunks: ["main"],
compileYear: compileYear,
compileTime: compileTime,
version: pkg.version,
})
@@ -426,6 +431,18 @@ module.exports = function (grunt) {
}
},
stdout: false
},
fixJimpModule: {
command: function () {
switch (process.platform) {
case "darwin":
// Space added before comma to prevent multiple modifications
return `sed -i '' 's/"es\\/index.js",/"es\\/index.js" ,\\n "type": "module",/' ./node_modules/jimp/package.json`;
default:
return `sed -i 's/"es\\/index.js",/"es\\/index.js" ,\\n "type": "module",/' ./node_modules/jimp/package.json`;
}
},
stdout: false
}
},
});
+18 -2
View File
@@ -20,6 +20,22 @@ Cryptographic operations in CyberChef should not be relied upon to provide secur
[A live demo can be found here][1] - have fun!
## Containers
If you would like to try out CyberChef locally you can either build it yourself:
```bash
docker build --tag cyberchef --ulimit nofile=10000 .
docker run -it -p 8080:80 cyberchef
```
Or you can use our image directly:
```bash
docker run -it -p 8080:80 ghcr.io/gchq/cyberchef:latest
```
This image is built and published through our [GitHub Workflows](.github/workflows/releases.yml)
## How it works
@@ -89,14 +105,14 @@ CyberChef is built to support
## Node.js support
CyberChef is built to fully support Node.js `v16`. For more information, see the Node API page in the project [wiki pages](https://github.com/gchq/CyberChef/wiki)
CyberChef is built to fully support Node.js `v16`. For more information, see the ["Node API" wiki page](https://github.com/gchq/CyberChef/wiki/Node-API)
## Contributing
Contributing a new operation to CyberChef is super easy! The quickstart script will walk you through the process. If you can write basic JavaScript, you can write a CyberChef operation.
An installation walkthrough, how-to guides for adding new operations and themes, descriptions of the repository structure, available data types and coding conventions can all be found in the project [wiki pages](https://github.com/gchq/CyberChef/wiki).
An installation walkthrough, how-to guides for adding new operations and themes, descriptions of the repository structure, available data types and coding conventions can all be found in the ["Contributing" wiki page](https://github.com/gchq/CyberChef/wiki/Contributing).
- Push your changes to your fork.
- Submit a pull request. If you are doing this for the first time, you will be prompted to sign the [GCHQ Contributor Licence Agreement](https://cla-assistant.io/gchq/CyberChef) via the CLA assistant on the pull request. This will also ask whether you are happy for GCHQ to contact you about a token of thanks for your contribution, or about job opportunities at GCHQ.
+129
View File
@@ -0,0 +1,129 @@
import babelParser from "@babel/eslint-parser";
import jsdoc from "eslint-plugin-jsdoc";
import js from "@eslint/js";
import globals from "globals";
export default [
js.configs.recommended,
{
languageOptions: {
ecmaVersion: 2022,
parser: babelParser,
parserOptions: {
ecmaVersion: 2022,
ecmaFeatures: {
impliedStrict: true
},
sourceType: "module",
allowImportExportEverywhere: true
},
globals: {
...globals.browser,
...globals.node,
...globals.es6,
"$": false,
"jQuery": false,
"log": false,
"app": false,
"COMPILE_TIME": false,
"COMPILE_MSG": false,
"PKG_VERSION": false
},
},
ignores: ["src/core/vendor/**"],
plugins: {
jsdoc
},
rules: {
// enable additional rules
"no-eval": "error",
"no-implied-eval": "error",
"dot-notation": "error",
"eqeqeq": ["error", "smart"],
"no-caller": "error",
"no-extra-bind": "error",
"no-unused-expressions": "error",
"no-useless-call": "error",
"no-useless-return": "error",
"radix": "warn",
// modify rules from base configurations
"no-unused-vars": ["error", {
"args": "none",
"vars": "all",
"caughtErrors": "none"
}],
"no-empty": ["error", {
"allowEmptyCatch": true
}],
// disable rules from base configurations
"no-control-regex": "off",
"require-atomic-updates": "off",
"no-async-promise-executor": "off",
// stylistic conventions
"brace-style": ["error", "1tbs"],
"space-before-blocks": ["error", "always"],
"block-spacing": "error",
"array-bracket-spacing": "error",
"comma-spacing": "error",
"spaced-comment": ["error", "always", { "exceptions": ["/"] }],
"comma-style": "error",
"computed-property-spacing": "error",
"no-trailing-spaces": "warn",
"eol-last": "error",
"func-call-spacing": "error",
"key-spacing": ["warn", {
"mode": "minimum"
}],
"indent": ["error", 4, {
"ignoreComments": true,
"ArrayExpression": "first",
"SwitchCase": 1
}],
"linebreak-style": ["error", "unix"],
"quotes": ["error", "double", {
"avoidEscape": true,
"allowTemplateLiterals": true
}],
"camelcase": ["error", {
"properties": "always"
}],
"semi": ["error", "always"],
"unicode-bom": "error",
"jsdoc/require-jsdoc": ["error", {
"require": {
"FunctionDeclaration": true,
"MethodDefinition": true,
"ClassDeclaration": true,
"ArrowFunctionExpression": false
}
}],
"keyword-spacing": ["error", {
"before": true,
"after": true
}],
"no-multiple-empty-lines": ["warn", {
"max": 2,
"maxEOF": 1,
"maxBOF": 0
}],
"no-whitespace-before-property": "error",
"operator-linebreak": ["error", "after"],
"space-in-parens": "error",
"no-var": "error",
"prefer-const": "error",
"no-console": "error"
},
},
// File-pattern specific overrides
{
files: ["tests/**/*"],
rules: {
"no-unused-expressions": "off",
"no-console": "off"
}
},
];
+9498 -13249
View File
File diff suppressed because it is too large Load Diff
+82 -66
View File
@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "10.2.0",
"version": "10.19.4",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef",
@@ -39,54 +39,59 @@
"node >= 16"
],
"devDependencies": {
"@babel/core": "^7.21.0",
"@babel/eslint-parser": "^7.19.1",
"@babel/plugin-syntax-import-assertions": "^7.20.0",
"@babel/plugin-transform-runtime": "^7.21.0",
"@babel/preset-env": "^7.20.2",
"@babel/runtime": "^7.21.0",
"@codemirror/commands": "^6.2.1",
"@codemirror/language": "^6.6.0",
"@codemirror/search": "^6.2.3",
"@codemirror/state": "^6.2.0",
"@codemirror/view": "^6.9.2",
"autoprefixer": "^10.4.13",
"babel-loader": "^9.1.2",
"@babel/core": "^7.24.7",
"@babel/eslint-parser": "^7.24.7",
"@babel/plugin-syntax-import-assertions": "^7.24.7",
"@babel/plugin-transform-runtime": "^7.24.7",
"@babel/preset-env": "^7.24.7",
"@babel/runtime": "^7.24.7",
"@codemirror/commands": "^6.6.0",
"@codemirror/language": "^6.10.2",
"@codemirror/search": "^6.5.6",
"@codemirror/state": "^6.4.1",
"@codemirror/view": "^6.28.0",
"autoprefixer": "^10.4.19",
"babel-loader": "^9.1.3",
"babel-plugin-dynamic-import-node": "^2.3.3",
"babel-plugin-transform-builtin-extend": "1.1.2",
"chromedriver": "^110.0.0",
"base64-loader": "^1.0.0",
"chromedriver": "^130.0.0",
"cli-progress": "^3.12.0",
"colors": "^1.4.0",
"copy-webpack-plugin": "^11.0.0",
"core-js": "^3.29.0",
"css-loader": "6.7.3",
"eslint": "^8.35.0",
"compression-webpack-plugin": "^11.1.0",
"copy-webpack-plugin": "^12.0.2",
"core-js": "^3.37.1",
"cspell": "^8.17.3",
"css-loader": "7.1.2",
"eslint": "^9.4.0",
"eslint-plugin-jsdoc": "^48.2.9",
"globals": "^15.4.0",
"grunt": "^1.6.1",
"grunt-chmod": "~1.1.1",
"grunt-concurrent": "^3.0.0",
"grunt-contrib-clean": "~2.0.1",
"grunt-contrib-connect": "^3.0.0",
"grunt-contrib-connect": "^4.0.0",
"grunt-contrib-copy": "~1.0.0",
"grunt-contrib-watch": "^1.1.0",
"grunt-eslint": "^24.0.1",
"grunt-eslint": "^25.0.0",
"grunt-exec": "~3.0.0",
"grunt-webpack": "^5.0.0",
"grunt-zip": "^0.20.0",
"html-webpack-plugin": "^5.5.0",
"imports-loader": "^4.0.1",
"mini-css-extract-plugin": "2.7.3",
"modify-source-webpack-plugin": "^3.0.0",
"nightwatch": "^2.6.16",
"postcss": "^8.4.21",
"postcss-css-variables": "^0.18.0",
"postcss-import": "^15.1.0",
"postcss-loader": "^7.0.2",
"grunt-webpack": "^6.0.0",
"grunt-zip": "^1.0.0",
"html-webpack-plugin": "^5.6.0",
"imports-loader": "^5.0.0",
"mini-css-extract-plugin": "2.9.0",
"modify-source-webpack-plugin": "^4.1.0",
"nightwatch": "^3.6.3",
"postcss": "^8.4.38",
"postcss-css-variables": "^0.19.0",
"postcss-import": "^16.1.0",
"postcss-loader": "^8.1.1",
"prompt": "^1.3.0",
"sitemap": "^7.1.1",
"terser": "^5.16.6",
"webpack": "^5.76.0",
"webpack-bundle-analyzer": "^4.8.0",
"webpack-dev-server": "4.11.1",
"sitemap": "^8.0.0",
"terser": "^5.31.1",
"webpack": "^5.91.0",
"webpack-bundle-analyzer": "^4.10.2",
"webpack-dev-server": "5.0.4",
"webpack-node-externals": "^3.0.0",
"worker-loader": "^3.0.8"
},
@@ -94,10 +99,13 @@
"@astronautlabs/amf": "^0.0.6",
"@babel/polyfill": "^7.12.1",
"@blu3r4y/lzma": "^2.3.3",
"@wavesenterprise/crypto-gost-js": "^2.1.0-RC1",
"@xmldom/xmldom": "^0.8.10",
"argon2-browser": "^1.18.0",
"arrive": "^2.4.1",
"avsc": "^5.7.7",
"bcryptjs": "^2.4.3",
"bignumber.js": "^9.1.1",
"bignumber.js": "^9.1.2",
"blakejs": "^1.2.1",
"bootstrap": "4.6.2",
"bootstrap-colorpicker": "^3.4.0",
@@ -105,45 +113,51 @@
"browserify-zlib": "^0.2.0",
"bson": "^4.7.2",
"buffer": "^6.0.3",
"cbor": "8.1.0",
"cbor": "9.0.2",
"chi-squared": "^1.1.0",
"codepage": "^1.15.0",
"crypto-api": "^0.8.5",
"crypto-browserify": "^3.12.0",
"crypto-js": "^4.1.1",
"crypto-js": "^4.2.0",
"ctph.js": "0.0.5",
"d3": "7.8.2",
"d3": "7.9.0",
"d3-hexbin": "^0.2.2",
"diff": "^5.1.0",
"diff": "^5.2.0",
"dompurify": "^3.2.5",
"es6-promisify": "^7.0.0",
"escodegen": "^2.0.0",
"escodegen": "^2.1.0",
"esprima": "^4.0.1",
"exif-parser": "^0.1.12",
"fernet": "^0.4.0",
"file-saver": "^2.0.5",
"flat": "^5.0.2",
"flat": "^6.0.1",
"geodesy": "1.1.3",
"highlight.js": "^11.7.0",
"jimp": "^0.16.13",
"jquery": "3.6.4",
"js-crc": "^0.2.0",
"js-sha3": "^0.8.0",
"handlebars": "^4.7.8",
"hash-wasm": "^4.12.0",
"highlight.js": "^11.9.0",
"ieee754": "^1.2.1",
"jimp": "^0.22.12",
"jq-web": "^0.5.1",
"jquery": "3.7.1",
"js-sha3": "^0.9.3",
"jsesc": "^3.0.2",
"json5": "^2.2.3",
"jsonpath-plus": "^7.2.0",
"jsonata": "^2.0.3",
"jsonpath-plus": "^9.0.0",
"jsonwebtoken": "8.5.1",
"jsqr": "^1.4.0",
"jsrsasign": "^10.6.1",
"jsrsasign": "^11.1.0",
"kbpgp": "2.1.15",
"libbzip2-wasm": "0.0.4",
"libyara-wasm": "^1.2.1",
"lodash": "^4.17.21",
"loglevel": "^1.8.1",
"loglevel": "^1.9.1",
"loglevel-message-prefix": "^3.0.0",
"lz-string": "^1.5.0",
"lz4js": "^0.2.0",
"markdown-it": "^13.0.1",
"moment": "^2.29.4",
"moment-timezone": "^0.5.41",
"markdown-it": "^14.1.0",
"moment": "^2.30.1",
"moment-timezone": "^0.5.45",
"ngeohash": "^0.6.3",
"node-forge": "^1.3.1",
"node-md6": "^0.1.0",
@@ -151,26 +165,27 @@
"notepack.io": "^3.0.1",
"ntlm": "^0.1.3",
"nwmatcher": "^1.4.4",
"otp": "0.1.3",
"otpauth": "9.3.6",
"path": "^0.12.7",
"popper.js": "^1.16.1",
"process": "^0.11.10",
"protobufjs": "^7.2.2",
"protobufjs": "^7.3.1",
"qr-image": "^3.2.0",
"reflect-metadata": "^0.1.13",
"reflect-metadata": "^0.2.2",
"rison": "^0.1.1",
"scryptsy": "^2.1.0",
"snackbarjs": "^1.1.0",
"sortablejs": "^1.15.0",
"sortablejs": "^1.15.2",
"split.js": "^1.6.5",
"ssdeep.js": "0.0.3",
"stream-browserify": "^3.0.0",
"tesseract.js": "3.0.3",
"ua-parser-js": "^1.0.34",
"tesseract.js": "5.1.0",
"ua-parser-js": "^1.0.38",
"unorm": "^1.6.0",
"utf8": "^3.0.0",
"uuid": "^11.1.0",
"vkbeautify": "^0.99.3",
"xmldom": "^0.6.0",
"xpath": "0.0.32",
"xpath": "0.0.34",
"xregexp": "^5.1.1",
"zlibjs": "^0.3.1"
},
@@ -178,13 +193,14 @@
"start": "npx grunt dev",
"build": "npx grunt prod",
"node": "npx grunt node",
"repl": "node --experimental-modules --experimental-json-modules --experimental-specifier-resolution=node --no-warnings src/node/repl.mjs",
"test": "npx grunt configTests && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation --openssl-legacy-provider tests/node/index.mjs && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation --openssl-legacy-provider tests/operations/index.mjs",
"repl": "node --experimental-modules --experimental-json-modules --experimental-specifier-resolution=node --no-experimental-fetch --no-warnings src/node/repl.mjs",
"test": "npx grunt configTests && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation --openssl-legacy-provider --no-experimental-fetch tests/node/index.mjs && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation --openssl-legacy-provider --no-experimental-fetch --trace-uncaught tests/operations/index.mjs",
"testnodeconsumer": "npx grunt testnodeconsumer",
"testui": "npx grunt testui",
"testuidev": "npx nightwatch --env=dev",
"lint": "npx grunt lint",
"postinstall": "npx grunt exec:fixCryptoApiImports && npx grunt exec:fixSnackbarMarkup",
"lint:grammar": "cspell ./src",
"postinstall": "npx grunt exec:fixCryptoApiImports && npx grunt exec:fixSnackbarMarkup && npx grunt exec:fixJimpModule",
"newop": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newOperation.mjs",
"minor": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newMinorVersion.mjs",
"getheapsize": "node -e 'console.log(`node heap limit = ${require(\"v8\").getHeapStatistics().heap_size_limit / (1024 * 1024)} Mb`)'",
+17
View File
@@ -892,6 +892,23 @@ class Utils {
}
/**
* Converts a string to its title case equivalent.
*
* @param {string} str
* @returns string
*
* @example
* // return "A Tiny String"
* Utils.toTitleCase("a tIny String");
*/
static toTitleCase(str) {
return str.replace(/\w\S*/g, function(txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
}
/**
* Encodes a URI fragment (#) or query (?) using a minimal amount of percent-encoding.
*
+74 -11
View File
@@ -14,6 +14,8 @@
"From Charcode",
"To Decimal",
"From Decimal",
"To Float",
"From Float",
"To Binary",
"From Binary",
"To Octal",
@@ -29,6 +31,8 @@
"To Base64",
"From Base64",
"Show Base64 offsets",
"To Base92",
"From Base92",
"To Base85",
"From Base85",
"To Base",
@@ -67,7 +71,15 @@
"JSON to CSV",
"Avro to JSON",
"CBOR Encode",
"CBOR Decode"
"CBOR Decode",
"YAML to JSON",
"JSON to YAML",
"Caret/M-decode",
"Rison Encode",
"Rison Decode",
"To Modhex",
"From Modhex",
"MIME Decoding"
]
},
{
@@ -81,6 +93,8 @@
"DES Decrypt",
"Triple DES Encrypt",
"Triple DES Decrypt",
"Fernet Encrypt",
"Fernet Decrypt",
"LS47 Encrypt",
"LS47 Decrypt",
"RC2 Encrypt",
@@ -88,9 +102,17 @@
"RC4",
"RC4 Drop",
"ChaCha",
"Salsa20",
"XSalsa20",
"Rabbit",
"SM4 Encrypt",
"SM4 Decrypt",
"GOST Encrypt",
"GOST Decrypt",
"GOST Sign",
"GOST Verify",
"GOST Key Wrap",
"GOST Key Unwrap",
"ROT13",
"ROT13 Brute Force",
"ROT47",
@@ -100,6 +122,8 @@
"XOR Brute Force",
"Vigenère Encode",
"Vigenère Decode",
"XXTEA Encrypt",
"XXTEA Decrypt",
"To Morse Code",
"From Morse Code",
"Bacon Cipher Encode",
@@ -145,11 +169,14 @@
"name": "Public Key",
"ops": [
"Parse X.509 certificate",
"Parse X.509 CRL",
"Parse ASN.1 hex string",
"PEM to Hex",
"Hex to PEM",
"Hex to Object Identifier",
"Object Identifier to Hex",
"PEM to JWK",
"JWK to PEM",
"Generate PGP Key Pair",
"PGP Encrypt",
"PGP Decrypt",
@@ -161,7 +188,16 @@
"RSA Verify",
"RSA Encrypt",
"RSA Decrypt",
"Parse SSH Host Key"
"Generate ECDSA Key Pair",
"ECDSA Signature Conversion",
"ECDSA Sign",
"ECDSA Verify",
"Parse SSH Host Key",
"Parse CSR",
"Public Key from Certificate",
"Public Key from Private Key",
"SM2 Encrypt",
"SM2 Decrypt"
]
},
{
@@ -205,9 +241,14 @@
"Parse User Agent",
"Parse IP range",
"Parse IPv6 address",
"IPv6 Transition Addresses",
"Parse IPv4 header",
"Strip IPv4 header",
"Parse TCP",
"Strip TCP header",
"Parse TLS record",
"Parse UDP",
"Strip UDP header",
"Parse SSH Host Key",
"Parse URI",
"URL Encode",
@@ -218,6 +259,8 @@
"VarInt Decode",
"JA3 Fingerprint",
"JA3S Fingerprint",
"JA4 Fingerprint",
"JA4Server Fingerprint",
"HASSH Client Fingerprint",
"HASSH Server Fingerprint",
"Format MAC addresses",
@@ -226,6 +269,7 @@
"Encode NetBIOS Name",
"Decode NetBIOS Name",
"Defang URL",
"Fang URL",
"Defang IP Addresses"
]
},
@@ -237,7 +281,8 @@
"Unicode Text Format",
"Remove Diacritics",
"Unescape Unicode Characters",
"Convert to NATO alphabet"
"Convert to NATO alphabet",
"Convert Leet Speak"
]
},
{
@@ -249,6 +294,7 @@
"To Upper case",
"To Lower case",
"Swap case",
"Alternating Caps",
"To Case Insensitive Regex",
"From Case Insensitive Regex",
"Add line numbers",
@@ -288,7 +334,10 @@
"Escape string",
"Unescape string",
"Pseudo-Random Number Generator",
"Sleep"
"Sleep",
"File Tree",
"Take nth bytes",
"Drop nth bytes"
]
},
{
@@ -300,6 +349,7 @@
"To UNIX Timestamp",
"Windows Filetime to UNIX Timestamp",
"UNIX Timestamp to Windows Filetime",
"DateTime Delta",
"Extract dates",
"Get Time",
"Sleep"
@@ -316,13 +366,17 @@
"Extract domains",
"Extract file paths",
"Extract dates",
"Extract hashes",
"Regular expression",
"XPath expression",
"JPath expression",
"Jsonata Query",
"CSS selector",
"Extract EXIF",
"Extract ID3",
"Extract Files"
"Extract Files",
"RAKE",
"Template"
]
},
{
@@ -345,13 +399,15 @@
"LZMA Decompress",
"LZMA Compress",
"LZ4 Decompress",
"LZ4 Compress"
"LZ4 Compress",
"LZNT1 Decompress"
]
},
{
"name": "Hashing",
"ops": [
"Analyse hash",
"Generate all checksums",
"Generate all hashes",
"MD2",
"MD4",
@@ -370,7 +426,8 @@
"Snefru",
"BLAKE2b",
"BLAKE2s",
"GOST hash",
"BLAKE3",
"GOST Hash",
"Streebog",
"SSDEEP",
"CTPH",
@@ -381,19 +438,21 @@
"Bcrypt",
"Bcrypt compare",
"Bcrypt parse",
"Argon2",
"Argon2 compare",
"Scrypt",
"NT Hash",
"LM Hash",
"MurmurHash3",
"Fletcher-8 Checksum",
"Fletcher-16 Checksum",
"Fletcher-32 Checksum",
"Fletcher-64 Checksum",
"Adler-32 Checksum",
"Luhn Checksum",
"CRC-8 Checksum",
"CRC-16 Checksum",
"CRC-32 Checksum",
"TCP/IP Checksum"
"CRC Checksum",
"TCP/IP Checksum",
"XOR Checksum"
]
},
{
@@ -414,8 +473,10 @@
"CSS Minify",
"XPath expression",
"JPath expression",
"Jq",
"CSS selector",
"PHP Deserialize",
"PHP Serialize",
"Microsoft Script Decoder",
"Strip HTML tags",
"Diff",
@@ -488,7 +549,9 @@
"P-list Viewer",
"Disassemble x86",
"Pseudo-Random Number Generator",
"Generate De Bruijn Sequence",
"Generate UUID",
"Analyse UUID",
"Generate TOTP",
"Generate HOTP",
"Generate QR Code",
+6 -6
View File
@@ -30,12 +30,12 @@ fs.readdirSync(path.join(dir, "../operations")).forEach(file => {
// Construct index file
let code = `/**
* THIS FILE IS AUTOMATICALLY GENERATED BY src/core/config/scripts/generateOpsIndex.mjs
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright ${new Date().getUTCFullYear()}
* @license Apache-2.0
*/
* THIS FILE IS AUTOMATICALLY GENERATED BY src/core/config/scripts/generateOpsIndex.mjs
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright ${new Date().getUTCFullYear()}
* @license Apache-2.0
*/
`;
opObjs.forEach(obj => {
+1 -1
View File
@@ -147,7 +147,7 @@ class ${moduleName} extends Operation {
this.name = "${result.opName}";
this.module = "${result.module}";
this.description = "${(new EscapeString).run(result.description, ["Special chars", "Double"])}";
this.infoURL = "${result.infoURL}";
this.infoURL = "${result.infoURL}"; // Usually a Wikipedia link. Remember to remove localisation (i.e. https://wikipedia.org/etc rather than https://en.wikipedia.org/etc)
this.inputType = "${result.inputType}";
this.outputType = "${result.outputType}";
this.args = [
+23
View File
@@ -0,0 +1,23 @@
// import Utils from "../Utils.mjs";
/**
* Base32 resources.
*
* @author Peter C-S [petercs@purelymail.com]
* @license Apache-2.0
*/
/**
* Base32 alphabets.
*/
export const ALPHABET_OPTIONS = [
{
name: "Standard", // https://www.rfc-editor.org/rfc/rfc4648#section-6
value: "A-Z2-7=",
},
{
name: "Hex Extended", // https://www.rfc-editor.org/rfc/rfc4648#section-7
value: "0-9A-V=",
},
];
+44
View File
@@ -0,0 +1,44 @@
/**
* Base92 resources.
*
* @author sg5506844 [sg5506844@gmail.com]
* @copyright Crown Copyright 2021
* @license Apache-2.0
*/
import OperationError from "../errors/OperationError.mjs";
/**
* Base92 alphabet char
*
* @param {number} val
* @returns {number}
*/
export function base92Chr(val) {
if (val < 0 || val >= 91) {
throw new OperationError("Invalid value");
}
if (val === 0)
return "!".charCodeAt(0);
else if (val <= 61)
return "#".charCodeAt(0) + val - 1;
else
return "a".charCodeAt(0) + val - 62;
}
/**
* Base92 alphabet ord
*
* @param {string} val
* @returns {number}
*/
export function base92Ord(val) {
if (val === "!")
return 0;
else if ("#" <= val && val <= "_")
return val.charCodeAt(0) - "#".charCodeAt(0) + 1;
else if ("a" <= val && val <= "}")
return val.charCodeAt(0) - "a".charCodeAt(0) + 62;
throw new OperationError(`${val} is not a base92 character`);
}
+79 -2
View File
@@ -224,8 +224,85 @@ export function chrEncWidth(page) {
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
export const UNICODE_NORMALISATION_FORMS = ["NFD", "NFC", "NFKD", "NFKC"];
/**
* Character encoding format mappings.
* Detects whether the input buffer is valid UTF8.
*
* @param {ArrayBuffer} data
* @returns {number} - 0 = not UTF8, 1 = ASCII, 2 = UTF8
*/
export const UNICODE_NORMALISATION_FORMS = ["NFD", "NFC", "NFKD", "NFKC"];
export function isUTF8(data) {
const bytes = new Uint8Array(data);
let i = 0;
let onlyASCII = true;
while (i < bytes.length) {
if (( // ASCII
bytes[i] === 0x09 ||
bytes[i] === 0x0A ||
bytes[i] === 0x0D ||
(0x20 <= bytes[i] && bytes[i] <= 0x7E)
)) {
i += 1;
continue;
}
onlyASCII = false;
if (( // non-overlong 2-byte
(0xC2 <= bytes[i] && bytes[i] <= 0xDF) &&
(0x80 <= bytes[i+1] && bytes[i+1] <= 0xBF)
)) {
i += 2;
continue;
}
if (( // excluding overlongs
bytes[i] === 0xE0 &&
(0xA0 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
(0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF)
) ||
( // straight 3-byte
((0xE1 <= bytes[i] && bytes[i] <= 0xEC) ||
bytes[i] === 0xEE ||
bytes[i] === 0xEF) &&
(0x80 <= bytes[i + 1] && bytes[i+1] <= 0xBF) &&
(0x80 <= bytes[i+2] && bytes[i+2] <= 0xBF)
) ||
( // excluding surrogates
bytes[i] === 0xED &&
(0x80 <= bytes[i+1] && bytes[i+1] <= 0x9F) &&
(0x80 <= bytes[i+2] && bytes[i+2] <= 0xBF)
)) {
i += 3;
continue;
}
if (( // planes 1-3
bytes[i] === 0xF0 &&
(0x90 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
(0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) &&
(0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF)
) ||
( // planes 4-15
(0xF1 <= bytes[i] && bytes[i] <= 0xF3) &&
(0x80 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
(0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) &&
(0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF)
) ||
( // plane 16
bytes[i] === 0xF4 &&
(0x80 <= bytes[i + 1] && bytes[i + 1] <= 0x8F) &&
(0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) &&
(0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF)
)) {
i += 4;
continue;
}
return 0;
}
return onlyASCII ? 1 : 2;
}
+1 -1
View File
@@ -4,7 +4,7 @@
* @license Apache-2.0
*/
export function encode(tempIVP, key, rounds, input) {
const ivp = new Uint8Array(key.concat(tempIVP));
const ivp = new Uint8Array([...key, ...tempIVP]);
const state = new Array(256).fill(0);
let j = 0, i = 0;
const result = [];
+6
View File
@@ -3,6 +3,7 @@
*
* @author Matt C [matt@artemisbot.uk]
* @author n1474335 [n1474335@gmail.com]
* @author Evie H [evie@evie.sh]
*
* @copyright Crown Copyright 2018
* @license Apache-2.0
@@ -10,6 +11,7 @@
*/
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import CryptoJS from "crypto-js";
/**
@@ -30,6 +32,10 @@ export function affineEncode(input, args) {
throw new OperationError("The values of a and b can only be integers.");
}
if (Utils.gcd(a, 26) !== 1) {
throw new OperationError("The value of `a` must be coprime to 26.");
}
for (let i = 0; i < input.length; i++) {
if (alphabet.indexOf(input[i]) >= 0) {
// Uses the affine function ax+b % m = y (where m is length of the alphabet)
+6
View File
@@ -62,3 +62,9 @@ export const URL_REGEX = new RegExp(protocol + hostname + "(?:" + port + ")?(?:"
* 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;
/**
* DMARC Domain name regular expression
*/
export const DMARC_DOMAIN_REGEX = /\b((?=[a-z0-9_-]{1,63}\.)(xn--)?[a-z0-9_]+(-[a-z0-9_]+)*\.)+[a-z]{2,63}\b/ig;
+22 -1
View File
@@ -72,6 +72,27 @@ export const FILE_SIGNATURES = {
},
extractor: extractWEBP
},
{
name: "High Efficiency Image File Format",
extension: "heic,heif",
mime: "image/heif",
description: "",
signature: {
0: 0x00,
1: 0x00,
2: 0x00,
3: [0x24, 0x18],
4: 0x66, // ftypheic
5: 0x74,
6: 0x79,
7: 0x70,
8: 0x68,
9: 0x65,
10: 0x69,
11: 0x63
},
extractor: null
},
{
name: "Camera Image File Format",
extension: "crw",
@@ -2727,7 +2748,7 @@ export function extractGIF(bytes, offset) {
stream.moveForwardsBy(11);
// Loop until next Graphic Control Extension.
while (stream.getBytes(2) !== [0x21, 0xf9]) {
while (!Array.from(stream.getBytes(2)).equals([0x21, 0xf9])) {
stream.moveBackwardsBy(2);
stream.moveForwardsBy(stream.readInt(1));
if (!stream.readInt(1))
+264
View File
@@ -0,0 +1,264 @@
/**
* JA4 resources.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2024
* @license Apache-2.0
*
* JA4 Copyright 2023 FoxIO, LLC.
* @license BSD-3-Clause
*/
import OperationError from "../errors/OperationError.mjs";
import { parseTLSRecord, parseHighestSupportedVersion, parseFirstALPNValue } from "./TLS.mjs";
import { toHexFast } from "./Hex.mjs";
import { runHash } from "./Hash.mjs";
import Utils from "../Utils.mjs";
/**
* Calculate the JA4 from a given TLS Client Hello Stream
* @param {Uint8Array} bytes
* @returns {string}
*/
export function toJA4(bytes) {
let tlsr = {};
try {
tlsr = parseTLSRecord(bytes);
if (tlsr.handshake.value.handshakeType.value !== 0x01) {
throw new Error();
}
} catch (err) {
throw new OperationError("Data is not a valid TLS Client Hello. QUIC is not yet supported.\n" + err);
}
/* QUIC
“q” or “t”, which denotes whether the hello packet is for QUIC or TCP.
TODO: Implement QUIC
*/
const ptype = "t";
/* TLS Version
TLS version is shown in 3 different places. If extension 0x002b exists (supported_versions), then the version
is the highest value in the extension. Remember to ignore GREASE values. If the extension doesn’t exist, then
the TLS version is the value of the Protocol Version. Handshake version (located at the top of the packet)
should be ignored.
*/
let version = tlsr.handshake.value.helloVersion.value;
for (const ext of tlsr.handshake.value.extensions.value) {
if (ext.type.value === "supported_versions") {
version = parseHighestSupportedVersion(ext.value.data);
break;
}
}
version = tlsVersionMapper(version);
/* SNI
If the SNI extension (0x0000) exists, then the destination of the connection is a domain, or “d” in the fingerprint.
If the SNI does not exist, then the destination is an IP address, or “i”.
*/
let sni = "i";
for (const ext of tlsr.handshake.value.extensions.value) {
if (ext.type.value === "server_name") {
sni = "d";
break;
}
}
/* Number of Ciphers
2 character number of cipher suites, so if there’s 6 cipher suites in the hello packet, then the value should be “06”.
If there’s > 99, which there should never be, then output “99”. Remember, ignore GREASE values. They don’t count.
*/
let cipherLen = 0;
for (const cs of tlsr.handshake.value.cipherSuites.value) {
if (cs.value !== "GREASE") cipherLen++;
}
cipherLen = cipherLen > 99 ? "99" : cipherLen.toString().padStart(2, "0");
/* Number of Extensions
Same as counting ciphers. Ignore GREASE. Include SNI and ALPN.
*/
let extLen = 0;
for (const ext of tlsr.handshake.value.extensions.value) {
if (ext.type.value !== "GREASE") extLen++;
}
extLen = extLen > 99 ? "99" : extLen.toString().padStart(2, "0");
/* ALPN Extension Value
The first and last characters of the ALPN (Application-Layer Protocol Negotiation) first value.
If there are no ALPN values or no ALPN extension then we print “00” as the value in the fingerprint.
*/
let alpn = "00";
for (const ext of tlsr.handshake.value.extensions.value) {
if (ext.type.value === "application_layer_protocol_negotiation") {
alpn = parseFirstALPNValue(ext.value.data);
alpn = alpn.charAt(0) + alpn.charAt(alpn.length - 1);
if (alpn.charCodeAt(0) > 127) alpn = "99";
break;
}
}
/* Cipher hash
A 12 character truncated sha256 hash of the list of ciphers sorted in hex order, first 12 characters.
The list is created using the 4 character hex values of the ciphers, lower case, comma delimited, ignoring GREASE.
*/
const originalCiphersList = [];
for (const cs of tlsr.handshake.value.cipherSuites.value) {
if (cs.value !== "GREASE") {
originalCiphersList.push(toHexFast(cs.data));
}
}
const sortedCiphersList = [...originalCiphersList].sort();
const sortedCiphersRaw = sortedCiphersList.join(",");
const originalCiphersRaw = originalCiphersList.join(",");
const sortedCiphers = runHash(
"sha256",
Utils.strToArrayBuffer(sortedCiphersRaw)
).substring(0, 12);
const originalCiphers = runHash(
"sha256",
Utils.strToArrayBuffer(originalCiphersRaw)
).substring(0, 12);
/* Extension hash
A 12 character truncated sha256 hash of the list of extensions, sorted by hex value, followed by the list of signature
algorithms, in the order that they appear (not sorted).
The extension list is created using the 4 character hex values of the extensions, lower case, comma delimited, sorted
(not in the order they appear). Ignore the SNI extension (0000) and the ALPN extension (0010) as we’ve already captured
them in the a section of the fingerprint. These values are omitted so that the same application would have the same b
section of the fingerprint regardless of if it were going to a domain, IP, or changing ALPNs.
*/
const originalExtensionsList = [];
let signatureAlgorithms = "";
for (const ext of tlsr.handshake.value.extensions.value) {
if (ext.type.value !== "GREASE") {
originalExtensionsList.push(toHexFast(ext.type.data));
}
if (ext.type.value === "signature_algorithms") {
signatureAlgorithms = toHexFast(ext.value.data.slice(2));
signatureAlgorithms = signatureAlgorithms.replace(/(.{4})/g, "$1,");
signatureAlgorithms = signatureAlgorithms.substring(0, signatureAlgorithms.length - 1);
}
}
const sortedExtensionsList = [...originalExtensionsList].filter(e => e !== "0000" && e !== "0010").sort();
const sortedExtensionsRaw = sortedExtensionsList.join(",") + "_" + signatureAlgorithms;
const originalExtensionsRaw = originalExtensionsList.join(",") + "_" + signatureAlgorithms;
const sortedExtensions = runHash(
"sha256",
Utils.strToArrayBuffer(sortedExtensionsRaw)
).substring(0, 12);
const originalExtensions = runHash(
"sha256",
Utils.strToArrayBuffer(originalExtensionsRaw)
).substring(0, 12);
return {
"JA4": `${ptype}${version}${sni}${cipherLen}${extLen}${alpn}_${sortedCiphers}_${sortedExtensions}`,
"JA4_o": `${ptype}${version}${sni}${cipherLen}${extLen}${alpn}_${originalCiphers}_${originalExtensions}`,
"JA4_r": `${ptype}${version}${sni}${cipherLen}${extLen}${alpn}_${sortedCiphersRaw}_${sortedExtensionsRaw}`,
"JA4_ro": `${ptype}${version}${sni}${cipherLen}${extLen}${alpn}_${originalCiphersRaw}_${originalExtensionsRaw}`,
};
}
/**
* Calculate the JA4Server from a given TLS Server Hello Stream
* @param {Uint8Array} bytes
* @returns {string}
*/
export function toJA4S(bytes) {
let tlsr = {};
try {
tlsr = parseTLSRecord(bytes);
if (tlsr.handshake.value.handshakeType.value !== 0x02) {
throw new Error();
}
} catch (err) {
throw new OperationError("Data is not a valid TLS Server Hello. QUIC is not yet supported.\n" + err);
}
/* QUIC
“q” or “t”, which denotes whether the hello packet is for QUIC or TCP.
TODO: Implement QUIC
*/
const ptype = "t";
/* TLS Version
TLS version is shown in 3 different places. If extension 0x002b exists (supported_versions), then the version
is the highest value in the extension. Remember to ignore GREASE values. If the extension doesn’t exist, then
the TLS version is the value of the Protocol Version. Handshake version (located at the top of the packet)
should be ignored.
*/
let version = tlsr.handshake.value.helloVersion.value;
for (const ext of tlsr.handshake.value.extensions.value) {
if (ext.type.value === "supported_versions") {
version = parseHighestSupportedVersion(ext.value.data);
break;
}
}
version = tlsVersionMapper(version);
/* Number of Extensions
2 character number of cipher suites, so if there’s 6 cipher suites in the hello packet, then the value should be “06”.
If there’s > 99, which there should never be, then output “99”.
*/
let extLen = tlsr.handshake.value.extensions.value.length;
extLen = extLen > 99 ? "99" : extLen.toString().padStart(2, "0");
/* ALPN Extension Chosen Value
The first and last characters of the ALPN (Application-Layer Protocol Negotiation) first value.
If there are no ALPN values or no ALPN extension then we print “00” as the value in the fingerprint.
*/
let alpn = "00";
for (const ext of tlsr.handshake.value.extensions.value) {
if (ext.type.value === "application_layer_protocol_negotiation") {
alpn = parseFirstALPNValue(ext.value.data);
alpn = alpn.charAt(0) + alpn.charAt(alpn.length - 1);
if (alpn.charCodeAt(0) > 127) alpn = "99";
break;
}
}
/* Chosen Cipher
The hex value of the chosen cipher suite
*/
const cipher = toHexFast(tlsr.handshake.value.cipherSuite.data);
/* Extension hash
A 12 character truncated sha256 hash of the list of extensions.
The extension list is created using the 4 character hex values of the extensions, lower case, comma delimited.
*/
const extensionsList = [];
for (const ext of tlsr.handshake.value.extensions.value) {
extensionsList.push(toHexFast(ext.type.data));
}
const extensionsRaw = extensionsList.join(",");
const extensionsHash = runHash(
"sha256",
Utils.strToArrayBuffer(extensionsRaw)
).substring(0, 12);
return {
"JA4S": `${ptype}${version}${extLen}${alpn}_${cipher}_${extensionsHash}`,
"JA4S_r": `${ptype}${version}${extLen}${alpn}_${cipher}_${extensionsRaw}`,
};
}
/**
* Takes a TLS version value and returns a JA4 TLS version string
* @param {Uint8Array} version - Two byte array of version number
* @returns {string}
*/
function tlsVersionMapper(version) {
switch (version) {
case 0x0304: return "13"; // TLS 1.3
case 0x0303: return "12"; // TLS 1.2
case 0x0302: return "11"; // TLS 1.1
case 0x0301: return "10"; // TLS 1.0
case 0x0300: return "s3"; // SSL 3.0
case 0x0200: return "s2"; // SSL 2.0
case 0x0100: return "s1"; // SSL 1.0
default: return "00"; // Unknown
}
}
+88
View File
@@ -0,0 +1,88 @@
/**
*
* LZNT1 Decompress.
*
* @author 0xThiebaut [thiebaut.dev]
* @copyright Crown Copyright 2023
* @license Apache-2.0
*
* https://github.com/Velocidex/go-ntfs/blob/master/parser%2Flznt1.go
*/
import Utils from "../Utils.mjs";
import OperationError from "../errors/OperationError.mjs";
const COMPRESSED_MASK = 1 << 15,
SIZE_MASK = (1 << 12) - 1;
/**
* @param {number} offset
* @returns {number}
*/
function getDisplacement(offset) {
let result = 0;
while (offset >= 0x10) {
offset >>= 1;
result += 1;
}
return result;
}
/**
* @param {byteArray} compressed
* @returns {byteArray}
*/
export function decompress(compressed) {
const decompressed = Array();
let coffset = 0;
while (coffset + 2 <= compressed.length) {
const doffset = decompressed.length;
const blockHeader = Utils.byteArrayToInt(compressed.slice(coffset, coffset + 2), "little");
coffset += 2;
const size = blockHeader & SIZE_MASK;
const blockEnd = coffset + size + 1;
if (size === 0) {
break;
} else if (compressed.length < coffset + size) {
throw new OperationError("Malformed LZNT1 stream: Block too small! Has the stream been truncated?");
}
if ((blockHeader & COMPRESSED_MASK) !== 0) {
while (coffset < blockEnd) {
let header = compressed[coffset++];
for (let i = 0; i < 8 && coffset < blockEnd; i++) {
if ((header & 1) === 0) {
decompressed.push(compressed[coffset++]);
} else {
const pointer = Utils.byteArrayToInt(compressed.slice(coffset, coffset + 2), "little");
coffset += 2;
const displacement = getDisplacement(decompressed.length - doffset - 1);
const symbolOffset = (pointer >> (12 - displacement)) + 1;
const symbolLength = (pointer & (0xFFF >> displacement)) + 2;
const shiftOffset = decompressed.length - symbolOffset;
for (let shiftDelta = 0; shiftDelta < symbolLength + 1; shiftDelta++) {
const shift = shiftOffset + shiftDelta;
if (shift < 0 || decompressed.length <= shift) {
throw new OperationError("Malformed LZNT1 stream: Invalid shift!");
}
decompressed.push(decompressed[shift]);
}
}
header >>= 1;
}
}
} else {
decompressed.push(...compressed.slice(coffset, coffset + size + 1));
coffset += size + 1;
}
}
return decompressed;
}
+2 -77
View File
@@ -3,6 +3,7 @@ import Utils, { isWorkerEnvironment } from "../Utils.mjs";
import Recipe from "../Recipe.mjs";
import Dish from "../Dish.mjs";
import {detectFileType, isType} from "./FileType.mjs";
import {isUTF8} from "./ChrEnc.mjs";
import chiSquared from "chi-squared";
/**
@@ -111,82 +112,6 @@ class Magic {
};
}
/**
* Detects whether the input buffer is valid UTF8.
*
* @returns {boolean}
*/
isUTF8() {
const bytes = new Uint8Array(this.inputBuffer);
let i = 0;
while (i < bytes.length) {
if (( // ASCII
bytes[i] === 0x09 ||
bytes[i] === 0x0A ||
bytes[i] === 0x0D ||
(0x20 <= bytes[i] && bytes[i] <= 0x7E)
)) {
i += 1;
continue;
}
if (( // non-overlong 2-byte
(0xC2 <= bytes[i] && bytes[i] <= 0xDF) &&
(0x80 <= bytes[i+1] && bytes[i+1] <= 0xBF)
)) {
i += 2;
continue;
}
if (( // excluding overlongs
bytes[i] === 0xE0 &&
(0xA0 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
(0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF)
) ||
( // straight 3-byte
((0xE1 <= bytes[i] && bytes[i] <= 0xEC) ||
bytes[i] === 0xEE ||
bytes[i] === 0xEF) &&
(0x80 <= bytes[i + 1] && bytes[i+1] <= 0xBF) &&
(0x80 <= bytes[i+2] && bytes[i+2] <= 0xBF)
) ||
( // excluding surrogates
bytes[i] === 0xED &&
(0x80 <= bytes[i+1] && bytes[i+1] <= 0x9F) &&
(0x80 <= bytes[i+2] && bytes[i+2] <= 0xBF)
)) {
i += 3;
continue;
}
if (( // planes 1-3
bytes[i] === 0xF0 &&
(0x90 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
(0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) &&
(0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF)
) ||
( // planes 4-15
(0xF1 <= bytes[i] && bytes[i] <= 0xF3) &&
(0x80 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
(0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) &&
(0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF)
) ||
( // plane 16
bytes[i] === 0xF4 &&
(0x80 <= bytes[i + 1] && bytes[i + 1] <= 0x8F) &&
(0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) &&
(0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF)
)) {
i += 4;
continue;
}
return false;
}
return true;
}
/**
* Calculates the Shannon entropy of the input data.
*
@@ -336,7 +261,7 @@ class Magic {
data: this.inputStr.slice(0, 100),
languageScores: this.detectLanguage(extLang),
fileType: this.detectFileType(),
isUTF8: this.isUTF8(),
isUTF8: !!isUTF8(this.inputBuffer),
entropy: this.calcEntropy(),
matchingOps: matchingOps,
useful: useful,
+165
View File
@@ -0,0 +1,165 @@
/**
* @author linuxgemini [ilteris@asenkron.com.tr]
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import Utils from "../Utils.mjs";
import OperationError from "../errors/OperationError.mjs";
import { fromHex, toHex } from "./Hex.mjs";
/**
* Modhex alphabet.
*/
const MODHEX_ALPHABET = "cbdefghijklnrtuv";
/**
* Modhex alphabet map.
*/
const MODHEX_ALPHABET_MAP = MODHEX_ALPHABET.split("");
/**
* Hex alphabet to substitute Modhex.
*/
const HEX_ALPHABET = "0123456789abcdef";
/**
* Hex alphabet map to substitute Modhex.
*/
const HEX_ALPHABET_MAP = HEX_ALPHABET.split("");
/**
* Convert a byte array into a modhex string.
*
* @param {byteArray|Uint8Array|ArrayBuffer} data
* @param {string} [delim=" "]
* @param {number} [padding=2]
* @returns {string}
*
* @example
* // returns "cl bf bu"
* toModhex([10,20,30]);
*
* // returns "cl:bf:bu"
* toModhex([10,20,30], ":");
*/
export function toModhex(data, delim=" ", padding=2, extraDelim="", lineSize=0) {
if (!data) return "";
if (data instanceof ArrayBuffer) data = new Uint8Array(data);
const regularHexString = toHex(data, "", padding, "", 0);
let modhexString = "";
for (const letter of regularHexString.split("")) {
modhexString += MODHEX_ALPHABET_MAP[HEX_ALPHABET_MAP.indexOf(letter)];
}
let output = "";
const groupingRegexp = new RegExp(`.{1,${padding}}`, "g");
const groupedModhex = modhexString.match(groupingRegexp);
for (let i = 0; i < groupedModhex.length; i++) {
const group = groupedModhex[i];
output += group + delim;
if (extraDelim) {
output += extraDelim;
}
// Add LF after each lineSize amount of bytes but not at the end
if ((i !== groupedModhex.length - 1) && ((i + 1) % lineSize === 0)) {
output += "\n";
}
}
// Remove the extraDelim at the end (if there is one)
// and remove the delim at the end, but if it's prepended there's nothing to remove
const rTruncLen = extraDelim.length + delim.length;
if (rTruncLen) {
// If rTruncLen === 0 then output.slice(0,0) will be returned, which is nothing
return output.slice(0, -rTruncLen);
} else {
return output;
}
}
/**
* Convert a byte array into a modhex string as efficiently as possible with no options.
*
* @param {byteArray|Uint8Array|ArrayBuffer} data
* @returns {string}
*
* @example
* // returns "clbfbu"
* toModhexFast([10,20,30]);
*/
export function toModhexFast(data) {
if (!data) return "";
if (data instanceof ArrayBuffer) data = new Uint8Array(data);
const output = [];
for (let i = 0; i < data.length; i++) {
output.push(MODHEX_ALPHABET_MAP[(data[i] >> 4) & 0xf]);
output.push(MODHEX_ALPHABET_MAP[data[i] & 0xf]);
}
return output.join("");
}
/**
* Convert a modhex string into a byte array.
*
* @param {string} data
* @param {string} [delim]
* @param {number} [byteLen=2]
* @returns {byteArray}
*
* @example
* // returns [10,20,30]
* fromModhex("cl bf bu");
*
* // returns [10,20,30]
* fromModhex("cl:bf:bu", "Colon");
*/
export function fromModhex(data, delim="Auto", byteLen=2) {
if (byteLen < 1 || Math.round(byteLen) !== byteLen)
throw new OperationError("Byte length must be a positive integer");
// The `.replace(/\s/g, "")` an interesting workaround: Hex "multiline" tests aren't actually
// multiline. Tests for Modhex fixes that, thus exposing the issue.
data = data.toLowerCase().replace(/\s/g, "");
if (delim !== "None") {
const delimRegex = delim === "Auto" ? /[^cbdefghijklnrtuv]/gi : Utils.regexRep(delim);
data = data.split(delimRegex);
} else {
data = [data];
}
let regularHexString = "";
for (let i = 0; i < data.length; i++) {
for (const letter of data[i].split("")) {
regularHexString += HEX_ALPHABET_MAP[MODHEX_ALPHABET_MAP.indexOf(letter)];
}
}
const output = fromHex(regularHexString, "None", byteLen);
return output;
}
/**
* To Modhex delimiters.
*/
export const TO_MODHEX_DELIM_OPTIONS = ["Space", "Percent", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "None"];
/**
* From Modhex delimiters.
*/
export const FROM_MODHEX_DELIM_OPTIONS = ["Auto"].concat(TO_MODHEX_DELIM_OPTIONS);
+3
View File
@@ -26,6 +26,9 @@ export function objToTable(obj, nested=false) {
</tr>`;
for (const key in obj) {
if (typeof obj[key] === "function")
continue;
html += `<tr><td style='word-wrap: break-word'>${key}</td>`;
if (typeof obj[key] === "object")
html += `<td style='padding: 0'>${objToTable(obj[key], true)}</td>`;
+4 -4
View File
@@ -10,7 +10,7 @@ import OperationError from "../errors/OperationError.mjs";
import jsQR from "jsqr";
import qr from "qr-image";
import Utils from "../Utils.mjs";
import jimp from "jimp";
import Jimp from "jimp/es/index.js";
/**
* Parses a QR code image from an image
@@ -22,7 +22,7 @@ import jimp from "jimp";
export async function parseQrCode(input, normalise) {
let image;
try {
image = await jimp.read(input);
image = await Jimp.read(input);
} catch (err) {
throw new OperationError(`Error opening image. (${err})`);
}
@@ -33,8 +33,8 @@ export async function parseQrCode(input, normalise) {
image.background(0xFFFFFFFF);
image.normalize();
image.greyscale();
image = await image.getBufferAsync(jimp.MIME_JPEG);
image = await jimp.read(image);
image = await image.getBufferAsync(Jimp.MIME_JPEG);
image = await Jimp.read(image);
}
} catch (err) {
throw new OperationError(`Error normalising image. (${err})`);
+258
View File
@@ -0,0 +1,258 @@
/**
* Utilities and operations utilized for SM2 encryption and decryption
* @author flakjacket95 [dflack95@gmail.com]
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import OperationError from "../errors/OperationError.mjs";
import { fromHex } from "../lib/Hex.mjs";
import Utils from "../Utils.mjs";
import Sm3 from "crypto-api/src/hasher/sm3.mjs";
import {toHex} from "crypto-api/src/encoder/hex.mjs";
import r from "jsrsasign";
/**
* SM2 Class for encryption and decryption operations
*/
export class SM2 {
/**
* Constructor for SM2 class; sets up with the curve and the output format as specified in user args
*
* @param {*} curve
* @param {*} format
*/
constructor(curve, format) {
this.ecParams = null;
this.rng = new r.SecureRandom();
/*
For any additional curve definitions utilized by SM2, add another block like the below for that curve, then add the curve name to the Curve selection dropdown
*/
r.crypto.ECParameterDB.regist(
"sm2p256v1", // name / p = 2**256 - 2**224 - 2**96 + 2**64 - 1
256,
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", // p
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", // a
"28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", // b
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", // n
"1", // h
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", // gx
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", // gy
[]
); // alias
this.ecParams = r.crypto.ECParameterDB.getByName(curve);
this.format = format;
}
/**
* Set the public key coordinates for the SM2 class
*
* @param {string} publicKeyX
* @param {string} publicKeyY
*/
setPublicKey(publicKeyX, publicKeyY) {
/*
* TODO: This needs some additional length validation; and checking for errors in the decoding process
* TODO: Can probably support other public key encoding methods here as well in the future
*/
this.publicKey = this.ecParams.curve.decodePointHex("04" + publicKeyX + publicKeyY);
if (this.publicKey.isInfinity()) {
throw new OperationError("Invalid Public Key");
}
}
/**
* Set the private key value for the SM2 class
*
* @param {string} privateKey
*/
setPrivateKey(privateKeyHex) {
this.privateKey = new r.BigInteger(privateKeyHex, 16);
}
/**
* Main encryption function; takes user input, processes encryption and returns the result in hex (with the components arranged as configured by the user args)
*
* @param {*} input
* @returns {string}
*/
encrypt(input) {
const G = this.ecParams.G;
/*
* Compute a new, random public key along the same elliptic curve to form the starting point for our encryption process (record the resulting X and Y as hex to provide as part of the operation output)
* k: Randomly generated BigInteger
* c1: Result of dotting our curve generator point `G` with the value of `k`
*/
const k = this.generatePublicKey();
const c1 = G.multiply(k);
const [hexC1X, hexC1Y] = this.getPointAsHex(c1);
/*
* Compute p2 (secret) using the public key, and the chosen k value above
*/
const p2 = this.publicKey.multiply(k);
/*
* Compute the C3 SM3 hash before we transform the array
*/
const c3 = this.c3(p2, input);
/*
* Genreate a proper length encryption key, XOR iteratively, and convert newly encrypted data to hex
*/
const key = this.kdf(p2, input.byteLength);
for (let i = 0; i < input.byteLength; i++) {
input[i] ^= Utils.ord(key[i]);
}
const c2 = Buffer.from(input).toString("hex");
/*
* Check user input specs; order the output components as selected
*/
if (this.format === "C1C3C2") {
return hexC1X + hexC1Y + c3 + c2;
} else {
return hexC1X + hexC1Y + c2 + c3;
}
}
/**
* Function to decrypt an SM2 encrypted message
*
* @param {*} input
*/
decrypt(input) {
const c1X = input.slice(0, 64);
const c1Y = input.slice(64, 128);
let c3 = "";
let c2 = "";
if (this.format === "C1C3C2") {
c3 = input.slice(128, 192);
c2 = input.slice(192);
} else {
c2 = input.slice(128, -64);
c3 = input.slice(-64);
}
c2 = Uint8Array.from(fromHex(c2));
const c1 = this.ecParams.curve.decodePointHex("04" + c1X + c1Y);
/*
* Compute the p2 (secret) value by taking the C1 point provided in the encrypted package, and multiplying by the private k value
*/
const p2 = c1.multiply(this.privateKey);
/*
* Similar to encryption; compute sufficient length key material and XOR the input data to recover the original message
*/
const key = this.kdf(p2, c2.byteLength);
for (let i = 0; i < c2.byteLength; i++) {
c2[i] ^= Utils.ord(key[i]);
}
const check = this.c3(p2, c2);
if (check === c3) {
return c2.buffer;
} else {
throw new OperationError("Decryption Error -- Computed Hashes Do Not Match");
}
}
/**
* Generates a large random number
*
* @param {*} limit
* @returns
*/
getBigRandom(limit) {
return new r.BigInteger(limit.bitLength(), this.rng)
.mod(limit.subtract(r.BigInteger.ONE))
.add(r.BigInteger.ONE);
}
/**
* Helper function for generating a large random K number; utilized for generating our initial C1 point
* TODO: Do we need to do any sort of validation on the resulting k values?
*
* @returns {BigInteger}
*/
generatePublicKey() {
const n = this.ecParams.n;
const k = this.getBigRandom(n);
return k;
}
/**
* SM2 Key Derivation Function (KDF); Takes P2 point, and generates a key material stream large enough to encrypt all of the input data
*
* @param {*} p2
* @param {*} len
* @returns {string}
*/
kdf(p2, len) {
const [hX, hY] = this.getPointAsHex(p2);
const total = Math.ceil(len / 32) + 1;
let cnt = 1;
let keyMaterial = "";
while (cnt < total) {
const num = Utils.intToByteArray(cnt, 4, "big");
const overall = fromHex(hX).concat(fromHex(hY)).concat(num);
keyMaterial += this.sm3(overall);
cnt++;
}
return keyMaterial;
}
/**
* Calculates the C3 component of our final encrypted payload; which is the SM3 hash of the P2 point and the original, unencrypted input data
*
* @param {*} p2
* @param {*} input
* @returns {string}
*/
c3(p2, input) {
const [hX, hY] = this.getPointAsHex(p2);
const overall = fromHex(hX).concat(Array.from(input)).concat(fromHex(hY));
return toHex(this.sm3(overall));
}
/**
* SM3 setup helper function; takes input data as an array, processes the hash and returns the result
*
* @param {*} data
* @returns {string}
*/
sm3(data) {
const hashData = Utils.arrayBufferToStr(Uint8Array.from(data).buffer, false);
const hasher = new Sm3();
hasher.update(hashData);
return hasher.finalize();
}
/**
* Utility function, returns an elliptic curve points X and Y values as hex;
*
* @param {EcPointFp} point
* @returns {[]}
*/
getPointAsHex(point) {
const biX = point.getX().toBigInteger();
const biY = point.getY().toBigInteger();
const charlen = this.ecParams.keycharlen;
const hX = ("0000000000" + biX.toString(16)).slice(- charlen);
const hY = ("0000000000" + biY.toString(16)).slice(- charlen);
return [hX, hY];
}
}
+144
View File
@@ -0,0 +1,144 @@
/**
* @author joostrijneveld [joost@joostrijneveld.nl]
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import Utils from "../Utils.mjs";
/**
* Computes the Salsa20 permute function
*
* @param {byteArray} x
* @param {integer} rounds
*/
function salsa20Permute(x, rounds) {
/**
* Macro to compute a 32-bit rotate-left operation
*
* @param {integer} x
* @param {integer} n
* @returns {integer}
*/
function ROL32(x, n) {
return ((x << n) & 0xFFFFFFFF) | (x >>> (32 - n));
}
/**
* Macro to compute a single Salsa20 quarterround operation
*
* @param {integer} x
* @param {integer} a
* @param {integer} b
* @param {integer} c
* @param {integer} d
* @returns {integer}
*/
function quarterround(x, a, b, c, d) {
x[b] ^= ROL32((x[a] + x[d]) & 0xFFFFFFFF, 7);
x[c] ^= ROL32((x[b] + x[a]) & 0xFFFFFFFF, 9);
x[d] ^= ROL32((x[c] + x[b]) & 0xFFFFFFFF, 13);
x[a] ^= ROL32((x[d] + x[c]) & 0xFFFFFFFF, 18);
}
for (let i = 0; i < rounds / 2; i++) {
quarterround(x, 0, 4, 8, 12);
quarterround(x, 5, 9, 13, 1);
quarterround(x, 10, 14, 2, 6);
quarterround(x, 15, 3, 7, 11);
quarterround(x, 0, 1, 2, 3);
quarterround(x, 5, 6, 7, 4);
quarterround(x, 10, 11, 8, 9);
quarterround(x, 15, 12, 13, 14);
}
}
/**
* Computes the Salsa20 block function
*
* @param {byteArray} key
* @param {byteArray} nonce
* @param {byteArray} counter
* @param {integer} rounds
* @returns {byteArray}
*/
export function salsa20Block(key, nonce, counter, rounds) {
const tau = "expand 16-byte k";
const sigma = "expand 32-byte k";
let state, c;
if (key.length === 16) {
c = Utils.strToByteArray(tau);
key = key.concat(key);
} else {
c = Utils.strToByteArray(sigma);
}
state = c.slice(0, 4);
state = state.concat(key.slice(0, 16));
state = state.concat(c.slice(4, 8));
state = state.concat(nonce);
state = state.concat(counter);
state = state.concat(c.slice(8, 12));
state = state.concat(key.slice(16, 32));
state = state.concat(c.slice(12, 16));
const x = Array();
for (let i = 0; i < 64; i += 4) {
x.push(Utils.byteArrayToInt(state.slice(i, i + 4), "little"));
}
const a = [...x];
salsa20Permute(x, rounds);
for (let i = 0; i < 16; i++) {
x[i] = (x[i] + a[i]) & 0xFFFFFFFF;
}
let output = Array();
for (let i = 0; i < 16; i++) {
output = output.concat(Utils.intToByteArray(x[i], 4, "little"));
}
return output;
}
/**
* Computes the hSalsa20 function
*
* @param {byteArray} key
* @param {byteArray} nonce
* @param {integer} rounds
* @returns {byteArray}
*/
export function hsalsa20(key, nonce, rounds) {
const tau = "expand 16-byte k";
const sigma = "expand 32-byte k";
let state, c;
if (key.length === 16) {
c = Utils.strToByteArray(tau);
key = key.concat(key);
} else {
c = Utils.strToByteArray(sigma);
}
state = c.slice(0, 4);
state = state.concat(key.slice(0, 16));
state = state.concat(c.slice(4, 8));
state = state.concat(nonce);
state = state.concat(c.slice(8, 12));
state = state.concat(key.slice(16, 32));
state = state.concat(c.slice(12, 16));
const x = Array();
for (let i = 0; i < 64; i += 4) {
x.push(Utils.byteArrayToInt(state.slice(i, i + 4), "little"));
}
salsa20Permute(x, rounds);
let output = Array();
const idx = [0, 5, 10, 15, 6, 7, 8, 9];
for (let i = 0; i < 8; i++) {
output = output.concat(Utils.intToByteArray(x[idx[i]], 4, "little"));
}
return output;
}
+14 -3
View File
@@ -18,12 +18,23 @@ export default class Stream {
* Stream constructor.
*
* @param {Uint8Array} input
* @param {number} pos
* @param {number} bitPos
*/
constructor(input) {
constructor(input, pos=0, bitPos=0) {
this.bytes = input;
this.length = this.bytes.length;
this.position = 0;
this.bitPos = 0;
this.position = pos;
this.bitPos = bitPos;
}
/**
* Clone this Stream returning a new identical Stream.
*
* @returns {Stream}
*/
clone() {
return new Stream(this.bytes, this.position, this.bitPos);
}
/**
+877
View File
@@ -0,0 +1,877 @@
/**
* TLS resources.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import OperationError from "../errors/OperationError.mjs";
import Stream from "../lib/Stream.mjs";
/**
* Parse a TLS Record
* @param {Uint8Array} bytes
* @returns {JSON}
*/
export function parseTLSRecord(bytes) {
const s = new Stream(bytes);
const b = s.clone();
const r = {};
// Content type
r.contentType = {
description: "Content Type",
length: 1,
data: b.getBytes(1),
value: s.readInt(1)
};
if (r.contentType.value !== 0x16)
throw new OperationError("Not handshake data.");
// Version
r.version = {
description: "Protocol Version",
length: 2,
data: b.getBytes(2),
value: s.readInt(2)
};
// Length
r.length = {
description: "Record Length",
length: 2,
data: b.getBytes(2),
value: s.readInt(2)
};
if (s.length !== r.length.value + 5)
throw new OperationError("Incorrect handshake length.");
// Handshake
r.handshake = {
description: "Handshake",
length: r.length.value,
data: b.getBytes(r.length.value),
value: parseHandshake(s.getBytes(r.length.value))
};
return r;
}
/**
* Parse a TLS Handshake
* @param {Uint8Array} bytes
* @returns {JSON}
*/
function parseHandshake(bytes) {
const s = new Stream(bytes);
const b = s.clone();
const h = {};
// Handshake type
h.handshakeType = {
description: "Handshake Type",
length: 1,
data: b.getBytes(1),
value: s.readInt(1)
};
// Handshake length
h.handshakeLength = {
description: "Handshake Length",
length: 3,
data: b.getBytes(3),
value: s.readInt(3)
};
if (s.length !== h.handshakeLength.value + 4)
throw new OperationError("Not enough data in Handshake message.");
switch (h.handshakeType.value) {
case 0x01:
h.handshakeType.description = "Client Hello";
parseClientHello(s, b, h);
break;
case 0x02:
h.handshakeType.description = "Server Hello";
parseServerHello(s, b, h);
break;
default:
throw new OperationError("Not a known handshake message.");
}
return h;
}
/**
* Parse a TLS Client Hello
* @param {Stream} s
* @param {Stream} b
* @param {Object} h
* @returns {JSON}
*/
function parseClientHello(s, b, h) {
// Hello version
h.helloVersion = {
description: "Client Hello Version",
length: 2,
data: b.getBytes(2),
value: s.readInt(2)
};
// Random
h.random = {
description: "Client Random",
length: 32,
data: b.getBytes(32),
value: s.getBytes(32)
};
// Session ID Length
h.sessionIDLength = {
description: "Session ID Length",
length: 1,
data: b.getBytes(1),
value: s.readInt(1)
};
// Session ID
h.sessionID = {
description: "Session ID",
length: h.sessionIDLength.value,
data: b.getBytes(h.sessionIDLength.value),
value: s.getBytes(h.sessionIDLength.value)
};
// Cipher Suites Length
h.cipherSuitesLength = {
description: "Cipher Suites Length",
length: 2,
data: b.getBytes(2),
value: s.readInt(2)
};
// Cipher Suites
h.cipherSuites = {
description: "Cipher Suites",
length: h.cipherSuitesLength.value,
data: b.getBytes(h.cipherSuitesLength.value),
value: parseCipherSuites(s.getBytes(h.cipherSuitesLength.value))
};
// Compression Methods Length
h.compressionMethodsLength = {
description: "Compression Methods Length",
length: 1,
data: b.getBytes(1),
value: s.readInt(1)
};
// Compression Methods
h.compressionMethods = {
description: "Compression Methods",
length: h.compressionMethodsLength.value,
data: b.getBytes(h.compressionMethodsLength.value),
value: parseCompressionMethods(s.getBytes(h.compressionMethodsLength.value))
};
// Extensions Length
h.extensionsLength = {
description: "Extensions Length",
length: 2,
data: b.getBytes(2),
value: s.readInt(2)
};
// Extensions
h.extensions = {
description: "Extensions",
length: h.extensionsLength.value,
data: b.getBytes(h.extensionsLength.value),
value: parseExtensions(s.getBytes(h.extensionsLength.value))
};
return h;
}
/**
* Parse a TLS Server Hello
* @param {Stream} s
* @param {Stream} b
* @param {Object} h
* @returns {JSON}
*/
function parseServerHello(s, b, h) {
// Hello version
h.helloVersion = {
description: "Server Hello Version",
length: 2,
data: b.getBytes(2),
value: s.readInt(2)
};
// Random
h.random = {
description: "Server Random",
length: 32,
data: b.getBytes(32),
value: s.getBytes(32)
};
// Session ID Length
h.sessionIDLength = {
description: "Session ID Length",
length: 1,
data: b.getBytes(1),
value: s.readInt(1)
};
// Session ID
h.sessionID = {
description: "Session ID",
length: h.sessionIDLength.value,
data: b.getBytes(h.sessionIDLength.value),
value: s.getBytes(h.sessionIDLength.value)
};
// Cipher Suite
h.cipherSuite = {
description: "Selected Cipher Suite",
length: 2,
data: b.getBytes(2),
value: CIPHER_SUITES_LOOKUP[s.readInt(2)] || "Unknown"
};
// Compression Method
h.compressionMethod = {
description: "Selected Compression Method",
length: 1,
data: b.getBytes(1),
value: s.readInt(1) // TODO: Compression method name here
};
// Extensions Length
h.extensionsLength = {
description: "Extensions Length",
length: 2,
data: b.getBytes(2),
value: s.readInt(2)
};
// Extensions
h.extensions = {
description: "Extensions",
length: h.extensionsLength.value,
data: b.getBytes(h.extensionsLength.value),
value: parseExtensions(s.getBytes(h.extensionsLength.value))
};
}
/**
* Parse Cipher Suites
* @param {Uint8Array} bytes
* @returns {JSON}
*/
function parseCipherSuites(bytes) {
const s = new Stream(bytes);
const b = s.clone();
const cs = [];
while (s.hasMore()) {
cs.push({
description: "Cipher Suite",
length: 2,
data: b.getBytes(2),
value: CIPHER_SUITES_LOOKUP[s.readInt(2)] || "Unknown"
});
}
return cs;
}
/**
* Parse Compression Methods
* @param {Uint8Array} bytes
* @returns {JSON}
*/
function parseCompressionMethods(bytes) {
const s = new Stream(bytes);
const b = s.clone();
const cm = [];
while (s.hasMore()) {
cm.push({
description: "Compression Method",
length: 1,
data: b.getBytes(1),
value: s.readInt(1) // TODO: Compression method name here
});
}
return cm;
}
/**
* Parse Extensions
* @param {Uint8Array} bytes
* @returns {JSON}
*/
function parseExtensions(bytes) {
const s = new Stream(bytes);
const b = s.clone();
const exts = [];
while (s.hasMore()) {
const ext = {};
// Type
ext.type = {
description: "Extension Type",
length: 2,
data: b.getBytes(2),
value: EXTENSION_LOOKUP[s.readInt(2)] || "unknown"
};
// Length
ext.length = {
description: "Extension Length",
length: 2,
data: b.getBytes(2),
value: s.readInt(2)
};
// Value
ext.value = {
description: "Extension Value",
length: ext.length.value,
data: b.getBytes(ext.length.value),
value: s.getBytes(ext.length.value)
};
exts.push(ext);
}
return exts;
}
/**
* Extension type lookup table
*/
const EXTENSION_LOOKUP = {
0: "server_name",
1: "max_fragment_length",
2: "client_certificate_url",
3: "trusted_ca_keys",
4: "truncated_hmac",
5: "status_request",
6: "user_mapping",
7: "client_authz",
8: "server_authz",
9: "cert_type",
10: "supported_groups",
11: "ec_point_formats",
12: "srp",
13: "signature_algorithms",
14: "use_srtp",
15: "heartbeat",
16: "application_layer_protocol_negotiation",
17: "status_request_v2",
18: "signed_certificate_timestamp",
19: "client_certificate_type",
20: "server_certificate_type",
21: "padding",
22: "encrypt_then_mac",
23: "extended_master_secret",
24: "token_binding",
25: "cached_info",
26: "tls_lts",
27: "compress_certificate",
28: "record_size_limit",
29: "pwd_protect",
30: "pwd_clear",
31: "password_salt",
32: "ticket_pinning",
33: "tls_cert_with_extern_psk",
34: "delegated_credential",
35: "session_ticket",
36: "TLMSP",
37: "TLMSP_proxying",
38: "TLMSP_delegate",
39: "supported_ekt_ciphers",
40: "Reserved",
41: "pre_shared_key",
42: "early_data",
43: "supported_versions",
44: "cookie",
45: "psk_key_exchange_modes",
46: "Reserved",
47: "certificate_authorities",
48: "oid_filters",
49: "post_handshake_auth",
50: "signature_algorithms_cert",
51: "key_share",
52: "transparency_info",
53: "connection_id (deprecated)",
54: "connection_id",
55: "external_id_hash",
56: "external_session_id",
57: "quic_transport_parameters",
58: "ticket_request",
59: "dnssec_chain",
60: "sequence_number_encryption_algorithms",
61: "rrc",
2570: "GREASE",
6682: "GREASE",
10794: "GREASE",
14906: "GREASE",
17513: "application_settings",
19018: "GREASE",
23130: "GREASE",
27242: "GREASE",
31354: "GREASE",
35466: "GREASE",
39578: "GREASE",
43690: "GREASE",
47802: "GREASE",
51914: "GREASE",
56026: "GREASE",
60138: "GREASE",
64250: "GREASE",
64768: "ech_outer_extensions",
65037: "encrypted_client_hello",
65281: "renegotiation_info"
};
/**
* Cipher suites lookup table
*/
const CIPHER_SUITES_LOOKUP = {
0x0000: "TLS_NULL_WITH_NULL_NULL",
0x0001: "TLS_RSA_WITH_NULL_MD5",
0x0002: "TLS_RSA_WITH_NULL_SHA",
0x0003: "TLS_RSA_EXPORT_WITH_RC4_40_MD5",
0x0004: "TLS_RSA_WITH_RC4_128_MD5",
0x0005: "TLS_RSA_WITH_RC4_128_SHA",
0x0006: "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5",
0x0007: "TLS_RSA_WITH_IDEA_CBC_SHA",
0x0008: "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA",
0x0009: "TLS_RSA_WITH_DES_CBC_SHA",
0x000A: "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
0x000B: "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA",
0x000C: "TLS_DH_DSS_WITH_DES_CBC_SHA",
0x000D: "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA",
0x000E: "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA",
0x000F: "TLS_DH_RSA_WITH_DES_CBC_SHA",
0x0010: "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA",
0x0011: "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
0x0012: "TLS_DHE_DSS_WITH_DES_CBC_SHA",
0x0013: "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
0x0014: "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
0x0015: "TLS_DHE_RSA_WITH_DES_CBC_SHA",
0x0016: "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
0x0017: "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5",
0x0018: "TLS_DH_anon_WITH_RC4_128_MD5",
0x0019: "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
0x001A: "TLS_DH_anon_WITH_DES_CBC_SHA",
0x001B: "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA",
0x001E: "TLS_KRB5_WITH_DES_CBC_SHA",
0x001F: "TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
0x0020: "TLS_KRB5_WITH_RC4_128_SHA",
0x0021: "TLS_KRB5_WITH_IDEA_CBC_SHA",
0x0022: "TLS_KRB5_WITH_DES_CBC_MD5",
0x0023: "TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
0x0024: "TLS_KRB5_WITH_RC4_128_MD5",
0x0025: "TLS_KRB5_WITH_IDEA_CBC_MD5",
0x0026: "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
0x0027: "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA",
0x0028: "TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
0x0029: "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
0x002A: "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5",
0x002B: "TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
0x002C: "TLS_PSK_WITH_NULL_SHA",
0x002D: "TLS_DHE_PSK_WITH_NULL_SHA",
0x002E: "TLS_RSA_PSK_WITH_NULL_SHA",
0x002F: "TLS_RSA_WITH_AES_128_CBC_SHA",
0x0030: "TLS_DH_DSS_WITH_AES_128_CBC_SHA",
0x0031: "TLS_DH_RSA_WITH_AES_128_CBC_SHA",
0x0032: "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
0x0033: "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
0x0034: "TLS_DH_anon_WITH_AES_128_CBC_SHA",
0x0035: "TLS_RSA_WITH_AES_256_CBC_SHA",
0x0036: "TLS_DH_DSS_WITH_AES_256_CBC_SHA",
0x0037: "TLS_DH_RSA_WITH_AES_256_CBC_SHA",
0x0038: "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
0x0039: "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
0x003A: "TLS_DH_anon_WITH_AES_256_CBC_SHA",
0x003B: "TLS_RSA_WITH_NULL_SHA256",
0x003C: "TLS_RSA_WITH_AES_128_CBC_SHA256",
0x003D: "TLS_RSA_WITH_AES_256_CBC_SHA256",
0x003E: "TLS_DH_DSS_WITH_AES_128_CBC_SHA256",
0x003F: "TLS_DH_RSA_WITH_AES_128_CBC_SHA256",
0x0040: "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
0x0041: "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",
0x0042: "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA",
0x0043: "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA",
0x0044: "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA",
0x0045: "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",
0x0046: "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA",
0x0067: "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
0x0068: "TLS_DH_DSS_WITH_AES_256_CBC_SHA256",
0x0069: "TLS_DH_RSA_WITH_AES_256_CBC_SHA256",
0x006A: "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
0x006B: "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
0x006C: "TLS_DH_anon_WITH_AES_128_CBC_SHA256",
0x006D: "TLS_DH_anon_WITH_AES_256_CBC_SHA256",
0x0084: "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",
0x0085: "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA",
0x0086: "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA",
0x0087: "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA",
0x0088: "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",
0x0089: "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA",
0x008A: "TLS_PSK_WITH_RC4_128_SHA",
0x008B: "TLS_PSK_WITH_3DES_EDE_CBC_SHA",
0x008C: "TLS_PSK_WITH_AES_128_CBC_SHA",
0x008D: "TLS_PSK_WITH_AES_256_CBC_SHA",
0x008E: "TLS_DHE_PSK_WITH_RC4_128_SHA",
0x008F: "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA",
0x0090: "TLS_DHE_PSK_WITH_AES_128_CBC_SHA",
0x0091: "TLS_DHE_PSK_WITH_AES_256_CBC_SHA",
0x0092: "TLS_RSA_PSK_WITH_RC4_128_SHA",
0x0093: "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA",
0x0094: "TLS_RSA_PSK_WITH_AES_128_CBC_SHA",
0x0095: "TLS_RSA_PSK_WITH_AES_256_CBC_SHA",
0x0096: "TLS_RSA_WITH_SEED_CBC_SHA",
0x0097: "TLS_DH_DSS_WITH_SEED_CBC_SHA",
0x0098: "TLS_DH_RSA_WITH_SEED_CBC_SHA",
0x0099: "TLS_DHE_DSS_WITH_SEED_CBC_SHA",
0x009A: "TLS_DHE_RSA_WITH_SEED_CBC_SHA",
0x009B: "TLS_DH_anon_WITH_SEED_CBC_SHA",
0x009C: "TLS_RSA_WITH_AES_128_GCM_SHA256",
0x009D: "TLS_RSA_WITH_AES_256_GCM_SHA384",
0x009E: "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
0x009F: "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
0x00A0: "TLS_DH_RSA_WITH_AES_128_GCM_SHA256",
0x00A1: "TLS_DH_RSA_WITH_AES_256_GCM_SHA384",
0x00A2: "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
0x00A3: "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
0x00A4: "TLS_DH_DSS_WITH_AES_128_GCM_SHA256",
0x00A5: "TLS_DH_DSS_WITH_AES_256_GCM_SHA384",
0x00A6: "TLS_DH_anon_WITH_AES_128_GCM_SHA256",
0x00A7: "TLS_DH_anon_WITH_AES_256_GCM_SHA384",
0x00A8: "TLS_PSK_WITH_AES_128_GCM_SHA256",
0x00A9: "TLS_PSK_WITH_AES_256_GCM_SHA384",
0x00AA: "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",
0x00AB: "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",
0x00AC: "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256",
0x00AD: "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384",
0x00AE: "TLS_PSK_WITH_AES_128_CBC_SHA256",
0x00AF: "TLS_PSK_WITH_AES_256_CBC_SHA384",
0x00B0: "TLS_PSK_WITH_NULL_SHA256",
0x00B1: "TLS_PSK_WITH_NULL_SHA384",
0x00B2: "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",
0x00B3: "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",
0x00B4: "TLS_DHE_PSK_WITH_NULL_SHA256",
0x00B5: "TLS_DHE_PSK_WITH_NULL_SHA384",
0x00B6: "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256",
0x00B7: "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384",
0x00B8: "TLS_RSA_PSK_WITH_NULL_SHA256",
0x00B9: "TLS_RSA_PSK_WITH_NULL_SHA384",
0x00BA: "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",
0x00BB: "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256",
0x00BC: "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256",
0x00BD: "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256",
0x00BE: "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
0x00BF: "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256",
0x00C0: "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",
0x00C1: "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256",
0x00C2: "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256",
0x00C3: "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256",
0x00C4: "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",
0x00C5: "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256",
0x00C6: "TLS_SM4_GCM_SM3",
0x00C7: "TLS_SM4_CCM_SM3",
0x00FF: "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
0x0A0A: "GREASE",
0x1301: "TLS_AES_128_GCM_SHA256",
0x1302: "TLS_AES_256_GCM_SHA384",
0x1303: "TLS_CHACHA20_POLY1305_SHA256",
0x1304: "TLS_AES_128_CCM_SHA256",
0x1305: "TLS_AES_128_CCM_8_SHA256",
0x1306: "TLS_AEGIS_256_SHA512",
0x1307: "TLS_AEGIS_128L_SHA256",
0x1A1A: "GREASE",
0x2A2A: "GREASE",
0x3A3A: "GREASE",
0x4A4A: "GREASE",
0x5600: "TLS_FALLBACK_SCSV",
0x5A5A: "GREASE",
0x6A6A: "GREASE",
0x7A7A: "GREASE",
0x8A8A: "GREASE",
0x9A9A: "GREASE",
0xAAAA: "GREASE",
0xBABA: "GREASE",
0xC001: "TLS_ECDH_ECDSA_WITH_NULL_SHA",
0xC002: "TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
0xC003: "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
0xC004: "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
0xC005: "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
0xC006: "TLS_ECDHE_ECDSA_WITH_NULL_SHA",
0xC007: "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
0xC008: "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
0xC009: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
0xC00A: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
0xC00B: "TLS_ECDH_RSA_WITH_NULL_SHA",
0xC00C: "TLS_ECDH_RSA_WITH_RC4_128_SHA",
0xC00D: "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
0xC00E: "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
0xC00F: "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
0xC010: "TLS_ECDHE_RSA_WITH_NULL_SHA",
0xC011: "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
0xC012: "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
0xC013: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
0xC014: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
0xC015: "TLS_ECDH_anon_WITH_NULL_SHA",
0xC016: "TLS_ECDH_anon_WITH_RC4_128_SHA",
0xC017: "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
0xC018: "TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
0xC019: "TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
0xC01A: "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA",
0xC01B: "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA",
0xC01C: "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA",
0xC01D: "TLS_SRP_SHA_WITH_AES_128_CBC_SHA",
0xC01E: "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA",
0xC01F: "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA",
0xC020: "TLS_SRP_SHA_WITH_AES_256_CBC_SHA",
0xC021: "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA",
0xC022: "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA",
0xC023: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
0xC024: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
0xC025: "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
0xC026: "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
0xC027: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
0xC028: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
0xC029: "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
0xC02A: "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
0xC02B: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
0xC02C: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
0xC02D: "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
0xC02E: "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
0xC02F: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
0xC030: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
0xC031: "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
0xC032: "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
0xC033: "TLS_ECDHE_PSK_WITH_RC4_128_SHA",
0xC034: "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA",
0xC035: "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",
0xC036: "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",
0xC037: "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",
0xC038: "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384",
0xC039: "TLS_ECDHE_PSK_WITH_NULL_SHA",
0xC03A: "TLS_ECDHE_PSK_WITH_NULL_SHA256",
0xC03B: "TLS_ECDHE_PSK_WITH_NULL_SHA384",
0xC03C: "TLS_RSA_WITH_ARIA_128_CBC_SHA256",
0xC03D: "TLS_RSA_WITH_ARIA_256_CBC_SHA384",
0xC03E: "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256",
0xC03F: "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384",
0xC040: "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256",
0xC041: "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384",
0xC042: "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256",
0xC043: "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384",
0xC044: "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256",
0xC045: "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384",
0xC046: "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256",
0xC047: "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384",
0xC048: "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256",
0xC049: "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384",
0xC04A: "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256",
0xC04B: "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384",
0xC04C: "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256",
0xC04D: "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384",
0xC04E: "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256",
0xC04F: "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384",
0xC050: "TLS_RSA_WITH_ARIA_128_GCM_SHA256",
0xC051: "TLS_RSA_WITH_ARIA_256_GCM_SHA384",
0xC052: "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256",
0xC053: "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384",
0xC054: "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256",
0xC055: "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384",
0xC056: "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256",
0xC057: "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384",
0xC058: "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256",
0xC059: "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384",
0xC05A: "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256",
0xC05B: "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384",
0xC05C: "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256",
0xC05D: "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384",
0xC05E: "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256",
0xC05F: "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384",
0xC060: "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256",
0xC061: "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384",
0xC062: "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256",
0xC063: "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384",
0xC064: "TLS_PSK_WITH_ARIA_128_CBC_SHA256",
0xC065: "TLS_PSK_WITH_ARIA_256_CBC_SHA384",
0xC066: "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256",
0xC067: "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384",
0xC068: "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256",
0xC069: "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384",
0xC06A: "TLS_PSK_WITH_ARIA_128_GCM_SHA256",
0xC06B: "TLS_PSK_WITH_ARIA_256_GCM_SHA384",
0xC06C: "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256",
0xC06D: "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384",
0xC06E: "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256",
0xC06F: "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384",
0xC070: "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256",
0xC071: "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384",
0xC072: "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256",
0xC073: "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384",
0xC074: "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256",
0xC075: "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384",
0xC076: "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
0xC077: "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384",
0xC078: "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256",
0xC079: "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384",
0xC07A: "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256",
0xC07B: "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384",
0xC07C: "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256",
0xC07D: "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384",
0xC07E: "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256",
0xC07F: "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384",
0xC080: "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256",
0xC081: "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384",
0xC082: "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256",
0xC083: "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384",
0xC084: "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256",
0xC085: "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384",
0xC086: "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256",
0xC087: "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384",
0xC088: "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256",
0xC089: "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384",
0xC08A: "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256",
0xC08B: "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384",
0xC08C: "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256",
0xC08D: "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384",
0xC08E: "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256",
0xC08F: "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384",
0xC090: "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256",
0xC091: "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384",
0xC092: "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256",
0xC093: "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384",
0xC094: "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256",
0xC095: "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384",
0xC096: "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256",
0xC097: "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384",
0xC098: "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256",
0xC099: "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384",
0xC09A: "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256",
0xC09B: "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384",
0xC09C: "TLS_RSA_WITH_AES_128_CCM",
0xC09D: "TLS_RSA_WITH_AES_256_CCM",
0xC09E: "TLS_DHE_RSA_WITH_AES_128_CCM",
0xC09F: "TLS_DHE_RSA_WITH_AES_256_CCM",
0xC0A0: "TLS_RSA_WITH_AES_128_CCM_8",
0xC0A1: "TLS_RSA_WITH_AES_256_CCM_8",
0xC0A2: "TLS_DHE_RSA_WITH_AES_128_CCM_8",
0xC0A3: "TLS_DHE_RSA_WITH_AES_256_CCM_8",
0xC0A4: "TLS_PSK_WITH_AES_128_CCM",
0xC0A5: "TLS_PSK_WITH_AES_256_CCM",
0xC0A6: "TLS_DHE_PSK_WITH_AES_128_CCM",
0xC0A7: "TLS_DHE_PSK_WITH_AES_256_CCM",
0xC0A8: "TLS_PSK_WITH_AES_128_CCM_8",
0xC0A9: "TLS_PSK_WITH_AES_256_CCM_8",
0xC0AA: "TLS_PSK_DHE_WITH_AES_128_CCM_8",
0xC0AB: "TLS_PSK_DHE_WITH_AES_256_CCM_8",
0xC0AC: "TLS_ECDHE_ECDSA_WITH_AES_128_CCM",
0xC0AD: "TLS_ECDHE_ECDSA_WITH_AES_256_CCM",
0xC0AE: "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8",
0xC0AF: "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8",
0xC0B0: "TLS_ECCPWD_WITH_AES_128_GCM_SHA256",
0xC0B1: "TLS_ECCPWD_WITH_AES_256_GCM_SHA384",
0xC0B2: "TLS_ECCPWD_WITH_AES_128_CCM_SHA256",
0xC0B3: "TLS_ECCPWD_WITH_AES_256_CCM_SHA384",
0xC0B4: "TLS_SHA256_SHA256",
0xC0B5: "TLS_SHA384_SHA384",
0xC100: "TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC",
0xC101: "TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC",
0xC102: "TLS_GOSTR341112_256_WITH_28147_CNT_IMIT",
0xC103: "TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_L",
0xC104: "TLS_GOSTR341112_256_WITH_MAGMA_MGM_L",
0xC105: "TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_S",
0xC106: "TLS_GOSTR341112_256_WITH_MAGMA_MGM_S",
0xCACA: "GREASE",
0xCCA8: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
0xCCA9: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
0xCCAA: "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
0xCCAB: "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256",
0xCCAC: "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
0xCCAD: "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
0xCCAE: "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256",
0xD001: "TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256",
0xD002: "TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384",
0xD003: "TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256",
0xD005: "TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256",
0xDADA: "GREASE",
0xEAEA: "GREASE",
0xFAFA: "GREASE",
};
/**
* GREASE values
*/
export const GREASE_VALUES = [
0x0a0a,
0x1a1a,
0x2a2a,
0x3a3a,
0x4a4a,
0x5a5a,
0x6a6a,
0x7a7a,
0x8a8a,
0x9a9a,
0xaaaa,
0xbaba,
0xcaca,
0xdada,
0xeaea,
0xfafa
];
/**
* Parses the supported_versions extension and returns the highest supported version.
* @param {Uint8Array} bytes
* @returns {number}
*/
export function parseHighestSupportedVersion(bytes) {
const s = new Stream(bytes);
// The Server Hello supported_versions extension simply contains the chosen version
if (s.length === 2) {
return s.readInt(2);
}
// Length
let i = s.readInt(1);
let highestVersion = 0;
while (s.hasMore() && i-- > 0) {
const v = s.readInt(2);
if (GREASE_VALUES.includes(v)) continue;
if (v > highestVersion) highestVersion = v;
}
return highestVersion;
}
/**
* Parses the application_layer_protocol_negotiation extension and returns the first value.
* @param {Uint8Array} bytes
* @returns {number}
*/
export function parseFirstALPNValue(bytes) {
const s = new Stream(bytes);
const alpnExtLen = s.readInt(2);
if (alpnExtLen < 3) return "00";
const strLen = s.readInt(1);
if (strLen < 2) return "00";
return s.readString(strLen);
}
+174
View File
@@ -0,0 +1,174 @@
/**
* XXTEA library
*
* Encryption Algorithm Authors:
* David J. Wheeler
* Roger M. Needham
*
* @author Ma Bingyao [mabingyao@gmail.com]
* @author n1474335 [n1474335@gmail.com]
* @license MIT
*/
const DELTA = 0x9E3779B9;
/**
* Convert a buffer to a Uint8Array
* @param {Uint32Array} v
* @param {boolean} includeLength
* @returns {Uint8Array}
*/
function toUint8Array(v, includeLength) {
const length = v.length;
let n = length << 2;
if (includeLength) {
const m = v[length - 1];
n -= 4;
if ((m < n - 3) || (m > n)) {
return null;
}
n = m;
}
const bytes = new Uint8Array(n);
for (let i = 0; i < n; i++) {
bytes[i] = v[i >> 2] >> ((i & 3) << 3);
}
return bytes;
}
/**
* Convert a buffer to a Uint32Array
* @param {TypedArray} bs
* @param {boolean} includeLength
* @returns {Uint32Array}
*/
function toUint32Array(bs, includeLength) {
const length = bs.length;
let n = length >> 2;
if ((length & 3) !== 0) {
++n;
}
let v;
if (includeLength) {
v = new Uint32Array(n + 1);
v[n] = length;
} else {
v = new Uint32Array(n);
}
for (let i = 0; i < length; ++i) {
v[i >> 2] |= bs[i] << ((i & 3) << 3);
}
return v;
}
/**
* Mask an int to 32 bits
* @param {number} i
* @returns {number}
*/
function int32(i) {
return i & 0xFFFFFFFF;
}
/**
* MX function for data randomisation
* @param {number} sum
* @param {number} y
* @param {number} z
* @param {number} p
* @param {number} e
* @param {number} k
* @returns {number}
*/
function mx(sum, y, z, p, e, k) {
return ((z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4)) ^ ((sum ^ y) + (k[p & 3 ^ e] ^ z));
}
/**
* Ensure an array is a multiple of 16 bits
* @param {TypedArray} k
* @returns {TypedArray}
*/
function fixk(k) {
if (k.length < 16) {
const key = new Uint8Array(16);
key.set(k);
return key;
}
return k;
}
/**
* Performs XXTEA encryption on a Uint32Array
* @param {Uint32Array} v
* @param {Uint32Array} k
* @returns {Uint32Array}
*/
function encryptUint32Array(v, k) {
const length = v.length;
const n = length - 1;
let y, z, sum, e, p, q;
z = v[n];
sum = 0;
for (q = Math.floor(6 + 52 / length) | 0; q > 0; --q) {
sum = int32(sum + DELTA);
e = sum >>> 2 & 3;
for (p = 0; p < n; ++p) {
y = v[p + 1];
z = v[p] = int32(v[p] + mx(sum, y, z, p, e, k));
}
y = v[0];
z = v[n] = int32(v[n] + mx(sum, y, z, n, e, k));
}
return v;
}
/**
* Performs XXTEA decryption on a Uint32Array
* @param {Uint32Array} v
* @param {Uint32Array} k
* @returns {Uint32Array}
*/
function decryptUint32Array(v, k) {
const length = v.length;
const n = length - 1;
let y, z, sum, e, p;
y = v[0];
const q = Math.floor(6 + 52 / length);
for (sum = int32(q * DELTA); sum !== 0; sum = int32(sum - DELTA)) {
e = sum >>> 2 & 3;
for (p = n; p > 0; --p) {
z = v[p - 1];
y = v[p] = int32(v[p] - mx(sum, y, z, p, e, k));
}
z = v[n];
y = v[0] = int32(v[0] - mx(sum, y, z, 0, e, k));
}
return v;
}
/**
* Encrypt function
* @param {TypedArray} data
* @param {TypedArray} key
* @returns {Uint8Array}
*/
export function encrypt(data, key) {
if (data === undefined || data === null || data.length === 0) {
return data;
}
return toUint8Array(encryptUint32Array(toUint32Array(data, true), toUint32Array(fixk(key), false)), false);
}
/**
* Decrypt function
* @param {TypedArray} data
* @param {TypedArray} key
* @returns {Uint8Array}
*/
export function decrypt(data, key) {
if (data === undefined || data === null || data.length === 0) {
return data;
}
return toUint8Array(decryptUint32Array(toUint32Array(data, false), toUint32Array(fixk(key), false)), true);
}
+1 -1
View File
@@ -112,7 +112,7 @@ class AESDecrypt extends Operation {
run(input, args) {
const key = Utils.convertToByteString(args[0].string, args[0].option),
iv = Utils.convertToByteString(args[1].string, args[1].option),
mode = args[2].substring(0, 3),
mode = args[2].split("/")[0],
noPadding = args[2].endsWith("NoPadding"),
inputType = args[3],
outputType = args[4],
+19 -1
View File
@@ -66,6 +66,14 @@ class AESEncrypt extends Operation {
{
name: "ECB",
off: [5]
},
{
name: "CBC/NoPadding",
off: [5]
},
{
name: "ECB/NoPadding",
off: [5]
}
]
},
@@ -98,7 +106,8 @@ class AESEncrypt extends Operation {
run(input, args) {
const key = Utils.convertToByteString(args[0].string, args[0].option),
iv = Utils.convertToByteString(args[1].string, args[1].option),
mode = args[2],
mode = args[2].split("/")[0],
noPadding = args[2].endsWith("NoPadding"),
inputType = args[3],
outputType = args[4],
aad = Utils.convertToByteString(args[5].string, args[5].option);
@@ -114,11 +123,20 @@ The following algorithms will be used based on the size of the key:
input = Utils.convertToByteString(input, inputType);
// Handle NoPadding modes
if (noPadding && input.length % 16 !== 0) {
throw new OperationError("Input length must be a multiple of 16 bytes for NoPadding modes.");
}
const cipher = forge.cipher.createCipher("AES-" + mode, key);
cipher.start({
iv: iv,
additionalData: mode === "GCM" ? aad : undefined
});
if (noPadding) {
cipher.mode.pad = function(output, options) {
return true;
};
}
cipher.update(forge.util.createBuffer(input));
cipher.finish();
+9 -2
View File
@@ -22,7 +22,13 @@ class AddLineNumbers extends Operation {
this.description = "Adds line numbers to the output.";
this.inputType = "string";
this.outputType = "string";
this.args = [];
this.args = [
{
"name": "Offset",
"type": "number",
"value": 0
}
];
}
/**
@@ -33,10 +39,11 @@ class AddLineNumbers extends Operation {
run(input, args) {
const lines = input.split("\n"),
width = lines.length.toString().length;
const offset = args[0] ? parseInt(args[0], 10) : 0;
let output = "";
for (let n = 0; n < lines.length; n++) {
output += (n+1).toString().padStart(width, " ") + " " + lines[n] + "\n";
output += (n+1+offset).toString().padStart(width, " ") + " " + lines[n] + "\n";
}
return output.slice(0, output.length-1);
}
+8 -8
View File
@@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs";
import { isImage } from "../lib/FileType.mjs";
import { toBase64 } from "../lib/Base64.mjs";
import { isWorkerEnvironment } from "../Utils.mjs";
import jimp from "jimp";
import Jimp from "jimp/es/index.js";
/**
* Add Text To Image operation
@@ -127,7 +127,7 @@ class AddTextToImage extends Operation {
let image;
try {
image = await jimp.read(input);
image = await Jimp.read(input);
} catch (err) {
throw new OperationError(`Error loading image. (${err})`);
}
@@ -163,7 +163,7 @@ class AddTextToImage extends Operation {
const font = fontsMap[fontFace];
// LoadFont needs an absolute url, so append the font name to self.docURL
const jimpFont = await jimp.loadFont(self.docURL + "/" + font.default);
const jimpFont = await Jimp.loadFont(self.docURL + "/" + font.default);
jimpFont.pages.forEach(function(page) {
if (page.bitmap) {
@@ -190,7 +190,7 @@ class AddTextToImage extends Operation {
});
// Create a temporary image to hold the rendered text
const textImage = new jimp(jimp.measureText(jimpFont, text), jimp.measureTextHeight(jimpFont, text));
const textImage = new Jimp(Jimp.measureText(jimpFont, text), Jimp.measureTextHeight(jimpFont, text));
textImage.print(jimpFont, 0, 0, text);
// Scale the rendered text image to the correct size
@@ -198,9 +198,9 @@ class AddTextToImage extends Operation {
if (size !== 1) {
// Use bicubic for decreasing size
if (size > 1) {
textImage.scale(scaleFactor, jimp.RESIZE_BICUBIC);
textImage.scale(scaleFactor, Jimp.RESIZE_BICUBIC);
} else {
textImage.scale(scaleFactor, jimp.RESIZE_BILINEAR);
textImage.scale(scaleFactor, Jimp.RESIZE_BILINEAR);
}
}
@@ -234,9 +234,9 @@ class AddTextToImage extends Operation {
let imageBuffer;
if (image.getMIME() === "image/gif") {
imageBuffer = await image.getBufferAsync(jimp.MIME_PNG);
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
} else {
imageBuffer = await image.getBufferAsync(jimp.AUTO);
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
}
return imageBuffer.buffer;
} catch (err) {
+53
View File
@@ -0,0 +1,53 @@
/**
* @author sw5678
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
/**
* Alternating caps operation
*/
class AlternatingCaps extends Operation {
/**
* AlternatingCaps constructor
*/
constructor() {
super();
this.name = "Alternating Caps";
this.module = "Default";
this.description = "Alternating caps, also known as studly caps, sticky caps, or spongecase is a form of text notation in which the capitalization of letters varies by some pattern, or arbitrarily. An example of this would be spelling 'alternative caps' as 'aLtErNaTiNg CaPs'.";
this.infoURL = "https://en.wikipedia.org/wiki/Alternating_caps";
this.inputType = "string";
this.outputType = "string";
this.args= [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
let output = "";
let previousCaps = true;
for (let i = 0; i < input.length; i++) {
// Check if the element is a letter
if (!RegExp(/^\p{L}/, "u").test(input[i])) {
output += input[i];
} else if (previousCaps) {
output += input[i].toLowerCase();
previousCaps = false;
} else {
output += input[i].toUpperCase();
previousCaps = true;
}
}
return output;
}
}
export default AlternatingCaps;
+48
View File
@@ -0,0 +1,48 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import * as uuid from "uuid";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* Analyse UUID operation
*/
class AnalyseUUID extends Operation {
/**
* AnalyseUUID constructor
*/
constructor() {
super();
this.name = "Analyse UUID";
this.module = "Crypto";
this.description = "Tries to determine information about a given UUID and suggests which version may have been used to generate it";
this.infoURL = "https://wikipedia.org/wiki/Universally_unique_identifier";
this.inputType = "string";
this.outputType = "string";
this.args = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
try {
const uuidVersion = uuid.version(input);
return "UUID version: " + uuidVersion;
} catch (error) {
throw new OperationError("Invalid UUID");
}
}
}
export default AnalyseUUID;
+117
View File
@@ -0,0 +1,117 @@
/**
* @author Tan Zhen Yong [tzy@beyondthesprawl.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import argon2 from "argon2-browser";
/**
* Argon2 operation
*/
class Argon2 extends Operation {
/**
* Argon2 constructor
*/
constructor() {
super();
this.name = "Argon2";
this.module = "Crypto";
this.description = "Argon2 is a key derivation function that was selected as the winner of the Password Hashing Competition in July 2015. It was designed by Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich from the University of Luxembourg.<br><br>Enter the password in the input to generate its hash.";
this.infoURL = "https://wikipedia.org/wiki/Argon2";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
"name": "Salt",
"type": "toggleString",
"value": "somesalt",
"toggleValues": ["UTF8", "Hex", "Base64", "Latin1"]
},
{
"name": "Iterations",
"type": "number",
"value": 3
},
{
"name": "Memory (KiB)",
"type": "number",
"value": 4096
},
{
"name": "Parallelism",
"type": "number",
"value": 1
},
{
"name": "Hash length (bytes)",
"type": "number",
"value": 32
},
{
"name": "Type",
"type": "option",
"value": ["Argon2i", "Argon2d", "Argon2id"],
"defaultIndex": 0
},
{
"name": "Output format",
"type": "option",
"value": ["Encoded hash", "Hex hash", "Raw hash"]
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
async run(input, args) {
const argon2Types = {
"Argon2i": argon2.ArgonType.Argon2i,
"Argon2d": argon2.ArgonType.Argon2d,
"Argon2id": argon2.ArgonType.Argon2id
};
const salt = Utils.convertToByteString(args[0].string || "", args[0].option),
time = args[1],
mem = args[2],
parallelism = args[3],
hashLen = args[4],
type = argon2Types[args[5]],
outFormat = args[6];
try {
const result = await argon2.hash({
pass: input,
salt,
time,
mem,
parallelism,
hashLen,
type,
});
switch (outFormat) {
case "Hex hash":
return result.hashHex;
case "Raw hash":
return Utils.arrayBufferToStr(result.hash);
case "Encoded hash":
default:
return result.encoded;
}
} catch (err) {
throw new OperationError(`Error: ${err.message}`);
}
}
}
export default Argon2;
+58
View File
@@ -0,0 +1,58 @@
/**
* @author Tan Zhen Yong [tzy@beyondthesprawl.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import argon2 from "argon2-browser";
/**
* Argon2 compare operation
*/
class Argon2Compare extends Operation {
/**
* Argon2Compare constructor
*/
constructor() {
super();
this.name = "Argon2 compare";
this.module = "Crypto";
this.description = "Tests whether the input matches the given Argon2 hash. To test multiple possible passwords, use the 'Fork' operation.";
this.infoURL = "https://wikipedia.org/wiki/Argon2";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
"name": "Encoded hash",
"type": "string",
"value": ""
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
async run(input, args) {
const encoded = args[0];
try {
await argon2.verify({
pass: input,
encoded
});
return `Match: ${input}`;
} catch (err) {
return "No match";
}
}
}
export default Argon2Compare;
+58
View File
@@ -0,0 +1,58 @@
/**
* @author xumptex [xumptex@outlook.fr]
* @copyright Crown Copyright 2025
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { blake3 } from "hash-wasm";
/**
* BLAKE3 operation
*/
class BLAKE3 extends Operation {
/**
* BLAKE3 constructor
*/
constructor() {
super();
this.name = "BLAKE3";
this.module = "Hashing";
this.description = "Hashes the input using BLAKE3 (UTF-8 encoded), with an optional key (also UTF-8), and outputs the result in hexadecimal format.";
this.infoURL = "https://en.wikipedia.org/wiki/BLAKE_(hash_function)#BLAKE3";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
"name": "Size (bytes)",
"type": "number"
}, {
"name": "Key",
"type": "string",
"value": ""
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const key = args[1];
const size = args[0];
// Check if the user want a key hash or not
if (key === "") {
return blake3(input, size*8);
} if (key.length !== 32) {
throw new OperationError("The key must be exactly 32 bytes long");
}
return blake3(input, size*8, key);
}
}
export default BLAKE3;
+6 -2
View File
@@ -70,10 +70,14 @@ class BlowfishDecrypt extends Operation {
inputType = args[3],
outputType = args[4];
if (key.length !== 8) {
if (key.length < 4 || key.length > 56) {
throw new OperationError(`Invalid key length: ${key.length} bytes
Blowfish uses a key length of 8 bytes (64 bits).`);
Blowfish's key length needs to be between 4 and 56 bytes (32-448 bits).`);
}
if (mode !== "ECB" && iv.length !== 8) {
throw new OperationError(`Invalid IV length: ${iv.length} bytes. Expected 8 bytes.`);
}
input = Utils.convertToByteString(input, inputType);
+6 -2
View File
@@ -70,10 +70,14 @@ class BlowfishEncrypt extends Operation {
inputType = args[3],
outputType = args[4];
if (key.length !== 8) {
if (key.length < 4 || key.length > 56) {
throw new OperationError(`Invalid key length: ${key.length} bytes
Blowfish uses a key length of 8 bytes (64 bits).`);
Blowfish's key length needs to be between 4 and 56 bytes (32-448 bits).`);
}
if (mode !== "ECB" && iv.length !== 8) {
throw new OperationError(`Invalid IV length: ${iv.length} bytes. Expected 8 bytes.`);
}
input = Utils.convertToByteString(input, inputType);
+4 -4
View File
@@ -10,7 +10,7 @@ import { isWorkerEnvironment } from "../Utils.mjs";
import { isImage } from "../lib/FileType.mjs";
import { toBase64 } from "../lib/Base64.mjs";
import { gaussianBlur } from "../lib/ImageManipulation.mjs";
import jimp from "jimp";
import Jimp from "jimp/es/index.js";
/**
* Blur Image operation
@@ -59,7 +59,7 @@ class BlurImage extends Operation {
let image;
try {
image = await jimp.read(input);
image = await Jimp.read(input);
} catch (err) {
throw new OperationError(`Error loading image. (${err})`);
}
@@ -79,9 +79,9 @@ class BlurImage extends Operation {
let imageBuffer;
if (image.getMIME() === "image/gif") {
imageBuffer = await image.getBufferAsync(jimp.MIME_PNG);
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
} else {
imageBuffer = await image.getBufferAsync(jimp.AUTO);
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
}
return imageBuffer.buffer;
} catch (err) {
-41
View File
@@ -1,41 +0,0 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import JSCRC from "js-crc";
/**
* CRC-16 Checksum operation
*/
class CRC16Checksum extends Operation {
/**
* CRC16Checksum constructor
*/
constructor() {
super();
this.name = "CRC-16 Checksum";
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";
this.outputType = "string";
this.args = [];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
return JSCRC.crc16(input);
}
}
export default CRC16Checksum;
-41
View File
@@ -1,41 +0,0 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import JSCRC from "js-crc";
/**
* CRC-32 Checksum operation
*/
class CRC32Checksum extends Operation {
/**
* CRC32Checksum constructor
*/
constructor() {
super();
this.name = "CRC-32 Checksum";
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";
this.outputType = "string";
this.args = [];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
return JSCRC.crc32(input);
}
}
export default CRC32Checksum;
-157
View File
@@ -1,157 +0,0 @@
/**
* @author mshwed [m@ttshwed.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { toHexFast } from "../lib/Hex.mjs";
/**
* CRC-8 Checksum operation
*/
class CRC8Checksum extends Operation {
/**
* CRC8Checksum constructor
*/
constructor() {
super();
this.name = "CRC-8 Checksum";
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";
this.outputType = "string";
this.args = [
{
"name": "Algorithm",
"type": "option",
"value": [
"CRC-8",
"CRC-8/CDMA2000",
"CRC-8/DARC",
"CRC-8/DVB-S2",
"CRC-8/EBU",
"CRC-8/I-CODE",
"CRC-8/ITU",
"CRC-8/MAXIM",
"CRC-8/ROHC",
"CRC-8/WCDMA"
]
}
];
}
/**
* Generates the pre-computed lookup table for byte division
*
* @param polynomial
*/
calculateCRC8LookupTable(polynomial) {
const crc8Table = new Uint8Array(256);
let currentByte;
for (let i = 0; i < 256; i++) {
currentByte = i;
for (let bit = 0; bit < 8; bit++) {
if ((currentByte & 0x80) !== 0) {
currentByte <<= 1;
currentByte ^= polynomial;
} else {
currentByte <<= 1;
}
}
crc8Table[i] = currentByte;
}
return crc8Table;
}
/**
* Calculates the CRC-8 Checksum from an input
*
* @param {ArrayBuffer} input
* @param {number} polynomial
* @param {number} initializationValue
* @param {boolean} inputReflection
* @param {boolean} outputReflection
* @param {number} xorOut
*/
calculateCRC8(input, polynomial, initializationValue, inputReflection, outputReflection, xorOut) {
const crcSize = 8;
const crcTable = this.calculateCRC8LookupTable(polynomial);
let crc = initializationValue !== 0 ? initializationValue : 0;
let currentByte, position;
input = new Uint8Array(input);
for (const inputByte of input) {
currentByte = inputReflection ? this.reverseBits(inputByte, crcSize) : inputByte;
position = (currentByte ^ crc) & 255;
crc = crcTable[position];
}
crc = outputReflection ? this.reverseBits(crc, crcSize) : crc;
if (xorOut !== 0) crc = crc ^ xorOut;
return toHexFast(new Uint8Array([crc]));
}
/**
* Reverse the bits for a given input byte.
*
* @param {number} input
*/
reverseBits(input, hashSize) {
let reversedByte = 0;
for (let i = hashSize - 1; i >= 0; i--) {
reversedByte |= ((input & 1) << i);
input >>= 1;
}
return reversedByte;
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const algorithm = args[0];
switch (algorithm) {
case "CRC-8":
return this.calculateCRC8(input, 0x7, 0x0, false, false, 0x0);
case "CRC-8/CDMA2000":
return this.calculateCRC8(input, 0x9B, 0xFF, false, false, 0x0);
case "CRC-8/DARC":
return this.calculateCRC8(input, 0x39, 0x0, true, true, 0x0);
case "CRC-8/DVB-S2":
return this.calculateCRC8(input, 0xD5, 0x0, false, false, 0x0);
case "CRC-8/EBU":
return this.calculateCRC8(input, 0x1D, 0xFF, true, true, 0x0);
case "CRC-8/I-CODE":
return this.calculateCRC8(input, 0x1D, 0xFD, false, false, 0x0);
case "CRC-8/ITU":
return this.calculateCRC8(input, 0x7, 0x0, false, false, 0x55);
case "CRC-8/MAXIM":
return this.calculateCRC8(input, 0x31, 0x0, true, true, 0x0);
case "CRC-8/ROHC":
return this.calculateCRC8(input, 0x7, 0xFF, true, true, 0x0);
case "CRC-8/WCDMA":
return this.calculateCRC8(input, 0x9B, 0x0, true, true, 0x0);
default:
throw new OperationError("Unknown checksum algorithm");
}
}
}
export default CRC8Checksum;
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -6,7 +6,7 @@
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import xmldom from "xmldom";
import xmldom from "@xmldom/xmldom";
import nwmatcher from "nwmatcher";
/**
+1 -1
View File
@@ -21,7 +21,7 @@ class CTPH extends Operation {
this.name = "CTPH";
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.xyz/wiki/index.php?title=Context_Triggered_Piecewise_Hashing";
this.infoURL = "https://forensics.wiki/context_triggered_piecewise_hashing/";
this.inputType = "string";
this.outputType = "string";
this.args = [];
+98
View File
@@ -0,0 +1,98 @@
/**
* @author tedk [tedk@ted.do]
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
/**
* Caret/M-decode operation
*
* https://gist.githubusercontent.com/JaHIY/3c91bbf7bea5661e6abfbd1349ee81a2/raw/c7b480e9ff24bcb8f5287a8a8a2dcb9bf5628506/decode_m_notation.cpp
*/
class CaretMdecode extends Operation {
/**
* CaretMdecode constructor
*/
constructor() {
super();
this.name = "Caret/M-decode";
this.module = "Default";
this.description = "Decodes caret or M-encoded strings, i.e. ^M turns into a newline, M-^] turns into 0x9d. Sources such as `cat -v`.\n\nPlease be aware that when using `cat -v` ^_ (caret-underscore) will not be encoded, but represents a valid encoding (namely that of 0x1f).";
this.infoURL = "https://en.wikipedia.org/wiki/Caret_notation";
this.inputType = "string";
this.outputType = "byteArray";
this.args = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {byteArray}
*/
run(input, args) {
const bytes = [];
let prev = "";
for (let i = 0; i < input.length; i++) {
const charCode = input.charCodeAt(i);
const curChar = input.charAt(i);
if (prev === "M-^") {
if (charCode > 63 && charCode <= 95) {
bytes.push(charCode + 64);
} else if (charCode === 63) {
bytes.push(255);
} else {
bytes.push(77, 45, 94, charCode);
}
prev = "";
} else if (prev === "M-") {
if (curChar === "^") {
prev = prev + "^";
} else if (charCode >= 32 && charCode <= 126) {
bytes.push(charCode + 128);
prev = "";
} else {
bytes.push(77, 45, charCode);
prev = "";
}
} else if (prev === "M") {
if (curChar === "-") {
prev = prev + "-";
} else {
bytes.push(77, charCode);
prev = "";
}
} else if (prev === "^") {
if (charCode > 63 && charCode <= 126) {
bytes.push(charCode - 64);
} else if (charCode === 63) {
bytes.push(127);
} else {
bytes.push(94, charCode);
}
prev = "";
} else {
if (curChar === "M") {
prev = "M";
} else if (curChar === "^") {
prev = "^";
} else {
bytes.push(charCode);
}
}
}
return bytes;
}
}
export default CaretMdecode;
+2 -2
View File
@@ -100,7 +100,7 @@ class ChaCha extends Operation {
super();
this.name = "ChaCha";
this.module = "Default";
this.module = "Ciphers";
this.description = "ChaCha is a stream cipher designed by Daniel J. Bernstein. It is a variant of the Salsa stream cipher. Several parameterizations exist; 'ChaCha' may refer to the original construction, or to the variant as described in RFC-8439. ChaCha is often used with Poly1305, in the ChaCha20-Poly1305 AEAD construction.<br><br><b>Key:</b> ChaCha uses a key of 16 or 32 bytes (128 or 256 bits).<br><br><b>Nonce:</b> ChaCha uses a nonce of 8 or 12 bytes (64 or 96 bits).<br><br><b>Counter:</b> ChaCha uses a counter of 4 or 8 bytes (32 or 64 bits); together, the nonce and counter must add up to 16 bytes. The counter starts at zero at the start of the keystream, and is incremented at every 64 bytes.";
this.infoURL = "https://wikipedia.org/wiki/Salsa20#ChaCha_variant";
this.inputType = "string";
@@ -191,7 +191,7 @@ ChaCha uses a nonce of 8 or 12 bytes (64 or 96 bits).`);
if (outputType === "Hex") {
return toHex(output);
} else {
return Utils.arrayBufferToStr(output);
return Utils.arrayBufferToStr(Uint8Array.from(output).buffer);
}
}
+1 -1
View File
@@ -24,7 +24,7 @@ class CompareCTPHHashes extends Operation {
this.name = "Compare CTPH hashes";
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.xyz/wiki/index.php?title=Context_Triggered_Piecewise_Hashing";
this.infoURL = "https://forensics.wiki/context_triggered_piecewise_hashing/";
this.inputType = "string";
this.outputType = "Number";
this.args = [
+1 -1
View File
@@ -24,7 +24,7 @@ class CompareSSDEEPHashes extends Operation {
this.name = "Compare SSDEEP hashes";
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.xyz/wiki/index.php?title=Ssdeep";
this.infoURL = "https://forensics.wiki/ssdeep/";
this.inputType = "string";
this.outputType = "Number";
this.args = [
+16 -16
View File
@@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs";
import { isImage } from "../lib/FileType.mjs";
import { toBase64 } from "../lib/Base64.mjs";
import { isWorkerEnvironment } from "../Utils.mjs";
import jimp from "jimp";
import Jimp from "jimp/es/index.js";
/**
* Contain Image operation
@@ -91,20 +91,20 @@ class ContainImage extends Operation {
const [width, height, hAlign, vAlign, alg, opaqueBg] = args;
const resizeMap = {
"Nearest Neighbour": jimp.RESIZE_NEAREST_NEIGHBOR,
"Bilinear": jimp.RESIZE_BILINEAR,
"Bicubic": jimp.RESIZE_BICUBIC,
"Hermite": jimp.RESIZE_HERMITE,
"Bezier": jimp.RESIZE_BEZIER
"Nearest Neighbour": Jimp.RESIZE_NEAREST_NEIGHBOR,
"Bilinear": Jimp.RESIZE_BILINEAR,
"Bicubic": Jimp.RESIZE_BICUBIC,
"Hermite": Jimp.RESIZE_HERMITE,
"Bezier": Jimp.RESIZE_BEZIER
};
const alignMap = {
"Left": jimp.HORIZONTAL_ALIGN_LEFT,
"Center": jimp.HORIZONTAL_ALIGN_CENTER,
"Right": jimp.HORIZONTAL_ALIGN_RIGHT,
"Top": jimp.VERTICAL_ALIGN_TOP,
"Middle": jimp.VERTICAL_ALIGN_MIDDLE,
"Bottom": jimp.VERTICAL_ALIGN_BOTTOM
"Left": Jimp.HORIZONTAL_ALIGN_LEFT,
"Center": Jimp.HORIZONTAL_ALIGN_CENTER,
"Right": Jimp.HORIZONTAL_ALIGN_RIGHT,
"Top": Jimp.VERTICAL_ALIGN_TOP,
"Middle": Jimp.VERTICAL_ALIGN_MIDDLE,
"Bottom": Jimp.VERTICAL_ALIGN_BOTTOM
};
if (!isImage(input)) {
@@ -113,7 +113,7 @@ class ContainImage extends Operation {
let image;
try {
image = await jimp.read(input);
image = await Jimp.read(input);
} catch (err) {
throw new OperationError(`Error loading image. (${err})`);
}
@@ -123,16 +123,16 @@ class ContainImage extends Operation {
image.contain(width, height, alignMap[hAlign] | alignMap[vAlign], resizeMap[alg]);
if (opaqueBg) {
const newImage = await jimp.read(width, height, 0x000000FF);
const newImage = await Jimp.read(width, height, 0x000000FF);
newImage.blit(image, 0, 0);
image = newImage;
}
let imageBuffer;
if (image.getMIME() === "image/gif") {
imageBuffer = await image.getBufferAsync(jimp.MIME_PNG);
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
} else {
imageBuffer = await image.getBufferAsync(jimp.AUTO);
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
}
return imageBuffer.buffer;
} catch (err) {
+12 -12
View File
@@ -8,7 +8,7 @@ import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { isImage } from "../lib/FileType.mjs";
import { toBase64 } from "../lib/Base64.mjs";
import jimp from "jimp";
import Jimp from "jimp/es/index.js";
/**
* Convert Image Format operation
@@ -76,19 +76,19 @@ class ConvertImageFormat extends Operation {
async run(input, args) {
const [format, jpegQuality, pngFilterType, pngDeflateLevel] = args;
const formatMap = {
"JPEG": jimp.MIME_JPEG,
"PNG": jimp.MIME_PNG,
"BMP": jimp.MIME_BMP,
"TIFF": jimp.MIME_TIFF
"JPEG": Jimp.MIME_JPEG,
"PNG": Jimp.MIME_PNG,
"BMP": Jimp.MIME_BMP,
"TIFF": Jimp.MIME_TIFF
};
const pngFilterMap = {
"Auto": jimp.PNG_FILTER_AUTO,
"None": jimp.PNG_FILTER_NONE,
"Sub": jimp.PNG_FILTER_SUB,
"Up": jimp.PNG_FILTER_UP,
"Average": jimp.PNG_FILTER_AVERAGE,
"Paeth": jimp.PNG_FILTER_PATH
"Auto": Jimp.PNG_FILTER_AUTO,
"None": Jimp.PNG_FILTER_NONE,
"Sub": Jimp.PNG_FILTER_SUB,
"Up": Jimp.PNG_FILTER_UP,
"Average": Jimp.PNG_FILTER_AVERAGE,
"Paeth": Jimp.PNG_FILTER_PATH
};
const mime = formatMap[format];
@@ -98,7 +98,7 @@ class ConvertImageFormat extends Operation {
}
let image;
try {
image = await jimp.read(input);
image = await Jimp.read(input);
} catch (err) {
throw new OperationError(`Error opening image file. (${err})`);
}
+116
View File
@@ -0,0 +1,116 @@
/**
* @author bartblaze []
* @copyright Crown Copyright 2025
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
/**
* Convert Leet Speak operation
*/
class ConvertLeetSpeak extends Operation {
/**
* ConvertLeetSpeak constructor
*/
constructor() {
super();
this.name = "Convert Leet Speak";
this.module = "Default";
this.description = "Converts to and from Leet Speak.";
this.infoURL = "https://wikipedia.org/wiki/Leet";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Direction",
type: "option",
value: ["To Leet Speak", "From Leet Speak"],
defaultIndex: 0
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const direction = args[0];
if (direction === "To Leet Speak") {
return input.replace(/[a-z]/gi, char => {
const leetChar = toLeetMap[char.toLowerCase()] || char;
return char === char.toUpperCase() ? leetChar.toUpperCase() : leetChar;
});
} else if (direction === "From Leet Speak") {
return input.replace(/[48cd3f6h1jklmn0pqr57uvwxyz]/gi, char => {
const normalChar = fromLeetMap[char] || char;
return normalChar;
});
}
}
}
const toLeetMap = {
"a": "4",
"b": "b",
"c": "c",
"d": "d",
"e": "3",
"f": "f",
"g": "g",
"h": "h",
"i": "1",
"j": "j",
"k": "k",
"l": "l",
"m": "m",
"n": "n",
"o": "0",
"p": "p",
"q": "q",
"r": "r",
"s": "5",
"t": "7",
"u": "u",
"v": "v",
"w": "w",
"x": "x",
"y": "y",
"z": "z"
};
const fromLeetMap = {
"4": "a",
"b": "b",
"c": "c",
"d": "d",
"3": "e",
"f": "f",
"g": "g",
"h": "h",
"1": "i",
"j": "j",
"k": "k",
"l": "l",
"m": "m",
"n": "n",
"0": "o",
"p": "p",
"q": "q",
"r": "r",
"5": "s",
"7": "t",
"u": "u",
"v": "v",
"w": "w",
"x": "x",
"y": "y",
"z": "z"
};
export default ConvertLeetSpeak;
+1 -1
View File
@@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs";
import { isImage } from "../lib/FileType.mjs";
import { toBase64 } from "../lib/Base64.mjs";
import { isWorkerEnvironment } from "../Utils.mjs";
import jimp from "jimp";
import jimp from "jimp/es/index.js";
/**
* Cover Image operation
+4 -4
View File
@@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs";
import { isImage } from "../lib/FileType.mjs";
import { toBase64 } from "../lib/Base64.mjs";
import { isWorkerEnvironment } from "../Utils.mjs";
import jimp from "jimp";
import Jimp from "jimp/es/index.js";
/**
* Crop Image operation
@@ -99,7 +99,7 @@ class CropImage extends Operation {
let image;
try {
image = await jimp.read(input);
image = await Jimp.read(input);
} catch (err) {
throw new OperationError(`Error loading image. (${err})`);
}
@@ -119,9 +119,9 @@ class CropImage extends Operation {
let imageBuffer;
if (image.getMIME() === "image/gif") {
imageBuffer = await image.getBufferAsync(jimp.MIME_PNG);
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
} else {
imageBuffer = await image.getBufferAsync(jimp.AUTO);
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
}
return imageBuffer.buffer;
} catch (err) {
+2 -3
View File
@@ -22,7 +22,7 @@ class DESDecrypt extends Operation {
this.name = "DES Decrypt";
this.module = "Ciphers";
this.description = "DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.<br><br><b>Key:</b> DES uses a key length of 8 bytes (64 bits).<br>Triple DES uses a key length of 24 bytes (192 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used as a default.";
this.description = "DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.<br><br><b>Key:</b> DES uses a key length of 8 bytes (64 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used as a default.";
this.infoURL = "https://wikipedia.org/wiki/Data_Encryption_Standard";
this.inputType = "string";
this.outputType = "string";
@@ -72,8 +72,7 @@ class DESDecrypt extends Operation {
if (key.length !== 8) {
throw new OperationError(`Invalid key length: ${key.length} bytes
DES uses a key length of 8 bytes (64 bits).
Triple DES uses a key length of 24 bytes (192 bits).`);
DES uses a key length of 8 bytes (64 bits).`);
}
if (iv.length !== 8 && mode !== "ECB") {
throw new OperationError(`Invalid IV length: ${iv.length} bytes
+2 -3
View File
@@ -22,7 +22,7 @@ class DESEncrypt extends Operation {
this.name = "DES Encrypt";
this.module = "Ciphers";
this.description = "DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.<br><br><b>Key:</b> DES uses a key length of 8 bytes (64 bits).<br>Triple DES uses a key length of 24 bytes (192 bits).<br><br>You can generate a password-based key using one of the KDF operations.<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.";
this.description = "DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.<br><br><b>Key:</b> DES uses a key length of 8 bytes (64 bits).<br><br>You can generate a password-based key using one of the KDF operations.<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.";
this.infoURL = "https://wikipedia.org/wiki/Data_Encryption_Standard";
this.inputType = "string";
this.outputType = "string";
@@ -70,8 +70,7 @@ class DESEncrypt extends Operation {
if (key.length !== 8) {
throw new OperationError(`Invalid key length: ${key.length} bytes
DES uses a key length of 8 bytes (64 bits).
Triple DES uses a key length of 24 bytes (192 bits).`);
DES uses a key length of 8 bytes (64 bits).`);
}
if (iv.length !== 8 && mode !== "ECB") {
throw new OperationError(`Invalid IV length: ${iv.length} bytes
+107
View File
@@ -0,0 +1,107 @@
/**
* @author tomgond [tom.gonda@gmail.com]
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import moment from "moment-timezone";
import {DATETIME_FORMATS, FORMAT_EXAMPLES} from "../lib/DateTime.mjs";
/**
* DateTime Delta operation
*/
class DateTimeDelta extends Operation {
/**
* DateTimeDelta constructor
*/
constructor() {
super();
this.name = "DateTime Delta";
this.module = "Default";
this.description = "Calculates a new DateTime value given an input DateTime value and a time difference (delta) from the input DateTime value.";
this.inputType = "string";
this.outputType = "html";
this.args = [
{
"name": "Built in formats",
"type": "populateOption",
"value": DATETIME_FORMATS,
"target": 1
},
{
"name": "Input format string",
"type": "binaryString",
"value": "DD/MM/YYYY HH:mm:ss"
},
{
"name": "Time Operation",
"type": "option",
"value": ["Add", "Subtract"]
},
{
"name": "Days",
"type": "number",
"value": 0
},
{
"name": "Hours",
"type": "number",
"value": 0
},
{
"name": "Minutes",
"type": "number",
"value": 0
},
{
"name": "Seconds",
"type": "number",
"value": 0
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const inputTimezone = "UTC";
const inputFormat = args[1];
const operationType = args[2];
const daysDelta = args[3];
const hoursDelta = args[4];
const minutesDelta = args[5];
const secondsDelta = args[6];
let date = "";
try {
date = moment.tz(input, inputFormat, inputTimezone);
if (!date || date.format() === "Invalid date") throw Error;
} catch (err) {
return `Invalid format.\n\n${FORMAT_EXAMPLES}`;
}
let newDate;
if (operationType === "Add") {
newDate = date.add(daysDelta, "days")
.add(hoursDelta, "hours")
.add(minutesDelta, "minutes")
.add(secondsDelta, "seconds");
} else {
newDate = date.add(-daysDelta, "days")
.add(-hoursDelta, "hours")
.add(-minutesDelta, "minutes")
.add(-secondsDelta, "seconds");
}
return newDate.tz(inputTimezone).format(inputFormat.replace(/[<>]/g, ""));
}
}
export default DateTimeDelta;
+4 -2
View File
@@ -62,11 +62,13 @@ class DeriveEVPKey extends Operation {
* @returns {string}
*/
run(input, args) {
const passphrase = Utils.convertToByteString(args[0].string, args[0].option),
const passphrase = CryptoJS.enc.Latin1.parse(
Utils.convertToByteString(args[0].string, args[0].option)),
keySize = args[1] / 32,
iterations = args[2],
hasher = args[3],
salt = Utils.convertToByteString(args[4].string, args[4].option),
salt = CryptoJS.enc.Latin1.parse(
Utils.convertToByteString(args[4].string, args[4].option)),
key = CryptoJS.EvpKDF(passphrase, salt, { // lgtm [js/insufficient-password-hash]
keySize: keySize,
hasher: CryptoJS.algo[hasher],
+2 -2
View File
@@ -119,9 +119,9 @@ class Diff extends Operation {
for (let i = 0; i < diff.length; i++) {
if (diff[i].added) {
if (showAdded) output += "<span class='hl5'>" + Utils.escapeHtml(diff[i].value) + "</span>";
if (showAdded) output += "<ins>" + Utils.escapeHtml(diff[i].value) + "</ins>";
} else if (diff[i].removed) {
if (showRemoved) output += "<span class='hl3'>" + Utils.escapeHtml(diff[i].value) + "</span>";
if (showRemoved) output += "<del>" + Utils.escapeHtml(diff[i].value) + "</del>";
} else if (!showSubtraction) {
output += Utils.escapeHtml(diff[i].value);
}
+4 -4
View File
@@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs";
import { isImage } from "../lib/FileType.mjs";
import { toBase64 } from "../lib/Base64.mjs";
import { isWorkerEnvironment } from "../Utils.mjs";
import jimp from "jimp";
import Jimp from "jimp/es/index.js";
/**
* Image Dither operation
@@ -44,7 +44,7 @@ class DitherImage extends Operation {
let image;
try {
image = await jimp.read(input);
image = await Jimp.read(input);
} catch (err) {
throw new OperationError(`Error loading image. (${err})`);
}
@@ -55,9 +55,9 @@ class DitherImage extends Operation {
let imageBuffer;
if (image.getMIME() === "image/gif") {
imageBuffer = await image.getBufferAsync(jimp.MIME_PNG);
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
} else {
imageBuffer = await image.getBufferAsync(jimp.AUTO);
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
}
return imageBuffer.buffer;
} catch (err) {
+79
View File
@@ -0,0 +1,79 @@
/**
* @author Oshawk [oshawk@protonmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* Drop nth bytes operation
*/
class DropNthBytes extends Operation {
/**
* DropNthBytes constructor
*/
constructor() {
super();
this.name = "Drop nth bytes";
this.module = "Default";
this.description = "Drops every nth byte starting with a given byte.";
this.infoURL = "";
this.inputType = "byteArray";
this.outputType = "byteArray";
this.args = [
{
name: "Drop every",
type: "number",
value: 4
},
{
name: "Starting at",
type: "number",
value: 0
},
{
name: "Apply to each line",
type: "boolean",
value: false
}
];
}
/**
* @param {byteArray} input
* @param {Object[]} args
* @returns {byteArray}
*/
run(input, args) {
const n = args[0];
const start = args[1];
const eachLine = args[2];
if (parseInt(n, 10) !== n || n <= 0) {
throw new OperationError("'Drop every' must be a positive integer.");
}
if (parseInt(start, 10) !== start || start < 0) {
throw new OperationError("'Starting at' must be a positive or zero integer.");
}
let offset = 0;
const output = [];
for (let i = 0; i < input.length; i++) {
if (eachLine && input[i] === 0x0a) {
output.push(0x0a);
offset = i + 1;
} else if (i - offset < start || (i - (start + offset)) % n !== 0) {
output.push(input[i]);
}
}
return output;
}
}
export default DropNthBytes;
+107
View File
@@ -0,0 +1,107 @@
/**
* @author cplussharp
* @copyright Crown Copyright 2021
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { fromHex } from "../lib/Hex.mjs";
import { toBase64 } from "../lib/Base64.mjs";
import r from "jsrsasign";
/**
* ECDSA Sign operation
*/
class ECDSASign extends Operation {
/**
* ECDSASign constructor
*/
constructor() {
super();
this.name = "ECDSA Sign";
this.module = "Ciphers";
this.description = "Sign a plaintext message with a PEM encoded EC key.";
this.infoURL = "https://wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "ECDSA Private Key (PEM)",
type: "text",
value: "-----BEGIN EC PRIVATE KEY-----"
},
{
name: "Message Digest Algorithm",
type: "option",
value: [
"SHA-256",
"SHA-384",
"SHA-512",
"SHA-1",
"MD5"
]
},
{
name: "Output Format",
type: "option",
value: [
"ASN.1 HEX",
"P1363 HEX",
"JSON Web Signature",
"Raw JSON"
]
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const [keyPem, mdAlgo, outputFormat] = args;
if (keyPem.replace("-----BEGIN EC PRIVATE KEY-----", "").length === 0) {
throw new OperationError("Please enter a private key.");
}
const internalAlgorithmName = mdAlgo.replace("-", "") + "withECDSA";
const sig = new r.KJUR.crypto.Signature({ alg: internalAlgorithmName });
const key = r.KEYUTIL.getKey(keyPem);
if (key.type !== "EC") {
throw new OperationError("Provided key is not an EC key.");
}
if (!key.isPrivate) {
throw new OperationError("Provided key is not a private key.");
}
sig.init(key);
const signatureASN1Hex = sig.signString(input);
let result;
switch (outputFormat) {
case "ASN.1 HEX":
result = signatureASN1Hex;
break;
case "P1363 HEX":
result = r.KJUR.crypto.ECDSA.asn1SigToConcatSig(signatureASN1Hex);
break;
case "JSON Web Signature":
result = r.KJUR.crypto.ECDSA.asn1SigToConcatSig(signatureASN1Hex);
result = toBase64(fromHex(result), "A-Za-z0-9-_"); // base64url
break;
case "Raw JSON": {
const signatureRS = r.KJUR.crypto.ECDSA.parseSigHexInHexRS(signatureASN1Hex);
result = JSON.stringify(signatureRS);
break;
}
}
return result;
}
}
export default ECDSASign;
@@ -0,0 +1,146 @@
/**
* @author cplussharp
* @copyright Crown Copyright 2021
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { fromBase64, toBase64 } from "../lib/Base64.mjs";
import { fromHex, toHexFast } from "../lib/Hex.mjs";
import r from "jsrsasign";
/**
* ECDSA Sign operation
*/
class ECDSASignatureConversion extends Operation {
/**
* ECDSASignatureConversion constructor
*/
constructor() {
super();
this.name = "ECDSA Signature Conversion";
this.module = "Ciphers";
this.description = "Convert an ECDSA signature between hex, asn1 and json.";
this.infoURL = "https://wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Input Format",
type: "option",
value: [
"Auto",
"ASN.1 HEX",
"P1363 HEX",
"JSON Web Signature",
"Raw JSON"
]
},
{
name: "Output Format",
type: "option",
value: [
"ASN.1 HEX",
"P1363 HEX",
"JSON Web Signature",
"Raw JSON"
]
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
let inputFormat = args[0];
const outputFormat = args[1];
// detect input format
let inputJson;
if (inputFormat === "Auto") {
try {
inputJson = JSON.parse(input);
if (typeof(inputJson) === "object") {
inputFormat = "Raw JSON";
}
} catch {}
}
if (inputFormat === "Auto") {
const hexRegex = /^[a-f\d]{2,}$/gi;
if (hexRegex.test(input)) {
if (input.substring(0, 2) === "30" && r.ASN1HEX.isASN1HEX(input)) {
inputFormat = "ASN.1 HEX";
} else {
inputFormat = "P1363 HEX";
}
}
}
let inputBase64;
if (inputFormat === "Auto") {
try {
inputBase64 = fromBase64(input, "A-Za-z0-9-_", false);
inputFormat = "JSON Web Signature";
} catch {}
}
// convert input to ASN.1 hex
let signatureASN1Hex;
switch (inputFormat) {
case "Auto":
throw new OperationError("Signature format could not be detected");
case "ASN.1 HEX":
signatureASN1Hex = input;
break;
case "P1363 HEX":
signatureASN1Hex = r.KJUR.crypto.ECDSA.concatSigToASN1Sig(input);
break;
case "JSON Web Signature":
if (!inputBase64) inputBase64 = fromBase64(input, "A-Za-z0-9-_");
signatureASN1Hex = r.KJUR.crypto.ECDSA.concatSigToASN1Sig(toHexFast(inputBase64));
break;
case "Raw JSON": {
if (!inputJson) inputJson = JSON.parse(input);
if (!inputJson.r) {
throw new OperationError('No "r" value in the signature JSON');
}
if (!inputJson.s) {
throw new OperationError('No "s" value in the signature JSON');
}
signatureASN1Hex = r.KJUR.crypto.ECDSA.hexRSSigToASN1Sig(inputJson.r, inputJson.s);
break;
}
}
// convert ASN.1 hex to output format
let result;
switch (outputFormat) {
case "ASN.1 HEX":
result = signatureASN1Hex;
break;
case "P1363 HEX":
result = r.KJUR.crypto.ECDSA.asn1SigToConcatSig(signatureASN1Hex);
break;
case "JSON Web Signature":
result = r.KJUR.crypto.ECDSA.asn1SigToConcatSig(signatureASN1Hex);
result = toBase64(fromHex(result), "A-Za-z0-9-_"); // base64url
break;
case "Raw JSON": {
const signatureRS = r.KJUR.crypto.ECDSA.parseSigHexInHexRS(signatureASN1Hex);
result = JSON.stringify(signatureRS);
break;
}
}
return result;
}
}
export default ECDSASignatureConversion;
+161
View File
@@ -0,0 +1,161 @@
/**
* @author cplussharp
* @copyright Crown Copyright 2021
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { fromBase64 } from "../lib/Base64.mjs";
import { toHexFast } from "../lib/Hex.mjs";
import r from "jsrsasign";
import Utils from "../Utils.mjs";
/**
* ECDSA Verify operation
*/
class ECDSAVerify extends Operation {
/**
* ECDSAVerify constructor
*/
constructor() {
super();
this.name = "ECDSA Verify";
this.module = "Ciphers";
this.description = "Verify a message against a signature and a public PEM encoded EC key.";
this.infoURL = "https://wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Input Format",
type: "option",
value: [
"Auto",
"ASN.1 HEX",
"P1363 HEX",
"JSON Web Signature",
"Raw JSON"
]
},
{
name: "Message Digest Algorithm",
type: "option",
value: [
"SHA-256",
"SHA-384",
"SHA-512",
"SHA-1",
"MD5"
]
},
{
name: "ECDSA Public Key (PEM)",
type: "text",
value: "-----BEGIN PUBLIC KEY-----"
},
{
name: "Message",
type: "text",
value: ""
},
{
name: "Message format",
type: "option",
value: ["Raw", "Hex", "Base64"]
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
let inputFormat = args[0];
const [, mdAlgo, keyPem, msg, msgFormat] = args;
if (keyPem.replace("-----BEGIN PUBLIC KEY-----", "").length === 0) {
throw new OperationError("Please enter a public key.");
}
// detect input format
let inputJson;
if (inputFormat === "Auto") {
try {
inputJson = JSON.parse(input);
if (typeof(inputJson) === "object") {
inputFormat = "Raw JSON";
}
} catch {}
}
if (inputFormat === "Auto") {
const hexRegex = /^[a-f\d]{2,}$/gi;
if (hexRegex.test(input)) {
if (input.substring(0, 2) === "30" && r.ASN1HEX.isASN1HEX(input)) {
inputFormat = "ASN.1 HEX";
} else {
inputFormat = "P1363 HEX";
}
}
}
let inputBase64;
if (inputFormat === "Auto") {
try {
inputBase64 = fromBase64(input, "A-Za-z0-9-_", false);
inputFormat = "JSON Web Signature";
} catch {}
}
// convert to ASN.1 signature
let signatureASN1Hex;
switch (inputFormat) {
case "Auto":
throw new OperationError("Signature format could not be detected");
case "ASN.1 HEX":
signatureASN1Hex = input;
break;
case "P1363 HEX":
signatureASN1Hex = r.KJUR.crypto.ECDSA.concatSigToASN1Sig(input);
break;
case "JSON Web Signature":
if (!inputBase64) inputBase64 = fromBase64(input, "A-Za-z0-9-_");
signatureASN1Hex = r.KJUR.crypto.ECDSA.concatSigToASN1Sig(toHexFast(inputBase64));
break;
case "Raw JSON": {
if (!inputJson) inputJson = JSON.parse(input);
if (!inputJson.r) {
throw new OperationError('No "r" value in the signature JSON');
}
if (!inputJson.s) {
throw new OperationError('No "s" value in the signature JSON');
}
signatureASN1Hex = r.KJUR.crypto.ECDSA.hexRSSigToASN1Sig(inputJson.r, inputJson.s);
break;
}
}
// verify signature
const internalAlgorithmName = mdAlgo.replace("-", "") + "withECDSA";
const sig = new r.KJUR.crypto.Signature({ alg: internalAlgorithmName });
const key = r.KEYUTIL.getKey(keyPem);
if (key.type !== "EC") {
throw new OperationError("Provided key is not an EC key.");
}
if (!key.isPublic) {
throw new OperationError("Provided key is not a public key.");
}
sig.init(key);
const messageStr = Utils.convertToByteString(msg, msgFormat);
sig.updateString(messageStr);
const result = sig.verify(signatureASN1Hex);
return result ? "Verified OK" : "Verification Failure";
}
}
export default ECDSAVerify;
+8 -3
View File
@@ -5,7 +5,7 @@
*/
import Operation from "../Operation.mjs";
import { search, DOMAIN_REGEX } from "../lib/Extract.mjs";
import { search, DOMAIN_REGEX, DMARC_DOMAIN_REGEX } from "../lib/Extract.mjs";
import { caseInsensitiveSort } from "../lib/Sort.mjs";
/**
@@ -39,6 +39,11 @@ class ExtractDomains extends Operation {
name: "Unique",
type: "boolean",
value: false
},
{
name: "Underscore (DMARC, DKIM, etc)",
type: "boolean",
value: false
}
];
}
@@ -49,11 +54,11 @@ class ExtractDomains extends Operation {
* @returns {string}
*/
run(input, args) {
const [displayTotal, sort, unique] = args;
const [displayTotal, sort, unique, dmarc] = args;
const results = search(
input,
DOMAIN_REGEX,
dmarc ? DMARC_DOMAIN_REGEX : DOMAIN_REGEX,
null,
sort ? caseInsensitiveSort : null,
unique
@@ -51,7 +51,7 @@ class ExtractEmailAddresses extends Operation {
run(input, args) {
const [displayTotal, sort, unique] = args,
// email regex from: https://www.regextester.com/98066
regex = /(?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9])?\.)+[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}\])/ig;
regex = /(?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9])?\.)+[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\])/ig;
const results = search(
input,
+1 -1
View File
@@ -39,7 +39,7 @@ class ExtractFiles extends Operation {
${supportedExts.join("</li><li>")}
</li>
</ul>Minimum File Size can be used to prune small false positives.`;
this.infoURL = "https://forensicswiki.xyz/wiki/index.php?title=File_Carving";
this.infoURL = "https://forensics.wiki/file_carving";
this.inputType = "ArrayBuffer";
this.outputType = "List<File>";
this.presentType = "html";
+84
View File
@@ -0,0 +1,84 @@
/**
* @author mshwed [m@ttshwed.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import { search } from "../lib/Extract.mjs";
/**
* Extract Hash Values operation
*/
class ExtractHashes extends Operation {
/**
* ExtractHashValues constructor
*/
constructor() {
super();
this.name = "Extract hashes";
this.module = "Regex";
this.description = "Extracts potential hashes based on hash character length";
this.infoURL = "https://wikipedia.org/wiki/Comparison_of_cryptographic_hash_functions";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Hash character length",
type: "number",
value: 40
},
{
name: "All hashes",
type: "boolean",
value: false
},
{
name: "Display Total",
type: "boolean",
value: false
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const results = [];
let hashCount = 0;
const [hashLength, searchAllHashes, showDisplayTotal] = args;
// Convert character length to bit length
let hashBitLengths = [(hashLength / 2) * 8];
if (searchAllHashes) hashBitLengths = [4, 8, 16, 32, 64, 128, 160, 192, 224, 256, 320, 384, 512, 1024];
for (const hashBitLength of hashBitLengths) {
// Convert bit length to character length
const hashCharacterLength = (hashBitLength / 8) * 2;
const regex = new RegExp(`(\\b|^)[a-f0-9]{${hashCharacterLength}}(\\b|$)`, "g");
const searchResults = search(input, regex, null, false);
hashCount += searchResults.length;
results.push(...searchResults);
}
let output = "";
if (showDisplayTotal) {
output = `Total Results: ${hashCount}\n\n`;
}
output = output + results.join("\n");
return output;
}
}
export default ExtractHashes;
+17 -3
View File
@@ -21,7 +21,7 @@ class ExtractIPAddresses extends Operation {
this.name = "Extract IP addresses";
this.module = "Regex";
this.description = "Extracts all IPv4 and IPv6 addresses.<br><br>Warning: Given a string <code>710.65.0.456</code>, this will match <code>10.65.0.45</code> so always check the original input!";
this.description = "Extracts all IPv4 and IPv6 addresses.<br><br>Warning: Given a string <code>1.2.3.4.5.6.7.8</code>, this will match <code>1.2.3.4 and 5.6.7.8</code> so always check the original input!";
this.inputType = "string";
this.outputType = "string";
this.args = [
@@ -65,8 +65,22 @@ class ExtractIPAddresses extends Operation {
*/
run(input, args) {
const [includeIpv4, includeIpv6, removeLocal, displayTotal, sort, unique] = args,
ipv4 = "(?:(?:\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d|\\d)(?:\\/\\d{1,2})?",
ipv6 = "((?=.*::)(?!.*::.+::)(::)?([\\dA-F]{1,4}:(:|\\b)|){5}|([\\dA-F]{1,4}:){6})((([\\dA-F]{1,4}((?!\\3)::|:\\b|(?![\\dA-F])))|(?!\\2\\3)){2}|(((2[0-4]|1\\d|[1-9])?\\d|25[0-5])\\.?\\b){4})";
// IPv4 decimal groups can have values 0 to 255. To construct a regex the following sub-regex is reused:
ipv4DecimalByte = "(?:25[0-5]|2[0-4]\\d|1?[0-9]\\d|\\d)",
ipv4OctalByte = "(?:0[1-3]?[0-7]{1,2})",
// Look behind and ahead will be used to exclude matches with additional decimal digits left and right of IP address
lookBehind = "(?<!\\d)",
lookAhead = "(?!\\d)",
// Each variant requires exactly 4 groups with literal . between.
ipv4Decimal = "(?:" + lookBehind + ipv4DecimalByte + "\\.){3}" + "(?:" + ipv4DecimalByte + lookAhead + ")",
ipv4Octal = "(?:" + lookBehind + ipv4OctalByte + "\\.){3}" + "(?:" + ipv4OctalByte + lookAhead + ")",
// Then we allow IPv4 addresses to be expressed either entirely in decimal or entirely in Octal
ipv4 = "(?:" + ipv4Decimal + "|" + ipv4Octal + ")",
ipv6 = "((?=.*::)(?!.*::.+::)(::)?([\\dA-F]{1,4}:(:|\\b)|){5}|([\\dA-F]{1,4}:){6})(([\\dA-F]{1,4}((?!\\3)::|:\\b|(?![\\dA-F])))|(?!\\2\\3)){2}";
let ips = "";
if (includeIpv4 && includeIpv6) {
+2 -2
View File
@@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import { fromBinary } from "../lib/Binary.mjs";
import { isImage } from "../lib/FileType.mjs";
import jimp from "jimp";
import Jimp from "jimp/es/index.js";
/**
* Extract LSB operation
@@ -73,7 +73,7 @@ class ExtractLSB extends Operation {
const bit = 7 - args.pop(),
pixelOrder = args.pop(),
colours = args.filter(option => option !== "").map(option => COLOUR_OPTIONS.indexOf(option)),
parsedImage = await jimp.read(input),
parsedImage = await Jimp.read(input),
width = parsedImage.bitmap.width,
height = parsedImage.bitmap.height,
rgba = parsedImage.bitmap.data;
+2 -2
View File
@@ -7,7 +7,7 @@
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { isImage } from "../lib/FileType.mjs";
import jimp from "jimp";
import Jimp from "jimp/es/index.js";
import {RGBA_DELIM_OPTIONS} from "../lib/Delim.mjs";
@@ -52,7 +52,7 @@ class ExtractRGBA extends Operation {
const delimiter = args[0],
includeAlpha = args[1],
parsedImage = await jimp.read(input);
parsedImage = await Jimp.read(input);
let bitmap = parsedImage.bitmap.data;
bitmap = includeAlpha ? bitmap : bitmap.filter((val, idx) => idx % 4 !== 3);
+78
View File
@@ -0,0 +1,78 @@
/**
* @author arnydo [github@arnydo.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
/**
* FangURL operation
*/
class FangURL extends Operation {
/**
* FangURL constructor
*/
constructor() {
super();
this.name = "Fang URL";
this.module = "Default";
this.description = "Takes a 'Defanged' Universal Resource Locator (URL) and 'Fangs' it. Meaning, it removes the alterations (defanged) that render it useless so that it can be used again.";
this.infoURL = "https://isc.sans.edu/forums/diary/Defang+all+the+things/22744/";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Restore [.]",
type: "boolean",
value: true
},
{
name: "Restore hxxp",
type: "boolean",
value: true
},
{
name: "Restore ://",
type: "boolean",
value: true
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const [dots, http, slashes] = args;
input = fangURL(input, dots, http, slashes);
return input;
}
}
/**
* Defangs a given URL
*
* @param {string} url
* @param {boolean} dots
* @param {boolean} http
* @param {boolean} slashes
* @returns {string}
*/
function fangURL(url, dots, http, slashes) {
if (dots) url = url.replace(/\[\.\]/g, ".");
if (http) url = url.replace(/hxxp/g, "http");
if (slashes) url = url.replace(/\[:\/\/\]/g, "://");
return url;
}
export default FangURL;
+63
View File
@@ -0,0 +1,63 @@
/**
* @author Karsten Silkenbäumer [github.com/kassi]
* @copyright Karsten Silkenbäumer 2019
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import fernet from "fernet";
/**
* FernetDecrypt operation
*/
class FernetDecrypt extends Operation {
/**
* FernetDecrypt constructor
*/
constructor() {
super();
this.name = "Fernet Decrypt";
this.module = "Default";
this.description = "Fernet is a symmetric encryption method which makes sure that the message encrypted cannot be manipulated/read without the key. It uses URL safe encoding for the keys. Fernet uses 128-bit AES in CBC mode and PKCS7 padding, with HMAC using SHA256 for authentication. The IV is created from os.random().<br><br><b>Key:</b> The key must be 32 bytes (256 bits) encoded with Base64.";
this.infoURL = "https://asecuritysite.com/encryption/fer";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
"name": "Key",
"type": "string",
"value": ""
},
];
this.patterns = [
{
match: "^[A-Z\\d\\-_=]{20,}$",
flags: "i",
args: []
},
];
}
/**
* @param {String} input
* @param {Object[]} args
* @returns {String}
*/
run(input, args) {
const [secretInput] = args;
try {
const secret = new fernet.Secret(secretInput);
const token = new fernet.Token({
secret: secret,
token: input,
ttl: 0
});
return token.decode();
} catch (err) {
throw new OperationError(err);
}
}
}
export default FernetDecrypt;
+54
View File
@@ -0,0 +1,54 @@
/**
* @author Karsten Silkenbäumer [github.com/kassi]
* @copyright Karsten Silkenbäumer 2019
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import fernet from "fernet";
/**
* FernetEncrypt operation
*/
class FernetEncrypt extends Operation {
/**
* FernetEncrypt constructor
*/
constructor() {
super();
this.name = "Fernet Encrypt";
this.module = "Default";
this.description = "Fernet is a symmetric encryption method which makes sure that the message encrypted cannot be manipulated/read without the key. It uses URL safe encoding for the keys. Fernet uses 128-bit AES in CBC mode and PKCS7 padding, with HMAC using SHA256 for authentication. The IV is created from os.random().<br><br><b>Key:</b> The key must be 32 bytes (256 bits) encoded with Base64.";
this.infoURL = "https://asecuritysite.com/encryption/fer";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
"name": "Key",
"type": "string",
"value": ""
},
];
}
/**
* @param {String} input
* @param {Object[]} args
* @returns {String}
*/
run(input, args) {
const [secretInput] = args;
try {
const secret = new fernet.Secret(secretInput);
const token = new fernet.Token({
secret: secret,
});
return token.encode(input);
} catch (err) {
throw new OperationError(err);
}
}
}
export default FernetEncrypt;
+94
View File
@@ -0,0 +1,94 @@
/**
* @author sw5678
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs";
/**
* Unique operation
*/
class FileTree extends Operation {
/**
* Unique constructor
*/
constructor() {
super();
this.name = "File Tree";
this.module = "Default";
this.description = "Creates a file tree from a list of file paths (similar to the tree command in Linux)";
this.infoURL = "https://wikipedia.org/wiki/Tree_(command)";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "File Path Delimiter",
type: "binaryString",
value: "/"
},
{
name: "Delimiter",
type: "option",
value: INPUT_DELIM_OPTIONS
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
// Set up arrow and pipe for nice output display
const ARROW = "|---";
const PIPE = "| ";
// Get args from input
const fileDelim = args[0];
const entryDelim = Utils.charRep(args[1]);
// Store path to print
const completedList = [];
const printList = [];
// Loop through all entries
const filePaths = input.split(entryDelim).unique().sort();
for (let i = 0; i < filePaths.length; i++) {
// Split by file delimiter
let path = filePaths[i].split(fileDelim);
if (path[0] === "") {
path = path.slice(1, path.length);
}
for (let j = 0; j < path.length; j++) {
let printLine;
let key;
if (j === 0) {
printLine = path[j];
key = path[j];
} else {
printLine = PIPE.repeat(j-1) + ARROW + path[j];
key = path.slice(0, j+1).join("/");
}
// Check to see we have already added that path
if (!completedList.includes(key)) {
completedList.push(key);
printList.push(printLine);
}
}
}
return printList.join("\n");
}
}
export default FileTree;
+4 -4
View File
@@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs";
import { isImage } from "../lib/FileType.mjs";
import { toBase64 } from "../lib/Base64.mjs";
import { isWorkerEnvironment } from "../Utils.mjs";
import jimp from "jimp";
import Jimp from "jimp/es/index.js";
/**
* Flip Image operation
@@ -51,7 +51,7 @@ class FlipImage extends Operation {
let image;
try {
image = await jimp.read(input);
image = await Jimp.read(input);
} catch (err) {
throw new OperationError(`Error loading image. (${err})`);
}
@@ -69,9 +69,9 @@ class FlipImage extends Operation {
let imageBuffer;
if (image.getMIME() === "image/gif") {
imageBuffer = await image.getBufferAsync(jimp.MIME_PNG);
imageBuffer = await image.getBufferAsync(Jimp.MIME_PNG);
} else {
imageBuffer = await image.getBufferAsync(jimp.AUTO);
imageBuffer = await image.getBufferAsync(Jimp.AUTO);
}
return imageBuffer.buffer;
} catch (err) {
+10 -2
View File
@@ -6,6 +6,8 @@
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import {ALPHABET_OPTIONS} from "../lib/Base32.mjs";
/**
* From Base32 operation
@@ -27,8 +29,8 @@ class FromBase32 extends Operation {
this.args = [
{
name: "Alphabet",
type: "binaryString",
value: "A-Z2-7="
type: "editableOption",
value: ALPHABET_OPTIONS
},
{
name: "Remove non-alphabet chars",
@@ -41,6 +43,11 @@ class FromBase32 extends Operation {
pattern: "^(?:[A-Z2-7]{8})+(?:[A-Z2-7]{2}={6}|[A-Z2-7]{4}={4}|[A-Z2-7]{5}={3}|[A-Z2-7]{7}={1})?$",
flags: "",
args: ["A-Z2-7=", false]
},
{
pattern: "^(?:[0-9A-V]{8})+(?:[0-9A-V]{2}={6}|[0-9A-V]{4}={4}|[0-9A-V]{5}={3}|[0-9A-V]{7}={1})?$",
flags: "",
args: ["0-9A-V=", false]
}
];
}
@@ -96,3 +103,4 @@ class FromBase32 extends Operation {
}
export default FromBase32;
+3 -5
View File
@@ -60,7 +60,7 @@ class FromBase58 extends Operation {
run(input, args) {
let alphabet = args[0] || ALPHABET_OPTIONS[0].value;
const removeNonAlphaChars = args[1] === undefined ? true : args[1],
result = [0];
result = [];
alphabet = Utils.expandAlphRange(alphabet).join("");
@@ -87,11 +87,9 @@ class FromBase58 extends Operation {
}
}
let carry = result[0] * 58 + index;
result[0] = carry & 0xFF;
carry = carry >> 8;
let carry = index;
for (let i = 1; i < result.length; i++) {
for (let i = 0; i < result.length; i++) {
carry += result[i] * 58;
result[i] = carry & 0xFF;
carry = carry >> 8;
+55
View File
@@ -0,0 +1,55 @@
/**
* @author sg5506844 [sg5506844@gmail.com]
* @copyright Crown Copyright 2021
* @license Apache-2.0
*/
import { base92Ord } from "../lib/Base92.mjs";
import Operation from "../Operation.mjs";
/**
* From Base92 operation
*/
class FromBase92 extends Operation {
/**
* FromBase92 constructor
*/
constructor() {
super();
this.name = "From Base92";
this.module = "Default";
this.description = "Base92 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.";
this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems";
this.inputType = "string";
this.outputType = "byteArray";
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {byteArray}
*/
run(input, args) {
const res = [];
let bitString = "";
for (let i = 0; i < input.length; i += 2) {
if (i + 1 !== input.length) {
const x = base92Ord(input[i]) * 91 + base92Ord(input[i + 1]);
bitString += x.toString(2).padStart(13, "0");
} else {
const x = base92Ord(input[i]);
bitString += x.toString(2).padStart(6, "0");
}
while (bitString.length >= 8) {
res.push(parseInt(bitString.slice(0, 8), 2));
bitString = bitString.slice(8);
}
}
return res;
}
}
export default FromBase92;
+78
View File
@@ -0,0 +1,78 @@
/**
* @author tcode2k16 [tcode2k16@gmail.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import ieee754 from "ieee754";
import {DELIM_OPTIONS} from "../lib/Delim.mjs";
/**
* From Float operation
*/
class FromFloat extends Operation {
/**
* FromFloat constructor
*/
constructor() {
super();
this.name = "From Float";
this.module = "Default";
this.description = "Convert from IEEE754 Floating Point Numbers";
this.infoURL = "https://wikipedia.org/wiki/IEEE_754";
this.inputType = "string";
this.outputType = "byteArray";
this.args = [
{
"name": "Endianness",
"type": "option",
"value": [
"Big Endian",
"Little Endian"
]
},
{
"name": "Size",
"type": "option",
"value": [
"Float (4 bytes)",
"Double (8 bytes)"
]
},
{
"name": "Delimiter",
"type": "option",
"value": DELIM_OPTIONS
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {byteArray}
*/
run(input, args) {
if (input.length === 0) return [];
const [endianness, size, delimiterName] = args;
const delim = Utils.charRep(delimiterName || "Space");
const byteSize = size === "Double (8 bytes)" ? 8 : 4;
const isLE = endianness === "Little Endian";
const mLen = byteSize === 4 ? 23 : 52;
const floats = input.split(delim);
const output = new Array(floats.length*byteSize);
for (let i = 0; i < floats.length; i++) {
ieee754.write(output, parseFloat(floats[i]), i*byteSize, isLE, mLen, byteSize);
}
return output;
}
}
export default FromFloat;
+84
View File
@@ -0,0 +1,84 @@
/**
* @author linuxgemini [ilteris@asenkron.com.tr]
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import { FROM_MODHEX_DELIM_OPTIONS, fromModhex } from "../lib/Modhex.mjs";
/**
* From Modhex operation
*/
class FromModhex extends Operation {
/**
* FromModhex constructor
*/
constructor() {
super();
this.name = "From Modhex";
this.module = "Default";
this.description = "Converts a modhex byte string back into its raw value.";
this.infoURL = "https://en.wikipedia.org/wiki/YubiKey#ModHex";
this.inputType = "string";
this.outputType = "byteArray";
this.args = [
{
name: "Delimiter",
type: "option",
value: FROM_MODHEX_DELIM_OPTIONS
}
];
this.checks = [
{
pattern: "^(?:[cbdefghijklnrtuv]{2})+$",
flags: "i",
args: ["None"]
},
{
pattern: "^[cbdefghijklnrtuv]{2}(?: [cbdefghijklnrtuv]{2})*$",
flags: "i",
args: ["Space"]
},
{
pattern: "^[cbdefghijklnrtuv]{2}(?:,[cbdefghijklnrtuv]{2})*$",
flags: "i",
args: ["Comma"]
},
{
pattern: "^[cbdefghijklnrtuv]{2}(?:;[cbdefghijklnrtuv]{2})*$",
flags: "i",
args: ["Semi-colon"]
},
{
pattern: "^[cbdefghijklnrtuv]{2}(?::[cbdefghijklnrtuv]{2})*$",
flags: "i",
args: ["Colon"]
},
{
pattern: "^[cbdefghijklnrtuv]{2}(?:\\n[cbdefghijklnrtuv]{2})*$",
flags: "i",
args: ["Line feed"]
},
{
pattern: "^[cbdefghijklnrtuv]{2}(?:\\r\\n[cbdefghijklnrtuv]{2})*$",
flags: "i",
args: ["CRLF"]
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {byteArray}
*/
run(input, args) {
const delim = args[0] || "Auto";
return fromModhex(input, delim, 2);
}
}
export default FromModhex;
+151
View File
@@ -0,0 +1,151 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import { toHexFast, fromHex } from "../lib/Hex.mjs";
import { CryptoGost, GostEngine } from "@wavesenterprise/crypto-gost-js/index.js";
/**
* GOST Decrypt operation
*/
class GOSTDecrypt extends Operation {
/**
* GOSTDecrypt constructor
*/
constructor() {
super();
this.name = "GOST Decrypt";
this.module = "Ciphers";
this.description = "The GOST block cipher (Magma), defined in the standard GOST 28147-89 (RFC 5830), is a Soviet and Russian government standard symmetric key block cipher with a block size of 64 bits. The original standard, published in 1989, did not give the cipher any name, but the most recent revision of the standard, GOST R 34.12-2015 (RFC 7801, RFC 8891), specifies that it may be referred to as Magma. The GOST hash function is based on this cipher. The new standard also specifies a new 128-bit block cipher called Kuznyechik.<br><br>Developed in the 1970s, the standard had been marked 'Top Secret' and then downgraded to 'Secret' in 1990. Shortly after the dissolution of the USSR, it was declassified and it was released to the public in 1994. GOST 28147 was a Soviet alternative to the United States standard algorithm, DES. Thus, the two are very similar in structure.";
this.infoURL = "https://wikipedia.org/wiki/GOST_(block_cipher)";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Key",
type: "toggleString",
value: "",
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"]
},
{
name: "IV",
type: "toggleString",
value: "",
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"]
},
{
name: "Input type",
type: "option",
value: ["Hex", "Raw"]
},
{
name: "Output type",
type: "option",
value: ["Raw", "Hex"]
},
{
name: "Algorithm",
type: "argSelector",
value: [
{
name: "GOST 28147 (1989)",
on: [5]
},
{
name: "GOST R 34.12 (Magma, 2015)",
off: [5]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
off: [5]
}
]
},
{
name: "sBox",
type: "option",
value: ["E-TEST", "E-A", "E-B", "E-C", "E-D", "E-SC", "E-Z", "D-TEST", "D-A", "D-SC"]
},
{
name: "Block mode",
type: "option",
value: ["ECB", "CFB", "OFB", "CTR", "CBC"]
},
{
name: "Key meshing mode",
type: "option",
value: ["NO", "CP"]
},
{
name: "Padding",
type: "option",
value: ["NO", "PKCS5", "ZERO", "RANDOM", "BIT"]
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
async run(input, args) {
const [keyObj, ivObj, inputType, outputType, version, sBox, blockMode, keyMeshing, padding] = args;
const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option));
const iv = toHexFast(Utils.convertToByteArray(ivObj.string, ivObj.option));
input = inputType === "Hex" ? input : toHexFast(Utils.strToArrayBuffer(input));
let blockLength, versionNum;
switch (version) {
case "GOST 28147 (1989)":
versionNum = 1989;
blockLength = 64;
break;
case "GOST R 34.12 (Magma, 2015)":
versionNum = 2015;
blockLength = 64;
break;
case "GOST R 34.12 (Kuznyechik, 2015)":
versionNum = 2015;
blockLength = 128;
break;
default:
throw new OperationError(`Unknown algorithm version: ${version}`);
}
const sBoxVal = versionNum === 1989 ? sBox : null;
const algorithm = {
version: versionNum,
length: blockLength,
mode: "ES",
sBox: sBoxVal,
block: blockMode,
keyMeshing: keyMeshing,
padding: padding
};
try {
const Hex = CryptoGost.coding.Hex;
if (iv) algorithm.iv = Hex.decode(iv);
const cipher = GostEngine.getGostCipher(algorithm);
const out = Hex.encode(cipher.decrypt(Hex.decode(key), Hex.decode(input)));
return outputType === "Hex" ? out : Utils.byteArrayToChars(fromHex(out));
} catch (err) {
throw new OperationError(err);
}
}
}
export default GOSTDecrypt;
+151
View File
@@ -0,0 +1,151 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import { toHexFast, fromHex } from "../lib/Hex.mjs";
import { CryptoGost, GostEngine } from "@wavesenterprise/crypto-gost-js/index.js";
/**
* GOST Encrypt operation
*/
class GOSTEncrypt extends Operation {
/**
* GOSTEncrypt constructor
*/
constructor() {
super();
this.name = "GOST Encrypt";
this.module = "Ciphers";
this.description = "The GOST block cipher (Magma), defined in the standard GOST 28147-89 (RFC 5830), is a Soviet and Russian government standard symmetric key block cipher with a block size of 64 bits. The original standard, published in 1989, did not give the cipher any name, but the most recent revision of the standard, GOST R 34.12-2015 (RFC 7801, RFC 8891), specifies that it may be referred to as Magma. The GOST hash function is based on this cipher. The new standard also specifies a new 128-bit block cipher called Kuznyechik.<br><br>Developed in the 1970s, the standard had been marked 'Top Secret' and then downgraded to 'Secret' in 1990. Shortly after the dissolution of the USSR, it was declassified and it was released to the public in 1994. GOST 28147 was a Soviet alternative to the United States standard algorithm, DES. Thus, the two are very similar in structure.";
this.infoURL = "https://wikipedia.org/wiki/GOST_(block_cipher)";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Key",
type: "toggleString",
value: "",
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"]
},
{
name: "IV",
type: "toggleString",
value: "",
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"]
},
{
name: "Input type",
type: "option",
value: ["Raw", "Hex"]
},
{
name: "Output type",
type: "option",
value: ["Hex", "Raw"]
},
{
name: "Algorithm",
type: "argSelector",
value: [
{
name: "GOST 28147 (1989)",
on: [5]
},
{
name: "GOST R 34.12 (Magma, 2015)",
off: [5]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
off: [5]
}
]
},
{
name: "sBox",
type: "option",
value: ["E-TEST", "E-A", "E-B", "E-C", "E-D", "E-SC", "E-Z", "D-TEST", "D-A", "D-SC"]
},
{
name: "Block mode",
type: "option",
value: ["ECB", "CFB", "OFB", "CTR", "CBC"]
},
{
name: "Key meshing mode",
type: "option",
value: ["NO", "CP"]
},
{
name: "Padding",
type: "option",
value: ["NO", "PKCS5", "ZERO", "RANDOM", "BIT"]
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
async run(input, args) {
const [keyObj, ivObj, inputType, outputType, version, sBox, blockMode, keyMeshing, padding] = args;
const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option));
const iv = toHexFast(Utils.convertToByteArray(ivObj.string, ivObj.option));
input = inputType === "Hex" ? input : toHexFast(Utils.strToArrayBuffer(input));
let blockLength, versionNum;
switch (version) {
case "GOST 28147 (1989)":
versionNum = 1989;
blockLength = 64;
break;
case "GOST R 34.12 (Magma, 2015)":
versionNum = 2015;
blockLength = 64;
break;
case "GOST R 34.12 (Kuznyechik, 2015)":
versionNum = 2015;
blockLength = 128;
break;
default:
throw new OperationError(`Unknown algorithm version: ${version}`);
}
const sBoxVal = versionNum === 1989 ? sBox : null;
const algorithm = {
version: versionNum,
length: blockLength,
mode: "ES",
sBox: sBoxVal,
block: blockMode,
keyMeshing: keyMeshing,
padding: padding
};
try {
const Hex = CryptoGost.coding.Hex;
if (iv) algorithm.iv = Hex.decode(iv);
const cipher = GostEngine.getGostCipher(algorithm);
const out = Hex.encode(cipher.encrypt(Hex.decode(key), Hex.decode(input)));
return outputType === "Hex" ? out : Utils.byteArrayToChars(fromHex(out));
} catch (err) {
throw new OperationError(err);
}
}
}
export default GOSTEncrypt;
+41 -21
View File
@@ -7,7 +7,7 @@
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import GostDigest from "../vendor/gost/gostDigest.mjs";
import {toHexFast} from "../lib/Hex.mjs";
import { toHexFast } from "../lib/Hex.mjs";
/**
* GOST hash operation
@@ -20,7 +20,7 @@ class GOSTHash extends Operation {
constructor() {
super();
this.name = "GOST hash";
this.name = "GOST Hash";
this.module = "Hashing";
this.description = "The GOST hash function, defined in the standards GOST R 34.11-94 and GOST 34.311-95 is a 256-bit cryptographic hash function. It was initially defined in the Russian national standard GOST R 34.11-94 <i>Information Technology – Cryptographic Information Security – Hash Function</i>. The equivalent standard used by other member-states of the CIS is GOST 34.311-95.<br><br>This function must not be confused with a different Streebog hash function, which is defined in the new revision of the standard GOST R 34.11-2012.<br><br>The GOST hash function is based on the GOST block cipher.";
this.infoURL = "https://wikipedia.org/wiki/GOST_(hash_function)";
@@ -28,20 +28,30 @@ class GOSTHash extends Operation {
this.outputType = "string";
this.args = [
{
"name": "S-Box",
"type": "option",
"value": [
"D-A",
"D-SC",
"E-TEST",
"E-A",
"E-B",
"E-C",
"E-D",
"E-SC",
"E-Z",
"D-TEST"
name: "Algorithm",
type: "argSelector",
value: [
{
name: "GOST 28147 (1994)",
off: [1],
on: [2]
},
{
name: "GOST R 34.11 (Streebog, 2012)",
on: [1],
off: [2]
}
]
},
{
name: "Digest length",
type: "option",
value: ["256", "512"]
},
{
name: "sBox",
type: "option",
value: ["E-TEST", "E-A", "E-B", "E-C", "E-D", "E-SC", "E-Z", "D-TEST", "D-A", "D-SC"]
}
];
}
@@ -52,13 +62,23 @@ class GOSTHash extends Operation {
* @returns {string}
*/
run(input, args) {
const [version, length, sBox] = args;
const versionNum = version === "GOST 28147 (1994)" ? 1994 : 2012;
const algorithm = {
name: versionNum === 1994 ? "GOST 28147" : "GOST R 34.10",
version: versionNum,
mode: "HASH"
};
if (versionNum === 1994) {
algorithm.sBox = sBox;
} else {
algorithm.length = parseInt(length, 10);
}
try {
const sBox = args[1];
const gostDigest = new GostDigest({
name: "GOST R 34.11",
version: 1994,
sBox: sBox
});
const gostDigest = new GostDigest(algorithm);
return toHexFast(gostDigest.digest(input));
} catch (err) {
+142
View File
@@ -0,0 +1,142 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import { toHexFast, fromHex } from "../lib/Hex.mjs";
import { CryptoGost, GostEngine } from "@wavesenterprise/crypto-gost-js/index.js";
/**
* GOST Key Unwrap operation
*/
class GOSTKeyUnwrap extends Operation {
/**
* GOSTKeyUnwrap constructor
*/
constructor() {
super();
this.name = "GOST Key Unwrap";
this.module = "Ciphers";
this.description = "A decryptor for keys wrapped using one of the GOST block ciphers.";
this.infoURL = "https://wikipedia.org/wiki/GOST_(block_cipher)";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Key",
type: "toggleString",
value: "",
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"]
},
{
name: "User Key Material",
type: "toggleString",
value: "",
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"]
},
{
name: "Input type",
type: "option",
value: ["Hex", "Raw"]
},
{
name: "Output type",
type: "option",
value: ["Raw", "Hex"]
},
{
name: "Algorithm",
type: "argSelector",
value: [
{
name: "GOST 28147 (1989)",
on: [5]
},
{
name: "GOST R 34.12 (Magma, 2015)",
off: [5]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
off: [5]
}
]
},
{
name: "sBox",
type: "option",
value: ["E-TEST", "E-A", "E-B", "E-C", "E-D", "E-SC", "E-Z", "D-TEST", "D-A", "D-SC"]
},
{
name: "Key wrapping",
type: "option",
value: ["NO", "CP", "SC"]
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
async run(input, args) {
const [keyObj, ukmObj, inputType, outputType, version, sBox, keyWrapping] = args;
const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option));
const ukm = toHexFast(Utils.convertToByteArray(ukmObj.string, ukmObj.option));
input = inputType === "Hex" ? input : toHexFast(Utils.strToArrayBuffer(input));
let blockLength, versionNum;
switch (version) {
case "GOST 28147 (1989)":
versionNum = 1989;
blockLength = 64;
break;
case "GOST R 34.12 (Magma, 2015)":
versionNum = 2015;
blockLength = 64;
break;
case "GOST R 34.12 (Kuznyechik, 2015)":
versionNum = 2015;
blockLength = 128;
break;
default:
throw new OperationError(`Unknown algorithm version: ${version}`);
}
const sBoxVal = versionNum === 1989 ? sBox : null;
const algorithm = {
version: versionNum,
length: blockLength,
mode: "KW",
sBox: sBoxVal,
keyWrapping: keyWrapping
};
try {
const Hex = CryptoGost.coding.Hex;
algorithm.ukm = Hex.decode(ukm);
const cipher = GostEngine.getGostCipher(algorithm);
const out = Hex.encode(cipher.unwrapKey(Hex.decode(key), Hex.decode(input)));
return outputType === "Hex" ? out : Utils.byteArrayToChars(fromHex(out));
} catch (err) {
if (err.toString().includes("Invalid typed array length")) {
throw new OperationError("Incorrect input length. Must be a multiple of the block size.");
}
throw new OperationError(err);
}
}
}
export default GOSTKeyUnwrap;
+142
View File
@@ -0,0 +1,142 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import { toHexFast, fromHex } from "../lib/Hex.mjs";
import { CryptoGost, GostEngine } from "@wavesenterprise/crypto-gost-js/index.js";
/**
* GOST Key Wrap operation
*/
class GOSTKeyWrap extends Operation {
/**
* GOSTKeyWrap constructor
*/
constructor() {
super();
this.name = "GOST Key Wrap";
this.module = "Ciphers";
this.description = "A key wrapping algorithm for protecting keys in untrusted storage using one of the GOST block cipers.";
this.infoURL = "https://wikipedia.org/wiki/GOST_(block_cipher)";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Key",
type: "toggleString",
value: "",
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"]
},
{
name: "User Key Material",
type: "toggleString",
value: "",
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"]
},
{
name: "Input type",
type: "option",
value: ["Raw", "Hex"]
},
{
name: "Output type",
type: "option",
value: ["Hex", "Raw"]
},
{
name: "Algorithm",
type: "argSelector",
value: [
{
name: "GOST 28147 (1989)",
on: [5]
},
{
name: "GOST R 34.12 (Magma, 2015)",
off: [5]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
off: [5]
}
]
},
{
name: "sBox",
type: "option",
value: ["E-TEST", "E-A", "E-B", "E-C", "E-D", "E-SC", "E-Z", "D-TEST", "D-A", "D-SC"]
},
{
name: "Key wrapping",
type: "option",
value: ["NO", "CP", "SC"]
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
async run(input, args) {
const [keyObj, ukmObj, inputType, outputType, version, sBox, keyWrapping] = args;
const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option));
const ukm = toHexFast(Utils.convertToByteArray(ukmObj.string, ukmObj.option));
input = inputType === "Hex" ? input : toHexFast(Utils.strToArrayBuffer(input));
let blockLength, versionNum;
switch (version) {
case "GOST 28147 (1989)":
versionNum = 1989;
blockLength = 64;
break;
case "GOST R 34.12 (Magma, 2015)":
versionNum = 2015;
blockLength = 64;
break;
case "GOST R 34.12 (Kuznyechik, 2015)":
versionNum = 2015;
blockLength = 128;
break;
default:
throw new OperationError(`Unknown algorithm version: ${version}`);
}
const sBoxVal = versionNum === 1989 ? sBox : null;
const algorithm = {
version: versionNum,
length: blockLength,
mode: "KW",
sBox: sBoxVal,
keyWrapping: keyWrapping
};
try {
const Hex = CryptoGost.coding.Hex;
algorithm.ukm = Hex.decode(ukm);
const cipher = GostEngine.getGostCipher(algorithm);
const out = Hex.encode(cipher.wrapKey(Hex.decode(key), Hex.decode(input)));
return outputType === "Hex" ? out : Utils.byteArrayToChars(fromHex(out));
} catch (err) {
if (err.toString().includes("Invalid typed array length")) {
throw new OperationError("Incorrect input length. Must be a multiple of the block size.");
}
throw new OperationError(err);
}
}
}
export default GOSTKeyWrap;
+142
View File
@@ -0,0 +1,142 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import { toHexFast, fromHex } from "../lib/Hex.mjs";
import { CryptoGost, GostEngine } from "@wavesenterprise/crypto-gost-js/index.js";
/**
* GOST Sign operation
*/
class GOSTSign extends Operation {
/**
* GOSTSign constructor
*/
constructor() {
super();
this.name = "GOST Sign";
this.module = "Ciphers";
this.description = "Sign a plaintext message using one of the GOST block ciphers.";
this.infoURL = "https://wikipedia.org/wiki/GOST_(block_cipher)";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Key",
type: "toggleString",
value: "",
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"]
},
{
name: "IV",
type: "toggleString",
value: "",
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"]
},
{
name: "Input type",
type: "option",
value: ["Raw", "Hex"]
},
{
name: "Output type",
type: "option",
value: ["Hex", "Raw"]
},
{
name: "Algorithm",
type: "argSelector",
value: [
{
name: "GOST 28147 (1989)",
on: [5]
},
{
name: "GOST R 34.12 (Magma, 2015)",
off: [5]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
off: [5]
}
]
},
{
name: "sBox",
type: "option",
value: ["E-TEST", "E-A", "E-B", "E-C", "E-D", "E-SC", "E-Z", "D-TEST", "D-A", "D-SC"]
},
{
name: "MAC length",
type: "number",
value: 32,
min: 8,
max: 64,
step: 8
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
async run(input, args) {
const [keyObj, ivObj, inputType, outputType, version, sBox, macLength] = args;
const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option));
const iv = toHexFast(Utils.convertToByteArray(ivObj.string, ivObj.option));
input = inputType === "Hex" ? input : toHexFast(Utils.strToArrayBuffer(input));
let blockLength, versionNum;
switch (version) {
case "GOST 28147 (1989)":
versionNum = 1989;
blockLength = 64;
break;
case "GOST R 34.12 (Magma, 2015)":
versionNum = 2015;
blockLength = 64;
break;
case "GOST R 34.12 (Kuznyechik, 2015)":
versionNum = 2015;
blockLength = 128;
break;
default:
throw new OperationError(`Unknown algorithm version: ${version}`);
}
const sBoxVal = versionNum === 1989 ? sBox : null;
const algorithm = {
version: versionNum,
length: blockLength,
mode: "MAC",
sBox: sBoxVal,
macLength: macLength
};
try {
const Hex = CryptoGost.coding.Hex;
if (iv) algorithm.iv = Hex.decode(iv);
const cipher = GostEngine.getGostCipher(algorithm);
const out = Hex.encode(cipher.sign(Hex.decode(key), Hex.decode(input)));
return outputType === "Hex" ? out : Utils.byteArrayToChars(fromHex(out));
} catch (err) {
throw new OperationError(err);
}
}
}
export default GOSTSign;
+136
View File
@@ -0,0 +1,136 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import { toHexFast } from "../lib/Hex.mjs";
import { CryptoGost, GostEngine } from "@wavesenterprise/crypto-gost-js/index.js";
/**
* GOST Verify operation
*/
class GOSTVerify extends Operation {
/**
* GOSTVerify constructor
*/
constructor() {
super();
this.name = "GOST Verify";
this.module = "Ciphers";
this.description = "Verify the signature of a plaintext message using one of the GOST block ciphers. Enter the signature in the MAC field.";
this.infoURL = "https://wikipedia.org/wiki/GOST_(block_cipher)";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Key",
type: "toggleString",
value: "",
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"]
},
{
name: "IV",
type: "toggleString",
value: "",
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"]
},
{
name: "MAC",
type: "toggleString",
value: "",
toggleValues: ["Hex", "UTF8", "Latin1", "Base64"]
},
{
name: "Input type",
type: "option",
value: ["Raw", "Hex"]
},
{
name: "Algorithm",
type: "argSelector",
value: [
{
name: "GOST 28147 (1989)",
on: [5]
},
{
name: "GOST R 34.12 (Magma, 2015)",
off: [5]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
off: [5]
}
]
},
{
name: "sBox",
type: "option",
value: ["E-TEST", "E-A", "E-B", "E-C", "E-D", "E-SC", "E-Z", "D-TEST", "D-A", "D-SC"]
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
async run(input, args) {
const [keyObj, ivObj, macObj, inputType, version, sBox] = args;
const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option));
const iv = toHexFast(Utils.convertToByteArray(ivObj.string, ivObj.option));
const mac = toHexFast(Utils.convertToByteArray(macObj.string, macObj.option));
input = inputType === "Hex" ? input : toHexFast(Utils.strToArrayBuffer(input));
let blockLength, versionNum;
switch (version) {
case "GOST 28147 (1989)":
versionNum = 1989;
blockLength = 64;
break;
case "GOST R 34.12 (Magma, 2015)":
versionNum = 2015;
blockLength = 64;
break;
case "GOST R 34.12 (Kuznyechik, 2015)":
versionNum = 2015;
blockLength = 128;
break;
default:
throw new OperationError(`Unknown algorithm version: ${version}`);
}
const sBoxVal = versionNum === 1989 ? sBox : null;
const algorithm = {
version: versionNum,
length: blockLength,
mode: "MAC",
sBox: sBoxVal,
macLength: mac.length * 4
};
try {
const Hex = CryptoGost.coding.Hex;
if (iv) algorithm.iv = Hex.decode(iv);
const cipher = GostEngine.getGostCipher(algorithm);
const out = cipher.verify(Hex.decode(key), Hex.decode(mac), Hex.decode(input));
return out ? "The signature matches" : "The signature does not match";
} catch (err) {
throw new OperationError(err);
}
}
}
export default GOSTVerify;

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