Compare commits

..

25 Commits

Author SHA1 Message Date
n1474335
68ab2da866 7.10.2 2018-04-30 16:51:24 +00:00
n1474335
72f7f0b70c Utils.fromHex function now defaults to automatically strip all delimiters. Fixes #295 2018-04-30 16:51:04 +00:00
n1474335
d18a7df3bc 7.10.1 2018-04-29 21:45:07 +01:00
n1474335
f81012ef6e CRC Checksum operations now send their input as ArrayBuffers. Tests added. Fixes #293 2018-04-29 21:44:54 +01:00
n1474335
cb66508b8a jsesc is now transpiled with babel 2018-04-06 15:44:49 +01:00
n1474335
c56038a1e2 Added error message for loading errors. Closes #254 2018-04-05 15:58:19 +00:00
n1474335
81e62a6c22 Merge branch 'master' of github.com:gchq/CyberChef 2018-03-29 00:00:09 +01:00
n1474335
c501720cdd 7.10.0 2018-03-28 23:58:52 +01:00
n1474335
92b5aa08f3 Updated dependencies 2018-03-28 23:58:43 +01:00
n1474335
1097170a68 Updated dependencies 2018-03-28 23:56:33 +01:00
n1474335
e6e2b169dc Merge branch 'tlwr-feature-add-pgp-kbpgp' 2018-03-28 23:27:01 +01:00
n1474335
e41145427e Tidied up PGP operations and added progress callback 2018-03-28 23:26:48 +01:00
n1474335
caadf8e762 Added tags to X.509 operation description 2018-03-28 10:22:22 +00:00
n1474335
1143c23ad9 Merge branch 'feature-add-pgp-kbpgp' of https://github.com/tlwr/CyberChef into tlwr-feature-add-pgp-kbpgp 2018-03-27 00:07:20 +01:00
Toby Lorne
aa3f781e18 Merge pull request #3 from artemisbot/features/add-pgp-kbpgp
Update to master & add verify/sign
2018-01-13 12:33:28 +00:00
Matt C
50a3cc57ad Fixed missing newline 2018-01-12 18:18:52 +00:00
Matt C
7554cbda72 Added PGP Sign/Verify operations 2018-01-12 16:52:15 +00:00
Matt C
6a67fe09de Added passphrase support to importing private key 2018-01-12 12:03:46 +00:00
Matt C
f07263ca2a Fix decrypt operation 2018-01-12 11:45:16 +00:00
Matt C
bfbefb7318 Merge branch 'master' into features/add-pgp-kbpgp 2018-01-11 22:57:31 +00:00
Toby Lorne
db8955d90d WIP: add encrypt and decrypt operations
Currently the encrypt operation works only to my public key and not to
keys generated by the generate key pair operation. Probably something
wrong with the generate operation.
2017-12-24 17:44:32 +00:00
Toby Lorne
5a5ce1101b Merge pull request #2 from artemisbot/features/add-pgp-kbpgp
Promisified generation of key pair
2017-12-23 17:33:42 +00:00
Matt C
670566b7eb Promisified generation of key pair 2017-12-21 14:23:31 +00:00
tlwr
dcd8f98e8c Fix linting in PGP operations 2017-11-26 20:13:49 +00:00
tlwr
60c8da7bbb Add operation "Generate PGP Key Pair"
Have not yet found a nice way of working with the kbpgp API as it is
very callback heavy. Probably just my rusty javascript.
2017-11-25 16:00:33 +00:00
18 changed files with 1478 additions and 685 deletions

View File

@@ -5,7 +5,7 @@
"chrome": 40,
"firefox": 35,
"edge": 14,
"node": "6.5",
"node": "6.5"
},
"modules": false,
"useBuiltIns": true

View File

@@ -318,7 +318,7 @@ module.exports = function (grunt) {
chunks: false,
modules: false,
entrypoints: false,
warningsFilter: /source-map/,
warningsFilter: [/source-map/, /dependency is an expression/],
}
},
start: {

1368
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "7.9.0",
"version": "7.10.2",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef",
@@ -31,13 +31,14 @@
"bugs": "https://github.com/gchq/CyberChef/issues",
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.3",
"babel-loader": "^7.1.4",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.1",
"css-loader": "^0.28.10",
"eslint": "^4.18.1",
"css-loader": "^0.28.11",
"eslint": "^4.19.1",
"exports-loader": "^0.7.0",
"extract-text-webpack-plugin": "^4.0.0-alpha0",
"file-loader": "^1.1.10",
"file-loader": "^1.1.11",
"grunt": ">=1.0.2",
"grunt-accessibility": "~6.0.0",
"grunt-chmod": "~1.1.1",
@@ -48,23 +49,23 @@
"grunt-exec": "~3.0.0",
"grunt-execute": "^0.2.2",
"grunt-jsdoc": "^2.2.1",
"grunt-webpack": "^3.0.2",
"html-webpack-plugin": "^3.0.4",
"grunt-webpack": "^3.1.1",
"html-webpack-plugin": "^3.1.0",
"imports-loader": "^0.8.0",
"ink-docstrap": "^1.3.2",
"jsdoc-babel": "^0.3.0",
"jsdoc-babel": "^0.4.0",
"less": "^3.0.1",
"less-loader": "^4.0.6",
"postcss-css-variables": "^0.8.0",
"less-loader": "^4.1.0",
"postcss-css-variables": "^0.8.1",
"postcss-import": "^11.1.0",
"postcss-loader": "^2.1.1",
"postcss-loader": "^2.1.3",
"sitemap": "^1.13.0",
"style-loader": "^0.20.2",
"url-loader": "^0.6.2",
"style-loader": "^0.20.3",
"url-loader": "^1.0.1",
"val-loader": "^1.1.0",
"web-resource-inliner": "^4.2.1",
"webpack": "^4.0.1",
"webpack-dev-server": "^3.1.0",
"webpack": "^4.3.0",
"webpack-dev-server": "^3.1.1",
"webpack-node-externals": "^1.6.0",
"worker-loader": "^1.1.1"
},
@@ -79,12 +80,13 @@
"crypto-api": "^0.8.0",
"crypto-js": "^3.1.9-1",
"ctph.js": "0.0.5",
"diff": "^3.4.0",
"diff": "^3.5.0",
"escodegen": "^1.9.1",
"es6-promisify": "^6.0.0",
"esmangle": "^1.0.1",
"esprima": "^4.0.0",
"exif-parser": "^0.1.12",
"file-saver": "^1.3.3",
"file-saver": "^1.3.8",
"highlight.js": "^9.12.0",
"jquery": "^3.3.1",
"js-crc": "^0.2.0",
@@ -92,15 +94,16 @@
"jsbn": "^1.1.0",
"jsesc": "^2.5.1",
"jsonpath": "^1.0.0",
"jsrsasign": "8.0.6",
"jsrsasign": "8.0.7",
"lodash": "^4.17.5",
"loglevel": "^1.6.1",
"kbpgp": "^2.0.77",
"loglevel-message-prefix": "^3.0.0",
"moment": "^2.20.1",
"moment": "^2.21.0",
"moment-timezone": "^0.5.14",
"node-forge": "^0.7.2",
"node-forge": "^0.7.4",
"node-md6": "^0.1.0",
"nwmatcher": "^1.4.3",
"nwmatcher": "^1.4.4",
"otp": "^0.1.3",
"scryptsy": "^2.0.0",
"sladex-blowfish": "^0.8.1",

View File

@@ -718,10 +718,10 @@ const Utils = {
* Utils.fromHex("0a:14:1e", "Colon");
*/
fromHex: function(data, delim, byteLen) {
delim = delim || (data.indexOf(" ") >= 0 ? "Space" : "None");
delim = delim || "Auto";
byteLen = byteLen || 2;
if (delim !== "None") {
const delimRegex = Utils.regexRep[delim];
const delimRegex = delim === "Auto" ? /[^a-f\d]/gi : Utils.regexRep[delim];
data = data.replace(delimRegex, "");
}

View File

@@ -114,6 +114,11 @@ const Categories = [
"Hex to PEM",
"Hex to Object Identifier",
"Object Identifier to Hex",
"Generate PGP Key Pair",
"PGP Encrypt",
"PGP Decrypt",
"PGP Encrypt and Sign",
"PGP Decrypt and Verify",
]
},
{

155
src/core/config/OperationConfig.js Executable file → Normal file
View File

@@ -28,6 +28,7 @@ import MAC from "../operations/MAC.js";
import MorseCode from "../operations/MorseCode.js";
import NetBIOS from "../operations/NetBIOS.js";
import PHP from "../operations/PHP.js";
import PGP from "../operations/PGP.js";
import PublicKey from "../operations/PublicKey.js";
import Punycode from "../operations/Punycode.js";
import Regex from "../operations/Regex.js";
@@ -623,7 +624,7 @@ const OperationConfig = {
{
name: "Delimiter",
type: "option",
value: ByteRepr.HEX_DELIM_OPTIONS
value: ByteRepr.FROM_HEX_DELIM_OPTIONS
}
]
},
@@ -638,7 +639,7 @@ const OperationConfig = {
{
name: "Delimiter",
type: "option",
value: ByteRepr.HEX_DELIM_OPTIONS
value: ByteRepr.TO_HEX_DELIM_OPTIONS
}
]
},
@@ -3303,14 +3304,14 @@ const OperationConfig = {
"CRC-32 Checksum": {
module: "Hashing",
description: "A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data.<br><br>The CRC was invented by W. Wesley Peterson in 1961; the 32-bit CRC function of Ethernet and many other standards is the work of several researchers and was published in 1975.",
inputType: "string",
inputType: "ArrayBuffer",
outputType: "string",
args: []
},
"CRC-16 Checksum": {
module: "Hashing",
description: "A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data.<br><br>The CRC was invented by W. Wesley Peterson in 1961.",
inputType: "string",
inputType: "ArrayBuffer",
outputType: "string",
args: []
},
@@ -3363,7 +3364,7 @@ const OperationConfig = {
},
"Parse X.509 certificate": {
module: "PublicKey",
description: "X.509 is an ITU-T standard for a public key infrastructure (PKI) and Privilege Management Infrastructure (PMI). It is commonly involved with SSL/TLS security.<br><br>This operation displays the contents of a certificate in a human readable format, similar to the openssl command line tool.",
description: "X.509 is an ITU-T standard for a public key infrastructure (PKI) and Privilege Management Infrastructure (PMI). It is commonly involved with SSL/TLS security.<br><br>This operation displays the contents of a certificate in a human readable format, similar to the openssl command line tool.<br><br>Tags: X509, server hello, handshake",
inputType: "string",
outputType: "string",
args: [
@@ -4159,6 +4160,150 @@ const OperationConfig = {
outputType: "string",
args: []
},
"Generate PGP Key Pair": {
module: "PGP",
description: "Generates a new public/private PGP key pair. Supports RSA and Eliptic Curve (EC) keys.",
inputType: "string",
outputType: "string",
args: [
{
name: "Key type",
type: "option",
value: PGP.KEY_TYPES
},
{
name: "Password (optional)",
type: "string",
value: ""
},
{
name: "Name (optional)",
type: "string",
value: ""
},
{
name: "Email (optional)",
type: "string",
value: ""
},
]
},
"PGP Encrypt": {
module: "PGP",
description: [
"Input: the message you want to encrypt.",
"<br><br>",
"Arguments: the ASCII-armoured PGP public key of the recipient.",
"<br><br>",
"Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.",
"<br><br>",
"This function uses the Keybase implementation of PGP.",
].join("\n"),
inputType: "string",
outputType: "string",
args: [
{
name: "Public key of recipient",
type: "text",
value: ""
},
]
},
"PGP Decrypt": {
module: "PGP",
description: [
"Input: the ASCII-armoured PGP message you want to decrypt.",
"<br><br>",
"Arguments: the ASCII-armoured PGP private key of the recipient, ",
"(and the private key password if necessary).",
"<br><br>",
"Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.",
"<br><br>",
"This function uses the Keybase implementation of PGP.",
].join("\n"),
inputType: "string",
outputType: "string",
args: [
{
name: "Private key of recipient",
type: "text",
value: ""
},
{
name: "Private key passphrase",
type: "string",
value: ""
},
]
},
"PGP Encrypt and Sign": {
module: "PGP",
description: [
"Input: the cleartext you want to sign.",
"<br><br>",
"Arguments: the ASCII-armoured private key of the signer (plus the private key password if necessary)",
"and the ASCII-armoured PGP public key of the recipient.",
"<br><br>",
"This operation uses PGP to produce an encrypted digital signature.",
"<br><br>",
"Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.",
"<br><br>",
"This function uses the Keybase implementation of PGP.",
].join("\n"),
inputType: "string",
outputType: "string",
args: [
{
name: "Private key of signer",
type: "text",
value: ""
},
{
name: "Private key passphrase",
type: "string",
value: ""
},
{
name: "Public key of recipient",
type: "text",
value: ""
},
]
},
"PGP Decrypt and Verify": {
module: "PGP",
description: [
"Input: the ASCII-armoured encrypted PGP message you want to verify.",
"<br><br>",
"Arguments: the ASCII-armoured PGP public key of the signer, ",
"the ASCII-armoured private key of the recipient (and the private key password if necessary).",
"<br><br>",
"This operation uses PGP to decrypt and verify an encrypted digital signature.",
"<br><br>",
"Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.",
"<br><br>",
"This function uses the Keybase implementation of PGP.",
].join("\n"),
inputType: "string",
outputType: "string",
args: [
{
name: "Public key of signer",
type: "text",
value: "",
},
{
name: "Private key of recipient",
type: "text",
value: "",
},
{
name: "Private key password",
type: "string",
value: "",
},
]
},
};

View File

@@ -0,0 +1,25 @@
import PGP from "../../operations/PGP.js";
/**
* PGP module.
*
* Libraries:
* - kbpgp
*
* @author tlwr [toby@toby.codes]
* @author Matt C [matt@artemisbot.uk]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.PGP = {
"Generate PGP Key Pair": PGP.runGenerateKeyPair,
"PGP Encrypt": PGP.runEncrypt,
"PGP Decrypt": PGP.runDecrypt,
"PGP Encrypt and Sign": PGP.runSign,
"PGP Decrypt and Verify": PGP.runVerify,
};
export default OpModules;

View File

@@ -21,7 +21,12 @@ const ByteRepr = {
* @constant
* @default
*/
HEX_DELIM_OPTIONS: ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "0x", "\\x", "None"],
TO_HEX_DELIM_OPTIONS: ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "0x", "\\x", "None"],
/**
* @constant
* @default
*/
FROM_HEX_DELIM_OPTIONS: ["Auto", "Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "0x", "\\x", "None"],
/**
* @constant
* @default

View File

@@ -120,7 +120,7 @@ const Checksum = {
/**
* CRC-32 Checksum operation.
*
* @param {string} input
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/
@@ -132,7 +132,7 @@ const Checksum = {
/**
* CRC-16 Checksum operation.
*
* @param {string} input
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/

358
src/core/operations/PGP.js Executable file
View File

@@ -0,0 +1,358 @@
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,
});
if (key.is_pgp_locked() && passphrase) {
if (passphrase) {
await promisify(key.unlock_pgp.bind(key))({
passphrase
});
} else if (!passphrase) {
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,
});
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;

View File

@@ -82,6 +82,9 @@ App.prototype.loaded = function() {
// Clear the loading message interval
clearInterval(window.loadingMsgsInt);
// Remove the loading error handler
window.removeEventListener("error", window.loadingErrorHandler);
document.dispatchEvent(this.manager.apploaded);
};

View File

@@ -42,7 +42,7 @@
}
// Define loading messages
const loadingMsgs = [
var loadingMsgs = [
"Proving P = NP...",
"Computing 6 x 9...",
"Mining bitcoin...",
@@ -66,18 +66,18 @@
// Shuffle array using Durstenfeld algorithm
for (let i = loadingMsgs.length - 1; i > 0; --i) {
const j = Math.floor(Math.random() * (i + 1));
const temp = loadingMsgs[i];
var j = Math.floor(Math.random() * (i + 1));
var temp = loadingMsgs[i];
loadingMsgs[i] = loadingMsgs[j];
loadingMsgs[j] = temp;
}
// Show next loading message and move it to the end of the array
function changeLoadingMsg() {
const msg = loadingMsgs.shift();
var msg = loadingMsgs.shift();
loadingMsgs.push(msg);
try {
const el = document.getElementById("preloader-msg");
var el = document.getElementById("preloader-msg");
if (!el.classList.contains("loading"))
el.classList.add("loading"); // Causes CSS transition on first message
el.innerHTML = msg;
@@ -86,6 +86,46 @@
changeLoadingMsg();
window.loadingMsgsInt = setInterval(changeLoadingMsg, (Math.random() * 2000) + 1500);
// If any errors are thrown during loading, handle them here
function loadingErrorHandler(e) {
function escapeHtml(str) {
var HTML_CHARS = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': "&quot;",
"'": "&#x27;", // &apos; not recommended because it's not in the HTML spec
"/": "&#x2F;", // forward slash is included as it helps end an HTML entity
"`": "&#x60;"
};
return str.replace(/[&<>"'/`]/g, function (match) {
return HTML_CHARS[match];
});
}
var msg = e.message +
(e.filename ? "\nFilename: " + e.filename : "") +
(e.lineno ? "\nLine: " + e.lineno : "") +
(e.colno ? "\nColumn: " + e.colno : "") +
(e.error ? "\nError: " + e.error : "") +
"\nUser-Agent: " + navigator.userAgent +
"\nCyberChef version: <%= htmlWebpackPlugin.options.version %>";
clearInterval(window.loadingMsgsInt);
document.getElementById("preloader").remove();
document.getElementById("preloader-msg").remove();
document.getElementById("preloader-error").innerHTML =
"CyberChef encountered an error while loading.<br><br>" +
"The following browser versions are supported:" +
"<ul><li>Google Chrome 40+</li><li>Mozilla Firefox 35+</li><li>Microsoft Edge 14+</li></ul>" +
"Your user agent is:<br>" + escapeHtml(navigator.userAgent) + "<br><br>" +
"If your browser is supported, please <a href='https://github.com/gchq/CyberChef/issues/new'>" +
"raise an issue</a> including the following details:<br><br>" +
"<pre>" + escapeHtml(msg) + "</pre>";
};
window.addEventListener("error", loadingErrorHandler);
</script>
<% if (htmlWebpackPlugin.options.inline) { %>
<meta name="robots" content="noindex" />
@@ -100,6 +140,7 @@
<div id="loader-wrapper">
<div id="preloader" class="loader"></div>
<div id="preloader-msg" class="loading-msg"></div>
<div id="preloader-error" class="loading-error"></div>
</div>
<!-- End preloader overlay -->
<span id="edit-favourites" class="btn btn-default btn-sm"><img aria-hidden="true" src="<%- require('../static/images/favourite-16x16.png') %>" alt="Star Icon"/> Edit</span>

View File

@@ -64,3 +64,4 @@ window.compileMessage = COMPILE_MSG;
window.CanvasComponents = CanvasComponents;
document.addEventListener("DOMContentLoaded", main, false);

View File

@@ -74,6 +74,14 @@
transition: all 0.1s ease-in;
}
.loading-error {
display: block;
position: relative;
width: 600px;
left: calc(50% - 300px);
top: 10%;
}
/* Loaded */
.loaded .loading-msg {

View File

@@ -20,6 +20,7 @@ import "./tests/operations/BitwiseOp.js";
import "./tests/operations/BSON.js";
import "./tests/operations/ByteRepr.js";
import "./tests/operations/CharEnc.js";
import "./tests/operations/Checksum.js";
import "./tests/operations/Cipher.js";
import "./tests/operations/Code.js";
import "./tests/operations/Compress.js";

View File

@@ -0,0 +1,120 @@
/**
* Checksum tests.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import TestRegister from "../../TestRegister.js";
const BASIC_STRING = "The ships hung in the sky in much the same way that bricks don't.";
const UTF8_STR = "ნუ პანიკას";
const ALL_BYTES = [
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f",
"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f",
"\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
"\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f",
"\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f",
"\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f",
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f",
"\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f",
"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
"\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf",
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
"\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf",
"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef",
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
].join("");
TestRegister.addTests([
{
name: "CRC-16: nothing",
input: "",
expectedOutput: "0000",
recipeConfig: [
{
"op": "CRC-16 Checksum",
"args": []
}
]
},
{
name: "CRC-16: basic string",
input: BASIC_STRING,
expectedOutput: "0c70",
recipeConfig: [
{
"op": "CRC-16 Checksum",
"args": []
}
]
},
{
name: "CRC-16: UTF-8",
input: UTF8_STR,
expectedOutput: "dcf6",
recipeConfig: [
{
"op": "CRC-16 Checksum",
"args": []
}
]
},
{
name: "CRC-16: all bytes",
input: ALL_BYTES,
expectedOutput: "bad3",
recipeConfig: [
{
"op": "CRC-16 Checksum",
"args": []
}
]
},
{
name: "CRC-32: nothing",
input: "",
expectedOutput: "00000000",
recipeConfig: [
{
"op": "CRC-32 Checksum",
"args": []
}
]
},
{
name: "CRC-32: basic string",
input: BASIC_STRING,
expectedOutput: "bf4b739c",
recipeConfig: [
{
"op": "CRC-32 Checksum",
"args": []
}
]
},
{
name: "CRC-32: UTF-8",
input: UTF8_STR,
expectedOutput: "87553290",
recipeConfig: [
{
"op": "CRC-32 Checksum",
"args": []
}
]
},
{
name: "CRC-32: all bytes",
input: ALL_BYTES,
expectedOutput: "29058c73",
recipeConfig: [
{
"op": "CRC-32 Checksum",
"args": []
}
]
},
]);

View File

@@ -53,7 +53,7 @@ module.exports = {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
exclude: /node_modules\/(?!jsesc)/,
loader: "babel-loader?compact=false"
},
{
@@ -109,7 +109,7 @@ module.exports = {
chunks: false,
modules: false,
entrypoints: false,
warningsFilter: /source-map/,
warningsFilter: [/source-map/, /dependency is an expression/],
},
node: {
fs: "empty"