Implement PGP encrypt and PGP decrypt operations

This commit is contained in:
toby 2017-03-07 12:40:28 -05:00
parent 7f0ce0da8d
commit 67f94df060
7 changed files with 24726 additions and 30 deletions

View file

@ -92,6 +92,8 @@ var Categories = [
"Substitute",
"Derive PBKDF2 key",
"Derive EVP key",
"PGP Encrypt",
"PGP Decrypt",
]
},
{

View file

@ -3148,4 +3148,35 @@ var OperationConfig = {
}
]
},
"PGP Encrypt": {
description: "Input: An ASCII-Armored PGP public key.<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/",
run: PGP.runEncrypt,
inputType: "string",
outputType: "string",
args: [
{
name: "Public key",
type: "text",
value: "",
},
]
},
"PGP Decrypt": {
description: "Input: An ASCII-Armored PGP private key (and optionally, the password needed to decrypt the private key).<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/",
run: PGP.runDecrypt,
inputType: "string",
outputType: "string",
args: [
{
name: "Private key",
type: "text",
value: "",
},
{
name: "Private key password",
type: "text",
value: "",
},
]
},
};

24051
src/js/lib/openpgp.js Normal file

File diff suppressed because it is too large Load diff

93
src/js/operations/PGP.js Executable file
View file

@ -0,0 +1,93 @@
/* globals openpgp */
/**
* PGP operations.
*
* @author tlwr [toby@toby.codes]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*
* @namespace
*/
var PGP = {
/**
* Encrypts the input using PGP.
*
* @param {string} input - plaintext to encrypt
* @param {function} args
* @returns {string}
*/
runEncrypt: function (plaintext, args) {
var publicKey = args[0];
return new Promise(function(resolve, reject) {
try {
var options = {
data: plaintext,
publicKeys: openpgp.key.readArmored(publicKey).keys,
};
} catch (error) {
reject("Failed to read public key", error);
}
// Timeout is so that UI can update before openpgp blocks thread
openpgp.encrypt(options)
.then(function(ciphertext) {
console.log(ciphertext);
resolve(ciphertext.data);
})
.catch(function(error) {
reject("Failed to encrypt input", error);
});
});
},
/**
* Decrypts the input using PGP.
*
* @param {string} input - ciphertext to decrypt
* @param {function} args
* @returns {string}
*/
runDecrypt: function (input, args) {
var privateKey = args[0],
password = args[1];
return new Promise(function(resolve, reject) {
try {
privateKey = openpgp.key.readArmored(privateKey).keys[0];
} catch (error) {
reject("Failed to read private key", error);
}
try {
if (password && password.length) {
privateKey.decrypt(password);
}
} catch (error) {
reject("Failed to decrypt private key", error);
}
try {
var options = {
message: openpgp.message.readArmored(input),
privateKey: privateKey,
};
} catch (error) {
reject("Failed to read input message", error);
}
openpgp.decrypt(options)
.then(function(plaintext) {
resolve(plaintext.data);
})
.catch(function(error) {
reject("Failed to encrypt input", error);
});
});
},
};

View file

@ -106,41 +106,45 @@ HTMLApp.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);