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

Compare commits

...

73 Commits

Author SHA1 Message Date
a3957273
411f78d27a Merge pull request #2011 from bartvanandel/feat/1216-1531-upgrade-uuid 2025-05-12 16:44:22 +01:00
a3957273
7ed7fca3ad Merge branch 'master' into feat/1216-1531-upgrade-uuid 2025-05-12 16:24:53 +01:00
a3957273
5d3353189b Merge pull request #2015 from bartvanandel/fix/use-default-index-in-option-transform 2025-05-12 16:24:35 +01:00
a3957273
f92238bf04 Merge pull request #2023 from xumptex/feature/add-BLAKE3 2025-05-12 16:14:00 +01:00
a3957273
2b1ceef6a3 Merge pull request #2025 from ericli-splunk/patch-1 2025-05-12 16:06:53 +01:00
a3957273
f4e73eef54 Merge pull request #1986 from Odyhibit/master 2025-05-12 16:05:42 +01:00
gchqdev364
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
a3957273
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 Das
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
a3957273
06f1982acf Merge pull request #2038 from GCHQDeveloper94872/Issue-2036-Safari-load-bug 2025-05-12 15:04:14 +01:00
es45411
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
GCHQDeveloper94872
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
es45411
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
es45411
66d445c5ef Add GenerateAllChecksums operation
* Add GenerateAllChecksums operation
* Remove checksums from GenerateAllHashes operation
2025-05-12 12:29:33 +01:00
jg42526
b2045e5bd8 Merge pull request #2035 from jg42526/checksum/xor
XOR Checksum operation added
2025-05-12 12:01:29 +01:00
a3957273
64a4bfeadf Merge pull request #1897 from sw5678/master 2025-05-12 12:00:34 +01:00
jg42526
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
a3957273
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
sw5678
7ca472279c Merge branch 'gchq:master' into master 2025-05-12 09:42:30 +01:00
a3957273
670721f1f6 Merge pull request #2031 from PathToLife/patch-1 2025-05-12 09:25:34 +01:00
a3957273
3c5eea5dfb Merge pull request #1587 from jonking-ajar/feat/jsonata-operation 2025-05-12 09:24:54 +01:00
a3957273
497e2a9d45 Merge pull request #1992 from kenduguay1/push-input-through-postmessage 2025-05-12 09:23:53 +01:00
sw5678
e4a59c6990 Merge branch 'gchq:master' into master 2025-05-12 09:02:32 +01:00
kenduguay1
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
PathToLife
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 Bloom
0a94c4a7c9 Merge branch 'master' into master 2025-04-22 23:33:28 -05:00
ericli-splunk
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
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
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
victorlpgazolli
e0bdde89c4 testing only class default value 2025-04-04 10:24:46 +02:00
victorlpgazolli
68db8e93b7 ref assert validation uuid tests 2025-04-04 10:24:46 +02:00
victorlpgazolli
9069d8e3ec ref uuid tests 2025-04-04 10:24:46 +02:00
victorlpgazolli
e146636250 add more uuid tests 2025-04-04 10:24:45 +02:00
victorlpgazolli
c0af2a9eb5 add analyse uuid category 2025-04-04 10:24:45 +02:00
victorlpgazolli
ae5648ede1 add analyse uuid version 2025-04-04 10:24:45 +02:00
victorlpgazolli
197d6735d2 ref generate uuid versions v1, v3, v4 and v5 2025-04-04 10:24:45 +02:00
victorlpgazolli
75b52bef6d add uuid dependency 2025-04-04 10:24:45 +02:00
kenduguay1
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
Odyhibit
2c32a64bfe Remove trim from rail fence. 2025-02-21 20:40:37 -06: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
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
sw5678
95f6c4c5d5 Added alternating caps functionality 2024-09-12 15:40:54 +01:00
Thomas Weißschuh
3e8c5d945c Add "XOR Checksum" operation 2023-02-27 15:12:38 +00:00
35 changed files with 2613 additions and 115 deletions

View File

@@ -92,6 +92,5 @@ jobs:
- name: Publish to NPM
uses: JS-DevTools/npm-publish@v1
if: false
with:
token: ${{ secrets.NPM_TOKEN }}
token: ${{ secrets.NPM_TOKEN }}

View File

@@ -29,8 +29,7 @@ RUN npm run build
#########################################
# We are using Github Actions: redhat-actions/buildah-build@v2 which needs manual selection of arch in base image
# Remove TARGETARCH if docker buildx is supported in the CI release as --platform=$TARGETPLATFORM will be automatically set
ARG TARGETARCH
ARG TARGETPLATFORM
FROM ${TARGETARCH}/nginx:stable-alpine AS cyberchef
FROM --platform=${TARGETPLATFORM} nginx:stable-alpine AS cyberchef
COPY --from=builder /app/build/prod /usr/share/nginx/html/

48
package-lock.json generated
View File

@@ -46,6 +46,7 @@
"file-saver": "^2.0.5",
"flat": "^6.0.1",
"geodesy": "1.1.3",
"hash-wasm": "^4.12.0",
"highlight.js": "^11.9.0",
"ieee754": "^1.2.1",
"jimp": "^0.22.12",
@@ -54,6 +55,7 @@
"js-sha3": "^0.9.3",
"jsesc": "^3.0.2",
"json5": "^2.2.3",
"jsonata": "^2.0.3",
"jsonpath-plus": "^9.0.0",
"jsonwebtoken": "8.5.1",
"jsqr": "^1.4.0",
@@ -94,6 +96,7 @@
"ua-parser-js": "^1.0.38",
"unorm": "^1.6.0",
"utf8": "^3.0.0",
"uuid": "^11.1.0",
"vkbeautify": "^0.99.3",
"xpath": "0.0.34",
"xregexp": "^5.1.1",
@@ -10940,6 +10943,11 @@
"node": ">= 0.10"
}
},
"node_modules/hash-wasm": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/hash-wasm/-/hash-wasm-4.12.0.tgz",
"integrity": "sha512-+/2B2rYLb48I/evdOIhP+K/DD2ca2fgBjp6O+GBEnCDk2e4rpeXIK8GvIyRPjTezgmWn9gmKwkQjjx6BtqDHVQ=="
},
"node_modules/hash.js": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
@@ -12464,6 +12472,14 @@
"node": ">=6"
}
},
"node_modules/jsonata": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.6.tgz",
"integrity": "sha512-WhQB5tXQ32qjkx2GYHFw2XbL90u+LLzjofAYwi+86g6SyZeXHz9F1Q0amy3dWRYczshOC3Haok9J4pOCgHtwyQ==",
"engines": {
"node": ">= 8"
}
},
"node_modules/jsonpath-plus": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-9.0.0.tgz",
@@ -13876,6 +13892,15 @@
"node": ">=8"
}
},
"node_modules/nightwatch/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true,
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/nightwatch/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
@@ -16819,6 +16844,15 @@
"node": ">=0.8.0"
}
},
"node_modules/sockjs/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true,
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/socks": {
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
@@ -18106,13 +18140,15 @@
}
},
"node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true,
"license": "MIT",
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
"integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"bin": {
"uuid": "dist/bin/uuid"
"uuid": "dist/esm/bin/uuid"
}
},
"node_modules/v8flags": {

View File

@@ -132,6 +132,7 @@
"file-saver": "^2.0.5",
"flat": "^6.0.1",
"geodesy": "1.1.3",
"hash-wasm": "^4.12.0",
"highlight.js": "^11.9.0",
"ieee754": "^1.2.1",
"jimp": "^0.22.12",
@@ -140,6 +141,7 @@
"js-sha3": "^0.9.3",
"jsesc": "^3.0.2",
"json5": "^2.2.3",
"jsonata": "^2.0.3",
"jsonpath-plus": "^9.0.0",
"jsonwebtoken": "8.5.1",
"jsqr": "^1.4.0",
@@ -180,6 +182,7 @@
"ua-parser-js": "^1.0.38",
"unorm": "^1.6.0",
"utf8": "^3.0.0",
"uuid": "^11.1.0",
"vkbeautify": "^0.99.3",
"xpath": "0.0.34",
"xregexp": "^5.1.1",

View File

@@ -294,6 +294,7 @@
"To Upper case",
"To Lower case",
"Swap case",
"Alternating Caps",
"To Case Insensitive Regex",
"From Case Insensitive Regex",
"Add line numbers",
@@ -369,6 +370,7 @@
"Regular expression",
"XPath expression",
"JPath expression",
"Jsonata Query",
"CSS selector",
"Extract EXIF",
"Extract ID3",
@@ -404,6 +406,7 @@
"name": "Hashing",
"ops": [
"Analyse hash",
"Generate all checksums",
"Generate all hashes",
"MD2",
"MD4",
@@ -422,6 +425,7 @@
"Snefru",
"BLAKE2b",
"BLAKE2s",
"BLAKE3",
"GOST Hash",
"Streebog",
"SSDEEP",
@@ -446,7 +450,8 @@
"Adler-32 Checksum",
"Luhn Checksum",
"CRC Checksum",
"TCP/IP Checksum"
"TCP/IP Checksum",
"XOR Checksum"
]
},
{
@@ -545,6 +550,7 @@
"Pseudo-Random Number Generator",
"Generate De Bruijn Sequence",
"Generate UUID",
"Analyse UUID",
"Generate TOTP",
"Generate HOTP",
"Generate QR Code",

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;

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;

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;

View File

@@ -9,6 +9,7 @@ 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
@@ -59,6 +60,11 @@ class ECDSAVerify extends Operation {
name: "Message",
type: "text",
value: ""
},
{
name: "Message format",
type: "option",
value: ["Raw", "Hex", "Base64"]
}
];
}
@@ -70,7 +76,7 @@ class ECDSAVerify extends Operation {
*/
run(input, args) {
let inputFormat = args[0];
const [, mdAlgo, keyPem, msg] = args;
const [, mdAlgo, keyPem, msg, msgFormat] = args;
if (keyPem.replace("-----BEGIN PUBLIC KEY-----", "").length === 0) {
throw new OperationError("Please enter a public key.");
@@ -145,7 +151,8 @@ class ECDSAVerify extends Operation {
throw new OperationError("Provided key is not a public key.");
}
sig.init(key);
sig.updateString(msg);
const messageStr = Utils.convertToByteString(msg, msgFormat);
sig.updateString(messageStr);
const result = sig.verify(signatureASN1Hex);
return result ? "Verified OK" : "Verification Failure";
}

View File

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

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,7 +65,21 @@ 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})?",
// 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 = "";

View File

@@ -0,0 +1,254 @@
/**
* @author r4mos [2k95ljkhg@mozmail.com]
* @copyright Crown Copyright 2025
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import Adler32Checksum from "./Adler32Checksum.mjs";
import CRCChecksum from "./CRCChecksum.mjs";
import Fletcher8Checksum from "./Fletcher8Checksum.mjs";
import Fletcher16Checksum from "./Fletcher16Checksum.mjs";
import Fletcher32Checksum from "./Fletcher32Checksum.mjs";
import Fletcher64Checksum from "./Fletcher64Checksum.mjs";
/**
* Generate all checksums operation
*/
class GenerateAllChecksums extends Operation {
/**
* GenerateAllChecksums constructor
*/
constructor() {
super();
this.name = "Generate all checksums";
this.module = "Crypto";
this.description = "Generates all available checksums for the input.";
this.infoURL = "https://wikipedia.org/wiki/Checksum";
this.inputType = "ArrayBuffer";
this.outputType = "string";
this.args = [
{
name: "Length (bits)",
type: "option",
value: [
"All", "3", "4", "5", "6", "7", "8", "10", "11", "12", "13", "14", "15", "16", "17", "21", "24", "30", "31", "32", "40", "64", "82"
]
},
{
name: "Include names",
type: "boolean",
value: true
},
];
const adler32 = new Adler32Checksum;
const crc = new CRCChecksum;
const fletcher8 = new Fletcher8Checksum;
const fletcher16 = new Fletcher16Checksum;
const fletcher32 = new Fletcher32Checksum;
const fletcher64 = new Fletcher64Checksum;
this.checksums = [
{name: "CRC-3/GSM", algo: crc, params: ["CRC-3/GSM"]},
{name: "CRC-3/ROHC", algo: crc, params: ["CRC-3/ROHC"]},
{name: "CRC-4/G-704", algo: crc, params: ["CRC-4/G-704"]},
{name: "CRC-4/INTERLAKEN", algo: crc, params: ["CRC-4/INTERLAKEN"]},
{name: "CRC-4/ITU", algo: crc, params: ["CRC-4/ITU"]},
{name: "CRC-5/EPC", algo: crc, params: ["CRC-5/EPC"]},
{name: "CRC-5/EPC-C1G2", algo: crc, params: ["CRC-5/EPC-C1G2"]},
{name: "CRC-5/G-704", algo: crc, params: ["CRC-5/G-704"]},
{name: "CRC-5/ITU", algo: crc, params: ["CRC-5/ITU"]},
{name: "CRC-5/USB", algo: crc, params: ["CRC-5/USB"]},
{name: "CRC-6/CDMA2000-A", algo: crc, params: ["CRC-6/CDMA2000-A"]},
{name: "CRC-6/CDMA2000-B", algo: crc, params: ["CRC-6/CDMA2000-B"]},
{name: "CRC-6/DARC", algo: crc, params: ["CRC-6/DARC"]},
{name: "CRC-6/G-704", algo: crc, params: ["CRC-6/G-704"]},
{name: "CRC-6/GSM", algo: crc, params: ["CRC-6/GSM"]},
{name: "CRC-6/ITU", algo: crc, params: ["CRC-6/ITU"]},
{name: "CRC-7/MMC", algo: crc, params: ["CRC-7/MMC"]},
{name: "CRC-7/ROHC", algo: crc, params: ["CRC-7/ROHC"]},
{name: "CRC-7/UMTS", algo: crc, params: ["CRC-7/UMTS"]},
{name: "CRC-8", algo: crc, params: ["CRC-8"]},
{name: "CRC-8/8H2F", algo: crc, params: ["CRC-8/8H2F"]},
{name: "CRC-8/AES", algo: crc, params: ["CRC-8/AES"]},
{name: "CRC-8/AUTOSAR", algo: crc, params: ["CRC-8/AUTOSAR"]},
{name: "CRC-8/BLUETOOTH", algo: crc, params: ["CRC-8/BLUETOOTH"]},
{name: "CRC-8/CDMA2000", algo: crc, params: ["CRC-8/CDMA2000"]},
{name: "CRC-8/DARC", algo: crc, params: ["CRC-8/DARC"]},
{name: "CRC-8/DVB-S2", algo: crc, params: ["CRC-8/DVB-S2"]},
{name: "CRC-8/EBU", algo: crc, params: ["CRC-8/EBU"]},
{name: "CRC-8/GSM-A", algo: crc, params: ["CRC-8/GSM-A"]},
{name: "CRC-8/GSM-B", algo: crc, params: ["CRC-8/GSM-B"]},
{name: "CRC-8/HITAG", algo: crc, params: ["CRC-8/HITAG"]},
{name: "CRC-8/I-432-1", algo: crc, params: ["CRC-8/I-432-1"]},
{name: "CRC-8/I-CODE", algo: crc, params: ["CRC-8/I-CODE"]},
{name: "CRC-8/ITU", algo: crc, params: ["CRC-8/ITU"]},
{name: "CRC-8/LTE", algo: crc, params: ["CRC-8/LTE"]},
{name: "CRC-8/MAXIM", algo: crc, params: ["CRC-8/MAXIM"]},
{name: "CRC-8/MAXIM-DOW", algo: crc, params: ["CRC-8/MAXIM-DOW"]},
{name: "CRC-8/MIFARE-MAD", algo: crc, params: ["CRC-8/MIFARE-MAD"]},
{name: "CRC-8/NRSC-5", algo: crc, params: ["CRC-8/NRSC-5"]},
{name: "CRC-8/OPENSAFETY", algo: crc, params: ["CRC-8/OPENSAFETY"]},
{name: "CRC-8/ROHC", algo: crc, params: ["CRC-8/ROHC"]},
{name: "CRC-8/SAE-J1850", algo: crc, params: ["CRC-8/SAE-J1850"]},
{name: "CRC-8/SAE-J1850-ZERO", algo: crc, params: ["CRC-8/SAE-J1850-ZERO"]},
{name: "CRC-8/SMBUS", algo: crc, params: ["CRC-8/SMBUS"]},
{name: "CRC-8/TECH-3250", algo: crc, params: ["CRC-8/TECH-3250"]},
{name: "CRC-8/WCDMA", algo: crc, params: ["CRC-8/WCDMA"]},
{name: "Fletcher-8", algo: fletcher8, params: []},
{name: "CRC-10/ATM", algo: crc, params: ["CRC-10/ATM"]},
{name: "CRC-10/CDMA2000", algo: crc, params: ["CRC-10/CDMA2000"]},
{name: "CRC-10/GSM", algo: crc, params: ["CRC-10/GSM"]},
{name: "CRC-10/I-610", algo: crc, params: ["CRC-10/I-610"]},
{name: "CRC-11/FLEXRAY", algo: crc, params: ["CRC-11/FLEXRAY"]},
{name: "CRC-11/UMTS", algo: crc, params: ["CRC-11/UMTS"]},
{name: "CRC-12/3GPP", algo: crc, params: ["CRC-12/3GPP"]},
{name: "CRC-12/CDMA2000", algo: crc, params: ["CRC-12/CDMA2000"]},
{name: "CRC-12/DECT", algo: crc, params: ["CRC-12/DECT"]},
{name: "CRC-12/GSM", algo: crc, params: ["CRC-12/GSM"]},
{name: "CRC-12/UMTS", algo: crc, params: ["CRC-12/UMTS"]},
{name: "CRC-13/BBC", algo: crc, params: ["CRC-13/BBC"]},
{name: "CRC-14/DARC", algo: crc, params: ["CRC-14/DARC"]},
{name: "CRC-14/GSM", algo: crc, params: ["CRC-14/GSM"]},
{name: "CRC-15/CAN", algo: crc, params: ["CRC-15/CAN"]},
{name: "CRC-15/MPT1327", algo: crc, params: ["CRC-15/MPT1327"]},
{name: "CRC-16", algo: crc, params: ["CRC-16"]},
{name: "CRC-16/A", algo: crc, params: ["CRC-16/A"]},
{name: "CRC-16/ACORN", algo: crc, params: ["CRC-16/ACORN"]},
{name: "CRC-16/ARC", algo: crc, params: ["CRC-16/ARC"]},
{name: "CRC-16/AUG-CCITT", algo: crc, params: ["CRC-16/AUG-CCITT"]},
{name: "CRC-16/AUTOSAR", algo: crc, params: ["CRC-16/AUTOSAR"]},
{name: "CRC-16/B", algo: crc, params: ["CRC-16/B"]},
{name: "CRC-16/BLUETOOTH", algo: crc, params: ["CRC-16/BLUETOOTH"]},
{name: "CRC-16/BUYPASS", algo: crc, params: ["CRC-16/BUYPASS"]},
{name: "CRC-16/CCITT", algo: crc, params: ["CRC-16/CCITT"]},
{name: "CRC-16/CCITT-FALSE", algo: crc, params: ["CRC-16/CCITT-FALSE"]},
{name: "CRC-16/CCITT-TRUE", algo: crc, params: ["CRC-16/CCITT-TRUE"]},
{name: "CRC-16/CCITT-ZERO", algo: crc, params: ["CRC-16/CCITT-ZERO"]},
{name: "CRC-16/CDMA2000", algo: crc, params: ["CRC-16/CDMA2000"]},
{name: "CRC-16/CMS", algo: crc, params: ["CRC-16/CMS"]},
{name: "CRC-16/DARC", algo: crc, params: ["CRC-16/DARC"]},
{name: "CRC-16/DDS-110", algo: crc, params: ["CRC-16/DDS-110"]},
{name: "CRC-16/DECT-R", algo: crc, params: ["CRC-16/DECT-R"]},
{name: "CRC-16/DECT-X", algo: crc, params: ["CRC-16/DECT-X"]},
{name: "CRC-16/DNP", algo: crc, params: ["CRC-16/DNP"]},
{name: "CRC-16/EN-13757", algo: crc, params: ["CRC-16/EN-13757"]},
{name: "CRC-16/EPC", algo: crc, params: ["CRC-16/EPC"]},
{name: "CRC-16/EPC-C1G2", algo: crc, params: ["CRC-16/EPC-C1G2"]},
{name: "CRC-16/GENIBUS", algo: crc, params: ["CRC-16/GENIBUS"]},
{name: "CRC-16/GSM", algo: crc, params: ["CRC-16/GSM"]},
{name: "CRC-16/I-CODE", algo: crc, params: ["CRC-16/I-CODE"]},
{name: "CRC-16/IBM", algo: crc, params: ["CRC-16/IBM"]},
{name: "CRC-16/IBM-3740", algo: crc, params: ["CRC-16/IBM-3740"]},
{name: "CRC-16/IBM-SDLC", algo: crc, params: ["CRC-16/IBM-SDLC"]},
{name: "CRC-16/IEC-61158-2", algo: crc, params: ["CRC-16/IEC-61158-2"]},
{name: "CRC-16/ISO-HDLC", algo: crc, params: ["CRC-16/ISO-HDLC"]},
{name: "CRC-16/ISO-IEC-14443-3-A", algo: crc, params: ["CRC-16/ISO-IEC-14443-3-A"]},
{name: "CRC-16/ISO-IEC-14443-3-B", algo: crc, params: ["CRC-16/ISO-IEC-14443-3-B"]},
{name: "CRC-16/KERMIT", algo: crc, params: ["CRC-16/KERMIT"]},
{name: "CRC-16/LHA", algo: crc, params: ["CRC-16/LHA"]},
{name: "CRC-16/LJ1200", algo: crc, params: ["CRC-16/LJ1200"]},
{name: "CRC-16/LTE", algo: crc, params: ["CRC-16/LTE"]},
{name: "CRC-16/M17", algo: crc, params: ["CRC-16/M17"]},
{name: "CRC-16/MAXIM", algo: crc, params: ["CRC-16/MAXIM"]},
{name: "CRC-16/MAXIM-DOW", algo: crc, params: ["CRC-16/MAXIM-DOW"]},
{name: "CRC-16/MCRF4XX", algo: crc, params: ["CRC-16/MCRF4XX"]},
{name: "CRC-16/MODBUS", algo: crc, params: ["CRC-16/MODBUS"]},
{name: "CRC-16/NRSC-5", algo: crc, params: ["CRC-16/NRSC-5"]},
{name: "CRC-16/OPENSAFETY-A", algo: crc, params: ["CRC-16/OPENSAFETY-A"]},
{name: "CRC-16/OPENSAFETY-B", algo: crc, params: ["CRC-16/OPENSAFETY-B"]},
{name: "CRC-16/PROFIBUS", algo: crc, params: ["CRC-16/PROFIBUS"]},
{name: "CRC-16/RIELLO", algo: crc, params: ["CRC-16/RIELLO"]},
{name: "CRC-16/SPI-FUJITSU", algo: crc, params: ["CRC-16/SPI-FUJITSU"]},
{name: "CRC-16/T10-DIF", algo: crc, params: ["CRC-16/T10-DIF"]},
{name: "CRC-16/TELEDISK", algo: crc, params: ["CRC-16/TELEDISK"]},
{name: "CRC-16/TMS37157", algo: crc, params: ["CRC-16/TMS37157"]},
{name: "CRC-16/UMTS", algo: crc, params: ["CRC-16/UMTS"]},
{name: "CRC-16/USB", algo: crc, params: ["CRC-16/USB"]},
{name: "CRC-16/V-41-LSB", algo: crc, params: ["CRC-16/V-41-LSB"]},
{name: "CRC-16/V-41-MSB", algo: crc, params: ["CRC-16/V-41-MSB"]},
{name: "CRC-16/VERIFONE", algo: crc, params: ["CRC-16/VERIFONE"]},
{name: "CRC-16/X-25", algo: crc, params: ["CRC-16/X-25"]},
{name: "CRC-16/XMODEM", algo: crc, params: ["CRC-16/XMODEM"]},
{name: "CRC-16/ZMODEM", algo: crc, params: ["CRC-16/ZMODEM"]},
{name: "Fletcher-16", algo: fletcher16, params: []},
{name: "CRC-17/CAN-FD", algo: crc, params: ["CRC-17/CAN-FD"]},
{name: "CRC-21/CAN-FD", algo: crc, params: ["CRC-21/CAN-FD"]},
{name: "CRC-24/BLE", algo: crc, params: ["CRC-24/BLE"]},
{name: "CRC-24/FLEXRAY-A", algo: crc, params: ["CRC-24/FLEXRAY-A"]},
{name: "CRC-24/FLEXRAY-B", algo: crc, params: ["CRC-24/FLEXRAY-B"]},
{name: "CRC-24/INTERLAKEN", algo: crc, params: ["CRC-24/INTERLAKEN"]},
{name: "CRC-24/LTE-A", algo: crc, params: ["CRC-24/LTE-A"]},
{name: "CRC-24/LTE-B", algo: crc, params: ["CRC-24/LTE-B"]},
{name: "CRC-24/OPENPGP", algo: crc, params: ["CRC-24/OPENPGP"]},
{name: "CRC-24/OS-9", algo: crc, params: ["CRC-24/OS-9"]},
{name: "CRC-30/CDMA", algo: crc, params: ["CRC-30/CDMA"]},
{name: "CRC-31/PHILIPS", algo: crc, params: ["CRC-31/PHILIPS"]},
{name: "Adler-32", algo: adler32, params: []},
{name: "CRC-32", algo: crc, params: ["CRC-32"]},
{name: "CRC-32/AAL5", algo: crc, params: ["CRC-32/AAL5"]},
{name: "CRC-32/ADCCP", algo: crc, params: ["CRC-32/ADCCP"]},
{name: "CRC-32/AIXM", algo: crc, params: ["CRC-32/AIXM"]},
{name: "CRC-32/AUTOSAR", algo: crc, params: ["CRC-32/AUTOSAR"]},
{name: "CRC-32/BASE91-C", algo: crc, params: ["CRC-32/BASE91-C"]},
{name: "CRC-32/BASE91-D", algo: crc, params: ["CRC-32/BASE91-D"]},
{name: "CRC-32/BZIP2", algo: crc, params: ["CRC-32/BZIP2"]},
{name: "CRC-32/C", algo: crc, params: ["CRC-32/C"]},
{name: "CRC-32/CASTAGNOLI", algo: crc, params: ["CRC-32/CASTAGNOLI"]},
{name: "CRC-32/CD-ROM-EDC", algo: crc, params: ["CRC-32/CD-ROM-EDC"]},
{name: "CRC-32/CKSUM", algo: crc, params: ["CRC-32/CKSUM"]},
{name: "CRC-32/D", algo: crc, params: ["CRC-32/D"]},
{name: "CRC-32/DECT-B", algo: crc, params: ["CRC-32/DECT-B"]},
{name: "CRC-32/INTERLAKEN", algo: crc, params: ["CRC-32/INTERLAKEN"]},
{name: "CRC-32/ISCSI", algo: crc, params: ["CRC-32/ISCSI"]},
{name: "CRC-32/ISO-HDLC", algo: crc, params: ["CRC-32/ISO-HDLC"]},
{name: "CRC-32/JAMCRC", algo: crc, params: ["CRC-32/JAMCRC"]},
{name: "CRC-32/MEF", algo: crc, params: ["CRC-32/MEF"]},
{name: "CRC-32/MPEG-2", algo: crc, params: ["CRC-32/MPEG-2"]},
{name: "CRC-32/NVME", algo: crc, params: ["CRC-32/NVME"]},
{name: "CRC-32/PKZIP", algo: crc, params: ["CRC-32/PKZIP"]},
{name: "CRC-32/POSIX", algo: crc, params: ["CRC-32/POSIX"]},
{name: "CRC-32/Q", algo: crc, params: ["CRC-32/Q"]},
{name: "CRC-32/SATA", algo: crc, params: ["CRC-32/SATA"]},
{name: "CRC-32/V-42", algo: crc, params: ["CRC-32/V-42"]},
{name: "CRC-32/XFER", algo: crc, params: ["CRC-32/XFER"]},
{name: "CRC-32/XZ", algo: crc, params: ["CRC-32/XZ"]},
{name: "Fletcher-32", algo: fletcher32, params: []},
{name: "CRC-40/GSM", algo: crc, params: ["CRC-40/GSM"]},
{name: "CRC-64/ECMA-182", algo: crc, params: ["CRC-64/ECMA-182"]},
{name: "CRC-64/GO-ECMA", algo: crc, params: ["CRC-64/GO-ECMA"]},
{name: "CRC-64/GO-ISO", algo: crc, params: ["CRC-64/GO-ISO"]},
{name: "CRC-64/MS", algo: crc, params: ["CRC-64/MS"]},
{name: "CRC-64/NVME", algo: crc, params: ["CRC-64/NVME"]},
{name: "CRC-64/REDIS", algo: crc, params: ["CRC-64/REDIS"]},
{name: "CRC-64/WE", algo: crc, params: ["CRC-64/WE"]},
{name: "CRC-64/XZ", algo: crc, params: ["CRC-64/XZ"]},
{name: "Fletcher-64", algo: fletcher64, params: []},
{name: "CRC-82/DARC", algo: crc, params: ["CRC-82/DARC"]}
];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const [length, includeNames] = args;
let output = "";
this.checksums.forEach(checksum => {
const checksumLength = checksum.name.match(new RegExp("-(\\d{1,2})(\\/|$)"))[1];
if (length === "All" || length === checksumLength) {
const value = checksum.algo.run(new Uint8Array(input), checksum.params || []);
output += includeNames ?
`${checksum.name}:${" ".repeat(25-checksum.name.length)}${value}\n`:
`${value}\n`;
}
});
return output;
}
}
export default GenerateAllChecksums;

View File

@@ -22,12 +22,6 @@ import HAS160 from "./HAS160.mjs";
import Whirlpool from "./Whirlpool.mjs";
import SSDEEP from "./SSDEEP.mjs";
import CTPH from "./CTPH.mjs";
import Fletcher8Checksum from "./Fletcher8Checksum.mjs";
import Fletcher16Checksum from "./Fletcher16Checksum.mjs";
import Fletcher32Checksum from "./Fletcher32Checksum.mjs";
import Fletcher64Checksum from "./Fletcher64Checksum.mjs";
import Adler32Checksum from "./Adler32Checksum.mjs";
import CRCChecksum from "./CRCChecksum.mjs";
import BLAKE2b from "./BLAKE2b.mjs";
import BLAKE2s from "./BLAKE2s.mjs";
import Streebog from "./Streebog.mjs";
@@ -112,16 +106,6 @@ class GenerateAllHashes extends Operation {
{name: "SSDEEP", algo: (new SSDEEP()), inputType: "str"},
{name: "CTPH", algo: (new CTPH()), inputType: "str"}
];
this.checksums = [
{name: "Fletcher-8", algo: (new Fletcher8Checksum), inputType: "byteArray", params: []},
{name: "Fletcher-16", algo: (new Fletcher16Checksum), inputType: "byteArray", params: []},
{name: "Fletcher-32", algo: (new Fletcher32Checksum), inputType: "byteArray", params: []},
{name: "Fletcher-64", algo: (new Fletcher64Checksum), inputType: "byteArray", params: []},
{name: "Adler-32", algo: (new Adler32Checksum), inputType: "byteArray", params: []},
{name: "CRC-8", algo: (new CRCChecksum), inputType: "arrayBuffer", params: ["CRC-8"]},
{name: "CRC-16", algo: (new CRCChecksum), inputType: "arrayBuffer", params: ["CRC-16"]},
{name: "CRC-32", algo: (new CRCChecksum), inputType: "arrayBuffer", params: ["CRC-32"]}
];
}
/**
@@ -142,14 +126,6 @@ class GenerateAllHashes extends Operation {
output += this.formatDigest(digest, length, includeNames, hash.name);
});
if (length === "All") {
output += "\nChecksums:\n";
this.checksums.forEach(checksum => {
digest = this.executeAlgo(checksum.algo, checksum.inputType, checksum.params || []);
output += this.formatDigest(digest, length, includeNames, checksum.name);
});
}
return output;
}

View File

@@ -5,8 +5,8 @@
*/
import Operation from "../Operation.mjs";
import crypto from "crypto";
import * as uuid from "uuid";
import OperationError from "../errors/OperationError.mjs";
/**
* Generate UUID operation
*/
@@ -20,11 +20,38 @@ class GenerateUUID extends Operation {
this.name = "Generate UUID";
this.module = "Crypto";
this.description = "Generates an RFC 4122 version 4 compliant Universally Unique Identifier (UUID), also known as a Globally Unique Identifier (GUID).<br><br>A version 4 UUID relies on random numbers, in this case generated using <code>window.crypto</code> if available and falling back to <code>Math.random</code> if not.";
this.description =
"Generates an RFC 9562 (formerly RFC 4122) compliant Universally Unique Identifier (UUID), " +
"also known as a Globally Unique Identifier (GUID).<br>" +
"<br>" +
"We currently support generating the following UUID versions:<br>" +
"<ul>" +
"<li><strong>v1</strong>: Timestamp-based</li>" +
"<li><strong>v3</strong>: Namespace w/ MD5</li>" +
"<li><strong>v4</strong>: Random (default)</li>" +
"<li><strong>v5</strong>: Namespace w/ SHA-1</li>" +
"<li><strong>v6</strong>: Timestamp, reordered</li>" +
"<li><strong>v7</strong>: Unix Epoch time-based</li>" +
"</ul>" +
"UUIDs are generated using the <a href='https://npmjs.org/uuid/'><code>uuid</code><a> package.<br>";
this.infoURL = "https://wikipedia.org/wiki/Universally_unique_identifier";
this.inputType = "string";
this.outputType = "string";
this.args = [];
this.args = [
{
name: "Version",
hint: "UUID version",
type: "option",
value: ["v1", "v3", "v4", "v5", "v6", "v7"],
defaultIndex: 2,
},
{
name: "Namespace",
hint: "UUID namespace (UUID; valid for v3 and v5)",
type: "string",
value: "1b671a64-40d5-491e-99b0-da01ff1f3341"
}
];
}
/**
@@ -33,16 +60,17 @@ class GenerateUUID extends Operation {
* @returns {string}
*/
run(input, args) {
const buf = new Uint32Array(4).map(() => {
return crypto.randomBytes(4).readUInt32BE(0, true);
});
let i = 0;
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
const r = (buf[i >> 3] >> ((i % 8) * 4)) & 0xf,
v = c === "x" ? r : (r & 0x3 | 0x8);
i++;
return v.toString(16);
});
const [version, namespace] = args;
const hasDesiredVersion = typeof uuid[version] === "function";
if (!hasDesiredVersion) throw new OperationError("Invalid UUID version");
const requiresNamespace = ["v3", "v5"].includes(version);
if (!requiresNamespace) return uuid[version]();
const hasValidNamespace = typeof namespace === "string" && uuid.validate(namespace);
if (!hasValidNamespace) throw new OperationError("Invalid UUID namespace");
return uuid[version](input, namespace);
}
}

View File

@@ -0,0 +1,65 @@
/**
* @author Jon K (jon@ajarsoftware.com)
* @copyright Crown Copyright 2016
* @license Apache-2.0
*/
import jsonata from "jsonata";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* Jsonata Query operation
*/
class JsonataQuery extends Operation {
/**
* JsonataQuery constructor
*/
constructor() {
super();
this.name = "Jsonata Query";
this.module = "Code";
this.description =
"Query and transform JSON data with a jsonata query.";
this.infoURL = "https://docs.jsonata.org/overview.html";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Query",
type: "text",
value: "string",
},
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
async run(input, args) {
const [query] = args;
let result, jsonObj;
try {
jsonObj = JSON.parse(input);
} catch (err) {
throw new OperationError(`Invalid input JSON: ${err.message}`);
}
try {
const expression = jsonata(query);
result = await expression.evaluate(jsonObj);
} catch (err) {
throw new OperationError(
`Invalid Jsonata Expression: ${err.message}`
);
}
return JSON.stringify(result === undefined ? "" : result);
}
}
export default JsonataQuery;

View File

@@ -72,7 +72,7 @@ class RailFenceCipherDecode extends Operation {
}
}
return plaintext.join("").trim();
return plaintext.join("");
}
}

View File

@@ -66,7 +66,7 @@ class RailFenceCipherEncode extends Operation {
rows[rowIdx] += plaintext[pos];
}
return rows.join("").trim();
return rows.join("");
}
}

View File

@@ -23,7 +23,13 @@ class URLDecode extends Operation {
this.infoURL = "https://wikipedia.org/wiki/Percent-encoding";
this.inputType = "string";
this.outputType = "string";
this.args = [];
this.args = [
{
"name": "Treat \"+\" as space",
"type": "boolean",
"value": true
},
];
this.checks = [
{
pattern: ".*(?:%[\\da-f]{2}.*){4}",
@@ -39,7 +45,8 @@ class URLDecode extends Operation {
* @returns {string}
*/
run(input, args) {
const data = input.replace(/\+/g, "%20");
const plusIsSpace = args[0];
const data = plusIsSpace ? input.replace(/\+/g, "%20") : input;
try {
return decodeURIComponent(data);
} catch (err) {

View File

@@ -0,0 +1,59 @@
/**
* @author Thomas Weißschuh [thomas@t-8ch.de]
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import { toHex } from "../lib/Hex.mjs";
/**
* XOR Checksum operation
*/
class XORChecksum extends Operation {
/**
* XORChecksum constructor
*/
constructor() {
super();
this.name = "XOR Checksum";
this.module = "Crypto";
this.description = "XOR Checksum splits the input into blocks of a configurable size and performs the XOR operation on these blocks.";
this.infoURL = "https://wikipedia.org/wiki/XOR";
this.inputType = "ArrayBuffer";
this.outputType = "string";
this.args = [
{
name: "Blocksize",
type: "number",
value: 4
},
];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const blocksize = args[0];
input = new Uint8Array(input);
const res = Array(blocksize);
res.fill(0);
for (const chunk of Utils.chunked(input, blocksize)) {
for (let i = 0; i < blocksize; i++) {
res[i] ^= chunk[i];
}
}
return toHex(res, "");
}
}
export default XORChecksum;

View File

@@ -74,11 +74,11 @@ function transformArgs(opArgsList, newArgs) {
return opArgs.map((arg) => {
if (arg.type === "option") {
// pick default option if not already chosen
return typeof arg.value === "string" ? arg.value : arg.value[0];
return typeof arg.value === "string" ? arg.value : arg.value[arg.defaultIndex ?? 0];
}
if (arg.type === "editableOption") {
return typeof arg.value === "string" ? arg.value : arg.value[0].value;
return typeof arg.value === "string" ? arg.value : arg.value[arg.defaultIndex ?? 0].value;
}
if (arg.type === "toggleString") {

View File

@@ -125,6 +125,7 @@ class Manager {
window.addEventListener("focus", this.window.windowFocus.bind(this.window));
window.addEventListener("statechange", this.app.stateChange.bind(this.app));
window.addEventListener("popstate", this.app.popState.bind(this.app));
window.addEventListener("message", this.input.handlePostMessage.bind(this.input));
// Controls
document.getElementById("bake").addEventListener("click", this.controls.bakeClick.bind(this.controls));

View File

@@ -1,23 +1,26 @@
[
{
"@context": "http://schema.org",
"@type": "Organization",
"url": "https://gchq.github.io/CyberChef/",
"logo": "https://gchq.github.io/CyberChef/images/cyberchef-128x128.png",
"sameAs": [
"https://github.com/gchq/CyberChef",
"https://www.npmjs.com/package/cyberchef"
"@graph": [
{
"@type": "Organization",
"url": "https://gchq.github.io/CyberChef/",
"logo": "https://gchq.github.io/CyberChef/images/cyberchef-128x128.png",
"sameAs": [
"https://github.com/gchq/CyberChef",
"https://www.npmjs.com/package/cyberchef"
]
},
{
"@type": "WebSite",
"url": "https://gchq.github.io/CyberChef/",
"name": "CyberChef",
"potentialAction": {
"@type": "SearchAction",
"target": "https://gchq.github.io/CyberChef/?op={operation_search_term}",
"query-input": "required name=operation_search_term"
}
}
]
},
{
"@context": "http://schema.org",
"@type": "WebSite",
"url": "https://gchq.github.io/CyberChef/",
"name": "CyberChef",
"potentialAction": {
"@type": "SearchAction",
"target": "https://gchq.github.io/CyberChef/?op={operation_search_term}",
"query-input": "required name=operation_search_term"
}
}
]
]

View File

@@ -1654,6 +1654,23 @@ class InputWaiter {
this.changeTab(inputNum, this.app.options.syncTabs);
}
/**
* Handler for incoming postMessages
* If the events data has a `type` property set to `dataSubmit`
* the value property is set to the current input
* @param {event} e
* @param {object} e.data
* @param {string} e.data.type - the type of request, currently the only value is "dataSubmit"
* @param {string} e.data.value - the value of the message
*/
handlePostMessage(e) {
log.debug(e);
if ("data" in e && "id" in e.data && "value" in e.data) {
if (e.data.id === "setInput") {
this.setInput(e.data.value);
}
}
}
}
export default InputWaiter;

View File

@@ -580,10 +580,25 @@ Password: 282760`;
assert.strictEqual(result.toString().substr(0, 37), "-----BEGIN PGP PRIVATE KEY BLOCK-----");
}),
it("Generate UUID", () => {
const result = chef.generateUUID();
assert.ok(result.toString());
assert.strictEqual(result.toString().length, 36);
...[1, 3, 4, 5, 6, 7].map(version => it(`Generate UUID v${version}`, () => {
const result = chef.generateUUID("", { "version": `v${version}` }).toString();
assert.ok(result);
assert.strictEqual(result.length, 36);
})),
...[1, 3, 4, 5, 6, 7].map(version => it(`Analyze UUID v${version}`, () => {
const uuid = chef.generateUUID("", { "version": `v${version}` }).toString();
const result = chef.analyseUUID(uuid).toString();
const expected = `UUID version: ${version}`;
assert.strictEqual(result, expected);
})),
it("Generate UUID using defaults", () => {
const uuid = chef.generateUUID();
assert.ok(uuid);
const analysis = chef.analyseUUID(uuid).toString();
assert.strictEqual(analysis, "UUID version: 4");
}),
it("Gzip, Gunzip", () => {

View File

@@ -11,13 +11,11 @@
* @license Apache-2.0
*/
import {
setLongTestFailure,
logTestReport,
} from "../lib/utils.mjs";
import { setLongTestFailure, logTestReport } from "../lib/utils.mjs";
import TestRegister from "../lib/TestRegister.mjs";
import "./tests/AESKeyWrap.mjs";
import "./tests/AlternatingCaps.mjs";
import "./tests/AvroToJSON.mjs";
import "./tests/BaconCipher.mjs";
import "./tests/Base32.mjs";
@@ -31,6 +29,7 @@ import "./tests/BCD.mjs";
import "./tests/BitwiseOp.mjs";
import "./tests/BLAKE2b.mjs";
import "./tests/BLAKE2s.mjs";
import "./tests/BLAKE3.mjs";
import "./tests/Bombe.mjs";
import "./tests/BSON.mjs";
import "./tests/ByteRepr.mjs";
@@ -67,11 +66,13 @@ import "./tests/ELFInfo.mjs";
import "./tests/Enigma.mjs";
import "./tests/ExtractEmailAddresses.mjs";
import "./tests/ExtractHashes.mjs";
import "./tests/ExtractIPAddresses.mjs";
import "./tests/Float.mjs";
import "./tests/FileTree.mjs";
import "./tests/FletcherChecksum.mjs";
import "./tests/Fork.mjs";
import "./tests/FromDecimal.mjs";
import "./tests/GenerateAllChecksums.mjs";
import "./tests/GenerateAllHashes.mjs";
import "./tests/GenerateDeBruijnSequence.mjs";
import "./tests/GetAllCasings.mjs";
@@ -89,6 +90,7 @@ import "./tests/IndexOfCoincidence.mjs";
import "./tests/JA3Fingerprint.mjs";
import "./tests/JA4.mjs";
import "./tests/JA3SFingerprint.mjs";
import "./tests/Jsonata.mjs";
import "./tests/JSONBeautify.mjs";
import "./tests/JSONMinify.mjs";
import "./tests/JSONtoCSV.mjs";
@@ -163,6 +165,7 @@ import "./tests/TranslateDateTimeFormat.mjs";
import "./tests/Typex.mjs";
import "./tests/UnescapeString.mjs";
import "./tests/Unicode.mjs";
import "./tests/URLEncodeDecode.mjs";
import "./tests/RSA.mjs";
import "./tests/CBOREncode.mjs";
import "./tests/CBORDecode.mjs";
@@ -181,14 +184,14 @@ const testStatus = {
allTestsPassing: true,
counts: {
total: 0,
}
},
};
setLongTestFailure();
const logOpsTestReport = logTestReport.bind(null, testStatus);
(async function() {
(async function () {
const results = await TestRegister.runTests();
logOpsTestReport(results);
})();

View File

@@ -0,0 +1,19 @@
/* @author sw5678
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
"name": "AlternatingCaps: Basic Example",
"input": "Hello, world!",
"expectedOutput": "hElLo, WoRlD!",
"recipeConfig": [
{
"op": "Alternating Caps",
"args": []
},
],
}
]);

View File

@@ -0,0 +1,55 @@
/**
* BLAKE3 tests.
* @author xumptex [xumptex@outlook.fr]
* @copyright Crown Copyright 2025
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "BLAKE3: 8 - Hello world",
input: "Hello world",
expectedOutput: "e7e6fb7d2869d109",
recipeConfig: [
{ "op": "BLAKE3",
"args": [8, ""] }
]
},
{
name: "BLAKE3: 16 - Hello world 2",
input: "Hello world 2",
expectedOutput: "2a3df5fe5f0d3fcdd995fc203c7f7c52",
recipeConfig: [
{ "op": "BLAKE3",
"args": [16, ""] }
]
},
{
name: "BLAKE3: 32 - Hello world",
input: "Hello world",
expectedOutput: "e7e6fb7d2869d109b62cdb1227208d4016cdaa0af6603d95223c6a698137d945",
recipeConfig: [
{ "op": "BLAKE3",
"args": [32, ""] }
]
},
{
name: "BLAKE3: Key Test",
input: "Hello world",
expectedOutput: "59dd23ac9d025690",
recipeConfig: [
{ "op": "BLAKE3",
"args": [8, "ThiskeyisexactlythirtytwoBytesLo"] }
]
},
{
name: "BLAKE3: Key Test 2",
input: "Hello world",
expectedOutput: "c8302c9634c1da42",
recipeConfig: [
{ "op": "BLAKE3",
"args": [8, "ThiskeyisexactlythirtytwoByteslo"] }
]
}
]);

View File

@@ -528,4 +528,15 @@ TestRegister.addTests([
}
],
},
{
name: "Rail Fence Cipher Encode: Normal with Offset with Spaces",
input: "No one expects the spanish Inquisition.",
expectedOutput: " e n ut.ooeepcstesaihIqiiinNnxthpsnso",
recipeConfig: [
{
"op": "Rail Fence Cipher Encode",
"args": [3, 2]
}
],
},
]);

View File

@@ -6,7 +6,10 @@
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
import { ASCII_TEXT } from "../../samples/Ciphers.mjs";
import {ALL_BYTES, ASCII_TEXT, UTF8_TEXT} from "../../samples/Ciphers.mjs";
const SOME_HEX_BYTES = "cdb23f958e018418621d9e489b7bba0f0c481f604eba2eb1ea35e38f99490cc0";
const SOME_BASE64_BYTES = "zbI/lY4BhBhiHZ5Im3u6DwxIH2BOui6x6jXjj5lJDMA=";
const P256 = {
// openssl ecparam -name prime256v1 -genkey -noout -out p256.priv.key
@@ -104,7 +107,7 @@ TestRegister.addTests([
},
{
"op": "ECDSA Verify",
"args": ["ASN.1 HEX", "MD5", P256.publicKey, ASCII_TEXT]
"args": ["ASN.1 HEX", "MD5", P256.publicKey, ASCII_TEXT, "Raw"]
}
]
},
@@ -119,7 +122,7 @@ TestRegister.addTests([
},
{
"op": "ECDSA Verify",
"args": ["ASN.1 HEX", "SHA-1", P256.publicKey, ASCII_TEXT]
"args": ["ASN.1 HEX", "SHA-1", P256.publicKey, ASCII_TEXT, "Raw"]
}
]
},
@@ -134,7 +137,7 @@ TestRegister.addTests([
},
{
"op": "ECDSA Verify",
"args": ["ASN.1 HEX", "SHA-256", P256.publicKey, ASCII_TEXT]
"args": ["ASN.1 HEX", "SHA-256", P256.publicKey, ASCII_TEXT, "Raw"]
}
]
},
@@ -149,7 +152,7 @@ TestRegister.addTests([
},
{
"op": "ECDSA Verify",
"args": ["ASN.1 HEX", "SHA-384", P256.publicKey, ASCII_TEXT]
"args": ["ASN.1 HEX", "SHA-384", P256.publicKey, ASCII_TEXT, "Raw"]
}
]
},
@@ -164,7 +167,7 @@ TestRegister.addTests([
},
{
"op": "ECDSA Verify",
"args": ["ASN.1 HEX", "SHA-512", P256.publicKey, ASCII_TEXT]
"args": ["ASN.1 HEX", "SHA-512", P256.publicKey, ASCII_TEXT, "Raw"]
}
]
},
@@ -179,7 +182,7 @@ TestRegister.addTests([
},
{
"op": "ECDSA Verify",
"args": ["ASN.1 HEX", "SHA-256", P256.publicKey, ASCII_TEXT]
"args": ["ASN.1 HEX", "SHA-256", P256.publicKey, ASCII_TEXT, "Raw"]
}
]
},
@@ -194,7 +197,7 @@ TestRegister.addTests([
},
{
"op": "ECDSA Verify",
"args": ["ASN.1 HEX", "SHA-384", P384.publicKey, ASCII_TEXT]
"args": ["ASN.1 HEX", "SHA-384", P384.publicKey, ASCII_TEXT, "Raw"]
}
]
},
@@ -209,7 +212,7 @@ TestRegister.addTests([
},
{
"op": "ECDSA Verify",
"args": ["ASN.1 HEX", "SHA-512", P521.publicKey, ASCII_TEXT]
"args": ["ASN.1 HEX", "SHA-512", P521.publicKey, ASCII_TEXT, "Raw"]
}
]
},
@@ -246,7 +249,7 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "ECDSA Verify",
"args": ["Auto", "SHA-256", P256.publicKey, ASCII_TEXT]
"args": ["Auto", "SHA-256", P256.publicKey, ASCII_TEXT, "Raw"]
}
]
},
@@ -257,7 +260,7 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "ECDSA Verify",
"args": ["Auto", "SHA-256", P256.publicKey, ASCII_TEXT]
"args": ["Auto", "SHA-256", P256.publicKey, ASCII_TEXT, "Raw"]
}
]
},
@@ -268,7 +271,7 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "ECDSA Verify",
"args": ["Auto", "SHA-256", P256.publicKey, ASCII_TEXT]
"args": ["Auto", "SHA-256", P256.publicKey, ASCII_TEXT, "Raw"]
}
]
},
@@ -279,7 +282,7 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "ECDSA Verify",
"args": ["Auto", "SHA-256", P256.publicKey, ASCII_TEXT]
"args": ["Auto", "SHA-256", P256.publicKey, ASCII_TEXT, "Raw"]
}
]
},
@@ -290,7 +293,7 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "ECDSA Verify",
"args": ["Auto", "SHA-256", P256.publicKey, ASCII_TEXT]
"args": ["Auto", "SHA-256", P256.publicKey, ASCII_TEXT, "Raw"]
}
]
},
@@ -301,7 +304,7 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "ECDSA Verify",
"args": ["Auto", "SHA-256", P256.publicKey, ASCII_TEXT]
"args": ["Auto", "SHA-256", P256.publicKey, ASCII_TEXT, "Raw"]
}
]
},
@@ -312,7 +315,7 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "ECDSA Verify",
"args": ["ASN.1 HEX", "SHA-256", P256.privateKeyPkcs1, ASCII_TEXT]
"args": ["ASN.1 HEX", "SHA-256", P256.privateKeyPkcs1, ASCII_TEXT, "Raw"]
}
]
},
@@ -323,7 +326,7 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "ECDSA Verify",
"args": ["ASN.1 HEX", "SHA-256", PEM_PUB_RSA512, ASCII_TEXT]
"args": ["ASN.1 HEX", "SHA-256", PEM_PUB_RSA512, ASCII_TEXT, "Raw"]
}
]
},
@@ -460,5 +463,73 @@ TestRegister.addTests([
"args": ["Auto", "Raw JSON"]
}
]
},
{
name: "ECDSA Sign/Verify: P-256 with SHA256 UTF8",
input: UTF8_TEXT,
expectedOutput: "Verified OK",
recipeConfig: [
{
"op": "ECDSA Sign",
"args": [P256.privateKeyPkcs1, "SHA-256", "ASN.1 HEX"]
},
{
"op": "ECDSA Verify",
"args": ["ASN.1 HEX", "SHA-256", P256.publicKey, UTF8_TEXT, "Raw"]
}
]
},
{
name: "ECDSA Sign/Verify: P-256 with SHA256 bytes raw",
input: ALL_BYTES,
expectedOutput: "Verified OK",
recipeConfig: [
{
"op": "ECDSA Sign",
"args": [P256.privateKeyPkcs1, "SHA-256", "ASN.1 HEX"]
},
{
"op": "ECDSA Verify",
"args": ["ASN.1 HEX", "SHA-256", P256.publicKey, ALL_BYTES, "Raw"]
}
]
},
{
name: "ECDSA Sign/Verify: P-256 with SHA256 bytes hex",
input: SOME_HEX_BYTES,
expectedOutput: "Verified OK",
recipeConfig: [
{
"op": "From Hex",
"args": ["Auto"]
},
{
"op": "ECDSA Sign",
"args": [P256.privateKeyPkcs1, "SHA-256", "ASN.1 HEX"]
},
{
"op": "ECDSA Verify",
"args": ["ASN.1 HEX", "SHA-256", P256.publicKey, SOME_HEX_BYTES, "Hex"]
}
]
},
{
name: "ECDSA Sign/Verify: P-256 with SHA256 bytes Base64",
input: SOME_BASE64_BYTES,
expectedOutput: "Verified OK",
recipeConfig: [
{
"op": "From Base64",
"args": ["A-Za-z0-9+/=", true]
},
{
"op": "ECDSA Sign",
"args": [P256.privateKeyPkcs1, "SHA-256", "ASN.1 HEX"]
},
{
"op": "ECDSA Verify",
"args": ["ASN.1 HEX", "SHA-256", P256.publicKey, SOME_BASE64_BYTES, "Base64"]
}
]
}
]);

View File

@@ -0,0 +1,133 @@
/**
* ExtractIPAddresses tests.
*
* @author gchqdev365 [gchqdev365@outlook.com]
* @copyright Crown Copyright 2025
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "ExtractIPAddress All Zeros",
input: "0.0.0.0",
expectedOutput: "0.0.0.0",
recipeConfig: [
{
"op": "Extract IP addresses",
"args": [true, true, false, false, false, false]
},
],
},
{
name: "ExtractIPAddress All 10s",
input: "10.10.10.10",
expectedOutput: "10.10.10.10",
recipeConfig: [
{
"op": "Extract IP addresses",
"args": [true, true, false, false, false, false]
},
],
},
{
name: "ExtractIPAddress All 10s",
input: "100.100.100.100",
expectedOutput: "100.100.100.100",
recipeConfig: [
{
"op": "Extract IP addresses",
"args": [true, true, false, false, false, false]
},
],
},
{
name: "ExtractIPAddress 255s",
input: "255.255.255.255",
expectedOutput: "255.255.255.255",
recipeConfig: [
{
"op": "Extract IP addresses",
"args": [true, true, false, false, false, false]
},
],
},
{
name: "ExtractIPAddress double digits",
input: "10.10.10.10 25.25.25.25 99.99.99.99",
expectedOutput: "10.10.10.10\n25.25.25.25\n99.99.99.99",
recipeConfig: [
{
"op": "Extract IP addresses",
"args": [true, true, false, false, false, false]
},
],
},
{
name: "ExtractIPAddress 256 in middle",
input: "255.256.255.255 255.255.256.255",
expectedOutput: "",
recipeConfig: [
{
"op": "Extract IP addresses",
"args": [true, true, false, false, false, false]
},
],
},
{
name: "ExtractIPAddress 256 at each end",
input: "256.255.255.255 255.255.255.256",
expectedOutput: "",
recipeConfig: [
{
"op": "Extract IP addresses",
"args": [true, true, false, false, false, false]
},
],
},
{
name: "ExtractIPAddress silly example",
input: "710.65.0.456",
expectedOutput: "",
recipeConfig: [
{
"op": "Extract IP addresses",
"args": [true, true, false, false, false, false]
},
],
},
{
name: "ExtractIPAddress longer dotted decimal",
input: "1.2.3.4.5.6.7.8",
expectedOutput: "1.2.3.4\n5.6.7.8",
recipeConfig: [
{
"op": "Extract IP addresses",
"args": [true, true, false, false, false, false]
},
],
},
{
name: "ExtractIPAddress octal valid",
input: "01.01.01.01 0123.0123.0123.0123 0377.0377.0377.0377",
expectedOutput: "01.01.01.01\n0123.0123.0123.0123\n0377.0377.0377.0377",
recipeConfig: [
{
"op": "Extract IP addresses",
"args": [true, true, false, false, false, false]
},
],
},
{
name: "ExtractIPAddress octal invalid",
input: "0378.01.01.01 03.0377.2.3",
expectedOutput: "",
recipeConfig: [
{
"op": "Extract IP addresses",
"args": [true, true, false, false, false, false]
},
],
},
]);

View File

@@ -0,0 +1,805 @@
/**
* GenerateAllChecksums tests.
*
* @author r4mos [2k95ljkhg@mozmail.com]
* @copyright Crown Copyright 2025
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
const CHECK_STRING = "123456789";
TestRegister.addTests([
{
name: "Full generate all checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-3/GSM: 4
CRC-3/ROHC: 6
CRC-4/G-704: 7
CRC-4/INTERLAKEN: b
CRC-4/ITU: 7
CRC-5/EPC: 00
CRC-5/EPC-C1G2: 00
CRC-5/G-704: 07
CRC-5/ITU: 07
CRC-5/USB: 19
CRC-6/CDMA2000-A: 0d
CRC-6/CDMA2000-B: 3b
CRC-6/DARC: 26
CRC-6/G-704: 06
CRC-6/GSM: 13
CRC-6/ITU: 06
CRC-7/MMC: 75
CRC-7/ROHC: 53
CRC-7/UMTS: 61
CRC-8: f4
CRC-8/8H2F: df
CRC-8/AES: 97
CRC-8/AUTOSAR: df
CRC-8/BLUETOOTH: 26
CRC-8/CDMA2000: da
CRC-8/DARC: 15
CRC-8/DVB-S2: bc
CRC-8/EBU: 97
CRC-8/GSM-A: 37
CRC-8/GSM-B: 94
CRC-8/HITAG: b4
CRC-8/I-432-1: a1
CRC-8/I-CODE: 7e
CRC-8/ITU: a1
CRC-8/LTE: ea
CRC-8/MAXIM: a1
CRC-8/MAXIM-DOW: a1
CRC-8/MIFARE-MAD: 99
CRC-8/NRSC-5: f7
CRC-8/OPENSAFETY: 3e
CRC-8/ROHC: d0
CRC-8/SAE-J1850: 4b
CRC-8/SAE-J1850-ZERO: 37
CRC-8/SMBUS: f4
CRC-8/TECH-3250: 97
CRC-8/WCDMA: 25
Fletcher-8: 0c
CRC-10/ATM: 199
CRC-10/CDMA2000: 233
CRC-10/GSM: 12a
CRC-10/I-610: 199
CRC-11/FLEXRAY: 5a3
CRC-11/UMTS: 061
CRC-12/3GPP: daf
CRC-12/CDMA2000: d4d
CRC-12/DECT: f5b
CRC-12/GSM: b34
CRC-12/UMTS: daf
CRC-13/BBC: 04fa
CRC-14/DARC: 082d
CRC-14/GSM: 30ae
CRC-15/CAN: 059e
CRC-15/MPT1327: 2566
CRC-16: bb3d
CRC-16/A: bf05
CRC-16/ACORN: 31c3
CRC-16/ARC: bb3d
CRC-16/AUG-CCITT: e5cc
CRC-16/AUTOSAR: 29b1
CRC-16/B: 906e
CRC-16/BLUETOOTH: 2189
CRC-16/BUYPASS: fee8
CRC-16/CCITT: 2189
CRC-16/CCITT-FALSE: 29b1
CRC-16/CCITT-TRUE: 2189
CRC-16/CCITT-ZERO: 31c3
CRC-16/CDMA2000: 4c06
CRC-16/CMS: aee7
CRC-16/DARC: d64e
CRC-16/DDS-110: 9ecf
CRC-16/DECT-R: 007e
CRC-16/DECT-X: 007f
CRC-16/DNP: ea82
CRC-16/EN-13757: c2b7
CRC-16/EPC: d64e
CRC-16/EPC-C1G2: d64e
CRC-16/GENIBUS: d64e
CRC-16/GSM: ce3c
CRC-16/I-CODE: d64e
CRC-16/IBM: bb3d
CRC-16/IBM-3740: 29b1
CRC-16/IBM-SDLC: 906e
CRC-16/IEC-61158-2: a819
CRC-16/ISO-HDLC: 906e
CRC-16/ISO-IEC-14443-3-A: bf05
CRC-16/ISO-IEC-14443-3-B: 906e
CRC-16/KERMIT: 2189
CRC-16/LHA: bb3d
CRC-16/LJ1200: bdf4
CRC-16/LTE: 31c3
CRC-16/M17: 772b
CRC-16/MAXIM: 44c2
CRC-16/MAXIM-DOW: 44c2
CRC-16/MCRF4XX: 6f91
CRC-16/MODBUS: 4b37
CRC-16/NRSC-5: a066
CRC-16/OPENSAFETY-A: 5d38
CRC-16/OPENSAFETY-B: 20fe
CRC-16/PROFIBUS: a819
CRC-16/RIELLO: 63d0
CRC-16/SPI-FUJITSU: e5cc
CRC-16/T10-DIF: d0db
CRC-16/TELEDISK: 0fb3
CRC-16/TMS37157: 26b1
CRC-16/UMTS: fee8
CRC-16/USB: b4c8
CRC-16/V-41-LSB: 2189
CRC-16/V-41-MSB: 31c3
CRC-16/VERIFONE: fee8
CRC-16/X-25: 906e
CRC-16/XMODEM: 31c3
CRC-16/ZMODEM: 31c3
Fletcher-16: 1ede
CRC-17/CAN-FD: 04f03
CRC-21/CAN-FD: 0ed841
CRC-24/BLE: c25a56
CRC-24/FLEXRAY-A: 7979bd
CRC-24/FLEXRAY-B: 1f23b8
CRC-24/INTERLAKEN: b4f3e6
CRC-24/LTE-A: cde703
CRC-24/LTE-B: 23ef52
CRC-24/OPENPGP: 21cf02
CRC-24/OS-9: 200fa5
CRC-30/CDMA: 04c34abf
CRC-31/PHILIPS: 0ce9e46c
Adler-32: 091e01de
CRC-32: cbf43926
CRC-32/AAL5: fc891918
CRC-32/ADCCP: cbf43926
CRC-32/AIXM: 3010bf7f
CRC-32/AUTOSAR: 1697d06a
CRC-32/BASE91-C: e3069283
CRC-32/BASE91-D: 87315576
CRC-32/BZIP2: fc891918
CRC-32/C: e3069283
CRC-32/CASTAGNOLI: e3069283
CRC-32/CD-ROM-EDC: 6ec2edc4
CRC-32/CKSUM: 765e7680
CRC-32/D: 87315576
CRC-32/DECT-B: fc891918
CRC-32/INTERLAKEN: e3069283
CRC-32/ISCSI: e3069283
CRC-32/ISO-HDLC: cbf43926
CRC-32/JAMCRC: 340bc6d9
CRC-32/MEF: d2c22f51
CRC-32/MPEG-2: 0376e6e7
CRC-32/NVME: e3069283
CRC-32/PKZIP: cbf43926
CRC-32/POSIX: 765e7680
CRC-32/Q: 3010bf7f
CRC-32/SATA: cf72afe8
CRC-32/V-42: cbf43926
CRC-32/XFER: bd0be338
CRC-32/XZ: cbf43926
Fletcher-32: df09d509
CRC-40/GSM: d4164fc646
CRC-64/ECMA-182: 6c40df5f0b497347
CRC-64/GO-ECMA: 995dc9bbdf1939fa
CRC-64/GO-ISO: b90956c775a41001
CRC-64/MS: 75d4b74f024eceea
CRC-64/NVME: ae8b14860a799888
CRC-64/REDIS: e9c6d914c4b8d9ca
CRC-64/WE: 62ec59e3f1a4f00a
CRC-64/XZ: 995dc9bbdf1939fa
Fletcher-64: 0d0803376c6a689f
CRC-82/DARC: 09ea83f625023801fd612
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["All", true]
}
]
},
{
name: "Full generate all checksums without name",
input: CHECK_STRING,
expectedOutput: `4
6
7
b
7
00
00
07
07
19
0d
3b
26
06
13
06
75
53
61
f4
df
97
df
26
da
15
bc
97
37
94
b4
a1
7e
a1
ea
a1
a1
99
f7
3e
d0
4b
37
f4
97
25
0c
199
233
12a
199
5a3
061
daf
d4d
f5b
b34
daf
04fa
082d
30ae
059e
2566
bb3d
bf05
31c3
bb3d
e5cc
29b1
906e
2189
fee8
2189
29b1
2189
31c3
4c06
aee7
d64e
9ecf
007e
007f
ea82
c2b7
d64e
d64e
d64e
ce3c
d64e
bb3d
29b1
906e
a819
906e
bf05
906e
2189
bb3d
bdf4
31c3
772b
44c2
44c2
6f91
4b37
a066
5d38
20fe
a819
63d0
e5cc
d0db
0fb3
26b1
fee8
b4c8
2189
31c3
fee8
906e
31c3
31c3
1ede
04f03
0ed841
c25a56
7979bd
1f23b8
b4f3e6
cde703
23ef52
21cf02
200fa5
04c34abf
0ce9e46c
091e01de
cbf43926
fc891918
cbf43926
3010bf7f
1697d06a
e3069283
87315576
fc891918
e3069283
e3069283
6ec2edc4
765e7680
87315576
fc891918
e3069283
e3069283
cbf43926
340bc6d9
d2c22f51
0376e6e7
e3069283
cbf43926
765e7680
3010bf7f
cf72afe8
cbf43926
bd0be338
cbf43926
df09d509
d4164fc646
6c40df5f0b497347
995dc9bbdf1939fa
b90956c775a41001
75d4b74f024eceea
ae8b14860a799888
e9c6d914c4b8d9ca
62ec59e3f1a4f00a
995dc9bbdf1939fa
0d0803376c6a689f
09ea83f625023801fd612
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["All", false]
}
]
},
{
name: "Full generate 3 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-3/GSM: 4
CRC-3/ROHC: 6
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["3", true]
}
]
},
{
name: "Full generate 4 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-4/G-704: 7
CRC-4/INTERLAKEN: b
CRC-4/ITU: 7
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["4", true]
}
]
},
{
name: "Full generate 5 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-5/EPC: 00
CRC-5/EPC-C1G2: 00
CRC-5/G-704: 07
CRC-5/ITU: 07
CRC-5/USB: 19
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["5", true]
}
]
},
{
name: "Full generate 6 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-6/CDMA2000-A: 0d
CRC-6/CDMA2000-B: 3b
CRC-6/DARC: 26
CRC-6/G-704: 06
CRC-6/GSM: 13
CRC-6/ITU: 06
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["6", true]
}
]
},
{
name: "Full generate 7 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-7/MMC: 75
CRC-7/ROHC: 53
CRC-7/UMTS: 61
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["7", true]
}
]
},
{
name: "Full generate 8 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-8: f4
CRC-8/8H2F: df
CRC-8/AES: 97
CRC-8/AUTOSAR: df
CRC-8/BLUETOOTH: 26
CRC-8/CDMA2000: da
CRC-8/DARC: 15
CRC-8/DVB-S2: bc
CRC-8/EBU: 97
CRC-8/GSM-A: 37
CRC-8/GSM-B: 94
CRC-8/HITAG: b4
CRC-8/I-432-1: a1
CRC-8/I-CODE: 7e
CRC-8/ITU: a1
CRC-8/LTE: ea
CRC-8/MAXIM: a1
CRC-8/MAXIM-DOW: a1
CRC-8/MIFARE-MAD: 99
CRC-8/NRSC-5: f7
CRC-8/OPENSAFETY: 3e
CRC-8/ROHC: d0
CRC-8/SAE-J1850: 4b
CRC-8/SAE-J1850-ZERO: 37
CRC-8/SMBUS: f4
CRC-8/TECH-3250: 97
CRC-8/WCDMA: 25
Fletcher-8: 0c
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["8", true]
}
]
},
{
name: "Full generate 10 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-10/ATM: 199
CRC-10/CDMA2000: 233
CRC-10/GSM: 12a
CRC-10/I-610: 199
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["10", true]
}
]
},
{
name: "Full generate 11 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-11/FLEXRAY: 5a3
CRC-11/UMTS: 061
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["11", true]
}
]
},
{
name: "Full generate 12 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-12/3GPP: daf
CRC-12/CDMA2000: d4d
CRC-12/DECT: f5b
CRC-12/GSM: b34
CRC-12/UMTS: daf
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["12", true]
}
]
},
{
name: "Full generate 13 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-13/BBC: 04fa
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["13", true]
}
]
},
{
name: "Full generate 14 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-14/DARC: 082d
CRC-14/GSM: 30ae
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["14", true]
}
]
},
{
name: "Full generate 15 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-15/CAN: 059e
CRC-15/MPT1327: 2566
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["15", true]
}
]
},
{
name: "Full generate 16 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-16: bb3d
CRC-16/A: bf05
CRC-16/ACORN: 31c3
CRC-16/ARC: bb3d
CRC-16/AUG-CCITT: e5cc
CRC-16/AUTOSAR: 29b1
CRC-16/B: 906e
CRC-16/BLUETOOTH: 2189
CRC-16/BUYPASS: fee8
CRC-16/CCITT: 2189
CRC-16/CCITT-FALSE: 29b1
CRC-16/CCITT-TRUE: 2189
CRC-16/CCITT-ZERO: 31c3
CRC-16/CDMA2000: 4c06
CRC-16/CMS: aee7
CRC-16/DARC: d64e
CRC-16/DDS-110: 9ecf
CRC-16/DECT-R: 007e
CRC-16/DECT-X: 007f
CRC-16/DNP: ea82
CRC-16/EN-13757: c2b7
CRC-16/EPC: d64e
CRC-16/EPC-C1G2: d64e
CRC-16/GENIBUS: d64e
CRC-16/GSM: ce3c
CRC-16/I-CODE: d64e
CRC-16/IBM: bb3d
CRC-16/IBM-3740: 29b1
CRC-16/IBM-SDLC: 906e
CRC-16/IEC-61158-2: a819
CRC-16/ISO-HDLC: 906e
CRC-16/ISO-IEC-14443-3-A: bf05
CRC-16/ISO-IEC-14443-3-B: 906e
CRC-16/KERMIT: 2189
CRC-16/LHA: bb3d
CRC-16/LJ1200: bdf4
CRC-16/LTE: 31c3
CRC-16/M17: 772b
CRC-16/MAXIM: 44c2
CRC-16/MAXIM-DOW: 44c2
CRC-16/MCRF4XX: 6f91
CRC-16/MODBUS: 4b37
CRC-16/NRSC-5: a066
CRC-16/OPENSAFETY-A: 5d38
CRC-16/OPENSAFETY-B: 20fe
CRC-16/PROFIBUS: a819
CRC-16/RIELLO: 63d0
CRC-16/SPI-FUJITSU: e5cc
CRC-16/T10-DIF: d0db
CRC-16/TELEDISK: 0fb3
CRC-16/TMS37157: 26b1
CRC-16/UMTS: fee8
CRC-16/USB: b4c8
CRC-16/V-41-LSB: 2189
CRC-16/V-41-MSB: 31c3
CRC-16/VERIFONE: fee8
CRC-16/X-25: 906e
CRC-16/XMODEM: 31c3
CRC-16/ZMODEM: 31c3
Fletcher-16: 1ede
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["16", true]
}
]
},
{
name: "Full generate 17 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-17/CAN-FD: 04f03
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["17", true]
}
]
},
{
name: "Full generate 21 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-21/CAN-FD: 0ed841
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["21", true]
}
]
},
{
name: "Full generate 24 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-24/BLE: c25a56
CRC-24/FLEXRAY-A: 7979bd
CRC-24/FLEXRAY-B: 1f23b8
CRC-24/INTERLAKEN: b4f3e6
CRC-24/LTE-A: cde703
CRC-24/LTE-B: 23ef52
CRC-24/OPENPGP: 21cf02
CRC-24/OS-9: 200fa5
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["24", true]
}
]
},
{
name: "Full generate 30 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-30/CDMA: 04c34abf
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["30", true]
}
]
},
{
name: "Full generate 31 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-31/PHILIPS: 0ce9e46c
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["31", true]
}
]
},
{
name: "Full generate 32 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `Adler-32: 091e01de
CRC-32: cbf43926
CRC-32/AAL5: fc891918
CRC-32/ADCCP: cbf43926
CRC-32/AIXM: 3010bf7f
CRC-32/AUTOSAR: 1697d06a
CRC-32/BASE91-C: e3069283
CRC-32/BASE91-D: 87315576
CRC-32/BZIP2: fc891918
CRC-32/C: e3069283
CRC-32/CASTAGNOLI: e3069283
CRC-32/CD-ROM-EDC: 6ec2edc4
CRC-32/CKSUM: 765e7680
CRC-32/D: 87315576
CRC-32/DECT-B: fc891918
CRC-32/INTERLAKEN: e3069283
CRC-32/ISCSI: e3069283
CRC-32/ISO-HDLC: cbf43926
CRC-32/JAMCRC: 340bc6d9
CRC-32/MEF: d2c22f51
CRC-32/MPEG-2: 0376e6e7
CRC-32/NVME: e3069283
CRC-32/PKZIP: cbf43926
CRC-32/POSIX: 765e7680
CRC-32/Q: 3010bf7f
CRC-32/SATA: cf72afe8
CRC-32/V-42: cbf43926
CRC-32/XFER: bd0be338
CRC-32/XZ: cbf43926
Fletcher-32: df09d509
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["32", true]
}
]
},
{
name: "Full generate 40 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-40/GSM: d4164fc646
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["40", true]
}
]
},
{
name: "Full generate 64 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-64/ECMA-182: 6c40df5f0b497347
CRC-64/GO-ECMA: 995dc9bbdf1939fa
CRC-64/GO-ISO: b90956c775a41001
CRC-64/MS: 75d4b74f024eceea
CRC-64/NVME: ae8b14860a799888
CRC-64/REDIS: e9c6d914c4b8d9ca
CRC-64/WE: 62ec59e3f1a4f00a
CRC-64/XZ: 995dc9bbdf1939fa
Fletcher-64: 0d0803376c6a689f
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["64", true]
}
]
},
{
name: "Full generate 82 bits checksums with name",
input: CHECK_STRING,
expectedOutput: `CRC-82/DARC: 09ea83f625023801fd612
`,
recipeConfig: [
{
"op": "Generate all checksums",
"args": ["82", true]
}
]
}
]);

View File

@@ -54,16 +54,6 @@ LM Hash: 01FC5A6BE7BC6929AAD3B435B51404EE
NT Hash: 0CB6948805F797BF2A82807973B89537
SSDEEP: 3:Hn:Hn
CTPH: A:E:E
Checksums:
Fletcher-8: 3d
Fletcher-16: 5dc1
Fletcher-32: 3f5cd9e7
Fletcher-64: 7473657474736574
Adler-32: 045d01c1
CRC-8: b9
CRC-16: f82e
CRC-32: d87f7e0c
`,
recipeConfig: [
{

View File

@@ -0,0 +1,551 @@
/**
* Jsonata Query tests.
*
* @author Jon King [jon@ajarsoftware.com]
*
* @copyright Crown Copyright 2025
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
const INPUT_JSON_OBJECT_WITH_ARRAYS = `{
"FirstName": "Fred",
"Surname": "Smith",
"Age": 28,
"Address": {
"Street": "Hursley Park",
"City": "Winchester",
"Postcode": "SO21 2JN"
},
"Phone": [
{
"type": "home",
"number": "0203 544 1234"
},
{
"type": "office",
"number": "01962 001234"
},
{
"type": "office",
"number": "01962 001235"
},
{
"type": "mobile",
"number": "077 7700 1234"
}
],
"Email": [
{
"type": "work",
"address": ["fred.smith@my-work.com", "fsmith@my-work.com"]
},
{
"type": "home",
"address": ["freddy@my-social.com", "frederic.smith@very-serious.com"]
}
],
"Other": {
"Over 18 ?": true,
"Misc": null,
"Alternative.Address": {
"Street": "Brick Lane",
"City": "London",
"Postcode": "E1 6RF"
}
}
}`;
const INPUT_ARRAY_OF_OBJECTS = `[
{ "ref": [ 1,2 ] },
{ "ref": [ 3,4 ] }
]`;
const INPUT_NUMBER_ARRAY = `{
"Numbers": [1, 2.4, 3.5, 10, 20.9, 30]
}`;
TestRegister.addTests([
{
name: "Jsonata: Returns a JSON string (double quoted)",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '"Smith"',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Surname"],
},
],
},
{
name: "Jsonata: Returns a JSON number",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: "28",
recipeConfig: [
{
op: "Jsonata Query",
args: ["Age"],
},
],
},
{
name: "Jsonata: Field references are separated by '.'",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '"Winchester"',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Address.City"],
},
],
},
{
name: "Jsonata: Matched the path and returns the null value",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: "null",
recipeConfig: [
{
op: "Jsonata Query",
args: ["Other.Misc"],
},
],
},
{
name: "Jsonata: Path not found. Returns nothing",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '""',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Other.DoesntExist"],
},
],
},
{
name: "Jsonata: Field references containing whitespace or reserved tokens can be enclosed in backticks",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: "true",
recipeConfig: [
{
op: "Jsonata Query",
args: ["Other.`Over 18 ?`"],
},
],
},
{
name: "Jsonata: Returns the first item (an object)",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '{"type":"home","number":"0203 544 1234"}',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Phone[0]"],
},
],
},
{
name: "Jsonata: Returns the second item",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '{"type":"office","number":"01962 001234"}',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Phone[1]"],
},
],
},
{
name: "Jsonata: Returns the last item",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '{"type":"mobile","number":"077 7700 1234"}',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Phone[-1]"],
},
],
},
{
name: "Jsonata: Negative indexed count from the end",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '{"type":"office","number":"01962 001235"}',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Phone[-2]"],
},
],
},
{
name: "Jsonata: Doesn't exist - returns nothing",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '""',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Phone[8]"],
},
],
},
{
name: "Jsonata: Selects the number field in the first item",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '"0203 544 1234"',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Phone[0].number"],
},
],
},
{
name: "Jsonata: No index is given to Phone so it selects all of them (the whole array), then it selects all the number fields for each of them",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput:
'["0203 544 1234","01962 001234","01962 001235","077 7700 1234"]',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Phone.number"],
},
],
},
{
name: "Jsonata: Might expect it to just return the first number, but it returns the first number of each of the items selected by Phone",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput:
'["0203 544 1234","01962 001234","01962 001235","077 7700 1234"]',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Phone.number[0]"],
},
],
},
{
name: "Jsonata: Applies the index to the array returned by Phone.number.",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '"0203 544 1234"',
recipeConfig: [
{
op: "Jsonata Query",
args: ["(Phone.number)[0]"],
},
],
},
{
name: "Jsonata: Returns a range of items by creating an array of indexes",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput:
'[{"type":"home","number":"0203 544 1234"},{"type":"office","number":"01962 001234"}]',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Phone[[0..1]]"],
},
],
},
// Predicates
{
name: "Jsonata: Select the Phone items that have a type field that equals 'mobile'",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '{"type":"mobile","number":"077 7700 1234"}',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Phone[type='mobile']"],
},
],
},
{
name: "Jsonata: Select the mobile phone number",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '"077 7700 1234"',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Phone[type='mobile'].number"],
},
],
},
{
name: "Jsonata: Select the office phone numbers - there are two of them",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '["01962 001234","01962 001235"]',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Phone[type='office'].number"],
},
],
},
// Wildcards
{
name: "Jsonata: Select the values of all the fields of 'Address'",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '["Hursley Park","Winchester","SO21 2JN"]',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Address.*"],
},
],
},
{
name: "Jsonata: Select the 'Postcode' value of any child object",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '"SO21 2JN"',
recipeConfig: [
{
op: "Jsonata Query",
args: ["*.Postcode"],
},
],
},
{
name: "Jsonata: Select all Postcode values, regardless of how deeply nested they are in the structure",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '["SO21 2JN","E1 6RF"]',
recipeConfig: [
{
op: "Jsonata Query",
args: ["**.Postcode"],
},
],
},
// String Expressions
{
name: "Jsonata: Concatenate 'FirstName' followed by space followed by 'Surname'",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '"Fred Smith"',
recipeConfig: [
{
op: "Jsonata Query",
args: ["FirstName & ' ' & Surname"],
},
],
},
{
name: "Jsonata: Concatenates the 'Street' and 'City' from the 'Address' object with a comma separator",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '"Hursley Park, Winchester"',
recipeConfig: [
{
op: "Jsonata Query",
args: ["Address.(Street & ', ' & City)"],
},
],
},
{
name: "Jsonata: Casts the operands to strings, if necessary",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: '"50true"',
recipeConfig: [
{
op: "Jsonata Query",
args: ["5&0&true"],
},
],
},
// Numeric Expressions
{
name: "Jsonata: Addition",
input: INPUT_NUMBER_ARRAY,
expectedOutput: "3.4",
recipeConfig: [
{
op: "Jsonata Query",
args: ["Numbers[0] + Numbers[1]"],
},
],
},
{
name: "Jsonata: Subtraction",
input: INPUT_NUMBER_ARRAY,
expectedOutput: "-19.9",
recipeConfig: [
{
op: "Jsonata Query",
args: ["Numbers[0] - Numbers[4]"],
},
],
},
{
name: "Jsonata: Multiplication",
input: INPUT_NUMBER_ARRAY,
expectedOutput: "30",
recipeConfig: [
{
op: "Jsonata Query",
args: ["Numbers[0] * Numbers[5]"],
},
],
},
{
name: "Jsonata: Division",
input: INPUT_NUMBER_ARRAY,
expectedOutput: "0.04784688995215311",
recipeConfig: [
{
op: "Jsonata Query",
args: ["Numbers[0] / Numbers[4]"],
},
],
},
{
name: "Jsonata: Modulus",
input: INPUT_NUMBER_ARRAY,
expectedOutput: "3.5",
recipeConfig: [
{
op: "Jsonata Query",
args: ["Numbers[2] % Numbers[5]"],
},
],
},
{
name: "Jsonata: Equality",
input: INPUT_NUMBER_ARRAY,
expectedOutput: "false",
recipeConfig: [
{
op: "Jsonata Query",
args: ["Numbers[0] = Numbers[5]"],
},
],
},
{
name: "Jsonata: Inequality",
input: INPUT_NUMBER_ARRAY,
expectedOutput: "true",
recipeConfig: [
{
op: "Jsonata Query",
args: ["Numbers[0] != Numbers[4]"],
},
],
},
{
name: "Jsonata: Less than",
input: INPUT_NUMBER_ARRAY,
expectedOutput: "true",
recipeConfig: [
{
op: "Jsonata Query",
args: ["Numbers[0] < Numbers[4]"],
},
],
},
{
name: "Jsonata: Less than or equal to",
input: INPUT_NUMBER_ARRAY,
expectedOutput: "true",
recipeConfig: [
{
op: "Jsonata Query",
args: ["Numbers[0] <= Numbers[4]"],
},
],
},
{
name: "Jsonata: Greater than",
input: INPUT_NUMBER_ARRAY,
expectedOutput: "false",
recipeConfig: [
{
op: "Jsonata Query",
args: ["Numbers[0] > Numbers[4]"],
},
],
},
{
name: "Jsonata: Greater than or equal to",
input: INPUT_NUMBER_ARRAY,
expectedOutput: "false",
recipeConfig: [
{
op: "Jsonata Query",
args: ["Numbers[2] >= Numbers[4]"],
},
],
},
{
name: "Jsonata: Value is contained in",
input: INPUT_JSON_OBJECT_WITH_ARRAYS,
expectedOutput: "true",
recipeConfig: [
{
op: "Jsonata Query",
args: ['"01962 001234" in Phone.number'],
},
],
},
// Boolean Expressions
{
name: "Jsonata: and",
input: INPUT_NUMBER_ARRAY,
expectedOutput: "true",
recipeConfig: [
{
op: "Jsonata Query",
args: ["(Numbers[2] != 0) and (Numbers[5] != Numbers[1])"],
},
],
},
{
name: "Jsonata: or",
input: INPUT_NUMBER_ARRAY,
expectedOutput: "true",
recipeConfig: [
{
op: "Jsonata Query",
args: ["(Numbers[2] != 0) or (Numbers[5] = Numbers[1])"],
},
],
},
// Array tests
{
name: "Jsonata: $ at the start of an expression refers to the entire input document, subscripting it with 0 selects the first item",
input: INPUT_ARRAY_OF_OBJECTS,
expectedOutput: '{"ref":[1,2]}',
recipeConfig: [
{
op: "Jsonata Query",
args: ["$[0]"],
},
],
},
{
name: "Jsonata: .ref here returns the entire internal array",
input: INPUT_ARRAY_OF_OBJECTS,
expectedOutput: "[1,2]",
recipeConfig: [
{
op: "Jsonata Query",
args: ["$[0].ref"],
},
],
},
{
name: "Jsonata: returns element on first position of the internal array",
input: INPUT_ARRAY_OF_OBJECTS,
expectedOutput: "1",
recipeConfig: [
{
op: "Jsonata Query",
args: ["$[0].ref[0]"],
},
],
},
{
name: "Jsonata: $.field_reference flattens the result into a single array",
input: INPUT_ARRAY_OF_OBJECTS,
expectedOutput: "[1,2,3,4]",
recipeConfig: [
{
op: "Jsonata Query",
args: ["$.ref"],
},
],
},
]);

View File

@@ -0,0 +1,92 @@
/**
* URLEncode and URLDecode tests.
*
* @author es45411 [135977478+es45411@users.noreply.github.com]
*
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
// URL Decode
{
name: "URLDecode: nothing",
input: "",
expectedOutput: "",
recipeConfig: [
{
op: "URL Decode",
args: [],
},
],
},
{
name: "URLDecode: spaces without special chars",
input: "Hello%20world%21",
expectedOutput: "Hello world!",
recipeConfig: [
{
op: "URL Decode",
args: [],
},
],
},
{
name: "URLDecode: spaces with special chars",
input: "Hello%20world!",
expectedOutput: "Hello world!",
recipeConfig: [
{
op: "URL Decode",
args: [],
},
],
},
{
name: "URLDecode: decode plus as space",
input: "Hello%20world!",
expectedOutput: "Hello world!",
recipeConfig: [
{
op: "URL Decode",
args: [],
},
],
},
// URL Encode
{
name: "URLEncode: nothing",
input: "",
expectedOutput: "",
recipeConfig: [
{
op: "URL Encode",
args: [],
},
],
},
{
name: "URLEncode: spaces without special chars",
input: "Hello world!",
expectedOutput: "Hello%20world!",
recipeConfig: [
{
op: "URL Encode",
args: [],
},
],
},
{
name: "URLEncode: spaces with special chars",
input: "Hello world!",
expectedOutput: "Hello%20world%21",
recipeConfig: [
{
op: "URL Encode",
args: [true],
},
],
},
]);

View File

@@ -0,0 +1,120 @@
/**
* Checksum tests.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
const BASIC_STRING = "The ships hung in the sky in much the same way that bricks don't.";
const UTF8_STR = "ნუ პანიკას";
const ALL_BYTES = [
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f",
"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f",
"\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
"\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f",
"\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f",
"\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f",
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f",
"\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f",
"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
"\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf",
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
"\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf",
"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef",
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
].join("");
TestRegister.addTests([
{
name: "XOR Checksum (1): nothing",
input: "",
expectedOutput: "00",
recipeConfig: [
{
"op": "XOR Checksum",
"args": [1]
}
]
},
{
name: "XOR Checksum (1): basic string",
input: BASIC_STRING,
expectedOutput: "08",
recipeConfig: [
{
"op": "XOR Checksum",
"args": [1]
}
]
},
{
name: "XOR Checksum (1): UTF-8",
input: UTF8_STR,
expectedOutput: "df",
recipeConfig: [
{
"op": "XOR Checksum",
"args": [1]
}
]
},
{
name: "XOR Checksum (1): all bytes",
input: ALL_BYTES,
expectedOutput: "00",
recipeConfig: [
{
"op": "XOR Checksum",
"args": [1]
}
]
},
{
name: "XOR Checksum (4): nothing",
input: "",
expectedOutput: "00000000",
recipeConfig: [
{
"op": "XOR Checksum",
"args": [4]
}
]
},
{
name: "XOR Checksum (4): basic string",
input: BASIC_STRING,
expectedOutput: "4918421b",
recipeConfig: [
{
"op": "XOR Checksum",
"args": [4]
}
]
},
{
name: "XOR Checksum (4): UTF-8",
input: UTF8_STR,
expectedOutput: "83a424dc",
recipeConfig: [
{
"op": "XOR Checksum",
"args": [4]
}
]
},
{
name: "XOR Checksum (4): all bytes",
input: ALL_BYTES,
expectedOutput: "00000000",
recipeConfig: [
{
"op": "XOR Checksum",
"args": [4]
}
]
},
]);