PGPDecryptAndVerify.mjs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /**
  2. * @author tlwr [toby@toby.codes]
  3. * @copyright Crown Copyright 2017
  4. * @license Apache-2.0
  5. */
  6. import Operation from "../Operation";
  7. import kbpgp from "kbpgp";
  8. import { ASP, importPrivateKey, importPublicKey } from "../lib/PGP";
  9. import OperationError from "../errors/OperationError";
  10. import promisifyDefault from "es6-promisify";
  11. const promisify = promisifyDefault.promisify;
  12. /**
  13. * PGP Decrypt and Verify operation
  14. */
  15. class PGPDecryptAndVerify extends Operation {
  16. /**
  17. * PGPDecryptAndVerify constructor
  18. */
  19. constructor() {
  20. super();
  21. this.name = "PGP Decrypt and Verify";
  22. this.module = "PGP";
  23. this.description = [
  24. "Input: the ASCII-armoured encrypted PGP message you want to verify.",
  25. "<br><br>",
  26. "Arguments: the ASCII-armoured PGP public key of the signer, ",
  27. "the ASCII-armoured private key of the recipient (and the private key password if necessary).",
  28. "<br><br>",
  29. "This operation uses PGP to decrypt and verify an encrypted digital signature.",
  30. "<br><br>",
  31. "Pretty Good Privacy is an encryption standard (OpenPGP) used for encrypting, decrypting, and signing messages.",
  32. "<br><br>",
  33. "This function uses the Keybase implementation of PGP.",
  34. ].join("\n");
  35. this.inputType = "string";
  36. this.outputType = "string";
  37. this.args = [
  38. {
  39. "name": "Public key of signer",
  40. "type": "text",
  41. "value": ""
  42. },
  43. {
  44. "name": "Private key of recipient",
  45. "type": "text",
  46. "value": ""
  47. },
  48. {
  49. "name": "Private key password",
  50. "type": "string",
  51. "value": ""
  52. }
  53. ];
  54. }
  55. /**
  56. * @param {string} input
  57. * @param {Object[]} args
  58. * @returns {string}
  59. */
  60. async run(input, args) {
  61. const signedMessage = input,
  62. [publicKey, privateKey, passphrase] = args,
  63. keyring = new kbpgp.keyring.KeyRing();
  64. let unboxedLiterals;
  65. if (!publicKey) throw new OperationError("Enter the public key of the signer.");
  66. if (!privateKey) throw new OperationError("Enter the private key of the recipient.");
  67. const privKey = await importPrivateKey(privateKey, passphrase);
  68. const pubKey = await importPublicKey(publicKey);
  69. keyring.add_key_manager(privKey);
  70. keyring.add_key_manager(pubKey);
  71. try {
  72. unboxedLiterals = await promisify(kbpgp.unbox)({
  73. armored: signedMessage,
  74. keyfetch: keyring,
  75. asp: ASP
  76. });
  77. const ds = unboxedLiterals[0].get_data_signer();
  78. if (ds) {
  79. const km = ds.get_key_manager();
  80. if (km) {
  81. const signer = km.get_userids_mark_primary()[0].components;
  82. let text = "Signed by ";
  83. if (signer.email || signer.username || signer.comment) {
  84. if (signer.username) {
  85. text += `${signer.username} `;
  86. }
  87. if (signer.comment) {
  88. text += `${signer.comment} `;
  89. }
  90. if (signer.email) {
  91. text += `<${signer.email}>`;
  92. }
  93. text += "\n";
  94. }
  95. text += [
  96. `PGP fingerprint: ${km.get_pgp_fingerprint().toString("hex")}`,
  97. `Signed on ${new Date(ds.sig.hashed_subpackets[0].time * 1000).toUTCString()}`,
  98. "----------------------------------\n"
  99. ].join("\n");
  100. text += unboxedLiterals.toString();
  101. return text.trim();
  102. } else {
  103. throw new OperationError("Could not identify a key manager.");
  104. }
  105. } else {
  106. throw new OperationError("The data does not appear to be signed.");
  107. }
  108. } catch (err) {
  109. throw new OperationError(`Couldn't verify message: ${err}`);
  110. }
  111. }
  112. }
  113. export default PGPDecryptAndVerify;