cyberchef 11.1.0 → 11.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/AGENTS.md +75 -0
  2. package/CHANGELOG.md +173 -2
  3. package/Dockerfile +2 -2
  4. package/Gruntfile.js +1 -0
  5. package/README.md +7 -6
  6. package/SECURITY.md +3 -1
  7. package/package.json +22 -21
  8. package/src/core/Chef.mjs +2 -0
  9. package/src/core/Dish.mjs +1 -5
  10. package/src/core/Ingredient.mjs +92 -0
  11. package/src/core/Operation.mjs +19 -0
  12. package/src/core/Recipe.mjs +4 -0
  13. package/src/core/Utils.mjs +48 -0
  14. package/src/core/config/Categories.json +22 -6
  15. package/src/core/config/OperationConfig.json +4774 -1228
  16. package/src/core/config/modules/Ciphers.mjs +20 -0
  17. package/src/core/config/modules/Crypto.mjs +10 -0
  18. package/src/core/config/modules/Default.mjs +8 -0
  19. package/src/core/config/modules/File.mjs +16 -0
  20. package/src/core/config/modules/OpModules.mjs +2 -0
  21. package/src/core/config/scripts/generateHTMLEntities.mjs +139 -0
  22. package/src/core/config/scripts/htmlEntityOverrides.mjs +86 -0
  23. package/src/core/dishTypes/DishType.mjs +1 -1
  24. package/src/core/errors/ExcludedOperationError.mjs +1 -1
  25. package/src/core/lib/Arithmetic.mjs +21 -5
  26. package/src/core/lib/BigIntUtils.mjs +0 -1
  27. package/src/core/lib/COBS.mjs +86 -0
  28. package/src/core/lib/Charts.mjs +3 -3
  29. package/src/core/lib/Decimal.mjs +5 -5
  30. package/src/core/lib/HTMLEntities.mjs +2068 -0
  31. package/src/core/lib/Present.mjs +422 -0
  32. package/src/core/lib/Protocol.mjs +8 -6
  33. package/src/core/lib/TEA.mjs +494 -0
  34. package/src/core/lib/TLVParser.mjs +16 -7
  35. package/src/core/lib/Twofish.mjs +608 -0
  36. package/src/core/operations/AsconDecrypt.mjs +112 -0
  37. package/src/core/operations/AsconEncrypt.mjs +108 -0
  38. package/src/core/operations/AsconHash.mjs +49 -0
  39. package/src/core/operations/AsconMAC.mjs +68 -0
  40. package/src/core/operations/AutomatedValidationTestOp.mjs +84 -0
  41. package/src/core/operations/AvroToJSON.mjs +1 -1
  42. package/src/core/operations/BLAKE3.mjs +5 -1
  43. package/src/core/operations/BcryptCompare.mjs +11 -5
  44. package/src/core/operations/BitShiftLeft.mjs +4 -1
  45. package/src/core/operations/Bzip2Compress.mjs +1 -1
  46. package/src/core/operations/DechunkHTTPResponse.mjs +4 -1
  47. package/src/core/operations/ExtendedGCD.mjs +101 -0
  48. package/src/core/operations/FromBase.mjs +2 -1
  49. package/src/core/operations/FromCOBS.mjs +38 -0
  50. package/src/core/operations/FromDecimal.mjs +6 -1
  51. package/src/core/operations/FromHTMLEntity.mjs +2 -1458
  52. package/src/core/operations/GenerateDeBruijnSequence.mjs +8 -0
  53. package/src/core/operations/GenerateHOTP.mjs +21 -6
  54. package/src/core/operations/GenerateImage.mjs +22 -10
  55. package/src/core/operations/GeneratePrime.mjs +154 -0
  56. package/src/core/operations/GenerateTOTP.mjs +24 -7
  57. package/src/core/operations/Gzip.mjs +1 -3
  58. package/src/core/operations/Jsonata.mjs +12 -0
  59. package/src/core/operations/MIMEDecoding.mjs +1 -1
  60. package/src/core/operations/MOD.mjs +62 -0
  61. package/src/core/operations/ModularInverse.mjs +107 -0
  62. package/src/core/operations/PRESENTDecrypt.mjs +94 -0
  63. package/src/core/operations/PRESENTEncrypt.mjs +94 -0
  64. package/src/core/operations/ParityBit.mjs +1 -1
  65. package/src/core/operations/ParseIPv4Header.mjs +1 -1
  66. package/src/core/operations/ParseURI.mjs +18 -5
  67. package/src/core/operations/PseudoRandomNumberGenerator.mjs +2 -1
  68. package/src/core/operations/RandomPrime.mjs +154 -0
  69. package/src/core/operations/RenderPDF.mjs +100 -0
  70. package/src/core/operations/SHA2.mjs +1 -1
  71. package/src/core/operations/SM4Encrypt.mjs +1 -1
  72. package/src/core/operations/SetDifference.mjs +8 -1
  73. package/src/core/operations/SetIntersection.mjs +8 -1
  74. package/src/core/operations/ShowOnMap.mjs +14 -2
  75. package/src/core/operations/TEADecrypt.mjs +98 -0
  76. package/src/core/operations/TEAEncrypt.mjs +98 -0
  77. package/src/core/operations/ToBase.mjs +4 -4
  78. package/src/core/operations/ToBase32.mjs +20 -4
  79. package/src/core/operations/ToBinary.mjs +4 -1
  80. package/src/core/operations/ToCOBS.mjs +38 -0
  81. package/src/core/operations/ToHTMLEntity.mjs +7 -1430
  82. package/src/core/operations/ToHexdump.mjs +7 -1
  83. package/src/core/operations/TwofishDecrypt.mjs +94 -0
  84. package/src/core/operations/TwofishEncrypt.mjs +94 -0
  85. package/src/core/operations/URLEncode.mjs +22 -18
  86. package/src/core/operations/UnescapeUnicodeCharacters.mjs +2 -1
  87. package/src/core/operations/ViewBitPlane.mjs +9 -3
  88. package/src/core/operations/Wrap.mjs +5 -0
  89. package/src/core/operations/XORBruteForce.mjs +4 -1
  90. package/src/core/operations/XORChecksum.mjs +10 -3
  91. package/src/core/operations/XTEADecrypt.mjs +110 -0
  92. package/src/core/operations/XTEAEncrypt.mjs +110 -0
  93. package/src/core/operations/index.mjs +42 -0
  94. package/src/core/vendor/ascon.mjs +162 -0
  95. package/src/core/vendor/htmlEntities/entity.json +2233 -0
  96. package/src/core/vendor/htmlEntities/entity.txt +14 -0
  97. package/src/node/api.mjs +4 -1
  98. package/src/node/index.mjs +105 -0
  99. package/src/web/HTMLOperation.mjs +2 -1
  100. package/src/web/stylesheets/layout/_io.css +8 -0
  101. package/tests/browser/00_nightwatch.js +26 -0
  102. package/tests/browser/02_ops.js +20 -4
  103. package/tests/node/index.mjs +2 -0
  104. package/tests/node/tests/Dish.mjs +19 -0
  105. package/tests/node/tests/NodeDish.mjs +36 -0
  106. package/tests/node/tests/ToHTMLEntity.mjs +82 -0
  107. package/tests/node/tests/Utils.mjs +77 -0
  108. package/tests/node/tests/lib/ChartsProtocolPrototypePollution.mjs +90 -0
  109. package/tests/node/tests/nodeApi.mjs +33 -1
  110. package/tests/node/tests/operations.mjs +26 -1
  111. package/tests/operations/index.mjs +17 -0
  112. package/tests/operations/tests/Arithmetic.mjs +33 -0
  113. package/tests/operations/tests/Ascon.mjs +501 -0
  114. package/tests/operations/tests/AutomatedValidation.mjs +154 -0
  115. package/tests/operations/tests/BLAKE3.mjs +39 -1
  116. package/tests/operations/tests/Base32.mjs +22 -0
  117. package/tests/operations/tests/COBS.mjs +476 -0
  118. package/tests/operations/tests/CharEnc.mjs +2 -2
  119. package/tests/operations/tests/DechunkHTTPResponse.mjs +66 -0
  120. package/tests/operations/tests/ExtendedGCD.mjs +78 -0
  121. package/tests/operations/tests/FromBase.mjs +66 -0
  122. package/tests/operations/tests/FromDecimal.mjs +55 -0
  123. package/tests/operations/tests/GenerateLoremIpsum.mjs +2 -2
  124. package/tests/operations/tests/Gzip.mjs +60 -0
  125. package/tests/operations/tests/HTMLEntity.mjs +126 -0
  126. package/tests/operations/tests/Hash.mjs +44 -0
  127. package/tests/operations/tests/Hexdump.mjs +11 -0
  128. package/tests/operations/tests/Image.mjs +26 -0
  129. package/tests/operations/tests/Jsonata.mjs +23 -0
  130. package/tests/operations/tests/MIMEDecoding.mjs +33 -0
  131. package/tests/operations/tests/MOD.mjs +208 -0
  132. package/tests/operations/tests/Median.mjs +33 -0
  133. package/tests/operations/tests/ModularInverse.mjs +78 -0
  134. package/tests/operations/tests/OTP.mjs +167 -2
  135. package/tests/operations/tests/PRESENT.mjs +465 -0
  136. package/tests/operations/tests/ParseIPv4Header.mjs +11 -0
  137. package/tests/operations/tests/ParseTLV.mjs +41 -0
  138. package/tests/operations/tests/RenderPDF.mjs +55 -0
  139. package/tests/operations/tests/SM2.mjs +1 -1
  140. package/tests/operations/tests/SetDifference.mjs +22 -0
  141. package/tests/operations/tests/SetIntersection.mjs +23 -1
  142. package/tests/operations/tests/ShowOnMap.mjs +61 -0
  143. package/tests/operations/tests/TEA.mjs +566 -0
  144. package/tests/operations/tests/Twofish.mjs +486 -0
  145. package/tests/operations/tests/URLEncodeDecode.mjs +26 -0
  146. package/tests/operations/tests/UnescapeUnicodeCharacters.mjs +88 -0
  147. package/tests/operations/tests/Wrap.mjs +44 -0
  148. package/webpack.config.js +3 -3
@@ -0,0 +1,112 @@
1
+ /**
2
+ * @author Medjedtxm
3
+ * @copyright Crown Copyright 2025
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+ import OperationError from "../errors/OperationError.mjs";
9
+ import Utils from "../Utils.mjs";
10
+ import { toHexFast } from "../lib/Hex.mjs";
11
+ import JsAscon from "js-ascon";
12
+
13
+ /**
14
+ * Ascon Decrypt operation
15
+ */
16
+ class AsconDecrypt extends Operation {
17
+
18
+ /**
19
+ * AsconDecrypt constructor
20
+ */
21
+ constructor() {
22
+ super();
23
+
24
+ this.name = "Ascon Decrypt";
25
+ this.module = "Ciphers";
26
+ this.description = "Ascon-AEAD128 authenticated decryption as standardised in NIST SP 800-232. Decrypts ciphertext and verifies the authentication tag. Decryption will fail if the ciphertext or associated data has been tampered with.<br><br><b>Key:</b> Must be exactly 16 bytes (128 bits).<br><br><b>Nonce:</b> Must be exactly 16 bytes (128 bits). Must match the nonce used during encryption.<br><br><b>Associated Data:</b> Must match the associated data used during encryption. Any mismatch will cause authentication failure.";
27
+ this.infoURL = "https://wikipedia.org/wiki/Ascon_(cipher)";
28
+ this.inputType = "string";
29
+ this.outputType = "string";
30
+ this.args = [
31
+ {
32
+ "name": "Key",
33
+ "type": "toggleString",
34
+ "value": "",
35
+ "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
36
+ },
37
+ {
38
+ "name": "Nonce",
39
+ "type": "toggleString",
40
+ "value": "",
41
+ "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
42
+ },
43
+ {
44
+ "name": "Associated Data",
45
+ "type": "toggleString",
46
+ "value": "",
47
+ "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
48
+ },
49
+ {
50
+ "name": "Input",
51
+ "type": "option",
52
+ "value": ["Hex", "Raw"]
53
+ },
54
+ {
55
+ "name": "Output",
56
+ "type": "option",
57
+ "value": ["Raw", "Hex"]
58
+ }
59
+ ];
60
+ }
61
+
62
+ /**
63
+ * @param {string} input
64
+ * @param {Object[]} args
65
+ * @returns {string}
66
+ * @throws {OperationError} if invalid key or nonce length, or authentication fails
67
+ */
68
+ run(input, args) {
69
+ const key = Utils.convertToByteArray(args[0].string, args[0].option),
70
+ nonce = Utils.convertToByteArray(args[1].string, args[1].option),
71
+ ad = Utils.convertToByteArray(args[2].string, args[2].option),
72
+ inputType = args[3],
73
+ outputType = args[4];
74
+
75
+ if (key.length !== 16) {
76
+ throw new OperationError(`Invalid key length: ${key.length} bytes.
77
+
78
+ Ascon-AEAD128 requires a key of exactly 16 bytes (128 bits).`);
79
+ }
80
+
81
+ if (nonce.length !== 16) {
82
+ throw new OperationError(`Invalid nonce length: ${nonce.length} bytes.
83
+
84
+ Ascon-AEAD128 requires a nonce of exactly 16 bytes (128 bits).`);
85
+ }
86
+
87
+ // Convert input to byte array
88
+ const inputData = Utils.convertToByteArray(input, inputType);
89
+
90
+ const keyUint8 = new Uint8Array(key);
91
+ const nonceUint8 = new Uint8Array(nonce);
92
+ const adUint8 = new Uint8Array(ad);
93
+ const ciphertextUint8 = new Uint8Array(inputData);
94
+
95
+ try {
96
+ // Decrypt (returns Uint8Array containing plaintext)
97
+ const plaintext = JsAscon.decrypt(keyUint8, nonceUint8, adUint8, ciphertextUint8);
98
+
99
+ // Return in requested format
100
+ if (outputType === "Hex") {
101
+ return toHexFast(plaintext);
102
+ } else {
103
+ return Utils.arrayBufferToStr(Uint8Array.from(plaintext).buffer);
104
+ }
105
+ } catch (e) {
106
+ throw new OperationError("Unable to decrypt: authentication failed. The ciphertext, key, nonce, or associated data may be incorrect or tampered with.");
107
+ }
108
+ }
109
+
110
+ }
111
+
112
+ export default AsconDecrypt;
@@ -0,0 +1,108 @@
1
+ /**
2
+ * @author Medjedtxm
3
+ * @copyright Crown Copyright 2025
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+ import OperationError from "../errors/OperationError.mjs";
9
+ import Utils from "../Utils.mjs";
10
+ import { toHexFast } from "../lib/Hex.mjs";
11
+ import JsAscon from "js-ascon";
12
+
13
+ /**
14
+ * Ascon Encrypt operation
15
+ */
16
+ class AsconEncrypt extends Operation {
17
+
18
+ /**
19
+ * AsconEncrypt constructor
20
+ */
21
+ constructor() {
22
+ super();
23
+
24
+ this.name = "Ascon Encrypt";
25
+ this.module = "Ciphers";
26
+ this.description = "Ascon-AEAD128 authenticated encryption as standardised in NIST SP 800-232. Ascon is a family of lightweight authenticated encryption algorithms designed for constrained devices such as IoT sensors and embedded systems.<br><br><b>Key:</b> Must be exactly 16 bytes (128 bits).<br><br><b>Nonce:</b> Must be exactly 16 bytes (128 bits). Should be unique for each encryption with the same key. Never reuse a nonce with the same key.<br><br><b>Associated Data:</b> Optional additional data that is authenticated but not encrypted. Useful for including metadata like headers or timestamps.<br><br>The output includes both the ciphertext and a 128-bit authentication tag.";
27
+ this.infoURL = "https://wikipedia.org/wiki/Ascon_(cipher)";
28
+ this.inputType = "string";
29
+ this.outputType = "string";
30
+ this.args = [
31
+ {
32
+ "name": "Key",
33
+ "type": "toggleString",
34
+ "value": "",
35
+ "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
36
+ },
37
+ {
38
+ "name": "Nonce",
39
+ "type": "toggleString",
40
+ "value": "",
41
+ "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
42
+ },
43
+ {
44
+ "name": "Associated Data",
45
+ "type": "toggleString",
46
+ "value": "",
47
+ "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
48
+ },
49
+ {
50
+ "name": "Input",
51
+ "type": "option",
52
+ "value": ["Raw", "Hex"]
53
+ },
54
+ {
55
+ "name": "Output",
56
+ "type": "option",
57
+ "value": ["Hex", "Raw"]
58
+ }
59
+ ];
60
+ }
61
+
62
+ /**
63
+ * @param {string} input
64
+ * @param {Object[]} args
65
+ * @returns {string}
66
+ * @throws {OperationError} if invalid key or nonce length
67
+ */
68
+ run(input, args) {
69
+ const key = Utils.convertToByteArray(args[0].string, args[0].option),
70
+ nonce = Utils.convertToByteArray(args[1].string, args[1].option),
71
+ ad = Utils.convertToByteArray(args[2].string, args[2].option),
72
+ inputType = args[3],
73
+ outputType = args[4];
74
+
75
+ if (key.length !== 16) {
76
+ throw new OperationError(`Invalid key length: ${key.length} bytes.
77
+
78
+ Ascon-AEAD128 requires a key of exactly 16 bytes (128 bits).`);
79
+ }
80
+
81
+ if (nonce.length !== 16) {
82
+ throw new OperationError(`Invalid nonce length: ${nonce.length} bytes.
83
+
84
+ Ascon-AEAD128 requires a nonce of exactly 16 bytes (128 bits).`);
85
+ }
86
+
87
+ // Convert input to byte array
88
+ const inputData = Utils.convertToByteArray(input, inputType);
89
+
90
+ const keyUint8 = new Uint8Array(key);
91
+ const nonceUint8 = new Uint8Array(nonce);
92
+ const adUint8 = new Uint8Array(ad);
93
+ const inputUint8 = new Uint8Array(inputData);
94
+
95
+ // Encrypt (returns Uint8Array containing ciphertext + tag)
96
+ const ciphertext = JsAscon.encrypt(keyUint8, nonceUint8, adUint8, inputUint8);
97
+
98
+ // Return in requested format
99
+ if (outputType === "Hex") {
100
+ return toHexFast(ciphertext);
101
+ } else {
102
+ return Utils.arrayBufferToStr(Uint8Array.from(ciphertext).buffer);
103
+ }
104
+ }
105
+
106
+ }
107
+
108
+ export default AsconEncrypt;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @author Medjedtxm
3
+ * @copyright Crown Copyright 2025
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+ import { toHexFast } from "../lib/Hex.mjs";
9
+ import JsAscon from "js-ascon";
10
+
11
+ /**
12
+ * Ascon Hash operation
13
+ */
14
+ class AsconHash extends Operation {
15
+
16
+ /**
17
+ * AsconHash constructor
18
+ */
19
+ constructor() {
20
+ super();
21
+
22
+ this.name = "Ascon Hash";
23
+ this.module = "Crypto";
24
+ this.description = "Ascon-Hash256 produces a fixed 256-bit (32-byte) cryptographic hash as standardised in NIST SP 800-232. Ascon is a family of lightweight authenticated encryption and hashing algorithms designed for constrained devices such as IoT sensors and embedded systems.<br><br>The algorithm was selected by NIST in 2023 as the new standard for lightweight cryptography after a multi-year competition.";
25
+ this.infoURL = "https://wikipedia.org/wiki/Ascon_(cipher)";
26
+ this.inputType = "ArrayBuffer";
27
+ this.outputType = "string";
28
+ this.args = [];
29
+ }
30
+
31
+ /**
32
+ * @param {ArrayBuffer} input
33
+ * @param {Object[]} args
34
+ * @returns {string}
35
+ */
36
+ run(input, args) {
37
+
38
+ const inputUint8 = new Uint8Array(input);
39
+
40
+ // Compute hash (returns Uint8Array)
41
+ const hashResult = JsAscon.hash(inputUint8);
42
+
43
+ // Convert to hex string
44
+ return toHexFast(hashResult);
45
+ }
46
+
47
+ }
48
+
49
+ export default AsconHash;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @author Medjedtxm
3
+ * @copyright Crown Copyright 2025
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+ import OperationError from "../errors/OperationError.mjs";
9
+ import Utils from "../Utils.mjs";
10
+ import { toHexFast } from "../lib/Hex.mjs";
11
+ import AsconMac from "../vendor/ascon.mjs";
12
+
13
+ /**
14
+ * Ascon MAC operation
15
+ */
16
+ class AsconMAC extends Operation {
17
+
18
+ /**
19
+ * AsconMAC constructor
20
+ */
21
+ constructor() {
22
+ super();
23
+
24
+ this.name = "Ascon MAC";
25
+ this.module = "Crypto";
26
+ this.description = "Ascon-Mac produces a 128-bit (16-byte) message authentication code as part of the Ascon family standardised by NIST in SP 800-232. It provides authentication for messages using a secret key, ensuring both data integrity and authenticity.<br><br>Ascon is designed for lightweight cryptography on constrained devices such as IoT sensors and embedded systems.";
27
+ this.infoURL = "https://wikipedia.org/wiki/Ascon_(cipher)";
28
+ this.inputType = "ArrayBuffer";
29
+ this.outputType = "string";
30
+ this.args = [
31
+ {
32
+ "name": "Key",
33
+ "type": "toggleString",
34
+ "value": "",
35
+ "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
36
+ }
37
+ ];
38
+ }
39
+
40
+ /**
41
+ * @param {ArrayBuffer} input
42
+ * @param {Object[]} args
43
+ * @returns {string}
44
+ * @throws {OperationError} if invalid key length
45
+ */
46
+ run(input, args) {
47
+ const keyArray = Utils.convertToByteArray(args[0].string, args[0].option);
48
+
49
+ if (keyArray.length !== 16) {
50
+ throw new OperationError(`Invalid key length: ${keyArray.length} bytes.
51
+
52
+ Ascon-Mac requires a key of exactly 16 bytes (128 bits).`);
53
+ }
54
+
55
+ // Convert to Uint8Array for vendor Ascon implementation
56
+ const keyUint8 = new Uint8Array(keyArray);
57
+ const inputUint8 = new Uint8Array(input);
58
+
59
+ // Compute MAC (returns Uint8Array)
60
+ const macResult = AsconMac.mac(keyUint8, inputUint8);
61
+
62
+ // Convert to hex string
63
+ return toHexFast(macResult);
64
+ }
65
+
66
+ }
67
+
68
+ export default AsconMAC;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @author CyberChef
3
+ * @copyright Crown Copyright 2026
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+
9
+ /**
10
+ * Automated validation test operation
11
+ */
12
+ class AutomatedValidationTestOp extends Operation {
13
+
14
+ /**
15
+ * AutomatedValidationTestOp constructor
16
+ */
17
+ constructor() {
18
+ super();
19
+
20
+ this.name = "Automated Validation Test Op";
21
+ this.module = "Default";
22
+ this.description = "Operation used specifically to test automated parameter validation.";
23
+ this.inputType = "string";
24
+ this.outputType = "string";
25
+ this.args = [
26
+ {
27
+ "name": "Integer Number",
28
+ "type": "number",
29
+ "value": 5,
30
+ "min": 5,
31
+ "max": 10,
32
+ "integer": true
33
+ },
34
+ {
35
+ "name": "Real Number",
36
+ "type": "number",
37
+ "value": 1.5,
38
+ "min": 1.5,
39
+ "max": 5.5
40
+ },
41
+ {
42
+ "name": "Non Empty String",
43
+ "type": "string",
44
+ "value": "hello",
45
+ "maxLength": 5,
46
+ "allowEmpty": false
47
+ },
48
+ {
49
+ "name": "Empty Allowed String",
50
+ "type": "string",
51
+ "value": "",
52
+ "allowEmpty": true
53
+ },
54
+ {
55
+ "name": "Non Empty Toggle String",
56
+ "type": "toggleString",
57
+ "value": {
58
+ "option": "Option A",
59
+ "string": "test"
60
+ },
61
+ "toggleValues": ["Option A", "Option B"],
62
+ "allowEmpty": false
63
+ },
64
+ {
65
+ "name": "Option Ingredient",
66
+ "type": "option",
67
+ "value": ["[Group 1]", "Option 1", "Option 2", "[/Group 1]", "[Group 2]", "Option 3", "[/Group 2]"],
68
+ "allowEmpty": false
69
+ }
70
+ ];
71
+ }
72
+
73
+ /**
74
+ * @param {string} input
75
+ * @param {Object[]} args
76
+ * @returns {string}
77
+ */
78
+ run(input, args) {
79
+ return "Success";
80
+ }
81
+
82
+ }
83
+
84
+ export default AutomatedValidationTestOp;
@@ -39,7 +39,7 @@ class AvroToJSON extends Operation {
39
39
  * @param {Object[]} args
40
40
  * @returns {string}
41
41
  */
42
- run(input, args) {
42
+ async run(input, args) {
43
43
  if (input.byteLength <= 0) {
44
44
  throw new OperationError("Please provide an input.");
45
45
  }
@@ -30,7 +30,11 @@ class BLAKE3 extends Operation {
30
30
  this.args = [
31
31
  {
32
32
  "name": "Size (bytes)",
33
- "type": "number"
33
+ "type": "number",
34
+ "value": 16,
35
+ "min": 1,
36
+ "max": 65535, // arbitrary limit to prevent resource exhaustion
37
+ "integer": true,
34
38
  }, {
35
39
  "name": "Key",
36
40
  "type": "string",
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import Operation from "../Operation.mjs";
8
+ import OperationError from "../errors/OperationError.mjs";
8
9
  import bcrypt from "bcryptjs";
9
10
  import { isWorkerEnvironment } from "../Utils.mjs";
10
11
 
@@ -43,11 +44,16 @@ class BcryptCompare extends Operation {
43
44
  async run(input, args) {
44
45
  const hash = args[0];
45
46
 
46
- const match = await bcrypt.compare(input, hash, undefined, p => {
47
- // Progress callback
48
- if (isWorkerEnvironment())
49
- self.sendStatusMessage(`Progress: ${(p * 100).toFixed(0)}%`);
50
- });
47
+ let match;
48
+ try {
49
+ match = await bcrypt.compare(input, hash, undefined, p => {
50
+ // Progress callback
51
+ if (isWorkerEnvironment())
52
+ self.sendStatusMessage(`Progress: ${(p * 100).toFixed(0)}%`);
53
+ });
54
+ } catch (err) {
55
+ throw new OperationError(err.toString());
56
+ }
51
57
 
52
58
  return match ? "Match: " + input : "No match";
53
59
 
@@ -27,7 +27,10 @@ class BitShiftLeft extends Operation {
27
27
  {
28
28
  "name": "Amount",
29
29
  "type": "number",
30
- "value": 1
30
+ "value": 1,
31
+ "min": 0,
32
+ "max": 7,
33
+ "integer": true,
31
34
  }
32
35
  ];
33
36
  }
@@ -47,7 +47,7 @@ class Bzip2Compress extends Operation {
47
47
  * @param {Object[]} args
48
48
  * @returns {File}
49
49
  */
50
- run(input, args) {
50
+ async run(input, args) {
51
51
  const [blockSize, workFactor] = args;
52
52
  if (input.byteLength <= 0) {
53
53
  throw new OperationError("Please provide an input.");
@@ -45,12 +45,15 @@ class DechunkHTTPResponse extends Operation {
45
45
  const lineEndingsLength = lineEndings.length;
46
46
  let chunkSize = parseInt(input.slice(0, chunkSizeEnd), 16);
47
47
  while (!isNaN(chunkSize)) {
48
+ if (chunkSize === 0) {
49
+ break;
50
+ }
48
51
  chunks.push(input.slice(chunkSizeEnd, chunkSize + chunkSizeEnd));
49
52
  input = input.slice(chunkSizeEnd + chunkSize + lineEndingsLength);
50
53
  chunkSizeEnd = input.indexOf(lineEndings) + lineEndingsLength;
51
54
  chunkSize = parseInt(input.slice(0, chunkSizeEnd), 16);
52
55
  }
53
- return chunks.join("") + input;
56
+ return chunks.join("");
54
57
  }
55
58
 
56
59
  }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * @author p-leriche [philip.leriche@cantab.net]
3
+ * @copyright Crown Copyright 2025
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+ import OperationError from "../errors/OperationError.mjs";
9
+ import { parseBigInt, egcd } from "../lib/BigIntUtils.mjs";
10
+
11
+ /* ---------- operation class ---------- */
12
+
13
+ /**
14
+ * Extended GCD operation
15
+ */
16
+ class ExtendedGCD extends Operation {
17
+ /**
18
+ * ExtendedGCD constructor
19
+ */
20
+ constructor() {
21
+ super();
22
+
23
+ this.name = "Extended GCD";
24
+ this.module = "Crypto";
25
+ this.description =
26
+ "Computes the Extended Euclidean Algorithm for integers <i>a</i> and <i>b</i>.<br><br>" +
27
+ "Finds integers <i>x</i> and <i>y</i> (Bezout coefficients) such that:<br>" +
28
+ "a*x + b*y = gcd(a, b)<br><br>" +
29
+ "This is fundamental to many number theory algorithms including modular inverse, " +
30
+ "solving linear Diophantine equations, and cryptographic operations.<br><br>" +
31
+ "<b>Input handling:</b> If either <i>a</i> or <i>b</i> is left blank, " +
32
+ "its value is taken from the Input field.";
33
+ this.infoURL = "https://wikipedia.org/wiki/Extended_Euclidean_algorithm";
34
+ this.inputType = "string";
35
+ this.outputType = "string";
36
+ this.args = [
37
+ {
38
+ name: "Value a",
39
+ type: "string",
40
+ value: ""
41
+ },
42
+ {
43
+ name: "Value b",
44
+ type: "string",
45
+ value: ""
46
+ }
47
+ ];
48
+ }
49
+
50
+ /**
51
+ * @param {string} input
52
+ * @param {Object[]} args
53
+ * @returns {string}
54
+ */
55
+ run(input, args) {
56
+ const [aStr, bStr] = args;
57
+
58
+ // Trim everything so "" and " " count as empty
59
+ const aParam = aStr?.trim();
60
+ const bParam = bStr?.trim();
61
+ const inputVal = input?.trim();
62
+
63
+ let a, b;
64
+
65
+ if (aParam && bParam) {
66
+ // Case 1: both values given as parameters
67
+ a = aParam;
68
+ b = bParam;
69
+ } else if (!aParam && bParam) {
70
+ // Case 2: a missing - take from input
71
+ a = inputVal;
72
+ b = bParam;
73
+ if (!a) throw new OperationError("Value a must be defined");
74
+ } else if (aParam && !bParam) {
75
+ // Case 3: b missing - take from input
76
+ a = aParam;
77
+ b = inputVal;
78
+ if (!b) throw new OperationError("Value b must be defined");
79
+ } else if (!aParam && !bParam) {
80
+ // Case 4: both values missing
81
+ throw new OperationError("Values a and b must be defined");
82
+ }
83
+
84
+ const aBI = parseBigInt(a, "Value a");
85
+ const bBI = parseBigInt(b, "Value b");
86
+
87
+ const [g, x, y] = egcd(aBI, bBI);
88
+ const gcd = g < 0n ? -g : g;
89
+
90
+ // Format output string bearing in mind that crypto-grade numbers
91
+ // may greatly exceed the line length.
92
+ let output = "gcd: " + gcd.toString() + "\n\n";
93
+ output += "Bezout coefficients:\n";
94
+ output += "x = " + x.toString() + "\n";
95
+ output += "y = " + y.toString() + "\n\n";
96
+
97
+ return output;
98
+ }
99
+ }
100
+
101
+ export default ExtendedGCD;
@@ -51,9 +51,10 @@ class FromBase extends Operation {
51
51
  if (number.length === 1) return result;
52
52
 
53
53
  // Fractional part
54
+ const radixBN = new BigNumber(radix);
54
55
  for (let i = 0; i < number[1].length; i++) {
55
56
  const digit = new BigNumber(number[1][i], radix);
56
- result += digit.div(Math.pow(radix, i+1));
57
+ result = result.plus(digit.div(radixBN.pow(i + 1)));
57
58
  }
58
59
 
59
60
  return result;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @author Imantas Lukenskas [imantas@lukenskas.dev]
3
+ * @copyright Imantas Lukenskas 2026
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+ import {fromCobs} from "../lib/COBS.mjs";
9
+
10
+ /**
11
+ * From COBS operation
12
+ */
13
+ class FromCOBS extends Operation {
14
+ /**
15
+ * FromCOBS constructor
16
+ */
17
+ constructor() {
18
+ super();
19
+
20
+ this.name = "From COBS";
21
+ this.module = "Default";
22
+ this.description = "Decodes COBS encoded bytes";
23
+ this.infoURL = "https://wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing";
24
+ this.inputType = "byteArray";
25
+ this.outputType = "byteArray";
26
+ }
27
+
28
+ /**
29
+ * @param {byteArray} input
30
+ * @param {Object[]} args
31
+ * @returns {byteArray}
32
+ */
33
+ run(input, args) {
34
+ return fromCobs(input);
35
+ }
36
+ }
37
+
38
+ export default FromCOBS;