diff --git a/src/js/config/OperationConfig.js b/src/js/config/OperationConfig.js index 08cd9da3..013d016f 100755 --- a/src/js/config/OperationConfig.js +++ b/src/js/config/OperationConfig.js @@ -3179,4 +3179,140 @@ var OperationConfig = { }, ] }, + "PGP Sign": { + description: "Input: An ASCII-Armored PGP private key (and optionally, the password needed to decrypt the private key); the public key of the recipient.

This operation uses PGP to produce an encrypted digital signature.

Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.

This function relies on OpenPGP.js for the implementation of PGP.

See more at https://openpgpjs.org/", + 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: An ASCII-Armored PGP public key.

This operation uses PGP to decrypt and verify an encrypted digital signature.

Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.

This function relies on OpenPGP.js for the implementation of PGP.

See more at https://openpgpjs.org/", + 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: "", + }, + { + name: "Display message in output", + type: "boolean", + value: true, + } + ] + }, + "PGP Sign Cleartext": { + description: "Input: An ASCII-Armored PGP private key (and optionally, the password needed to decrypt the private key).

This operation uses PGP to produce a digital signature.

Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.

This function relies on OpenPGP.js for the implementation of PGP.

See more at https://openpgpjs.org/", + run: PGP.runSignCleartext, + inputType: "string", + outputType: "string", + args: [ + { + name: "Private key", + type: "text", + value: "", + }, + { + name: "Private key password", + type: "string", + value: "", + }, + ] + }, + "PGP Verify Cleartext": { + description: "Input: An ASCII-Armored PGP public key.

This operation uses PGP to verify a cleartext digital signature.

Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.

This function relies on OpenPGP.js for the implementation of PGP.

See more at https://openpgpjs.org/", + run: PGP.runVerifyCleartext, + inputType: "string", + outputType: "string", + args: [ + { + name: "Public key", + type: "text", + value: "", + }, + { + name: "Display message in output", + type: "boolean", + value: true, + } + ] + }, + "PGP Generate Key Pair": { + description: "Input is ignored.

This operation generates a PGP key pair.

Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.

This function relies on OpenPGP.js for the implementation of PGP.

See more at https://openpgpjs.org/", + 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: "", + }, + ] + }, + "PGP Add ASCII Armor": { + description: "", + run: PGP.runAddArmor, + inputType: "byteArray", + outputType: "string", + args: [ + { + name: "Armor type", + type: "option", + value: PGP.ARMOR_TYPES, + }, + ], + }, + "PGP Remove ASCII Armor": { + description: "", + run: PGP.runRemoveArmor, + inputType: "string", + outputType: "byteArray", + args: [ + ], + }, }; diff --git a/src/js/operations/PGP.js b/src/js/operations/PGP.js index edfebf5b..fabadcd7 100755 --- a/src/js/operations/PGP.js +++ b/src/js/operations/PGP.js @@ -10,6 +10,26 @@ * @namespace */ var PGP = { + /** + * @constant + * @default + */ + ARMOR_TYPES: [ + "Message", + "Public key", + "Private key", + ], + + + /** + * @constant + * @default + */ + ARMOR_TYPE_MAPPING: { + "Message": 3, + "Public key": 4, + "Private key": 5, + }, /** @@ -24,20 +44,22 @@ var PGP = { 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); + var publicKeys = openpgp.key.readArmored(publicKey).keys; + } catch (err) { + return reject("Cannot read public key: " + err); } + var options = { + data: plaintext, + publicKeys: publicKeys, + }; + openpgp.encrypt(options) .then(function(ciphertext) { resolve(ciphertext.data); }) - .catch(function(error) { - reject("Failed to encrypt input", error); + .catch(function(err) { + reject("Could not encrypt text: " + err); }); }); }, @@ -54,38 +76,336 @@ var PGP = { 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); + } catch (err) { + return reject("Cannot read private key: " + err); } try { - if (password && password.length) { + var message = openpgp.message.readArmored(input); + } catch (err) { + return reject("Cannot read message: " + err); + } + + var options = { + message: message, + privateKey: privateKey, + }; + + try { + if (password) { 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); + } catch (err) { + return reject("Cannot decrypt password: " + err); } openpgp.decrypt(options) .then(function(plaintext) { resolve(plaintext.data); }) - .catch(function(error) { - reject("Failed to encrypt input", error); + .catch(function(err) { + reject("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) { + var publicKey = args[0], + privateKey = args[1], + password = args[2]; + + return new Promise(function(resolve, reject) { + try { + var publicKeys = openpgp.key.readArmored(publicKey).keys; + } catch (err) { + return reject("Could not read public key: " + err); + } + + try { + var privateKeys = openpgp.key.readArmored(privateKey).keys; + } catch (err) { + return reject("Could not read private key: " + err); + } + + try { + if (password) { + privateKeys[0].decrypt(password); + } + } catch (err) { + return reject("Cannot decrypt password: " + err); + } + + var options = { + data: input, + publicKeys: publicKeys, + privateKeys: privateKeys, + }; + + openpgp.encrypt(options) + .then(function(signedData) { + resolve(signedData.data); + }) + .catch(function(err) { + reject("Could not sign input: " + err); + }); + }); + }, + + + /** + * Verifies the signed input using PGP. + * + * @param {string} input - signed input to verify + * @param {Object[]} args + * @returns {string} - "true" or "false" depending on the validity of the signature + */ + runVerify: function (input, args) { + var publicKey = args[0], + privateKey = args[1], + password = args[2], + displayDecrypt = args[3]; + + return new Promise(function(resolve, reject) { + try { + var publicKeys = openpgp.key.readArmored(publicKey).keys; + } catch (err) { + return reject("Could not read public key: " + err); + } + + try { + var privateKeys = openpgp.key.readArmored(privateKey).keys; + } catch (err) { + return reject("Could not read private key: " + err); + } + + try { + if (password) { + privateKeys[0].decrypt(password); + } + } catch (err) { + return reject("Cannot decrypt password: " + err); + } + + try { + var message = openpgp.message.readArmored(input); + } catch (err) { + return reject("Could not read encrypted message: " + err); + } + + var verification = { + verified: false, + author: publicKeys[0].users[0].userId.userid, + recipient: privateKeys[0].users[0].userId.userid, + date: "", + keyID: "", + message: "", + }; + + openpgp.decrypt({ + message: message, + publicKeys: publicKeys, + privateKey: privateKeys[0], + }) + .then(function(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(); + } + + resolve([ + "Verified: " + verification.verified, + "Key ID: " + verification.keyID, + "Encrypted for: " + verification.recipient, + "Signed on: " + verification.date, + "Signed by: " + verification.author, + "Signed with: ", + "\n", + displayDecrypt ? decrypted.data : "", + ].join("\n")); + + }) + .catch(function(err) { + reject("Could not decrypt and verify message: " + err); + }); + }); + }, + + + /** + * Clearsigns the input using PGP. + * + * @param {string} input - data to be signed + * @param {Object[]} args + * @returns {string} + */ + runSignCleartext: function (input, args) { + var privateKey = args[0], + password = args[1]; + + + return new Promise(function(resolve, reject) { + var privateKeys = openpgp.key.readArmored(privateKey).keys; + + try { + if (password) { + privateKeys[0].decrypt(password); + } + } catch (err) { + return reject("Cannot decrypt password: " + err); + } + + var options = { + data: input, + privateKeys: privateKeys, + }; + + openpgp.sign(options) + .then(function(signedData) { + resolve(signedData.data); + }) + .catch(function(err) { + reject("Could not clearsign input: " + err); + }); + }); + }, + + + /** + * Verifies the clearsigned input using PGP. + * + * @param {string} input - signed input to verify + * @param {Object[]} args + * @returns {string} - "true" or "false" depending on the validity of the signature + */ + runVerifyCleartext: function (input, args) { + var publicKey = args[0], + displayDecrypt = args[1]; + + return new Promise(function(resolve, reject) { + + try { + var publicKeys = openpgp.key.readArmored(publicKey).keys; + } catch (err) { + return reject("Could not read public key: " + err); + } + + try { + var message = openpgp.cleartext.readArmored(input); + } catch (err) { + return reject("Could not read input message: " + err); + } + + var verification = { + verified: false, + author: publicKeys[0].users[0].userId.userid, + date: "", + keyID: "", + message: message.text, + }; + + openpgp.verify({ + message: message, + publicKeys: publicKeys, + }) + .then(function(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(); + } + + resolve([ + "Verified: " + verification.verified, + "Key ID: " + verification.keyID, + "Signed on: " + verification.date, + "Signed by: " + verification.author, + "Signed with: ", + "\n", + displayDecrypt ? verification.message : "", + ].join("\n")); + }) + .catch(function(err) { + reject("Could not verify message: " + err); + }); + }); + }, + + + /** + * Generates a PGP key pair. + * + * @param {string} input is ignored + * @param {Object[]} args + * @returns {string} - armored public key and private key separated by whitespace. + */ + runGenKeyPair: function (input, args) { + var password = args[0], + keySize = parseInt(args[1], 10), + name = args[2], + email = args[3]; + + return new Promise(function(resolve, reject) { + var options = { + numBits: keySize, + userIds: [{name: name, email: email}], + }; + + if (password) { + options.password = password; + } + + openpgp.generateKey(options) + .then(function(key) { + var output = [ + key.publicKeyArmored, + key.privateKeyArmored, + ].join(""); // Preceding and trailing newlines are already generated. + resolve(output); + }) + .catch(function(err) { + reject("Could not generate key pair: " + err); + }); + }); + }, + + + /** + * Turns raw PGP bytes into an ASCII armored string. + * + * @param {byteArray} input + * @param {Object[]} args + * @returns {string} - armored public key and private key separated by whitespace. + */ + runAddArmor: function (input, args) { + var armorType = PGP.ARMOR_TYPE_MAPPING[args[0]]; + return openpgp.armor.encode(armorType, input); + }, + + + /** + * Turns an ASCII armored string into raw PGP bytes. + * + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} - armored public key and private key separated by whitespace. + */ + runRemoveArmor: function (input, args) { + var decoded = openpgp.armor.decode(input); + var uint8bytes = decoded.data; + var bytes = Array.prototype.slice.call(uint8bytes); + return bytes; + }, +}; \ No newline at end of file diff --git a/test/tests/operations/PGP.js b/test/tests/operations/PGP.js index d7318e64..8428e4df 100644 --- a/test/tests/operations/PGP.js +++ b/test/tests/operations/PGP.js @@ -6,9 +6,92 @@ * @copyright Crown Copyright 2017 * @license Apache-2.0 */ +var 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"), + messages: [ + [ + "-----BEGIN PGP MESSAGE-----", + "Version: OpenPGP.js v2.3.6", + "Comment: http://openpgpjs.org", + "", + "wYwDmsTgRYVqFPcBA/kBfc7BnEcbKGwac/JOSK6YWzpDERR8NjJT/3R7JDsG", + "ywJB/ouaHy3e5KGDulALV6pUzcPbCC0CCl5tlFVaFYAj6+BdwR/WCb7dhlRE", + "x+vw5VKLlY6adSgtvU9aLF0nL0YlU9Pxf9wrPdo3bvxJij7S4mbGS2iybhQO", + "41ZUtWhOotI9AR/e7f2WHSt8dpl7T9Uq8trAptFWVIZkj+78Gp/8u5o8/mqV", + "9gxmOGsViKhVZ1b554nwd243IrqlzW2szg==", + "=prpZ", + "-----END PGP MESSAGE-----", + ].join("\n"), + ], + }, +]; var PGP_TEST_KEY_PAIRS = [ { + keyID: "a9510d8fd7e352f5", + name: "CyberChef nopw 1024 ", size: 1024, pub: [ "-----BEGIN PGP PUBLIC KEY BLOCK-----", @@ -66,6 +149,8 @@ var PGP_TEST_KEY_PAIRS = [ ].join("\n"), }, { + keyID: "02da58ca894c4cc7", + name: "CyberChef pw 1024 ", size: 1024, password: "2NSRJYTzgsTVJfih", pub: [ @@ -481,7 +566,7 @@ var PGP_TEST_KEY_PAIRS = [ ); }); -TestRegister.addTests({ +TestRegister.addTests([{ name: "PGP encrypt, PGP Decrypt: fails when incorrect password, empty string (1024)", input: "", expectedError: true, @@ -495,9 +580,9 @@ TestRegister.addTests({ args: [PGP_TEST_KEY_PAIRS[1].sec, "gibberish"], }, ], -}); +}]); -TestRegister.addTests({ +TestRegister.addTests([{ name: "PGP encrypt, PGP Decrypt: fails when incorrect password, hello world (1024)", input: "hello world", expectedError: true, @@ -511,4 +596,223 @@ TestRegister.addTests({ 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 on: ", + "Signed by: " + alice.name, + "Signed with: ", + "\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, true], + }, + ], + }]); + }); }); + +["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' (message hidden)"; + 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 on: ", + "Signed by: " + alice.name, + "Signed with: ", + "\n", + "", + ].join("\n"), + recipeConfig: [ + { + op: "PGP Sign", + args: [bob.pub, alice.sec, alice.password], + }, + { + op: "PGP Verify", + args: [alice.pub, bob.sec, bob.password, false], + }, + ], + }]); + }); +}); + +["", "hello world"].forEach(function(input) { + TestRegister.addTests( + PGP_TEST_KEY_PAIRS.map(function(keyPair) { + var testName = "PGP Sign Cleartext, PGP Verify 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 on: ", + "Signed by: " + keyPair.name, + "Signed with: ", + "\n", + input, + ].join("\n"), + recipeConfig: [ + { + op: "PGP Sign Cleartext", + args: [keyPair.sec, keyPair.password], + }, + { + op: "PGP Verify Cleartext", + args: [keyPair.pub, true], + }, + ], + }; + }) + ); +}); + +["", "hello world"].forEach(function(input) { + TestRegister.addTests( + PGP_TEST_KEY_PAIRS.map(function(keyPair) { + var testName = "PGP Sign Cleartext, PGP Verify Cleartext ($pw, $ks) '$input' (message hidden)"; + 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 on: ", + "Signed by: " + keyPair.name, + "Signed with: ", + "\n", + "", + ].join("\n"), + recipeConfig: [ + { + op: "PGP Sign Cleartext", + args: [keyPair.sec, keyPair.password], + }, + { + op: "PGP Verify Cleartext", + args: [keyPair.pub, false], + }, + ], + }; + }) + ); +}); + +TestRegister.addTests(CYBERCHEF_GENERATED_KEY_PAIRS.map(function(keyPair) { + var testName = "PGP Remove ASCII Armor, PGP Add ASCII Armor: Public Key '$name'"; + testName = testName.replace("$name", keyPair.name); + + return { + name: testName, + input: keyPair.pub, + expectedOutput: keyPair.pub, + ignoreWhitespace: true, + recipeConfig: [ + { + op: "PGP Remove ASCII Armor", + args: [], + }, + { + op: "PGP Add ASCII Armor", + args: ["Public key"], + }, + ], + } +})); + +TestRegister.addTests(CYBERCHEF_GENERATED_KEY_PAIRS.map(function(keyPair) { + var testName = "PGP Remove ASCII Armor, PGP Add ASCII Armor: Private Key '$name'"; + testName = testName.replace("$name", keyPair.name); + + return { + name: testName, + input: keyPair.sec, + expectedOutput: keyPair.sec, + ignoreWhitespace: true, + recipeConfig: [ + { + op: "PGP Remove ASCII Armor", + args: [], + }, + { + op: "PGP Add ASCII Armor", + args: ["Private key"], + }, + ], + } +})); + +CYBERCHEF_GENERATED_KEY_PAIRS.forEach(function(keyPair) { + TestRegister.addTests(keyPair.messages.map(function(encryptedMessage, messageIndex) { + var testName = "PGP Remove ASCII Armor, PGP Add ASCII Armor: Message $message '$name'"; + testName = testName.replace("$message", messageIndex); + testName = testName.replace("$name", keyPair.name); + + return { + name: testName, + input: encryptedMessage, + expectedOutput: encryptedMessage, + ignoreWhitespace: true, + recipeConfig: [ + { + op: "PGP Remove ASCII Armor", + args: [], + }, + { + op: "PGP Add ASCII Armor", + args: ["Message"], + }, + ], + }; + })); +}); \ No newline at end of file