mirror of
https://github.com/gchq/CyberChef.git
synced 2024-11-02 14:11:02 +01:00
Merge branch 'esmconversion' of https://github.com/artemisbot/CyberChef into esm
This commit is contained in:
commit
acb8a342a7
41
src/core/lib/Extract.mjs
Normal file
41
src/core/lib/Extract.mjs
Normal file
@ -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;
|
||||
}
|
116
src/core/lib/PGP.mjs
Normal file
116
src/core/lib/PGP.mjs
Normal file
@ -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}`;
|
||||
}
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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",
|
||||
|
@ -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"),
|
||||
|
@ -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"),
|
||||
|
@ -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) {
|
||||
|
131
src/core/operations/DisassembleX86.mjs
Normal file
131
src/core/operations/DisassembleX86.mjs
Normal file
@ -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.<br><br>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.<br><br>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;
|
@ -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),
|
||||
|
52
src/core/operations/ExtractDates.mjs
Normal file
52
src/core/operations/ExtractDates.mjs
Normal file
@ -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<ul><li><code>yyyy-mm-dd</code></li><li><code>dd/mm/yyyy</code></li><li><code>mm/dd/yyyy</code></li></ul>Dividers can be any of /, -, . or space";
|
||||
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],
|
||||
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 search(input, regex, null, displayTotal);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ExtractDates;
|
49
src/core/operations/ExtractDomains.mjs
Normal file
49
src/core/operations/ExtractDomains.mjs
Normal file
@ -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 domains operation
|
||||
*/
|
||||
class ExtractDomains extends Operation {
|
||||
|
||||
/**
|
||||
* ExtractDomains constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Extract domains";
|
||||
this.module = "Regex";
|
||||
this.description = "Extracts domain names.<br>Note that this will not include paths. Use <strong>Extract URLs</strong> to find entire URLs.";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Display total",
|
||||
"type": "boolean",
|
||||
"value": "Extract.DISPLAY_TOTAL"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(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 search(input, regex, null, displayTotal);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ExtractDomains;
|
49
src/core/operations/ExtractEmailAddresses.mjs
Normal file
49
src/core/operations/ExtractEmailAddresses.mjs
Normal file
@ -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 email addresses operation
|
||||
*/
|
||||
class ExtractEmailAddresses extends Operation {
|
||||
|
||||
/**
|
||||
* ExtractEmailAddresses constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Extract email addresses";
|
||||
this.module = "Regex";
|
||||
this.description = "Extracts all email 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 = /\b\w[-.\w]*@[-\w]+(?:\.[-\w]+)*\.[A-Z]{2,4}\b/ig;
|
||||
|
||||
return search(input, regex, null, displayTotal);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ExtractEmailAddresses;
|
79
src/core/operations/ExtractFilePaths.mjs
Normal file
79
src/core/operations/ExtractFilePaths.mjs
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import { search } from "../lib/Extract";
|
||||
/**
|
||||
* Extract file paths operation
|
||||
*/
|
||||
class ExtractFilePaths extends Operation {
|
||||
|
||||
/**
|
||||
* ExtractFilePaths constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Extract file paths";
|
||||
this.module = "Regex";
|
||||
this.description = "Extracts anything that looks like a Windows or UNIX file path.<br><br>Note that if UNIX is selected, there will likely be a lot of false positives.";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Windows",
|
||||
"type": "boolean",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"name": "UNIX",
|
||||
"type": "boolean",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"name": "Display total",
|
||||
"type": "boolean",
|
||||
"value": false
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const 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})+";
|
||||
let 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 search(input, regex, null, displayTotal);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ExtractFilePaths;
|
94
src/core/operations/ExtractIPAddresses.mjs
Normal file
94
src/core/operations/ExtractIPAddresses.mjs
Normal file
@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import { search } from "../lib/Extract";
|
||||
|
||||
/**
|
||||
* Extract IP addresses operation
|
||||
*/
|
||||
class ExtractIPAddresses extends Operation {
|
||||
|
||||
/**
|
||||
* ExtractIPAddresses constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Extract IP addresses";
|
||||
this.module = "Regex";
|
||||
this.description = "Extracts all IPv4 and IPv6 addresses.<br><br>Warning: Given a string <code>710.65.0.456</code>, this will match <code>10.65.0.45</code> so always check the original input!";
|
||||
this.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;
|
49
src/core/operations/ExtractMACAddresses.mjs
Normal file
49
src/core/operations/ExtractMACAddresses.mjs
Normal file
@ -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;
|
55
src/core/operations/ExtractURLs.mjs
Normal file
55
src/core/operations/ExtractURLs.mjs
Normal file
@ -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;
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
115
src/core/operations/GeneratePGPKeyPair.mjs
Normal file
115
src/core/operations/GeneratePGPKeyPair.mjs
Normal file
@ -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;
|
@ -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") {
|
||||
|
@ -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
|
||||
|
79
src/core/operations/PGPDecrypt.mjs
Normal file
79
src/core/operations/PGPDecrypt.mjs
Normal file
@ -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<br><br>\nArguments: the ASCII-armoured PGP private key of the recipient, \n(and the private key password if necessary).\n<br><br>\nPretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.\n<br><br>\nThis function uses the Keybase implementation of PGP.";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Private key of recipient",
|
||||
"type": "text",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "Private key passphrase",
|
||||
"type": "string",
|
||||
"value": ""
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*
|
||||
* @throws {OperationError} if invalid private key
|
||||
*/
|
||||
async run(input, args) {
|
||||
const encryptedMessage = input,
|
||||
privateKey = args[0],
|
||||
passphrase = args[1],
|
||||
keyring = new kbpgp.keyring.KeyRing();
|
||||
let plaintextMessage;
|
||||
|
||||
if (!privateKey) throw new OperationError("Enter the private key of the recipient.");
|
||||
|
||||
const key = await importPrivateKey(privateKey, passphrase);
|
||||
keyring.add_key_manager(key);
|
||||
|
||||
try {
|
||||
plaintextMessage = await promisify(kbpgp.unbox)({
|
||||
armored: encryptedMessage,
|
||||
keyfetch: keyring,
|
||||
asp: ASP
|
||||
});
|
||||
} catch (err) {
|
||||
throw new OperationError(`Couldn't decrypt message with provided private key: ${err}`);
|
||||
}
|
||||
|
||||
return plaintextMessage.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PGPDecrypt;
|
113
src/core/operations/PGPDecryptAndVerify.mjs
Normal file
113
src/core/operations/PGPDecryptAndVerify.mjs
Normal file
@ -0,0 +1,113 @@
|
||||
/**
|
||||
* @author tlwr [toby@toby.codes]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import kbpgp from "kbpgp";
|
||||
import { ASP, importPrivateKey, importPublicKey } from "../lib/PGP";
|
||||
import OperationError from "../errors/OperationError";
|
||||
import promisifyDefault from "es6-promisify";
|
||||
const promisify = promisifyDefault.promisify;
|
||||
|
||||
/**
|
||||
* PGP Decrypt and Verify operation
|
||||
*/
|
||||
class PGPDecryptAndVerify extends Operation {
|
||||
|
||||
/**
|
||||
* PGPDecryptAndVerify constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "PGP Decrypt and Verify";
|
||||
this.module = "PGP";
|
||||
this.description = "Input: the ASCII-armoured encrypted PGP message you want to verify.\n<br><br>\nArguments: the ASCII-armoured PGP public key of the signer, \nthe ASCII-armoured private key of the recipient (and the private key password if necessary).\n<br><br>\nThis operation uses PGP to decrypt and verify an encrypted digital signature.\n<br><br>\nPretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.\n<br><br>\nThis function uses the Keybase implementation of PGP.";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Public key of signer",
|
||||
"type": "text",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "Private key of recipient",
|
||||
"type": "text",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "Private key password",
|
||||
"type": "string",
|
||||
"value": ""
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
async run(input, args) {
|
||||
const signedMessage = input,
|
||||
publicKey = args[0],
|
||||
privateKey = args[1],
|
||||
passphrase = args[2],
|
||||
keyring = new kbpgp.keyring.KeyRing();
|
||||
let unboxedLiterals;
|
||||
|
||||
if (!publicKey) throw new OperationError("Enter the public key of the signer.");
|
||||
if (!privateKey) throw new OperationError("Enter the private key of the recipient.");
|
||||
const privKey = await importPrivateKey(privateKey, passphrase);
|
||||
const pubKey = await importPublicKey(publicKey);
|
||||
keyring.add_key_manager(privKey);
|
||||
keyring.add_key_manager(pubKey);
|
||||
|
||||
try {
|
||||
unboxedLiterals = await promisify(kbpgp.unbox)({
|
||||
armored: signedMessage,
|
||||
keyfetch: keyring,
|
||||
asp: 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 {
|
||||
throw new OperationError("Could not identify a key manager.");
|
||||
}
|
||||
} else {
|
||||
throw new OperationError("The data does not appear to be signed.");
|
||||
}
|
||||
} catch (err) {
|
||||
throw new OperationError(`Couldn't verify message: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PGPDecryptAndVerify;
|
77
src/core/operations/PGPEncrypt.mjs
Normal file
77
src/core/operations/PGPEncrypt.mjs
Normal file
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @author tlwr [toby@toby.codes]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import kbpgp from "kbpgp";
|
||||
import { ASP } from "../lib/PGP";
|
||||
import OperationError from "../errors/OperationError";
|
||||
import promisifyDefault from "es6-promisify";
|
||||
const promisify = promisifyDefault.promisify;
|
||||
|
||||
/**
|
||||
* PGP Encrypt operation
|
||||
*/
|
||||
class PGPEncrypt extends Operation {
|
||||
|
||||
/**
|
||||
* PGPEncrypt constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "PGP Encrypt";
|
||||
this.module = "PGP";
|
||||
this.description = "Input: the message you want to encrypt.\n<br><br>\nArguments: the ASCII-armoured PGP public key of the recipient.\n<br><br>\nPretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.\n<br><br>\nThis function uses the Keybase implementation of PGP.";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Public key of recipient",
|
||||
"type": "text",
|
||||
"value": ""
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*
|
||||
* @throws {OperationError} if failed private key import or failed encryption
|
||||
*/
|
||||
async run(input, args) {
|
||||
const plaintextMessage = input,
|
||||
plainPubKey = args[0];
|
||||
let key,
|
||||
encryptedMessage;
|
||||
|
||||
if (!plainPubKey) throw new OperationError("Enter the public key of the recipient.");
|
||||
|
||||
try {
|
||||
key = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({
|
||||
armored: plainPubKey,
|
||||
});
|
||||
} catch (err) {
|
||||
throw new OperationError(`Could not import public key: ${err}`);
|
||||
}
|
||||
|
||||
try {
|
||||
encryptedMessage = await promisify(kbpgp.box)({
|
||||
"msg": plaintextMessage,
|
||||
"encrypt_for": key,
|
||||
"asp": ASP
|
||||
});
|
||||
} catch (err) {
|
||||
throw new OperationError(`Couldn't encrypt message with provided public key: ${err}`);
|
||||
}
|
||||
|
||||
return encryptedMessage.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PGPEncrypt;
|
84
src/core/operations/PGPEncryptAndSign.mjs
Normal file
84
src/core/operations/PGPEncryptAndSign.mjs
Normal file
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @author tlwr [toby@toby.codes]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import kbpgp from "kbpgp";
|
||||
import { ASP, importPrivateKey, importPublicKey } from "../lib/PGP";
|
||||
import OperationError from "../errors/OperationError";
|
||||
import promisifyDefault from "es6-promisify";
|
||||
const promisify = promisifyDefault.promisify;
|
||||
|
||||
/**
|
||||
* PGP Encrypt and Sign operation
|
||||
*/
|
||||
class PGPEncryptAndSign extends Operation {
|
||||
|
||||
/**
|
||||
* PGPEncryptAndSign constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "PGP Encrypt and Sign";
|
||||
this.module = "PGP";
|
||||
this.description = "Input: the cleartext you want to sign.\n<br><br>\nArguments: the ASCII-armoured private key of the signer (plus the private key password if necessary)\nand the ASCII-armoured PGP public key of the recipient.\n<br><br>\nThis operation uses PGP to produce an encrypted digital signature.\n<br><br>\nPretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.\n<br><br>\nThis function uses the Keybase implementation of PGP.";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Private key of signer",
|
||||
"type": "text",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "Private key passphrase",
|
||||
"type": "string",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "Public key of recipient",
|
||||
"type": "text",
|
||||
"value": ""
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*
|
||||
* @throws {OperationError} if failure to sign message
|
||||
*/
|
||||
async run(input, args) {
|
||||
const message = input,
|
||||
privateKey = args[0],
|
||||
passphrase = args[1],
|
||||
publicKey = args[2];
|
||||
let signedMessage;
|
||||
|
||||
if (!privateKey) throw new OperationError("Enter the private key of the signer.");
|
||||
if (!publicKey) throw new OperationError("Enter the public key of the recipient.");
|
||||
const privKey = await importPrivateKey(privateKey, passphrase);
|
||||
const pubKey = await importPublicKey(publicKey);
|
||||
|
||||
try {
|
||||
signedMessage = await promisify(kbpgp.box)({
|
||||
"msg": message,
|
||||
"encrypt_for": pubKey,
|
||||
"sign_with": privKey,
|
||||
"asp": ASP
|
||||
});
|
||||
} catch (err) {
|
||||
throw new OperationError(`Couldn't sign message: ${err}`);
|
||||
}
|
||||
|
||||
return signedMessage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PGPEncryptAndSign;
|
@ -7,6 +7,7 @@
|
||||
import Operation from "../Operation";
|
||||
import moment from "moment-timezone";
|
||||
import {DATETIME_FORMATS, FORMAT_EXAMPLES} from "../lib/DateTime";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* Parse DateTime operation
|
||||
@ -59,7 +60,7 @@ class ParseDateTime extends Operation {
|
||||
date = moment.tz(input, inputFormat, inputTimezone);
|
||||
if (!date || date.format() === "Invalid date") throw Error;
|
||||
} catch (err) {
|
||||
return "Invalid format.\n\n" + FORMAT_EXAMPLES;
|
||||
throw new OperationError(`Invalid format.\n\n${FORMAT_EXAMPLES}`);
|
||||
}
|
||||
|
||||
output += "Date: " + date.format("dddd Do MMMM YYYY") +
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* Parse UNIX file permissions operation
|
||||
@ -169,7 +170,7 @@ class ParseUNIXFilePermissions extends Operation {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return "Invalid input format.\nPlease enter the permissions in either octal (e.g. 755) or textual (e.g. drwxr-xr-x) format.";
|
||||
throw new OperationError("Invalid input format.\nPlease enter the permissions in either octal (e.g. 755) or textual (e.g. drwxr-xr-x) format.");
|
||||
}
|
||||
|
||||
output += "Textual representation: " + permsToStr(perms);
|
||||
|
69
src/core/operations/ParseURI.mjs
Normal file
69
src/core/operations/ParseURI.mjs
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import url from "url";
|
||||
|
||||
/**
|
||||
* Parse URI operation
|
||||
*/
|
||||
class ParseURI extends Operation {
|
||||
|
||||
/**
|
||||
* ParseURI constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Parse URI";
|
||||
this.module = "URL";
|
||||
this.description = "Pretty prints complicated Uniform Resource Identifier (URI) strings for ease of reading. Particularly useful for Uniform Resource Locators (URLs) with a lot of arguments.";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(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) {
|
||||
const keys = Object.keys(uri.query);
|
||||
let padding = 0;
|
||||
|
||||
keys.forEach(k => {
|
||||
padding = (k.length > padding) ? k.length : padding;
|
||||
});
|
||||
|
||||
output += "Arguments:\n";
|
||||
for (const 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ParseURI;
|
@ -7,6 +7,7 @@
|
||||
import Operation from "../Operation";
|
||||
import {INFLATE_BUFFER_TYPE} from "../lib/Zlib";
|
||||
import rawinflate from "zlibjs/bin/rawinflate.min";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
const Zlib = rawinflate.Zlib;
|
||||
|
||||
@ -90,7 +91,7 @@ class RawInflate extends Operation {
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
throw "Error: Unable to inflate data";
|
||||
throw new OperationError("Error: Unable to inflate data");
|
||||
}
|
||||
}
|
||||
// This seems to be the easiest way...
|
||||
|
@ -7,6 +7,7 @@
|
||||
import Operation from "../Operation";
|
||||
import Utils from "../Utils";
|
||||
import {fromBase64, toBase64} from "../lib/Base64";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* Show Base64 offsets operation
|
||||
@ -58,7 +59,7 @@ class ShowBase64Offsets extends Operation {
|
||||
script = "<script type='application/javascript'>$('[data-toggle=\"tooltip\"]').tooltip()</script>";
|
||||
|
||||
if (input.length < 1) {
|
||||
return "Please enter a string.";
|
||||
throw new OperationError("Please enter a string.");
|
||||
}
|
||||
|
||||
// Highlight offset 0
|
||||
|
118
src/core/operations/Strings.mjs
Normal file
118
src/core/operations/Strings.mjs
Normal file
@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import XRegExp from "xregexp";
|
||||
import { search } from "../lib/Extract";
|
||||
/**
|
||||
* Strings operation
|
||||
*/
|
||||
class Strings extends Operation {
|
||||
|
||||
/**
|
||||
* Strings constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Strings";
|
||||
this.module = "Regex";
|
||||
this.description = "Extracts all strings from the input.";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Encoding",
|
||||
"type": "option",
|
||||
"value": ["Single byte", "16-bit littleendian", "16-bit bigendian", "All"]
|
||||
},
|
||||
{
|
||||
"name": "Minimum length",
|
||||
"type": "number",
|
||||
"value": 4
|
||||
},
|
||||
{
|
||||
"name": "Match",
|
||||
"type": "option",
|
||||
"value": [
|
||||
"[ASCII]", "Alphanumeric + punctuation (A)", "All printable chars (A)", "Null-terminated strings (A)",
|
||||
"[Unicode]", "Alphanumeric + punctuation (U)", "All printable chars (U)", "Null-terminated strings (U)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Display total",
|
||||
"type": "boolean",
|
||||
"value": false
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(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 search(input, regex, null, displayTotal);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Strings;
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* Take bytes operation
|
||||
@ -45,6 +46,8 @@ class TakeBytes extends Operation {
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {ArrayBuffer}
|
||||
*
|
||||
* @throws {OperationError} if invalid value
|
||||
*/
|
||||
run(input, args) {
|
||||
const start = args[0],
|
||||
@ -52,7 +55,7 @@ class TakeBytes extends Operation {
|
||||
applyToEachLine = args[2];
|
||||
|
||||
if (start < 0 || length < 0)
|
||||
throw "Error: Invalid value";
|
||||
throw new OperationError("Error: Invalid value");
|
||||
|
||||
if (!applyToEachLine)
|
||||
return input.slice(start, start+length);
|
||||
|
@ -7,6 +7,7 @@
|
||||
import Operation from "../Operation";
|
||||
import Utils from "../Utils";
|
||||
import {DELIM_OPTIONS} from "../lib/Delim";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* To Charcode operation
|
||||
@ -42,6 +43,8 @@ class ToCharcode extends Operation {
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*
|
||||
* @throws {OperationError} if base argument out of range
|
||||
*/
|
||||
run(input, args) {
|
||||
const delim = Utils.charRep(args[0] || "Space"),
|
||||
@ -51,7 +54,7 @@ class ToCharcode extends Operation {
|
||||
ordinal;
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
const charcode = Utils.strToCharcode(input);
|
||||
|
@ -7,6 +7,7 @@
|
||||
import Operation from "../Operation";
|
||||
import moment from "moment-timezone";
|
||||
import {UNITS} from "../lib/DateTime";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* To UNIX Timestamp operation
|
||||
@ -47,6 +48,8 @@ class ToUNIXTimestamp extends Operation {
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*
|
||||
* @throws {OperationError} if unit unrecognised
|
||||
*/
|
||||
run(input, args) {
|
||||
const [units, treatAsUTC, showDateTime] = args,
|
||||
@ -63,7 +66,7 @@ class ToUNIXTimestamp extends Operation {
|
||||
} else if (units === "Nanoseconds (ns)") {
|
||||
result = d.valueOf() * 1000000;
|
||||
} else {
|
||||
throw "Unrecognised unit";
|
||||
throw new OperationError("Unrecognised unit");
|
||||
}
|
||||
|
||||
return showDateTime ? `${result} (${d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss")} UTC)` : result.toString();
|
||||
|
@ -7,6 +7,7 @@
|
||||
import Operation from "../Operation";
|
||||
import moment from "moment-timezone";
|
||||
import {DATETIME_FORMATS, FORMAT_EXAMPLES} from "../lib/DateTime";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* Translate DateTime Format operation
|
||||
@ -67,7 +68,7 @@ class TranslateDateTimeFormat extends Operation {
|
||||
date = moment.tz(input, inputFormat, inputTimezone);
|
||||
if (!date || date.format() === "Invalid date") throw Error;
|
||||
} catch (err) {
|
||||
return "Invalid format.\n\n" + FORMAT_EXAMPLES;
|
||||
throw new OperationError(`Invalid format.\n\n${FORMAT_EXAMPLES}`);
|
||||
}
|
||||
|
||||
return date.tz(outputTimezone).format(outputFormat);
|
||||
|
44
src/core/operations/URLDecode.mjs
Normal file
44
src/core/operations/URLDecode.mjs
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
|
||||
/**
|
||||
* URL Decode operation
|
||||
*/
|
||||
class URLDecode extends Operation {
|
||||
|
||||
/**
|
||||
* URLDecode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "URL Decode";
|
||||
this.module = "URL";
|
||||
this.description = "Converts URI/URL percent-encoded characters back to their raw values.<br><br>e.g. <code>%3d</code> becomes <code>=</code>";
|
||||
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;
|
68
src/core/operations/URLEncode.mjs
Normal file
68
src/core/operations/URLEncode.mjs
Normal file
@ -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.<br><br>e.g. <code>=</code> becomes <code>%3d</code>";
|
||||
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;
|
@ -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;
|
@ -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;
|
@ -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_;
|
@ -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;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user