From 1cd90183464d214ef22eca2d6669ee6f9560638a Mon Sep 17 00:00:00 2001 From: Bart Butler Date: Tue, 6 Mar 2018 10:04:33 -0800 Subject: [PATCH] some cleanup --- src/key.js | 73 ++-- src/message.js | 351 +++++++++--------- src/openpgp.js | 30 +- src/packet/packetlist.js | 6 +- .../public_key_encrypted_session_key.js | 13 +- src/packet/secret_key.js | 14 +- src/packet/signature.js | 4 +- src/packet/sym_encrypted_aead_protected.js | 6 +- .../sym_encrypted_integrity_protected.js | 5 +- src/packet/sym_encrypted_session_key.js | 14 +- src/packet/symmetrically_encrypted.js | 19 +- src/worker/async_proxy.js | 13 +- 12 files changed, 286 insertions(+), 262 deletions(-) diff --git a/src/key.js b/src/key.js index 5af81553..8c989b96 100644 --- a/src/key.js +++ b/src/key.js @@ -153,7 +153,7 @@ Key.prototype.packetlist2structure = function(packetlist) { /** * Transforms structured key data to packetlist - * @return {module:packet/packetlist} The packets that form a key + * @returns {module:packet/packetlist} The packets that form a key */ Key.prototype.toPacketlist = function() { const packetlist = new packet.List(); @@ -210,7 +210,7 @@ Key.prototype.getKeyIds = function() { /** * Returns array containing first key packet for given key ID or all key packets in the case of a wildcard ID * @param {type/keyid} keyId - * @return {(module:packet/public_subkey|module:packet/public_key| + * @returns {(module:packet/public_subkey|module:packet/public_key| * module:packet/secret_subkey|module:packet/secret_key|null)} */ Key.prototype.getKeyPackets = function(packetKeyId) { @@ -229,7 +229,7 @@ Key.prototype.getKeyPackets = function(packetKeyId) { /** * Returns userids - * @return {Array} array of userids + * @returns {Array} array of userids */ Key.prototype.getUserIds = function() { const userids = []; @@ -243,7 +243,7 @@ Key.prototype.getUserIds = function() { /** * Returns true if this is a public key - * @return {Boolean} + * @returns {Boolean} */ Key.prototype.isPublic = function() { return this.primaryKey.tag === enums.packet.publicKey; @@ -251,7 +251,7 @@ Key.prototype.isPublic = function() { /** * Returns true if this is a private key - * @return {Boolean} + * @returns {Boolean} */ Key.prototype.isPrivate = function() { return this.primaryKey.tag === enums.packet.secretKey; @@ -259,7 +259,7 @@ Key.prototype.isPrivate = function() { /** * Returns key as public key (shallow copy) - * @return {module:key~Key} new public Key + * @returns {module:key~Key} new public Key */ Key.prototype.toPublic = function() { const packetlist = new packet.List(); @@ -290,7 +290,7 @@ Key.prototype.toPublic = function() { /** * Returns ASCII armored text of key - * @return {String} ASCII armor + * @returns {String} ASCII armor */ Key.prototype.armor = function() { const type = this.isPublic() ? enums.armor.public_key : enums.armor.private_key; @@ -301,7 +301,7 @@ Key.prototype.armor = function() { * Returns first key packet or key packet by given keyId that is available for signing or signature verification * @param {module:type/keyid} keyId, optional * @param {Date} date use the given date for verification instead of the current time - * @return {(module:packet/secret_subkey|module:packet/secret_key|null)} key packet or null if no signing key has been found + * @returns {(module:packet/secret_subkey|module:packet/secret_key|null)} key packet or null if no signing key has been found */ Key.prototype.getSigningKeyPacket = function (keyId=null, date=new Date()) { const primaryUser = this.getPrimaryUser(date); @@ -379,6 +379,7 @@ Key.prototype.getEncryptionKeyPacket = function(keyId, date=new Date()) { /** * Encrypts all secret key and subkey packets * @param {String} passphrase + * @returns {Promise} */ Key.prototype.encrypt = async function(passphrase) { if (!this.isPrivate()) { @@ -397,7 +398,7 @@ Key.prototype.encrypt = async function(passphrase) { /** * Decrypts all secret key and subkey packets * @param {String} passphrase - * @return {Promise} true if all key and subkey packets decrypted successfully + * @returns {Promise} true if all key and subkey packets decrypted successfully */ Key.prototype.decrypt = async function(passphrase) { if (!this.isPrivate()) { @@ -413,7 +414,7 @@ Key.prototype.decrypt = async function(passphrase) { * Decrypts specific key packets by key ID * @param {Array} keyIds * @param {String} passphrase - * @return {Boolean} true if all key packets decrypted successfully + * @returns {Boolean} true if all key packets decrypted successfully */ Key.prototype.decryptKeyPacket = function(keyIds, passphrase) { if (this.isPrivate()) { @@ -439,7 +440,7 @@ Key.prototype.decryptKeyPacket = function(keyIds, passphrase) { * Verify primary key. Checks for revocation signatures, expiration time * and valid self signature * @param {Date} date (optional) use the given date for verification instead of the current time - * @return {module:enums.keyStatus} The status of the primary key + * @returns {Promise{module:enums.keyStatus}} The status of the primary key */ Key.prototype.verifyPrimaryKey = async function(date=new Date()) { // TODO clarify OpenPGP's behavior given an expired revocation signature @@ -481,7 +482,7 @@ Key.prototype.verifyPrimaryKey = async function(date=new Date()) { /** * Returns the expiration time of the primary key or null if key does not expire - * @return {Date|null} + * @returns {Date|null} */ Key.prototype.getExpirationTime = function() { if (this.primaryKey.version === 3) { @@ -516,7 +517,7 @@ function getExpirationTime(keyPacket, selfCertificate, defaultValue=null) { * * NOTE: call verifyPrimaryUser before calling this function. * @param {Date} date use the given date for verification instead of the current time - * @return {{user: Array, selfCertificate: Array}|null} The primary user and the self signature + * @returns {{user: Array, selfCertificate: Array}|null} The primary user and the self signature */ Key.prototype.getPrimaryUser = function(date=new Date()) { let primaryUsers = []; @@ -649,7 +650,7 @@ Key.prototype.revoke = function() { /** * Signs primary user of key * @param {Array} privateKey decrypted private keys for signing - * @return {module:key~Key} new public key with new certificate signature + * @returns {Promise} new public key with new certificate signature */ Key.prototype.signPrimaryUser = async function(privateKeys) { await this.verifyPrimaryUser(); @@ -666,7 +667,7 @@ Key.prototype.signPrimaryUser = async function(privateKeys) { /** * Signs all users of key * @param {Array} privateKeys decrypted private keys for signing - * @return {module:key~Key} new public key with new certificate signature + * @returns {Promise} new public key with new certificate signature */ Key.prototype.signAllUsers = async function(privateKeys) { const that = this; @@ -682,7 +683,7 @@ Key.prototype.signAllUsers = async function(privateKeys) { * - if no arguments are given, verifies the self certificates; * - otherwise, verifies all certificates signed with given keys. * @param {Array} keys array of keys to verify certificate signatures - * @return {Array<({keyid: module:type/keyid, valid: Boolean})>} list of signer's keyid and validity of signature + * @returns {Promise>} list of signer's keyid and validity of signature */ Key.prototype.verifyPrimaryUser = async function(keys) { const { primaryKey } = this; @@ -732,7 +733,7 @@ Key.prototype.verifyPrimaryUser = async function(keys) { * - if no arguments are given, verifies the self certificates; * - otherwise, verifies all certificates signed with given keys. * @param {Array} keys array of keys to verify certificate signatures - * @return {Array<({userid: String, keyid: module:type/keyid, valid: Boolean})>} list of userid, signer's keyid and validity of signature + * @returns {Promise>} list of userid, signer's keyid and validity of signature */ Key.prototype.verifyAllUsers = async function(keys) { const results = []; @@ -768,7 +769,7 @@ function User(userPacket) { /** * Transforms structured user data to packetlist - * @return {module:packet/packetlist} + * @returns {module:packet/packetlist} */ User.prototype.toPacketlist = function() { const packetlist = new packet.List(); @@ -785,7 +786,7 @@ User.prototype.toPacketlist = function() { * @param {module:packet/signature} certificate The certificate to verify * @param {module:packet/public_subkey|module:packet/public_key| * module:packet/secret_subkey|module:packet/secret_key} key, optional The key to verify the signature - * @return {Boolean} True if the certificate is revoked + * @returns {Promise} True if the certificate is revoked */ User.prototype.isRevoked = async function(primaryKey, certificate, key) { certificate.revoked = null; @@ -807,7 +808,7 @@ User.prototype.isRevoked = async function(primaryKey, certificate, key) { * Signs user * @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet * @param {Array} privateKeys decrypted private keys for signing - * @return {module:key~Key} new user with new certificate signatures + * @returns {Promise} new user with new certificate signatures */ User.prototype.sign = async function(primaryKey, privateKeys) { const dataToSign = { userid: this.userId || this.userAttribute, key: primaryKey }; @@ -848,7 +849,7 @@ User.prototype.sign = async function(primaryKey, privateKeys) { * @param {module:packet/signature} certificate A certificate of this user * @param {Array} keys array of keys to verify certificate signatures * @param {Date} date use the given date for verification instead of the current time - * @return {module:enums.keyStatus} status of the certificate + * @returns {Promise} status of the certificate */ User.prototype.verifyCertificate = async function(primaryKey, certificate, keys, date=new Date()) { const that = this; @@ -876,7 +877,7 @@ User.prototype.verifyCertificate = async function(primaryKey, certificate, keys, * Verifies all user certificates * @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet * @param {Array} keys array of keys to verify certificate signatures - * @return {Array<({keyid: module:type/keyid, valid: Boolean})>} list of signer's keyid and validity of signature + * @returns {Promise>} list of signer's keyid and validity of signature */ User.prototype.verifyAllCertifications = async function(primaryKey, keys) { const that = this; @@ -894,7 +895,7 @@ User.prototype.verifyAllCertifications = async function(primaryKey, keys) { * Verify User. Checks for existence of self signatures, revocation signatures * and validity of self signature * @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet - * @return {module:enums.keyStatus} status of user + * @returns {Promise} status of user */ User.prototype.verify = async function(primaryKey) { if (!this.selfCertifications) { @@ -922,7 +923,7 @@ User.prototype.verify = async function(primaryKey) { /** * Update user with new components from specified user * @param {module:key~User} user source user to merge - * @param {module:packet/signature} primaryKey primary key used for validation + * @param {Promise} primaryKey primary key used for validation */ User.prototype.update = async function(user, primaryKey) { const dataToVerify = { userid: this.userId || this.userAttribute, key: primaryKey }; @@ -951,7 +952,7 @@ function SubKey(subKeyPacket) { /** * Transforms structured subkey data to packetlist - * @return {module:packet/packetlist} + * @returns {module:packet/packetlist} */ SubKey.prototype.toPacketlist = function() { const packetlist = new packet.List(); @@ -967,7 +968,7 @@ SubKey.prototype.toPacketlist = function() { * Returns true if the subkey can be used for encryption * @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet * @param {Date} date use the given date for verification instead of the current time - * @return {Boolean} + * @returns {Promise} */ SubKey.prototype.isValidEncryptionKey = async function(primaryKey, date=new Date()) { if (await this.verify(primaryKey, date) !== enums.keyStatus.valid) { @@ -985,7 +986,7 @@ SubKey.prototype.isValidEncryptionKey = async function(primaryKey, date=new Date * Returns true if the subkey can be used for signing of data * @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet * @param {Date} date use the given date for verification instead of the current time - * @return {Boolean} + * @returns {Promise} */ SubKey.prototype.isValidSigningKey = async function(primaryKey, date=new Date()) { if (await this.verify(primaryKey, date) !== enums.keyStatus.valid) { @@ -1004,7 +1005,7 @@ SubKey.prototype.isValidSigningKey = async function(primaryKey, date=new Date()) * and valid binding signature * @param {module:packet/secret_key|module:packet/public_key} primaryKey The primary key packet * @param {Date} date use the given date for verification instead of the current time - * @return {module:enums.keyStatus} The status of the subkey + * @returns {Promise} The status of the subkey */ SubKey.prototype.verify = async function(primaryKey, date=new Date()) { const that = this; @@ -1051,7 +1052,7 @@ SubKey.prototype.verify = async function(primaryKey, date=new Date()) { /** * Returns the expiration time of the subkey or null if key does not expire - * @return {Date|null} + * @returns {Date|null} */ SubKey.prototype.getExpirationTime = function() { let highest; @@ -1070,7 +1071,7 @@ SubKey.prototype.getExpirationTime = function() { /** * Update subkey with new components from specified subkey * @param {module:key~SubKey} subKey source subkey to merge - * @param {module:packet/signature} primaryKey primary key used for validation + * @param {Promise} primaryKey primary key used for validation */ SubKey.prototype.update = async function(subKey, primaryKey) { if (await subKey.verify(primaryKey) === enums.keyStatus.invalid) { @@ -1112,7 +1113,7 @@ SubKey.prototype.update = async function(subKey, primaryKey) { /** * Reads an unarmored OpenPGP key list and returns one or multiple key objects * @param {Uint8Array} data to be parsed - * @return {{keys: Array, err: (Array|null)}} result object with key and error arrays + * @returns {{keys: Array, err: (Array|null)}} result object with key and error arrays * @static */ export function read(data) { @@ -1145,7 +1146,7 @@ export function read(data) { /** * Reads an OpenPGP armored text and returns one or multiple key objects * @param {String} armoredText text to be parsed - * @return {{keys: Array, err: (Array|null)}} result object with key and error arrays + * @returns {{keys: Array, err: (Array|null)}} result object with key and error arrays * @static */ export function readArmored(armoredText) { @@ -1173,7 +1174,7 @@ export function readArmored(armoredText) { * @param {String} options.passphrase The passphrase used to encrypt the resulting private key * @param {Boolean} [options.unlocked=false] The secret part of the generated key is unlocked * @param {Number} [options.keyExpirationTime=0] The number of seconds after the key creation time that the key expires - * @return {module:key~Key} + * @returns {module:key~Key} * @static */ export function generate(options) { @@ -1248,7 +1249,7 @@ export function generate(options) { * @param {String} options.passphrase The passphrase used to encrypt the resulting private key * @param {Boolean} [options.unlocked=false] The secret part of the generated key is unlocked * @param {Number} [options.keyExpirationTime=0] The number of seconds after the key creation time that the key expires - * @return {module:key~Key} + * @returns {Promise} * @static */ export async function reformat(options) { @@ -1382,7 +1383,7 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPacket, options) { /** * Returns the preferred signature hash algorithm of a key * @param {object} key - * @return {String} + * @returns {String} */ export function getPreferredHashAlgo(key) { let hash_algo = config.prefer_hash_algorithm; @@ -1416,7 +1417,7 @@ export function getPreferredHashAlgo(key) { /** * Returns the preferred symmetric algorithm for a set of keys * @param {Array} keys Set of keys - * @return {enums.symmetric} Preferred symmetric algorithm + * @returns {enums.symmetric} Preferred symmetric algorithm */ export function getPreferredSymAlgo(keys) { const prioMap = {}; diff --git a/src/message.js b/src/message.js index 40788a4a..2c39b1e1 100644 --- a/src/message.js +++ b/src/message.js @@ -55,7 +55,7 @@ export function Message(packetlist) { /** * Returns the key IDs of the keys to which the session key is encrypted - * @return {Array} array of keyid objects + * @returns {Array} array of keyid objects */ Message.prototype.getEncryptionKeyIds = function() { const keyIds = []; @@ -68,7 +68,7 @@ Message.prototype.getEncryptionKeyIds = function() { /** * Returns the key IDs of the keys that signed the message - * @return {Array} array of keyid objects + * @returns {Array} array of keyid objects */ Message.prototype.getSigningKeyIds = function() { const keyIds = []; @@ -93,7 +93,7 @@ Message.prototype.getSigningKeyIds = function() { * @param {Array} privateKeys (optional) private keys with decrypted secret data * @param {Array} passwords (optional) passwords used to decrypt * @param {Array} sessionKeys (optional) session keys in the form: { data:Uint8Array, algorithm:String } - * @return {Message} new message with decrypted content + * @returns {Promise} new message with decrypted content */ Message.prototype.decrypt = async function(privateKeys, passwords, sessionKeys) { const keyObjs = sessionKeys || await this.decryptSessionKeys(privateKeys, passwords); @@ -105,7 +105,7 @@ Message.prototype.decrypt = async function(privateKeys, passwords, sessionKeys) ); if (symEncryptedPacketlist.length === 0) { - return; + return this; } const symEncryptedPacket = symEncryptedPacketlist[0]; @@ -138,74 +138,73 @@ Message.prototype.decrypt = async function(privateKeys, passwords, sessionKeys) * Decrypt encrypted session keys either with private keys or passwords. * @param {Array} privateKeys (optional) private keys with decrypted secret data * @param {Array} passwords (optional) passwords used to decrypt - * @return {Array<{ data:Uint8Array, algorithm:String }>} array of object with potential sessionKey, algorithm pairs + * @returns {Promise{Array<{ data:Uint8Array, algorithm:String }>}} array of object with potential sessionKey, algorithm pairs */ -Message.prototype.decryptSessionKeys = function(privateKeys, passwords) { +Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) { let keyPackets = []; - return Promise.resolve().then(async () => { - if (passwords) { - const symESKeyPacketlist = this.packets.filterByTag(enums.packet.symEncryptedSessionKey); - if (!symESKeyPacketlist) { - throw new Error('No symmetrically encrypted session key packet found.'); - } - await Promise.all(symESKeyPacketlist.map(async function(packet) { - await Promise.all(passwords.map(async function(password) { - try { - await packet.decrypt(password); - keyPackets.push(packet); - } catch (err) {} - })); - })); - } else if (privateKeys) { - const pkESKeyPacketlist = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); - if (!pkESKeyPacketlist) { - throw new Error('No public key encrypted session key packet found.'); - } - await Promise.all(pkESKeyPacketlist.map(async function(packet) { - const privateKeyPackets = privateKeys.reduce(function(acc, privateKey) { - return acc.concat(privateKey.getKeyPackets(packet.publicKeyId)); - }, []); - await Promise.all(privateKeyPackets.map(async function(privateKeyPacket) { - if (!privateKeyPacket) { - return; - } - if (!privateKeyPacket.isDecrypted) { - throw new Error('Private key is not decrypted.'); - } - try { - await packet.decrypt(privateKeyPacket); - keyPackets.push(packet); - } catch (err) {} - })); + if (passwords) { + const symESKeyPacketlist = this.packets.filterByTag(enums.packet.symEncryptedSessionKey); + if (!symESKeyPacketlist) { + throw new Error('No symmetrically encrypted session key packet found.'); + } + await Promise.all(symESKeyPacketlist.map(async function(packet) { + await Promise.all(passwords.map(async function(password) { + try { + await packet.decrypt(password); + keyPackets.push(packet); + } catch (err) {} })); - } else { - throw new Error('No key or password specified.'); - } - }).then(() => { - if (keyPackets.length) { - // Return only unique session keys - if (keyPackets.length > 1) { - const seen = {}; - keyPackets = keyPackets.filter(function(item) { - const k = item.sessionKeyAlgorithm + util.Uint8Array_to_str(item.sessionKey); - if (seen.hasOwnProperty(k)) { - return false; - } - seen[k] = true; - return true; - }); - } + })); - return keyPackets.map(packet => ({ data: packet.sessionKey, algorithm: packet.sessionKeyAlgorithm })); + } else if (privateKeys) { + const pkESKeyPacketlist = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); + if (!pkESKeyPacketlist) { + throw new Error('No public key encrypted session key packet found.'); } - throw new Error('Session key decryption failed.'); - }); + await Promise.all(pkESKeyPacketlist.map(async function(packet) { + const privateKeyPackets = privateKeys.reduce(function(acc, privateKey) { + return acc.concat(privateKey.getKeyPackets(packet.publicKeyId)); + }, []); + await Promise.all(privateKeyPackets.map(async function(privateKeyPacket) { + if (!privateKeyPacket) { + return; + } + if (!privateKeyPacket.isDecrypted) { + throw new Error('Private key is not decrypted.'); + } + try { + await packet.decrypt(privateKeyPacket); + keyPackets.push(packet); + } catch (err) {} + })); + })); + } else { + throw new Error('No key or password specified.'); + } + + if (keyPackets.length) { + // Return only unique session keys + if (keyPackets.length > 1) { + const seen = {}; + keyPackets = keyPackets.filter(function(item) { + const k = item.sessionKeyAlgorithm + util.Uint8Array_to_str(item.sessionKey); + if (seen.hasOwnProperty(k)) { + return false; + } + seen[k] = true; + return true; + }); + } + + return keyPackets.map(packet => ({ data: packet.sessionKey, algorithm: packet.sessionKeyAlgorithm })); + } + throw new Error('Session key decryption failed.'); }; /** * Get literal data that is the body of the message - * @return {(Uint8Array|null)} literal body of the message as Uint8Array + * @returns {(Uint8Array|null)} literal body of the message as Uint8Array */ Message.prototype.getLiteralData = function() { const literal = this.packets.findPacket(enums.packet.literal); @@ -214,7 +213,7 @@ Message.prototype.getLiteralData = function() { /** * Get filename from literal data packet - * @return {(String|null)} filename of literal data packet as string + * @returns {(String|null)} filename of literal data packet as string */ Message.prototype.getFilename = function() { const literal = this.packets.findPacket(enums.packet.literal); @@ -223,7 +222,7 @@ Message.prototype.getFilename = function() { /** * Get literal data as text - * @return {(String|null)} literal body of the message interpreted as text + * @returns {(String|null)} literal body of the message interpreted as text */ Message.prototype.getText = function() { const literal = this.packets.findPacket(enums.packet.literal); @@ -240,54 +239,52 @@ Message.prototype.getText = function() { * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String } * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs * @param {Date} date (optional) override the creation date of the literal package - * @return {Message} new message with encrypted content + * @returns {Promise} new message with encrypted content */ -Message.prototype.encrypt = function(keys, passwords, sessionKey, wildcard=false, date=new Date()) { +Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard=false, date=new Date()) { let symAlgo; - let msg; let symEncryptedPacket; - return Promise.resolve().then(async () => { - if (sessionKey) { - if (!util.isUint8Array(sessionKey.data) || !util.isString(sessionKey.algorithm)) { - throw new Error('Invalid session key for encryption.'); - } - symAlgo = sessionKey.algorithm; - sessionKey = sessionKey.data; - } else if (keys && keys.length) { - symAlgo = enums.read(enums.symmetric, getPreferredSymAlgo(keys)); - } else if (passwords && passwords.length) { - symAlgo = enums.read(enums.symmetric, config.encryption_cipher); - } else { - throw new Error('No keys, passwords, or session key provided.'); + + if (sessionKey) { + if (!util.isUint8Array(sessionKey.data) || !util.isString(sessionKey.algorithm)) { + throw new Error('Invalid session key for encryption.'); } + symAlgo = sessionKey.algorithm; + sessionKey = sessionKey.data; + } else if (keys && keys.length) { + symAlgo = enums.read(enums.symmetric, getPreferredSymAlgo(keys)); + } else if (passwords && passwords.length) { + symAlgo = enums.read(enums.symmetric, config.encryption_cipher); + } else { + throw new Error('No keys, passwords, or session key provided.'); + } - if (!sessionKey) { - sessionKey = await crypto.generateSessionKey(symAlgo); + if (!sessionKey) { + sessionKey = await crypto.generateSessionKey(symAlgo); + } + + const msg = await encryptSessionKey(sessionKey, symAlgo, keys, passwords, wildcard, date); + + if (config.aead_protect) { + symEncryptedPacket = new packet.SymEncryptedAEADProtected(); + } else if (config.integrity_protect) { + symEncryptedPacket = new packet.SymEncryptedIntegrityProtected(); + } else { + symEncryptedPacket = new packet.SymmetricallyEncrypted(); + } + symEncryptedPacket.packets = this.packets; + + await symEncryptedPacket.encrypt(symAlgo, sessionKey); + + msg.packets.push(symEncryptedPacket); + symEncryptedPacket.packets = new packet.List(); // remove packets after encryption + return { + message: msg, + sessionKey: { + data: sessionKey, + algorithm: symAlgo } - - msg = await encryptSessionKey(sessionKey, symAlgo, keys, passwords, wildcard, date); - - if (config.aead_protect) { - symEncryptedPacket = new packet.SymEncryptedAEADProtected(); - } else if (config.integrity_protect) { - symEncryptedPacket = new packet.SymEncryptedIntegrityProtected(); - } else { - symEncryptedPacket = new packet.SymmetricallyEncrypted(); - } - symEncryptedPacket.packets = this.packets; - - return symEncryptedPacket.encrypt(symAlgo, sessionKey); - }).then(() => { - msg.packets.push(symEncryptedPacket); - symEncryptedPacket.packets = new packet.List(); // remove packets after encryption - return { - message: msg, - sessionKey: { - data: sessionKey, - algorithm: symAlgo - } - }; - }); + }; }; /** @@ -298,64 +295,64 @@ Message.prototype.encrypt = function(keys, passwords, sessionKey, wildcard=false * @param {Array} passwords (optional) for message encryption * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs * @param {Date} date (optional) override the creation date signature - * @return {Message} new message with encrypted content + * @returns {Promise} new message with encrypted content */ -export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, wildcard=false, date=new Date()) { +export async function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, wildcard=false, date=new Date()) { const packetlist = new packet.List(); - return Promise.resolve().then(async () => { - if (publicKeys) { - const results = await Promise.all(publicKeys.map(async function(key) { - await key.verifyPrimaryUser(); - const encryptionKeyPacket = key.getEncryptionKeyPacket(undefined, date); - if (!encryptionKeyPacket) { - throw new Error('Could not find valid key packet for encryption in key ' + key.primaryKey.getKeyId().toHex()); + if (publicKeys) { + const results = await Promise.all(publicKeys.map(async function(key) { + await key.verifyPrimaryUser(); + const encryptionKeyPacket = key.getEncryptionKeyPacket(undefined, date); + if (!encryptionKeyPacket) { + throw new Error('Could not find valid key packet for encryption in key ' + key.primaryKey.getKeyId().toHex()); + } + const pkESKeyPacket = new packet.PublicKeyEncryptedSessionKey(); + pkESKeyPacket.publicKeyId = wildcard ? type_keyid.wildcard() : encryptionKeyPacket.getKeyId(); + pkESKeyPacket.publicKeyAlgorithm = encryptionKeyPacket.algorithm; + pkESKeyPacket.sessionKey = sessionKey; + pkESKeyPacket.sessionKeyAlgorithm = symAlgo; + await pkESKeyPacket.encrypt(encryptionKeyPacket); + delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption + return pkESKeyPacket; + })); + packetlist.concat(results); + } + + if (passwords) { + const testDecrypt = async function(keyPacket, password) { + try { + await keyPacket.decrypt(password); + return 1; + } catch (e) { + return 0; + } + }; + + const sum = (accumulator, currentValue) => accumulator + currentValue; + + const encryptPassword = async function(sessionKey, symAlgo, password) { + const symEncryptedSessionKeyPacket = new packet.SymEncryptedSessionKey(); + symEncryptedSessionKeyPacket.sessionKey = sessionKey; + symEncryptedSessionKeyPacket.sessionKeyAlgorithm = symAlgo; + await symEncryptedSessionKeyPacket.encrypt(password); + + if (config.password_collision_check) { + const results = await Promise.all(passwords.map(pwd => testDecrypt(symEncryptedSessionKeyPacket, pwd))); + if (results.reduce(sum) !== 1) { + return encryptPassword(sessionKey, symAlgo, password); } - const pkESKeyPacket = new packet.PublicKeyEncryptedSessionKey(); - pkESKeyPacket.publicKeyId = wildcard ? type_keyid.wildcard() : encryptionKeyPacket.getKeyId(); - pkESKeyPacket.publicKeyAlgorithm = encryptionKeyPacket.algorithm; - pkESKeyPacket.sessionKey = sessionKey; - pkESKeyPacket.sessionKeyAlgorithm = symAlgo; - await pkESKeyPacket.encrypt(encryptionKeyPacket); - delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption - return pkESKeyPacket; - })); - packetlist.concat(results); - } + } - if (passwords) { - const testDecrypt = async function(keyPacket, password) { - try { - await keyPacket.decrypt(password); - return 1; - } catch (e) { - return 0; - } - }; + delete symEncryptedSessionKeyPacket.sessionKey; // delete plaintext session key after encryption + return symEncryptedSessionKeyPacket; + }; - const sum = (accumulator, currentValue) => accumulator + currentValue; + const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, symAlgo, pwd))); + packetlist.concat(results); + } - const encryptPassword = async function(sessionKey, symAlgo, password) { - const symEncryptedSessionKeyPacket = new packet.SymEncryptedSessionKey(); - symEncryptedSessionKeyPacket.sessionKey = sessionKey; - symEncryptedSessionKeyPacket.sessionKeyAlgorithm = symAlgo; - await symEncryptedSessionKeyPacket.encrypt(password); - - if (config.password_collision_check) { - const results = await Promise.all(passwords.map(pwd => testDecrypt(symEncryptedSessionKeyPacket, pwd))); - if (results.reduce(sum) !== 1) { - return encryptPassword(sessionKey, symAlgo, password); - } - } - - delete symEncryptedSessionKeyPacket.sessionKey; // delete plaintext session key after encryption - return symEncryptedSessionKeyPacket; - }; - - const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, symAlgo, pwd))); - packetlist.concat(results); - } - }).then(() => new Message(packetlist)); + return new Message(packetlist); } /** @@ -363,7 +360,7 @@ export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, wi * @param {Array} privateKeys private keys with decrypted secret key data for signing * @param {Signature} signature (optional) any existing detached signature to add to the message * @param {Date} date} (optional) override the creation time of the signature - * @return {module:message~Message} new message with signed content + * @returns {Promise} new message with signed content */ Message.prototype.sign = async function(privateKeys=[], signature=null, date=new Date()) { const packetlist = new packet.List(); @@ -427,7 +424,7 @@ Message.prototype.sign = async function(privateKeys=[], signature=null, date=new /** * Compresses the message (the literal and -if signed- signature data packets of the message) * @param {module:enums.compression} compression compression algorithm to be used - * @return {module:message~Message} new message with compressed content + * @returns {module:message~Message} new message with compressed content */ Message.prototype.compress = function(compression) { if (compression === enums.compression.uncompressed) { @@ -446,10 +443,10 @@ Message.prototype.compress = function(compression) { /** * Create a detached signature for the message (the literal data packet of the message) - * @param {Array} privateKeys private keys with decrypted secret key data for signing - * @param {Signature} signature (optional) any existing detached signature - * @param {Date} date (optional) override the creation time of the signature - * @return {module:signature~Signature} new detached signature of message content + * @param {Array} privateKeys private keys with decrypted secret key data for signing + * @param {Signature} signature (optional) any existing detached signature + * @param {Date} date (optional) override the creation time of the signature + * @returns {Promise} new detached signature of message content */ Message.prototype.signDetached = async function(privateKeys=[], signature=null, date=new Date()) { const literalDataPacket = this.packets.findPacket(enums.packet.literal); @@ -461,11 +458,11 @@ Message.prototype.signDetached = async function(privateKeys=[], signature=null, /** * Create signature packets for the message - * @param {module:packet/literal} literalDataPacket the literal data packet to sign - * @param {Array} privateKeys private keys with decrypted secret key data for signing - * @param {Signature} signature (optional) any existing detached signature to append - * @param {Date} date (optional) override the creationtime of the signature - * @return {module:packet/packetlist} list of signature packets + * @param {module:packet/literal} literalDataPacket the literal data packet to sign + * @param {Array} privateKeys private keys with decrypted secret key data for signing + * @param {Signature} signature (optional) any existing detached signature to append + * @param {Date} date (optional) override the creationtime of the signature + * @returns {Promise} list of signature packets */ export async function createSignaturePackets(literalDataPacket, privateKeys, signature=null, date=new Date()) { const packetlist = new packet.List(); @@ -507,7 +504,7 @@ export async function createSignaturePackets(literalDataPacket, privateKeys, sig * Verify message signatures * @param {Array} keys array of keys to verify signatures * @param {Date} date (optional) Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @return {Array<({keyid: module:type/keyid, valid: Boolean})>} list of signer's keyid and validity of signature + * @returns {Array<({keyid: module:type/keyid, valid: Boolean})>} list of signer's keyid and validity of signature */ Message.prototype.verify = function(keys, date=new Date()) { const msg = this.unwrapCompressed(); @@ -524,7 +521,7 @@ Message.prototype.verify = function(keys, date=new Date()) { * @param {Array} keys array of keys to verify signatures * @param {Signature} signature * @param {Date} date Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @return {Array<({keyid: module:type/keyid, valid: Boolean})>} list of signer's keyid and validity of signature + * @returns {Array<({keyid: module:type/keyid, valid: Boolean})>} list of signer's keyid and validity of signature */ Message.prototype.verifyDetached = function(signature, keys, date=new Date()) { const msg = this.unwrapCompressed(); @@ -542,7 +539,7 @@ Message.prototype.verifyDetached = function(signature, keys, date=new Date()) { * @param {Array} literalDataList array of literal data packets * @param {Array} keys array of keys to verify signatures * @param {Date} date Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @return {Array<({keyid: module:type/keyid, valid: Boolean})>} list of signer's keyid and validity of signature + * @returns {Promise{Array<({keyid: module:type/keyid, valid: Boolean})>}} list of signer's keyid and validity of signature */ export async function createVerificationObjects(signatureList, literalDataList, keys, date=new Date()) { return Promise.all(signatureList.map(async function(signature) { @@ -572,7 +569,7 @@ export async function createVerificationObjects(signatureList, literalDataList, /** * Unwrap compressed message - * @return {module:message~Message} message Content of compressed message + * @returns {module:message~Message} message Content of compressed message */ Message.prototype.unwrapCompressed = function() { const compressed = this.packets.filterByTag(enums.packet.compressed); @@ -592,7 +589,7 @@ Message.prototype.appendSignature = function(detachedSignature) { /** * Returns ASCII armored text of message - * @return {String} ASCII armor + * @returns {String} ASCII armor */ Message.prototype.armor = function() { return armor.encode(enums.armor.message, this.packets.write()); @@ -601,7 +598,7 @@ Message.prototype.armor = function() { /** * reads an OpenPGP armored message and returns a message object * @param {String} armoredText text to be parsed - * @return {module:message~Message} new message object + * @returns {module:message~Message} new message object * @static */ export function readArmored(armoredText) { @@ -614,7 +611,7 @@ export function readArmored(armoredText) { /** * reads an OpenPGP message as byte array and returns a message object * @param {Uint8Array} input binary message - * @return {Message} new message object + * @returns {Message} new message object * @static */ export function read(input) { @@ -628,7 +625,7 @@ export function read(input) { * @param {String} text * @param {String} filename (optional) * @param {Date} date (optional) - * @return {module:message~Message} new message object + * @returns {module:message~Message} new message object * @static */ export function fromText(text, filename, date=new Date()) { @@ -648,7 +645,7 @@ export function fromText(text, filename, date=new Date()) { * @param {Uint8Array} bytes * @param {String} filename (optional) * @param {Date} date (optional) - * @return {module:message~Message} new message object + * @returns {module:message~Message} new message object * @static */ export function fromBinary(bytes, filename, date=new Date()) { diff --git a/src/openpgp.js b/src/openpgp.js index e7c9c64e..4f73229a 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -68,7 +68,7 @@ export function initWorker({ path='openpgp.worker.js', n = 1, workers = [] } = { /** * Returns a reference to the async proxy if the worker was initialized with openpgp.initWorker() - * @return {module:worker/async_proxy~AsyncProxy|null} the async proxy or null if not initialized + * @returns {module:worker/async_proxy~AsyncProxy|null} the async proxy or null if not initialized */ export function getWorker() { return asyncProxy; @@ -97,7 +97,7 @@ export function destroyWorker() { * @param {String} curve (optional) elliptic curve for ECC keys: curve25519, p256, p384, p521, or secp256k1 * @param {Boolean} unlocked (optional) If the returned secret part of the generated key is unlocked * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires - * @return {Promise} The generated key object in the form: + * @returns {Promise} The generated key object in the form: * { key:Key, privateKeyArmored:String, publicKeyArmored:String } * @static */ @@ -134,7 +134,7 @@ export function generateKey({ * @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key * @param {Boolean} unlocked (optional) If the returned secret part of the generated key is unlocked * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires - * @return {Promise} The generated key object in the form: + * @returns {Promise} The generated key object in the form: * { key:Key, privateKeyArmored:String, publicKeyArmored:String } * @static */ @@ -164,7 +164,7 @@ export function reformatKey({ * Unlock a private key with your passphrase. * @param {Key} privateKey the private key that is to be decrypted * @param {String} passphrase the user's passphrase chosen during key generation - * @return {Key} the unlocked private key + * @returns {Promise} the unlocked key object in the form: { key:Key } */ export function decryptKey({ privateKey, passphrase }) { if (asyncProxy) { // use web worker if available @@ -184,7 +184,7 @@ export function decryptKey({ privateKey, passphrase }) { * Lock a private key with your passphrase. * @param {Key} privateKey the private key that is to be decrypted * @param {String} passphrase the user's passphrase chosen during key generation - * @return {Key} the locked private key + * @returns {Promise} the locked key object in the form: { key:Key } */ export function encryptKey({ privateKey, passphrase }) { if (asyncProxy) { // use web worker if available @@ -224,7 +224,7 @@ export function encryptKey({ privateKey, passphrase }) { * @param {Boolean} returnSessionKey (optional) if the unencrypted session key should be added to returned object * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs * @param {Date} date (optional) override the creation date of the message and the message signature - * @return {Promise} encrypted (and optionally signed message) in the form: + * @returns {Promise} encrypted (and optionally signed message) in the form: * {data: ASCII armored message if 'armor' is true, * message: full Message object if 'armor' is false, signature: detached signature if 'detached' is true} * @static @@ -276,7 +276,7 @@ export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey, * @param {String} format (optional) return data format either as 'utf8' or 'binary' * @param {Signature} signature (optional) detached signature for verification * @param {Date} date (optional) use the given date for verification instead of the current time - * @return {Promise} decrypted and verified message in the form: + * @returns {Promise} decrypted and verified message in the form: * { data:Uint8Array|String, filename:String, signatures:[{ keyid:String, valid:Boolean }] } * @static */ @@ -315,7 +315,7 @@ export function decrypt({ message, privateKeys, passwords, sessionKeys, publicKe * @param {Boolean} armor (optional) if the return value should be ascii armored or the message object * @param {Boolean} detached (optional) if the return value should contain a detached signature * @param {Date} date (optional) override the creation date signature - * @return {Promise} signed cleartext in the form: + * @returns {Promise} signed cleartext in the form: * {data: ASCII armored message if 'armor' is true, * message: full Message object if 'armor' is false, signature: detached signature if 'detached' is true} * @static @@ -357,7 +357,7 @@ export function sign({ * @param {CleartextMessage} message cleartext message object with signatures * @param {Signature} signature (optional) detached signature for verification * @param {Date} date (optional) use the given date for verification instead of the current time - * @return {Promise} cleartext with status of verified signatures in the form of: + * @returns {Promise} cleartext with status of verified signatures in the form of: * { data:String, signatures: [{ keyid:String, valid:Boolean }] } * @static */ @@ -393,7 +393,7 @@ export function verify({ message, publicKeys, signature=null, date=new Date() }) * @param {Key|Array} publicKeys (optional) array of public keys or single key, used to encrypt the key * @param {String|Array} passwords (optional) passwords for the message * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs - * @return {Promise} the encrypted session key packets contained in a message object + * @returns {Promise} the encrypted session key packets contained in a message object * @static */ export function encryptSessionKey({ data, algorithm, publicKeys, passwords, wildcard=false }) { @@ -416,7 +416,7 @@ export function encryptSessionKey({ data, algorithm, publicKeys, passwords, wild * @param {Message} message a message object containing the encrypted session key packets * @param {Key|Array} privateKeys (optional) private keys with decrypted secret key data * @param {String|Array} passwords (optional) passwords to decrypt the session key - * @return {Promise} Array of decrypted session key, algorithm pairs in form: + * @returns {Promise} Array of decrypted session key, algorithm pairs in form: * { data:Uint8Array, algorithm:String } * or 'undefined' if no key packets found * @static @@ -505,7 +505,7 @@ function formatUserIds(userIds) { /** * Normalize parameter to an array if it is not undefined. * @param {Object} param the parameter to be normalized - * @return {Array|undefined} the resulting array or undefined + * @returns {Array|undefined} the resulting array or undefined */ function toArray(param) { if (param && !util.isArray(param)) { @@ -519,7 +519,7 @@ function toArray(param) { * @param {String|Uint8Array} data the payload for the message * @param {String} filename the literal data packet's filename * @param {Date} date the creation date of the package - * @return {Message} a message object + * @returns {Message} a message object */ function createMessage(data, filename, date=new Date()) { let msg; @@ -537,7 +537,7 @@ function createMessage(data, filename, date=new Date()) { * Parse the message given a certain format. * @param {Message} message the message object to be parse * @param {String} format the output format e.g. 'utf8' or 'binary' - * @return {Object} the parse data in the respective format + * @returns {Object} the parse data in the respective format */ function parseMessage(message, format) { if (format === 'binary') { @@ -572,7 +572,7 @@ function onError(message, error) { /** * Check for AES-GCM support and configuration by the user. Only browsers that * implement the current WebCrypto specification support native AES-GCM. - * @return {Boolean} If authenticated encryption should be used + * @returns {Boolean} If authenticated encryption should be used */ function nativeAEAD() { return util.getWebCrypto() && config.aead_protect; diff --git a/src/packet/packetlist.js b/src/packet/packetlist.js index 41946213..35c561c7 100644 --- a/src/packet/packetlist.js +++ b/src/packet/packetlist.js @@ -91,7 +91,7 @@ Packetlist.prototype.push = function (packet) { /** * Remove a packet from the list and return it. - * @return {Object} The packet that was removed + * @returns {Object} The packet that was removed */ Packetlist.prototype.pop = function() { if (this.length === 0) { @@ -164,6 +164,8 @@ Packetlist.prototype.map = function (callback) { /** * Executes the callback function once for each element * until it finds one where callback returns a truthy value +* @param {Function} callback +* @returns {Promise} */ Packetlist.prototype.some = async function (callback) { for (let i = 0; i < this.length; i++) { @@ -178,7 +180,7 @@ Packetlist.prototype.some = async function (callback) { /** * Traverses packet tree and returns first matching packet * @param {module:enums.packet} type The packet type - * @return {module:packet/packet|null} + * @returns {module:packet/packet|null} */ Packetlist.prototype.findPacket = function (type) { const packetlist = this.filterByTag(type); diff --git a/src/packet/public_key_encrypted_session_key.js b/src/packet/public_key_encrypted_session_key.js index a14a67cb..23a90fdb 100644 --- a/src/packet/public_key_encrypted_session_key.js +++ b/src/packet/public_key_encrypted_session_key.js @@ -67,7 +67,7 @@ export default function PublicKeyEncryptedSessionKey() { * @param {Integer} position Position to start reading from the input string * @param {Integer} len Length of the packet or the remaining length of * input at position - * @return {module:packet/public_key_encrypted_session_key} Object representation + * @returns {module:packet/public_key_encrypted_session_key} Object representation */ PublicKeyEncryptedSessionKey.prototype.read = function (bytes) { this.version = bytes[0]; @@ -88,7 +88,7 @@ PublicKeyEncryptedSessionKey.prototype.read = function (bytes) { /** * Create a string representation of a tag 1 packet * - * @return {Uint8Array} The Uint8Array representation + * @returns {Uint8Array} The Uint8Array representation */ PublicKeyEncryptedSessionKey.prototype.write = function () { const arr = [new Uint8Array([this.version]), this.publicKeyId.write(), new Uint8Array([enums.write(enums.publicKey, this.publicKeyAlgorithm)])]; @@ -100,6 +100,11 @@ PublicKeyEncryptedSessionKey.prototype.write = function () { return util.concatUint8Array(arr); }; +/** + * Encrypt session key packet + * @param {module:packet/public_key} key Public key + * @returns {Promise} + */ PublicKeyEncryptedSessionKey.prototype.encrypt = async function (key) { let data = String.fromCharCode(enums.write(enums.symmetric, this.sessionKeyAlgorithm)); @@ -117,6 +122,7 @@ PublicKeyEncryptedSessionKey.prototype.encrypt = async function (key) { this.encrypted = await crypto.publicKeyEncrypt( algo, key.params, toEncrypt, key.fingerprint); + return true; }; /** @@ -125,7 +131,7 @@ PublicKeyEncryptedSessionKey.prototype.encrypt = async function (key) { * * @param {module:packet/secret_key} key * Private key with secret params unlocked - * @return {String} The unencrypted session key + * @returns {Promise} */ PublicKeyEncryptedSessionKey.prototype.decrypt = async function (key) { const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm); @@ -150,6 +156,7 @@ PublicKeyEncryptedSessionKey.prototype.decrypt = async function (key) { this.sessionKey = key; this.sessionKeyAlgorithm = enums.read(enums.symmetric, decoded.charCodeAt(0)); } + return true; }; /** diff --git a/src/packet/secret_key.js b/src/packet/secret_key.js index e7046f52..13fd624d 100644 --- a/src/packet/secret_key.js +++ b/src/packet/secret_key.js @@ -151,7 +151,7 @@ SecretKey.prototype.read = function (bytes) { }; /** Creates an OpenPGP key packet for the given key. - * @return {String} A string of bytes containing the secret key OpenPGP packet + * @returns {String} A string of bytes containing the secret key OpenPGP packet */ SecretKey.prototype.write = function () { const arr = [this.writePublicKey()]; @@ -172,11 +172,12 @@ SecretKey.prototype.write = function () { * and the passphrase is empty or undefined, the key will be set as not encrypted. * This can be used to remove passphrase protection after calling decrypt(). * @param {String} passphrase + * @returns {Promise} */ SecretKey.prototype.encrypt = async function (passphrase) { if (this.isDecrypted && !passphrase) { this.encrypted = null; - return; + return false; } else if (!passphrase) { throw new Error('The key must be decrypted before removing passphrase protection.'); } @@ -195,6 +196,7 @@ SecretKey.prototype.encrypt = async function (passphrase) { arr.push(crypto.cfb.normalEncrypt(symmetric, key, cleartext, iv)); this.encrypted = util.concatUint8Array(arr); + return true; }; function produceEncryptionKey(s2k, passphrase, algorithm) { @@ -209,10 +211,8 @@ function produceEncryptionKey(s2k, passphrase, algorithm) { * @link module:packet/secret_key.isDecrypted should be * false otherwise a call to this function is not needed * - * @param {String} str_passphrase The passphrase for this private key - * as string - * @return {Boolean} True if the passphrase was correct or param already - * decrypted; false if not + * @param {String} passphrase The passphrase for this private key as string + * @returns {Promise} */ SecretKey.prototype.decrypt = async function (passphrase) { if (this.isDecrypted) { @@ -267,6 +267,8 @@ SecretKey.prototype.decrypt = async function (passphrase) { this.params = this.params.concat(privParams); this.isDecrypted = true; this.encrypted = null; + + return true; }; SecretKey.prototype.generate = function (bits, curve) { diff --git a/src/packet/signature.js b/src/packet/signature.js index b1449a17..4e0fd88d 100644 --- a/src/packet/signature.js +++ b/src/packet/signature.js @@ -211,6 +211,7 @@ Signature.prototype.write = function () { * Signs provided data. This needs to be done prior to serialization. * @param {module:packet/secret_key} key private key used to sign the message. * @param {Object} data Contains packets to be signed. + * @returns {Promise} */ Signature.prototype.sign = async function (key, data) { const signatureType = enums.write(enums.signature, this.signatureType); @@ -247,6 +248,7 @@ Signature.prototype.sign = async function (key, data) { this.signature = await crypto.signature.sign( publicKeyAlgorithm, hashAlgorithm, key.params, toHash ); + return true; }; /** @@ -615,7 +617,7 @@ Signature.prototype.calculateTrailer = function () { * @param {String|Object} data data which on the signature applies * @param {module:packet/public_subkey|module:packet/public_key| * module:packet/secret_subkey|module:packet/secret_key} key the public key to verify the signature - * @return {boolean} True if message is verified, else false. + * @return {Promise} True if message is verified, else false. */ Signature.prototype.verify = async function (key, data) { const signatureType = enums.write(enums.signature, this.signatureType); diff --git a/src/packet/sym_encrypted_aead_protected.js b/src/packet/sym_encrypted_aead_protected.js index a6fbe934..af469913 100644 --- a/src/packet/sym_encrypted_aead_protected.js +++ b/src/packet/sym_encrypted_aead_protected.js @@ -64,19 +64,21 @@ SymEncryptedAEADProtected.prototype.write = function () { * Decrypt the encrypted payload. * @param {String} sessionKeyAlgorithm The session key's cipher algorithm e.g. 'aes128' * @param {Uint8Array} key The session key used to encrypt the payload - * @return {Promise} Nothing is returned + * @return {Promise} */ SymEncryptedAEADProtected.prototype.decrypt = async function (sessionKeyAlgorithm, key) { this.packets.read(await crypto.gcm.decrypt(sessionKeyAlgorithm, this.encrypted, key, this.iv)); + return true; }; /** * Encrypt the packet list payload. * @param {String} sessionKeyAlgorithm The session key's cipher algorithm e.g. 'aes128' * @param {Uint8Array} key The session key used to encrypt the payload - * @return {Promise} Nothing is returned + * @return {Promise} */ SymEncryptedAEADProtected.prototype.encrypt = async function (sessionKeyAlgorithm, key) { this.iv = await crypto.random.getRandomBytes(IV_LEN); // generate new random IV this.encrypted = await crypto.gcm.encrypt(sessionKeyAlgorithm, this.packets.write(), key, this.iv); + return true; }; diff --git a/src/packet/sym_encrypted_integrity_protected.js b/src/packet/sym_encrypted_integrity_protected.js index 6b8c7c29..335dfd5b 100644 --- a/src/packet/sym_encrypted_integrity_protected.js +++ b/src/packet/sym_encrypted_integrity_protected.js @@ -79,7 +79,7 @@ SymEncryptedIntegrityProtected.prototype.write = function () { * Encrypt the payload in the packet. * @param {String} sessionKeyAlgorithm The selected symmetric encryption algorithm to be used e.g. 'aes128' * @param {Uint8Array} key The key of cipher blocksize length to be used - * @return {Promise} + * @return {Promise} */ SymEncryptedIntegrityProtected.prototype.encrypt = async function (sessionKeyAlgorithm, key) { const bytes = this.packets.write(); @@ -98,13 +98,14 @@ SymEncryptedIntegrityProtected.prototype.encrypt = async function (sessionKeyAlg this.encrypted = crypto.cfb.encrypt(prefixrandom, sessionKeyAlgorithm, tohash, key, false); this.encrypted = this.encrypted.subarray(0, prefix.length + tohash.length); } + return true; }; /** * Decrypts the encrypted data contained in the packet. * @param {String} sessionKeyAlgorithm The selected symmetric encryption algorithm to be used e.g. 'aes128' * @param {Uint8Array} key The key of cipher blocksize length to be used - * @return {Promise} + * @return {Promise} */ SymEncryptedIntegrityProtected.prototype.decrypt = async function (sessionKeyAlgorithm, key) { let decrypted; diff --git a/src/packet/sym_encrypted_session_key.js b/src/packet/sym_encrypted_session_key.js index 248b13cc..3884f072 100644 --- a/src/packet/sym_encrypted_session_key.js +++ b/src/packet/sym_encrypted_session_key.js @@ -102,10 +102,9 @@ SymEncryptedSessionKey.prototype.write = function() { }; /** - * Decrypts the session key (only for public key encrypted session key - * packets (tag 1) - * - * @return {Uint8Array} The unencrypted session key + * Decrypts the session key + * @param {String} passphrase The passphrase in string form + * @return {Promise} */ SymmetricallyEncrypted.prototype.decrypt = async function (sessionKeyAlgorithm, key) { const decrypted = crypto.cfb.decrypt(sessionKeyAlgorithm, key, this.encrypted, true); @@ -73,13 +71,20 @@ SymmetricallyEncrypted.prototype.decrypt = async function (sessionKeyAlgorithm, } this.packets.read(decrypted); - return Promise.resolve(); + return true; }; +/** + * Encrypt the symmetrically-encrypted packet data + * @param {module:enums.symmetric} sessionKeyAlgorithm + * Symmetric key algorithm to use // See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880 9.2} + * @param {Uint8Array} key The key of cipher blocksize length to be used + * @returns {Promise} + */ SymmetricallyEncrypted.prototype.encrypt = async function (algo, key) { const data = this.packets.write(); this.encrypted = crypto.cfb.encrypt(await crypto.getPrefixRandom(algo), algo, data, key, true); - return Promise.resolve(); + return true; }; diff --git a/src/worker/async_proxy.js b/src/worker/async_proxy.js index d44f87e4..2d8469bb 100644 --- a/src/worker/async_proxy.js +++ b/src/worker/async_proxy.js @@ -22,7 +22,7 @@ import packet from '../packet'; /** * Message handling */ -function handleMessage(id) { +function handleMessage(workerId) { return function(event) { const msg = event.data; switch (msg.event) { @@ -38,10 +38,10 @@ function handleMessage(id) { this.tasks[msg.id].resolve(msg.data); } delete this.tasks[msg.id]; - this.workers[id].requests--; + this.workers[workerId].requests--; break; case 'request-seed': - this.seedRandom(id, msg.amount); + this.seedRandom(workerId, msg.amount); break; default: throw new Error('Unknown Worker Event.'); @@ -53,10 +53,9 @@ function handleMessage(id) { * Initializes a new proxy and loads the web worker * @constructor * @param {String} path The path to the worker or 'openpgp.worker.js' by default - * @param {Number} n number of workers to initialize + * @param {Number} n number of workers to initialize if path given * @param {Object} config config The worker configuration * @param {Array} worker alternative to path parameter: web worker initialized with 'openpgp.worker.js' - * @return {Promise} */ export default function AsyncProxy({ path='openpgp.worker.js', n = 1, workers = [], config } = {}) { @@ -100,9 +99,9 @@ AsyncProxy.prototype.getID = function() { * Send message to worker with random data * @param {Integer} size Number of bytes to send */ -AsyncProxy.prototype.seedRandom = async function(id, size) { +AsyncProxy.prototype.seedRandom = async function(workerId, size) { const buf = await crypto.random.getRandomBytes(size); - this.workers[id].postMessage({ event:'seed-random', buf }, util.getTransferables(buf)); + this.workers[workerId].postMessage({ event:'seed-random', buf }, util.getTransferables(buf)); }; /**