diff options
Diffstat (limited to '')
-rw-r--r-- | lang/js/src/Keyring.js | 675 |
1 files changed, 338 insertions, 337 deletions
diff --git a/lang/js/src/Keyring.js b/lang/js/src/Keyring.js index d18fb649..de21736e 100644 --- a/lang/js/src/Keyring.js +++ b/lang/js/src/Keyring.js @@ -32,383 +32,384 @@ import { gpgme_error } from './Errors'; */ export class GPGME_Keyring { constructor(){ + } - /** - * Queries Keys (all Keys or a subset) from gnupg. - * - * @param {String | Array<String>} pattern (optional) A pattern to - * search for in userIds or KeyIds. - * @param {Boolean} prepare_sync (optional) if set to true, most data - * (with the exception of armored Key blocks) will be cached for the - * Keys. This enables direct, synchronous use of these properties for - * all keys. It does not check for changes on the backend. The cached - * information can be updated with the {@link Key.refresh} method. - * @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>>} - * @static - * @async - */ - this.getKeys = function(pattern, prepare_sync=false, search=false){ - return new Promise(function(resolve, reject) { - let msg = createMessage('keylist'); - if (pattern !== undefined && pattern !== null){ - msg.setParameter('keys', pattern); - } - msg.setParameter('sigs', true); - if (search === true){ - msg.setParameter('locate', true); - } - msg.post().then(function(result){ - let resultset = []; - if (result.keys.length === 0){ - resolve([]); + /** + * Queries Keys (all Keys or a subset) from gnupg. + * + * @param {String | Array<String>} pattern (optional) A pattern to + * search for in userIds or KeyIds. + * @param {Boolean} prepare_sync (optional) if set to true, most data + * (with the exception of armored Key blocks) will be cached for the + * Keys. This enables direct, synchronous use of these properties for + * all keys. It does not check for changes on the backend. The cached + * information can be updated with the {@link Key.refresh} method. + * @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>>} + * @static + * @async + */ + getKeys (pattern, prepare_sync=false, search=false){ + return new Promise(function(resolve, reject) { + let msg = createMessage('keylist'); + if (pattern !== undefined && pattern !== null){ + msg.setParameter('keys', pattern); + } + msg.setParameter('sigs', true); + if (search === true){ + msg.setParameter('locate', true); + } + msg.post().then(function(result){ + let resultset = []; + if (result.keys.length === 0){ + resolve([]); + } else { + let secondrequest; + if (prepare_sync === true) { + secondrequest = function() { + let msg2 = createMessage('keylist'); + msg2.setParameter('keys', pattern); + msg2.setParameter('secret', true); + return msg2.post(); + }; } else { - let secondrequest; - if (prepare_sync === true) { - secondrequest = function() { - let msg2 = createMessage('keylist'); - msg2.setParameter('keys', pattern); - msg2.setParameter('secret', true); - return msg2.post(); - }; - } else { - secondrequest = function() { - return Promise.resolve(true); - }; - } - secondrequest().then(function(answer) { - for (let i=0; i < result.keys.length; i++){ - if (prepare_sync === true){ - if (answer && answer.keys) { - for (let j=0; - j < answer.keys.length; j++ ){ - const a = answer.keys[j]; - const b = result.keys[i]; - if ( - a.fingerprint === b.fingerprint - ) { - if (a.secret === true){ - b.hasSecret = true; - } else { - b.hasSecret = false; - } - break; + secondrequest = function() { + return Promise.resolve(true); + }; + } + secondrequest().then(function(answer) { + for (let i=0; i < result.keys.length; i++){ + if (prepare_sync === true){ + if (answer && answer.keys) { + for (let j=0; + j < answer.keys.length; j++ ){ + const a = answer.keys[j]; + const b = result.keys[i]; + if ( + a.fingerprint === b.fingerprint + ) { + if (a.secret === true){ + b.hasSecret = true; + } else { + b.hasSecret = false; } + break; } } } - let k = createKey(result.keys[i].fingerprint, - !prepare_sync, result.keys[i]); - resultset.push(k); } - resolve(resultset); - }, function(error){ - reject(error); - }); - } - }); + let k = createKey(result.keys[i].fingerprint, + !prepare_sync, result.keys[i]); + resultset.push(k); + } + resolve(resultset); + }, function(error){ + reject(error); + }); + } }); - }; + }); + } - /** - * @typedef {Object} exportResult The result of a getKeysArmored - * operation. - * @property {String} armored The public Key(s) as armored block. Note - * that the result is one armored block, and not a block per key. - * @property {Array<String>} secret_fprs (optional) list of - * fingerprints for those Keys that also have a secret Key available in - * gnupg. The secret key will not be exported, but the fingerprint can - * be used in operations needing a secret key. - */ + /** + * @typedef {Object} exportResult The result of a getKeysArmored + * operation. + * @property {String} armored The public Key(s) as armored block. Note + * that the result is one armored block, and not a block per key. + * @property {Array<String>} secret_fprs (optional) list of + * fingerprints for those Keys that also have a secret Key available in + * gnupg. The secret key will not be exported, but the fingerprint can + * be used in operations needing a secret key. + */ - /** - * Fetches the armored public Key blocks for all Keys matching the - * pattern (if no pattern is given, fetches all keys known to gnupg). - * @param {String|Array<String>} pattern (optional) The Pattern to - * search for - * @param {Boolean} with_secret_fpr (optional) also return a list of - * fingerprints for the keys that have a secret key available - * @returns {Promise<exportResult|GPGME_Error>} Object containing the - * armored Key(s) and additional information. - * @static - * @async - */ - this.getKeysArmored = function(pattern, with_secret_fpr) { - return new Promise(function(resolve, reject) { - let msg = createMessage('export'); - msg.setParameter('armor', true); - if (with_secret_fpr === true) { - msg.setParameter('with-sec-fprs', true); - } - if (pattern !== undefined && pattern !== null){ - msg.setParameter('keys', pattern); + /** + * Fetches the armored public Key blocks for all Keys matching the + * pattern (if no pattern is given, fetches all keys known to gnupg). + * @param {String|Array<String>} pattern (optional) The Pattern to + * search for + * @param {Boolean} with_secret_fpr (optional) also return a list of + * fingerprints for the keys that have a secret key available + * @returns {Promise<exportResult|GPGME_Error>} Object containing the + * armored Key(s) and additional information. + * @static + * @async + */ + getKeysArmored (pattern, with_secret_fpr) { + return new Promise(function(resolve, reject) { + let msg = createMessage('export'); + msg.setParameter('armor', true); + if (with_secret_fpr === true) { + msg.setParameter('with-sec-fprs', true); + } + if (pattern !== undefined && pattern !== null){ + msg.setParameter('keys', pattern); + } + msg.post().then(function(answer){ + const result = {armored: answer.data}; + if (with_secret_fpr === true + && answer.hasOwnProperty('sec-fprs') + ) { + result.secret_fprs = answer['sec-fprs']; } - msg.post().then(function(answer){ - const result = {armored: answer.data}; - if (with_secret_fpr === true - && answer.hasOwnProperty('sec-fprs') - ) { - result.secret_fprs = answer['sec-fprs']; - } - resolve(result); - }, function(error){ - reject(error); - }); + resolve(result); + }, function(error){ + reject(error); }); - }; + }); + } - /** - * Returns the Key used by default in gnupg. - * (a.k.a. 'primary Key or 'main key'). - * It looks up the gpg configuration if set, or the first key that - * contains a secret key. - * - * @returns {Promise<GPGME_Key|GPGME_Error>} - * @async - * @static - */ - this.getDefaultKey = function(prepare_sync = false) { - let me = this; - return new Promise(function(resolve, reject){ - let msg = createMessage('config_opt'); - msg.setParameter('component', 'gpg'); - msg.setParameter('option', 'default-key'); - msg.post().then(function(resp){ - if (resp.option !== undefined - && resp.option.hasOwnProperty('value') - && resp.option.value.length === 1 - && resp.option.value[0].hasOwnProperty('string') - && typeof(resp.option.value[0].string) === 'string'){ - me.getKeys(resp.option.value[0].string, true).then( - function(keys){ - if(keys.length === 1){ - resolve(keys[0]); - } else { - reject(gpgme_error('KEY_NO_DEFAULT')); - } - }, function(error){ - reject(error); - }); - } else { - let msg = createMessage('keylist'); - msg.setParameter('secret', true); - msg.post().then(function(result){ - if (result.keys.length === 0){ - reject(gpgme_error('KEY_NO_DEFAULT')); + /** + * Returns the Key used by default in gnupg. + * (a.k.a. 'primary Key or 'main key'). + * It looks up the gpg configuration if set, or the first key that + * contains a secret key. + * + * @returns {Promise<GPGME_Key|GPGME_Error>} + * @async + * @static + */ + getDefaultKey(prepare_sync = false) { + let me = this; + return new Promise(function(resolve, reject){ + let msg = createMessage('config_opt'); + msg.setParameter('component', 'gpg'); + msg.setParameter('option', 'default-key'); + msg.post().then(function(resp){ + if (resp.option !== undefined + && resp.option.hasOwnProperty('value') + && resp.option.value.length === 1 + && resp.option.value[0].hasOwnProperty('string') + && typeof(resp.option.value[0].string) === 'string'){ + me.getKeys(resp.option.value[0].string, true).then( + function(keys){ + if(keys.length === 1){ + resolve(keys[0]); } else { - for (let i=0; i< result.keys.length; i++ ) { - if (result.keys[i].invalid === false) { - let k = createKey( - result.keys[i].fingerprint, - !prepare_sync, - result.keys[i]); - resolve(k); - break; - } else if (i === result.keys.length - 1){ - reject(gpgme_error('KEY_NO_DEFAULT')); - } - } + reject(gpgme_error('KEY_NO_DEFAULT')); } }, function(error){ reject(error); }); - } - }, function(error){ - reject(error); - }); + } else { + let msg = createMessage('keylist'); + msg.setParameter('secret', true); + msg.post().then(function(result){ + if (result.keys.length === 0){ + reject(gpgme_error('KEY_NO_DEFAULT')); + } else { + for (let i=0; i< result.keys.length; i++ ) { + if (result.keys[i].invalid === false) { + let k = createKey( + result.keys[i].fingerprint, + !prepare_sync, + result.keys[i]); + resolve(k); + break; + } else if (i === result.keys.length - 1){ + reject(gpgme_error('KEY_NO_DEFAULT')); + } + } + } + }, function(error){ + reject(error); + }); + } + }, function(error){ + reject(error); }); - }; + }); + } - /** - * @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} 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 - */ + /** + * @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 into gnupg - * @param {Boolean} prepare_sync prepare the keys for synched use - * (see {@link getKeys}). - * @returns {Promise<importResult>} A summary and Keys considered. - * @async - * @static - */ - this.importKey = function (armored, prepare_sync) { - let feedbackValues = ['considered', 'no_user_id', 'imported', - 'imported_rsa', 'unchanged', 'new_user_ids', 'new_sub_keys', - 'new_signatures', 'new_revocations', 'secret_read', - 'secret_imported', 'secret_unchanged', 'skipped_new_keys', - 'not_imported', 'skipped_v3_keys']; - if (!armored || typeof(armored) !== 'string'){ - return Promise.reject(gpgme_error('PARAM_WRONG')); - } - let me = this; - return new Promise(function(resolve, reject){ - let msg = createMessage('import'); - msg.setParameter('data', armored); - msg.post().then(function(response){ - let infos = {}; - let fprs = []; - let summary = {}; - for (let i=0; i < feedbackValues.length; i++ ){ - summary[feedbackValues[i]] = - response.result[feedbackValues[i]]; - } - if (!response.result.hasOwnProperty('imports') || - response.result.imports.length === 0 - ){ - resolve({Keys:[],summary: summary}); - return; + /** + * 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 into gnupg + * @param {Boolean} prepare_sync prepare the keys for synched use + * (see {@link getKeys}). + * @returns {Promise<importResult>} A summary and Keys considered. + * @async + * @static + */ + importKey (armored, prepare_sync) { + let feedbackValues = ['considered', 'no_user_id', 'imported', + 'imported_rsa', 'unchanged', 'new_user_ids', 'new_sub_keys', + 'new_signatures', 'new_revocations', 'secret_read', + 'secret_imported', 'secret_unchanged', 'skipped_new_keys', + 'not_imported', 'skipped_v3_keys']; + if (!armored || typeof(armored) !== 'string'){ + return Promise.reject(gpgme_error('PARAM_WRONG')); + } + let me = this; + return new Promise(function(resolve, reject){ + let msg = createMessage('import'); + msg.setParameter('data', armored); + msg.post().then(function(response){ + let infos = {}; + let fprs = []; + let summary = {}; + for (let i=0; i < feedbackValues.length; i++ ){ + summary[feedbackValues[i]] = + response.result[feedbackValues[i]]; + } + if (!response.result.hasOwnProperty('imports') || + response.result.imports.length === 0 + ){ + resolve({Keys:[],summary: summary}); + return; + } + for (let res=0; res<response.result.imports.length; res++){ + let result = response.result.imports[res]; + let status = ''; + if (result.status === 0){ + status = 'nochange'; + } else if ((result.status & 1) === 1){ + status = 'newkey'; + } else { + status = 'change'; } - for (let res=0; res<response.result.imports.length; res++){ - let result = response.result.imports[res]; - let status = ''; - if (result.status === 0){ - status = 'nochange'; - } else if ((result.status & 1) === 1){ - status = 'newkey'; - } else { - status = 'change'; - } - let changes = {}; - changes.userId = (result.status & 2) === 2; - changes.signature = (result.status & 4) === 4; - changes.subkey = (result.status & 8) === 8; - //16 new secret key: not implemented + let changes = {}; + changes.userId = (result.status & 2) === 2; + changes.signature = (result.status & 4) === 4; + changes.subkey = (result.status & 8) === 8; + //16 new secret key: not implemented - fprs.push(result.fingerprint); - infos[result.fingerprint] = { - changes: changes, - status: status - }; - } - let resultset = []; - if (prepare_sync === true){ - me.getKeys(fprs, true).then(function(result){ - for (let i=0; i < result.length; i++) { - resultset.push({ - key: result[i], - changes: - infos[result[i].fingerprint].changes, - status: infos[result[i].fingerprint].status - }); - } - resolve({Keys:resultset,summary: summary}); - }, function(error){ - reject(error); - }); - } else { - for (let i=0; i < fprs.length; i++) { + fprs.push(result.fingerprint); + infos[result.fingerprint] = { + changes: changes, + status: status + }; + } + let resultset = []; + if (prepare_sync === true){ + me.getKeys(fprs, true).then(function(result){ + for (let i=0; i < result.length; i++) { resultset.push({ - key: createKey(fprs[i]), - changes: infos[fprs[i]].changes, - status: infos[fprs[i]].status + key: result[i], + changes: + infos[result[i].fingerprint].changes, + status: infos[result[i].fingerprint].status }); } - resolve({Keys:resultset,summary:summary}); + resolve({Keys:resultset,summary: summary}); + }, function(error){ + reject(error); + }); + } else { + for (let i=0; i < fprs.length; i++) { + resultset.push({ + key: createKey(fprs[i]), + changes: infos[fprs[i]].changes, + status: infos[fprs[i]].status + }); } + resolve({Keys:resultset,summary:summary}); + } - }, function(error){ - reject(error); - }); + }, function(error){ + reject(error); + }); - }); + }); - }; + } - /** - * 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 - */ - this.deleteKey = function(fingerprint){ - if (isFingerprint(fingerprint) === true) { - let key = createKey(fingerprint); - return key.delete(); - } else { - return Promise.reject(gpgme_error('KEY_INVALID')); - } - }; + /** + * 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){ + if (isFingerprint(fingerprint) === true) { + let key = createKey(fingerprint); + return key.delete(); + } else { + return Promise.reject(gpgme_error('KEY_INVALID')); + } + } - /** - * Generates a new Key pair directly in gpg, and returns a GPGME_Key - * representing that Key. Please note that due to security concerns, - * secret Keys can not be deleted or exported from inside gpgme.js. - * - * @param {String} userId The user Id, e.g. 'Foo Bar <[email protected]>' - * @param {String} algo (optional) algorithm (and optionally key size) - * to be used. See {@link supportedKeyAlgos} below for supported - * values. - * @param {Date} expires (optional) Expiration date. If not set, - * expiration will be set to 'never' - * - * @return {Promise<Key|GPGME_Error>} - * @async - */ - this.generateKey = function (userId, algo = 'default', expires){ - if ( - typeof(userId) !== 'string' || - supportedKeyAlgos.indexOf(algo) < 0 || - (expires && !(expires instanceof Date)) - ){ - return Promise.reject(gpgme_error('PARAM_WRONG')); + /** + * Generates a new Key pair directly in gpg, and returns a GPGME_Key + * representing that Key. Please note that due to security concerns, + * secret Keys can not be deleted or exported from inside gpgme.js. + * + * @param {String} userId The user Id, e.g. 'Foo Bar <[email protected]>' + * @param {String} algo (optional) algorithm (and optionally key size) + * to be used. See {@link supportedKeyAlgos} below for supported + * values. + * @param {Date} expires (optional) Expiration date. If not set, + * expiration will be set to 'never' + * + * @return {Promise<Key|GPGME_Error>} + * @async + */ + generateKey(userId, algo = 'default', expires){ + if ( + typeof(userId) !== 'string' || + supportedKeyAlgos.indexOf(algo) < 0 || + (expires && !(expires instanceof Date)) + ){ + return Promise.reject(gpgme_error('PARAM_WRONG')); + } + let me = this; + return new Promise(function(resolve, reject){ + let msg = createMessage('createkey'); + msg.setParameter('userid', userId); + msg.setParameter('algo', algo ); + if (expires){ + msg.setParameter('expires', + Math.floor(expires.valueOf()/1000)); + } else { + msg.setParameter('expires', 0); } - let me = this; - return new Promise(function(resolve, reject){ - let msg = createMessage('createkey'); - msg.setParameter('userid', userId); - msg.setParameter('algo', algo ); - if (expires){ - msg.setParameter('expires', - Math.floor(expires.valueOf()/1000)); - } else { - msg.setParameter('expires', 0); - } - msg.post().then(function(response){ - me.getKeys(response.fingerprint, true).then( - // TODO prepare_sync? - function(result){ - resolve(result); - }, function(error){ - reject(error); - }); - }, function(error) { - reject(error); - }); + msg.post().then(function(response){ + me.getKeys(response.fingerprint, true).then( + // TODO prepare_sync? + function(result){ + resolve(result); + }, function(error){ + reject(error); + }); + }, function(error) { + reject(error); }); - }; + }); } } + /** * List of algorithms supported for key generation. Please refer to the gnupg * documentation for details |