cyberchef 11.0.0 → 11.1.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/CHANGELOG.md +144 -0
- package/Dockerfile +2 -2
- package/Gruntfile.js +10 -5
- package/README.md +3 -1
- package/SECURITY.md +8 -18
- package/package.json +35 -34
- package/src/core/config/Categories.json +6 -0
- package/src/core/config/OperationConfig.json +140 -16
- package/src/core/config/modules/Default.mjs +8 -0
- package/src/core/config/modules/PGP.mjs +2 -0
- package/src/core/config/scripts/generateOpsIndex.mjs +63 -0
- package/src/core/config/scripts/newOperation.mjs +31 -4
- package/src/core/operations/AESDecrypt.mjs +61 -16
- package/src/core/operations/AESEncrypt.mjs +26 -11
- package/src/core/operations/BLAKE3.mjs +13 -7
- package/src/core/operations/BSONDeserialise.mjs +2 -2
- package/src/core/operations/BSONSerialise.mjs +3 -2
- package/src/core/operations/Bcrypt.mjs +1 -1
- package/src/core/operations/BcryptCompare.mjs +1 -1
- package/src/core/operations/DecodeText.mjs +4 -0
- package/src/core/operations/EncodeText.mjs +4 -0
- package/src/core/operations/EscapeSmartCharacters.mjs +129 -0
- package/src/core/operations/GenerateLoremIpsum.mjs +34 -3
- package/src/core/operations/GeneratePGPKeyPair.mjs +8 -7
- package/src/core/operations/PGPSign.mjs +83 -0
- package/src/core/operations/ParseEthernetFrame.mjs +1 -1
- package/src/core/operations/ParseIPv4Header.mjs +1 -1
- package/src/core/operations/ParseObjectIDTimestamp.mjs +2 -2
- package/src/core/operations/ParseUserAgent.mjs +1 -1
- package/src/core/operations/ROR13.mjs +83 -0
- package/src/core/operations/RemoveANSIEscapeCodes.mjs +41 -0
- package/src/core/operations/SeriesChart.mjs +16 -0
- package/src/core/operations/Wrap.mjs +47 -0
- package/src/core/operations/index.mjs +10 -0
- package/src/node/index.mjs +25 -0
- package/src/web/App.mjs +19 -1
- package/src/web/HTMLIngredient.mjs +1 -0
- package/src/web/html/index.html +3 -3
- package/src/web/static/sitemap.mjs +3 -3
- package/src/web/waiters/RecipeWaiter.mjs +9 -1
- package/tests/browser/02_ops.js +7 -7
- package/tests/browser/03_recipe_load.js +48 -0
- package/tests/browser/browserUtils.js +6 -3
- package/tests/node/index.mjs +1 -0
- package/tests/node/tests/PGP.mjs +69 -0
- package/tests/node/tests/operations.mjs +41 -2
- package/tests/operations/index.mjs +71 -66
- package/tests/operations/tests/BLAKE3.mjs +18 -0
- package/tests/operations/tests/CharEnc.mjs +26 -0
- package/tests/operations/tests/Charts.mjs +11 -0
- package/tests/operations/tests/Crypt.mjs +288 -62
- package/tests/operations/tests/EscapeSmartCharacters.mjs +132 -0
- package/tests/operations/tests/FlaskSession.mjs +11 -8
- package/tests/operations/tests/GenerateLoremIpsum.mjs +80 -0
- package/tests/operations/tests/IPv6Transition.mjs +4 -4
- package/tests/operations/tests/PGP.mjs +178 -154
- package/tests/operations/tests/ParseEthernetFrame.mjs +11 -0
- package/tests/operations/tests/ParseIPv4Header.mjs +23 -0
- package/tests/operations/tests/ParseX509CRL.mjs +16 -16
- package/tests/operations/tests/ROR13.mjs +45 -0
- package/tests/operations/tests/Register.mjs +3 -1
- package/tests/operations/tests/RemoveANSIEscapeCodes.mjs +62 -0
- package/tests/operations/tests/Wrap.mjs +44 -0
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
import Operation from "../Operation.mjs";
|
|
8
8
|
import OperationError from "../errors/OperationError.mjs";
|
|
9
|
-
import
|
|
9
|
+
import Utils from "../Utils.mjs";
|
|
10
|
+
import { blake3 } from "@noble/hashes/blake3.js";
|
|
11
|
+
import { bytesToHex } from "@noble/hashes/utils.js";
|
|
12
|
+
|
|
10
13
|
/**
|
|
11
14
|
* BLAKE3 operation
|
|
12
15
|
*/
|
|
@@ -44,13 +47,16 @@ class BLAKE3 extends Operation {
|
|
|
44
47
|
run(input, args) {
|
|
45
48
|
const key = args[1];
|
|
46
49
|
const size = args[0];
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
const opts = { dkLen: size };
|
|
51
|
+
const inputBytes = new Uint8Array(Utils.strToArrayBuffer(input));
|
|
52
|
+
if (key !== "") {
|
|
53
|
+
const keyBytes = new Uint8Array(Utils.strToArrayBuffer(key));
|
|
54
|
+
if (keyBytes.length !== 32) {
|
|
55
|
+
throw new OperationError("The key must be exactly 32 bytes long");
|
|
56
|
+
}
|
|
57
|
+
opts.key = keyBytes;
|
|
52
58
|
}
|
|
53
|
-
return blake3(
|
|
59
|
+
return bytesToHex(blake3(inputBytes, opts));
|
|
54
60
|
}
|
|
55
61
|
|
|
56
62
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import Operation from "../Operation.mjs";
|
|
8
|
-
import
|
|
8
|
+
import { deserialize } from "bson";
|
|
9
9
|
import OperationError from "../errors/OperationError.mjs";
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -37,7 +37,7 @@ class BSONDeserialise extends Operation {
|
|
|
37
37
|
if (!input.byteLength) return "";
|
|
38
38
|
|
|
39
39
|
try {
|
|
40
|
-
const data =
|
|
40
|
+
const data = deserialize(new Uint8Array(input));
|
|
41
41
|
return JSON.stringify(data, null, 2);
|
|
42
42
|
} catch (err) {
|
|
43
43
|
throw new OperationError(err.toString());
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import Operation from "../Operation.mjs";
|
|
8
|
-
import
|
|
8
|
+
import { serialize } from "bson";
|
|
9
9
|
import OperationError from "../errors/OperationError.mjs";
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -38,7 +38,8 @@ class BSONSerialise extends Operation {
|
|
|
38
38
|
|
|
39
39
|
try {
|
|
40
40
|
const data = JSON.parse(input);
|
|
41
|
-
|
|
41
|
+
const result = serialize(data);
|
|
42
|
+
return result.buffer.slice(result.byteOffset, result.byteOffset + result.byteLength);
|
|
42
43
|
} catch (err) {
|
|
43
44
|
throw new OperationError(err.toString());
|
|
44
45
|
}
|
|
@@ -43,7 +43,7 @@ class Bcrypt extends Operation {
|
|
|
43
43
|
const rounds = args[0];
|
|
44
44
|
const salt = await bcrypt.genSalt(rounds);
|
|
45
45
|
|
|
46
|
-
return await bcrypt.hash(input, salt,
|
|
46
|
+
return await bcrypt.hash(input, salt, undefined, p => {
|
|
47
47
|
// Progress callback
|
|
48
48
|
if (isWorkerEnvironment())
|
|
49
49
|
self.sendStatusMessage(`Progress: ${(p * 100).toFixed(0)}%`);
|
|
@@ -43,7 +43,7 @@ class BcryptCompare extends Operation {
|
|
|
43
43
|
async run(input, args) {
|
|
44
44
|
const hash = args[0];
|
|
45
45
|
|
|
46
|
-
const match = await bcrypt.compare(input, hash,
|
|
46
|
+
const match = await bcrypt.compare(input, hash, undefined, p => {
|
|
47
47
|
// Progress callback
|
|
48
48
|
if (isWorkerEnvironment())
|
|
49
49
|
self.sendStatusMessage(`Progress: ${(p * 100).toFixed(0)}%`);
|
|
@@ -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 cptable from "codepage";
|
|
9
10
|
import {CHR_ENC_CODE_PAGES} from "../lib/ChrEnc.mjs";
|
|
10
11
|
|
|
@@ -48,6 +49,9 @@ class DecodeText extends Operation {
|
|
|
48
49
|
*/
|
|
49
50
|
run(input, args) {
|
|
50
51
|
const format = CHR_ENC_CODE_PAGES[args[0]];
|
|
52
|
+
if (!format) {
|
|
53
|
+
throw new OperationError("Invalid encoding");
|
|
54
|
+
}
|
|
51
55
|
return cptable.utils.decode(format, new Uint8Array(input));
|
|
52
56
|
}
|
|
53
57
|
|
|
@@ -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 cptable from "codepage";
|
|
9
10
|
import {CHR_ENC_CODE_PAGES} from "../lib/ChrEnc.mjs";
|
|
10
11
|
|
|
@@ -48,6 +49,9 @@ class EncodeText extends Operation {
|
|
|
48
49
|
*/
|
|
49
50
|
run(input, args) {
|
|
50
51
|
const format = CHR_ENC_CODE_PAGES[args[0]];
|
|
52
|
+
if (!format) {
|
|
53
|
+
throw new OperationError("Invalid encoding");
|
|
54
|
+
}
|
|
51
55
|
const encoded = cptable.utils.encode(format, input);
|
|
52
56
|
return new Uint8Array(encoded).buffer;
|
|
53
57
|
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author HarelKatz [github.com/HarelKatz]
|
|
3
|
+
* @copyright Crown Copyright 2026
|
|
4
|
+
* @license Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Operation from "../Operation.mjs";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Escape Smart Characters operation
|
|
11
|
+
*/
|
|
12
|
+
class EscapeSmartCharacters extends Operation {
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* EscapeSmartCharacters constructor
|
|
16
|
+
*/
|
|
17
|
+
constructor() {
|
|
18
|
+
super();
|
|
19
|
+
|
|
20
|
+
this.name = "Escape Smart Characters";
|
|
21
|
+
this.module = "Default";
|
|
22
|
+
this.description = "Converts smart (typographic) Unicode characters — e.g. smart quotes, em/en dashes, ellipses, ©, ®, ™, arrows — into their plain ASCII equivalents.<br><br>Characters with no ASCII mapping (e.g. <code>☣</code>) are handled according to the 'Unmappable characters' option.<br><br>e.g. <code>“Hello” — world…</code> becomes <code>\"Hello\" -- world...</code>";
|
|
23
|
+
this.infoURL = "";
|
|
24
|
+
this.inputType = "string";
|
|
25
|
+
this.outputType = "string";
|
|
26
|
+
this.args = [
|
|
27
|
+
{
|
|
28
|
+
name: "Unmappable characters",
|
|
29
|
+
type: "option",
|
|
30
|
+
value: ["Include", "Remove", "Replace with '.'"]
|
|
31
|
+
}
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {string} input
|
|
37
|
+
* @param {Object[]} args
|
|
38
|
+
* @returns {string}
|
|
39
|
+
*/
|
|
40
|
+
run(input, args) {
|
|
41
|
+
const [unmappable] = args;
|
|
42
|
+
let result = "";
|
|
43
|
+
for (const ch of input) {
|
|
44
|
+
if (ch.codePointAt(0) < 128) {
|
|
45
|
+
result += ch;
|
|
46
|
+
} else if (Object.prototype.hasOwnProperty.call(SMART_MAP, ch)) {
|
|
47
|
+
result += SMART_MAP[ch];
|
|
48
|
+
} else {
|
|
49
|
+
switch (unmappable) {
|
|
50
|
+
case "Remove":
|
|
51
|
+
break;
|
|
52
|
+
case "Replace with '.'":
|
|
53
|
+
result += ".";
|
|
54
|
+
break;
|
|
55
|
+
case "Include":
|
|
56
|
+
default:
|
|
57
|
+
result += ch;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const SMART_MAP = {
|
|
68
|
+
// Smart double quotes
|
|
69
|
+
"“": "\"", // “ left double quotation mark
|
|
70
|
+
"”": "\"", // ” right double quotation mark
|
|
71
|
+
"„": "\"", // „ double low-9 quotation mark
|
|
72
|
+
"‟": "\"", // ‟ double high-reversed-9 quotation mark
|
|
73
|
+
"″": "\"", // ″ double prime
|
|
74
|
+
|
|
75
|
+
// Smart single quotes / apostrophes
|
|
76
|
+
"‘": "'", // ‘ left single quotation mark
|
|
77
|
+
"’": "'", // ’ right single quotation mark / apostrophe
|
|
78
|
+
"‚": "'", // ‚ single low-9 quotation mark
|
|
79
|
+
"‛": "'", // ‛ single high-reversed-9 quotation mark
|
|
80
|
+
"′": "'", // ′ prime
|
|
81
|
+
|
|
82
|
+
// Dashes & hyphens
|
|
83
|
+
"‐": "-", // ‐ hyphen
|
|
84
|
+
"‑": "-", // ‑ non-breaking hyphen
|
|
85
|
+
"‒": "-", // ‒ figure dash
|
|
86
|
+
"–": "-", // – en dash
|
|
87
|
+
"—": "--", // — em dash
|
|
88
|
+
"―": "--", // ― horizontal bar
|
|
89
|
+
|
|
90
|
+
// Ellipsis
|
|
91
|
+
"…": "...", // …
|
|
92
|
+
|
|
93
|
+
// Trademark / copyright symbols
|
|
94
|
+
"©": "(c)", // ©
|
|
95
|
+
"®": "(r)", // ®
|
|
96
|
+
"™": "(tm)", // ™
|
|
97
|
+
|
|
98
|
+
// Arrows
|
|
99
|
+
"←": "<--", // ←
|
|
100
|
+
"→": "-->", // →
|
|
101
|
+
"↑": "^", // ↑
|
|
102
|
+
"↓": "v", // ↓
|
|
103
|
+
"↔": "<->", // ↔
|
|
104
|
+
"⇐": "<==", // ⇐
|
|
105
|
+
"⇒": "==>", // ⇒
|
|
106
|
+
"⇔": "<=>", // ⇔
|
|
107
|
+
|
|
108
|
+
// Guillemets
|
|
109
|
+
"«": "<<", // «
|
|
110
|
+
"»": ">>", // »
|
|
111
|
+
"‹": "<", // ‹
|
|
112
|
+
"›": ">", // ›
|
|
113
|
+
|
|
114
|
+
// Math & misc symbols
|
|
115
|
+
"×": "x", // ×
|
|
116
|
+
"÷": "/", // ÷
|
|
117
|
+
"±": "+/-", // ±
|
|
118
|
+
"•": "*", // •
|
|
119
|
+
"·": ".", // ·
|
|
120
|
+
|
|
121
|
+
// Non-ASCII spaces
|
|
122
|
+
"\u00A0": " ", // NBSP
|
|
123
|
+
"\u2002": " ", // en space
|
|
124
|
+
"\u2003": " ", // em space
|
|
125
|
+
"\u2009": " ", // thin space
|
|
126
|
+
"\u200A": " " // hair space
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export default EscapeSmartCharacters;
|
|
@@ -8,6 +8,10 @@ import Operation from "../Operation.mjs";
|
|
|
8
8
|
import OperationError from "../errors/OperationError.mjs";
|
|
9
9
|
import { GenerateParagraphs, GenerateSentences, GenerateWords, GenerateBytes } from "../lib/LoremIpsum.mjs";
|
|
10
10
|
|
|
11
|
+
// arbitrary limits set to avoid DoS by requesting ridiculous amounts of data
|
|
12
|
+
const maxLoremWords = 100_000; // same limit also used for paragraphs/sentences
|
|
13
|
+
const maxLoremCharacters = 1_000_000;
|
|
14
|
+
|
|
11
15
|
/**
|
|
12
16
|
* Generate Lorem Ipsum operation
|
|
13
17
|
*/
|
|
@@ -47,9 +51,7 @@ class GenerateLoremIpsum extends Operation {
|
|
|
47
51
|
*/
|
|
48
52
|
run(input, args) {
|
|
49
53
|
const [length, lengthType] = args;
|
|
50
|
-
|
|
51
|
-
throw new OperationError("Length must be greater than 0");
|
|
52
|
-
}
|
|
54
|
+
checkLimits(lengthType, length);
|
|
53
55
|
switch (lengthType) {
|
|
54
56
|
case "Paragraphs":
|
|
55
57
|
return GenerateParagraphs(length);
|
|
@@ -68,3 +70,32 @@ class GenerateLoremIpsum extends Operation {
|
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
export default GenerateLoremIpsum;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* check combined validity of lengthType and length arguments
|
|
76
|
+
* @param {string} lengthType
|
|
77
|
+
* @param {number} length
|
|
78
|
+
* @throws {OperationError}
|
|
79
|
+
*/
|
|
80
|
+
function checkLimits(lengthType, length) {
|
|
81
|
+
if (length < 1) {
|
|
82
|
+
throw new OperationError("Length must be greater than 0");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
switch (lengthType) {
|
|
86
|
+
case "Paragraphs":
|
|
87
|
+
case "Sentences":
|
|
88
|
+
case "Words":
|
|
89
|
+
if (length > maxLoremWords) {
|
|
90
|
+
throw new OperationError("Length must be less than " + maxLoremWords);
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
case "Bytes":
|
|
94
|
+
if (length > maxLoremCharacters) {
|
|
95
|
+
throw new OperationError("Length must be less than " + maxLoremCharacters);
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
default:
|
|
99
|
+
throw new OperationError("Invalid length type");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -12,6 +12,7 @@ import { getSubkeySize, ASP } from "../lib/PGP.mjs";
|
|
|
12
12
|
import { cryptNotice } from "../lib/Crypt.mjs";
|
|
13
13
|
import * as es6promisify from "es6-promisify";
|
|
14
14
|
const promisify = es6promisify.default ? es6promisify.default.promisify : es6promisify.promisify;
|
|
15
|
+
const KEY_FLAGS = kbpgp.const.openpgp.key_flags;
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -73,11 +74,11 @@ class GeneratePGPKeyPair extends Operation {
|
|
|
73
74
|
if (name) userIdentifier += name;
|
|
74
75
|
if (email) userIdentifier += ` <${email}>`;
|
|
75
76
|
|
|
76
|
-
let flags =
|
|
77
|
-
flags |=
|
|
78
|
-
flags |=
|
|
79
|
-
flags |=
|
|
80
|
-
flags |=
|
|
77
|
+
let flags = KEY_FLAGS.certify_keys;
|
|
78
|
+
flags |= KEY_FLAGS.sign_data;
|
|
79
|
+
flags |= KEY_FLAGS.auth;
|
|
80
|
+
flags |= KEY_FLAGS.encrypt_comm;
|
|
81
|
+
flags |= KEY_FLAGS.encrypt_storage;
|
|
81
82
|
|
|
82
83
|
const keyGenerationOptions = {
|
|
83
84
|
userid: userIdentifier,
|
|
@@ -89,11 +90,11 @@ class GeneratePGPKeyPair extends Operation {
|
|
|
89
90
|
},
|
|
90
91
|
subkeys: [{
|
|
91
92
|
"nbits": getSubkeySize(keySize),
|
|
92
|
-
"flags":
|
|
93
|
+
"flags": KEY_FLAGS.sign_data,
|
|
93
94
|
"expire_in": 86400 * 365 * 8
|
|
94
95
|
}, {
|
|
95
96
|
"nbits": getSubkeySize(keySize),
|
|
96
|
-
"flags":
|
|
97
|
+
"flags": KEY_FLAGS.encrypt_comm | KEY_FLAGS.encrypt_storage,
|
|
97
98
|
"expire_in": 86400 * 365 * 2
|
|
98
99
|
}],
|
|
99
100
|
asp: ASP
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author GCHQDeveloper581
|
|
3
|
+
* @copyright Crown Copyright 2026
|
|
4
|
+
* @license Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Operation from "../Operation.mjs";
|
|
8
|
+
import kbpgp from "kbpgp";
|
|
9
|
+
import { ASP, importPrivateKey } from "../lib/PGP.mjs";
|
|
10
|
+
import OperationError from "../errors/OperationError.mjs";
|
|
11
|
+
import * as es6promisify from "es6-promisify";
|
|
12
|
+
const promisify = es6promisify.default ? es6promisify.default.promisify : es6promisify.promisify;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* PGP Sign operation
|
|
16
|
+
*/
|
|
17
|
+
class PGPSign extends Operation {
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* PGPSign constructor
|
|
21
|
+
*/
|
|
22
|
+
constructor() {
|
|
23
|
+
super();
|
|
24
|
+
|
|
25
|
+
this.name = "PGP Sign";
|
|
26
|
+
this.module = "PGP";
|
|
27
|
+
this.description = [
|
|
28
|
+
"Input: the message you want to sign",
|
|
29
|
+
"<br><br>",
|
|
30
|
+
"Arguments: the ASCII-armoured PGP private key of the sender.",
|
|
31
|
+
"<br><br>",
|
|
32
|
+
"Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.",
|
|
33
|
+
"<br><br>",
|
|
34
|
+
"This function uses the Keybase implementation of PGP.",
|
|
35
|
+
].join("\n");
|
|
36
|
+
this.infoURL = "https://wikipedia.org/wiki/Pretty_Good_Privacy"; // Usually a Wikipedia link. Remember to remove localisation (i.e. https://wikipedia.org/etc rather than https://en.wikipedia.org/etc)
|
|
37
|
+
this.inputType = "string";
|
|
38
|
+
this.outputType = "string";
|
|
39
|
+
this.args = [
|
|
40
|
+
{
|
|
41
|
+
"name": "Private key of signer",
|
|
42
|
+
"type": "text",
|
|
43
|
+
"value": ""
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"name": "Private key passphrase (optional)",
|
|
47
|
+
"type": "string",
|
|
48
|
+
"value": ""
|
|
49
|
+
}
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param {string} input
|
|
55
|
+
* @param {Object[]} args
|
|
56
|
+
* @returns {string}
|
|
57
|
+
*
|
|
58
|
+
* @throws {OperationError} if failed private key import or failed encryption
|
|
59
|
+
*/
|
|
60
|
+
async run(input, args) {
|
|
61
|
+
const message = input,
|
|
62
|
+
[privateKey, passphrase] = args;
|
|
63
|
+
let signedMessage;
|
|
64
|
+
|
|
65
|
+
if (!privateKey) throw new OperationError("Enter the private key of the signer.");
|
|
66
|
+
const privKey = await importPrivateKey(privateKey, passphrase);
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
signedMessage = await promisify(kbpgp.box)({
|
|
70
|
+
"msg": message,
|
|
71
|
+
"sign_with": privKey,
|
|
72
|
+
"asp": ASP
|
|
73
|
+
});
|
|
74
|
+
} catch (err) {
|
|
75
|
+
throw new OperationError(`Couldn't sign message: ${err}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return signedMessage;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export default PGPSign;
|
|
@@ -92,7 +92,7 @@ class ParseEthernetFrame extends Operation {
|
|
|
92
92
|
const packetData = input.slice(offset);
|
|
93
93
|
|
|
94
94
|
if (outputFormat === "Packet data") {
|
|
95
|
-
return Utils.byteArrayToChars(packetData);
|
|
95
|
+
return Utils.escapeHtml(Utils.byteArrayToChars(packetData));
|
|
96
96
|
} else if (outputFormat === "Packet data (hex)") {
|
|
97
97
|
return toHex(packetData);
|
|
98
98
|
} else if (outputFormat === "Text output") {
|
|
@@ -138,7 +138,7 @@ class ParseIPv4Header extends Operation {
|
|
|
138
138
|
} else if (outputFormat === "Data (hex)") {
|
|
139
139
|
return toHex(data);
|
|
140
140
|
} else if (outputFormat === "Data (raw)") {
|
|
141
|
-
return Utils.byteArrayToChars(data);
|
|
141
|
+
return Utils.escapeHtml(Utils.byteArrayToChars(data));
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import Operation from "../Operation.mjs";
|
|
8
8
|
import OperationError from "../errors/OperationError.mjs";
|
|
9
|
-
import
|
|
9
|
+
import { ObjectId } from "bson";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Parse ObjectID timestamp operation
|
|
@@ -35,7 +35,7 @@ class ParseObjectIDTimestamp extends Operation {
|
|
|
35
35
|
*/
|
|
36
36
|
run(input, args) {
|
|
37
37
|
try {
|
|
38
|
-
const objectId = new
|
|
38
|
+
const objectId = new ObjectId(input);
|
|
39
39
|
return objectId.getTimestamp().toISOString();
|
|
40
40
|
} catch (err) {
|
|
41
41
|
throw new OperationError(err);
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ROR13 Hash operation (Windows API hashing convention)
|
|
3
|
+
* @author fufu_btw
|
|
4
|
+
* @license Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Operation from "../Operation.mjs";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Implements a ROR13 hash used for API name hashing techniques.
|
|
11
|
+
*/
|
|
12
|
+
class ROR13 extends Operation {
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Constructor
|
|
16
|
+
*/
|
|
17
|
+
constructor() {
|
|
18
|
+
super();
|
|
19
|
+
|
|
20
|
+
this.name = "ROR13";
|
|
21
|
+
this.module = "Default";
|
|
22
|
+
this.description = "Computes a ROR13 hash used in API hashing techniques.";
|
|
23
|
+
this.infoURL = "";
|
|
24
|
+
this.inputType = "byteArray";
|
|
25
|
+
this.outputType = "string";
|
|
26
|
+
|
|
27
|
+
this.args = [];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Rotate right (32-bit)
|
|
32
|
+
*
|
|
33
|
+
* @param {number} value - input value
|
|
34
|
+
* @param {number} bits - rotation bits
|
|
35
|
+
* @returns {number} rotated value
|
|
36
|
+
*/
|
|
37
|
+
ror(value, bits) {
|
|
38
|
+
return ((value >>> bits) | (value << (32 - bits))) >>> 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Execute ROR13 hash
|
|
43
|
+
*
|
|
44
|
+
* @param {byteArray} input - input bytes
|
|
45
|
+
* @param {Object[]} args - operation arguments
|
|
46
|
+
* @returns {string} hex hash
|
|
47
|
+
*/
|
|
48
|
+
run(input, args) {
|
|
49
|
+
let hash = 0;
|
|
50
|
+
|
|
51
|
+
for (let i = 0; i < input.length; i++) {
|
|
52
|
+
const chr = input[i] & 0xFF;
|
|
53
|
+
hash = this.ror(hash, 13);
|
|
54
|
+
hash = (hash + chr) >>> 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return "0x" + hash.toString(16).padStart(8, "0").toUpperCase();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Highlight input
|
|
62
|
+
*
|
|
63
|
+
* @param {Object[]} pos
|
|
64
|
+
* @param {Object[]} args
|
|
65
|
+
* @returns {Object[]}
|
|
66
|
+
*/
|
|
67
|
+
highlight(pos, args) {
|
|
68
|
+
return pos;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Reverse highlight
|
|
73
|
+
*
|
|
74
|
+
* @param {Object[]} pos
|
|
75
|
+
* @param {Object[]} args
|
|
76
|
+
* @returns {Object[]}
|
|
77
|
+
*/
|
|
78
|
+
highlightReverse(pos, args) {
|
|
79
|
+
return pos;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export default ROR13;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Louis-Ladd [lewisharshman1@gmail.com]
|
|
3
|
+
* @copyright Crown Copyright 2025
|
|
4
|
+
* @license Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Operation from "../Operation.mjs";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Remove ANSI Escape Codes operation
|
|
11
|
+
*/
|
|
12
|
+
class RemoveANSIEscapeCodes extends Operation {
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* RemoveANSIEscapeCodes constructor
|
|
16
|
+
*/
|
|
17
|
+
constructor() {
|
|
18
|
+
super();
|
|
19
|
+
|
|
20
|
+
this.name = "Remove ANSI Escape Codes";
|
|
21
|
+
this.module = "Default";
|
|
22
|
+
this.description = "Removes ANSI Escape Codes.";
|
|
23
|
+
this.infoURL = "https://wikipedia.org/wiki/ANSI_escape_code";
|
|
24
|
+
this.inputType = "string";
|
|
25
|
+
this.outputType = "string";
|
|
26
|
+
this.args = [];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {string} input
|
|
31
|
+
* @param {Object[]} args
|
|
32
|
+
* @returns {string}
|
|
33
|
+
*/
|
|
34
|
+
run(input, args) {
|
|
35
|
+
const ansiRegex = /\x1B\[[0-?]*[ -/]*[@-~]/g;
|
|
36
|
+
return input.replace(ansiRegex, "");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default RemoveANSIEscapeCodes;
|
|
@@ -15,6 +15,20 @@ import Utils from "../Utils.mjs";
|
|
|
15
15
|
const d3 = d3temp.default ? d3temp.default : d3temp;
|
|
16
16
|
const nodom = nodomtemp.default ? nodomtemp.default: nodomtemp;
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Removes D3's internal bound data from a nodom tree before serialization.
|
|
20
|
+
* nodom serializes enumerable expando properties such as __data__ as attributes,
|
|
21
|
+
* so leaving them on attacker-controlled values can create executable markup.
|
|
22
|
+
*
|
|
23
|
+
* @param {Object} node
|
|
24
|
+
*/
|
|
25
|
+
function clearD3BoundData(node) {
|
|
26
|
+
delete node.__data__;
|
|
27
|
+
|
|
28
|
+
if (!node.childNodes) return;
|
|
29
|
+
node.childNodes.forEach(clearD3BoundData);
|
|
30
|
+
}
|
|
31
|
+
|
|
18
32
|
/**
|
|
19
33
|
* Series chart operation
|
|
20
34
|
*/
|
|
@@ -222,6 +236,8 @@ class SeriesChart extends Operation {
|
|
|
222
236
|
.text(serie.name);
|
|
223
237
|
});
|
|
224
238
|
|
|
239
|
+
clearD3BoundData(svg.node());
|
|
240
|
+
|
|
225
241
|
return svg._groups[0][0].outerHTML;
|
|
226
242
|
}
|
|
227
243
|
|