Merge 4d8d28b7aa4a7843e12f9c0e3e879de95c47951e into 2eada231feceb4474b418fb18de41722a6d47c20

This commit is contained in:
Toby Lorne 2017-04-13 18:15:29 +00:00 committed by GitHub
commit 06a11f8f63
10 changed files with 1498 additions and 109 deletions

View File

@ -69,6 +69,7 @@
"jsrsasign": "^7.1.0",
"moment": "^2.17.1",
"moment-timezone": "^0.5.11",
"openpgp": "^2.5.4",
"sladex-blowfish": "^0.8.1",
"sortablejs": "^1.5.1",
"split.js": "^1.2.0",

View File

@ -1,6 +1,6 @@
{
"parserOptions": {
"ecmaVersion": 6,
"ecmaVersion": 8,
"ecmaFeatures": {
"impliedStrict": true
},

View File

@ -145,10 +145,10 @@ Recipe.prototype.lastOpIndex = function(startIndex) {
* @param {number} [currentStep=0] - The index of the Operation to start executing from
* @returns {number} - The final progress through the recipe
*/
Recipe.prototype.execute = function(dish, currentStep, state) {
Recipe.prototype.execute = async function(dish, currentStep, state) {
var recipe = this;
var formatErrMsg = function(err, step, op) {
let formatErrMsg = function(err, step, op) {
var e = typeof err == "string" ? { message: err } : err;
e.progress = step;
@ -163,90 +163,40 @@ Recipe.prototype.execute = function(dish, currentStep, state) {
return e;
};
// Operations can be asynchronous so we have to return a Promise to a future value.
return new Promise(function(resolve, reject) {
// Helper function to clean up recursing to the next recipe step.
// It is a closure to avoid having to pass in resolve and reject.
var execRecipe = function(recipe, dish, step, state) {
return recipe.execute(dish, step, state)
.then(function(progress) {
resolve(progress);
})
.catch(function(err) {
// Pass back the error to the previous caller.
// We don't want to handle the error here as the current
// operation did not cause the error, and so it should
// not appear in the error message.
reject(err);
});
};
currentStep = currentStep || 0;
currentStep = currentStep || 0;
if (currentStep >= recipe.opList.length) {
return currentStep;
}
if (currentStep >= recipe.opList.length) {
resolve(currentStep);
return;
}
var op = recipe.opList[currentStep],
input = dish.get(op.inputType);
let op = recipe.opList[currentStep],
input = dish.get(op.inputType);
try {
if (op.isDisabled()) {
// Skip to next operation
var nextStep = currentStep + 1;
execRecipe(recipe, dish, nextStep, state);
return recipe.execute(dish, currentStep + 1, state);
} else if (op.isBreakpoint()) {
// We are at a breakpoint, we shouldn't recurse to the next op.
resolve(currentStep);
} else {
var operationResult;
// We must try/catch here because op.run can either return
// A) a value
// B) a promise
// Promise.resolve -> .catch will handle errors from promises
// try/catch will handle errors from values
try {
if (op.isFlowControl()) {
state = {
progress: currentStep,
dish: dish,
opList: recipe.opList,
numJumps: (state && state.numJumps) || 0,
};
operationResult = op.run(state);
} else {
operationResult = op.run(input, op.getIngValues());
}
} catch (err) {
reject(formatErrMsg(err, currentStep, op));
return;
}
if (op.isFlowControl()) {
Promise.resolve(operationResult)
.then(function(state) {
return recipe.execute(state.dish, state.progress + 1);
})
.then(function(progress) {
resolve(progress);
})
.catch(function(err) {
reject(formatErrMsg(err, currentStep, op));
});
} else {
Promise.resolve(operationResult)
.then(function(output) {
dish.set(output, op.outputType);
var nextStep = currentStep + 1;
execRecipe(recipe, dish, nextStep, state);
})
.catch(function(err) {
reject(formatErrMsg(err, currentStep, op));
});
}
return currentStep;
} else if (op.isFlowControl()) {
state = {
progress: currentStep,
dish: dish,
opList: recipe.opList,
numJumps: (state && state.numJumps) || 0,
};
state = await op.run(state);
let progress = await recipe.execute(state.dish, state.progress + 1);
return progress;
} else {
let output = await op.run(input, op.getIngValues());
dish.set(output, op.outputType);
return recipe.execute(dish, currentStep + 1, state);
}
});
} catch (err) {
throw formatErrMsg(err, currentStep, op);
}
};

View File

@ -92,6 +92,18 @@ const Categories = [
"Substitute",
"Derive PBKDF2 key",
"Derive EVP key",
"PGP Encrypt",
"PGP Decrypt",
"PGP Sign",
"PGP Verify",
"Sign PGP Detached",
"Verify PGP Detached",
"Sign PGP Cleartext",
"Verify PGP Cleartext",
"Generate PGP Key Pair",
"Detach PGP Cleartext",
"Add PGP ASCII Armour",
"Remove PGP ASCII Armour",
]
},
{
@ -103,6 +115,18 @@ const Categories = [
"Hex to PEM",
"Hex to Object Identifier",
"Object Identifier to Hex",
"PGP Encrypt",
"PGP Decrypt",
"PGP Sign",
"PGP Verify",
"Sign PGP Detached",
"Verify PGP Detached",
"Sign PGP Cleartext",
"Verify PGP Cleartext",
"Detach PGP Cleartext",
"Generate PGP Key Pair",
"Add PGP ASCII Armour",
"Remove PGP ASCII Armour",
]
},
{

View File

@ -26,6 +26,7 @@ import MorseCode from "../operations/MorseCode.js";
import NetBIOS from "../operations/NetBIOS.js";
import Numberwang from "../operations/Numberwang.js";
import OS from "../operations/OS.js";
import PGP from "../operations/PGP.js";
import PublicKey from "../operations/PublicKey.js";
import Punycode from "../operations/Punycode.js";
import QuotedPrintable from "../operations/QuotedPrintable.js";
@ -3181,6 +3182,353 @@ const OperationConfig = {
}
]
},
"PGP Encrypt": {
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 relies on OpenPGP.js for the implementation of PGP.",
"<br><br>",
"See more at https://openpgpjs.org/",
].join("\n"),
run: PGP.runEncrypt,
inputType: "string",
outputType: "string",
args: [
{
name: "Public key",
type: "text",
value: "",
},
]
},
"PGP Decrypt": {
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 relies on OpenPGP.js for the implementation of PGP.<br><br>See more at https://openpgpjs.org/",
].join("\n"),
run: PGP.runDecrypt,
inputType: "string",
outputType: "string",
args: [
{
name: "Private key",
type: "text",
value: "",
},
{
name: "Private key password",
type: "string",
value: "",
},
]
},
"PGP Sign": {
description: [
"Input: the cleartext you want to sign.",
"<br><br>",
"Arguments: the ASCII-armoured PGP public key of the recipient, ",
"the ASCII-armoured private key of the signer (and the private key password if necessary).",
"<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 relies on OpenPGP.js for the implementation of PGP.",
"<br><br>",
"See more at https://openpgpjs.org/",
].join("\n"),
run: PGP.runSign,
inputType: "string",
outputType: "string",
args: [
{
name: "Public key",
type: "text",
value: "",
},
{
name: "Private key",
type: "text",
value: "",
},
{
name: "Private key password",
type: "string",
value: "",
},
]
},
"PGP Verify": {
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 relies on OpenPGP.js for the implementation of PGP.",
"<br><br>",
"See more at https://openpgpjs.org/",
].join("\n"),
run: PGP.runVerify,
inputType: "string",
outputType: "string",
args: [
{
name: "Public key",
type: "text",
value: "",
},
{
name: "Private key",
type: "text",
value: "",
},
{
name: "Private key password",
type: "string",
value: "",
},
]
},
"Sign PGP Detached": {
description: [
"Input: the cleartext you want to sign.",
"<br><br>",
"Arguments: the ASCII-armoured PGP private key of the signer, ",
" (and the private key password if necessary).",
"<br><br>",
"This operation uses PGP to produce a cleartext message and its digital signature. ",
"It outputs 3 files as HTML: ",
"the cleartext message (msg), ",
"the ASCII-armoured signature (msg.asc), and ",
"the raw bytes of the signature (msg.sig).",
"<br><br>",
"Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.",
"<br><br>",
"This function relies on OpenPGP.js for the implementation of PGP.",
"<br><br>",
"See more at https://openpgpjs.org/",
].join("\n"),
run: PGP.runSignDetached,
inputType: "string",
outputType: "HTML",
args: [
{
name: "Private key",
type: "text",
value: "",
},
{
name: "Private key password",
type: "string",
value: "",
},
]
},
"Verify PGP Detached": {
description: [
"Input: the cleartext of the message you want to verify.",
"<br><br>",
"Arguments: the ASCII-armoured PGP public key of the sender, ",
"the ASCII-armoured signature of the message.",
"<br><br>",
"This operation uses PGP to verify a detached cleartext PGP signature.",
"<br><br>",
"Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.",
"<br><br>",
"This function relies on OpenPGP.js for the implementation of PGP.",
"<br><br>",
"See more at https://openpgpjs.org/",
].join("\n"),
run: PGP.runVerifyDetached,
inputType: "string",
outputType: "string",
args: [
{
name: "Public key",
type: "text",
value: "",
},
{
name: "Signature",
type: "text",
value: "",
},
]
},
"Sign PGP Cleartext": {
description: [
"Input: the cleartext of the message you want to sign.",
"<br><br>",
"Arguments: the ASCII-armoured PGP private key of the signer, ",
"(and the private key password if necessary).",
"<br><br>",
"This operation uses PGP to produce a digital signature.",
"<br><br>",
"Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.",
"<br><br>",
"This function relies on OpenPGP.js for the implementation of PGP.",
"<br><br>",
"See more at https://openpgpjs.org/",
].join("\n"),
run: PGP.runSignCleartext,
inputType: "string",
outputType: "string",
args: [
{
name: "Private key",
type: "text",
value: "",
},
{
name: "Private key password",
type: "string",
value: "",
},
]
},
"Verify PGP Cleartext": {
description: [
"Input: the ASCII-armoured cleartext signature you want to verify.",
"<br><br>",
"Arguments: the ASCII-armoured PGP public key of the sender.",
"<br><br>",
"This operation uses PGP to verify a cleartext digital signature.",
"<br><br>",
"Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.",
"<br><br>",
"This function relies on OpenPGP.js for the implementation of PGP.",
"<br><br>",
"See more at https://openpgpjs.org/",
].join("\n"),
run: PGP.runVerifyCleartext,
inputType: "string",
outputType: "string",
args: [
{
name: "Public key",
type: "text",
value: "",
},
]
},
"Generate PGP Key Pair": {
description: [
"Input is ignored.",
"<br><br>",
"This operation generates a PGP key pair.",
"<br><br>",
"Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.",
"<br><br>",
"This function relies on OpenPGP.js for the implementation of PGP.",
"<br><br>",
"See more at https://openpgpjs.org/",
].join("\n"),
run: PGP.runGenKeyPair,
inputType: "string",
outputType: "string",
args: [
{
name: "Password",
type: "string",
value: "",
},
{
name: "Key size",
type: "option",
value: ["1024", "2048", "4096"],
},
{
name: "Name",
type: "string",
value: "",
},
{
name: "Email",
type: "string",
value: "",
},
]
},
"Detach PGP Cleartext": {
description: [
"Input: the ASCII-armoured cleartext signature you want to verify.",
"<br><br>",
"This operation will detach the cleartext message from the signature.",
"It outputs 3 files as HTML: ",
"the cleartext message (msg), ",
"the ASCII-armoured signature (msg.asc), and ",
"the raw bytes of the signature (msg.sig).",
"<br><br>",
"Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.",
"<br><br>",
"This function relies on OpenPGP.js for the implementation of PGP.",
"<br><br>",
"See more at https://openpgpjs.org/",
].join("\n"),
run: PGP.runDetachClearsig,
inputType: "string",
outputType: "HTML",
args: [
],
},
"Add PGP ASCII Armour": {
description: [
"Input: the raw PGP bytes of the message or key that you want to add ASCII-armour to.",
"<br><br>",
"Arguments: the kind of the raw bytes: message / public key / private key.",
"<br><br>",
"This operation will output the ASCII-armoured input.",
"<br><br>",
"Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.",
"<br><br>",
"This function relies on OpenPGP.js for the implementation of PGP.",
"<br><br>",
"See more at https://openpgpjs.org/",
].join("\n"),
run: PGP.runAddArmour,
inputType: "byteArray",
outputType: "string",
args: [
{
name: "Armour type",
type: "option",
value: PGP.ARMOUR_TYPES,
},
],
},
"Remove PGP ASCII Armour": {
description: [
"Input: the ASCII-armoured PGP message or key that you want to remove the ASCII-armour from.",
"<br><br>",
"This operation will output the raw bytes of the PGP packets.",
"<br><br>",
"Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.",
"<br><br>",
"This function relies on OpenPGP.js for the implementation of PGP.",
"<br><br>",
"See more at https://openpgpjs.org/",
].join("\n"),
run: PGP.runRemoveArmour,
inputType: "string",
outputType: "byteArray",
args: [
],
},
};
export default OperationConfig;

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

@ -0,0 +1,596 @@
import * as openpgp from "openpgp";
import Utils from "../Utils.js";
/**
* PGP operations.
*
* @author tlwr [toby@toby.codes]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
* @namespace
*/
const PGP = {
/**
* @constant
* @default
*/
ARMOUR_TYPES: [
"Message",
"Public key",
"Private key",
],
/**
* @constant
* @default
*/
ARMOUR_TYPE_MAPPING: {
"Message": 3,
"Public key": 4,
"Private key": 5,
},
/**
* Encrypts the input using PGP.
*
* @param {string} input - plaintext to encrypt
* @param {Object[]} args
* @returns {string}
*/
runEncrypt: function (plaintext, args) {
let publicKey = args[0],
publicKeys;
try {
publicKeys = openpgp.key.readArmored(publicKey).keys;
} catch (err) {
throw "Cannot read public key: " + err;
}
let options = {
data: plaintext,
publicKeys: publicKeys,
};
return openpgp.encrypt(options)
.then(ciphertext => ciphertext.data)
.catch(function(err) {
throw "Could not encrypt text: " + err;
});
},
/**
* Decrypts the input using PGP.
*
* @param {string} input - ciphertext to decrypt
* @param {Object[]} args
* @returns {string}
*/
runDecrypt: function (input, args) {
let privateKey = args[0],
password = args[1],
message;
try {
privateKey = openpgp.key.readArmored(privateKey).keys[0];
} catch (err) {
throw "Cannot read private key: " + err;
}
try {
message = openpgp.message.readArmored(input);
} catch (err) {
throw "Cannot read message: " + err;
}
let options = {
message: message,
privateKey: privateKey,
};
if (password) {
privateKey.decrypt(password);
}
if (privateKey.primaryKey.encrypted !== null) {
throw "Could not decrypt private key.";
}
return openpgp.decrypt(options)
.then(plaintext => plaintext.data)
.catch(function(err) {
throw "Could not decrypt message: " + err;
});
},
/**
* Signs the input using PGP.
*
* @param {string} input - data to be signed
* @param {Object[]} args
* @returns {string}
*/
runSign: function (input, args) {
let publicKey = args[0],
privateKey = args[1],
password = args[2],
publicKeys,
privateKeys;
try {
publicKeys = openpgp.key.readArmored(publicKey).keys;
} catch (err) {
throw "Could not read public key: " + err;
}
try {
privateKeys = openpgp.key.readArmored(privateKey).keys;
} catch (err) {
throw "Could not read private key: " + err;
}
if (password) {
privateKeys[0].decrypt(password);
}
if (privateKeys[0].primaryKey.encrypted !== null) {
throw "Could not decrypt private key.";
}
let options = {
data: input,
publicKeys: publicKeys,
privateKeys: privateKeys,
};
return openpgp.encrypt(options)
.then(signedData => signedData.data)
.catch(function(err) {
throw "Could not sign input: " + err;
});
},
/**
* Verifies the signed input using PGP.
*
* @param {string} input - signed input to verify
* @param {Object[]} args
* @returns {string} - the original message, and a summary of the verification process
*/
runVerify: function (input, args) {
let publicKey = args[0],
privateKey = args[1],
password = args[2],
publicKeys,
privateKeys,
message;
try {
publicKeys = openpgp.key.readArmored(publicKey).keys;
} catch (err) {
throw "Could not read public key: " + err;
}
try {
privateKeys = openpgp.key.readArmored(privateKey).keys;
} catch (err) {
throw "Could not read private key: " + err;
}
if (password) {
privateKeys[0].decrypt(password);
}
if (privateKeys[0].primaryKey.encrypted !== null) {
throw "Could not decrypt private key.";
}
try {
message = openpgp.message.readArmored(input);
} catch (err) {
throw "Could not read encrypted message: " + err;
}
let packetContainingAlgorithms = message.packets.filterByTag(
openpgp.enums.packet.publicKeyEncryptedSessionKey
)[0];
let verification = {
verified: false,
pkAlgorithm: packetContainingAlgorithms.publicKeyAlgorithm,
sessionAlgorithm: packetContainingAlgorithms.sessionKeyAlgorithm,
author: publicKeys[0].users[0].userId.userid,
recipient: privateKeys[0].users[0].userId.userid,
keyID: "",
message: "",
};
return openpgp.decrypt({
message: message,
publicKeys: publicKeys,
privateKey: privateKeys[0],
})
.then(decrypted => {
if (decrypted.signatures) {
// valid is either true or null, casting required.
verification.verified = !!decrypted.signatures[0].valid;
verification.keyID = decrypted.signatures[0].keyid.toHex();
}
return [
"Verified: " + verification.verified,
"Key ID: " + verification.keyID,
"Encrypted for: " + verification.recipient,
"Signed by: " + verification.author,
"Signed with: " +
verification.pkAlgorithm +
"/" +
verification.sessionAlgorithm,
"\n",
decrypted.data,
].join("\n");
})
.catch(function(err) {
throw "Could not decrypt and verify message: " + err;
});
},
/**
* Signs the input using PGP and outputs the plaintext, the raw PGP signature, and the ASCII armoured signature files.
*
* @param {string} input - data to be signed
* @param {Object[]} args
* @returns {HTML} - HTML file display of message, armoured signature, and bytes signature
*/
runSignDetached: function (input, args) {
let privateKey = args[0],
password = args[1],
privateKeys;
try {
privateKeys = openpgp.key.readArmored(privateKey).keys;
} catch (err) {
throw "Could not read private key: " + err;
}
if (password) {
privateKeys[0].decrypt(password);
}
if (privateKeys[0].primaryKey.encrypted !== null) {
throw "Could not decrypt private key.";
}
let bytes = openpgp.util.str2Uint8Array(input);
let message = openpgp.message.fromBinary(bytes);
let signedMessage = message.sign(privateKeys);
let signature = signedMessage.packets.filterByTag(openpgp.enums.packet.signature);
let rawSignatureBytes = signature.write();
let armouredMessage = openpgp.armor.encode(
openpgp.enums.armor.message,
rawSignatureBytes
);
armouredMessage = armouredMessage.replace(
"-----BEGIN PGP MESSAGE-----\r\n",
"-----BEGIN PGP SIGNATURE-----\r\n"
);
armouredMessage = armouredMessage.replace(
"-----END PGP MESSAGE-----\r\n",
"-----END PGP SIGNATURE-----\r\n"
);
let files = [{
fileName: "msg",
size: input.length,
contents: input,
bytes: bytes,
}, {
fileName: "msg.asc",
size: armouredMessage.length,
contents: armouredMessage,
bytes: openpgp.util.str2Uint8Array(armouredMessage),
}, {
fileName: "msg.sig",
size: rawSignatureBytes.length,
contents: openpgp.util.Uint8Array2str(rawSignatureBytes),
bytes: rawSignatureBytes,
}];
return Utils.displayFilesAsHTML(files);
},
/**
* Verifies the detached signature and input using PGP.
*
* @param {string} input - signed input to verify
* @param {Object[]} args
* @returns {string} - the original message, and a summary of the verification process
*/
runVerifyDetached: function (input, args) {
let publicKey = args[0],
armouredSignature = args[1],
publicKeys,
message;
try {
publicKeys = openpgp.key.readArmored(publicKey).keys;
} catch (err) {
throw "Could not read public key: " + err;
}
try {
message = openpgp.message.readSignedContent(
input,
armouredSignature
);
} catch (err) {
throw "Could not read armoured signature or message: " + err;
}
let packetContainingSignature = message.packets.filterByTag(
openpgp.enums.packet.signature
)[0];
let verification = {
verified: false,
pkAlgorithm: publicKeys[0].primaryKey.algorithm,
author: publicKeys[0].users[0].userId.userid,
date: packetContainingSignature.created,
keyID: "",
message: "",
};
return Promise.resolve(message.verify(publicKeys))
.then(function(signatures) {
if (signatures && signatures.length) {
verification.verified = !!signatures[0].valid;
verification.keyID = signatures[0].keyid.toHex();
}
return [
"Verified: " + verification.verified,
"Key ID: " + verification.keyID,
"Signed on: " + verification.date,
"Signed by: " + verification.author,
"Signed with: " + verification.pkAlgorithm,
"\n",
input,
].join("\n");
})
.catch(function(err) {
throw "Could not verify message: " + err;
});
},
/**
* Clearsigns the input using PGP.
*
* @param {string} input - data to be signed
* @param {Object[]} args
* @returns {string}
*/
runSignCleartext: function (input, args) {
let privateKey = args[0],
password = args[1],
privateKeys;
try {
privateKeys = openpgp.key.readArmored(privateKey).keys;
} catch (err) {
throw "Could not read private key: " + err;
}
if (password) {
privateKeys[0].decrypt(password);
}
if (privateKeys[0].primaryKey.encrypted !== null) {
throw "Could not decrypt private key.";
}
let options = {
data: input,
privateKeys: privateKeys,
};
return openpgp.sign(options)
.then(signedData => signedData.data)
.catch(function(err) {
throw "Could not clearsign input: " + err;
});
},
/**
* Verifies the clearsigned input using PGP.
*
* @param {string} input - signed input to verify
* @param {Object[]} args
* @returns {string} - the original message, and a summary of the verification process
*/
runVerifyCleartext: function (input, args) {
let publicKey = args[0],
publicKeys,
message;
try {
publicKeys = openpgp.key.readArmored(publicKey).keys;
} catch (err) {
throw "Could not read public key: " + err;
}
try {
message = openpgp.cleartext.readArmored(input);
} catch (err) {
throw "Could not read input message: " + err;
}
let packetContainingSignature = message.packets.filterByTag(
openpgp.enums.packet.signature
)[0];
let verification = {
verified: false,
pkAlgorithm: publicKeys[0].primaryKey.algorithm,
author: publicKeys[0].users[0].userId.userid,
date: packetContainingSignature.created,
keyID: "",
message: message.text,
};
return openpgp.verify({
message: message,
publicKeys: publicKeys,
})
.then(verifiedData => {
if (verifiedData.signatures) {
// valid is either true or null, casting required.
verification.verified = !!verifiedData.signatures[0].valid;
verification.keyID = verifiedData.signatures[0].keyid.toHex();
}
return [
"Verified: " + verification.verified,
"Key ID: " + verification.keyID,
"Signed on: " + verification.date,
"Signed by: " + verification.author,
"Signed with: " + verification.pkAlgorithm,
"\n",
verification.message,
].join("\n");
})
.catch(function(err) {
throw "Could not verify message: " + err;
});
},
/**
* Generates a PGP key pair.
*
* @param {string} input is ignored
* @param {Object[]} args
* @returns {string} - armoured public key and private key separated by whitespace.
*/
runGenKeyPair: function (input, args) {
let password = args[0],
keySize = parseInt(args[1], 10),
name = args[2],
email = args[3];
let options = {
numBits: keySize,
userIds: [{name: name, email: email}],
};
if (password) {
options.passphrase = password;
}
return openpgp.generateKey(options)
.then(key => {
return [
key.publicKeyArmored,
key.privateKeyArmored,
].join(""); // Preceding and trailing newlines are already generated.
})
.catch(function(err) {
throw "Could not generate key pair: " + err;
});
},
/**
* Turns a PGP clearsigned message into a detached signature.
*
* @param {string} input
* @param {Object[]} args
* @returns {HTML} - HTML file display of message, armoured signature, and bytes signature
*/
runDetachClearsig: function (input, args) {
let message;
try {
message = openpgp.cleartext.readArmored(input);
} catch (err) {
throw "Could not read input message: " + err;
}
let cleartext = message.getText();
let clearbytes = openpgp.util.str2Uint8Array(cleartext);
let signature = message.packets.filterByTag(openpgp.enums.packet.signature);
let rawSignatureBytes = signature.write();
let armouredMessage = openpgp.armor.encode(
openpgp.enums.armor.message,
rawSignatureBytes
);
armouredMessage = armouredMessage.replace(
"-----BEGIN PGP MESSAGE-----\r\n",
"-----BEGIN PGP SIGNATURE-----\r\n"
);
armouredMessage = armouredMessage.replace(
"-----END PGP MESSAGE-----\r\n",
"-----END PGP SIGNATURE-----\r\n"
);
let files = [{
fileName: "msg",
size: cleartext.length,
contents: cleartext,
bytes: clearbytes,
}, {
fileName: "msg.asc",
size: armouredMessage.length,
contents: armouredMessage,
bytes: openpgp.util.str2Uint8Array(armouredMessage),
}, {
fileName: "msg.sig",
size: rawSignatureBytes.length,
contents: openpgp.util.Uint8Array2str(rawSignatureBytes),
bytes: rawSignatureBytes,
}];
return Utils.displayFilesAsHTML(files);
},
/**
* Turns raw PGP bytes into an ASCII armoured string.
*
* @param {byteArray} input
* @param {Object[]} args
* @returns {string} - armoured public key and private key separated by whitespace.
*/
runAddArmour: function (input, args) {
let armourType = PGP.ARMOUR_TYPE_MAPPING[args[0]];
return openpgp.armor.encode(armourType, input);
},
/**
* Turns an ASCII armoured string into raw PGP bytes.
*
* @param {string} input
* @param {Object[]} args
* @returns {byteArray}
*/
runRemoveArmour: function (input, args) {
let decoded = openpgp.armor.decode(input);
let uint8bytes = decoded.data;
let bytes = Array.prototype.slice.call(uint8bytes);
return bytes;
},
};
export default PGP;

View File

@ -112,41 +112,45 @@ App.prototype.bake = function(step) {
app.setBakingStatus(true);
try {
app.chef.bake(
app.getInput(), // The user's input
app.getRecipeConfig(), // The configuration of the recipe
app.options, // Options set by the user
app.progress, // The current position in the recipe
step // Whether or not to take one step or execute the whole recipe
)
.then(function(response) {
app.setBakingStatus(false);
// This timeout is so the UI has time to update the baking status
// before any blocking operations delay it until after the operation.
setTimeout(function() {
app.chef.bake(
app.getInput(), // The user's input
app.getRecipeConfig(), // The configuration of the recipe
app.options, // Options set by the user
app.progress, // The current position in the recipe
step // Whether or not to take one step or execute the whole recipe
)
.then(function(response) {
app.setBakingStatus(false);
if (!response) return;
if (response.error) app.handleError(response.error);
if (!response) return;
if (response.error) app.handleError(response.error);
app.options = response.options;
app.options = response.options;
if (response.type === "html") {
app.dishStr = Utils.stripHtmlTags(response.result, true);
} else {
app.dishStr = response.result;
}
if (response.type === "html") {
app.dishStr = Utils.stripHtmlTags(response.result, true);
} else {
app.dishStr = response.result;
}
app.progress = response.progress;
app.manager.recipe.updateBreakpointIndicator(response.progress);
app.manager.output.set(response.result, response.type, response.duration);
app.progress = response.progress;
app.manager.recipe.updateBreakpointIndicator(response.progress);
app.manager.output.set(response.result, response.type, response.duration);
// If baking took too long, disable auto-bake
if (response.duration > app.options.autoBakeThreshold && app.autoBake_) {
app.manager.controls.setAutoBake(false);
app.alert("Baking took longer than " + app.options.autoBakeThreshold +
"ms, Auto Bake has been disabled.", "warning", 5000);
}
})
.catch(function(err) {
console.error("Chef's promise was rejected, this should never occur");
});
// If baking took too long, disable auto-bake
if (response.duration > app.options.autoBakeThreshold && app.autoBake_) {
app.manager.controls.setAutoBake(false);
app.alert("Baking took longer than " + app.options.autoBakeThreshold +
"ms, Auto Bake has been disabled.", "warning", 5000);
}
})
.catch(function(err) {
console.error("Chef's promise was rejected, this should never occur");
});
}, 10);
} catch (err) {
app.setBakingStatus(false);
app.handleError(err);

View File

@ -54,6 +54,11 @@ import Chef from "../src/core/Chef.js";
output: null,
};
// Remove whitespace helper
var noWS = function(string) {
return string.replace(/\s/g, "");
};
if (result.error) {
if (test.expectedError) {
ret.status = "passing";
@ -67,6 +72,9 @@ import Chef from "../src/core/Chef.js";
ret.output = "Expected an error but did not receive one.";
} else if (result.result === test.expectedOutput) {
ret.status = "passing";
} else if (test.ignoreWhitespace &&
noWS(result.result) === noWS(test.expectedOutput)) {
ret.status = "passing";
} else {
ret.status = "failing";
ret.output = [

View File

@ -15,6 +15,7 @@ import "./tests/operations/Base58.js";
import "./tests/operations/Compress.js";
import "./tests/operations/FlowControl.js";
import "./tests/operations/MorseCode.js";
import "./tests/operations/PGP.js";
import "./tests/operations/StrUtils.js";
var allTestsPassing = true,

View File

@ -0,0 +1,457 @@
/**
* PGP tests.
*
* @author tlwr [toby@toby.codes]
*
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import TestRegister from "../../TestRegister.js";
const CYBERCHEF_GENERATED_KEY_PAIRS = [
{
name: "CyberChef 1",
size: 1024,
pub: [
"-----BEGIN PGP PUBLIC KEY BLOCK-----",
"Version: OpenPGP.js v2.3.6",
"Comment: http://openpgpjs.org",
"",
"xo0EWMQszAEEAMY6F0o6jL6TrVVXDkqJwNVJRR6tQKr+LIt7plEJoaTRVDfL",
"1jetdhPg+YiE7xZI8ygf6fhsrot4ccUN1QdtwedAz6GH0xjFzpL1i4/7/f3U",
"ItJ0p1MO4Amy8Tei/AtXXMTy/YwE77V1AMcv7OYFw9va5S0PD87XoKK6rx7z",
"GFMTABEBAAHNAjw+wrUEEAEIACkFAljELMwGCwkHCAMCCRAar/puuym6vQQV",
"CAIKAxYCAQIZAQIbAwIeAQAA8/QEAKDVde34L3rvFECzUOFPA5w4w4gbwkg+",
"YwPa084WvMTdo/wBEiEhj+7P+/5eN/U96yuHD48+Cmm5AHBaaf+K1b2LbNe7",
"3PP5rV1rMcooUGeIhq7SFw0BdPZTLoCNbkBKFCpvrS/F4SuUQF7g+fVyOyve",
"zVWew+E41ZC3vsDd63Y3zo0EWMQszAEEANYNy0yka1+c3Oe2U1GqoAHXv05p",
"VnlHAZ+28JGs8Thq5ns0K8bxI+Fn9CFpPO7Vofrr40V3vweoJVK2Eiq2gN/X",
"QdxPHckcpYbFKTAZIXt2MAZfb027JxWZid5lyYSCwvY+BK7x5X4jdY5KfbKu",
"7WDivOkq8MhomSiX+QYDV8qrABEBAAHCnwQYAQgAEwUCWMQszAkQGq/6brsp",
"ur0CGwwAAIjWA/9WhpbfM+oA08m5XwXgCkuRfTymIkexzn17dZOngTzaGcbK",
"vpS3QN164XNu229JNKTrsdgn5zeeq3AqhQ63hTMbePajvUYSssHPqKB8qQlp",
"OUY/rcFEUXMirIkKBGByYBmlz56Ai855wJoSOrZJA6yfnGepyV5ChcG/cEmB",
"dH/6bA==",
"=4nW6",
"-----END PGP PUBLIC KEY BLOCK-----",
].join("\n"),
sec: [
"-----BEGIN PGP PRIVATE KEY BLOCK-----",
"Version: OpenPGP.js v2.3.6",
"Comment: http://openpgpjs.org",
"",
"xcEYBFjELMwBBADGOhdKOoy+k61VVw5KicDVSUUerUCq/iyLe6ZRCaGk0VQ3",
"y9Y3rXYT4PmIhO8WSPMoH+n4bK6LeHHFDdUHbcHnQM+hh9MYxc6S9YuP+/39",
"1CLSdKdTDuAJsvE3ovwLV1zE8v2MBO+1dQDHL+zmBcPb2uUtDw/O16Ciuq8e",
"8xhTEwARAQABAAP6A0jnJeW+e1H7J1Tf+cA6n84tBQsd7Td1CYKtCN69/Psz",
"CBGqpRWMxVuPBwIc7COdU+bje6hhZBJE4F0QUKUy91iQRssy4MzOYmZbdZaa",
"eTT81MdYb6QPYdTvPBVxjeLJBL7mKB+hM2Z8SvtJMDBdLlprf/XIdZKxD/NB",
"R+q66OECAPPsaMb+Yv1F30pEJZkATWvUSQS57HzWoBaNGxGkDqcik7+2q3DU",
"fWe0586HfMFQ3ba1ziNy2SWYJDAqMAe0QekCANAKgQJwww75GGK1RwNFZRoJ",
"Sb/Jzx3RVbwy1xqfVbadTuvf2+oSBLy/+eGXglwrok08e2BvYWMmhB+uJSJb",
"M5sCAItUBCJqTszPQPZdIOi7rGomnL2fijBDAUz+kWAWBPcIf8zzexKl7Ebq",
"dxc621BD5xjDjE7x1Z5XX/Rd2Lt+PvOdyM0CPD7CtQQQAQgAKQUCWMQszAYL",
"CQcIAwIJEBqv+m67Kbq9BBUIAgoDFgIBAhkBAhsDAh4BAADz9AQAoNV17fgv",
"eu8UQLNQ4U8DnDjDiBvCSD5jA9rTzha8xN2j/AESISGP7s/7/l439T3rK4cP",
"jz4KabkAcFpp/4rVvYts17vc8/mtXWsxyihQZ4iGrtIXDQF09lMugI1uQEoU",
"Km+tL8XhK5RAXuD59XI7K97NVZ7D4TjVkLe+wN3rdjfHwRgEWMQszAEEANYN",
"y0yka1+c3Oe2U1GqoAHXv05pVnlHAZ+28JGs8Thq5ns0K8bxI+Fn9CFpPO7V",
"ofrr40V3vweoJVK2Eiq2gN/XQdxPHckcpYbFKTAZIXt2MAZfb027JxWZid5l",
"yYSCwvY+BK7x5X4jdY5KfbKu7WDivOkq8MhomSiX+QYDV8qrABEBAAEAA/0e",
"rqd/eunxMJjxlc7nm9+HpBdF9A9zHtx6ukxNdU62WYxkCJxlzdbozm/OAjm7",
"ul+XigxvvrRhMpb2/iYofTSHnj+6yGGghCic6BtstJOU7qepMrX+IKh3TNEp",
"YNU8z0E1fSd9fMOx1hnTZwaTroii9CzM0i4YH3pSjze7Ir7cIQIA8Cg8sBmG",
"IDhe7SBq5xcG2V4iNqiK5gHXbQrcit9/XJFqIeda5Ec7lRjpa6vG5f1xeT1w",
"KdBil2L4prnD6XDAEwIA5Cy51YIjizFyKormqQNGR1fdAl+6T/qReUcw5Cmw",
"cDU7tUujZwZz/utmjOcadq8JR2LG6rNwLzeMgDNCCKAOCQH/RX0h3eLXcpWq",
"jGBH3mJbukSLH/98ybP5LV+4jg0q5iXOOjUIXxFsPElyZZHUBvpoRrKbRG/f",
"PzOpx7akqEOuDJ/Dwp8EGAEIABMFAljELMwJEBqv+m67Kbq9AhsMAACI1gP/",
"VoaW3zPqANPJuV8F4ApLkX08piJHsc59e3WTp4E82hnGyr6Ut0DdeuFzbttv",
"STSk67HYJ+c3nqtwKoUOt4UzG3j2o71GErLBz6igfKkJaTlGP63BRFFzIqyJ",
"CgRgcmAZpc+egIvOecCaEjq2SQOsn5xnqcleQoXBv3BJgXR/+mw=",
"=8R+g",
"-----END PGP PRIVATE KEY BLOCK-----",
].join("\n"),
},
];
const PGP_TEST_KEY_PAIRS = [
{
keyID: "a9510d8fd7e352f5",
name: "CyberChef nopw 1024 <toby@toby.codes>",
size: 1024,
pub: [
"-----BEGIN PGP PUBLIC KEY BLOCK-----",
"",
"mI0EWL7mbwEEANVcA5s+pXliwZBZXvfjy69JlPkX8dWRTZLuqZPz5XKGb9E1RKxQ",
"jELZ9bBIv/t0HDoiwh1XJok3SRMPzLPHK9lLXaa/l7716CkRddTvkd3cjFA3yAEL",
"X97+4nPVIajYUPDy6ovCrRru2bXyW2cjHKErlI0GJ37Hbbpj/GXSQL6HABEBAAG0",
"JUN5YmVyQ2hlZiBub3B3IDEwMjQgPHRvYnlAdG9ieS5jb2Rlcz6ItwQTAQgAIQUC",
"WL7mbwIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRCpUQ2P1+NS9ZhxA/49",
"sXqWYoi34HMtHfVejPpPSXrFxY+ZjgM1cMVe5m4cumBeZVVYaEH9/3xDlrhfrlMi",
"xCRGNqfIRwavIbNWyBshrjVnZ1PR/hvp2P3tV0ciV51lJi6ApO46fsmsWZw84cOA",
"ejQ1giBjuLuu4du52+MVbcko2yEJ2tOS2WMPnYO7RbiNBFi+5m8BBAClMs6KZuXd",
"2mhmz3vGcczlA0vv2k7lZjdT7LmbYLt/ir7Hdqg7z7l84wO1qPNQc6pRkLVd1rMX",
"8fh+RtLUVAuvATpRJCAdaeslcxaH7o0p5DbjrRmiDmnaLDl/S0xMhI137XaKdUS7",
"ZRuGFZVfqXeFerpbjrlUlhzAcHua8aAmHQARAQABiJ8EGAEIAAkFAli+5m8CGwwA",
"CgkQqVENj9fjUvUA6AP/b9jZvaQ7w6mdlCvCrFpfp3vBZN1E0vLIMdRKRMmNR8D7",
"pmZ4RcmMJxjVTLkB6Uc90+9Tbb2ysykQaTTw3YdpmyoGmy3qgH3opd/IdZzEAJyL",
"oBC+u8G7nATB58m4xmBYL1G5hn8nCBbNAiz1rrbXmWmVExQCVAXp7T50vPBdyFY=",
"=xCxV",
"-----END PGP PUBLIC KEY BLOCK-----",
].join("\n"),
sec: [
"-----BEGIN PGP PRIVATE KEY BLOCK-----",
"",
"lQHYBFi+5m8BBADVXAObPqV5YsGQWV7348uvSZT5F/HVkU2S7qmT8+Vyhm/RNUSs",
"UIxC2fWwSL/7dBw6IsIdVyaJN0kTD8yzxyvZS12mv5e+9egpEXXU75Hd3IxQN8gB",
"C1/e/uJz1SGo2FDw8uqLwq0a7tm18ltnIxyhK5SNBid+x226Y/xl0kC+hwARAQAB",
"AAP7BLFYuDDhPrQDIgsdyzzsuIDPbj6G9z9+hsN/sLrZlEFbBt67c95+Sbzm6h1O",
"SdgcoZiPgJig0L3OyR1kO5ypBG4jhSgbaTKRHjP4KsOWoPuXmL1p8XLzZHOGp3hS",
"/recAxhqdbbO7uim+nbaPdmby9v0XrMAkFkBTU+D+ZlmC3ECAODTUZ7i+vRD6R3x",
"NzN2uhomWy94I7SkugTjcTw6BrzvdffFKtW7Yp6MbPdCpRIhuKy/QhG1LCUGwJKQ",
"vvNe5z8CAPLxrsx6jiFHpzAtUBYNBY5M3t805OYRFbs3mJ3LgsUP0wVOnODqo5TA",
"anevkFoakvcKJ8d0OlbO0/ewm4wd3rkB+wRQrllfYFfLqGzUlZDP15NKoHFk8T/w",
"LWg6nDm8pxXlhptaA8V4rVK1HrrPU56GBbzXftqL6iDpbYh9ZPR/U/qoXLQlQ3li",
"ZXJDaGVmIG5vcHcgMTAyNCA8dG9ieUB0b2J5LmNvZGVzPoi3BBMBCAAhBQJYvuZv",
"AhsDBQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJEKlRDY/X41L1mHED/j2xepZi",
"iLfgcy0d9V6M+k9JesXFj5mOAzVwxV7mbhy6YF5lVVhoQf3/fEOWuF+uUyLEJEY2",
"p8hHBq8hs1bIGyGuNWdnU9H+G+nY/e1XRyJXnWUmLoCk7jp+yaxZnDzhw4B6NDWC",
"IGO4u67h27nb4xVtySjbIQna05LZYw+dg7tFnQHYBFi+5m8BBAClMs6KZuXd2mhm",
"z3vGcczlA0vv2k7lZjdT7LmbYLt/ir7Hdqg7z7l84wO1qPNQc6pRkLVd1rMX8fh+",
"RtLUVAuvATpRJCAdaeslcxaH7o0p5DbjrRmiDmnaLDl/S0xMhI137XaKdUS7ZRuG",
"FZVfqXeFerpbjrlUlhzAcHua8aAmHQARAQABAAP8C0IAnaGbME4WMkzDyHIbPqTF",
"s9qX6NMumbthVLY4C4jhgnH9egH9x9sn9rpvm7/Iz2vXUvCdiNgLu/3zQoFYawsn",
"zpTQREm6CyITOLxyc5TrckodSlx6eoCezvnTzI/PvXrUSSqEP9c9hvcLuKm+aeZz",
"fclhPfDOL/EQx337aeECAMU0UXXb95hQqSdRMcsGkpoAlAIEM664/S9eBvXrJYWw",
"1Pfgms7Axi/tZ4ebkc3urRW/YKAt423Ixmdd5rOwIDECANZzoOU8LxreLcLQOoA9",
"SWswRWUeyQTvH4yskT2iIXen22CO1pp7ruy07vSxHE+yyR3t2ZHKPJU864J39d4k",
"da0CAJS838KMD8h+Zv1C/jhKkYjpnDRuE+Lj7qVNHCJqsFSzpJAbJ09VpwSGbUso",
"Ptc/oyXgzb91+sLKfsIwGa7ZysarEIifBBgBCAAJBQJYvuZvAhsMAAoJEKlRDY/X",
"41L1AOgD/2/Y2b2kO8OpnZQrwqxaX6d7wWTdRNLyyDHUSkTJjUfA+6ZmeEXJjCcY",
"1Uy5AelHPdPvU229srMpEGk08N2HaZsqBpst6oB96KXfyHWcxACci6AQvrvBu5wE",
"wefJuMZgWC9RuYZ/JwgWzQIs9a6215lplRMUAlQF6e0+dLzwXchW",
"=S56e",
"-----END PGP PRIVATE KEY BLOCK-----",
].join("\n"),
},
{
keyID: "02da58ca894c4cc7",
name: "CyberChef pw 1024 <toby@toby.codes>",
size: 1024,
password: "2NSRJYTzgsTVJfih",
pub: [
"-----BEGIN PGP PUBLIC KEY BLOCK-----",
"",
"mI0EWL7mswEEAMcw0PSzmNfh4MkGwejsyreXb34FqEjYMc1GmswvC5uuLp0KzbC6",
"HecV1GyyPQ7kKshWVLloShN3KtgSZF7DJ8/Hioiv4Q5HJYPY4AYwqECi+/C4W1FA",
"tJEbItdEIxw0IgHOX64X5kMptVV9J5bGc7DqkqUHgapXJI+yLZel0s83ABEBAAG0",
"I0N5YmVyQ2hlZiBwdyAxMDI0IDx0b2J5QHRvYnkuY29kZXM+iLcEEwEIACEFAli+",
"5rMCGwMFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQAtpYyolMTMeOGwP+NvLU",
"GHhHaIFwI+VMB655CiD6QuRWnurcrXq7qZYl3flyBehhZdtgGBx9vynffElEFEFz",
"cbqzv8unkDTRdPqTA0gM2wOaC/L6Kuy4ErjQD7A4i5rC/IG0ja+3DQeKLShGGtaD",
"bG0H0mJl7gzlqR3/fxgLxi/JaCtqapjtZDF/GTC4jQRYvuazAQQA5oNC4NeWKBKU",
"m9H/QZyxKRWGaaQRKLrmSGVkQgJlzo3pnNjJMFUaMcQaJve+PZGay7y9sCOFpumf",
"6v1ERY+qw4ZOyCRnRqHJOxdLrbTPSmOwIUYkYFkNzARGpdy/FqWCByXDXea5qsb1",
"DJRT9WUte3Bbx1YvzsqrZMqsExgwgdcAEQEAAYifBBgBCAAJBQJYvuazAhsMAAoJ",
"EALaWMqJTEzH7woEAKIKQS8bEf8iHaVf7aGEWWOShN10gb+xpWD4V5r8H6hlNpIk",
"xwQEbj8glTJBEJoD5xO1tdrHmOJ7BVO1d7otdgXpjBAOxn0ngW4MAB8BO+Qa5U/t",
"M+6yuL8REwE5YUnvIyhgvhiHsBhlLeMNXtwCrF94WyDzyb+hwVwwi/PFtI0y",
"=djdC",
"-----END PGP PUBLIC KEY BLOCK-----",
].join("\n"),
sec: [
"-----BEGIN PGP PRIVATE KEY BLOCK-----",
"",
"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",
"=j2j0",
"-----END PGP PRIVATE KEY BLOCK-----",
].join("\n"),
},
];
PGP_TEST_KEY_PAIRS.forEach(function(keyPair) {
if (keyPair.password) {
TestRegister.addTests(
["", "nottherightpassword"].map(function(incorrectPW) {
var testName = "PGP Encrypt, PGP Decrypt: ensure error for incorrect password (pw [$pw], $ks, $name)";
testName = testName.replace("$ks", keyPair.size);
testName = testName.replace("$pw", incorrectPW);
return {
name: testName,
input: "hello world",
expectedError: true,
recipeConfig: [
{
op: "PGP Encrypt",
args: [keyPair.pub],
},
{
op: "PGP Decrypt",
args: [keyPair.sec, incorrectPW],
},
],
};
})
);
}
});
["", "hello world"].forEach(function(input) {
TestRegister.addTests(
PGP_TEST_KEY_PAIRS.map(function(keyPair) {
var testName = "PGP Encrypt, PGP Decrypt ($pw, $ks) '$input'";
testName = testName.replace("$ks", keyPair.size);
testName = testName.replace("$pw", keyPair.password ? "pw" : "no pw");
testName = testName.replace("$input", input);
return {
name: testName,
input: input,
expectedOutput: input,
recipeConfig: [
{
op: "PGP Encrypt",
args: [keyPair.pub],
},
{
op: "PGP Decrypt",
args: [keyPair.sec, keyPair.password],
},
],
};
})
);
});
TestRegister.addTests([{
name: "PGP Encrypt, PGP Decrypt: fails when incorrect password, empty string (1024)",
input: "",
expectedError: true,
recipeConfig: [
{
op: "PGP Encrypt",
args: [PGP_TEST_KEY_PAIRS[1].pub],
},
{
op: "PGP Decrypt",
args: [PGP_TEST_KEY_PAIRS[1].sec, "gibberish"],
},
],
}]);
TestRegister.addTests([{
name: "PGP Encrypt, PGP Decrypt: fails when incorrect password, hello world (1024)",
input: "hello world",
expectedError: true,
recipeConfig: [
{
op: "PGP Encrypt",
args: [PGP_TEST_KEY_PAIRS[1].pub],
},
{
op: "PGP Decrypt",
args: [PGP_TEST_KEY_PAIRS[1].sec, "gibberish"],
},
],
}]);
["hello world"].forEach(function(input) {
[
[PGP_TEST_KEY_PAIRS[0], PGP_TEST_KEY_PAIRS[1]],
[PGP_TEST_KEY_PAIRS[1], PGP_TEST_KEY_PAIRS[0]],
].forEach(function(pairOfKeyPairs) {
var alice = pairOfKeyPairs[0];
var bob = pairOfKeyPairs[1];
var testName = "PGP Sign ($alice), PGP Verify ($bob) '$input'";
testName = testName.replace("$alice", alice.name);
testName = testName.replace("$bob", bob.name);
testName = testName.replace("$input", input);
TestRegister.addTests([{
name: testName,
input: input,
expectedOutput: [
"Verified: true",
"Key ID: " + alice.keyID,
"Encrypted for: " + bob.name,
"Signed by: " + alice.name,
"Signed with: rsa_encrypt_sign/aes256",
"\n",
input,
].join("\n"),
recipeConfig: [
{
op: "PGP Sign",
args: [bob.pub, alice.sec, alice.password],
},
{
op: "PGP Verify",
args: [alice.pub, bob.sec, bob.password],
},
],
}]);
});
});
["", "hello world"].forEach(function(input) {
TestRegister.addTests(
PGP_TEST_KEY_PAIRS.map(function(keyPair) {
var testName = "Sign PGP Cleartext, Verify PGP Cleartext ($pw, $ks) '$input'";
testName = testName.replace("$ks", keyPair.size);
testName = testName.replace("$pw", keyPair.password ? "pw" : "no pw");
testName = testName.replace("$input", input);
return {
name: testName,
input: input,
expectedOutput: [
"Verified: true",
"Key ID: " + keyPair.keyID,
"Signed by: " + keyPair.name,
"Signed with: rsa_encrypt_sign",
"\n",
input,
].join("\n"),
recipeConfig: [
{
op: "Sign PGP Cleartext",
args: [keyPair.sec, keyPair.password],
},
{
op: "Verify PGP Cleartext",
args: [keyPair.pub],
},
{
op: "Find / Replace",
args: [
{option: "Regex", string: "Signed on: .*\r?\n"},
"",
true,
false,
false,
],
},
],
};
})
);
});
TestRegister.addTests(CYBERCHEF_GENERATED_KEY_PAIRS.map(function(keyPair) {
var testName = "Remove PGP ASCII Armour, Add PGP ASCII Armour: Public Key '$name'";
testName = testName.replace("$name", keyPair.name);
return {
name: testName,
input: keyPair.pub,
expectedOutput: keyPair.pub,
ignoreWhitespace: true,
recipeConfig: [
{
op: "Remove PGP ASCII Armour",
args: [],
},
{
op: "Add PGP ASCII Armour",
args: ["Public key"],
},
],
};
}));
TestRegister.addTests(CYBERCHEF_GENERATED_KEY_PAIRS.map(function(keyPair) {
var testName = "Remove PGP ASCII Armour, Add PGP ASCII Armour: Private Key '$name'";
testName = testName.replace("$name", keyPair.name);
return {
name: testName,
input: keyPair.sec,
expectedOutput: keyPair.sec,
ignoreWhitespace: true,
recipeConfig: [
{
op: "Remove PGP ASCII Armour",
args: [],
},
{
op: "Add PGP ASCII Armour",
args: ["Private key"],
},
],
};
}));
PGP_TEST_KEY_PAIRS.forEach(function(keyPair) {
TestRegister.addTests(
["", "hello world"].map(function(message, messageIndex) {
var testName = "PGP Encrypt, Remove PGP ASCII Armour, Add PGP ASCII Armour, PGP Decrypt: Message $message '$name'";
testName = testName.replace("$message", messageIndex);
testName = testName.replace("$name", keyPair.name);
return {
name: testName,
input: message,
expectedOutput: message,
ignoreWhitespace: true,
recipeConfig: [
{
op: "PGP Encrypt",
args: [keyPair.pub],
},
{
op: "Remove PGP ASCII Armour",
args: [],
},
{
op: "To Hex",
args: ["None"],
},
{
op: "From Hex",
args: ["None"],
},
{
op: "Add PGP ASCII Armour",
args: ["Message"],
},
{
op: "PGP Decrypt",
args: [keyPair.sec, keyPair.password],
},
],
};
})
);
});