diff --git a/src/core/lib/Extract.mjs b/src/core/lib/Extract.mjs
new file mode 100644
index 00000000..ba57d758
--- /dev/null
+++ b/src/core/lib/Extract.mjs
@@ -0,0 +1,41 @@
+/**
+ * Identifier extraction functions
+ *
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ *
+ */
+
+/**
+ * Runs search operations across the input data using regular expressions.
+ *
+ * @param {string} input
+ * @param {RegExp} searchRegex
+ * @param {RegExp} removeRegex - A regular expression defining results to remove from the
+ * final list
+ * @param {boolean} includeTotal - Whether or not to include the total number of results
+ * @returns {string}
+ */
+export function search (input, searchRegex, removeRegex, includeTotal) {
+ let output = "",
+ total = 0,
+ match;
+
+ while ((match = searchRegex.exec(input))) {
+ // Moves pointer when an empty string is matched (prevents infinite loop)
+ if (match.index === searchRegex.lastIndex) {
+ searchRegex.lastIndex++;
+ }
+
+ if (removeRegex && removeRegex.test(match[0]))
+ continue;
+ total++;
+ output += match[0] + "\n";
+ }
+
+ if (includeTotal)
+ output = "Total found: " + total + "\n\n" + output;
+
+ return output;
+}
diff --git a/src/core/lib/PGP.mjs b/src/core/lib/PGP.mjs
new file mode 100644
index 00000000..ea222ae8
--- /dev/null
+++ b/src/core/lib/PGP.mjs
@@ -0,0 +1,116 @@
+/**
+ * PGP functions.
+ *
+ * @author tlwr [toby@toby.codes]
+ * @author Matt C [matt@artemisbot.uk]
+ * @author n1474335 [n1474335@gmail.com]
+ *
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ *
+ */
+
+import kbpgp from "kbpgp";
+import promisifyDefault from "es6-promisify";
+const promisify = promisifyDefault.promisify;
+/**
+ * Progress callback
+ *
+ */
+export const ASP = kbpgp.ASP({
+ "progress_hook": info => {
+ let msg = "";
+
+ switch (info.what) {
+ case "guess":
+ msg = "Guessing a prime";
+ break;
+ case "fermat":
+ msg = "Factoring prime using Fermat's factorization method";
+ break;
+ case "mr":
+ msg = "Performing Miller-Rabin primality test";
+ break;
+ case "passed_mr":
+ msg = "Passed Miller-Rabin primality test";
+ break;
+ case "failed_mr":
+ msg = "Failed Miller-Rabin primality test";
+ break;
+ case "found":
+ msg = "Prime found";
+ break;
+ default:
+ msg = `Stage: ${info.what}`;
+ }
+
+ if (ENVIRONMENT_IS_WORKER())
+ self.sendStatusMessage(msg);
+ }
+});
+
+/**
+ * Get size of subkey
+ *
+ * @param {number} keySize
+ * @returns {number}
+ */
+export function getSubkeySize(keySize) {
+ return {
+ 1024: 1024,
+ 2048: 1024,
+ 4096: 2048,
+ 256: 256,
+ 384: 256,
+ }[keySize];
+}
+
+/**
+* Import private key and unlock if necessary
+*
+* @param {string} privateKey
+* @param {string} [passphrase]
+* @returns {Object}
+*/
+export async function importPrivateKey(privateKey, passphrase) {
+ try {
+ const key = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({
+ armored: privateKey,
+ opts: {
+ "no_check_keys": true
+ }
+ });
+ if (key.is_pgp_locked()) {
+ if (passphrase) {
+ await promisify(key.unlock_pgp.bind(key))({
+ passphrase
+ });
+ } else {
+ throw "Did not provide passphrase with locked private key.";
+ }
+ }
+ return key;
+ } catch (err) {
+ throw `Could not import private key: ${err}`;
+ }
+}
+
+/**
+ * Import public key
+ *
+ * @param {string} publicKey
+ * @returns {Object}
+ */
+export async function importPublicKey (publicKey) {
+ try {
+ const key = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({
+ armored: publicKey,
+ opts: {
+ "no_check_keys": true
+ }
+ });
+ return key;
+ } catch (err) {
+ throw `Could not import public key: ${err}`;
+ }
+}
diff --git a/src/core/operations/AESDecrypt.mjs b/src/core/operations/AESDecrypt.mjs
index 01415ddc..7d9ac5ca 100644
--- a/src/core/operations/AESDecrypt.mjs
+++ b/src/core/operations/AESDecrypt.mjs
@@ -7,6 +7,7 @@
import Operation from "../Operation";
import Utils from "../Utils";
import forge from "node-forge/dist/forge.min.js";
+import OperationError from "../errors/OperationError";
/**
* AES Decrypt operation
@@ -65,6 +66,8 @@ class AESDecrypt extends Operation {
* @param {string} input
* @param {Object[]} args
* @returns {string}
+ *
+ * @throws {OperationError} if cannot decrypt input or invalid key length
*/
run(input, args) {
const key = Utils.convertToByteArray(args[0].string, args[0].option),
@@ -75,12 +78,12 @@ class AESDecrypt extends Operation {
gcmTag = Utils.convertToByteString(args[5].string, args[5].option);
if ([16, 24, 32].indexOf(key.length) < 0) {
- return `Invalid key length: ${key.length} bytes
+ throw new OperationError(`Invalid key length: ${key.length} bytes
The following algorithms will be used based on the size of the key:
16 bytes = AES-128
24 bytes = AES-192
- 32 bytes = AES-256`;
+ 32 bytes = AES-256`);
}
input = Utils.convertToByteString(input, inputType);
@@ -96,7 +99,7 @@ The following algorithms will be used based on the size of the key:
if (result) {
return outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes();
} else {
- return "Unable to decrypt input with these parameters.";
+ throw new OperationError("Unable to decrypt input with these parameters.");
}
}
diff --git a/src/core/operations/AESEncrypt.mjs b/src/core/operations/AESEncrypt.mjs
index 62763c5f..98a4c259 100644
--- a/src/core/operations/AESEncrypt.mjs
+++ b/src/core/operations/AESEncrypt.mjs
@@ -7,6 +7,7 @@
import Operation from "../Operation";
import Utils from "../Utils";
import forge from "node-forge/dist/forge.min.js";
+import OperationError from "../errors/OperationError";
/**
* AES Encrypt operation
@@ -59,6 +60,8 @@ class AESEncrypt extends Operation {
* @param {string} input
* @param {Object[]} args
* @returns {string}
+ *
+ * @throws {OperationError} if invalid key length
*/
run(input, args) {
const key = Utils.convertToByteArray(args[0].string, args[0].option),
@@ -68,12 +71,12 @@ class AESEncrypt extends Operation {
outputType = args[4];
if ([16, 24, 32].indexOf(key.length) < 0) {
- return `Invalid key length: ${key.length} bytes
+ throw new OperationError(`Invalid key length: ${key.length} bytes
The following algorithms will be used based on the size of the key:
16 bytes = AES-128
24 bytes = AES-192
- 32 bytes = AES-256`;
+ 32 bytes = AES-256`);
}
input = Utils.convertToByteString(input, inputType);
diff --git a/src/core/operations/AffineCipherDecode.mjs b/src/core/operations/AffineCipherDecode.mjs
index 184fa67c..3f65c150 100644
--- a/src/core/operations/AffineCipherDecode.mjs
+++ b/src/core/operations/AffineCipherDecode.mjs
@@ -42,6 +42,8 @@ class AffineCipherDecode extends Operation {
* @param {string} input
* @param {Object[]} args
* @returns {string}
+ *
+ * @throws {OperationError} if a or b values are invalid
*/
run(input, args) {
const alphabet = "abcdefghijklmnopqrstuvwxyz",
diff --git a/src/core/operations/BifidCipherDecode.mjs b/src/core/operations/BifidCipherDecode.mjs
index dbfc7628..f5e2ad47 100644
--- a/src/core/operations/BifidCipherDecode.mjs
+++ b/src/core/operations/BifidCipherDecode.mjs
@@ -37,6 +37,8 @@ class BifidCipherDecode extends Operation {
* @param {string} input
* @param {Object[]} args
* @returns {string}
+ *
+ * @throws {OperationError} if invalid key
*/
run(input, args) {
const keywordStr = args[0].toUpperCase().replace("J", "I"),
diff --git a/src/core/operations/BifidCipherEncode.mjs b/src/core/operations/BifidCipherEncode.mjs
index 11050349..41c29db0 100644
--- a/src/core/operations/BifidCipherEncode.mjs
+++ b/src/core/operations/BifidCipherEncode.mjs
@@ -37,6 +37,8 @@ class BifidCipherEncode extends Operation {
* @param {string} input
* @param {Object[]} args
* @returns {string}
+ *
+ * @throws {OperationError} if key is invalid
*/
run(input, args) {
const keywordStr = args[0].toUpperCase().replace("J", "I"),
diff --git a/src/core/operations/CartesianProduct.mjs b/src/core/operations/CartesianProduct.mjs
index 5125511b..0d5346fb 100644
--- a/src/core/operations/CartesianProduct.mjs
+++ b/src/core/operations/CartesianProduct.mjs
@@ -41,7 +41,7 @@ class CartesianProduct extends Operation {
* Validate input length
*
* @param {Object[]} sets
- * @throws {Error} if fewer than 2 sets
+ * @throws {OperationError} if fewer than 2 sets
*/
validateSampleNumbers(sets) {
if (!sets || sets.length < 2) {
diff --git a/src/core/operations/DisassembleX86.mjs b/src/core/operations/DisassembleX86.mjs
new file mode 100644
index 00000000..602f281c
--- /dev/null
+++ b/src/core/operations/DisassembleX86.mjs
@@ -0,0 +1,131 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2017
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import * as disassemble from "../vendor/DisassembleX86-64";
+import OperationError from "../errors/OperationError";
+
+/**
+ * Disassemble x86 operation
+ */
+class DisassembleX86 extends Operation {
+
+ /**
+ * DisassembleX86 constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "Disassemble x86";
+ this.module = "Shellcode";
+ this.description = "Disassembly is the process of translating machine language into assembly language.
This operation supports 64-bit, 32-bit and 16-bit code written for Intel or AMD x86 processors. It is particularly useful for reverse engineering shellcode.
Input should be in hexadecimal.";
+ this.inputType = "string";
+ this.outputType = "string";
+ this.args = [
+ {
+ "name": "Bit mode",
+ "type": "option",
+ "value": ["64", "32", "16"]
+ },
+ {
+ "name": "Compatibility",
+ "type": "option",
+ "value": [
+ "Full x86 architecture",
+ "Knights Corner",
+ "Larrabee",
+ "Cyrix",
+ "Geode",
+ "Centaur",
+ "X86/486"
+ ]
+ },
+ {
+ "name": "Code Segment (CS)",
+ "type": "number",
+ "value": 16
+ },
+ {
+ "name": "Offset (IP)",
+ "type": "number",
+ "value": 0
+ },
+ {
+ "name": "Show instruction hex",
+ "type": "boolean",
+ "value": true
+ },
+ {
+ "name": "Show instruction position",
+ "type": "boolean",
+ "value": true
+ }
+ ];
+ }
+
+ /**
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {string}
+ *
+ * @throws {OperationError} if invalid mode value
+ */
+ run(input, args) {
+ const mode = args[0],
+ compatibility = args[1],
+ codeSegment = args[2],
+ offset = args[3],
+ showInstructionHex = args[4],
+ showInstructionPos = args[5];
+
+ switch (mode) {
+ case "64":
+ disassemble.setBitMode(2);
+ break;
+ case "32":
+ disassemble.setBitMode(1);
+ break;
+ case "16":
+ disassemble.setBitMode(0);
+ break;
+ default:
+ throw new OperationError("Invalid mode value");
+ }
+
+ switch (compatibility) {
+ case "Full x86 architecture":
+ disassemble.CompatibilityMode(0);
+ break;
+ case "Knights Corner":
+ disassemble.CompatibilityMode(1);
+ break;
+ case "Larrabee":
+ disassemble.CompatibilityMode(2);
+ break;
+ case "Cyrix":
+ disassemble.CompatibilityMode(3);
+ break;
+ case "Geode":
+ disassemble.CompatibilityMode(4);
+ break;
+ case "Centaur":
+ disassemble.CompatibilityMode(5);
+ break;
+ case "X86/486":
+ disassemble.CompatibilityMode(6);
+ break;
+ }
+
+ disassemble.SetBasePosition(codeSegment + ":" + offset);
+ disassemble.setShowInstructionHex(showInstructionHex);
+ disassemble.setShowInstructionPos(showInstructionPos);
+ disassemble.LoadBinCode(input.replace(/\s/g, ""));
+ return disassemble.LDisassemble();
+ }
+
+}
+
+export default DisassembleX86;
diff --git a/src/core/operations/DropBytes.mjs b/src/core/operations/DropBytes.mjs
index f62ac1bf..e697f4e9 100644
--- a/src/core/operations/DropBytes.mjs
+++ b/src/core/operations/DropBytes.mjs
@@ -5,6 +5,7 @@
*/
import Operation from "../Operation";
+import OperationError from "../errors/OperationError";
/**
* Drop bytes operation
@@ -45,6 +46,8 @@ class DropBytes extends Operation {
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {ArrayBuffer}
+ *
+ * @throws {OperationError} if invalid input
*/
run(input, args) {
const start = args[0],
@@ -52,7 +55,7 @@ class DropBytes extends Operation {
applyToEachLine = args[2];
if (start < 0 || length < 0)
- throw "Error: Invalid value";
+ throw new OperationError("Error: Invalid value");
if (!applyToEachLine) {
const left = input.slice(0, start),
diff --git a/src/core/operations/ExtractDates.mjs b/src/core/operations/ExtractDates.mjs
new file mode 100644
index 00000000..530db194
--- /dev/null
+++ b/src/core/operations/ExtractDates.mjs
@@ -0,0 +1,52 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import { search } from "../lib/Extract";
+
+/**
+ * Extract dates operation
+ */
+class ExtractDates extends Operation {
+
+ /**
+ * ExtractDates constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "Extract dates";
+ this.module = "Regex";
+ this.description = "Extracts dates in the following formats
yyyy-mm-dd
dd/mm/yyyy
mm/dd/yyyy
710.65.0.456
, this will match 10.65.0.45
so always check the original input!";
+ this.inputType = "string";
+ this.outputType = "string";
+ this.args = [
+ {
+ "name": "IPv4",
+ "type": "boolean",
+ "value": true
+ },
+ {
+ "name": "IPv6",
+ "type": "boolean",
+ "value": false
+ },
+ {
+ "name": "Remove local IPv4 addresses",
+ "type": "boolean",
+ "value": false
+ },
+ {
+ "name": "Display total",
+ "type": "boolean",
+ "value": false
+ }
+ ];
+ }
+
+ /**
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {string}
+ */
+ run(input, args) {
+ const includeIpv4 = args[0],
+ includeIpv6 = args[1],
+ removeLocal = args[2],
+ displayTotal = args[3],
+ 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})?",
+ ipv6 = "((?=.*::)(?!.*::.+::)(::)?([\\dA-F]{1,4}:(:|\\b)|){5}|([\\dA-F]{1,4}:){6})((([\\dA-F]{1,4}((?!\\3)::|:\\b|(?![\\dA-F])))|(?!\\2\\3)){2}|(((2[0-4]|1\\d|[1-9])?\\d|25[0-5])\\.?\\b){4})";
+ let ips = "";
+
+ if (includeIpv4 && includeIpv6) {
+ ips = ipv4 + "|" + ipv6;
+ } else if (includeIpv4) {
+ ips = ipv4;
+ } else if (includeIpv6) {
+ ips = ipv6;
+ }
+
+ if (ips) {
+ const regex = new RegExp(ips, "ig");
+
+ if (removeLocal) {
+ const ten = "10\\..+",
+ oneninetwo = "192\\.168\\..+",
+ oneseventwo = "172\\.(?:1[6-9]|2\\d|3[01])\\..+",
+ onetwoseven = "127\\..+",
+ removeRegex = new RegExp("^(?:" + ten + "|" + oneninetwo +
+ "|" + oneseventwo + "|" + onetwoseven + ")");
+
+ return search(input, regex, removeRegex, displayTotal);
+ } else {
+ return search(input, regex, null, displayTotal);
+ }
+ } else {
+ return "";
+ }
+ }
+
+}
+
+export default ExtractIPAddresses;
diff --git a/src/core/operations/ExtractMACAddresses.mjs b/src/core/operations/ExtractMACAddresses.mjs
new file mode 100644
index 00000000..9c3c2a5b
--- /dev/null
+++ b/src/core/operations/ExtractMACAddresses.mjs
@@ -0,0 +1,49 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import { search } from "../lib/Extract";
+
+/**
+ * Extract MAC addresses operation
+ */
+class ExtractMACAddresses extends Operation {
+
+ /**
+ * ExtractMACAddresses constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "Extract MAC addresses";
+ this.module = "Regex";
+ this.description = "Extracts all Media Access Control (MAC) addresses from the input.";
+ this.inputType = "string";
+ this.outputType = "string";
+ this.args = [
+ {
+ "name": "Display total",
+ "type": "boolean",
+ "value": false
+ }
+ ];
+ }
+
+ /**
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {string}
+ */
+ run(input, args) {
+ const displayTotal = args[0],
+ regex = /[A-F\d]{2}(?:[:-][A-F\d]{2}){5}/ig;
+
+ return search(input, regex, null, displayTotal);
+ }
+
+}
+
+export default ExtractMACAddresses;
diff --git a/src/core/operations/ExtractURLs.mjs b/src/core/operations/ExtractURLs.mjs
new file mode 100644
index 00000000..ab306d3f
--- /dev/null
+++ b/src/core/operations/ExtractURLs.mjs
@@ -0,0 +1,55 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import { search } from "../lib/Extract";
+
+/**
+ * Extract URLs operation
+ */
+class ExtractURLs extends Operation {
+
+ /**
+ * ExtractURLs constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "Extract URLs";
+ this.module = "Regex";
+ this.description = "Extracts Uniform Resource Locators (URLs) from the input. The protocol (http, ftp etc.) is required otherwise there will be far too many false positives.";
+ this.inputType = "string";
+ this.outputType = "string";
+ this.args = [
+ {
+ "name": "Display total",
+ "type": "boolean",
+ "value": false
+ }
+ ];
+ }
+
+ /**
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {string}
+ */
+ run(input, args) {
+ const displayTotal = args[0],
+ protocol = "[A-Z]+://",
+ hostname = "[-\\w]+(?:\\.\\w[-\\w]*)+",
+ port = ":\\d+";
+ let path = "/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*";
+
+ path += "(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*";
+ const regex = new RegExp(protocol + hostname + "(?:" + port +
+ ")?(?:" + path + ")?", "ig");
+ return search(input, regex, null, displayTotal);
+ }
+
+}
+
+export default ExtractURLs;
diff --git a/src/core/operations/Filter.mjs b/src/core/operations/Filter.mjs
index 1782b38c..aaf53f0f 100644
--- a/src/core/operations/Filter.mjs
+++ b/src/core/operations/Filter.mjs
@@ -7,6 +7,7 @@
import Operation from "../Operation";
import Utils from "../Utils";
import {INPUT_DELIM_OPTIONS} from "../lib/Delim";
+import OperationError from "../errors/OperationError";
/**
* Filter operation
@@ -56,7 +57,7 @@ class Filter extends Operation {
try {
regex = new RegExp(args[1]);
} catch (err) {
- return "Invalid regex. Details: " + err.message;
+ throw new OperationError(`Invalid regex. Details: ${err.message}`);
}
const regexFilter = function(value) {
diff --git a/src/core/operations/FromCharcode.mjs b/src/core/operations/FromCharcode.mjs
index ed2197bc..2dee72f2 100644
--- a/src/core/operations/FromCharcode.mjs
+++ b/src/core/operations/FromCharcode.mjs
@@ -7,6 +7,7 @@
import Operation from "../Operation";
import Utils from "../Utils";
import {DELIM_OPTIONS} from "../lib/Delim";
+import OperationError from "../errors/OperationError";
/**
* From Charcode operation
@@ -42,6 +43,8 @@ class FromCharcode extends Operation {
* @param {string} input
* @param {Object[]} args
* @returns {byteArray}
+ *
+ * @throws {OperationError} if base out of range
*/
run(input, args) {
const delim = Utils.charRep(args[0] || "Space"),
@@ -50,7 +53,7 @@ class FromCharcode extends Operation {
i = 0;
if (base < 2 || base > 36) {
- throw "Error: Base argument must be between 2 and 36";
+ throw new OperationError("Error: Base argument must be between 2 and 36");
}
if (input.length === 0) {
diff --git a/src/core/operations/FromUNIXTimestamp.mjs b/src/core/operations/FromUNIXTimestamp.mjs
index 90c7f120..258b6808 100644
--- a/src/core/operations/FromUNIXTimestamp.mjs
+++ b/src/core/operations/FromUNIXTimestamp.mjs
@@ -7,6 +7,7 @@
import Operation from "../Operation";
import moment from "moment-timezone";
import {UNITS} from "../lib/DateTime";
+import OperationError from "../errors/OperationError";
/**
* From UNIX Timestamp operation
@@ -37,6 +38,8 @@ class FromUNIXTimestamp extends Operation {
* @param {number} input
* @param {Object[]} args
* @returns {string}
+ *
+ * @throws {OperationError} if invalid unit
*/
run(input, args) {
const units = args[0];
@@ -57,7 +60,7 @@ class FromUNIXTimestamp extends Operation {
d = moment(input / 1000000);
return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss.SSS") + " UTC";
} else {
- throw "Unrecognised unit";
+ throw new OperationError("Unrecognised unit");
}
}
diff --git a/src/core/operations/GeneratePGPKeyPair.mjs b/src/core/operations/GeneratePGPKeyPair.mjs
new file mode 100644
index 00000000..77a60fae
--- /dev/null
+++ b/src/core/operations/GeneratePGPKeyPair.mjs
@@ -0,0 +1,115 @@
+/**
+ * @author tlwr [toby@toby.codes]
+ * @author Matt C [matt@artemisbot.uk]
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2017
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import kbpgp from "kbpgp";
+import { getSubkeySize, ASP } from "../lib/PGP";
+import promisifyDefault from "es6-promisify";
+const promisify = promisifyDefault.promisify;
+/**
+ * Generate PGP Key Pair operation
+ */
+class GeneratePGPKeyPair extends Operation {
+
+ /**
+ * GeneratePGPKeyPair constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "Generate PGP Key Pair";
+ this.module = "PGP";
+ this.description = "Generates a new public/private PGP key pair. Supports RSA and Eliptic Curve (EC) keys.";
+ this.inputType = "string";
+ this.outputType = "string";
+ this.args = [
+ {
+ "name": "Key type",
+ "type": "option",
+ "value": ["RSA-1024", "RSA-2048", "RSA-4096", "ECC-256", "ECC-384"]
+ },
+ {
+ "name": "Password (optional)",
+ "type": "string",
+ "value": ""
+ },
+ {
+ "name": "Name (optional)",
+ "type": "string",
+ "value": ""
+ },
+ {
+ "name": "Email (optional)",
+ "type": "string",
+ "value": ""
+ }
+ ];
+ }
+
+ /**
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {string}
+ */
+ run(input, args) {
+ const [keyType, keySize] = args[0].split("-"),
+ password = args[1],
+ name = args[2],
+ email = args[3];
+ let userIdentifier = "";
+
+ if (name) userIdentifier += name;
+ if (email) userIdentifier += ` <${email}>`;
+
+ let flags = kbpgp.const.openpgp.certify_keys;
+ flags |= kbpgp.const.openpgp.sign_data;
+ flags |= kbpgp.const.openpgp.auth;
+ flags |= kbpgp.const.openpgp.encrypt_comm;
+ flags |= kbpgp.const.openpgp.encrypt_storage;
+
+ const keyGenerationOptions = {
+ userid: userIdentifier,
+ ecc: keyType === "ecc",
+ primary: {
+ "nbits": keySize,
+ "flags": flags,
+ "expire_in": 0
+ },
+ subkeys: [{
+ "nbits": getSubkeySize(keySize),
+ "flags": kbpgp.const.openpgp.sign_data,
+ "expire_in": 86400 * 365 * 8
+ }, {
+ "nbits": getSubkeySize(keySize),
+ "flags": kbpgp.const.openpgp.encrypt_comm | kbpgp.const.openpgp.encrypt_storage,
+ "expire_in": 86400 * 365 * 2
+ }],
+ asp: ASP
+ };
+
+ return new Promise(async (resolve, reject) => {
+ try {
+ const unsignedKey = await promisify(kbpgp.KeyManager.generate)(keyGenerationOptions);
+ await promisify(unsignedKey.sign.bind(unsignedKey))({});
+
+ const signedKey = unsignedKey,
+ privateKeyExportOptions = {};
+
+ if (password) privateKeyExportOptions.passphrase = password;
+ const privateKey = await promisify(signedKey.export_pgp_private.bind(signedKey))(privateKeyExportOptions);
+ const publicKey = await promisify(signedKey.export_pgp_public.bind(signedKey))({});
+ resolve(privateKey + "\n" + publicKey.trim());
+ } catch (err) {
+ reject(`Error whilst generating key pair: ${err}`);
+ }
+ });
+ }
+
+}
+
+export default GeneratePGPKeyPair;
diff --git a/src/core/operations/HammingDistance.mjs b/src/core/operations/HammingDistance.mjs
index 9e2a4550..173ca3e7 100644
--- a/src/core/operations/HammingDistance.mjs
+++ b/src/core/operations/HammingDistance.mjs
@@ -7,6 +7,7 @@
import Operation from "../Operation";
import Utils from "../Utils";
import {fromHex} from "../lib/Hex";
+import OperationError from "../errors/OperationError";
/**
* Hamming Distance operation
@@ -55,11 +56,11 @@ class HammingDistance extends Operation {
samples = input.split(delim);
if (samples.length !== 2) {
- return "Error: You can only calculae the edit distance between 2 strings. Please ensure exactly two inputs are provided, separated by the specified delimiter.";
+ throw new OperationError("Error: You can only calculae the edit distance between 2 strings. Please ensure exactly two inputs are provided, separated by the specified delimiter.");
}
if (samples[0].length !== samples[1].length) {
- return "Error: Both inputs must be of the same length.";
+ throw new OperationError("Error: Both inputs must be of the same length.");
}
if (inputType === "Hex") {
diff --git a/src/core/operations/OffsetChecker.mjs b/src/core/operations/OffsetChecker.mjs
index c49fdd1a..07b15d2f 100644
--- a/src/core/operations/OffsetChecker.mjs
+++ b/src/core/operations/OffsetChecker.mjs
@@ -6,6 +6,7 @@
import Operation from "../Operation";
import Utils from "../Utils";
+import OperationError from "../errors/OperationError";
/**
* Offset checker operation
@@ -48,7 +49,7 @@ class OffsetChecker extends Operation {
chr;
if (!samples || samples.length < 2) {
- return "Not enough samples, perhaps you need to modify the sample delimiter or add more data?";
+ throw new OperationError("Not enough samples, perhaps you need to modify the sample delimiter or add more data?");
}
// Initialise output strings
diff --git a/src/core/operations/PGPDecrypt.mjs b/src/core/operations/PGPDecrypt.mjs
new file mode 100644
index 00000000..4402a457
--- /dev/null
+++ b/src/core/operations/PGPDecrypt.mjs
@@ -0,0 +1,79 @@
+/**
+ * @author tlwr [toby@toby.codes]
+ * @copyright Crown Copyright 2017
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import kbpgp from "kbpgp";
+import { ASP, importPrivateKey } from "../lib/PGP";
+import OperationError from "../errors/OperationError";
+import promisifyDefault from "es6-promisify";
+const promisify = promisifyDefault.promisify;
+
+
+/**
+ * PGP Decrypt operation
+ */
+class PGPDecrypt extends Operation {
+
+ /**
+ * PGPDecrypt constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "PGP Decrypt";
+ this.module = "PGP";
+ this.description = "Input: the ASCII-armoured PGP message you want to decrypt.\n%3d
becomes =
";
+ this.inputType = "string";
+ this.outputType = "string";
+ this.args = [];
+ }
+
+ /**
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {string}
+ */
+ run(input, args) {
+ const data = input.replace(/\+/g, "%20");
+ try {
+ return decodeURIComponent(data);
+ } catch (err) {
+ return unescape(data);
+ }
+ }
+
+}
+
+export default URLDecode;
diff --git a/src/core/operations/URLEncode.mjs b/src/core/operations/URLEncode.mjs
new file mode 100644
index 00000000..b1637594
--- /dev/null
+++ b/src/core/operations/URLEncode.mjs
@@ -0,0 +1,68 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+
+/**
+ * URL Encode operation
+ */
+class URLEncode extends Operation {
+
+ /**
+ * URLEncode constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "URL Encode";
+ this.module = "URL";
+ this.description = "Encodes problematic characters into percent-encoding, a format supported by URIs/URLs.=
becomes %3d
";
+ this.inputType = "string";
+ this.outputType = "string";
+ this.args = [
+ {
+ "name": "Encode all special chars",
+ "type": "boolean",
+ "value": false
+ }
+ ];
+ }
+
+ /**
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {string}
+ */
+ run(input, args) {
+ const encodeAll = args[0];
+ return encodeAll ? this.encodeAllChars(input) : encodeURI(input);
+ }
+
+ /**
+ * Encode characters in URL outside of encodeURI() function spec
+ *
+ * @param {string} str
+ * @returns {string}
+ */
+ encodeAllChars (str) {
+ //TODO Do this programatically
+ return encodeURIComponent(str)
+ .replace(/!/g, "%21")
+ .replace(/#/g, "%23")
+ .replace(/'/g, "%27")
+ .replace(/\(/g, "%28")
+ .replace(/\)/g, "%29")
+ .replace(/\*/g, "%2A")
+ .replace(/-/g, "%2D")
+ .replace(/\./g, "%2E")
+ .replace(/_/g, "%5F")
+ .replace(/~/g, "%7E");
+ }
+
+}
+
+
+export default URLEncode;
diff --git a/src/core/operations/legacy/Extract.js b/src/core/operations/legacy/Extract.js
deleted file mode 100755
index 92c75a21..00000000
--- a/src/core/operations/legacy/Extract.js
+++ /dev/null
@@ -1,333 +0,0 @@
-import XRegExp from "xregexp";
-
-
-/**
- * Identifier extraction operations.
- *
- * @author n1474335 [n1474335@gmail.com]
- * @copyright Crown Copyright 2016
- * @license Apache-2.0
- *
- * @namespace
- */
-const Extract = {
-
- /**
- * Runs search operations across the input data using regular expressions.
- *
- * @private
- * @param {string} input
- * @param {RegExp} searchRegex
- * @param {RegExp} removeRegex - A regular expression defining results to remove from the
- * final list
- * @param {boolean} includeTotal - Whether or not to include the total number of results
- * @returns {string}
- */
- _search: function(input, searchRegex, removeRegex, includeTotal) {
- let output = "",
- total = 0,
- match;
-
- while ((match = searchRegex.exec(input))) {
- // Moves pointer when an empty string is matched (prevents infinite loop)
- if (match.index === searchRegex.lastIndex) {
- searchRegex.lastIndex++;
- }
-
- if (removeRegex && removeRegex.test(match[0]))
- continue;
- total++;
- output += match[0] + "\n";
- }
-
- if (includeTotal)
- output = "Total found: " + total + "\n\n" + output;
-
- return output;
- },
-
-
- /**
- * @constant
- * @default
- */
- MIN_STRING_LEN: 4,
- /**
- * @constant
- * @default
- */
- STRING_MATCH_TYPE: [
- "[ASCII]", "Alphanumeric + punctuation (A)", "All printable chars (A)", "Null-terminated strings (A)",
- "[Unicode]", "Alphanumeric + punctuation (U)", "All printable chars (U)", "Null-terminated strings (U)"
- ],
- /**
- * @constant
- * @default
- */
- ENCODING_LIST: ["Single byte", "16-bit littleendian", "16-bit bigendian", "All"],
- /**
- * @constant
- * @default
- */
- DISPLAY_TOTAL: false,
-
- /**
- * Strings operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runStrings: function(input, args) {
- const encoding = args[0],
- minLen = args[1],
- matchType = args[2],
- displayTotal = args[3],
- alphanumeric = "A-Z\\d",
- punctuation = "/\\-:.,_$%'\"()<>= !\\[\\]{}@",
- printable = "\x20-\x7e",
- uniAlphanumeric = "\\pL\\pN",
- uniPunctuation = "\\pP\\pZ",
- uniPrintable = "\\pL\\pM\\pZ\\pS\\pN\\pP";
-
- let strings = "";
-
- switch (matchType) {
- case "Alphanumeric + punctuation (A)":
- strings = `[${alphanumeric + punctuation}]`;
- break;
- case "All printable chars (A)":
- case "Null-terminated strings (A)":
- strings = `[${printable}]`;
- break;
- case "Alphanumeric + punctuation (U)":
- strings = `[${uniAlphanumeric + uniPunctuation}]`;
- break;
- case "All printable chars (U)":
- case "Null-terminated strings (U)":
- strings = `[${uniPrintable}]`;
- break;
- }
-
- // UTF-16 support is hacked in by allowing null bytes on either side of the matched chars
- switch (encoding) {
- case "All":
- strings = `(\x00?${strings}\x00?)`;
- break;
- case "16-bit littleendian":
- strings = `(${strings}\x00)`;
- break;
- case "16-bit bigendian":
- strings = `(\x00${strings})`;
- break;
- case "Single byte":
- default:
- break;
- }
-
- strings = `${strings}{${minLen},}`;
-
- if (matchType.includes("Null-terminated")) {
- strings += "\x00";
- }
-
- const regex = new XRegExp(strings, "ig");
-
- return Extract._search(input, regex, null, displayTotal);
- },
-
-
- /**
- * @constant
- * @default
- */
- INCLUDE_IPV4: true,
- /**
- * @constant
- * @default
- */
- INCLUDE_IPV6: false,
- /**
- * @constant
- * @default
- */
- REMOVE_LOCAL: false,
-
- /**
- * Extract IP addresses operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runIp: function(input, args) {
- let includeIpv4 = args[0],
- includeIpv6 = args[1],
- removeLocal = args[2],
- displayTotal = args[3],
- 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})?",
- ipv6 = "((?=.*::)(?!.*::.+::)(::)?([\\dA-F]{1,4}:(:|\\b)|){5}|([\\dA-F]{1,4}:){6})((([\\dA-F]{1,4}((?!\\3)::|:\\b|(?![\\dA-F])))|(?!\\2\\3)){2}|(((2[0-4]|1\\d|[1-9])?\\d|25[0-5])\\.?\\b){4})",
- ips = "";
-
- if (includeIpv4 && includeIpv6) {
- ips = ipv4 + "|" + ipv6;
- } else if (includeIpv4) {
- ips = ipv4;
- } else if (includeIpv6) {
- ips = ipv6;
- }
-
- if (ips) {
- const regex = new RegExp(ips, "ig");
-
- if (removeLocal) {
- let ten = "10\\..+",
- oneninetwo = "192\\.168\\..+",
- oneseventwo = "172\\.(?:1[6-9]|2\\d|3[01])\\..+",
- onetwoseven = "127\\..+",
- removeRegex = new RegExp("^(?:" + ten + "|" + oneninetwo +
- "|" + oneseventwo + "|" + onetwoseven + ")");
-
- return Extract._search(input, regex, removeRegex, displayTotal);
- } else {
- return Extract._search(input, regex, null, displayTotal);
- }
- } else {
- return "";
- }
- },
-
-
- /**
- * Extract email addresses operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runEmail: function(input, args) {
- let displayTotal = args[0],
- regex = /\b\w[-.\w]*@[-\w]+(?:\.[-\w]+)*\.[A-Z]{2,4}\b/ig;
-
- return Extract._search(input, regex, null, displayTotal);
- },
-
-
- /**
- * Extract MAC addresses operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runMac: function(input, args) {
- let displayTotal = args[0],
- regex = /[A-F\d]{2}(?:[:-][A-F\d]{2}){5}/ig;
-
- return Extract._search(input, regex, null, displayTotal);
- },
-
-
- /**
- * Extract URLs operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runUrls: function(input, args) {
- let displayTotal = args[0],
- protocol = "[A-Z]+://",
- hostname = "[-\\w]+(?:\\.\\w[-\\w]*)+",
- port = ":\\d+",
- path = "/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*";
-
- path += "(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*";
- const regex = new RegExp(protocol + hostname + "(?:" + port +
- ")?(?:" + path + ")?", "ig");
- return Extract._search(input, regex, null, displayTotal);
- },
-
-
- /**
- * Extract domains operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runDomains: function(input, args) {
- const displayTotal = args[0],
- regex = /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/ig;
-
- return Extract._search(input, regex, null, displayTotal);
- },
-
-
- /**
- * @constant
- * @default
- */
- INCLUDE_WIN_PATH: true,
- /**
- * @constant
- * @default
- */
- INCLUDE_UNIX_PATH: true,
-
- /**
- * Extract file paths operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runFilePaths: function(input, args) {
- let includeWinPath = args[0],
- includeUnixPath = args[1],
- displayTotal = args[2],
- winDrive = "[A-Z]:\\\\",
- winName = "[A-Z\\d][A-Z\\d\\- '_\\(\\)~]{0,61}",
- winExt = "[A-Z\\d]{1,6}",
- winPath = winDrive + "(?:" + winName + "\\\\?)*" + winName +
- "(?:\\." + winExt + ")?",
- unixPath = "(?:/[A-Z\\d.][A-Z\\d\\-.]{0,61})+",
- filePaths = "";
-
- if (includeWinPath && includeUnixPath) {
- filePaths = winPath + "|" + unixPath;
- } else if (includeWinPath) {
- filePaths = winPath;
- } else if (includeUnixPath) {
- filePaths = unixPath;
- }
-
- if (filePaths) {
- const regex = new RegExp(filePaths, "ig");
- return Extract._search(input, regex, null, displayTotal);
- } else {
- return "";
- }
- },
-
-
- /**
- * Extract dates operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runDates: function(input, args) {
- let displayTotal = args[0],
- date1 = "(?:19|20)\\d\\d[- /.](?:0[1-9]|1[012])[- /.](?:0[1-9]|[12][0-9]|3[01])", // yyyy-mm-dd
- date2 = "(?:0[1-9]|[12][0-9]|3[01])[- /.](?:0[1-9]|1[012])[- /.](?:19|20)\\d\\d", // dd/mm/yyyy
- date3 = "(?:0[1-9]|1[012])[- /.](?:0[1-9]|[12][0-9]|3[01])[- /.](?:19|20)\\d\\d", // mm/dd/yyyy
- regex = new RegExp(date1 + "|" + date2 + "|" + date3, "ig");
-
- return Extract._search(input, regex, null, displayTotal);
- },
-
-};
-
-export default Extract;
diff --git a/src/core/operations/legacy/PGP.js b/src/core/operations/legacy/PGP.js
deleted file mode 100644
index b80ab4ae..00000000
--- a/src/core/operations/legacy/PGP.js
+++ /dev/null
@@ -1,364 +0,0 @@
-import * as kbpgp from "kbpgp";
-import {promisify} from "es6-promisify";
-
-
-/**
- * PGP operations.
- *
- * @author tlwr [toby@toby.codes]
- * @author Matt C [matt@artemisbot.uk]
- * @author n1474335 [n1474335@gmail.com]
- * @copyright Crown Copyright 2017
- * @license Apache-2.0
- *
- * @namespace
- */
-const PGP = {
-
- /**
- * @constant
- * @default
- */
- KEY_TYPES: ["RSA-1024", "RSA-2048", "RSA-4096", "ECC-256", "ECC-384"],
-
-
- /**
- * Get size of subkey
- *
- * @private
- * @param {number} keySize
- * @returns {number}
- */
- _getSubkeySize(keySize) {
- return {
- 1024: 1024,
- 2048: 1024,
- 4096: 2048,
- 256: 256,
- 384: 256,
- }[keySize];
- },
-
-
- /**
- * Progress callback
- *
- * @private
- */
- _ASP: new kbpgp.ASP({
- "progress_hook": info => {
- let msg = "";
-
- switch (info.what) {
- case "guess":
- msg = "Guessing a prime";
- break;
- case "fermat":
- msg = "Factoring prime using Fermat's factorization method";
- break;
- case "mr":
- msg = "Performing Miller-Rabin primality test";
- break;
- case "passed_mr":
- msg = "Passed Miller-Rabin primality test";
- break;
- case "failed_mr":
- msg = "Failed Miller-Rabin primality test";
- break;
- case "found":
- msg = "Prime found";
- break;
- default:
- msg = `Stage: ${info.what}`;
- }
-
- if (ENVIRONMENT_IS_WORKER())
- self.sendStatusMessage(msg);
- }
- }),
-
-
- /**
- * Import private key and unlock if necessary
- *
- * @private
- * @param {string} privateKey
- * @param {string} [passphrase]
- * @returns {Object}
- */
- async _importPrivateKey(privateKey, passphrase) {
- try {
- const key = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({
- armored: privateKey,
- opts: {
- "no_check_keys": true
- }
- });
- if (key.is_pgp_locked()) {
- if (passphrase) {
- await promisify(key.unlock_pgp.bind(key))({
- passphrase
- });
- } else {
- throw "Did not provide passphrase with locked private key.";
- }
- }
- return key;
- } catch (err) {
- throw `Could not import private key: ${err}`;
- }
- },
-
-
- /**
- * Import public key
- *
- * @private
- * @param {string} publicKey
- * @returns {Object}
- */
- async _importPublicKey (publicKey) {
- try {
- const key = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({
- armored: publicKey,
- opts: {
- "no_check_keys": true
- }
- });
- return key;
- } catch (err) {
- throw `Could not import public key: ${err}`;
- }
- },
-
-
- /**
- * Generate PGP Key Pair operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runGenerateKeyPair(input, args) {
- let [keyType, keySize] = args[0].split("-"),
- password = args[1],
- name = args[2],
- email = args[3],
- userIdentifier = "";
-
- if (name) userIdentifier += name;
- if (email) userIdentifier += ` <${email}>`;
-
- let flags = kbpgp.const.openpgp.certify_keys;
- flags |= kbpgp.const.openpgp.sign_data;
- flags |= kbpgp.const.openpgp.auth;
- flags |= kbpgp.const.openpgp.encrypt_comm;
- flags |= kbpgp.const.openpgp.encrypt_storage;
-
- let keyGenerationOptions = {
- userid: userIdentifier,
- ecc: keyType === "ecc",
- primary: {
- "nbits": keySize,
- "flags": flags,
- "expire_in": 0
- },
- subkeys: [{
- "nbits": PGP._getSubkeySize(keySize),
- "flags": kbpgp.const.openpgp.sign_data,
- "expire_in": 86400 * 365 * 8
- }, {
- "nbits": PGP._getSubkeySize(keySize),
- "flags": kbpgp.const.openpgp.encrypt_comm | kbpgp.const.openpgp.encrypt_storage,
- "expire_in": 86400 * 365 * 2
- }],
- asp: PGP._ASP
- };
-
- return new Promise(async (resolve, reject) => {
- try {
- const unsignedKey = await promisify(kbpgp.KeyManager.generate)(keyGenerationOptions);
- await promisify(unsignedKey.sign.bind(unsignedKey))({});
- let signedKey = unsignedKey;
- let privateKeyExportOptions = {};
- if (password) privateKeyExportOptions.passphrase = password;
- const privateKey = await promisify(signedKey.export_pgp_private.bind(signedKey))(privateKeyExportOptions);
- const publicKey = await promisify(signedKey.export_pgp_public.bind(signedKey))({});
- resolve(privateKey + "\n" + publicKey.trim());
- } catch (err) {
- reject(`Error whilst generating key pair: ${err}`);
- }
- });
- },
-
-
- /**
- * PGP Encrypt operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- async runEncrypt(input, args) {
- let plaintextMessage = input,
- plainPubKey = args[0],
- key,
- encryptedMessage;
-
- if (!plainPubKey) return "Enter the public key of the recipient.";
-
- try {
- key = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({
- armored: plainPubKey,
- });
- } catch (err) {
- throw `Could not import public key: ${err}`;
- }
-
- try {
- encryptedMessage = await promisify(kbpgp.box)({
- "msg": plaintextMessage,
- "encrypt_for": key,
- "asp": PGP._ASP
- });
- } catch (err) {
- throw `Couldn't encrypt message with provided public key: ${err}`;
- }
-
- return encryptedMessage.toString();
- },
-
-
- /**
- * PGP Decrypt operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- async runDecrypt(input, args) {
- let encryptedMessage = input,
- privateKey = args[0],
- passphrase = args[1],
- keyring = new kbpgp.keyring.KeyRing(),
- plaintextMessage;
-
- if (!privateKey) return "Enter the private key of the recipient.";
-
- const key = await PGP._importPrivateKey(privateKey, passphrase);
- keyring.add_key_manager(key);
-
- try {
- plaintextMessage = await promisify(kbpgp.unbox)({
- armored: encryptedMessage,
- keyfetch: keyring,
- asp: PGP._ASP
- });
- } catch (err) {
- throw `Couldn't decrypt message with provided private key: ${err}`;
- }
-
- return plaintextMessage.toString();
- },
-
-
- /**
- * PGP Sign Message operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- async runSign(input, args) {
- let message = input,
- privateKey = args[0],
- passphrase = args[1],
- publicKey = args[2],
- signedMessage;
-
- if (!privateKey) return "Enter the private key of the signer.";
- if (!publicKey) return "Enter the public key of the recipient.";
- const privKey = await PGP._importPrivateKey(privateKey, passphrase);
- const pubKey = await PGP._importPublicKey(publicKey);
-
- try {
- signedMessage = await promisify(kbpgp.box)({
- "msg": message,
- "encrypt_for": pubKey,
- "sign_with": privKey,
- "asp": PGP._ASP
- });
- } catch (err) {
- throw `Couldn't sign message: ${err}`;
- }
-
- return signedMessage;
- },
-
-
- /**
- * PGP Verify Message operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- async runVerify(input, args) {
- let signedMessage = input,
- publicKey = args[0],
- privateKey = args[1],
- passphrase = args[2],
- keyring = new kbpgp.keyring.KeyRing(),
- unboxedLiterals;
-
- if (!publicKey) return "Enter the public key of the signer.";
- if (!privateKey) return "Enter the private key of the recipient.";
- const privKey = await PGP._importPrivateKey(privateKey, passphrase);
- const pubKey = await PGP._importPublicKey(publicKey);
- keyring.add_key_manager(privKey);
- keyring.add_key_manager(pubKey);
-
- try {
- unboxedLiterals = await promisify(kbpgp.unbox)({
- armored: signedMessage,
- keyfetch: keyring,
- asp: PGP._ASP
- });
- const ds = unboxedLiterals[0].get_data_signer();
- if (ds) {
- const km = ds.get_key_manager();
- if (km) {
- const signer = km.get_userids_mark_primary()[0].components;
- let text = "Signed by ";
- if (signer.email || signer.username || signer.comment) {
- if (signer.username) {
- text += `${signer.username} `;
- }
- if (signer.comment) {
- text += `${signer.comment} `;
- }
- if (signer.email) {
- text += `<${signer.email}>`;
- }
- text += "\n";
- }
- text += [
- `PGP fingerprint: ${km.get_pgp_fingerprint().toString("hex")}`,
- `Signed on ${new Date(ds.sig.hashed_subpackets[0].time * 1000).toUTCString()}`,
- "----------------------------------\n"
- ].join("\n");
- text += unboxedLiterals.toString();
- return text.trim();
- } else {
- return "Could not identify a key manager.";
- }
- } else {
- return "The data does not appear to be signed.";
- }
- } catch (err) {
- return `Couldn't verify message: ${err}`;
- }
- },
-};
-
-export default PGP;
diff --git a/src/core/operations/legacy/URL.js b/src/core/operations/legacy/URL.js
deleted file mode 100755
index 2f30c952..00000000
--- a/src/core/operations/legacy/URL.js
+++ /dev/null
@@ -1,118 +0,0 @@
-/* globals unescape */
-import url from "url";
-
-
-/**
- * URL operations.
- * Namespace is appended with an underscore to prevent overwriting the global URL object.
- *
- * @author n1474335 [n1474335@gmail.com]
- * @copyright Crown Copyright 2016
- * @license Apache-2.0
- *
- * @namespace
- */
-const URL_ = {
-
- /**
- * @constant
- * @default
- */
- ENCODE_ALL: false,
-
- /**
- * URL Encode operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runTo: function(input, args) {
- const encodeAll = args[0];
- return encodeAll ? URL_._encodeAllChars(input) : encodeURI(input);
- },
-
-
- /**
- * URL Decode operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runFrom: function(input, args) {
- const data = input.replace(/\+/g, "%20");
- try {
- return decodeURIComponent(data);
- } catch (err) {
- return unescape(data);
- }
- },
-
-
- /**
- * Parse URI operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runParse: function(input, args) {
- const uri = url.parse(input, true);
-
- let output = "";
-
- if (uri.protocol) output += "Protocol:\t" + uri.protocol + "\n";
- if (uri.auth) output += "Auth:\t\t" + uri.auth + "\n";
- if (uri.hostname) output += "Hostname:\t" + uri.hostname + "\n";
- if (uri.port) output += "Port:\t\t" + uri.port + "\n";
- if (uri.pathname) output += "Path name:\t" + uri.pathname + "\n";
- if (uri.query) {
- let keys = Object.keys(uri.query),
- padding = 0;
-
- keys.forEach(k => {
- padding = (k.length > padding) ? k.length : padding;
- });
-
- output += "Arguments:\n";
- for (let key in uri.query) {
- output += "\t" + key.padEnd(padding, " ");
- if (uri.query[key].length) {
- output += " = " + uri.query[key] + "\n";
- } else {
- output += "\n";
- }
- }
- }
- if (uri.hash) output += "Hash:\t\t" + uri.hash + "\n";
-
- return output;
- },
-
-
- /**
- * URL encodes additional special characters beyond the standard set.
- *
- * @private
- * @param {string} str
- * @returns {string}
- */
- _encodeAllChars: function(str) {
- //TODO Do this programatically
- return encodeURIComponent(str)
- .replace(/!/g, "%21")
- .replace(/#/g, "%23")
- .replace(/'/g, "%27")
- .replace(/\(/g, "%28")
- .replace(/\)/g, "%29")
- .replace(/\*/g, "%2A")
- .replace(/-/g, "%2D")
- .replace(/\./g, "%2E")
- .replace(/_/g, "%5F")
- .replace(/~/g, "%7E");
- },
-
-};
-
-export default URL_;
diff --git a/src/core/vendor/DisassembleX86-64.js b/src/core/vendor/DisassembleX86-64.mjs
similarity index 99%
rename from src/core/vendor/DisassembleX86-64.js
rename to src/core/vendor/DisassembleX86-64.mjs
index e320c6c2..f0d30511 100644
--- a/src/core/vendor/DisassembleX86-64.js
+++ b/src/core/vendor/DisassembleX86-64.mjs
@@ -3316,7 +3316,7 @@ If input "type" is set 5 it will adjust the mnemonic array to decode Centaur ins
If input "type" is set 6 it will adjust the mnemonic array to decode instruction for the X86/486 CPU which conflict with the vector unit instructions with UMOV.
-------------------------------------------------------------------------------------------------------------------------*/
-function CompatibilityMode( type )
+export function CompatibilityMode( type )
{
//Reset the changeable sections of the Mnemonics array, and operand encoding array.
@@ -3515,7 +3515,7 @@ The function "GetPosition()" Gives back the current base address in it's proper
If the hex input is invalid returns false.
-------------------------------------------------------------------------------------------------------------------------*/
-function LoadBinCode( HexStr )
+export function LoadBinCode( HexStr )
{
//Clear BinCode, and Reset Code Position in Bin Code array.
@@ -3605,7 +3605,7 @@ segment, and offset address. Note that the Code Segment is used in 16 bit code.
if set 36, or higher. Effects instruction location in memory when decoding a program.
-------------------------------------------------------------------------------------------------------------------------*/
-function SetBasePosition( Address )
+export function SetBasePosition( Address )
{
//Split the Segment:offset.
@@ -5652,7 +5652,7 @@ function Reset()
do an linear disassemble.
-------------------------------------------------------------------------------------------------------------------------*/
-function LDisassemble()
+export function LDisassemble()
{
var Instruction = ""; //Stores the Decoded instruction.
var Out = ""; //The Disassemble output
@@ -5709,13 +5709,13 @@ function LDisassemble()
* The following code has been added to expose public methods for use in CyberChef
*/
-export default {
- LoadBinCode: LoadBinCode,
- LDisassemble: LDisassemble,
- SetBasePosition: SetBasePosition,
- CompatibilityMode: CompatibilityMode,
-
- setBitMode: val => { BitMode = val; },
- setShowInstructionHex: val => { ShowInstructionHex = val; },
- setShowInstructionPos: val => { ShowInstructionPos = val; },
+export function setBitMode (val) {
+ BitMode = val;
};
+export function setShowInstructionHex (val) {
+ ShowInstructionHex = val;
+};
+export function setShowInstructionPos (val) {
+ ShowInstructionPos = val;
+};
+