Merge branch 'tlwr-feature-add-pgp-kbpgp'

This commit is contained in:
n1474335 2018-03-28 23:27:01 +01:00
commit e6e2b169dc
9 changed files with 681 additions and 16 deletions

View file

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

View file

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

155
package-lock.json generated
View file

@ -1197,6 +1197,11 @@
"integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=", "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=",
"dev": true "dev": true
}, },
"bn": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/bn/-/bn-1.0.1.tgz",
"integrity": "sha1-oVOCXmsessLbdyYUmwR6B84KO7M="
},
"bn.js": { "bn.js": {
"version": "4.11.8", "version": "4.11.8",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
@ -1499,6 +1504,11 @@
"integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=",
"dev": true "dev": true
}, },
"bzip-deflate": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/bzip-deflate/-/bzip-deflate-1.0.0.tgz",
"integrity": "sha1-sC2wB+83vrzCk4Skssb08PTHlsk="
},
"cacache": { "cacache": {
"version": "10.0.4", "version": "10.0.4",
"resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
@ -2525,8 +2535,7 @@
"deep-equal": { "deep-equal": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
"dev": true
}, },
"deep-extend": { "deep-extend": {
"version": "0.4.2", "version": "0.4.2",
@ -2915,16 +2924,23 @@
} }
}, },
"es6-promise": { "es6-promise": {
"version": "4.2.4", "version": "4.0.5",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.0.5.tgz",
"integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", "integrity": "sha1-eILzCt3lskDM+n99eMVIMwlRrkI="
"dev": true
}, },
"es6-promise-polyfill": { "es6-promise-polyfill": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/es6-promise-polyfill/-/es6-promise-polyfill-1.2.0.tgz", "resolved": "https://registry.npmjs.org/es6-promise-polyfill/-/es6-promise-polyfill-1.2.0.tgz",
"integrity": "sha1-84kl8jyz4+jObNqP93T867sJDN4=" "integrity": "sha1-84kl8jyz4+jObNqP93T867sJDN4="
}, },
"es6-promisify": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
"integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
"requires": {
"es6-promise": "4.0.5"
}
},
"escape-html": { "escape-html": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@ -3957,7 +3973,7 @@
"dev": true, "dev": true,
"requires": { "requires": {
"commondir": "1.0.1", "commondir": "1.0.1",
"make-dir": "1.2.0", "make-dir": "1.1.0",
"pkg-dir": "2.0.0" "pkg-dir": "2.0.0"
} }
}, },
@ -6081,6 +6097,24 @@
"integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
"dev": true "dev": true
}, },
"iced-error": {
"version": "0.0.12",
"resolved": "https://registry.npmjs.org/iced-error/-/iced-error-0.0.12.tgz",
"integrity": "sha1-4KhhRigXzwzpdLE/ymEtOg1dEL4="
},
"iced-lock": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/iced-lock/-/iced-lock-1.1.0.tgz",
"integrity": "sha1-YRbvHKs6zW5rEIk7snumIv0/3nI=",
"requires": {
"iced-runtime": "1.0.3"
}
},
"iced-runtime": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/iced-runtime/-/iced-runtime-1.0.3.tgz",
"integrity": "sha1-LU9PuZmreqVDCxk8d6f85BGDGc4="
},
"iconv-lite": { "iconv-lite": {
"version": "0.4.19", "version": "0.4.19",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
@ -7030,12 +7064,69 @@
"resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-8.0.6.tgz", "resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-8.0.6.tgz",
"integrity": "sha1-RYbwCCPjAuWZokSke+IMYardD88=" "integrity": "sha1-RYbwCCPjAuWZokSke+IMYardD88="
}, },
"kbpgp": {
"version": "2.0.76",
"resolved": "https://registry.npmjs.org/kbpgp/-/kbpgp-2.0.76.tgz",
"integrity": "sha1-qKtufM8279812BNdfJb/bpSLMAI=",
"requires": {
"bn": "1.0.1",
"bzip-deflate": "1.0.0",
"deep-equal": "1.0.1",
"iced-error": "0.0.12",
"iced-lock": "1.1.0",
"iced-runtime": "1.0.3",
"keybase-ecurve": "1.0.0",
"keybase-nacl": "1.0.10",
"minimist": "1.2.0",
"pgp-utils": "0.0.34",
"purepack": "1.0.4",
"triplesec": "3.0.26",
"tweetnacl": "0.13.3"
},
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
},
"tweetnacl": {
"version": "0.13.3",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.13.3.tgz",
"integrity": "sha1-1ii1bzvMPVrnS6nUwacE3vWrS1Y="
}
}
},
"kew": { "kew": {
"version": "0.7.0", "version": "0.7.0",
"resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz",
"integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=",
"dev": true "dev": true
}, },
"keybase-ecurve": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/keybase-ecurve/-/keybase-ecurve-1.0.0.tgz",
"integrity": "sha1-xrxyrdpGA/0xhP7n6ZaU7Y/WmtI=",
"requires": {
"bn": "1.0.1"
}
},
"keybase-nacl": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/keybase-nacl/-/keybase-nacl-1.0.10.tgz",
"integrity": "sha1-OGWDHpSBUWSI33y9mJRn6VDYeos=",
"requires": {
"iced-runtime": "1.0.3",
"tweetnacl": "0.13.3",
"uint64be": "1.0.1"
},
"dependencies": {
"tweetnacl": {
"version": "0.13.3",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.13.3.tgz",
"integrity": "sha1-1ii1bzvMPVrnS6nUwacE3vWrS1Y="
}
}
},
"killable": { "killable": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz",
@ -7523,9 +7614,9 @@
"dev": true "dev": true
}, },
"make-dir": { "make-dir": {
"version": "1.2.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz",
"integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==",
"dev": true, "dev": true,
"requires": { "requires": {
"pify": "3.0.0" "pify": "3.0.0"
@ -7853,6 +7944,14 @@
"moment": "2.20.1" "moment": "2.20.1"
} }
}, },
"more-entropy": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/more-entropy/-/more-entropy-0.0.7.tgz",
"integrity": "sha1-Z7/G96hvJvvDeqyD/UbYjGHRCbU=",
"requires": {
"iced-runtime": "1.0.3"
}
},
"move-concurrently": { "move-concurrently": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@ -8605,13 +8704,22 @@
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
"dev": true "dev": true
}, },
"pgp-utils": {
"version": "0.0.34",
"resolved": "https://registry.npmjs.org/pgp-utils/-/pgp-utils-0.0.34.tgz",
"integrity": "sha1-2E9J98GTteC5QV9cxcKmle15DCM=",
"requires": {
"iced-error": "0.0.12",
"iced-runtime": "1.0.3"
}
},
"phantomjs-prebuilt": { "phantomjs-prebuilt": {
"version": "2.1.16", "version": "2.1.16",
"resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz",
"integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=",
"dev": true, "dev": true,
"requires": { "requires": {
"es6-promise": "4.2.4", "es6-promise": "4.0.5",
"extract-zip": "1.6.6", "extract-zip": "1.6.6",
"fs-extra": "1.0.0", "fs-extra": "1.0.0",
"hasha": "2.2.0", "hasha": "2.2.0",
@ -9601,8 +9709,7 @@
"progress": { "progress": {
"version": "1.1.8", "version": "1.1.8",
"resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
"integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74="
"dev": true
}, },
"promise": { "promise": {
"version": "7.3.1", "version": "7.3.1",
@ -9682,6 +9789,11 @@
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
"dev": true "dev": true
}, },
"purepack": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/purepack/-/purepack-1.0.4.tgz",
"integrity": "sha1-CGKC/ZOShfWGZLqam7oxzbFlzNI="
},
"q": { "q": {
"version": "1.5.1", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
@ -11663,6 +11775,18 @@
"integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
"dev": true "dev": true
}, },
"triplesec": {
"version": "3.0.26",
"resolved": "https://registry.npmjs.org/triplesec/-/triplesec-3.0.26.tgz",
"integrity": "sha1-3/K7R1ikIzcuc5o5fYmR8Fl9CsE=",
"requires": {
"iced-error": "0.0.12",
"iced-lock": "1.1.0",
"iced-runtime": "1.0.3",
"more-entropy": "0.0.7",
"progress": "1.1.8"
}
},
"tty-browserify": { "tty-browserify": {
"version": "0.0.0", "version": "0.0.0",
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
@ -11820,6 +11944,11 @@
} }
} }
}, },
"uint64be": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/uint64be/-/uint64be-1.0.1.tgz",
"integrity": "sha1-H3FUIC8qG4rzU4cd2mUb80zpPpU="
},
"underscore": { "underscore": {
"version": "1.7.0", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz",

View file

@ -32,6 +32,7 @@
"devDependencies": { "devDependencies": {
"babel-core": "^6.26.0", "babel-core": "^6.26.0",
"babel-loader": "^7.1.3", "babel-loader": "^7.1.3",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.1", "babel-preset-env": "^1.6.1",
"css-loader": "^0.28.10", "css-loader": "^0.28.10",
"eslint": "^4.18.1", "eslint": "^4.18.1",
@ -81,6 +82,7 @@
"ctph.js": "0.0.5", "ctph.js": "0.0.5",
"diff": "^3.4.0", "diff": "^3.4.0",
"escodegen": "^1.9.1", "escodegen": "^1.9.1",
"es6-promisify": "^5.0.0",
"esmangle": "^1.0.1", "esmangle": "^1.0.1",
"esprima": "^4.0.0", "esprima": "^4.0.0",
"exif-parser": "^0.1.12", "exif-parser": "^0.1.12",
@ -95,6 +97,7 @@
"jsrsasign": "8.0.6", "jsrsasign": "8.0.6",
"lodash": "^4.17.5", "lodash": "^4.17.5",
"loglevel": "^1.6.1", "loglevel": "^1.6.1",
"kbpgp": "^2.0.76",
"loglevel-message-prefix": "^3.0.0", "loglevel-message-prefix": "^3.0.0",
"moment": "^2.20.1", "moment": "^2.20.1",
"moment-timezone": "^0.5.14", "moment-timezone": "^0.5.14",

View file

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

145
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 MorseCode from "../operations/MorseCode.js";
import NetBIOS from "../operations/NetBIOS.js"; import NetBIOS from "../operations/NetBIOS.js";
import PHP from "../operations/PHP.js"; import PHP from "../operations/PHP.js";
import PGP from "../operations/PGP.js";
import PublicKey from "../operations/PublicKey.js"; import PublicKey from "../operations/PublicKey.js";
import Punycode from "../operations/Punycode.js"; import Punycode from "../operations/Punycode.js";
import Regex from "../operations/Regex.js"; import Regex from "../operations/Regex.js";
@ -4159,6 +4160,150 @@ const OperationConfig = {
outputType: "string", outputType: "string",
args: [] 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;

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, 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, unsignedKey)({});
let signedKey = unsignedKey;
let privateKeyExportOptions = {};
if (password) privateKeyExportOptions.passphrase = password;
const privateKey = await promisify(signedKey.export_pgp_private, signedKey)(privateKeyExportOptions);
const publicKey = await promisify(signedKey.export_pgp_public, 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

@ -109,7 +109,7 @@ module.exports = {
chunks: false, chunks: false,
modules: false, modules: false,
entrypoints: false, entrypoints: false,
warningsFilter: /source-map/, warningsFilter: [/source-map/, /dependency is an expression/],
}, },
node: { node: {
fs: "empty" fs: "empty"