[git] GPGME - branch, javascript-binding, updated. gpgme-1.11.1-52-g332b4ad
by Maximilian Krambach
cvs at cvs.gnupg.org
Wed May 30 17:05:50 CEST 2018
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GnuPG Made Easy".
The branch, javascript-binding has been updated
via 332b4adbcc52ccf337cbc1943d5abef500769e10 (commit)
from 53ce2b94bc35243710dec9b7972c7aaaa79dbc75 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 332b4adbcc52ccf337cbc1943d5abef500769e10
Author: Maximilian Krambach <maximilian.krambach at intevation.de>
Date: Wed May 30 17:05:54 2018 +0200
js: more Keyring/Key handling
--
* src/Keys.js
- made setKeyData more consistent with other methods
- added convenience methods (Key.armored, Key.hasSecret)
- Added a Key delete function
* src/Keyring.js:
- added a getkeysArmored which allows for bulk export of public Keys
gpgmejs:
- removed deleteKey. It is now a method of the Key itself
- Encrypt: Added some common options as parameter, and the
possibility to set all allowed flags via an additional Object
diff --git a/lang/js/src/Errors.js b/lang/js/src/Errors.js
index fa8a4ef..3b53eeb 100644
--- a/lang/js/src/Errors.js
+++ b/lang/js/src/Errors.js
@@ -71,6 +71,10 @@ const err_list = {
msg:'This key does not exist in GPG',
type: 'error'
},
+ 'KEY_NO_INIT': {
+ msg:'This property has not been retrieved yet from GPG',
+ type: 'error'
+ }
// generic
'PARAM_WRONG':{
msg: 'Invalid parameter was found',
diff --git a/lang/js/src/Key.js b/lang/js/src/Key.js
index f2a16b4..454b191 100644
--- a/lang/js/src/Key.js
+++ b/lang/js/src/Key.js
@@ -93,56 +93,31 @@ export class GPGME_Key {
} else if (this._data.fingerprint !== data.fingerprint){
return gpgme_error('KEY_INVALID');
}
-
- let booleans = ['expired', 'disabled','invalid','can_encrypt',
- 'can_sign','can_certify','can_authenticate','secret',
- 'is_qualified'];
- for (let b =0; b < booleans.length; b++) {
- if (
- !data.hasOwnProperty(booleans[b]) ||
- typeof(data[booleans[b]]) !== 'boolean'
- ){
+ let dataKeys = Object.keys(data);
+ for (let i=0; i< dataKeys.length; i++){
+ if (!validKeyProperties.hasOwnProperty(dataKeys[i])){
return gpgme_error('KEY_INVALID');
}
- this._data[booleans[b]] = data[booleans[b]];
- }
- if (typeof(data.protocol) !== 'string'){
- return gpgme_error('KEY_INVALID');
- }
- // TODO check valid protocols?
- this._data.protocol = data.protocol;
-
- if (typeof(data.owner_trust) !== 'string'){
- return gpgme_error('KEY_INVALID');
- }
- // TODO check valid values?
- this._data.owner_trust = data.owner_trust;
-
- // TODO: what about origin ?
- if (!Number.isInteger(data.last_update)){
- return gpgme_error('KEY_INVALID');
- }
- this._data.last_update = data.last_update;
-
- this._data.subkeys = [];
- if (data.hasOwnProperty('subkeys')){
- if (!Array.isArray(data.subkeys)){
+ if (validKeyProperties[dataKeys[i]](data[dataKeys[i]]) !== true ){
return gpgme_error('KEY_INVALID');
}
- for (let i=0; i< data.subkeys.length; i++) {
- this._data.subkeys.push(
- new GPGME_Subkey(data.subkeys[i]));
- }
- }
-
- this._data.userids = [];
- if (data.hasOwnProperty('userids')){
- if (!Array.isArray(data.userids)){
- return gpgme_error('KEY_INVALID');
- }
- for (let i=0; i< data.userids.length; i++) {
- this._data.userids.push(
- new GPGME_UserId(data.userids[i]));
+ switch (dataKeys[i]){
+ case 'subkeys':
+ this._data.subkeys = [];
+ for (let i=0; i< data.subkeys.length; i++) {
+ this._data.subkeys.push(
+ new GPGME_Subkey(data.subkeys[i]));
+ }
+ break;
+ case 'userids':
+ this._data.userids = [];
+ for (let i=0; i< data.userids.length; i++) {
+ this._data.userids.push(
+ new GPGME_UserId(data.userids[i]));
+ }
+ break;
+ default:
+ this._data[dataKeys[i]] = data[dataKeys[i]];
}
}
return this;
@@ -161,7 +136,9 @@ export class GPGME_Key {
if (cached === false) {
let me = this;
return new Promise(function(resolve, reject) {
- if (property === 'armor'){
+ if (!validKeyProperties.hasOwnProperty(property)){
+ reject('PARAM_WRONG');
+ } else if (property === 'armored'){
resolve(me.getArmor());
} else if (property === 'hasSecret'){
resolve(me.getHasSecret());
@@ -173,15 +150,23 @@ export class GPGME_Key {
});
}
});
- } else {
- if (!this._data.hasOwnProperty(property)){
+ } else {
+ if (!validKeyProperties.hasOwnProperty(property)){
return gpgme_error('PARAM_WRONG');
+ }
+ if (!this._data.hasOwnProperty(property)){
+ return gpgme_error('KEY_NO_INIT');
} else {
return (this._data[property]);
}
}
}
+ get armored () {
+ return this.get('armored');
+ //TODO exception if empty
+ }
+
/**
* Reloads the Key from gnupg
*/
@@ -208,15 +193,6 @@ export class GPGME_Key {
}
/**
- * Get the armored block of the non- secret parts of the Key.
- * @returns {String} the armored Key block.
- * Notice that this may be outdated cached info. Use the async getArmor if
- * you need the most current info
- */
-
- // get armor(){ TODO }
-
- /**
* Query the armored block of the non- secret parts of the Key directly
* from gpg.
* @returns {Promise<String>}
@@ -279,6 +255,49 @@ export class GPGME_Key {
})
});
}
+
+ /**
+ * Convenience function to be directly used as properties of the Key
+ * Notice that these rely on cached info and may be outdated. Use the async
+ * get(property, false) if you need the most current info
+ */
+
+ /**
+ * @returns {String} The armored public Key block
+ */
+ get armored(){
+ return this.get('armored', true);
+ }
+
+ /**
+ * @returns {Boolean} If the key is considered a "private Key",
+ * i.e. owns a secret subkey.
+ */
+ get hasSecret(){
+ return this.get('hasSecret', true);
+ }
+
+ /**
+ * Deletes the public Key from the GPG Keyring. Note that a deletion of a
+ * secret key is not supported by the native backend.
+ * @returns {Boolean} Success if key was deleted, rejects with a GPG error
+ * otherwise
+ */
+ delete(){
+ let me = this;
+ return new Promise(function(resolve, reject){
+ if (!me._data.fingerprint){
+ reject(gpgme_error('KEY_INVALID'));
+ }
+ let msg = createMessage('delete');
+ msg.setParameter('key', me._data.fingerprint);
+ msg.post().then(function(result){
+ resolve(result.success);
+ }, function(error){
+ reject(error);
+ })
+ });
+ }
}
/**
@@ -453,3 +472,78 @@ const validSubKeyProperties = {
return (Number.isInteger(value) && value > 0);
}
}
+const validKeyProperties = {
+ //TODO better validation?
+ 'fingerprint': function(value){
+ return isFingerprint(value);
+ },
+ 'armored': function(value){
+ return typeof(value === 'string');
+ },
+ 'revoked': function(value){
+ return typeof(value) === 'boolean';
+ },
+ 'expired': function(value){
+ return typeof(value) === 'boolean';
+ },
+ 'disabled': function(value){
+ return typeof(value) === 'boolean';
+ },
+ 'invalid': function(value){
+ return typeof(value) === 'boolean';
+ },
+ 'can_encrypt': function(value){
+ return typeof(value) === 'boolean';
+ },
+ 'can_sign': function(value){
+ return typeof(value) === 'boolean';
+ },
+ 'can_certify': function(value){
+ return typeof(value) === 'boolean';
+ },
+ 'can_authenticate': function(value){
+ return typeof(value) === 'boolean';
+ },
+ 'secret': function(value){
+ return typeof(value) === 'boolean';
+ },
+ 'is_qualified': function(value){
+ return typeof(value) === 'boolean';
+ },
+ 'protocol': function(value){
+ return typeof(value) === 'string';
+ //TODO check for implemented ones
+ },
+ 'issuer_serial': function(value){
+ return typeof(value) === 'string';
+ },
+ 'issuer_name': function(value){
+ return typeof(value) === 'string';
+ },
+ 'chain_id': function(value){
+ return typeof(value) === 'string';
+ },
+ 'owner_trust': function(value){
+ return typeof(value) === 'string';
+ },
+ 'last_update': function(value){
+ return (Number.isInteger(value));
+ //TODO undefined/null possible?
+ },
+ 'origin': function(value){
+ return (Number.isInteger(value));
+ },
+ 'subkeys': function(value){
+ return (Array.isArray(value));
+ },
+ 'userids': function(value){
+ return (Array.isArray(value));
+ },
+ 'tofu': function(value){
+ return (Array.isArray(value));
+ },
+ 'hasSecret': function(value){
+ return typeof(value) === 'boolean';
+ }
+
+}
diff --git a/lang/js/src/Keyring.js b/lang/js/src/Keyring.js
index 7e13dfe..9081cbe 100644
--- a/lang/js/src/Keyring.js
+++ b/lang/js/src/Keyring.js
@@ -20,7 +20,7 @@
import {createMessage} from './Message'
import {GPGME_Key, createKey} from './Key'
-import { isFingerprint } from './Helpers';
+import { isFingerprint, toKeyIdArray } from './Helpers';
import { gpgme_error } from './Errors';
export class GPGME_Keyring {
@@ -43,10 +43,10 @@ export class GPGME_Keyring {
return new Promise(function(resolve, reject) {
let msg;
msg = createMessage('keylist');
- if (pattern && typeof(pattern) === 'string'){
+ if (pattern !== undefined){
msg.setParameter('keys', pattern);
}
- msg.setParameter('sigs', true); //TODO do we need this?
+ msg.setParameter('sigs', true);
msg.post().then(function(result){
let resultset = [];
let promises = [];
@@ -72,10 +72,30 @@ export class GPGME_Keyring {
});
});
}
-// TODO:
- // deleteKey(key, include_secret=false)
- // getKeysArmored(pattern) //just dump all armored keys
+
+ /**
+ * Fetches the armored public Key blocks for all Keys matchin the pattern
+ * (if no pattern is given, fetches all known to gnupg)
+ * @param {String|Array<String>} pattern (optional)
+ * @returns {Promise<String>} Armored Key blocks
+ */
+ getKeysArmored(pattern) {
+ if (pattern)
+ return new Promise(function(resolve, reject) {
+ let msg = createMessage('export');
+ msg.setParameter('armor', true);
+ if (pattern !== undefined){
+ msg.setParameter('keys', pattern);
+ }
+ msg.post().then(function(result){
+ resolve(result.data);
+ }, function(error){
+ reject(error);
+ });
+ }
+
// getDefaultKey() Big TODO
// importKeys(armoredKeys)
+ // generateKey --> TODO (Andre noch anfragen!)
};
diff --git a/lang/js/src/gpgmejs.js b/lang/js/src/gpgmejs.js
index 88a91a6..39f6a2f 100644
--- a/lang/js/src/gpgmejs.js
+++ b/lang/js/src/gpgmejs.js
@@ -46,28 +46,48 @@ export class GpgME {
}
/**
- * @param {String} data text/data to be encrypted as String
+ * Encrypt (and optionally sign) a Message
+ * @param {String|Object} data text/data to be encrypted as String. Also accepts Objects with a getText method
* @param {GPGME_Key|String|Array<String>|Array<GPGME_Key>} publicKeys Keys used to encrypt the message
+ * @param {GPGME_Key|String|Array<String>|Array<GPGME_Key>} secretKeys (optional) Keys used to sign the message
+ * @param {Boolean} base64 (optional) The data is already considered to be in base64 encoding
+ * @param {Boolean} armor (optional) Request the output as armored block
* @param {Boolean} wildcard (optional) If true, recipient information will not be added to the message
+ * @param {Object} additional use additional gpg options (refer to src/permittedOperations)
+ * @returns {Promise<Object>} Encrypted message:
+ * data: The encrypted message
+ * base64: Boolean indicating whether data is base64 encoded.
+ * @async
*/
- encrypt(data, publicKeys, base64=false, wildcard=false){
-
+ encrypt(data, publicKeys, secretKeys, base64=false, armor=true,
+ wildcard=false, additional = {}
+ ){
let msg = createMessage('encrypt');
if (msg instanceof Error){
return Promise.reject(msg)
}
- // TODO temporary
- msg.setParameter('armor', true);
+ msg.setParameter('armor', armor);
msg.setParameter('always-trust', true);
if (base64 === true) {
msg.setParameter('base64', true);
}
let pubkeys = toKeyIdArray(publicKeys);
msg.setParameter('keys', pubkeys);
+ let sigkeys = toKeyIdArray(secretKeys);
+ if (sigkeys.length > 0) {
+ msg.setParameter('signing_keys', sigkeys);
+ }
putData(msg, data);
if (wildcard === true){
msg.setParameter('throw-keyids', true);
};
+ if (additional){
+ let additional_Keys = Object.keys(additional);
+ for (let k = 0; k < additional_Keys.length; k++) {
+ msg.setParameter(additional_Keys[k],
+ additional[additional_Keys[k]]);
+ }
+ }
if (msg.isComplete === true){
return msg.post();
} else {
@@ -76,16 +96,17 @@ export class GpgME {
}
/**
- * @param {String} data TODO base64? Message with the encrypted data
- * @param {Boolean} base64 (optional) Response should stay base64
+ * Decrypt a Message
+ * @param {String|Object} data text/data to be decrypted. Accepts Strings and Objects with a getText method
+ * @param {Boolean} base64 (optional) Response is expected to be base64 encoded
* @returns {Promise<Object>} decrypted message:
data: The decrypted data. This may be base64 encoded.
base64: Boolean indicating whether data is base64 encoded.
mime: A Boolean indicating whether the data is a MIME object.
- info: An optional object with extra information.
+ signatures: Array of signature Objects TODO not yet implemented.
+ // should be an object that can tell if all signatures are valid etc.
* @async
*/
-
decrypt(data, base64=false){
if (data === undefined){
return Promise.reject(gpgme_error('MSG_EMPTY'));
@@ -99,10 +120,22 @@ export class GpgME {
}
putData(msg, data);
return msg.post();
-
}
- sign(data, keys, mode='clearsign', base64=false) { //sender
+ /**
+ * Sign a Message
+ * @param {String|Object} data text/data to be decrypted. Accepts Strings and Objects with a gettext methos
+ * @param {GPGME_Key|String|Array<String>|Array<GPGME_Key>} keys The key/keys to use for signing
+ * @param {*} mode The signing mode. Currently supported:
+ * 'clearsign': (default) The Message is embedded into the signature
+ * 'detached': The signature is stored separately
+ * @param {*} base64 input is considered base64
+ * @returns {Promise<Object>}
+ * data: The resulting data. In clearsign mode this includes the signature
+ * signature: The detached signature (if in detached mode)
+ * @async
+ */
+ sign(data, keys, mode='clearsign', base64=false) {
if (data === undefined){
return Promise.reject(gpgme_error('MSG_EMPTY'));
}
@@ -139,38 +172,10 @@ export class GpgME {
})
});
}
-
- deleteKey(key, delete_secret = false, no_confirm = false){
- return Promise.reject(gpgme_error('NOT_YET_IMPLEMENTED'));
- let msg = createMessage('deletekey');
- if (msg instanceof Error){
- return Promise.reject(msg);
- }
- let key_arr = toKeyIdArray(key);
- if (key_arr.length !== 1){
- return Promise.reject(
- gpgme_error('GENERIC_ERROR'));
- // TBD should always be ONE key?
- }
- msg.setParameter('key', key_arr[0]);
- if (delete_secret === true){
- msg.setParameter('allow_secret', true);
- // TBD
- }
- if (no_confirm === true){ //TODO: Do we want this hidden deep in the code?
- msg.setParameter('delete_force', true);
- // TBD
- }
- if (msg.isComplete === true){
- return msg.post();
- } else {
- return Promise.reject(gpgme_error('MSG_INCOMPLETE'));
- }
- }
}
/**
- * Sets the data of the message
+ * 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 {*} data The data to enter
*/
-----------------------------------------------------------------------
Summary of changes:
lang/js/src/Errors.js | 4 +
lang/js/src/Key.js | 210 +++++++++++++++++++++++++++++++++++--------------
lang/js/src/Keyring.js | 32 ++++++--
lang/js/src/gpgmejs.js | 85 ++++++++++----------
4 files changed, 227 insertions(+), 104 deletions(-)
hooks/post-receive
--
GnuPG Made Easy
http://git.gnupg.org
More information about the Gnupg-commits
mailing list