js: documentation
-- * Fixed errors: - src/Message.js post(): Set chunksize to defined default value instead of hardcoded - src/Keys.js: added getHasSecret() to refreshKey operation. * Reviewed and updated the documentation * non-documentation changes which do not affect functionality: - src/Errors: disabled a console.warn that is only useful for debugging - helpers.js: renamed "string" to "value" in isFingerprint and isLongId to avoid confusion - src/Keyring: prepare_sync, search are both explicitly set to false by default
This commit is contained in:
parent
8964627f6a
commit
4015f5b498
@ -1,10 +1,17 @@
|
|||||||
gpgmejs, as contained in this directory, is a javascript library for direct use
|
gpgme.js, as contained in this directory, is a javascript library for direct use
|
||||||
of gnupg in browsers, with the help of nativeMessaging.
|
of gnupg in browsers, with the help of nativeMessaging.
|
||||||
|
|
||||||
Installation
|
Prerequisites:
|
||||||
-------------
|
--------------
|
||||||
gpgmejs uses webpack, and thus depends on nodejs for building. All dependencies
|
gpgme.js will make use of the application gpgme-json, which is distributed with
|
||||||
will be installed (in a local subdirectory) with the command `npm install`.
|
gpgme. Gpgme-json needs to be installed; it will further need to accept the
|
||||||
|
browser extension in the manifest file.
|
||||||
|
|
||||||
|
Building gpgme.js
|
||||||
|
-----------------
|
||||||
|
gpgme.js uses webpack, and thus depends on nodejs for building. All
|
||||||
|
dependencies will be installed (in a local subdirectory) with the command
|
||||||
|
`npm install`.
|
||||||
|
|
||||||
To create a current version of the package, the command is
|
To create a current version of the package, the command is
|
||||||
`npx webpack --config webpack.conf.js`.
|
`npx webpack --config webpack.conf.js`.
|
||||||
@ -14,7 +21,7 @@ in webpack.conf.js.
|
|||||||
Demo and Test WebExtension:
|
Demo and Test WebExtension:
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
The Demo Extension shows simple examples of the usage of gpgmejs.
|
The Demo Extension shows simple examples of the usage of gpgme.js.
|
||||||
|
|
||||||
The BrowsertestExtension runs more intensive tests (using the mocha and chai
|
The BrowsertestExtension runs more intensive tests (using the mocha and chai
|
||||||
frameworks). Tests from BrowserTestExtension/tests will be run against the
|
frameworks). Tests from BrowserTestExtension/tests will be run against the
|
||||||
@ -22,11 +29,11 @@ gpgmejs.bundle.js itself. They aim to test the outward facing functionality
|
|||||||
and API.
|
and API.
|
||||||
|
|
||||||
Unittests as defined in ./unittests.js will be bundled in
|
Unittests as defined in ./unittests.js will be bundled in
|
||||||
gpgmejs_unittests.bundle.js, and test the separate components of gpgmejs,
|
gpgmejs_unittests.bundle.js, and test the separate components of gpgme.js,
|
||||||
which mostly are not exported.
|
which mostly are not exported.
|
||||||
|
|
||||||
. The file `build_extension.sh` may serve as a pointer on how to
|
The file `build_extension.sh` may serve as a pointer on how to build and
|
||||||
build and assemble these two Extensions and their dependencies. It can directly
|
assemble these two Extensions and their dependencies. It can directly
|
||||||
be used in most linux systems.
|
be used in most linux systems.
|
||||||
|
|
||||||
The resulting folders can just be included in the extensions tab of the browser
|
The resulting folders can just be included in the extensions tab of the browser
|
||||||
@ -46,7 +53,7 @@ is needed, with the following content:
|
|||||||
```
|
```
|
||||||
{
|
{
|
||||||
"name": "gpgmejson",
|
"name": "gpgmejson",
|
||||||
"description": "This is a test application for gpgmejs",
|
"description": "This is a test application for gpgme.js",
|
||||||
"path": "/usr/bin/gpgme-json",
|
"path": "/usr/bin/gpgme-json",
|
||||||
"type": "stdio",
|
"type": "stdio",
|
||||||
"allowed_origins": ["chrome-extension://ExtensionIdentifier/"]
|
"allowed_origins": ["chrome-extension://ExtensionIdentifier/"]
|
||||||
@ -61,7 +68,7 @@ is needed, with the following content:
|
|||||||
```
|
```
|
||||||
{
|
{
|
||||||
"name": "gpgmejson",
|
"name": "gpgmejson",
|
||||||
"description": "This is a test application for gpgmejs",
|
"description": "This is a test application for gpgme.js",
|
||||||
"path": "/usr/bin/gpgme-json",
|
"path": "/usr/bin/gpgme-json",
|
||||||
"type": "stdio",
|
"type": "stdio",
|
||||||
"allowed_extensions": ["ExtensionIdentifier@temporary-addon"]
|
"allowed_extensions": ["ExtensionIdentifier@temporary-addon"]
|
||||||
|
@ -28,7 +28,12 @@ import { gpgme_error } from './Errors';
|
|||||||
import { GPGME_Message, createMessage } from './Message';
|
import { GPGME_Message, createMessage } from './Message';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Connection handles the nativeMessaging interaction.
|
* A Connection handles the nativeMessaging interaction via a port. As the
|
||||||
|
* protocol only allows up to 1MB of message sent from the nativeApp to the
|
||||||
|
* browser, the connection will stay open until all parts of a communication
|
||||||
|
* are finished. For a new request, a new port will open, to avoid mixing
|
||||||
|
* contexts.
|
||||||
|
* @class
|
||||||
*/
|
*/
|
||||||
export class Connection{
|
export class Connection{
|
||||||
|
|
||||||
@ -37,19 +42,26 @@ export class Connection{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the information about the backend.
|
* @typedef {Object} backEndDetails
|
||||||
* @param {Boolean} details (optional) If set to false, the promise will
|
* @property {String} gpgme Version number of gpgme
|
||||||
* just return a connection status
|
* @property {Array<Object>} info Further information about the backend
|
||||||
* @returns {Promise<Object>} result
|
* and the used applications (Example:
|
||||||
* @returns {String} result.gpgme Version number of gpgme
|
* {
|
||||||
* @returns {Array<Object>} result.info Further information about the
|
|
||||||
* backends.
|
|
||||||
* Example:
|
|
||||||
* "protocol": "OpenPGP",
|
* "protocol": "OpenPGP",
|
||||||
* "fname": "/usr/bin/gpg",
|
* "fname": "/usr/bin/gpg",
|
||||||
* "version": "2.2.6",
|
* "version": "2.2.6",
|
||||||
* "req_version": "1.4.0",
|
* "req_version": "1.4.0",
|
||||||
* "homedir": "default"
|
* "homedir": "default"
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the information about the backend.
|
||||||
|
* @param {Boolean} details (optional) If set to false, the promise will
|
||||||
|
* just return if a connection was successful.
|
||||||
|
* @returns {Promise<backEndDetails>|Promise<Boolean>} Details from the
|
||||||
|
* backend
|
||||||
|
* @async
|
||||||
*/
|
*/
|
||||||
checkConnection(details = true){
|
checkConnection(details = true){
|
||||||
if (details === true) {
|
if (details === true) {
|
||||||
@ -74,7 +86,7 @@ export class Connection{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immediately closes the open port.
|
* Immediately closes an open port.
|
||||||
*/
|
*/
|
||||||
disconnect() {
|
disconnect() {
|
||||||
if (this._connection){
|
if (this._connection){
|
||||||
@ -93,10 +105,13 @@ export class Connection{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a message and resolves with the answer.
|
* Sends a {@link GPGME_Message} via tghe nativeMessaging port. It resolves
|
||||||
|
* with the completed answer after all parts have been received and
|
||||||
|
* reassembled, or rejects with an {@link GPGME_Error}.
|
||||||
|
*
|
||||||
* @param {GPGME_Message} message
|
* @param {GPGME_Message} message
|
||||||
* @returns {Promise<Object>} the gnupg answer, or rejection with error
|
* @returns {Promise<Object>} The collected answer
|
||||||
* information.
|
* @async
|
||||||
*/
|
*/
|
||||||
post(message){
|
post(message){
|
||||||
if (!message || !(message instanceof GPGME_Message)){
|
if (!message || !(message instanceof GPGME_Message)){
|
||||||
@ -170,16 +185,25 @@ export class Connection{
|
|||||||
/**
|
/**
|
||||||
* A class for answer objects, checking and processing the return messages of
|
* A class for answer objects, checking and processing the return messages of
|
||||||
* the nativeMessaging communication.
|
* the nativeMessaging communication.
|
||||||
* @param {String} operation The operation, to look up validity of returning
|
* @protected
|
||||||
* messages
|
|
||||||
*/
|
*/
|
||||||
class Answer{
|
class Answer{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {GPGME_Message} message
|
||||||
|
*/
|
||||||
constructor(message){
|
constructor(message){
|
||||||
this.operation = message.operation;
|
this.operation = message.operation;
|
||||||
this.expect = message.expect;
|
this.expect = message.expect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds incoming base64 encoded data to the existing response
|
||||||
|
* @param {*} msg base64 encoded data.
|
||||||
|
* @returns {Boolean}
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
collect(msg){
|
collect(msg){
|
||||||
if (typeof(msg) !== 'object' || !msg.hasOwnProperty('response')) {
|
if (typeof(msg) !== 'object' || !msg.hasOwnProperty('response')) {
|
||||||
return gpgme_error('CONN_UNEXPECTED_ANSWER');
|
return gpgme_error('CONN_UNEXPECTED_ANSWER');
|
||||||
@ -195,6 +219,10 @@ class Answer{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the base64 encoded answer data with the content verified against
|
||||||
|
* {@link permittedOperations}.
|
||||||
|
*/
|
||||||
get message(){
|
get message(){
|
||||||
if (this._responseb64 === undefined){
|
if (this._responseb64 === undefined){
|
||||||
return gpgme_error('CONN_UNEXPECTED_ANSWER');
|
return gpgme_error('CONN_UNEXPECTED_ANSWER');
|
||||||
|
@ -21,6 +21,9 @@
|
|||||||
* Maximilian Krambach <mkrambach@intevation.de>
|
* Maximilian Krambach <mkrambach@intevation.de>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listing of all possible error codes and messages of a {@link GPGME_Error}.
|
||||||
|
*/
|
||||||
const err_list = {
|
const err_list = {
|
||||||
// Connection
|
// Connection
|
||||||
'CONN_NO_CONNECT': {
|
'CONN_NO_CONNECT': {
|
||||||
@ -107,10 +110,11 @@ const err_list = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the given error code and returns an error object with some
|
* Checks the given error code and returns an {@link GPGME_Error} error object
|
||||||
* information about meaning and origin
|
* with some information about meaning and origin
|
||||||
* @param {*} code Error code. Should be in err_list or 'GNUPG_ERROR'
|
* @param {*} code Error code. Should be in err_list or 'GNUPG_ERROR'
|
||||||
* @param {*} info Error message passed through if code is 'GNUPG_ERROR'
|
* @param {*} info Error message passed through if code is 'GNUPG_ERROR'
|
||||||
|
* @returns {GPGME_Error}
|
||||||
*/
|
*/
|
||||||
export function gpgme_error(code = 'GENERIC_ERROR', info){
|
export function gpgme_error(code = 'GENERIC_ERROR', info){
|
||||||
if (err_list.hasOwnProperty(code)){
|
if (err_list.hasOwnProperty(code)){
|
||||||
@ -119,7 +123,7 @@ export function gpgme_error(code = 'GENERIC_ERROR', info){
|
|||||||
}
|
}
|
||||||
if (err_list[code].type === 'warning'){
|
if (err_list[code].type === 'warning'){
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.warn(code + ': ' + err_list[code].msg);
|
// console.warn(code + ': ' + err_list[code].msg);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} else if (code === 'GNUPG_ERROR'){
|
} else if (code === 'GNUPG_ERROR'){
|
||||||
@ -130,6 +134,14 @@ export function gpgme_error(code = 'GENERIC_ERROR', info){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An error class with additional info about the origin of the error, as string
|
||||||
|
* @property {String} code Short description of origin and type of the error
|
||||||
|
* @property {String} msg Additional info
|
||||||
|
* @class
|
||||||
|
* @protected
|
||||||
|
* @extends Error
|
||||||
|
*/
|
||||||
class GPGME_Error extends Error{
|
class GPGME_Error extends Error{
|
||||||
constructor(code, msg=''){
|
constructor(code, msg=''){
|
||||||
if (code === 'GNUPG_ERROR' && typeof(msg) === 'string'){
|
if (code === 'GNUPG_ERROR' && typeof(msg) === 'string'){
|
||||||
|
@ -26,11 +26,11 @@ import { GPGME_Key } from './Key';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to return an array of fingerprints, either from input fingerprints or
|
* Tries to return an array of fingerprints, either from input fingerprints or
|
||||||
* from Key objects (openpgp Keys or GPGME_Keys are both expected)
|
* from Key objects (openpgp Keys or GPGME_Keys are both accepted).
|
||||||
* @param {Object |Array<Object>| String|Array<String>} input
|
*
|
||||||
* @returns {Array<String>} Array of fingerprints.
|
* @param {Object | Array<Object> | String | Array<String>} input
|
||||||
|
* @returns {Array<String>} Array of fingerprints, or an empty array
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function toKeyIdArray(input){
|
export function toKeyIdArray(input){
|
||||||
if (!input){
|
if (!input){
|
||||||
return [];
|
return [];
|
||||||
@ -44,6 +44,8 @@ export function toKeyIdArray(input){
|
|||||||
if (isFingerprint(input[i]) === true){
|
if (isFingerprint(input[i]) === true){
|
||||||
result.push(input[i]);
|
result.push(input[i]);
|
||||||
} else {
|
} else {
|
||||||
|
// MSG_NOT_A_FPR is just a console warning if warning enabled
|
||||||
|
// in src/Errors.js
|
||||||
gpgme_error('MSG_NOT_A_FPR');
|
gpgme_error('MSG_NOT_A_FPR');
|
||||||
}
|
}
|
||||||
} else if (typeof(input[i]) === 'object'){
|
} else if (typeof(input[i]) === 'object'){
|
||||||
@ -71,9 +73,11 @@ export function toKeyIdArray(input){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check if values are valid hexadecimal values of a specified length
|
* Check if values are valid hexadecimal values of a specified length
|
||||||
* @param {*} key input value.
|
* @param {String} key input value.
|
||||||
* @param {int} len the expected length of the value
|
* @param {int} len the expected length of the value
|
||||||
|
* @returns {Boolean} true if value passes test
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
function hextest(key, len){
|
function hextest(key, len){
|
||||||
if (!key || typeof(key) !== 'string'){
|
if (!key || typeof(key) !== 'string'){
|
||||||
@ -87,15 +91,21 @@ function hextest(key, len){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check if the input is a valid Hex string with a length of 40
|
* check if the input is a valid Fingerprint
|
||||||
|
* (Hex string with a length of 40 characters)
|
||||||
|
* @param {String} value to check
|
||||||
|
* @returns {Boolean} true if value passes test
|
||||||
*/
|
*/
|
||||||
export function isFingerprint(string){
|
export function isFingerprint(value){
|
||||||
return hextest(string, 40);
|
return hextest(value, 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check if the input is a valid Hex string with a length of 16
|
* check if the input is a valid gnupg long ID (Hex string with a length of 16
|
||||||
|
* characters)
|
||||||
|
* @param {String} value to check
|
||||||
|
* @returns {Boolean} true if value passes test
|
||||||
*/
|
*/
|
||||||
export function isLongId(string){
|
export function isLongId(value){
|
||||||
return hextest(string, 16);
|
return hextest(value, 16);
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,9 @@ import { gpgme_error } from './Errors';
|
|||||||
import { createMessage } from './Message';
|
import { createMessage } from './Message';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the fingerprint.
|
* Validates the given fingerprint and creates a new {@link GPGME_Key}
|
||||||
* @param {String} fingerprint
|
* @param {String} fingerprint
|
||||||
|
* @returns {GPGME_Key|GPGME_Error}
|
||||||
*/
|
*/
|
||||||
export function createKey(fingerprint){
|
export function createKey(fingerprint){
|
||||||
if (!isFingerprint(fingerprint)){
|
if (!isFingerprint(fingerprint)){
|
||||||
@ -37,12 +38,13 @@ export function createKey(fingerprint){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representing the Keys as stored in GPG
|
* Represents the Keys as stored in the gnupg backend
|
||||||
* It allows to query almost all information defined in gpgme Key Objects
|
* It allows to query almost all information defined in gpgme Key Objects
|
||||||
* Refer to validKeyProperties for available information, and the gpgme
|
* Refer to {@link validKeyProperties} for available information, and the gpgme
|
||||||
* documentation on their meaning
|
* documentation on their meaning
|
||||||
* (https://www.gnupg.org/documentation/manuals/gpgme/Key-objects.html)
|
* (https://www.gnupg.org/documentation/manuals/gpgme/Key-objects.html)
|
||||||
*
|
*
|
||||||
|
* @class
|
||||||
*/
|
*/
|
||||||
export class GPGME_Key {
|
export class GPGME_Key {
|
||||||
|
|
||||||
@ -62,6 +64,9 @@ export class GPGME_Key {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {String} The fingerprint defining this Key
|
||||||
|
*/
|
||||||
get fingerprint(){
|
get fingerprint(){
|
||||||
if (!this._data || !this._data.fingerprint){
|
if (!this._data || !this._data.fingerprint){
|
||||||
return gpgme_error('KEY_INVALID');
|
return gpgme_error('KEY_INVALID');
|
||||||
@ -70,11 +75,11 @@ export class GPGME_Key {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @param {Object} data Bulk set the data for this key, with an Object sent
|
||||||
* @param {Object} data Bulk set data for this key, with the Object as sent
|
|
||||||
* by gpgme-json.
|
* by gpgme-json.
|
||||||
* @returns {GPGME_Key|GPGME_Error} The Key object itself after values have
|
* @returns {GPGME_Key|GPGME_Error} Itself after values have been set, an
|
||||||
* been set
|
* error if something went wrong
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
setKeyData(data){
|
setKeyData(data){
|
||||||
if (this._data === undefined) {
|
if (this._data === undefined) {
|
||||||
@ -126,12 +131,17 @@ export class GPGME_Key {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query any property of the Key list
|
* Query any property of the Key listed in {@link validKeyProperties}
|
||||||
* @param {String} property Key property to be retreived
|
* @param {String} property property to be retreived
|
||||||
* @param {*} cached (optional) if false, the data will be directly queried
|
* @param {Boolean} cached (optional) if false, the data will be directly
|
||||||
* from gnupg.
|
* queried from gnupg, and the operation will be asynchronous. Else, the
|
||||||
* @returns {*|Promise<*>} the value, or if not cached, a Promise
|
* data will be fetched from the state of the initialization of the Key.
|
||||||
* resolving on the value
|
* The cached mode may contain outdated information, but can be used as
|
||||||
|
* synchronous operation, where the backend is not expected to change Keys
|
||||||
|
* during a session. The key still can be reloaded by invoking
|
||||||
|
* {@link refreshKey}.
|
||||||
|
* @returns {*|Promise<*>} the value (Boolean, String, Array, Object).
|
||||||
|
* If 'cached' is true, the value will be resolved as a Promise.
|
||||||
*/
|
*/
|
||||||
get(property, cached=true) {
|
get(property, cached=true) {
|
||||||
if (cached === false) {
|
if (cached === false) {
|
||||||
@ -164,7 +174,12 @@ export class GPGME_Key {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reloads the Key from gnupg
|
* Reloads the Key information from gnupg. This is only useful if you use
|
||||||
|
* the GPGME_Keys cached. Note that this is a performance hungry operation.
|
||||||
|
* If you desire more than a few refreshs, it may be advisable to run
|
||||||
|
* {@link Keyring.getKeys} instead.
|
||||||
|
* @returns {Promise<GPGME_Key|GPGME_Error>}
|
||||||
|
* @async
|
||||||
*/
|
*/
|
||||||
refreshKey() {
|
refreshKey() {
|
||||||
let me = this;
|
let me = this;
|
||||||
@ -178,7 +193,12 @@ export class GPGME_Key {
|
|||||||
msg.post().then(function(result){
|
msg.post().then(function(result){
|
||||||
if (result.keys.length === 1){
|
if (result.keys.length === 1){
|
||||||
me.setKeyData(result.keys[0]);
|
me.setKeyData(result.keys[0]);
|
||||||
resolve(me);
|
me.getHasSecret().then(function(){
|
||||||
|
//TODO retrieve armored Key
|
||||||
|
resolve(me);
|
||||||
|
}, function(error){
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
reject(gpgme_error('KEY_NOKEY'));
|
reject(gpgme_error('KEY_NOKEY'));
|
||||||
}
|
}
|
||||||
@ -189,9 +209,9 @@ export class GPGME_Key {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query the armored block of the non- secret parts of the Key directly
|
* Query the armored block of the Key directly from gnupg. Please note that
|
||||||
* from gpg.
|
* this will not get you any export of the secret/private parts of a Key
|
||||||
* @returns {Promise<String>}
|
* @returns {Promise<String|GPGME_Error>}
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
getArmor(){
|
getArmor(){
|
||||||
@ -213,9 +233,12 @@ export class GPGME_Key {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find out if the Key includes a secret part
|
* Find out if the Key includes a secret part. Note that this is a rather
|
||||||
* @returns {Promise<Boolean>}
|
* nonperformant operation, as it needs to query gnupg twice. If you want
|
||||||
*
|
* this inforrmation about more than a few Keys, it may be advisable to run
|
||||||
|
* {@link Keyring.getKeys} instead.
|
||||||
|
* @returns {Promise<Boolean|GPGME_Error>} True if a secret/private Key is
|
||||||
|
* available in the gnupg Keyring
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
getHasSecret(){
|
getHasSecret(){
|
||||||
@ -253,25 +276,30 @@ export class GPGME_Key {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {String} The armored public Key block
|
* Property for the export of armored Key. If the armored Key is not
|
||||||
|
* cached, it returns an {@link GPGME_Error} with code 'KEY_NO_INIT'.
|
||||||
|
* Running {@link refreshKey} may help in this case.
|
||||||
|
* @returns {String|GPGME_Error} The armored public Key block.
|
||||||
*/
|
*/
|
||||||
get armored(){
|
get armored(){
|
||||||
return this.get('armored', true);
|
return this.get('armored', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {Boolean} If the key is considered a "private Key",
|
* Property indicating if the Key possesses a private/secret part. If this
|
||||||
* i.e. owns a secret subkey.
|
* information is not yet cached, it returns an {@link GPGME_Error} with
|
||||||
|
* code 'KEY_NO_INIT'. Running {@link refreshKey} may help in this case.
|
||||||
|
* @returns {Boolean} If the Key has a secret subkey.
|
||||||
*/
|
*/
|
||||||
get hasSecret(){
|
get hasSecret(){
|
||||||
return this.get('hasSecret', true);
|
return this.get('hasSecret', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes the public Key from the GPG Keyring. Note that a deletion of a
|
* Deletes the (public) Key from the GPG Keyring. Note that a deletion of a
|
||||||
* secret key is not supported by the native backend.
|
* secret key is not supported by the native backend.
|
||||||
* @returns {Promise<Boolean>} Success if key was deleted, rejects with a
|
* @returns {Promise<Boolean|GPGME_Error>} Success if key was deleted,
|
||||||
* GPG error otherwise
|
* rejects with a GPG error otherwise.
|
||||||
*/
|
*/
|
||||||
delete(){
|
delete(){
|
||||||
let me = this;
|
let me = this;
|
||||||
@ -291,10 +319,17 @@ export class GPGME_Key {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The subkeys of a Key. Currently, they cannot be refreshed separately
|
* Representing a subkey of a Key.
|
||||||
|
* @class
|
||||||
|
* @protected
|
||||||
*/
|
*/
|
||||||
class GPGME_Subkey {
|
class GPGME_Subkey {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes with the json data sent by gpgme-json
|
||||||
|
* @param {Object} data
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
constructor(data){
|
constructor(data){
|
||||||
let keys = Object.keys(data);
|
let keys = Object.keys(data);
|
||||||
for (let i=0; i< keys.length; i++) {
|
for (let i=0; i< keys.length; i++) {
|
||||||
@ -302,6 +337,13 @@ class GPGME_Subkey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a subkey property against {@link validSubKeyProperties} and
|
||||||
|
* sets it if validation is successful
|
||||||
|
* @param {String} property
|
||||||
|
* @param {*} value
|
||||||
|
* @param private
|
||||||
|
*/
|
||||||
setProperty(property, value){
|
setProperty(property, value){
|
||||||
if (!this._data){
|
if (!this._data){
|
||||||
this._data = {};
|
this._data = {};
|
||||||
@ -318,10 +360,9 @@ class GPGME_Subkey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Fetches any information about this subkey
|
||||||
* @param {String} property Information to request
|
* @param {String} property Information to request
|
||||||
* @returns {String | Number}
|
* @returns {String | Number | Date}
|
||||||
* TODO: date properties are numbers with Date in seconds
|
|
||||||
*/
|
*/
|
||||||
get(property) {
|
get(property) {
|
||||||
if (this._data.hasOwnProperty(property)){
|
if (this._data.hasOwnProperty(property)){
|
||||||
@ -330,15 +371,31 @@ class GPGME_Subkey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representing user attributes associated with a Key or subkey
|
||||||
|
* @class
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
class GPGME_UserId {
|
class GPGME_UserId {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes with the json data sent by gpgme-json
|
||||||
|
* @param {Object} data
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
constructor(data){
|
constructor(data){
|
||||||
let keys = Object.keys(data);
|
let keys = Object.keys(data);
|
||||||
for (let i=0; i< keys.length; i++) {
|
for (let i=0; i< keys.length; i++) {
|
||||||
this.setProperty(keys[i], data[keys[i]]);
|
this.setProperty(keys[i], data[keys[i]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Validates a subkey property against {@link validUserIdProperties} and
|
||||||
|
* sets it if validation is successful
|
||||||
|
* @param {String} property
|
||||||
|
* @param {*} value
|
||||||
|
* @param private
|
||||||
|
*/
|
||||||
setProperty(property, value){
|
setProperty(property, value){
|
||||||
if (!this._data){
|
if (!this._data){
|
||||||
this._data = {};
|
this._data = {};
|
||||||
@ -356,10 +413,9 @@ class GPGME_UserId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Fetches information about the user
|
||||||
* @param {String} property Information to request
|
* @param {String} property Information to request
|
||||||
* @returns {String | Number}
|
* @returns {String | Number}
|
||||||
* TODO: date properties are numbers with Date in seconds
|
|
||||||
*/
|
*/
|
||||||
get(property) {
|
get(property) {
|
||||||
if (this._data.hasOwnProperty(property)){
|
if (this._data.hasOwnProperty(property)){
|
||||||
@ -368,6 +424,13 @@ class GPGME_UserId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validation definition for userIds. Each valid userId property is represented
|
||||||
|
* as a key- Value pair, with their value being a validation function to check
|
||||||
|
* against
|
||||||
|
* @protected
|
||||||
|
* @const
|
||||||
|
*/
|
||||||
const validUserIdProperties = {
|
const validUserIdProperties = {
|
||||||
'revoked': function(value){
|
'revoked': function(value){
|
||||||
return typeof(value) === 'boolean';
|
return typeof(value) === 'boolean';
|
||||||
@ -419,6 +482,12 @@ const validUserIdProperties = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validation definition for subKeys. Each valid userId property is represented
|
||||||
|
* as a key-value pair, with the value being a validation function
|
||||||
|
* @protected
|
||||||
|
* @const
|
||||||
|
*/
|
||||||
const validSubKeyProperties = {
|
const validSubKeyProperties = {
|
||||||
'invalid': function(value){
|
'invalid': function(value){
|
||||||
return typeof(value) === 'boolean';
|
return typeof(value) === 'boolean';
|
||||||
@ -471,8 +540,14 @@ const validSubKeyProperties = {
|
|||||||
return (Number.isInteger(value) && value > 0);
|
return (Number.isInteger(value) && value > 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validation definition for Keys. Each valid Key property is represented
|
||||||
|
* as a key-value pair, with their value being a validation function
|
||||||
|
* @protected
|
||||||
|
* @const
|
||||||
|
*/
|
||||||
const validKeyProperties = {
|
const validKeyProperties = {
|
||||||
//TODO better validation?
|
|
||||||
'fingerprint': function(value){
|
'fingerprint': function(value){
|
||||||
return isFingerprint(value);
|
return isFingerprint(value);
|
||||||
},
|
},
|
||||||
|
@ -27,24 +27,30 @@ import {createKey} from './Key';
|
|||||||
import { isFingerprint } from './Helpers';
|
import { isFingerprint } from './Helpers';
|
||||||
import { gpgme_error } from './Errors';
|
import { gpgme_error } from './Errors';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class offers access to the gnupg keyring
|
||||||
|
*/
|
||||||
export class GPGME_Keyring {
|
export class GPGME_Keyring {
|
||||||
constructor(){
|
constructor(){
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} pattern (optional) pattern A pattern to search for,
|
* Queries Keys (all Keys or a subset) from gnupg.
|
||||||
* in userIds or KeyIds
|
|
||||||
* @param {Boolean} prepare_sync (optional, default true) if set to true,
|
|
||||||
* Key.armor and Key.hasSecret will be called, so they can be used
|
|
||||||
* inmediately. This allows for full synchronous use. If set to false,
|
|
||||||
* these will initially only be available as Promises in getArmor() and
|
|
||||||
* getHasSecret()
|
|
||||||
* @param {Boolean} search (optional) retrieve the Keys from servers with
|
|
||||||
* the method(s) defined in gnupg (e.g. WKD/HKP lookup)
|
|
||||||
* @returns {Promise.<Array<GPGME_Key>>}
|
|
||||||
*
|
*
|
||||||
|
* @param {String | Array<String>} pattern (optional) A pattern to search
|
||||||
|
* for in userIds or KeyIds.
|
||||||
|
* @param {Boolean} prepare_sync (optional) if set to true, the 'hasSecret'
|
||||||
|
* and 'armored' properties will be fetched for the Keys as well. These
|
||||||
|
* require additional calls to gnupg, resulting in a performance hungry
|
||||||
|
* operation. Calling them here enables direct, synchronous use of these
|
||||||
|
* properties for all keys, without having to resort to a refresh() first.
|
||||||
|
* @param {Boolean} search (optional) retrieve Keys from external servers
|
||||||
|
* with the method(s) defined in gnupg (e.g. WKD/HKP lookup)
|
||||||
|
* @returns {Promise.<Array<GPGME_Key>|GPGME_Error>}
|
||||||
|
* @static
|
||||||
|
* @async
|
||||||
*/
|
*/
|
||||||
getKeys(pattern, prepare_sync, search){
|
getKeys(pattern, prepare_sync=false, search=false){
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
let msg = createMessage('keylist');
|
let msg = createMessage('keylist');
|
||||||
if (pattern !== undefined){
|
if (pattern !== undefined){
|
||||||
@ -102,10 +108,15 @@ export class GPGME_Keyring {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the armored public Key blocks for all Keys matchin the pattern
|
* Fetches the armored public Key blocks for all Keys matching the pattern
|
||||||
* (if no pattern is given, fetches all known to gnupg)
|
* (if no pattern is given, fetches all keys known to gnupg). Note that the
|
||||||
* @param {String|Array<String>} pattern (optional)
|
* result may be one big armored block, instead of several smaller armored
|
||||||
* @returns {Promise<String>} Armored Key blocks
|
* blocks
|
||||||
|
* @param {String|Array<String>} pattern (optional) The Pattern to search
|
||||||
|
* for
|
||||||
|
* @returns {Promise<String|GPGME_Error>} Armored Key blocks
|
||||||
|
* @static
|
||||||
|
* @async
|
||||||
*/
|
*/
|
||||||
getKeysArmored(pattern) {
|
getKeysArmored(pattern) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
@ -123,15 +134,14 @@ export class GPGME_Keyring {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Key to be used by default for signing operations,
|
* Returns the Key used by default in gnupg.
|
||||||
* looking up the gpg configuration, or returning the first key that
|
* (a.k.a. 'primary Key or 'main key').
|
||||||
* contains a secret key.
|
* It looks up the gpg configuration if set, or the first key that contains
|
||||||
* @returns {Promise<GPGME_Key>}
|
* a secret key.
|
||||||
*
|
*
|
||||||
*
|
* @returns {Promise<GPGME_Key|GPGME_Error>}
|
||||||
* TODO: getHasSecret always returns false at this moment, so this fucntion
|
* @async
|
||||||
* still does not fully work as intended.
|
* @static
|
||||||
* * @async
|
|
||||||
*/
|
*/
|
||||||
getDefaultKey() {
|
getDefaultKey() {
|
||||||
let me = this;
|
let me = this;
|
||||||
@ -177,30 +187,40 @@ export class GPGME_Keyring {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @typedef {Object} importResult The result of a Key update
|
||||||
|
* @property {Object} summary Numerical summary of the result. See the
|
||||||
|
* feedbackValues variable for available Keys values and the gnupg
|
||||||
|
* documentation.
|
||||||
|
* https://www.gnupg.org/documentation/manuals/gpgme/Importing-Keys.html
|
||||||
|
* for details on their meaning.
|
||||||
|
* @property {Array<importedKeyResult>} Keys Array of Object containing
|
||||||
|
* GPGME_Keys with additional import information
|
||||||
*
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} importedKeyResult
|
||||||
|
* @property {GPGME_Key} key The resulting key
|
||||||
|
* @property {String} status:
|
||||||
|
* 'nochange' if the Key was not changed,
|
||||||
|
* 'newkey' if the Key was imported in gpg, and did not exist previously,
|
||||||
|
* 'change' if the key existed, but details were updated. For details,
|
||||||
|
* Key.changes is available.
|
||||||
|
* @property {Boolean} changes.userId Changes in userIds
|
||||||
|
* @property {Boolean} changes.signature Changes in signatures
|
||||||
|
* @property {Boolean} changes.subkey Changes in subkeys
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Import an armored Key block into gnupg. Note that this currently will
|
||||||
|
* not succeed on private Key blocks.
|
||||||
* @param {String} armored Armored Key block of the Key(s) to be imported
|
* @param {String} armored Armored Key block of the Key(s) to be imported
|
||||||
* into gnupg
|
* into gnupg
|
||||||
* @param {Boolean} prepare_sync prepare the keys for synched use
|
* @param {Boolean} prepare_sync prepare the keys for synched use
|
||||||
* (see getKeys()).
|
* (see {@link getKeys}).
|
||||||
*
|
* @returns {Promise<importResult>} A summary and Keys considered.
|
||||||
* @returns {Promise<Object>} result: A summary and an array of Keys
|
* @async
|
||||||
* considered
|
* @static
|
||||||
*
|
|
||||||
* @returns result.summary: Numerical summary of the result. See the
|
|
||||||
* feedbackValues variable for available values and the gnupg documentation
|
|
||||||
* https://www.gnupg.org/documentation/manuals/gpgme/Importing-Keys.html
|
|
||||||
* for details on their meaning.
|
|
||||||
* @returns {Array<Object>} result.Keys: Array of objects containing:
|
|
||||||
* @returns {GPGME_Key} Key.key The resulting key
|
|
||||||
* @returns {String} Key.status:
|
|
||||||
* 'nochange' if the Key was not changed,
|
|
||||||
* 'newkey' if the Key was imported in gpg, and did not exist
|
|
||||||
* previously,
|
|
||||||
* 'change' if the key existed, but details were updated. For
|
|
||||||
* details, Key.changes is available.
|
|
||||||
* @returns {Boolean} Key.changes.userId: userIds changed
|
|
||||||
* @returns {Boolean} Key.changes.signature: signatures changed
|
|
||||||
* @returns {Boolean} Key.changes.subkey: subkeys changed
|
|
||||||
*/
|
*/
|
||||||
importKey(armored, prepare_sync) {
|
importKey(armored, prepare_sync) {
|
||||||
let feedbackValues = ['considered', 'no_user_id', 'imported',
|
let feedbackValues = ['considered', 'no_user_id', 'imported',
|
||||||
@ -283,25 +303,36 @@ export class GPGME_Keyring {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience function for deleting a Key. See {@link Key.delete} for
|
||||||
|
* further information about the return values.
|
||||||
|
* @param {String} fingerprint
|
||||||
|
* @returns {Promise<Boolean|GPGME_Error>}
|
||||||
|
* @async
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
deleteKey(fingerprint){
|
deleteKey(fingerprint){
|
||||||
if (isFingerprint(fingerprint) === true) {
|
if (isFingerprint(fingerprint) === true) {
|
||||||
let key = createKey(fingerprint);
|
let key = createKey(fingerprint);
|
||||||
key.delete();
|
return key.delete();
|
||||||
|
} else {
|
||||||
|
return Promise.reject(gpgme_error('KEY_INVALID'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a new Key pair directly in gpg, and returns a GPGME_Key
|
* Generates a new Key pair directly in gpg, and returns a GPGME_Key
|
||||||
* representing that Key. Please note that due to security concerns, secret
|
* representing that Key. Please note that due to security concerns, secret
|
||||||
* Keys can not be _deleted_ from inside gpgmejs.
|
* Keys can not be deleted or exported from inside gpgme.js.
|
||||||
*
|
*
|
||||||
* @param {String} userId The user Id, e.g. "Foo Bar <foo@bar.baz>"
|
* @param {String} userId The user Id, e.g. 'Foo Bar <foo@bar.baz>'
|
||||||
* @param {*} algo (optional) algorithm (and optionally key size to be
|
* @param {String} algo (optional) algorithm (and optionally key size) to
|
||||||
* used. See {@link supportedKeyAlgos } below for supported values.
|
* be used. See {@link supportedKeyAlgos} below for supported values.
|
||||||
* @param {Date} expires (optional) Expiration date. If not set, expiration
|
* @param {Date} expires (optional) Expiration date. If not set, expiration
|
||||||
* will be set to 'never'
|
* will be set to 'never'
|
||||||
*
|
*
|
||||||
* @return {Promise<Key>}
|
* @return {Promise<Key|GPGME_Error>}
|
||||||
|
* @async
|
||||||
*/
|
*/
|
||||||
generateKey(userId, algo = 'default', expires){
|
generateKey(userId, algo = 'default', expires){
|
||||||
if (
|
if (
|
||||||
@ -336,7 +367,8 @@ export class GPGME_Keyring {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of algorithms supported for key generation.
|
* List of algorithms supported for key generation. Please refer to the gnupg
|
||||||
|
* documentation for details
|
||||||
*/
|
*/
|
||||||
const supportedKeyAlgos = [
|
const supportedKeyAlgos = [
|
||||||
'default',
|
'default',
|
||||||
|
@ -25,6 +25,12 @@ import { permittedOperations } from './permittedOperations';
|
|||||||
import { gpgme_error } from './Errors';
|
import { gpgme_error } from './Errors';
|
||||||
import { Connection } from './Connection';
|
import { Connection } from './Connection';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a message for gnupg, validating the message's purpose with
|
||||||
|
* {@link permittedOperations} first
|
||||||
|
* @param {String} operation
|
||||||
|
* @returns {GPGME_Message|GPGME_Error} The Message object
|
||||||
|
*/
|
||||||
export function createMessage(operation){
|
export function createMessage(operation){
|
||||||
if (typeof(operation) !== 'string'){
|
if (typeof(operation) !== 'string'){
|
||||||
return gpgme_error('PARAM_WRONG');
|
return gpgme_error('PARAM_WRONG');
|
||||||
@ -37,12 +43,13 @@ export function createMessage(operation){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepares a communication request. It checks operations and parameters in
|
* A Message collects, validates and handles all information required to
|
||||||
* ./permittedOperations.
|
* successfully establish a meaningful communication with gpgme-json via
|
||||||
* @param {String} operation
|
* {@link Connection.post}. The definition on which communication is available
|
||||||
|
* can be found in {@link permittedOperations}.
|
||||||
|
* @class
|
||||||
*/
|
*/
|
||||||
export class GPGME_Message {
|
export class GPGME_Message {
|
||||||
//TODO getter
|
|
||||||
|
|
||||||
constructor(operation){
|
constructor(operation){
|
||||||
this.operation = operation;
|
this.operation = operation;
|
||||||
@ -63,9 +70,13 @@ export class GPGME_Message {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the maximum size of responses from gpgme in bytes. Values allowed
|
* The maximum size of responses from gpgme in bytes. As of July 2018,
|
||||||
* range from 10kB to 1MB. The lower limit is arbitrary, the upper limit
|
* most browsers will only accept answers up to 1 MB of size. Everything
|
||||||
* fixed by browsers' nativeMessaging specifications
|
* above that threshold will not pass through nativeMessaging; answers that
|
||||||
|
* are larger need to be sent in parts. The lower limit is set to 10 KB.
|
||||||
|
* Messages smaller than the threshold will not encounter problems, larger
|
||||||
|
* messages will be received in chunks.
|
||||||
|
* If the value is not explicitly specified, 1023 KB is used.
|
||||||
*/
|
*/
|
||||||
set chunksize(value){
|
set chunksize(value){
|
||||||
if (
|
if (
|
||||||
@ -85,8 +96,9 @@ export class GPGME_Message {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If expect is set to 'base64', the response is expected to be base64
|
* Expect indicates which format data is expected to be in. It currently
|
||||||
* encoded binary
|
* only supports 'base64', indicating that the response data from gnupg are
|
||||||
|
* expected to be base64 encoded binary
|
||||||
*/
|
*/
|
||||||
set expect(value){
|
set expect(value){
|
||||||
if (value ==='base64'){
|
if (value ==='base64'){
|
||||||
@ -103,13 +115,13 @@ export class GPGME_Message {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a parameter for the message. Note that the operation has to be set
|
* Sets a parameter for the message. It validates with
|
||||||
* first, to be able to check if the parameter is permittted
|
* {@link permittedOperations}
|
||||||
* @param {String} param Parameter to set
|
* @param {String} param Parameter to set
|
||||||
* @param {any} value Value to set //TODO: Some type checking
|
* @param {any} value Value to set
|
||||||
* @returns {Boolean} If the parameter was set successfully
|
* @returns {Boolean} If the parameter was set successfully
|
||||||
*/
|
*/
|
||||||
setParameter(param,value){
|
setParameter( param,value ){
|
||||||
if (!param || typeof(param) !== 'string'){
|
if (!param || typeof(param) !== 'string'){
|
||||||
return gpgme_error('PARAM_WRONG');
|
return gpgme_error('PARAM_WRONG');
|
||||||
}
|
}
|
||||||
@ -125,6 +137,7 @@ export class GPGME_Message {
|
|||||||
} else {
|
} else {
|
||||||
return gpgme_error('PARAM_WRONG');
|
return gpgme_error('PARAM_WRONG');
|
||||||
}
|
}
|
||||||
|
// check incoming value for correctness
|
||||||
let checktype = function(val){
|
let checktype = function(val){
|
||||||
switch(typeof(val)){
|
switch(typeof(val)){
|
||||||
case 'string':
|
case 'string':
|
||||||
@ -187,9 +200,9 @@ export class GPGME_Message {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the message has the minimum requirements to be sent, according
|
* Check if the message has the minimum requirements to be sent, that is
|
||||||
* to the definitions in permittedOperations
|
* all 'required' parameters according to {@link permittedOperations}.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean} true if message is complete.
|
||||||
*/
|
*/
|
||||||
get isComplete(){
|
get isComplete(){
|
||||||
if (!this._msg.op){
|
if (!this._msg.op){
|
||||||
@ -222,13 +235,18 @@ export class GPGME_Message {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the Message via nativeMessaging and resolves with the answer.
|
||||||
|
* @returns {Promise<Object|GPGME_Error>}
|
||||||
|
* @async
|
||||||
|
*/
|
||||||
post(){
|
post(){
|
||||||
let me = this;
|
let me = this;
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
if (me.isComplete === true) {
|
if (me.isComplete === true) {
|
||||||
let conn = new Connection;
|
let conn = new Connection;
|
||||||
if (me._msg.chunksize === undefined){
|
if (me._msg.chunksize === undefined){
|
||||||
me._msg.chunksize = 1023*1024;
|
me._msg.chunksize = me.chunksize;
|
||||||
}
|
}
|
||||||
conn.post(me).then(function(response) {
|
conn.post(me).then(function(response) {
|
||||||
resolve(response);
|
resolve(response);
|
||||||
|
@ -20,17 +20,16 @@
|
|||||||
* Author(s):
|
* Author(s):
|
||||||
* Maximilian Krambach <mkrambach@intevation.de>
|
* Maximilian Krambach <mkrambach@intevation.de>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates a signature object and returns
|
|
||||||
* @param {Object} sigObject Object as returned by gpgme-json. The definition
|
|
||||||
* of the expected values are to be found in the constants 'expKeys', 'expSum',
|
|
||||||
* 'expNote' in this file.
|
|
||||||
* @returns {GPGME_Signature} Signature Object
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { gpgme_error } from './Errors';
|
import { gpgme_error } from './Errors';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates an object containing a signature, as sent by the nativeMessaging
|
||||||
|
* interface
|
||||||
|
* @param {Object} sigObject Object as returned by gpgme-json. The definition
|
||||||
|
* of the expected values are to be found in {@link expKeys}, {@link expSum},
|
||||||
|
* {@link expNote}.
|
||||||
|
* @returns {GPGME_Signature|GPGME_Error} Signature Object
|
||||||
|
*/
|
||||||
export function createSignature(sigObject){
|
export function createSignature(sigObject){
|
||||||
if (
|
if (
|
||||||
typeof(sigObject) !=='object' ||
|
typeof(sigObject) !=='object' ||
|
||||||
@ -72,18 +71,20 @@ export function createSignature(sigObject){
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representing the details of a signature. It is supposed to be read-only. The
|
* Representing the details of a signature. The full details as given by
|
||||||
* full details as given by gpgme-json can be accessed from the _rawSigObject.
|
* gpgme-json can be read from the _rawSigObject.
|
||||||
* )
|
*
|
||||||
|
* Note to reviewers: This class should be read only except via
|
||||||
|
* {@link createSignature}
|
||||||
|
* @protected
|
||||||
|
* @class
|
||||||
*/
|
*/
|
||||||
class GPGME_Signature {
|
class GPGME_Signature {
|
||||||
|
|
||||||
constructor(sigObject){
|
constructor(sigObject){
|
||||||
this._rawSigObject = sigObject;
|
this._rawSigObject = sigObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The signatures' fingerprint
|
|
||||||
*/
|
|
||||||
get fingerprint(){
|
get fingerprint(){
|
||||||
return this._rawSigObject.fingerprint;
|
return this._rawSigObject.fingerprint;
|
||||||
}
|
}
|
||||||
@ -105,7 +106,7 @@ class GPGME_Signature {
|
|||||||
* @returns {Date}
|
* @returns {Date}
|
||||||
*/
|
*/
|
||||||
get timestamp(){
|
get timestamp(){
|
||||||
return new Date(this._rawSigObject.timestamp* 1000);
|
return new Date(this._rawSigObject.timestamp * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,10 +28,62 @@ import { gpgme_error } from './Errors';
|
|||||||
import { GPGME_Keyring } from './Keyring';
|
import { GPGME_Keyring } from './Keyring';
|
||||||
import { createSignature } from './Signature';
|
import { createSignature } from './Signature';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} decrypt_result
|
||||||
|
* @property {String} data The decrypted data
|
||||||
|
* @property {Boolean} base64 indicating whether data is base64 encoded.
|
||||||
|
* @property {Boolean} is_mime (optional) the data claims to be a MIME
|
||||||
|
* object.
|
||||||
|
* @property {String} file_name (optional) the original file name
|
||||||
|
* @property {signatureDetails} signatures Verification details for
|
||||||
|
* signatures
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} signatureDetails
|
||||||
|
* @property {Boolean} all_valid Summary if all signatures are fully valid
|
||||||
|
* @property {Number} count Number of signatures found
|
||||||
|
* @property {Number} failures Number of invalid signatures
|
||||||
|
* @property {Array<GPGME_Signature>} signatures.good All valid signatures
|
||||||
|
* @property {Array<GPGME_Signature>} signatures.bad All invalid signatures
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} encrypt_result The result of an encrypt operation
|
||||||
|
* @property {String} data The encrypted message
|
||||||
|
* @property {Boolean} base64 Indicating whether data is base64 encoded.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef { GPGME_Key | String | Object } inputKeys
|
||||||
|
* Accepts different identifiers of a gnupg Key that can be parsed by
|
||||||
|
* {@link toKeyIdArray}. Expected inputs are: One or an array of
|
||||||
|
* GPGME_Keys; one or an array of fingerprint strings; one or an array of
|
||||||
|
* openpgpjs Key objects.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} signResult The result of a signing operation
|
||||||
|
* @property {String} data The resulting data. Includes the signature in
|
||||||
|
* clearsign mode
|
||||||
|
* @property {String} signature The detached signature (if in detached mode)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @typedef {Object} verifyResult The result of a verification
|
||||||
|
* @property {Boolean} data: The verified data
|
||||||
|
* @property {Boolean} is_mime (optional) the data claims to be a MIME
|
||||||
|
* object.
|
||||||
|
* @property {String} file_name (optional) the original file name
|
||||||
|
* @property {signatureDetails} signatures Verification details for
|
||||||
|
* signatures
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main entry point for gpgme.js.
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
export class GpgME {
|
export class GpgME {
|
||||||
/**
|
|
||||||
* initializes GpgME by opening a nativeMessaging port
|
|
||||||
*/
|
|
||||||
constructor(){
|
constructor(){
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,6 +93,9 @@ export class GpgME {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesses the {@link GPGME_Keyring}.
|
||||||
|
*/
|
||||||
get Keyring(){
|
get Keyring(){
|
||||||
if (!this._Keyring){
|
if (!this._Keyring){
|
||||||
this._Keyring = new GPGME_Keyring;
|
this._Keyring = new GPGME_Keyring;
|
||||||
@ -49,23 +104,23 @@ export class GpgME {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt (and optionally sign) a Message
|
* Encrypt (and optionally sign) data
|
||||||
* @param {String|Object} data text/data to be encrypted as String. Also
|
* @param {String|Object} data text/data to be encrypted as String. Also
|
||||||
* accepts Objects with a getText method
|
* accepts Objects with a getText method
|
||||||
* @param {GPGME_Key|String|Array<String>|Array<GPGME_Key>} publicKeys
|
* @param {inputKeys} publicKeys
|
||||||
* Keys used to encrypt the message
|
* Keys used to encrypt the message
|
||||||
* @param {GPGME_Key|String|Array<String>|Array<GPGME_Key>} secretKeys
|
* @param {inputKeys} secretKeys (optional) Keys used to sign the message.
|
||||||
* (optional) Keys used to sign the message
|
* If Keys are present, the operation requested is assumed to be 'encrypt
|
||||||
|
* and sign'
|
||||||
* @param {Boolean} base64 (optional) The data will be interpreted as
|
* @param {Boolean} base64 (optional) The data will be interpreted as
|
||||||
* base64 encoded data
|
* base64 encoded data.
|
||||||
* @param {Boolean} armor (optional) Request the output as armored block
|
* @param {Boolean} armor (optional) Request the output as armored block.
|
||||||
* @param {Boolean} wildcard (optional) If true, recipient information will
|
* @param {Boolean} wildcard (optional) If true, recipient information will
|
||||||
* not be added to the message
|
* not be added to the message.
|
||||||
* @param {Object} additional use additional gpg options
|
* @param {Object} additional use additional valid gpg options as defined
|
||||||
* (refer to src/permittedOperations)
|
* in {@link permittedOperations}
|
||||||
* @returns {Promise<Object>} Encrypted message:
|
* @returns {Promise<encrypt_result>} Object containing the encrypted
|
||||||
* data: The encrypted message
|
* message and additional info.
|
||||||
* base64: Boolean indicating whether data is base64 encoded.
|
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
encrypt(data, publicKeys, secretKeys, base64=false, armor=true,
|
encrypt(data, publicKeys, secretKeys, base64=false, armor=true,
|
||||||
@ -105,28 +160,12 @@ export class GpgME {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypt a Message
|
* Decrypts a Message
|
||||||
* @param {String|Object} data text/data to be decrypted. Accepts Strings
|
* @param {String|Object} data text/data to be decrypted. Accepts Strings
|
||||||
* and Objects with a getText method
|
* and Objects with a getText method
|
||||||
* @param {Boolean} base64 (optional) false if the data is an armored block,
|
* @param {Boolean} base64 (optional) false if the data is an armored block,
|
||||||
* true if it is base64 encoded binary data
|
* true if it is base64 encoded binary data
|
||||||
* @returns {Promise<Object>} result: Decrypted Message and information
|
* @returns {Promise<decrypt_result>} Decrypted Message and information
|
||||||
* @returns {String} result.data: The decrypted data.
|
|
||||||
* @returns {Boolean} result.base64: indicating whether data is base64
|
|
||||||
* encoded.
|
|
||||||
* @returns {Boolean} result.is_mime: Indicating whether the data is a MIME
|
|
||||||
* object.
|
|
||||||
* @returns {String} result.file_name: The optional original file name
|
|
||||||
* @returns {Object} message.signatures Verification details for signatures:
|
|
||||||
* @returns {Boolean} message.signatures.all_valid: true if all signatures
|
|
||||||
* are valid
|
|
||||||
* @returns {Number} message.signatures.count: Number of signatures found
|
|
||||||
* @returns {Number} message.signatures.failures Number of invalid
|
|
||||||
* signatures
|
|
||||||
* @returns {Array<Object>} message.signatures.signatures. Two arrays
|
|
||||||
* (good & bad) of {@link GPGME_Signature} objects, offering further
|
|
||||||
* information.
|
|
||||||
*
|
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
decrypt(data, base64=false){
|
decrypt(data, base64=false){
|
||||||
@ -169,16 +208,13 @@ export class GpgME {
|
|||||||
/**
|
/**
|
||||||
* Sign a Message
|
* Sign a Message
|
||||||
* @param {String|Object} data text/data to be signed. Accepts Strings
|
* @param {String|Object} data text/data to be signed. Accepts Strings
|
||||||
* and Objects with a gettext methos
|
* and Objects with a getText method.
|
||||||
* @param {GPGME_Key|String|Array<String>|Array<GPGME_Key>} keys The
|
* @param {inputKeys} keys The key/keys to use for signing
|
||||||
* key/keys to use for signing
|
* @param {String} mode The signing mode. Currently supported:
|
||||||
* @param {*} mode The signing mode. Currently supported:
|
* 'clearsign':The Message is embedded into the signature;
|
||||||
* 'clearsign': (default) The Message is embedded into the signature
|
* 'detached': The signature is stored separately
|
||||||
* 'detached': The signature is stored separately
|
* @param {Boolean} base64 input is considered base64
|
||||||
* @param {*} base64 input is considered base64
|
* @returns {Promise<signResult>}
|
||||||
* @returns {Promise<Object>}
|
|
||||||
* data: The resulting data. Includes the signature in clearsign mode
|
|
||||||
* signature: The detached signature (if in detached mode)
|
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
sign(data, keys, mode='clearsign', base64=false) {
|
sign(data, keys, mode='clearsign', base64=false) {
|
||||||
@ -221,20 +257,12 @@ export class GpgME {
|
|||||||
/**
|
/**
|
||||||
* Verifies data.
|
* Verifies data.
|
||||||
* @param {String|Object} data text/data to be verified. Accepts Strings
|
* @param {String|Object} data text/data to be verified. Accepts Strings
|
||||||
* and Objects with a gettext method
|
* and Objects with a getText method
|
||||||
* @param {String} (optional) A detached signature. If not present, opaque
|
* @param {String} (optional) A detached signature. If not present, opaque
|
||||||
* mode is assumed
|
* mode is assumed
|
||||||
* @param {Boolean} (optional) Data and signature are base64 encoded
|
* @param {Boolean} (optional) Data and signature are base64 encoded
|
||||||
* // TODO verify if signature really is assumed to be base64
|
* @returns {Promise<verifyResult>}
|
||||||
* @returns {Promise<Object>} result:
|
*@async
|
||||||
* @returns {Boolean} result.data: The verified data
|
|
||||||
* @returns {Boolean} result.is_mime: The message claims it is MIME
|
|
||||||
* @returns {String} result.file_name: The optional filename of the message
|
|
||||||
* @returns {Boolean} result.all_valid: true if all signatures are valid
|
|
||||||
* @returns {Number} result.count: Number of signatures found
|
|
||||||
* @returns {Number} result.failures Number of unsuccessful signatures
|
|
||||||
* @returns {Array<Object>} result.signatures. Two arrays (good & bad) of
|
|
||||||
* {@link GPGME_Signature} objects, offering further information.
|
|
||||||
*/
|
*/
|
||||||
verify(data, signature, base64 = false){
|
verify(data, signature, base64 = false){
|
||||||
let msg = createMessage('verify');
|
let msg = createMessage('verify');
|
||||||
@ -275,7 +303,10 @@ export class GpgME {
|
|||||||
/**
|
/**
|
||||||
* Sets the data of the message, setting flags according on the data type
|
* Sets the data of the message, setting flags according on the data type
|
||||||
* @param {GPGME_Message} message The message where this data will be set
|
* @param {GPGME_Message} message The message where this data will be set
|
||||||
* @param {*} data The data to enter
|
* @param { String| Object } data The data to enter. Expects either a string of
|
||||||
|
* data, or an object with a getText method
|
||||||
|
* @returns {undefined| GPGME_Error} Error if not successful, nothing otherwise
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
function putData(message, data){
|
function putData(message, data){
|
||||||
if (!message || !(message instanceof GPGME_Message) ) {
|
if (!message || !(message instanceof GPGME_Message) ) {
|
||||||
@ -301,6 +332,11 @@ function putData(message, data){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses, validates and converts incoming objects into signatures.
|
||||||
|
* @param {Array<Object>} sigs
|
||||||
|
* @returns {signatureDetails} Details about the signatures
|
||||||
|
*/
|
||||||
function collectSignatures(sigs){
|
function collectSignatures(sigs){
|
||||||
if (!Array.isArray(sigs)){
|
if (!Array.isArray(sigs)){
|
||||||
return gpgme_error('SIG_NO_SIGS');
|
return gpgme_error('SIG_NO_SIGS');
|
||||||
|
@ -27,8 +27,8 @@ import { gpgme_error } from './Errors';
|
|||||||
import { Connection } from './Connection';
|
import { Connection } from './Connection';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests nativeMessaging once and returns a GpgME object if successful.
|
* Initializes gpgme.js by testing the nativeMessaging connection once.
|
||||||
* @returns {GpgME | Error}
|
* @returns {Promise<GpgME> | GPGME_Error}
|
||||||
*
|
*
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
|
@ -22,27 +22,30 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Definition of the possible interactions with gpgme-json.
|
* @typedef {Object} messageProperty
|
||||||
* operation: <Object>
|
* A message Property is defined by it's key.
|
||||||
required: Array<Object>
|
* @property {Array<String>} allowed Array of allowed types.
|
||||||
<String> name The name of the property
|
* Currently accepted values are 'number', 'string', 'boolean'.
|
||||||
allowed: Array of allowed types. Currently accepted values:
|
* @property {Boolean} array_allowed If the value can be an array of types
|
||||||
['number', 'string', 'boolean', 'Uint8Array']
|
* defined in allowed
|
||||||
array_allowed: Boolean. If the value can be an array of the above
|
* @property {<Array>} allowed_data (optional) restricts to the given values
|
||||||
allowed_data: <Array> If present, restricts to the given value
|
*/
|
||||||
optional: Array<Object>
|
|
||||||
see 'required', with these parameters not being mandatory for a
|
|
||||||
complete message
|
|
||||||
pinentry: boolean If a pinentry dialog is expected, and a timeout of
|
|
||||||
5000 ms would be too short
|
|
||||||
answer: <Object>
|
|
||||||
type: <String< The content type of answer expected
|
|
||||||
data: <Object>
|
|
||||||
the properties expected and their type, eg: {'data':'string'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Definition of the possible interactions with gpgme-json.
|
||||||
|
* @param {Object} operation Each operation is named by a key and contains
|
||||||
|
* the following properties:
|
||||||
|
* @property {messageProperty} required An object with all required parameters
|
||||||
|
* @property {messageProperty} optional An object with all optional parameters
|
||||||
|
* @property {Boolean} pinentry (optional) If true, a password dialog is
|
||||||
|
* expected, thus a connection tuimeout is not advisable
|
||||||
|
* @property {Object} answer The definition on what to expect as answer, if the
|
||||||
|
* answer is not an error
|
||||||
|
* @property {Array<String>} answer.type the type(s) as reported by gpgme-json.
|
||||||
|
* @property {Object} answer.data key-value combinations of expected properties
|
||||||
|
* of an answer and their type ('boolean', 'string', object)
|
||||||
|
@const
|
||||||
|
*/
|
||||||
export const permittedOperations = {
|
export const permittedOperations = {
|
||||||
encrypt: {
|
encrypt: {
|
||||||
pinentry: true, //TODO only with signing_keys
|
pinentry: true, //TODO only with signing_keys
|
||||||
|
Loading…
Reference in New Issue
Block a user