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

Compare commits

...

63 Commits

Author SHA1 Message Date
a3957273
df151eabf9 10.6.0 2024-02-03 14:19:50 +00:00
a3957273
c6da0c623d Merge pull request #1678 from cnotin/patch-3
Add UUID regex to 'Regular expression' operation
2024-02-03 14:06:23 +00:00
a3957273
44b566789f Merge pull request #1675 from 0xThiebaut/LZNT1
Add support for LZNT1 decompression.
2024-02-03 13:31:13 +00:00
a3957273
940f78a8a7 Merge branch 'master' into LZNT1 2024-02-03 13:08:03 +00:00
a3957273
06c912be72 Merge branch 'master' into patch-3 2024-02-03 13:05:42 +00:00
a3957273
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
a3957273
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
a3957273
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
a3957273
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
a3957273
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
a3957273
d022dbc406 Merge pull request #1676 from cnotin/patch-2
Add links to wiki pages
2024-02-02 22:06:43 +00:00
a3957273
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
Clément Notin
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 Notin
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
Jocelyn Castellano
6c63302d62 Update chromedriver to v119 so that it is compatible with the chrome version in CI 2023-11-20 11:01:00 -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
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 Coomber
266fbab8fd Fix loading messages
Missing comma in array
2023-03-24 09:57:06 +00:00
n1474335
e57fd2a408 10.2.0 2023-03-23 18:22:37 +00:00
n1474335
3328ae8afd Updated CHANGELOG 2023-03-23 18:22:27 +00:00
n1474335
1caecf70a2 Fixed HKDF op name 2023-03-23 18:21:43 +00:00
n1474335
6e347742d9 Merge branch 'hkdf' of https://github.com/mikecat/CyberChef 2023-03-23 18:18:25 +00:00
n1474335
2e2dcfa416 10.1.0 2023-03-23 18:00:13 +00:00
n1474335
4bb10a34e1 Updated CHANGELOG 2023-03-23 17:59:56 +00:00
n1474335
1632e23c78 Merge branch 'markdown-beautify' of https://github.com/JatinSanghvi/CyberChef 2023-03-23 17:53:31 +00:00
n1474335
11fca557af Merge branch 'fix_dark_theme_highlight' of https://github.com/SamueleFacenda/CyberChef 2023-03-23 17:52:41 +00:00
n1474335
1cf14c6f01 Merge branch 'master' of https://github.com/mattnotmax/CyberChef 2023-03-23 17:48:05 +00:00
n1474335
1bba10e7c2 Merge branch 'swap-case' of https://github.com/mikecat/CyberChef 2023-03-23 17:46:47 +00:00
n1474335
8f3096af0a Merge branch 'levenshtein-distance' of https://github.com/mikecat/CyberChef 2023-03-23 17:42:16 +00:00
mattnotmax
4a356476b1 Merge branch 'gchq:master' into master 2023-03-23 21:28:39 +11:00
mattnotmax
e58744c63a Update index.html
Added new loading message
2023-03-18 21:35:03 +11:00
MikeCAT
b0c9a1850d add operaton HKDF 2023-03-17 23:50:24 +09:00
Samuele Facenda
764bd4b9ae Update dark theme highligh 2023-03-15 08:38:56 +01: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
Jatin Sanghvi
dee2dc3777 Align Markdown table column separators 2023-02-17 11:32:05 +05:30
MikeCAT
d5b72548fc add new operation: Swap case 2023-01-11 05:48:05 +09:00
MikeCAT
2c822314df add new operation: Levenshtein Distance 2023-01-11 05:16:37 +09: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
46 changed files with 2398 additions and 105 deletions

1
.gitignore vendored
View File

@@ -3,6 +3,7 @@ npm-debug.log
travis.log
build
.vscode
.idea
.*.swp
src/core/config/modules/*
src/core/config/OperationConfig.json

View File

@@ -13,6 +13,28 @@ All major and minor version changes will be documented in this file. Details of
## Details
### [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]
### [10.1.0] - 2023-03-23
- Added 'Levenshtein Distance' operation [@mikecat] | [#1498]
- Added 'Swap case' operation [@mikecat] | [#1499]
## [10.0.0] - 2023-03-22
- [Full details explained here](https://github.com/gchq/CyberChef/wiki/Character-encoding,-EOL-separators,-and-editor-features)
- Status bars added to the Input and Output [@n1474335] | [#1405]
@@ -358,6 +380,11 @@ All major and minor version changes will be documented in this file. Details of
[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
[9.55.0]: https://github.com/gchq/CyberChef/releases/tag/v9.55.0
[9.54.0]: https://github.com/gchq/CyberChef/releases/tag/v9.54.0
@@ -505,6 +532,8 @@ 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
[8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
[9a33498]: https://github.com/gchq/CyberChef/commit/9a33498fed26a8df9c9f35f39a78a174bf50a513
@@ -617,4 +646,10 @@ All major and minor version changes will be documented in this file. Details of
[#1466]: https://github.com/gchq/CyberChef/pull/1466
[#1456]: https://github.com/gchq/CyberChef/pull/1456
[#1450]: https://github.com/gchq/CyberChef/pull/1450
[#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

View File

@@ -197,6 +197,7 @@ module.exports = function (grunt) {
},
webpack: {
options: webpackConfig,
myConfig: webpackConfig,
web: webpackProdConf(),
},
"webpack-dev-server": {

View File

@@ -89,14 +89,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.

146
package-lock.json generated
View File

@@ -1,18 +1,20 @@
{
"name": "cyberchef",
"version": "10.0.1",
"version": "10.6.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "cyberchef",
"version": "10.0.1",
"version": "10.6.0",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"@astronautlabs/amf": "^0.0.6",
"@babel/polyfill": "^7.12.1",
"@blu3r4y/lzma": "^2.3.3",
"@wavesenterprise/crypto-gost-js": "^2.1.0-RC1",
"argon2-browser": "^1.18.0",
"arrive": "^2.4.1",
"avsc": "^5.7.7",
"bcryptjs": "^2.4.3",
@@ -109,7 +111,8 @@
"babel-loader": "^9.1.2",
"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": "^121.0.0",
"cli-progress": "^3.12.0",
"colors": "^1.4.0",
"copy-webpack-plugin": "^11.0.0",
@@ -2619,9 +2622,9 @@
"license": "BSD-3-Clause"
},
"node_modules/@testim/chrome-version": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.3.tgz",
"integrity": "sha512-g697J3WxV/Zytemz8aTuKjTGYtta9+02kva3C1xc7KXB8GdbfE1akGJIsZLyY/FSh2QrnE+fiB7vmWU3XNcb6A==",
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.4.tgz",
"integrity": "sha512-kIhULpw9TrGYnHp/8VfdcneIcxKnLixmADtukQRtJUmsVlMg0niMkwV0xZmi8hqa57xqilIHjWFA0GKvEjVU5g==",
"dev": true
},
"node_modules/@tokenizer/token": {
@@ -2818,6 +2821,11 @@
"dev": true,
"license": "ISC"
},
"node_modules/@wavesenterprise/crypto-gost-js": {
"version": "2.1.0-RC1",
"resolved": "https://registry.npmjs.org/@wavesenterprise/crypto-gost-js/-/crypto-gost-js-2.1.0-RC1.tgz",
"integrity": "sha512-liAR3/T/vxnEgNUE00Llt+sDvKYqo+sm/L7tqkJorg2ha3SsplOSXAqpH0t4Ya0gRj8qN8zXqO+WwLCxXXuQcw=="
},
"node_modules/@webassemblyjs/ast": {
"version": "1.11.1",
"dev": true,
@@ -3200,6 +3208,11 @@
"dev": true,
"license": "MIT"
},
"node_modules/argon2-browser": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/argon2-browser/-/argon2-browser-1.18.0.tgz",
"integrity": "sha512-ImVAGIItnFnvET1exhsQB7apRztcoC5TnlSqernMJDUjbc/DLq3UEYeXFrLPrlaIl8cVfwnXb6wX2KpFf2zxHw=="
},
"node_modules/argparse": {
"version": "2.0.1",
"license": "Python-2.0"
@@ -3334,12 +3347,12 @@
}
},
"node_modules/axios": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz",
"integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==",
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz",
"integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==",
"dev": true,
"dependencies": {
"follow-redirects": "^1.15.0",
"follow-redirects": "^1.15.4",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
@@ -3633,6 +3646,12 @@
],
"license": "MIT"
},
"node_modules/base64-loader": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/base64-loader/-/base64-loader-1.0.0.tgz",
"integrity": "sha512-p32+F8dg+ANGx7s8QsZS74ZPHfIycmC2yZcoerzFgbersIYWitPbbF39G6SBx3gyvzyLH5nt1ooocxr0IHuWKA==",
"dev": true
},
"node_modules/basic-auth": {
"version": "2.0.1",
"dev": true,
@@ -4246,9 +4265,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001439",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz",
"integrity": "sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A==",
"version": "1.0.30001583",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001583.tgz",
"integrity": "sha512-acWTYaha8xfhA/Du/z4sNZjHUWjkiuoAi2LM+T/aL+kemKQgPT1xBb/YKjlQ0Qo8gvbHsGNplrEJ+9G3gL7i4Q==",
"dev": true,
"funding": [
{
@@ -4258,6 +4277,10 @@
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
]
},
@@ -4356,25 +4379,25 @@
}
},
"node_modules/chromedriver": {
"version": "110.0.0",
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-110.0.0.tgz",
"integrity": "sha512-Le6q8xrA/3fAt+g8qiN0YjsYxINIhQMC6wj9X3W5L77uN4NspEzklDrqYNwBcEVn7PcAEJ73nLlS7mTyZRspHA==",
"version": "121.0.0",
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-121.0.0.tgz",
"integrity": "sha512-ZIKEdZrQAfuzT/RRofjl8/EZR99ghbdBXNTOcgJMKGP6N/UL6lHUX4n6ONWBV18pDvDFfQJ0x58h5AdOaXIOMw==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
"@testim/chrome-version": "^1.1.3",
"axios": "^1.2.1",
"compare-versions": "^5.0.1",
"@testim/chrome-version": "^1.1.4",
"axios": "^1.6.5",
"compare-versions": "^6.1.0",
"extract-zip": "^2.0.1",
"https-proxy-agent": "^5.0.1",
"proxy-from-env": "^1.1.0",
"tcp-port-used": "^1.0.1"
"tcp-port-used": "^1.0.2"
},
"bin": {
"chromedriver": "bin/chromedriver"
},
"engines": {
"node": ">=14"
"node": ">=18"
}
},
"node_modules/ci-info": {
@@ -4545,9 +4568,9 @@
"license": "MIT"
},
"node_modules/compare-versions": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-5.0.1.tgz",
"integrity": "sha512-v8Au3l0b+Nwkp4G142JcgJFh1/TUhdxut7wzD1Nq1dyp5oa3tXaqb03EXOAB6jS4gMlalkjAUPZBMiAfKUixHQ==",
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz",
"integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==",
"dev": true
},
"node_modules/compressible": {
@@ -6774,9 +6797,9 @@
"license": "ISC"
},
"node_modules/follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"version": "1.15.5",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
"integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
"dev": true,
"funding": [
{
@@ -11240,8 +11263,9 @@
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"dev": true,
"license": "MIT"
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"dev": true
},
"node_modules/psl": {
"version": "1.9.0",
@@ -15585,9 +15609,9 @@
"version": "1.1.0"
},
"@testim/chrome-version": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.3.tgz",
"integrity": "sha512-g697J3WxV/Zytemz8aTuKjTGYtta9+02kva3C1xc7KXB8GdbfE1akGJIsZLyY/FSh2QrnE+fiB7vmWU3XNcb6A==",
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.4.tgz",
"integrity": "sha512-kIhULpw9TrGYnHp/8VfdcneIcxKnLixmADtukQRtJUmsVlMg0niMkwV0xZmi8hqa57xqilIHjWFA0GKvEjVU5g==",
"dev": true
},
"@tokenizer/token": {
@@ -15756,6 +15780,11 @@
"version": "1.1.2",
"dev": true
},
"@wavesenterprise/crypto-gost-js": {
"version": "2.1.0-RC1",
"resolved": "https://registry.npmjs.org/@wavesenterprise/crypto-gost-js/-/crypto-gost-js-2.1.0-RC1.tgz",
"integrity": "sha512-liAR3/T/vxnEgNUE00Llt+sDvKYqo+sm/L7tqkJorg2ha3SsplOSXAqpH0t4Ya0gRj8qN8zXqO+WwLCxXXuQcw=="
},
"@webassemblyjs/ast": {
"version": "1.11.1",
"dev": true,
@@ -16040,6 +16069,11 @@
"version": "5.0.1",
"dev": true
},
"argon2-browser": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/argon2-browser/-/argon2-browser-1.18.0.tgz",
"integrity": "sha512-ImVAGIItnFnvET1exhsQB7apRztcoC5TnlSqernMJDUjbc/DLq3UEYeXFrLPrlaIl8cVfwnXb6wX2KpFf2zxHw=="
},
"argparse": {
"version": "2.0.1"
},
@@ -16127,12 +16161,12 @@
"dev": true
},
"axios": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz",
"integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==",
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz",
"integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==",
"dev": true,
"requires": {
"follow-redirects": "^1.15.0",
"follow-redirects": "^1.15.4",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
@@ -16347,6 +16381,12 @@
"base64-js": {
"version": "1.5.1"
},
"base64-loader": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/base64-loader/-/base64-loader-1.0.0.tgz",
"integrity": "sha512-p32+F8dg+ANGx7s8QsZS74ZPHfIycmC2yZcoerzFgbersIYWitPbbF39G6SBx3gyvzyLH5nt1ooocxr0IHuWKA==",
"dev": true
},
"basic-auth": {
"version": "2.0.1",
"dev": true,
@@ -16744,9 +16784,9 @@
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001439",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz",
"integrity": "sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A==",
"version": "1.0.30001583",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001583.tgz",
"integrity": "sha512-acWTYaha8xfhA/Du/z4sNZjHUWjkiuoAi2LM+T/aL+kemKQgPT1xBb/YKjlQ0Qo8gvbHsGNplrEJ+9G3gL7i4Q==",
"dev": true
},
"cbor": {
@@ -16810,18 +16850,18 @@
"dev": true
},
"chromedriver": {
"version": "110.0.0",
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-110.0.0.tgz",
"integrity": "sha512-Le6q8xrA/3fAt+g8qiN0YjsYxINIhQMC6wj9X3W5L77uN4NspEzklDrqYNwBcEVn7PcAEJ73nLlS7mTyZRspHA==",
"version": "121.0.0",
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-121.0.0.tgz",
"integrity": "sha512-ZIKEdZrQAfuzT/RRofjl8/EZR99ghbdBXNTOcgJMKGP6N/UL6lHUX4n6ONWBV18pDvDFfQJ0x58h5AdOaXIOMw==",
"dev": true,
"requires": {
"@testim/chrome-version": "^1.1.3",
"axios": "^1.2.1",
"compare-versions": "^5.0.1",
"@testim/chrome-version": "^1.1.4",
"axios": "^1.6.5",
"compare-versions": "^6.1.0",
"extract-zip": "^2.0.1",
"https-proxy-agent": "^5.0.1",
"proxy-from-env": "^1.1.0",
"tcp-port-used": "^1.0.1"
"tcp-port-used": "^1.0.2"
}
},
"ci-info": {
@@ -16936,9 +16976,9 @@
"dev": true
},
"compare-versions": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-5.0.1.tgz",
"integrity": "sha512-v8Au3l0b+Nwkp4G142JcgJFh1/TUhdxut7wzD1Nq1dyp5oa3tXaqb03EXOAB6jS4gMlalkjAUPZBMiAfKUixHQ==",
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz",
"integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==",
"dev": true
},
"compressible": {
@@ -18454,9 +18494,9 @@
"version": "3.2.5"
},
"follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"version": "1.15.5",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
"integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
"dev": true
},
"for-in": {
@@ -21419,6 +21459,8 @@
},
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"dev": true
},
"psl": {

View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "10.0.1",
"version": "10.6.0",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef",
@@ -54,7 +54,8 @@
"babel-loader": "^9.1.2",
"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": "^121.0.0",
"cli-progress": "^3.12.0",
"colors": "^1.4.0",
"copy-webpack-plugin": "^11.0.0",
@@ -94,6 +95,8 @@
"@astronautlabs/amf": "^0.0.6",
"@babel/polyfill": "^7.12.1",
"@blu3r4y/lzma": "^2.3.3",
"@wavesenterprise/crypto-gost-js": "^2.1.0-RC1",
"argon2-browser": "^1.18.0",
"arrive": "^2.4.1",
"avsc": "^5.7.7",
"bcryptjs": "^2.4.3",
@@ -178,8 +181,8 @@
"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",

View File

@@ -892,6 +892,23 @@ class Utils {
}
/**
* Converts a string to it's 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.
*

View File

@@ -91,6 +91,12 @@
"Rabbit",
"SM4 Encrypt",
"SM4 Decrypt",
"GOST Encrypt",
"GOST Decrypt",
"GOST Sign",
"GOST Verify",
"GOST Key Wrap",
"GOST Key Unwrap",
"ROT13",
"ROT13 Brute Force",
"ROT47",
@@ -121,6 +127,7 @@
"Substitute",
"Derive PBKDF2 key",
"Derive EVP key",
"Derive HKDF key",
"Bcrypt",
"Scrypt",
"JWT Sign",
@@ -247,6 +254,7 @@
"Remove null bytes",
"To Upper case",
"To Lower case",
"Swap case",
"To Case Insensitive Regex",
"From Case Insensitive Regex",
"Add line numbers",
@@ -271,6 +279,7 @@
"Fuzzy Match",
"Offset checker",
"Hamming Distance",
"Levenshtein Distance",
"Convert distance",
"Convert area",
"Convert mass",
@@ -342,7 +351,8 @@
"LZMA Decompress",
"LZMA Compress",
"LZ4 Decompress",
"LZ4 Compress"
"LZ4 Compress",
"LZNT1 Decompress"
]
},
{
@@ -367,7 +377,7 @@
"Snefru",
"BLAKE2b",
"BLAKE2s",
"GOST hash",
"GOST Hash",
"Streebog",
"SSDEEP",
"CTPH",
@@ -378,6 +388,8 @@
"Bcrypt",
"Bcrypt compare",
"Bcrypt parse",
"Argon2",
"Argon2 compare",
"Scrypt",
"NT Hash",
"LM Hash",
@@ -485,6 +497,7 @@
"P-list Viewer",
"Disassemble x86",
"Pseudo-Random Number Generator",
"Generate De Bruijn Sequence",
"Generate UUID",
"Generate TOTP",
"Generate HOTP",

88
src/core/lib/LZNT1.mjs Normal file
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;
}

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;

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;

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 = [];

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 = [

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 = [

View File

@@ -0,0 +1,138 @@
/**
* @author mikecat
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import OperationError from "../errors/OperationError.mjs";
import CryptoApi from "crypto-api/src/crypto-api.mjs";
/**
* Derive HKDF Key operation
*/
class DeriveHKDFKey extends Operation {
/**
* DeriveHKDFKey constructor
*/
constructor() {
super();
this.name = "Derive HKDF key";
this.module = "Crypto";
this.description = "A simple Hashed Message Authenticaton Code (HMAC)-based key derivation function (HKDF), defined in RFC5869.";
this.infoURL = "https://wikipedia.org/wiki/HKDF";
this.inputType = "ArrayBuffer";
this.outputType = "string";
this.args = [
{
"name": "Salt",
"type": "toggleString",
"value": "",
"toggleValues": ["Hex", "Decimal", "Base64", "UTF8", "Latin1"]
},
{
"name": "Info",
"type": "toggleString",
"value": "",
"toggleValues": ["Hex", "Decimal", "Base64", "UTF8", "Latin1"]
},
{
"name": "Hashing function",
"type": "option",
"value": [
"MD2",
"MD4",
"MD5",
"SHA0",
"SHA1",
"SHA224",
"SHA256",
"SHA384",
"SHA512",
"SHA512/224",
"SHA512/256",
"RIPEMD128",
"RIPEMD160",
"RIPEMD256",
"RIPEMD320",
"HAS160",
"Whirlpool",
"Whirlpool-0",
"Whirlpool-T",
"Snefru"
],
"defaultIndex": 6
},
{
"name": "Extract mode",
"type": "argSelector",
"value": [
{
"name": "with salt",
"on": [0]
},
{
"name": "no salt",
"off": [0]
},
{
"name": "skip",
"off": [0]
}
]
},
{
"name": "L (number of output octets)",
"type": "number",
"value": 16,
"min": 0
},
];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {ArrayBuffer}
*/
run(input, args) {
const argSalt = Utils.convertToByteString(args[0].string || "", args[0].option),
info = Utils.convertToByteString(args[1].string || "", args[1].option),
hashFunc = args[2].toLowerCase(),
extractMode = args[3],
L = args[4],
IKM = Utils.arrayBufferToStr(input, false),
hasher = CryptoApi.getHasher(hashFunc),
HashLen = hasher.finalize().length;
if (L < 0) {
throw new OperationError("L must be non-negative");
}
if (L > 255 * HashLen) {
throw new OperationError("L too large (maximum length for " + args[2] + " is " + (255 * HashLen) + ")");
}
const hmacHash = function(key, data) {
hasher.reset();
const mac = CryptoApi.getHmac(key, hasher);
mac.update(data);
return mac.finalize();
};
const salt = extractMode === "with salt" ? argSalt : "\0".repeat(HashLen);
const PRK = extractMode === "skip" ? IKM : hmacHash(salt, IKM);
let T = "";
let result = "";
for (let i = 1; i <= 255 && result.length < L; i++) {
const TNext = hmacHash(PRK, T + info + String.fromCharCode(i));
result += TNext;
T = TNext;
}
return CryptoApi.encoder.toHex(result.substring(0, L));
}
}
export default DeriveHKDFKey;

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

View File

@@ -0,0 +1,138 @@
/**
* @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 (Magma, 1989)",
off: [5],
on: [6]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
on: [5],
off: [6]
}
]
},
{
name: "Block length",
type: "option",
value: ["64", "128"]
},
{
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, length, 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));
const versionNum = version === "GOST 28147 (Magma, 1989)" ? 1989 : 2015;
const blockLength = versionNum === 1989 ? 64 : parseInt(length, 10);
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;

View File

@@ -0,0 +1,138 @@
/**
* @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 (Magma, 1989)",
off: [5],
on: [6]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
on: [5],
off: [6]
}
]
},
{
name: "Block length",
type: "option",
value: ["64", "128"]
},
{
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, length, 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));
const versionNum = version === "GOST 28147 (Magma, 1989)" ? 1989 : 2015;
const blockLength = versionNum === 1989 ? 64 : parseInt(length, 10);
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;

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

View File

@@ -0,0 +1,129 @@
/**
* @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 (Magma, 1989)",
off: [5],
on: [6]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
on: [5],
off: [6]
}
]
},
{
name: "Block length",
type: "option",
value: ["64", "128"]
},
{
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, length, 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));
const versionNum = version === "GOST 28147 (Magma, 1989)" ? 1989 : 2015;
const blockLength = versionNum === 1989 ? 64 : parseInt(length, 10);
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;

View File

@@ -0,0 +1,129 @@
/**
* @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 (Magma, 1989)",
off: [5],
on: [6]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
on: [5],
off: [6]
}
]
},
{
name: "Block length",
type: "option",
value: ["64", "128"]
},
{
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, length, 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));
const versionNum = version === "GOST 28147 (Magma, 1989)" ? 1989 : 2015;
const blockLength = versionNum === 1989 ? 64 : parseInt(length, 10);
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;

View File

@@ -0,0 +1,129 @@
/**
* @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 (Magma, 1989)",
off: [5],
on: [6]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
on: [5],
off: [6]
}
]
},
{
name: "Block length",
type: "option",
value: ["64", "128"]
},
{
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, length, 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));
const versionNum = version === "GOST 28147 (Magma, 1989)" ? 1989 : 2015;
const blockLength = versionNum === 1989 ? 64 : parseInt(length, 10);
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;

View File

@@ -0,0 +1,123 @@
/**
* @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 (Magma, 1989)",
off: [5],
on: [6]
},
{
name: "GOST R 34.12 (Kuznyechik, 2015)",
on: [5],
off: [6]
}
]
},
{
name: "Block length",
type: "option",
value: ["64", "128"]
},
{
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, length, 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));
const versionNum = version === "GOST 28147 (Magma, 1989)" ? 1989 : 2015;
const blockLength = versionNum === 1989 ? 64 : parseInt(length, 10);
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;

View File

@@ -108,7 +108,7 @@ class GenerateAllHashes extends Operation {
{name: "BLAKE2s-256", algo: (new BLAKE2s), inputType: "arrayBuffer", params: ["256", "Hex", {string: "", option: "UTF8"}]},
{name: "Streebog-256", algo: (new Streebog), inputType: "arrayBuffer", params: ["256"]},
{name: "Streebog-512", algo: (new Streebog), inputType: "arrayBuffer", params: ["512"]},
{name: "GOST", algo: (new GOSTHash), inputType: "arrayBuffer", params: ["D-A"]},
{name: "GOST", algo: (new GOSTHash), inputType: "arrayBuffer", params: ["GOST 28147 (1994)", "256", "D-A"]},
{name: "LM Hash", algo: (new LMHash), inputType: "str", params: []},
{name: "NT Hash", algo: (new NTHash), inputType: "str", params: []},
{name: "SSDEEP", algo: (new SSDEEP()), inputType: "str"},

View File

@@ -0,0 +1,85 @@
/**
* @author gchq77703 [gchq77703@gchq.gov.uk]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* Generate De Bruijn Sequence operation
*/
class GenerateDeBruijnSequence extends Operation {
/**
* GenerateDeBruijnSequence constructor
*/
constructor() {
super();
this.name = "Generate De Bruijn Sequence";
this.module = "Default";
this.description = "Generates rolling keycode combinations given a certain alphabet size and key length.";
this.infoURL = "https://wikipedia.org/wiki/De_Bruijn_sequence";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Alphabet size (k)",
type: "number",
value: 2
},
{
name: "Key length (n)",
type: "number",
value: 3
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const [k, n] = args;
if (k < 2 || k > 9) {
throw new OperationError("Invalid alphabet size, required to be between 2 and 9 (inclusive).");
}
if (n < 2) {
throw new OperationError("Invalid key length, required to be at least 2.");
}
if (Math.pow(k, n) > 50000) {
throw new OperationError("Too many permutations, please reduce k^n to under 50,000.");
}
const a = new Array(k * n).fill(0);
const sequence = [];
(function db(t = 1, p = 1) {
if (t > n) {
if (n % p !== 0) return;
for (let j = 1; j <= p; j++) {
sequence.push(a[j]);
}
return;
}
a[t] = a[t - p];
db(t + 1, p);
for (let j = a[t - p] + 1; j < k; j++) {
a[t] = j;
db(t + 1, t);
}
})();
return sequence.join("");
}
}
export default GenerateDeBruijnSequence;

View File

@@ -0,0 +1,41 @@
/**
* @author 0xThiebaut [thiebaut.dev]
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import {decompress} from "../lib/LZNT1.mjs";
/**
* LZNT1 Decompress operation
*/
class LZNT1Decompress extends Operation {
/**
* LZNT1 Decompress constructor
*/
constructor() {
super();
this.name = "LZNT1 Decompress";
this.module = "Compression";
this.description = "Decompresses data using the LZNT1 algorithm.<br><br>Similar to the Windows API <code>RtlDecompressBuffer</code>.";
this.infoURL = "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-xca/5655f4a3-6ba4-489b-959f-e1f407c52f15";
this.inputType = "byteArray";
this.outputType = "byteArray";
this.args = [];
}
/**
* @param {byteArray} input
* @param {Object[]} args
* @returns {byteArray}
*/
run(input, args) {
return decompress(input);
}
}
export default LZNT1Decompress;

View File

@@ -0,0 +1,98 @@
/**
* @author mikecat
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* Levenshtein Distance operation
*/
class LevenshteinDistance extends Operation {
/**
* LevenshteinDistance constructor
*/
constructor() {
super();
this.name = "Levenshtein Distance";
this.module = "Default";
this.description = "Levenshtein Distance (also known as Edit Distance) is a string metric to measure a difference between two strings that counts operations (insertions, deletions, and substitutions) on single character that are required to change one string to another.";
this.infoURL = "https://wikipedia.org/wiki/Levenshtein_distance";
this.inputType = "string";
this.outputType = "number";
this.args = [
{
name: "Sample delimiter",
type: "binaryString",
value: "\\n"
},
{
name: "Insertion cost",
type: "number",
value: 1
},
{
name: "Deletion cost",
type: "number",
value: 1
},
{
name: "Substitution cost",
type: "number",
value: 1
},
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {number}
*/
run(input, args) {
const [delim, insCost, delCost, subCost] = args;
const samples = input.split(delim);
if (samples.length !== 2) {
throw new OperationError("Incorrect number of samples. Check your input and/or delimiter.");
}
if (insCost < 0 || delCost < 0 || subCost < 0) {
throw new OperationError("Negative costs are not allowed.");
}
const src = samples[0], dest = samples[1];
let currentCost = new Array(src.length + 1);
let nextCost = new Array(src.length + 1);
for (let i = 0; i < currentCost.length; i++) {
currentCost[i] = delCost * i;
}
for (let i = 0; i < dest.length; i++) {
const destc = dest.charAt(i);
nextCost[0] = currentCost[0] + insCost;
for (let j = 0; j < src.length; j++) {
let candidate;
// insertion
let optCost = currentCost[j + 1] + insCost;
// deletion
candidate = nextCost[j] + delCost;
if (candidate < optCost) optCost = candidate;
// substitution or matched character
candidate = currentCost[j];
if (src.charAt(j) !== destc) candidate += subCost;
if (candidate < optCost) optCost = candidate;
// store calculated cost
nextCost[j + 1] = optCost;
}
const tempCost = nextCost;
nextCost = currentCost;
currentCost = tempCost;
}
return currentCost[currentCost.length - 1];
}
}
export default LevenshteinDistance;

View File

@@ -83,6 +83,10 @@ class RegularExpression extends Operation {
name: "Strings",
value: "[A-Za-z\\d/\\-:.,_$%\\x27\"()<>= !\\[\\]{}@]{4,}"
},
{
name: "UUID (any version)",
value: "[0-9a-fA-F]{8}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{12}"
},
],
"target": 1
},

View File

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

View File

@@ -28,7 +28,7 @@ class Streebog extends Operation {
this.outputType = "string";
this.args = [
{
"name": "Size",
"name": "Digest length",
"type": "option",
"value": ["256", "512"]
}
@@ -41,13 +41,16 @@ class Streebog extends Operation {
* @returns {string}
*/
run(input, args) {
const [length] = args;
const algorithm = {
version: 2012,
mode: "HASH",
length: parseInt(length, 10)
};
try {
const length = parseInt(args[0], 10);
const gostDigest = new GostDigest({
name: "GOST R 34.11",
version: 2012,
length: length
});
const gostDigest = new GostDigest(algorithm);
return toHexFast(gostDigest.digest(input));
} catch (err) {

View File

@@ -0,0 +1,76 @@
/**
* @author mikecat
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
/**
* Swap case operation
*/
class SwapCase extends Operation {
/**
* SwapCase constructor
*/
constructor() {
super();
this.name = "Swap case";
this.module = "Default";
this.description = "Converts uppercase letters to lowercase ones, and lowercase ones to uppercase ones.";
this.infoURL = "";
this.inputType = "string";
this.outputType = "string";
this.args = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
let result = "";
for (let i = 0; i < input.length; i++) {
const c = input.charAt(i);
const upper = c.toUpperCase();
if (c === upper) {
result += c.toLowerCase();
} else {
result += upper;
}
}
return result;
}
/**
* Highlight Swap case
*
* @param {Object[]} pos
* @param {number} pos[].start
* @param {number} pos[].end
* @param {Object[]} args
* @returns {Object[]} pos
*/
highlight(pos, args) {
return pos;
}
/**
* Highlight Swap case in reverse
*
* @param {Object[]} pos
* @param {number} pos[].start
* @param {number} pos[].end
* @param {Object[]} args
* @returns {Object[]} pos
*/
highlightReverse(pos, args) {
return pos;
}
}
export default SwapCase;

View File

@@ -214,7 +214,7 @@ class ToTable extends Operation {
output += outputRow(row, longestCells);
let rowOutput = verticalBorder;
row.forEach(function(cell, index) {
rowOutput += " " + headerDivider + " " + verticalBorder;
rowOutput += " " + headerDivider.repeat(longestCells[index]) + " " + verticalBorder;
});
output += rowOutput += "\n";

View File

@@ -157,9 +157,9 @@ function titleFromWikiLink(urlStr) {
pageTitle = "";
switch (urlObj.host) {
case "forensicswiki.xyz":
case "forensics.wiki":
wikiName = "Forensics Wiki";
pageTitle = urlObj.query.substr(6).replace(/_/g, " "); // Chop off 'title='
pageTitle = Utils.toTitleCase(urlObj.path.replace(/\//g, "").replace(/_/g, " "));
break;
case "wikipedia.org":
wikiName = "Wikipedia";

View File

@@ -61,7 +61,9 @@
"Symlinking emacs and vim to ed...",
"Training branch predictor...",
"Timing cache hits...",
"Speculatively executing recipes..."
"Speculatively executing recipes...",
"Adding LLM hallucinations...",
"Decompressing malware..."
];
// Shuffle array using Durstenfeld algorithm

View File

@@ -108,7 +108,7 @@
/* Highlighter colours */
--hl1: #264f78;
--hl2: #675351;
--hl3: #ffb6b6;
--hl3: #c40000;
--hl4: #fcf8e3;
--hl5: #38811b;

View File

@@ -275,7 +275,6 @@ class StatusBarPanel {
bakingTime.textContent = this.timing.duration(this.tabNumGetter());
const info = this.timing.printStages(this.tabNumGetter()).replace(/\n/g, "<br>");
bakingTimeInfo.setAttribute("title", info);
bakingTimeInfo.setAttribute("data-original-title", info);
} else {
bakingTimeInfo.style.display = "none";

View File

@@ -635,6 +635,10 @@ WWFkYSBZYWRh\r
assert.strictEqual(chef.keccak("Flea Market").toString(), "c2a06880b19e453ee5440e8bd4c2024bedc15a6630096aa3f609acfd2b8f15f27cd293e1cc73933e81432269129ce954a6138889ce87831179d55dcff1cc7587");
}),
it("LZNT1 Decompress", () => {
assert.strictEqual(chef.LZNT1Decompress("\x1a\xb0\x00compress\x00edtestda\x04ta\x07\x88alot").toString(), "compressedtestdatacompressedalot");
}),
it("MD6", () => {
assert.strictEqual(chef.MD6("Head Over Heels", {key: "arty"}).toString(), "d8f7fe4931fbaa37316f76283d5f615f50ddd54afdc794b61da522556aee99ad");
}),

View File

@@ -62,6 +62,7 @@ import "./tests/JSONtoCSV.mjs";
import "./tests/JWTDecode.mjs";
import "./tests/JWTSign.mjs";
import "./tests/JWTVerify.mjs";
import "./tests/LZNT1Decompress.mjs";
import "./tests/MS.mjs";
import "./tests/Magic.mjs";
import "./tests/MorseCode.mjs";
@@ -130,6 +131,11 @@ import "./tests/FletcherChecksum.mjs";
import "./tests/CMAC.mjs";
import "./tests/AESKeyWrap.mjs";
import "./tests/Rabbit.mjs";
import "./tests/LevenshteinDistance.mjs";
import "./tests/SwapCase.mjs";
import "./tests/HKDF.mjs";
import "./tests/GenerateDeBruijnSequence.mjs";
import "./tests/GOST.mjs";
// Cannot test operations that use the File type yet
// import "./tests/SplitColourChannels.mjs";

View File

@@ -0,0 +1,183 @@
/**
* GOST tests.
*
* The GOST library already includes a range of tests for the correctness of
* the algorithms. These tests are intended only to confirm that the library
* has been correctly integrated into CyberChef.
*
* @author n1474335 [n1474335@gmail.com]
*
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "GOST Encrypt: Magma",
input: "Hello, World!",
expectedOutput: "f124ac5c0853870906dbaf9b56",
recipeConfig: [
{
op: "GOST Encrypt",
args: [
{ "option": "Hex", "string": "00112233" },
{ "option": "Hex", "string": "0011223344556677" },
"Raw",
"Hex",
"GOST 28147 (Magma, 1989)",
"64",
"E-SC",
"OFB",
"CP",
"ZERO"
]
}
],
},
{
name: "GOST Encrypt: Kuznyechik",
input: "Hello, World!",
expectedOutput: "8673d490dfa4a66d5e3ff00ba316724f",
recipeConfig: [
{
op: "GOST Encrypt",
args: [
{ "option": "Hex", "string": "00112233" },
{ "option": "Hex", "string": "00112233445566778899aabbccddeeff" },
"Raw",
"Hex",
"GOST R 34.12 (Kuznyechik, 2015)",
"128",
"E-SC",
"CBC",
"CP",
"PKCS5"
]
}
],
},
{
name: "GOST Decrypt: Magma",
input: "f124ac5c0853870906dbaf9b56",
expectedOutput: "Hello, World!",
recipeConfig: [
{
op: "GOST Decrypt",
args: [
{ "option": "Hex", "string": "00112233" },
{ "option": "Hex", "string": "0011223344556677" },
"Hex",
"Raw",
"GOST 28147 (Magma, 1989)",
"128",
"E-SC",
"OFB",
"CP",
"ZERO"
]
}
],
},
{
name: "GOST Decrypt: Kuznyechik",
input: "8673d490dfa4a66d5e3ff00ba316724f",
expectedOutput: "Hello, World!\0\0\0",
recipeConfig: [
{
op: "GOST Decrypt",
args: [
{ "option": "Hex", "string": "00112233" },
{ "option": "Hex", "string": "00112233445566778899aabbccddeeff" },
"Hex",
"Raw",
"GOST R 34.12 (Kuznyechik, 2015)",
"128",
"E-TEST",
"CBC",
"CP",
"PKCS5"
]
}
],
},
{
name: "GOST Sign",
input: "Hello, World!",
expectedOutput: "810d0c40e965",
recipeConfig: [
{
op: "GOST Sign",
args: [
{ "option": "Hex", "string": "00112233" },
{ "option": "Hex", "string": "0011223344556677" },
"Raw",
"Hex",
"GOST 28147 (Magma, 1989)",
"64",
"E-C",
48
]
}
],
},
{
name: "GOST Verify",
input: "Hello, World!",
expectedOutput: "The signature matches",
recipeConfig: [
{
op: "GOST Verify",
args: [
{ "option": "Hex", "string": "00112233" },
{ "option": "Hex", "string": "00112233445566778899aabbccddeeff" },
{ "option": "Hex", "string": "42b77fb3d6f6bf04" },
"Raw",
"GOST R 34.12 (Kuznyechik, 2015)",
"128",
"E-TEST"
]
}
],
},
{
name: "GOST Key Wrap",
input: "Hello, World!123",
expectedOutput: "0bb706e92487fceef97589911faeb28200000000000000000000000000000000\r\n6b7bfd16",
recipeConfig: [
{
op: "GOST Key Wrap",
args: [
{ "option": "Hex", "string": "00112233" },
{ "option": "Hex", "string": "0011223344556677" },
"Raw",
"Hex",
"GOST R 34.12 (Kuznyechik, 2015)",
"64",
"E-TEST",
"CP"
]
}
],
},
{
name: "GOST Key Unwrap",
input: "c8e58458a42d21974d50103d59b469f2c8e58458a42d21974d50103d59b469f2\r\na32a1575",
expectedOutput: "0123456789abcdef0123456789abcdef",
recipeConfig: [
{
op: "GOST Key Unwrap",
args: [
{ "option": "Hex", "string": "" },
{ "option": "Latin1", "string": "00112233" },
"Hex",
"Raw",
"GOST 28147 (Magma, 1989)",
"64",
"E-Z",
"CP"
]
}
],
},
]);

View File

@@ -0,0 +1,33 @@
/**
* De Brujin Sequence tests.
*
* @author gchq77703 [gchq77703@gchq.gov.uk]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "Generate De Bruijn Sequence: Small Sequence",
input: "",
expectedOutput: "00010111",
recipeConfig: [
{
"op": "Generate De Bruijn Sequence",
"args": [2, 3]
}
]
},
{
name: "Generate De Bruijn Sequence: Long Sequence",
input: "",
expectedOutput: "0000010000200003000110001200013000210002200023000310003200033001010010200103001110011200113001210012200123001310013200133002010020200203002110021200213002210022200223002310023200233003010030200303003110031200313003210032200323003310033200333010110101201013010210102201023010310103201033011020110301111011120111301121011220112301131011320113301202012030121101212012130122101222012230123101232012330130201303013110131201313013210132201323013310133201333020210202202023020310203202033021030211102112021130212102122021230213102132021330220302211022120221302221022220222302231022320223302303023110231202313023210232202323023310233202333030310303203033031110311203113031210312203123031310313203133032110321203213032210322203223032310323203233033110331203313033210332203323033310333203333111112111131112211123111321113311212112131122211223112321123311312113131132211323113321133312122121231213212133122131222212223122321223312313123221232312332123331313213133132221322313232132331332213323133321333322222322233223232233323233233333",
recipeConfig: [
{
"op": "Generate De Bruijn Sequence",
"args": [4, 5]
}
]
}
]);

View File

@@ -0,0 +1,180 @@
/**
* @author mikecat
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
"name": "HKDF: RFC5869 Test Case 1",
"input": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
"expectedOutput": "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"],
},
{
"op": "Derive HKDF key",
"args": [
{"option": "Hex", "string": "000102030405060708090a0b0c"},
{"option": "Hex", "string": "f0f1f2f3f4f5f6f7f8f9"},
"SHA256", "with salt", 42,
],
},
],
},
{
"name": "HKDF: RFC5869 Test Case 2",
"input": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f",
"expectedOutput": "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"],
},
{
"op": "Derive HKDF key",
"args": [
{"option": "Hex", "string": "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf"},
{"option": "Hex", "string": "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"},
"SHA256", "with salt", 82,
],
},
],
},
{
"name": "HKDF: RFC5869 Test Case 3",
"input": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
"expectedOutput": "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"],
},
{
"op": "Derive HKDF key",
"args": [
{"option": "Hex", "string": ""},
{"option": "Hex", "string": ""},
"SHA256", "with salt", 42,
],
},
],
},
{
"name": "HKDF: RFC5869 Test Case 4",
"input": "0b0b0b0b0b0b0b0b0b0b0b",
"expectedOutput": "085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"],
},
{
"op": "Derive HKDF key",
"args": [
{"option": "Hex", "string": "000102030405060708090a0b0c"},
{"option": "Hex", "string": "f0f1f2f3f4f5f6f7f8f9"},
"SHA1", "with salt", 42,
],
},
],
},
{
"name": "HKDF: RFC5869 Test Case 5",
"input": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f",
"expectedOutput": "0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"],
},
{
"op": "Derive HKDF key",
"args": [
{"option": "Hex", "string": "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf"},
{"option": "Hex", "string": "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"},
"SHA1", "with salt", 82,
],
},
],
},
{
"name": "HKDF: RFC5869 Test Case 6",
"input": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
"expectedOutput": "0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"],
},
{
"op": "Derive HKDF key",
"args": [
{"option": "Hex", "string": ""},
{"option": "Hex", "string": ""},
"SHA1", "with salt", 42,
],
},
],
},
{
"name": "HKDF: RFC5869 Test Case 7",
"input": "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
"expectedOutput": "2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"],
},
{
"op": "Derive HKDF key",
"args": [
{"option": "Hex", "string": ""},
{"option": "Hex", "string": ""},
"SHA1", "no salt", 42,
],
},
],
},
{
"name": "HKDF: RFC5869 Test Case 1 with skip extract",
"input": "077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5",
"expectedOutput": "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"],
},
{
"op": "Derive HKDF key",
"args": [
{"option": "Hex", "string": ""},
{"option": "Hex", "string": "f0f1f2f3f4f5f6f7f8f9"},
"SHA256", "skip", 42,
],
},
],
},
{
"name": "HKDF: too large L",
"input": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
"expectedOutput": "L too large (maximum length for SHA256 is 8160)",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"],
},
{
"op": "Derive HKDF key",
"args": [
{"option": "Hex", "string": "000102030405060708090a0b0c"},
{"option": "Hex", "string": "f0f1f2f3f4f5f6f7f8f9"},
"SHA256", "with salt", 8161,
],
},
],
},
]);

View File

@@ -1094,8 +1094,8 @@ TestRegister.addTests([
expectedOutput: "981e5f3ca30c841487830f84fb433e13ac1101569b9c13584ac483234cd656c0",
recipeConfig: [
{
op: "GOST hash",
args: ["D-A"]
op: "GOST Hash",
args: ["GOST 28147 (1994)", "256", "D-A"]
}
]
},
@@ -1105,11 +1105,11 @@ TestRegister.addTests([
expectedOutput: "2cefc2f7b7bdc514e18ea57fa74ff357e7fa17d652c75f69cb1be7893ede48eb",
recipeConfig: [
{
op: "GOST hash",
args: ["D-A"]
op: "GOST Hash",
args: ["GOST 28147 (1994)", "256", "D-A"]
}
]
}
},
/* { // This takes a LONG time to run (over a minute usually).
name: "Scrypt: RFC test vector 4",
input: "pleaseletmein",
@@ -1127,4 +1127,36 @@ TestRegister.addTests([
}
]
}, */
{
name: "Argon2",
input: "argon2password",
expectedOutput: "$argon2i$v=19$m=4096,t=3,p=1$c29tZXNhbHQ$s43my9eBljQADuF/LWCG8vGqwAJzOorKQ0Yog8jFvbw",
recipeConfig: [
{
op: "Argon2",
args: [
{"option": "UTF8", "string": "somesalt"},
3,
4096,
1,
32,
"Argon2i",
"Encoded hash"
]
}
]
},
{
name: "Argon2 compare",
input: "argon2password",
expectedOutput: "Match: argon2password",
recipeConfig: [
{
op: "Argon2 compare",
args: [
"$argon2i$v=19$m=4096,t=3,p=1$c29tZXNhbHQ$s43my9eBljQADuF/LWCG8vGqwAJzOorKQ0Yog8jFvbw"
]
}
]
}
]);

View File

@@ -0,0 +1,22 @@
/**
* LZNT1 Decompress tests.
*
* @author 0xThiebaut [thiebaut.dev]
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "LZNT1 Decompress",
input: "\x1a\xb0\x00compress\x00edtestda\x04ta\x07\x88alot",
expectedOutput: "compressedtestdatacompressedalot",
recipeConfig: [
{
op: "LZNT1 Decompress",
args: []
}
],
}
]);

View File

@@ -0,0 +1,165 @@
/**
* @author mikecat
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
"name": "Levenshtein Distance: Wikipedia example 1",
"input": "kitten\nsitting",
"expectedOutput": "3",
"recipeConfig": [
{
"op": "Levenshtein Distance",
"args": [
"\\n", 1, 1, 1,
],
},
],
},
{
"name": "Levenshtein Distance: Wikipedia example 2",
"input": "saturday\nsunday",
"expectedOutput": "3",
"recipeConfig": [
{
"op": "Levenshtein Distance",
"args": [
"\\n", 1, 1, 1,
],
},
],
},
{
"name": "Levenshtein Distance: Wikipedia example 1 with substitution cost 2",
"input": "kitten\nsitting",
"expectedOutput": "5",
"recipeConfig": [
{
"op": "Levenshtein Distance",
"args": [
"\\n", 1, 1, 2,
],
},
],
},
{
"name": "Levenshtein Distance: varied costs 1",
"input": "kitten\nsitting",
"expectedOutput": "230",
"recipeConfig": [
{
"op": "Levenshtein Distance",
"args": [
"\\n", 10, 100, 1000,
],
},
],
},
{
"name": "Levenshtein Distance: varied costs 2",
"input": "kitten\nsitting",
"expectedOutput": "1020",
"recipeConfig": [
{
"op": "Levenshtein Distance",
"args": [
"\\n", 1000, 100, 10,
],
},
],
},
{
"name": "Levenshtein Distance: another delimiter",
"input": "kitten sitting",
"expectedOutput": "3",
"recipeConfig": [
{
"op": "Levenshtein Distance",
"args": [
" ", 1, 1, 1,
],
},
],
},
{
"name": "Levenshtein Distance: too few samples",
"input": "kitten",
"expectedOutput": "Incorrect number of samples. Check your input and/or delimiter.",
"recipeConfig": [
{
"op": "Levenshtein Distance",
"args": [
"\\n", 1, 1, 1,
],
},
],
},
{
"name": "Levenshtein Distance: too many samples",
"input": "kitten\nsitting\nkitchen",
"expectedOutput": "Incorrect number of samples. Check your input and/or delimiter.",
"recipeConfig": [
{
"op": "Levenshtein Distance",
"args": [
"\\n", 1, 1, 1,
],
},
],
},
{
"name": "Levenshtein Distance: negative insertion cost",
"input": "kitten\nsitting",
"expectedOutput": "Negative costs are not allowed.",
"recipeConfig": [
{
"op": "Levenshtein Distance",
"args": [
"\\n", -1, 1, 1,
],
},
],
},
{
"name": "Levenshtein Distance: negative deletion cost",
"input": "kitten\nsitting",
"expectedOutput": "Negative costs are not allowed.",
"recipeConfig": [
{
"op": "Levenshtein Distance",
"args": [
"\\n", 1, -1, 1,
],
},
],
},
{
"name": "Levenshtein Distance: negative substitution cost",
"input": "kitten\nsitting",
"expectedOutput": "Negative costs are not allowed.",
"recipeConfig": [
{
"op": "Levenshtein Distance",
"args": [
"\\n", 1, 1, -1,
],
},
],
},
{
"name": "Levenshtein Distance: cost zero",
"input": "kitten\nsitting",
"expectedOutput": "0",
"recipeConfig": [
{
"op": "Levenshtein Distance",
"args": [
"\\n", 0, 0, 0,
],
},
],
},
]);

View File

@@ -0,0 +1,33 @@
/**
* @author mikecat
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
"name": "Swap Case: basic example",
"input": "Hello, World!",
"expectedOutput": "hELLO, wORLD!",
"recipeConfig": [
{
"op": "Swap case",
"args": [
],
},
],
},
{
"name": "Swap Case: empty input",
"input": "",
"expectedOutput": "",
"recipeConfig": [
{
"op": "Swap case",
"args": [
],
},
],
},
]);

View File

@@ -114,6 +114,8 @@ module.exports = {
}
},
module: {
// argon2-browser loads argon2.wasm by itself, so Webpack should not load it
noParse: /argon2\.wasm$/,
rules: [
{
test: /\.m?js$/,
@@ -133,6 +135,12 @@ module.exports = {
additionalCode: "var jQuery = false;"
}
},
{
// Load argon2.wasm as base64-encoded binary file expected by argon2-browser
test: /argon2\.wasm$/,
loader: "base64-loader",
type: "javascript/auto"
},
{
test: /prime.worker.min.js$/,
type: "asset/source"