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.
- package/AGENTS.md +75 -0
- package/CHANGELOG.md +173 -2
- package/Dockerfile +2 -2
- package/Gruntfile.js +1 -0
- package/README.md +7 -6
- package/SECURITY.md +3 -1
- package/package.json +22 -21
- package/src/core/Chef.mjs +2 -0
- package/src/core/Dish.mjs +1 -5
- package/src/core/Ingredient.mjs +92 -0
- package/src/core/Operation.mjs +19 -0
- package/src/core/Recipe.mjs +4 -0
- package/src/core/Utils.mjs +48 -0
- package/src/core/config/Categories.json +22 -6
- package/src/core/config/OperationConfig.json +4774 -1228
- package/src/core/config/modules/Ciphers.mjs +20 -0
- package/src/core/config/modules/Crypto.mjs +10 -0
- package/src/core/config/modules/Default.mjs +8 -0
- package/src/core/config/modules/File.mjs +16 -0
- package/src/core/config/modules/OpModules.mjs +2 -0
- package/src/core/config/scripts/generateHTMLEntities.mjs +139 -0
- package/src/core/config/scripts/htmlEntityOverrides.mjs +86 -0
- package/src/core/dishTypes/DishType.mjs +1 -1
- package/src/core/errors/ExcludedOperationError.mjs +1 -1
- package/src/core/lib/Arithmetic.mjs +21 -5
- package/src/core/lib/BigIntUtils.mjs +0 -1
- package/src/core/lib/COBS.mjs +86 -0
- package/src/core/lib/Charts.mjs +3 -3
- package/src/core/lib/Decimal.mjs +5 -5
- package/src/core/lib/HTMLEntities.mjs +2068 -0
- package/src/core/lib/Present.mjs +422 -0
- package/src/core/lib/Protocol.mjs +8 -6
- package/src/core/lib/TEA.mjs +494 -0
- package/src/core/lib/TLVParser.mjs +16 -7
- package/src/core/lib/Twofish.mjs +608 -0
- package/src/core/operations/AsconDecrypt.mjs +112 -0
- package/src/core/operations/AsconEncrypt.mjs +108 -0
- package/src/core/operations/AsconHash.mjs +49 -0
- package/src/core/operations/AsconMAC.mjs +68 -0
- package/src/core/operations/AutomatedValidationTestOp.mjs +84 -0
- package/src/core/operations/AvroToJSON.mjs +1 -1
- package/src/core/operations/BLAKE3.mjs +5 -1
- package/src/core/operations/BcryptCompare.mjs +11 -5
- package/src/core/operations/BitShiftLeft.mjs +4 -1
- package/src/core/operations/Bzip2Compress.mjs +1 -1
- package/src/core/operations/DechunkHTTPResponse.mjs +4 -1
- package/src/core/operations/ExtendedGCD.mjs +101 -0
- package/src/core/operations/FromBase.mjs +2 -1
- package/src/core/operations/FromCOBS.mjs +38 -0
- package/src/core/operations/FromDecimal.mjs +6 -1
- package/src/core/operations/FromHTMLEntity.mjs +2 -1458
- package/src/core/operations/GenerateDeBruijnSequence.mjs +8 -0
- package/src/core/operations/GenerateHOTP.mjs +21 -6
- package/src/core/operations/GenerateImage.mjs +22 -10
- package/src/core/operations/GeneratePrime.mjs +154 -0
- package/src/core/operations/GenerateTOTP.mjs +24 -7
- package/src/core/operations/Gzip.mjs +1 -3
- package/src/core/operations/Jsonata.mjs +12 -0
- package/src/core/operations/MIMEDecoding.mjs +1 -1
- package/src/core/operations/MOD.mjs +62 -0
- package/src/core/operations/ModularInverse.mjs +107 -0
- package/src/core/operations/PRESENTDecrypt.mjs +94 -0
- package/src/core/operations/PRESENTEncrypt.mjs +94 -0
- package/src/core/operations/ParityBit.mjs +1 -1
- package/src/core/operations/ParseIPv4Header.mjs +1 -1
- package/src/core/operations/ParseURI.mjs +18 -5
- package/src/core/operations/PseudoRandomNumberGenerator.mjs +2 -1
- package/src/core/operations/RandomPrime.mjs +154 -0
- package/src/core/operations/RenderPDF.mjs +100 -0
- package/src/core/operations/SHA2.mjs +1 -1
- package/src/core/operations/SM4Encrypt.mjs +1 -1
- package/src/core/operations/SetDifference.mjs +8 -1
- package/src/core/operations/SetIntersection.mjs +8 -1
- package/src/core/operations/ShowOnMap.mjs +14 -2
- package/src/core/operations/TEADecrypt.mjs +98 -0
- package/src/core/operations/TEAEncrypt.mjs +98 -0
- package/src/core/operations/ToBase.mjs +4 -4
- package/src/core/operations/ToBase32.mjs +20 -4
- package/src/core/operations/ToBinary.mjs +4 -1
- package/src/core/operations/ToCOBS.mjs +38 -0
- package/src/core/operations/ToHTMLEntity.mjs +7 -1430
- package/src/core/operations/ToHexdump.mjs +7 -1
- package/src/core/operations/TwofishDecrypt.mjs +94 -0
- package/src/core/operations/TwofishEncrypt.mjs +94 -0
- package/src/core/operations/URLEncode.mjs +22 -18
- package/src/core/operations/UnescapeUnicodeCharacters.mjs +2 -1
- package/src/core/operations/ViewBitPlane.mjs +9 -3
- package/src/core/operations/Wrap.mjs +5 -0
- package/src/core/operations/XORBruteForce.mjs +4 -1
- package/src/core/operations/XORChecksum.mjs +10 -3
- package/src/core/operations/XTEADecrypt.mjs +110 -0
- package/src/core/operations/XTEAEncrypt.mjs +110 -0
- package/src/core/operations/index.mjs +42 -0
- package/src/core/vendor/ascon.mjs +162 -0
- package/src/core/vendor/htmlEntities/entity.json +2233 -0
- package/src/core/vendor/htmlEntities/entity.txt +14 -0
- package/src/node/api.mjs +4 -1
- package/src/node/index.mjs +105 -0
- package/src/web/HTMLOperation.mjs +2 -1
- package/src/web/stylesheets/layout/_io.css +8 -0
- package/tests/browser/00_nightwatch.js +26 -0
- package/tests/browser/02_ops.js +20 -4
- package/tests/node/index.mjs +2 -0
- package/tests/node/tests/Dish.mjs +19 -0
- package/tests/node/tests/NodeDish.mjs +36 -0
- package/tests/node/tests/ToHTMLEntity.mjs +82 -0
- package/tests/node/tests/Utils.mjs +77 -0
- package/tests/node/tests/lib/ChartsProtocolPrototypePollution.mjs +90 -0
- package/tests/node/tests/nodeApi.mjs +33 -1
- package/tests/node/tests/operations.mjs +26 -1
- package/tests/operations/index.mjs +17 -0
- package/tests/operations/tests/Arithmetic.mjs +33 -0
- package/tests/operations/tests/Ascon.mjs +501 -0
- package/tests/operations/tests/AutomatedValidation.mjs +154 -0
- package/tests/operations/tests/BLAKE3.mjs +39 -1
- package/tests/operations/tests/Base32.mjs +22 -0
- package/tests/operations/tests/COBS.mjs +476 -0
- package/tests/operations/tests/CharEnc.mjs +2 -2
- package/tests/operations/tests/DechunkHTTPResponse.mjs +66 -0
- package/tests/operations/tests/ExtendedGCD.mjs +78 -0
- package/tests/operations/tests/FromBase.mjs +66 -0
- package/tests/operations/tests/FromDecimal.mjs +55 -0
- package/tests/operations/tests/GenerateLoremIpsum.mjs +2 -2
- package/tests/operations/tests/Gzip.mjs +60 -0
- package/tests/operations/tests/HTMLEntity.mjs +126 -0
- package/tests/operations/tests/Hash.mjs +44 -0
- package/tests/operations/tests/Hexdump.mjs +11 -0
- package/tests/operations/tests/Image.mjs +26 -0
- package/tests/operations/tests/Jsonata.mjs +23 -0
- package/tests/operations/tests/MIMEDecoding.mjs +33 -0
- package/tests/operations/tests/MOD.mjs +208 -0
- package/tests/operations/tests/Median.mjs +33 -0
- package/tests/operations/tests/ModularInverse.mjs +78 -0
- package/tests/operations/tests/OTP.mjs +167 -2
- package/tests/operations/tests/PRESENT.mjs +465 -0
- package/tests/operations/tests/ParseIPv4Header.mjs +11 -0
- package/tests/operations/tests/ParseTLV.mjs +41 -0
- package/tests/operations/tests/RenderPDF.mjs +55 -0
- package/tests/operations/tests/SM2.mjs +1 -1
- package/tests/operations/tests/SetDifference.mjs +22 -0
- package/tests/operations/tests/SetIntersection.mjs +23 -1
- package/tests/operations/tests/ShowOnMap.mjs +61 -0
- package/tests/operations/tests/TEA.mjs +566 -0
- package/tests/operations/tests/Twofish.mjs +486 -0
- package/tests/operations/tests/URLEncodeDecode.mjs +26 -0
- package/tests/operations/tests/UnescapeUnicodeCharacters.mjs +88 -0
- package/tests/operations/tests/Wrap.mjs +44 -0
- package/webpack.config.js +3 -3
|
@@ -8,6 +8,8 @@ import Operation from "../Operation.mjs";
|
|
|
8
8
|
import Utils from "../Utils.mjs";
|
|
9
9
|
import OperationError from "../errors/OperationError.mjs";
|
|
10
10
|
|
|
11
|
+
const MAX_WIDTH = 65536;
|
|
12
|
+
|
|
11
13
|
/**
|
|
12
14
|
* To Hexdump operation
|
|
13
15
|
*/
|
|
@@ -30,7 +32,8 @@ class ToHexdump extends Operation {
|
|
|
30
32
|
"name": "Width",
|
|
31
33
|
"type": "number",
|
|
32
34
|
"value": 16,
|
|
33
|
-
"min": 1
|
|
35
|
+
"min": 1,
|
|
36
|
+
"max": MAX_WIDTH
|
|
34
37
|
},
|
|
35
38
|
{
|
|
36
39
|
"name": "Upper case hex",
|
|
@@ -63,6 +66,9 @@ class ToHexdump extends Operation {
|
|
|
63
66
|
if (length < 1 || Math.round(length) !== length)
|
|
64
67
|
throw new OperationError("Width must be a positive integer");
|
|
65
68
|
|
|
69
|
+
if (length > MAX_WIDTH)
|
|
70
|
+
throw new OperationError(`Width must be no more than ${MAX_WIDTH}`);
|
|
71
|
+
|
|
66
72
|
const lines = [];
|
|
67
73
|
for (let i = 0; i < data.length; i += length) {
|
|
68
74
|
let lineNo = Utils.hex(i, 8);
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Medjedtxm
|
|
3
|
+
* @copyright Crown Copyright 2026
|
|
4
|
+
* @license Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Operation from "../Operation.mjs";
|
|
8
|
+
import Utils from "../Utils.mjs";
|
|
9
|
+
import OperationError from "../errors/OperationError.mjs";
|
|
10
|
+
import { toHex } from "../lib/Hex.mjs";
|
|
11
|
+
import { decryptTwofish } from "../lib/Twofish.mjs";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Twofish Decrypt operation
|
|
15
|
+
*/
|
|
16
|
+
class TwofishDecrypt extends Operation {
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* TwofishDecrypt constructor
|
|
20
|
+
*/
|
|
21
|
+
constructor() {
|
|
22
|
+
super();
|
|
23
|
+
|
|
24
|
+
this.name = "Twofish Decrypt";
|
|
25
|
+
this.module = "Ciphers";
|
|
26
|
+
this.description = "Twofish is a symmetric key block cipher designed by Bruce Schneier. It was one of the five AES finalists. Twofish operates on 128-bit blocks and supports key sizes of 128, 192, or 256 bits with 16 rounds of a Feistel network.<br><br>When using CBC or ECB mode, the PKCS#7 padding scheme is used.";
|
|
27
|
+
this.infoURL = "https://wikipedia.org/wiki/Twofish";
|
|
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": "IV",
|
|
39
|
+
"type": "toggleString",
|
|
40
|
+
"value": "",
|
|
41
|
+
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "Mode",
|
|
45
|
+
"type": "option",
|
|
46
|
+
"value": ["CBC", "CFB", "OFB", "CTR", "ECB"]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "Input",
|
|
50
|
+
"type": "option",
|
|
51
|
+
"value": ["Hex", "Raw"]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "Output",
|
|
55
|
+
"type": "option",
|
|
56
|
+
"value": ["Raw", "Hex"]
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "Padding",
|
|
60
|
+
"type": "option",
|
|
61
|
+
"value": ["PKCS5", "NO", "ZERO", "RANDOM", "BIT"]
|
|
62
|
+
}
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @param {string} input
|
|
68
|
+
* @param {Object[]} args
|
|
69
|
+
* @returns {string}
|
|
70
|
+
*/
|
|
71
|
+
run(input, args) {
|
|
72
|
+
const key = Utils.convertToByteArray(args[0].string, args[0].option),
|
|
73
|
+
iv = Utils.convertToByteArray(args[1].string, args[1].option),
|
|
74
|
+
[,, mode, inputType, outputType, padding] = args;
|
|
75
|
+
|
|
76
|
+
if (key.length !== 16 && key.length !== 24 && key.length !== 32)
|
|
77
|
+
throw new OperationError(`Invalid key length: ${key.length} bytes
|
|
78
|
+
|
|
79
|
+
Twofish uses a key length of 16 bytes (128 bits), 24 bytes (192 bits), or 32 bytes (256 bits).`);
|
|
80
|
+
|
|
81
|
+
if (iv.length !== 16 && mode !== "ECB")
|
|
82
|
+
throw new OperationError(`Invalid IV length: ${iv.length} bytes
|
|
83
|
+
|
|
84
|
+
Twofish uses an IV length of 16 bytes (128 bits).
|
|
85
|
+
Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
|
|
86
|
+
|
|
87
|
+
input = Utils.convertToByteArray(input, inputType);
|
|
88
|
+
const output = decryptTwofish(input, key, iv, mode, padding);
|
|
89
|
+
return outputType === "Hex" ? toHex(output, "") : Utils.byteArrayToUtf8(output);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export default TwofishDecrypt;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Medjedtxm
|
|
3
|
+
* @copyright Crown Copyright 2026
|
|
4
|
+
* @license Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Operation from "../Operation.mjs";
|
|
8
|
+
import Utils from "../Utils.mjs";
|
|
9
|
+
import OperationError from "../errors/OperationError.mjs";
|
|
10
|
+
import { toHex } from "../lib/Hex.mjs";
|
|
11
|
+
import { encryptTwofish } from "../lib/Twofish.mjs";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Twofish Encrypt operation
|
|
15
|
+
*/
|
|
16
|
+
class TwofishEncrypt extends Operation {
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* TwofishEncrypt constructor
|
|
20
|
+
*/
|
|
21
|
+
constructor() {
|
|
22
|
+
super();
|
|
23
|
+
|
|
24
|
+
this.name = "Twofish Encrypt";
|
|
25
|
+
this.module = "Ciphers";
|
|
26
|
+
this.description = "Twofish is a symmetric key block cipher designed by Bruce Schneier. It was one of the five AES finalists. Twofish operates on 128-bit blocks and supports key sizes of 128, 192, or 256 bits with 16 rounds of a Feistel network.<br><br>When using CBC or ECB mode, the PKCS#7 padding scheme is used.";
|
|
27
|
+
this.infoURL = "https://wikipedia.org/wiki/Twofish";
|
|
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": "IV",
|
|
39
|
+
"type": "toggleString",
|
|
40
|
+
"value": "",
|
|
41
|
+
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "Mode",
|
|
45
|
+
"type": "option",
|
|
46
|
+
"value": ["CBC", "CFB", "OFB", "CTR", "ECB"]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "Input",
|
|
50
|
+
"type": "option",
|
|
51
|
+
"value": ["Raw", "Hex"]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "Output",
|
|
55
|
+
"type": "option",
|
|
56
|
+
"value": ["Hex", "Raw"]
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "Padding",
|
|
60
|
+
"type": "option",
|
|
61
|
+
"value": ["PKCS5", "NO", "ZERO", "RANDOM", "BIT"]
|
|
62
|
+
}
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @param {string} input
|
|
68
|
+
* @param {Object[]} args
|
|
69
|
+
* @returns {string}
|
|
70
|
+
*/
|
|
71
|
+
run(input, args) {
|
|
72
|
+
const key = Utils.convertToByteArray(args[0].string, args[0].option),
|
|
73
|
+
iv = Utils.convertToByteArray(args[1].string, args[1].option),
|
|
74
|
+
[,, mode, inputType, outputType, padding] = args;
|
|
75
|
+
|
|
76
|
+
if (key.length !== 16 && key.length !== 24 && key.length !== 32)
|
|
77
|
+
throw new OperationError(`Invalid key length: ${key.length} bytes
|
|
78
|
+
|
|
79
|
+
Twofish uses a key length of 16 bytes (128 bits), 24 bytes (192 bits), or 32 bytes (256 bits).`);
|
|
80
|
+
|
|
81
|
+
if (iv.length !== 16 && mode !== "ECB")
|
|
82
|
+
throw new OperationError(`Invalid IV length: ${iv.length} bytes
|
|
83
|
+
|
|
84
|
+
Twofish uses an IV length of 16 bytes (128 bits).
|
|
85
|
+
Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
|
|
86
|
+
|
|
87
|
+
input = Utils.convertToByteArray(input, inputType);
|
|
88
|
+
const output = encryptTwofish(input, key, iv, mode, padding);
|
|
89
|
+
return outputType === "Hex" ? toHex(output, "") : Utils.byteArrayToUtf8(output);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export default TwofishEncrypt;
|
|
@@ -21,7 +21,7 @@ class URLEncode extends Operation {
|
|
|
21
21
|
this.module = "URL";
|
|
22
22
|
this.description = "Encodes problematic characters into percent-encoding, a format supported by URIs/URLs.<br><br>e.g. <code>=</code> becomes <code>%3d</code>";
|
|
23
23
|
this.infoURL = "https://wikipedia.org/wiki/Percent-encoding";
|
|
24
|
-
this.inputType = "
|
|
24
|
+
this.inputType = "byteArray";
|
|
25
25
|
this.outputType = "string";
|
|
26
26
|
this.args = [
|
|
27
27
|
{
|
|
@@ -33,34 +33,38 @@ class URLEncode extends Operation {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
* @param {
|
|
36
|
+
* @param {byteArray} input
|
|
37
37
|
* @param {Object[]} args
|
|
38
38
|
* @returns {string}
|
|
39
39
|
*/
|
|
40
40
|
run(input, args) {
|
|
41
41
|
const encodeAll = args[0];
|
|
42
|
-
return
|
|
42
|
+
return this.encodeBytes(input, encodeAll);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
|
-
* Encode
|
|
46
|
+
* Encode bytes in URL using percent encoding.
|
|
47
47
|
*
|
|
48
|
-
* @param {
|
|
48
|
+
* @param {byteArray} bytes
|
|
49
|
+
* @param {boolean} encodeAll
|
|
49
50
|
* @returns {string}
|
|
50
51
|
*/
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
.
|
|
60
|
-
|
|
61
|
-
.
|
|
62
|
-
|
|
63
|
-
|
|
52
|
+
encodeBytes(bytes, encodeAll) {
|
|
53
|
+
const safeChars = encodeAll ?
|
|
54
|
+
/^[A-Za-z0-9]$/ :
|
|
55
|
+
/^[A-Za-z0-9:/?#[\]@!$&'()*+,;=%]$/;
|
|
56
|
+
|
|
57
|
+
let output = "";
|
|
58
|
+
|
|
59
|
+
for (const byte of bytes) {
|
|
60
|
+
const char = String.fromCharCode(byte);
|
|
61
|
+
|
|
62
|
+
output += safeChars.test(char) ?
|
|
63
|
+
char :
|
|
64
|
+
"%" + byte.toString(16).toUpperCase().padStart(2, "0");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return output;
|
|
64
68
|
}
|
|
65
69
|
|
|
66
70
|
}
|
|
@@ -56,7 +56,8 @@ class UnescapeUnicodeCharacters extends Operation {
|
|
|
56
56
|
*/
|
|
57
57
|
run(input, args) {
|
|
58
58
|
const prefix = prefixToRegex[args[0]],
|
|
59
|
-
|
|
59
|
+
quantifier = args[0] === "U+" ? "{4,6}" : "{4}",
|
|
60
|
+
regex = new RegExp(prefix+"([a-f\\d]"+quantifier+")", "ig");
|
|
60
61
|
let output = "",
|
|
61
62
|
m,
|
|
62
63
|
i = 0;
|
|
@@ -52,9 +52,15 @@ class ViewBitPlane extends Operation {
|
|
|
52
52
|
if (!isImage(input))
|
|
53
53
|
throw new OperationError("Please enter a valid image file.");
|
|
54
54
|
|
|
55
|
-
const [colour, bit] = args
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
const [colour, bit] = args;
|
|
56
|
+
let parsedImage;
|
|
57
|
+
try {
|
|
58
|
+
parsedImage = await Jimp.read(input);
|
|
59
|
+
} catch (err) {
|
|
60
|
+
throw new OperationError(`Error loading image. (${err})`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const width = parsedImage.bitmap.width,
|
|
58
64
|
height = parsedImage.bitmap.height,
|
|
59
65
|
colourIndex = COLOUR_OPTIONS.indexOf(colour),
|
|
60
66
|
bitIndex = 7 - bit;
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
import Operation from "../Operation.mjs";
|
|
8
8
|
|
|
9
|
+
const MAX_LINE_WIDTH = 65536;
|
|
10
|
+
|
|
9
11
|
/**
|
|
10
12
|
* Wrap operation
|
|
11
13
|
*/
|
|
@@ -27,6 +29,9 @@ class Wrap extends Operation {
|
|
|
27
29
|
"name": "Line Width",
|
|
28
30
|
"type": "number",
|
|
29
31
|
"value": 64,
|
|
32
|
+
"min": 1,
|
|
33
|
+
"max": MAX_LINE_WIDTH,
|
|
34
|
+
"integer": true,
|
|
30
35
|
},
|
|
31
36
|
];
|
|
32
37
|
}
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
import Operation from "../Operation.mjs";
|
|
8
8
|
import Utils from "../Utils.mjs";
|
|
9
9
|
import { toHex } from "../lib/Hex.mjs";
|
|
10
|
+
import OperationError from "../errors/OperationError.mjs";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* XOR Checksum operation
|
|
13
14
|
*/
|
|
14
15
|
class XORChecksum extends Operation {
|
|
15
|
-
|
|
16
16
|
/**
|
|
17
17
|
* XORChecksum constructor
|
|
18
18
|
*/
|
|
@@ -21,7 +21,8 @@ class XORChecksum extends Operation {
|
|
|
21
21
|
|
|
22
22
|
this.name = "XOR Checksum";
|
|
23
23
|
this.module = "Crypto";
|
|
24
|
-
this.description =
|
|
24
|
+
this.description =
|
|
25
|
+
"XOR Checksum splits the input into blocks of a configurable size and performs the XOR operation on these blocks.";
|
|
25
26
|
this.infoURL = "https://wikipedia.org/wiki/XOR";
|
|
26
27
|
this.inputType = "ArrayBuffer";
|
|
27
28
|
this.outputType = "string";
|
|
@@ -29,7 +30,7 @@ class XORChecksum extends Operation {
|
|
|
29
30
|
{
|
|
30
31
|
name: "Blocksize",
|
|
31
32
|
type: "number",
|
|
32
|
-
value: 4
|
|
33
|
+
value: 4,
|
|
33
34
|
},
|
|
34
35
|
];
|
|
35
36
|
}
|
|
@@ -41,6 +42,12 @@ class XORChecksum extends Operation {
|
|
|
41
42
|
*/
|
|
42
43
|
run(input, args) {
|
|
43
44
|
const blocksize = args[0];
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
if (!Number.isInteger(blocksize) || blocksize <= 0) {
|
|
48
|
+
throw new OperationError("Blocksize must be a positive integer.");
|
|
49
|
+
}
|
|
50
|
+
|
|
44
51
|
input = new Uint8Array(input);
|
|
45
52
|
|
|
46
53
|
const res = Array(blocksize);
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Medjedtxm
|
|
3
|
+
* @copyright Crown Copyright 2026
|
|
4
|
+
* @license Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Operation from "../Operation.mjs";
|
|
8
|
+
import Utils from "../Utils.mjs";
|
|
9
|
+
import OperationError from "../errors/OperationError.mjs";
|
|
10
|
+
import { toHex } from "../lib/Hex.mjs";
|
|
11
|
+
import { decryptXTEA, TEA_BLOCK_SIZE } from "../lib/TEA.mjs";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* XTEA Decrypt operation
|
|
15
|
+
*/
|
|
16
|
+
class XTEADecrypt extends Operation {
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* XTEADecrypt constructor
|
|
20
|
+
*/
|
|
21
|
+
constructor() {
|
|
22
|
+
super();
|
|
23
|
+
|
|
24
|
+
this.name = "XTEA Decrypt";
|
|
25
|
+
this.module = "Ciphers";
|
|
26
|
+
this.description = "XTEA (eXtended Tiny Encryption Algorithm) is a block cipher designed by David Wheeler and Roger Needham in 1997 as a successor to TEA, correcting several weaknesses identified in the original algorithm. It operates on 64-bit blocks using a 128-bit key with an improved key schedule that uses sum-dependent key word selection to resist related-key attacks.<br><br>XTEA retains the simplicity and compact implementation of TEA whilst providing significantly improved security. It is frequently encountered in malware analysis and CTF challenges due to its straightforward implementation.<br><br><b>Key:</b> Must be exactly 16 bytes (128 bits).<br><br><b>IV:</b> The Initialisation Vector should be 8 bytes (64 bits). If not entered, it will default to null bytes.<br><br><b>Rounds:</b> The recommended number of rounds is 32 (default). The reference implementation by Wheeler & Needham accepts a configurable round count.<br><br><b>Padding:</b> In CBC and ECB mode, the PKCS#5 padding scheme is used.";
|
|
27
|
+
this.infoURL = "https://wikipedia.org/wiki/XTEA";
|
|
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": "IV",
|
|
39
|
+
"type": "toggleString",
|
|
40
|
+
"value": "",
|
|
41
|
+
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "Mode",
|
|
45
|
+
"type": "option",
|
|
46
|
+
"value": ["CBC", "CFB", "OFB", "CTR", "ECB"]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "Input",
|
|
50
|
+
"type": "option",
|
|
51
|
+
"value": ["Hex", "Raw"]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "Output",
|
|
55
|
+
"type": "option",
|
|
56
|
+
"value": ["Raw", "Hex"]
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "Padding",
|
|
60
|
+
"type": "option",
|
|
61
|
+
"value": ["PKCS5", "NO", "ZERO", "RANDOM", "BIT"]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "Rounds",
|
|
65
|
+
"type": "number",
|
|
66
|
+
"value": 32,
|
|
67
|
+
"min": 1,
|
|
68
|
+
"max": 255
|
|
69
|
+
}
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @param {string} input
|
|
75
|
+
* @param {Object[]} args
|
|
76
|
+
* @returns {string}
|
|
77
|
+
*/
|
|
78
|
+
run(input, args) {
|
|
79
|
+
const key = Utils.convertToByteArray(args[0].string, args[0].option),
|
|
80
|
+
iv = Utils.convertToByteArray(args[1].string, args[1].option),
|
|
81
|
+
[,, mode, inputType, outputType, padding, rounds] = args;
|
|
82
|
+
|
|
83
|
+
if (key.length !== 16)
|
|
84
|
+
throw new OperationError(`Invalid key length: ${key.length} bytes
|
|
85
|
+
|
|
86
|
+
XTEA requires a key length of 16 bytes (128 bits).
|
|
87
|
+
Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
|
|
88
|
+
|
|
89
|
+
if (iv.length !== TEA_BLOCK_SIZE && iv.length !== 0 && mode !== "ECB")
|
|
90
|
+
throw new OperationError(`Invalid IV length: ${iv.length} bytes
|
|
91
|
+
|
|
92
|
+
XTEA uses an IV length of ${TEA_BLOCK_SIZE} bytes (${TEA_BLOCK_SIZE * 8} bits).
|
|
93
|
+
Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
|
|
94
|
+
|
|
95
|
+
if (!Number.isInteger(rounds) || rounds < 1 || rounds > 255)
|
|
96
|
+
throw new OperationError(`Invalid number of rounds: ${rounds}
|
|
97
|
+
|
|
98
|
+
Rounds must be an integer between 1 and 255. Standard XTEA uses 32 rounds.`);
|
|
99
|
+
|
|
100
|
+
// Default IV to null bytes if empty (like AES)
|
|
101
|
+
const actualIv = iv.length === 0 ? new Array(TEA_BLOCK_SIZE).fill(0) : iv;
|
|
102
|
+
|
|
103
|
+
input = Utils.convertToByteArray(input, inputType);
|
|
104
|
+
const output = decryptXTEA(input, key, actualIv, mode, padding, rounds);
|
|
105
|
+
return outputType === "Hex" ? toHex(output, "") : Utils.byteArrayToUtf8(output);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export default XTEADecrypt;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Medjedtxm
|
|
3
|
+
* @copyright Crown Copyright 2026
|
|
4
|
+
* @license Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Operation from "../Operation.mjs";
|
|
8
|
+
import Utils from "../Utils.mjs";
|
|
9
|
+
import OperationError from "../errors/OperationError.mjs";
|
|
10
|
+
import { toHex } from "../lib/Hex.mjs";
|
|
11
|
+
import { encryptXTEA, TEA_BLOCK_SIZE } from "../lib/TEA.mjs";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* XTEA Encrypt operation
|
|
15
|
+
*/
|
|
16
|
+
class XTEAEncrypt extends Operation {
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* XTEAEncrypt constructor
|
|
20
|
+
*/
|
|
21
|
+
constructor() {
|
|
22
|
+
super();
|
|
23
|
+
|
|
24
|
+
this.name = "XTEA Encrypt";
|
|
25
|
+
this.module = "Ciphers";
|
|
26
|
+
this.description = "XTEA (eXtended Tiny Encryption Algorithm) is a block cipher designed by David Wheeler and Roger Needham in 1997 as a successor to TEA, correcting several weaknesses identified in the original algorithm. It operates on 64-bit blocks using a 128-bit key with an improved key schedule that uses sum-dependent key word selection to resist related-key attacks.<br><br>XTEA retains the simplicity and compact implementation of TEA whilst providing significantly improved security. It is frequently encountered in malware analysis and CTF challenges due to its straightforward implementation.<br><br><b>Key:</b> Must be exactly 16 bytes (128 bits).<br><br><b>IV:</b> The Initialisation Vector should be 8 bytes (64 bits). If not entered, it will default to null bytes.<br><br><b>Rounds:</b> The recommended number of rounds is 32 (default). The reference implementation by Wheeler & Needham accepts a configurable round count.<br><br><b>Padding:</b> In CBC and ECB mode, the PKCS#5 padding scheme is used.";
|
|
27
|
+
this.infoURL = "https://wikipedia.org/wiki/XTEA";
|
|
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": "IV",
|
|
39
|
+
"type": "toggleString",
|
|
40
|
+
"value": "",
|
|
41
|
+
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "Mode",
|
|
45
|
+
"type": "option",
|
|
46
|
+
"value": ["CBC", "CFB", "OFB", "CTR", "ECB"]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "Input",
|
|
50
|
+
"type": "option",
|
|
51
|
+
"value": ["Raw", "Hex"]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "Output",
|
|
55
|
+
"type": "option",
|
|
56
|
+
"value": ["Hex", "Raw"]
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "Padding",
|
|
60
|
+
"type": "option",
|
|
61
|
+
"value": ["PKCS5", "NO", "ZERO", "RANDOM", "BIT"]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "Rounds",
|
|
65
|
+
"type": "number",
|
|
66
|
+
"value": 32,
|
|
67
|
+
"min": 1,
|
|
68
|
+
"max": 255
|
|
69
|
+
}
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @param {string} input
|
|
75
|
+
* @param {Object[]} args
|
|
76
|
+
* @returns {string}
|
|
77
|
+
*/
|
|
78
|
+
run(input, args) {
|
|
79
|
+
const key = Utils.convertToByteArray(args[0].string, args[0].option),
|
|
80
|
+
iv = Utils.convertToByteArray(args[1].string, args[1].option),
|
|
81
|
+
[,, mode, inputType, outputType, padding, rounds] = args;
|
|
82
|
+
|
|
83
|
+
if (key.length !== 16)
|
|
84
|
+
throw new OperationError(`Invalid key length: ${key.length} bytes
|
|
85
|
+
|
|
86
|
+
XTEA requires a key length of 16 bytes (128 bits).
|
|
87
|
+
Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
|
|
88
|
+
|
|
89
|
+
if (iv.length !== TEA_BLOCK_SIZE && iv.length !== 0 && mode !== "ECB")
|
|
90
|
+
throw new OperationError(`Invalid IV length: ${iv.length} bytes
|
|
91
|
+
|
|
92
|
+
XTEA uses an IV length of ${TEA_BLOCK_SIZE} bytes (${TEA_BLOCK_SIZE * 8} bits).
|
|
93
|
+
Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
|
|
94
|
+
|
|
95
|
+
if (!Number.isInteger(rounds) || rounds < 1 || rounds > 255)
|
|
96
|
+
throw new OperationError(`Invalid number of rounds: ${rounds}
|
|
97
|
+
|
|
98
|
+
Rounds must be an integer between 1 and 255. Standard XTEA uses 32 rounds.`);
|
|
99
|
+
|
|
100
|
+
// Default IV to null bytes if empty (like AES)
|
|
101
|
+
const actualIv = iv.length === 0 ? new Array(TEA_BLOCK_SIZE).fill(0) : iv;
|
|
102
|
+
|
|
103
|
+
input = Utils.convertToByteArray(input, inputType);
|
|
104
|
+
const output = encryptXTEA(input, key, actualIv, mode, padding, rounds);
|
|
105
|
+
return outputType === "Hex" ? toHex(output, "") : Utils.byteArrayToUtf8(output);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export default XTEAEncrypt;
|