From e5e49901a7316254486737d7452a09e585247a32 Mon Sep 17 00:00:00 2001 From: Sanjana Rajan Date: Thu, 8 Feb 2018 12:30:34 +0100 Subject: [PATCH 1/6] change var names --- src/message.js | 22 +++++++++++----------- src/openpgp.js | 21 +++++++++++---------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/message.js b/src/message.js index 10073ae2..2036710c 100644 --- a/src/message.js +++ b/src/message.js @@ -91,13 +91,13 @@ Message.prototype.getSigningKeyIds = function() { /** * Decrypt the message. Either a private key, a session key, or a password must be specified. - * @param {Key} privateKey (optional) private key with decrypted secret data - * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String } - * @param {String} password (optional) password used to decrypt + * @param {Array} privateKeys (optional) private key with decrypted secret data + * @param {Array} passwords (optional) password used to decrypt + * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String } * @return {Message} new message with decrypted content */ -Message.prototype.decrypt = async function(privateKey, sessionKey, password) { - let keyObjs = sessionKey || await this.decryptSessionKeys(privateKey, password); +Message.prototype.decrypt = async function(privateKeys, passwords, sessionKey) { + let keyObjs = sessionKey || await this.decryptSessionKeys(privateKeys, passwords); if (!util.isArray(keyObjs)) { keyObjs = [keyObjs]; } @@ -140,15 +140,15 @@ Message.prototype.decrypt = async function(privateKey, sessionKey, password) { }; /** - * Decrypt an encrypted session key either with a private key or a password. - * @param {Key} privateKey (optional) private key with decrypted secret data - * @param {String} password (optional) password used to decrypt + * Decrypt an encrypted session key either with private keys or passwords. + * @param {Array} privateKeys (optional) private key with decrypted secret data + * @param {Array} passwords (optional) password used to decrypt * @return {Array<{ data:Uint8Array, algorithm:String }>} array of object with potential sessionKey, algorithm pairs */ -Message.prototype.decryptSessionKeys = function(privateKey, password) { +Message.prototype.decryptSessionKeys = function(privateKeys, passwords) { var keyPackets = []; return Promise.resolve().then(async () => { - if (password) { + if (passwords) { var symESKeyPacketlist = this.packets.filterByTag(enums.packet.symEncryptedSessionKey); if (!symESKeyPacketlist) { throw new Error('No symmetrically encrypted session key packet found.'); @@ -160,7 +160,7 @@ Message.prototype.decryptSessionKeys = function(privateKey, password) { } catch (err) {} })); - } else if (privateKey) { + } else if (privateKeys) { var pkESKeyPacketlist = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); if (!pkESKeyPacketlist) { throw new Error('No public key encrypted session key packet found.'); diff --git a/src/openpgp.js b/src/openpgp.js index 2b38859f..24399e73 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -246,30 +246,31 @@ export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey, * Decrypts a message with the user's private key, a session key or a password. Either a private key, * a session key or a password must be specified. * @param {Message} message the message object with the encrypted data - * @param {Key} privateKey (optional) private key with decrypted secret key data or session key - * @param {Key|Array} publicKeys (optional) array of public keys or single key, to verify signatures - * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String } - * @param {String} password (optional) single password to decrypt the message - * @param {String} format (optional) return data format either as 'utf8' or 'binary' - * @param {Signature} signature (optional) detached signature for verification + * @param {Key|Array} privateKeys (optional) private key with decrypted secret key data or session key + * @param {String|Array} passwords (optional) single password to decrypt the message + * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String } + * @param {Key|Array} publicKeys (optional) array of public keys or single key, to verify signatures + * @param {String} format (optional) return data format either as 'utf8' or 'binary' + * @param {Signature} signature (optional) detached signature for verification * @return {Promise} decrypted and verified message in the form: * { data:Uint8Array|String, filename:String, signatures:[{ keyid:String, valid:Boolean }] } * @static */ -export function decrypt({ message, privateKey, publicKeys, sessionKey, password, format='utf8', signature=null }) { - checkMessage(message); publicKeys = toArray(publicKeys); +export function decrypt({ message, privateKeys, passwords, sessionKey, publicKeys, format='utf8', signature=null }) { + checkMessage(message); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords); if (!nativeAEAD() && asyncProxy) { // use web worker if web crypto apis are not supported - return asyncProxy.delegate('decrypt', { message, privateKey, publicKeys, sessionKey, password, format, signature }); + return asyncProxy.delegate('decrypt', { message, privateKeys, passwords, sessionKey, publicKeys, format, signature }); } - return message.decrypt(privateKey, sessionKey, password).then(async function(message) { + return message.decrypt(privateKeys, passwords, sessionKey).then(async function(message) { const result = parseMessage(message, format); if (!publicKeys) { publicKeys = []; } + if (signature) { //detached signature result.signatures = await message.verifyDetached(signature, publicKeys); From d5022a3a4a75415637a9f1f3ab92cd7230699eac Mon Sep 17 00:00:00 2001 From: Sanjana Rajan Date: Thu, 8 Feb 2018 13:20:54 +0100 Subject: [PATCH 2/6] rename vars in old tests --- test/general/ecc_nist.js | 4 +-- test/general/key.js | 4 +-- test/general/openpgp.js | 54 +++++++++++++++++++-------------------- test/general/signature.js | 8 +++--- test/general/x25519.js | 6 ++--- 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/test/general/ecc_nist.js b/test/general/ecc_nist.js index 27149763..59cc26e4 100644 --- a/test/general/ecc_nist.js +++ b/test/general/ecc_nist.js @@ -186,7 +186,7 @@ describe('Elliptic Curve Cryptography', function () { var romeo = load_priv_key('romeo'); var msg = openpgp.message.readArmored(data.juliet.message_encrypted); return openpgp.decrypt( - {privateKey: romeo, publicKeys: [juliet], message: msg} + {privateKeys: romeo, publicKeys: [juliet], message: msg} ).then(function (result) { expect(result).to.exist; // trim required because https://github.com/openpgpjs/openpgpjs/issues/311 @@ -206,7 +206,7 @@ describe('Elliptic Curve Cryptography', function () { var romeo = load_pub_key('romeo'); var juliet = load_priv_key('juliet'); return openpgp.decrypt( - {privateKey: juliet, publicKeys: [romeo], message: message} + {privateKeys: juliet, publicKeys: [romeo], message: message} ).then(function (result) { expect(result).to.exist; expect(result.data.trim()).to.equal(data.romeo.message); diff --git a/test/general/key.js b/test/general/key.js index 8c409f12..22a7afd8 100644 --- a/test/general/key.js +++ b/test/general/key.js @@ -1004,7 +1004,7 @@ describe('Key', function() { key = newKey; return openpgp.message.fromText('hello').encrypt([key.key]); }).then(function(msg) { - return msg.message.decrypt(key.key); + return msg.message.decrypt([key.key]); }).catch(function(err) { expect(err.message).to.equal('Private key is not decrypted.'); }); @@ -1258,7 +1258,7 @@ describe('Key', function() { return openpgp.reformatKey(opt).then(function(newKey) { newKey = newKey.key; return openpgp.encrypt({data: 'hello', publicKeys: newKey.toPublic(), privateKeys: newKey, armor: true}).then(function(encrypted) { - return openpgp.decrypt({message: openpgp.message.readArmored(encrypted.data), privateKey: newKey, publicKeys: newKey.toPublic()}).then(function(decrypted) { + return openpgp.decrypt({message: openpgp.message.readArmored(encrypted.data), privateKeys: newKey, publicKeys: newKey.toPublic()}).then(function(decrypted) { expect(decrypted.data).to.equal('hello'); expect(decrypted.signatures[0].valid).to.be.true; }); diff --git a/test/general/openpgp.js b/test/general/openpgp.js index c30ef409..f274bdcf 100644 --- a/test/general/openpgp.js +++ b/test/general/openpgp.js @@ -494,7 +494,7 @@ describe('OpenPGP.js public api tests', function() { publicKeys: publicKey.keys, }; var decOpt = { - privateKey: privateKey.keys[0] + privateKeys: privateKey.keys[0] }; return openpgp.encrypt(encOpt).then(function(encrypted) { decOpt.message = openpgp.message.readArmored(encrypted.data); @@ -541,7 +541,7 @@ describe('OpenPGP.js public api tests', function() { }).then(function(encrypted) { return openpgp.decryptSessionKeys({ message: encrypted.message, - privateKey: privateKey.keys[0] + privateKeys: privateKey.keys[0] }); }).then(function(decrypted) { expect(decrypted[0].data).to.deep.equal(sk); @@ -556,7 +556,7 @@ describe('OpenPGP.js public api tests', function() { }).then(function(encrypted) { return openpgp.decryptSessionKeys({ message: encrypted.message, - password: password1 + passwords: password1 }); }).then(function(decrypted) { expect(decrypted[0].data).to.deep.equal(sk); @@ -572,7 +572,7 @@ describe('OpenPGP.js public api tests', function() { msgAsciiArmored = encrypted.data; return openpgp.decryptSessionKeys({ message: openpgp.message.readArmored(msgAsciiArmored), - privateKey: privateKey.keys[0] + privateKeys: privateKey.keys[0] }); }).then(function(decryptedSessionKeys) { @@ -595,7 +595,7 @@ describe('OpenPGP.js public api tests', function() { msgAsciiArmored = encrypted.data; return openpgp.decryptSessionKeys({ message: openpgp.message.readArmored(msgAsciiArmored), - password: password1 + passwords: password1 }); }).then(function(decryptedSessionKeys) { @@ -616,7 +616,7 @@ describe('OpenPGP.js public api tests', function() { }).then(function(encrypted) { return openpgp.decryptSessionKeys({ message: openpgp.message.readArmored(encrypted.data), - password: password1 + passwords: password1 }); }).then(function(decryptedSessionKeys) { expect(decryptedSessionKeys.length).to.equal(1); @@ -648,7 +648,7 @@ describe('OpenPGP.js public api tests', function() { publicKeys: publicKey.keys, }; var decOpt = { - privateKey: privateKey.keys[0] + privateKeys: privateKey.keys[0] }; return openpgp.encrypt(encOpt).then(function(encrypted) { expect(encrypted.data).to.match(/^-----BEGIN PGP MESSAGE/); @@ -715,7 +715,7 @@ describe('OpenPGP.js public api tests', function() { publicKeys: publicKey.keys }; var decOpt = { - privateKey: privateKey.keys[0] + privateKeys: privateKey.keys[0] }; return openpgp.encrypt(encOpt).then(function(encrypted) { expect(encrypted.data).to.match(/^-----BEGIN PGP MESSAGE/); @@ -733,7 +733,7 @@ describe('OpenPGP.js public api tests', function() { privateKeys: privateKey.keys }; var decOpt = { - privateKey: privateKey.keys[0], + privateKeys: privateKey.keys[0], publicKeys: publicKey.keys }; return openpgp.encrypt(encOpt).then(function(encrypted) { @@ -754,7 +754,7 @@ describe('OpenPGP.js public api tests', function() { privateKeys: privateKey.keys }; var decOpt = { - privateKey: privateKey.keys[0], + privateKeys: privateKey.keys[0], publicKeys: publicKey.keys }; return openpgp.encrypt(encOpt).then(function(encrypted) { @@ -776,7 +776,7 @@ describe('OpenPGP.js public api tests', function() { detached: true }; var decOpt = { - privateKey: privateKey.keys[0], + privateKeys: privateKey.keys[0], publicKeys: publicKey.keys }; return openpgp.encrypt(encOpt).then(function(encrypted) { @@ -805,7 +805,7 @@ describe('OpenPGP.js public api tests', function() { }; var decOpt = { - privateKey: privateKey.keys[0], + privateKeys: privateKey.keys[0], publicKeys: publicKey.keys[0] }; @@ -843,7 +843,7 @@ describe('OpenPGP.js public api tests', function() { }; var decOpt = { - privateKey: privateKey.keys[0], + privateKeys: privateKey.keys[0], publicKeys: [publicKey.keys[0], pubKeyDE] }; @@ -880,7 +880,7 @@ describe('OpenPGP.js public api tests', function() { }; var decOpt = { - privateKey: privateKey.keys[0], + privateKeys: privateKey.keys[0], publicKeys: openpgp.key.readArmored(wrong_pubkey).keys }; @@ -912,7 +912,7 @@ describe('OpenPGP.js public api tests', function() { }; var decOpt = { - privateKey: privateKey.keys[0], + privateKeys: privateKey.keys[0], publicKeys: openpgp.key.readArmored(wrong_pubkey).keys }; @@ -937,7 +937,7 @@ describe('OpenPGP.js public api tests', function() { privateKeys: privateKey.keys }; var decOpt = { - privateKey: privateKey.keys[0], + privateKeys: privateKey.keys[0], publicKeys: openpgp.key.readArmored(wrong_pubkey).keys }; return openpgp.encrypt(encOpt).then(function(encrypted) { @@ -958,7 +958,7 @@ describe('OpenPGP.js public api tests', function() { privateKeys: privateKey.keys }; var decOpt = { - privateKey: privateKey.keys[0], + privateKeys: privateKey.keys[0], publicKeys: openpgp.key.readArmored(wrong_pubkey).keys }; return openpgp.encrypt(encOpt).then(function(encrypted) { @@ -979,7 +979,7 @@ describe('OpenPGP.js public api tests', function() { privateKeys: privateKey.keys }; var decOpt = { - privateKey: privateKey.keys[0], + privateKeys: privateKey.keys[0], }; return openpgp.encrypt(encOpt).then(function(encrypted) { decOpt.message = openpgp.message.readArmored(encrypted.data); @@ -1000,7 +1000,7 @@ describe('OpenPGP.js public api tests', function() { detached: true }; var decOpt = { - privateKey: privateKey.keys[0], + privateKeys: privateKey.keys[0], publicKeys: openpgp.key.readArmored(wrong_pubkey).keys }; return openpgp.encrypt(encOpt).then(function(encrypted) { @@ -1028,7 +1028,7 @@ describe('OpenPGP.js public api tests', function() { }; var decOpt = { - privateKey: privateKey.keys[0], + privateKeys: privateKey.keys[0], publicKeys: [publicKey.keys[0], pubKeyDE] }; @@ -1183,7 +1183,7 @@ describe('OpenPGP.js public api tests', function() { data: plaintext }).then(function(encrypted) { return openpgp.decrypt({ - privateKey: privKeyDE, + privateKeys: privKeyDE, publicKeys: pubKeyDE, message: openpgp.message.readArmored(encrypted.data) }); @@ -1258,7 +1258,7 @@ describe('OpenPGP.js public api tests', function() { privKey.decrypt('1234'); message = openpgp.message.readArmored(pgp_msg); - return openpgp.decrypt({ privateKey:privKey, message:message }).then(function(decrypted) { + return openpgp.decrypt({ privateKeys:privKey, message:message }).then(function(decrypted) { expect(decrypted.data).to.equal('hello 3des\n'); expect(decrypted.signatures.length).to.equal(0); }); @@ -1272,7 +1272,7 @@ describe('OpenPGP.js public api tests', function() { passwords: password1 }; var decOpt = { - password: password1 + passwords: password1 }; return openpgp.encrypt(encOpt).then(function(encrypted) { decOpt.message = openpgp.message.readArmored(encrypted.data); @@ -1289,7 +1289,7 @@ describe('OpenPGP.js public api tests', function() { passwords: [password1, password2] }; var decOpt = { - password: password2 + passwords: password2 }; return openpgp.encrypt(encOpt).then(function(encrypted) { decOpt.message = openpgp.message.readArmored(encrypted.data); @@ -1304,7 +1304,7 @@ describe('OpenPGP.js public api tests', function() { var decOpt = { message: openpgp.message.readArmored(twoPasswordGPGFail), - password: password2 + passwords: password2 }; return openpgp.decrypt(decOpt).then(function(decrypted) { expect(decrypted.data).to.equal(plaintext); @@ -1319,7 +1319,7 @@ describe('OpenPGP.js public api tests', function() { armor: false }; var decOpt = { - password: password1 + passwords: password1 }; return openpgp.encrypt(encOpt).then(function(encrypted) { decOpt.message = encrypted.message; @@ -1338,7 +1338,7 @@ describe('OpenPGP.js public api tests', function() { armor: false }; var decOpt = { - password: password1, + passwords: password1, format: 'binary' }; return openpgp.encrypt(encOpt).then(function(encrypted) { diff --git a/test/general/signature.js b/test/general/signature.js index 9b6be339..9800ef22 100644 --- a/test/general/signature.js +++ b/test/general/signature.js @@ -340,7 +340,7 @@ describe("Signature", function() { var pub_key = openpgp.key.readArmored(pub_key_arm1).keys[0]; var msg = openpgp.message.readArmored(msg_arm1); priv_key.decrypt("abcd"); - return openpgp.decrypt({ privateKey: priv_key, publicKeys:[pub_key], message:msg }).then(function(decrypted) { + return openpgp.decrypt({ privateKeys: priv_key, publicKeys:[pub_key], message:msg }).then(function(decrypted) { expect(decrypted.data).to.exist; expect(decrypted.signatures[0].valid).to.be.true; expect(decrypted.signatures[0].signature.packets.length).to.equal(1); @@ -382,7 +382,7 @@ describe("Signature", function() { var msg = openpgp.message.readArmored(msg_arm1); priv_key_gnupg_ext.subKeys[0].subKey.decrypt("abcd"); - return msg.decrypt(priv_key_gnupg_ext).then(function(msg) { + return msg.decrypt([priv_key_gnupg_ext]).then(function(msg) { return msg.verify([pub_key]).then(verified => { expect(verified).to.exist; expect(verified).to.have.length(1); @@ -466,7 +466,7 @@ describe("Signature", function() { var keyids = esMsg.getEncryptionKeyIds(); privKey.decryptKeyPacket(keyids, 'hello world'); - return openpgp.decrypt({ privateKey: privKey, publicKeys:[pubKey], message:esMsg }).then(function(decrypted) { + return openpgp.decrypt({ privateKeys: privKey, publicKeys:[pubKey], message:esMsg }).then(function(decrypted) { expect(decrypted.data).to.exist; expect(decrypted.data).to.equal(plaintext); expect(decrypted.signatures).to.have.length(1); @@ -502,7 +502,7 @@ describe("Signature", function() { var keyids = esMsg.getEncryptionKeyIds(); privKey.decryptKeyPacket(keyids, 'hello world'); - return openpgp.decrypt({ privateKey: privKey, publicKeys:[pubKey], message:esMsg }).then(function(decrypted) { + return openpgp.decrypt({ privateKeys: privKey, publicKeys:[pubKey], message:esMsg }).then(function(decrypted) { expect(decrypted.data).to.exist; expect(decrypted.data).to.equal(plaintext); expect(decrypted.signatures).to.have.length(1); diff --git a/test/general/x25519.js b/test/general/x25519.js index fc43bad8..da89aa2e 100644 --- a/test/general/x25519.js +++ b/test/general/x25519.js @@ -174,7 +174,7 @@ describe('X25519 Cryptography', function () { expect(night.decrypt(data['night'].pass)).to.be.true; var msg = openpgp.message.readArmored(data['night'].message_encrypted); return openpgp.decrypt( - {privateKey: night, publicKeys: [light], message: msg} + {privateKeys: night, publicKeys: [light], message: msg} ).then(function (result) { expect(result).to.exist; // trim required because https://github.com/openpgpjs/openpgpjs/issues/311 @@ -194,7 +194,7 @@ describe('X25519 Cryptography', function () { var light = load_pub_key('light'); var night = load_priv_key('night'); return openpgp.decrypt( - {privateKey: night, publicKeys: [light], message: message} + {privateKeys: night, publicKeys: [light], message: message} ).then(function (result) { expect(result).to.exist; expect(result.data.trim()).to.equal(data['light'].message); @@ -291,7 +291,7 @@ describe('X25519 Cryptography', function () { // Decrypting and verifying return openpgp.decrypt( { message: msg, - privateKey: bye, + privateKeys: bye, publicKeys: [ hi.toPublic() ] } ).then(output => { expect(output.data).to.equal('Hi, Hi wrote this but only Bye can read it!'); From 7365ffc9b750d4b436baf3751ec5f6a950c18cea Mon Sep 17 00:00:00 2001 From: Sanjana Rajan Date: Fri, 9 Feb 2018 10:49:15 +0100 Subject: [PATCH 3/6] wildcard implementation --- src/message.js | 57 +++++++++++++------ src/openpgp.js | 26 ++++----- .../public_key_encrypted_session_key.js | 1 - src/type/keyid.js | 10 ++++ 4 files changed, 63 insertions(+), 31 deletions(-) diff --git a/src/message.js b/src/message.js index 2036710c..97e1b348 100644 --- a/src/message.js +++ b/src/message.js @@ -35,6 +35,7 @@ import armor from './encoding/armor'; import enums from './enums'; import util from './util'; import packet from './packet'; +import type_keyid from './type/keyid'; import { Signature } from './signature'; import { getPreferredHashAlgo, getPreferredSymAlgo } from './key'; @@ -154,10 +155,14 @@ Message.prototype.decryptSessionKeys = function(privateKeys, passwords) { throw new Error('No symmetrically encrypted session key packet found.'); } await Promise.all(symESKeyPacketlist.map(async function(packet) { - try { - await packet.decrypt(password); - keyPackets.push(packet); - } catch (err) {} + for (var i = 0; i < passwords.length; i++) { + try { + // eslint-disable-next-line no-await-in-loop + await packet.decrypt(passwords[i]); + keyPackets.push(packet); + break; + } catch (err) {} + } })); } else if (privateKeys) { @@ -165,16 +170,30 @@ Message.prototype.decryptSessionKeys = function(privateKeys, passwords) { if (!pkESKeyPacketlist) { throw new Error('No public key encrypted session key packet found.'); } - var privateKeyPacket = privateKey.getKeyPacket(this.getEncryptionKeyIds()); - if (!privateKeyPacket.isDecrypted) { - throw new Error('Private key is not decrypted.'); - } await Promise.all(pkESKeyPacketlist.map(async function(packet) { - if (packet.publicKeyId.equals(privateKeyPacket.getKeyId())) { - try { - await packet.decrypt(privateKeyPacket); - keyPackets.push(packet); - } catch (err) {} + for (var i = 0; i < privateKeys.length; i++){ + var privateKeyPackets; + if (packet.publicKeyId.isWildcard()) { + // wildcard key ID - try all key packets + privateKeyPackets = privateKeys[i].getAllKeyPackets(); + } else { + privateKeyPackets = [privateKeys[i].getKeyPacket([packet.publicKeyId])]; + } + for (var j = 0; j < privateKeyPackets.length; j++) { + var privateKeyPacket = privateKeyPackets[j]; + if (!privateKeyPacket) { + continue; + } + if (!privateKeyPacket.isDecrypted) { + throw new Error('Private key is not decrypted.'); + } + try { + // eslint-disable-next-line no-await-in-loop + await packet.decrypt(privateKeyPacket); + keyPackets.push(packet); + break; + } catch (err) {} + } } })); } else { @@ -242,7 +261,7 @@ Message.prototype.getText = function() { * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String } * @return {Message} new message with encrypted content */ -Message.prototype.encrypt = function(keys, passwords, sessionKey) { +Message.prototype.encrypt = function(keys, passwords, sessionKey, useWildcard) { let symAlgo, msg, symEncryptedPacket; return Promise.resolve().then(async () => { if (sessionKey) { @@ -263,7 +282,7 @@ Message.prototype.encrypt = function(keys, passwords, sessionKey) { sessionKey = crypto.generateSessionKey(symAlgo); } - msg = await encryptSessionKey(sessionKey, symAlgo, keys, passwords); + msg = await encryptSessionKey(sessionKey, symAlgo, keys, passwords, useWildcard); if (config.aead_protect) { symEncryptedPacket = new packet.SymEncryptedAEADProtected(); @@ -297,7 +316,7 @@ Message.prototype.encrypt = function(keys, passwords, sessionKey) { * @param {Array} passwords (optional) for message encryption * @return {Message} new message with encrypted content */ -export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords) { +export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, useWildcard) { var results, packetlist = new packet.List(); return Promise.resolve().then(async () => { @@ -309,7 +328,11 @@ export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords) { throw new Error('Could not find valid key packet for encryption in key ' + key.primaryKey.getKeyId().toHex()); } var pkESKeyPacket = new packet.PublicKeyEncryptedSessionKey(); - pkESKeyPacket.publicKeyId = encryptionKeyPacket.getKeyId(); + if (!useWildcard) { + pkESKeyPacket.publicKeyId = encryptionKeyPacket.getKeyId(); + } else { + pkESKeyPacket.publicKeyId = type_keyid.wildcard(); + } pkESKeyPacket.publicKeyAlgorithm = encryptionKeyPacket.algorithm; pkESKeyPacket.sessionKey = sessionKey; pkESKeyPacket.sessionKeyAlgorithm = symAlgo; diff --git a/src/openpgp.js b/src/openpgp.js index 24399e73..fa36b8ef 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -201,11 +201,11 @@ export function decryptKey({ privateKey, passphrase }) { * message: full Message object if 'armor' is false, signature: detached signature if 'detached' is true} * @static */ -export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey, filename, armor=true, detached=false, signature=null, returnSessionKey=false}) { +export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey, filename, armor=true, detached=false, signature=null, returnSessionKey=false, useWildcard=false}) { checkData(data); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords); if (!nativeAEAD() && asyncProxy) { // use web worker if web crypto apis are not supported - return asyncProxy.delegate('encrypt', { data, publicKeys, privateKeys, passwords, sessionKey, filename, armor, detached, signature, returnSessionKey }); + return asyncProxy.delegate('encrypt', { data, publicKeys, privateKeys, passwords, sessionKey, filename, armor, detached, signature, returnSessionKey, useWildcard }); } var result = {}; return Promise.resolve().then(async function() { @@ -226,7 +226,7 @@ export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey, message = await message.sign(privateKeys, signature); } } - return message.encrypt(publicKeys, passwords, sessionKey); + return message.encrypt(publicKeys, passwords, sessionKey, useWildcard); }).then(encrypted => { if (armor) { @@ -395,16 +395,16 @@ export function verify({ message, publicKeys, signature=null }) { * @return {Promise} the encrypted session key packets contained in a message object * @static */ -export function encryptSessionKey({ data, algorithm, publicKeys, passwords }) { +export function encryptSessionKey({ data, algorithm, publicKeys, passwords, useWildcard=false }) { checkBinary(data); checkString(algorithm, 'algorithm'); publicKeys = toArray(publicKeys); passwords = toArray(passwords); if (asyncProxy) { // use web worker if available - return asyncProxy.delegate('encryptSessionKey', { data, algorithm, publicKeys, passwords }); + return asyncProxy.delegate('encryptSessionKey', { data, algorithm, publicKeys, passwords, useWildcard }); } return Promise.resolve().then(async function() { - return { message: await messageLib.encryptSessionKey(data, algorithm, publicKeys, passwords) }; + return { message: await messageLib.encryptSessionKey(data, algorithm, publicKeys, passwords, useWildcard) }; }).catch(onError.bind(null, 'Error encrypting session key')); } @@ -412,24 +412,24 @@ export function encryptSessionKey({ data, algorithm, publicKeys, passwords }) { /** * Decrypt a symmetric session key with a private key or password. Either a private key or * a password must be specified. - * @param {Message} message a message object containing the encrypted session key packets - * @param {Key} privateKey (optional) private key with decrypted secret key data - * @param {String} password (optional) a single password to decrypt the session key + * @param {Message} message a message object containing the encrypted session key packets + * @param {Key|Array} passwords (optional) passwords to decrypt the session key * @return {Promise} Array of decrypted session key, algorithm pairs in form: * { data:Uint8Array, algorithm:String } * or 'undefined' if no key packets found * @static */ -export function decryptSessionKeys({ message, privateKey, password }) { - checkMessage(message); +export function decryptSessionKeys({ message, privateKeys, passwords }) { + checkMessage(message); privateKeys = toArray(privateKeys); passwords = toArray(passwords); if (asyncProxy) { // use web worker if available - return asyncProxy.delegate('decryptSessionKeys', { message, privateKey, password }); + return asyncProxy.delegate('decryptSessionKeys', { message, privateKeys, passwords }); } return Promise.resolve().then(async function() { - return message.decryptSessionKeys(privateKey, password); + return message.decryptSessionKeys(privateKeys, passwords); }).catch(onError.bind(null, 'Error decrypting session keys')); } diff --git a/src/packet/public_key_encrypted_session_key.js b/src/packet/public_key_encrypted_session_key.js index 9d86e2e0..8c59177e 100644 --- a/src/packet/public_key_encrypted_session_key.js +++ b/src/packet/public_key_encrypted_session_key.js @@ -71,7 +71,6 @@ export default function PublicKeyEncryptedSessionKey() { * @return {module:packet/public_key_encrypted_session_key} Object representation */ PublicKeyEncryptedSessionKey.prototype.read = function (bytes) { - this.version = bytes[0]; this.publicKeyId.read(bytes.subarray(1,bytes.length)); this.publicKeyAlgorithm = enums.read(enums.publicKey, bytes[9]); diff --git a/src/type/keyid.js b/src/type/keyid.js index 5aca938d..119f842c 100644 --- a/src/type/keyid.js +++ b/src/type/keyid.js @@ -61,6 +61,10 @@ Keyid.prototype.isNull = function() { return this.bytes === ''; }; +Keyid.prototype.isWildcard = function() { + return this.toHex() === '0000000000000000'; +}; + Keyid.mapToHex = function (keyId) { return keyId.toHex(); }; @@ -76,3 +80,9 @@ Keyid.fromId = function (hex) { keyid.read(util.str2Uint8Array(util.hex2bin(hex))); return keyid; }; + +Keyid.wildcard = function () { + var keyid = new Keyid(); + keyid.read(util.str2Uint8Array(util.hex2bin('0000000000000000'))); + return keyid; +}; From 417af8c6bc749e7813a3818f62bde533e8fa1474 Mon Sep 17 00:00:00 2001 From: Sanjana Rajan Date: Fri, 9 Feb 2018 10:50:06 +0100 Subject: [PATCH 4/6] tests --- test/general/openpgp.js | 133 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 1 deletion(-) diff --git a/test/general/openpgp.js b/test/general/openpgp.js index f274bdcf..4e27fc60 100644 --- a/test/general/openpgp.js +++ b/test/general/openpgp.js @@ -163,6 +163,7 @@ var passphrase = 'hello world'; var plaintext = 'short message\nnext line\n한국어/조선말'; var password1 = 'I am a password'; var password2 = 'I am another password'; +var password3 = 'I am a third password'; var twoPasswordGPGFail = ['-----BEGIN PGP MESSAGE-----', 'Version: OpenPGP.js v3.0.0', @@ -609,6 +610,52 @@ describe('OpenPGP.js public api tests', function() { }); }); + it('roundtrip workflow: encrypt, decryptSessionKeys, decrypt with multiple passwords', function() { + var msgAsciiArmored; + return openpgp.encrypt({ + data: plaintext, + passwords: password2 + }).then(function(encrypted) { + msgAsciiArmored = encrypted.data; + return openpgp.decryptSessionKeys({ + message: openpgp.message.readArmored(msgAsciiArmored), + passwords: [password1, password2, password3] + }); + + }).then(function(decryptedSessionKeys) { + return openpgp.decrypt({ + sessionKey: decryptedSessionKeys[0], + message: openpgp.message.readArmored(msgAsciiArmored) + }); + + }).then(function(decrypted) { + expect(decrypted.data).to.equal(plaintext); + }); + }); + + it('roundtrip workflow: encrypt with multiple passwords, decryptSessionKeys, decrypt with multiple passwords', function() { + var msgAsciiArmored; + return openpgp.encrypt({ + data: plaintext, + passwords: [password1, password2] + }).then(function(encrypted) { + msgAsciiArmored = encrypted.data; + return openpgp.decryptSessionKeys({ + message: openpgp.message.readArmored(msgAsciiArmored), + passwords: [password1, password2] + }); + + }).then(function(decryptedSessionKeys) { + return openpgp.decrypt({ + sessionKey: decryptedSessionKeys[0], + message: openpgp.message.readArmored(msgAsciiArmored) + }); + + }).then(function(decrypted) { + expect(decrypted.data).to.equal(plaintext); + }); + }); + it('roundtrip workflow: encrypt twice with one password, decryptSessionKeys, only one session key', function() { return openpgp.encrypt({ data: plaintext, @@ -648,7 +695,91 @@ describe('OpenPGP.js public api tests', function() { publicKeys: publicKey.keys, }; var decOpt = { - privateKeys: privateKey.keys[0] + privateKeys: privateKey.keys + }; + return openpgp.encrypt(encOpt).then(function(encrypted) { + expect(encrypted.data).to.match(/^-----BEGIN PGP MESSAGE/); + decOpt.message = openpgp.message.readArmored(encrypted.data); + return openpgp.decrypt(decOpt); + }).then(function(decrypted) { + expect(decrypted.data).to.equal(plaintext); + expect(decrypted.signatures).to.exist; + expect(decrypted.signatures.length).to.equal(0); + }); + }); + + it('should encrypt then decrypt', function() { + var encOpt = { + data: plaintext, + publicKeys: publicKey.keys, + }; + var decOpt = { + privateKeys: privateKey.keys + }; + return openpgp.encrypt(encOpt).then(function(encrypted) { + expect(encrypted.data).to.match(/^-----BEGIN PGP MESSAGE/); + decOpt.message = openpgp.message.readArmored(encrypted.data); + return openpgp.decrypt(decOpt); + }).then(function(decrypted) { + expect(decrypted.data).to.equal(plaintext); + expect(decrypted.signatures).to.exist; + expect(decrypted.signatures.length).to.equal(0); + }); + }); + + it('should encrypt then decrypt wuth multiple private keys', function() { + var privKeyDE = openpgp.key.readArmored(priv_key_de).keys[0]; + privKeyDE.decrypt(passphrase); + + var encOpt = { + data: plaintext, + publicKeys: publicKey.keys, + }; + var decOpt = { + privateKeys: [privKeyDE, privateKey.keys[0]] + }; + return openpgp.encrypt(encOpt).then(function(encrypted) { + expect(encrypted.data).to.match(/^-----BEGIN PGP MESSAGE/); + decOpt.message = openpgp.message.readArmored(encrypted.data); + return openpgp.decrypt(decOpt); + }).then(function(decrypted) { + expect(decrypted.data).to.equal(plaintext); + expect(decrypted.signatures).to.exist; + expect(decrypted.signatures.length).to.equal(0); + }); + }); + + it('should encrypt then decrypt with wildcard', function() { + var encOpt = { + data: plaintext, + publicKeys: publicKey.keys, + useWildcard: true + }; + var decOpt = { + privateKeys: privateKey.keys + }; + return openpgp.encrypt(encOpt).then(function(encrypted) { + expect(encrypted.data).to.match(/^-----BEGIN PGP MESSAGE/); + decOpt.message = openpgp.message.readArmored(encrypted.data); + return openpgp.decrypt(decOpt); + }).then(function(decrypted) { + expect(decrypted.data).to.equal(plaintext); + expect(decrypted.signatures).to.exist; + expect(decrypted.signatures.length).to.equal(0); + }); + }); + + it('should encrypt then decrypt with wildcard with multiple private keys', function() { + var privKeyDE = openpgp.key.readArmored(priv_key_de).keys[0]; + privKeyDE.decrypt(passphrase); + + var encOpt = { + data: plaintext, + publicKeys: publicKey.keys, + useWildcard: true + }; + var decOpt = { + privateKeys: [privKeyDE, privateKey.keys[0]] }; return openpgp.encrypt(encOpt).then(function(encrypted) { expect(encrypted.data).to.match(/^-----BEGIN PGP MESSAGE/); From 989ad5077ea078ed62e8f0d601b47e2b7db0cda1 Mon Sep 17 00:00:00 2001 From: Sanjana Rajan Date: Mon, 12 Feb 2018 10:51:54 +0100 Subject: [PATCH 5/6] cleanup, docs --- npm-shrinkwrap.json | 8 +- src/key.js | 17 +++-- src/message.js | 74 ++++++++----------- src/openpgp.js | 68 +++++------------ .../public_key_encrypted_session_key.js | 1 + src/type/keyid.js | 4 +- test/general/openpgp.js | 37 ++-------- test/general/signature.js | 8 +- 8 files changed, 76 insertions(+), 141 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index f7ed1001..32d3b9b9 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1525,7 +1525,7 @@ "browserify-rsa": "4.0.1", "create-hash": "1.1.3", "create-hmac": "1.1.6", - "elliptic": "git+https://github.com/openpgpjs/elliptic.git#0bd7555723b84ac2b747e00c8cea1e64e99b4f4f", + "elliptic": "git+https://github.com/openpgpjs/elliptic.git#8b8ee8475b86402b125d4ad3a863a4ccd762e48c", "inherits": "2.0.3", "parse-asn1": "5.1.0" } @@ -1937,7 +1937,7 @@ "dev": true, "requires": { "bn.js": "4.11.8", - "elliptic": "git+https://github.com/openpgpjs/elliptic.git#0bd7555723b84ac2b747e00c8cea1e64e99b4f4f" + "elliptic": "git+https://github.com/openpgpjs/elliptic.git#8b8ee8475b86402b125d4ad3a863a4ccd762e48c" } }, "create-hash": { @@ -2325,7 +2325,7 @@ "dev": true }, "elliptic": { - "version": "git+https://github.com/openpgpjs/elliptic.git#0bd7555723b84ac2b747e00c8cea1e64e99b4f4f", + "version": "git+https://github.com/openpgpjs/elliptic.git#8b8ee8475b86402b125d4ad3a863a4ccd762e48c", "requires": { "bn.js": "4.11.8", "brorand": "1.1.0", @@ -5604,7 +5604,7 @@ "integrity": "sha1-1QfOzkAInFJI4J7GgmaiAwqcYyU=", "requires": { "asn1.js": "4.9.2", - "elliptic": "git+https://github.com/openpgpjs/elliptic.git#0bd7555723b84ac2b747e00c8cea1e64e99b4f4f", + "elliptic": "git+https://github.com/openpgpjs/elliptic.git#8b8ee8475b86402b125d4ad3a863a4ccd762e48c", "safe-buffer": "5.1.1" }, "dependencies": { diff --git a/src/key.js b/src/key.js index 4acc880c..a929729c 100644 --- a/src/key.js +++ b/src/key.js @@ -208,22 +208,23 @@ Key.prototype.getKeyIds = function() { }; /** - * Returns first key packet for given array of key IDs - * @param {Array} keyIds + * Returns array containing first key packet for given key ID or all key packets in the case of a wildcard ID + * @param {type/keyid>} keyIds * @return {(module:packet/public_subkey|module:packet/public_key| * module:packet/secret_subkey|module:packet/secret_key|null)} */ -Key.prototype.getKeyPacket = function(keyIds) { +Key.prototype.getKeyPackets = function(packetKeyId) { var keys = this.getAllKeyPackets(); + if (packetKeyId.isWildcard()) { + return keys; + } for (var i = 0; i < keys.length; i++) { var keyId = keys[i].getKeyId(); - for (var j = 0; j < keyIds.length; j++) { - if (keyId.equals(keyIds[j])) { - return keys[i]; - } + if (keyId.equals(packetKeyId)) { + return [keys[i]]; } } - return null; + return []; }; /** diff --git a/src/message.js b/src/message.js index 97e1b348..04009b55 100644 --- a/src/message.js +++ b/src/message.js @@ -92,16 +92,13 @@ Message.prototype.getSigningKeyIds = function() { /** * Decrypt the message. Either a private key, a session key, or a password must be specified. - * @param {Array} privateKeys (optional) private key with decrypted secret data - * @param {Array} passwords (optional) password used to decrypt - * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String } + * @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 */ -Message.prototype.decrypt = async function(privateKeys, passwords, sessionKey) { - let keyObjs = sessionKey || await this.decryptSessionKeys(privateKeys, passwords); - if (!util.isArray(keyObjs)) { - keyObjs = [keyObjs]; - } +Message.prototype.decrypt = async function(privateKeys, passwords, sessionKeys) { + const keyObjs = sessionKeys || await this.decryptSessionKeys(privateKeys, passwords); const symEncryptedPacketlist = this.packets.filterByTag( enums.packet.symmetricallyEncrypted, @@ -141,9 +138,9 @@ Message.prototype.decrypt = async function(privateKeys, passwords, sessionKey) { }; /** - * Decrypt an encrypted session key either with private keys or passwords. - * @param {Array} privateKeys (optional) private key with decrypted secret data - * @param {Array} passwords (optional) password used to decrypt + * 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 */ Message.prototype.decryptSessionKeys = function(privateKeys, passwords) { @@ -155,14 +152,12 @@ Message.prototype.decryptSessionKeys = function(privateKeys, passwords) { throw new Error('No symmetrically encrypted session key packet found.'); } await Promise.all(symESKeyPacketlist.map(async function(packet) { - for (var i = 0; i < passwords.length; i++) { + await Promise.all(passwords.map(async function(password) { try { - // eslint-disable-next-line no-await-in-loop - await packet.decrypt(passwords[i]); + await packet.decrypt(password); keyPackets.push(packet); - break; } catch (err) {} - } + })); })); } else if (privateKeys) { @@ -171,30 +166,21 @@ Message.prototype.decryptSessionKeys = function(privateKeys, passwords) { throw new Error('No public key encrypted session key packet found.'); } await Promise.all(pkESKeyPacketlist.map(async function(packet) { - for (var i = 0; i < privateKeys.length; i++){ - var privateKeyPackets; - if (packet.publicKeyId.isWildcard()) { - // wildcard key ID - try all key packets - privateKeyPackets = privateKeys[i].getAllKeyPackets(); - } else { - privateKeyPackets = [privateKeys[i].getKeyPacket([packet.publicKeyId])]; + var privateKeyPackets = privateKeys.reduce(function(acc, privateKey) { + return acc.concat(privateKey.getKeyPackets(packet.publicKeyId)); + }, []); + await Promise.all(privateKeyPackets.map(async function(privateKeyPacket) { + if (!privateKeyPacket) { + return; } - for (var j = 0; j < privateKeyPackets.length; j++) { - var privateKeyPacket = privateKeyPackets[j]; - if (!privateKeyPacket) { - continue; - } - if (!privateKeyPacket.isDecrypted) { - throw new Error('Private key is not decrypted.'); - } - try { - // eslint-disable-next-line no-await-in-loop - await packet.decrypt(privateKeyPacket); - keyPackets.push(packet); - break; - } catch (err) {} + 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.'); @@ -259,9 +245,10 @@ Message.prototype.getText = function() { * @param {Array} keys (optional) public key(s) for message encryption * @param {Array} passwords (optional) password(s) for message encryption * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String } + * @param {Boolean} useWildcard (optional) use a key ID of 0 instead of the public key IDs * @return {Message} new message with encrypted content */ -Message.prototype.encrypt = function(keys, passwords, sessionKey, useWildcard) { +Message.prototype.encrypt = function(keys, passwords, sessionKey, useWildcard=false) { let symAlgo, msg, symEncryptedPacket; return Promise.resolve().then(async () => { if (sessionKey) { @@ -314,9 +301,10 @@ Message.prototype.encrypt = function(keys, passwords, sessionKey, useWildcard) { * @param {String} symAlgo session key algorithm * @param {Array} publicKeys (optional) public key(s) for message encryption * @param {Array} passwords (optional) for message encryption + * @param {Boolean} useWildcard (optional) use a key ID of 0 instead of the public key IDs * @return {Message} new message with encrypted content */ -export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, useWildcard) { +export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, useWildcard=false) { var results, packetlist = new packet.List(); return Promise.resolve().then(async () => { @@ -328,11 +316,7 @@ export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, us throw new Error('Could not find valid key packet for encryption in key ' + key.primaryKey.getKeyId().toHex()); } var pkESKeyPacket = new packet.PublicKeyEncryptedSessionKey(); - if (!useWildcard) { - pkESKeyPacket.publicKeyId = encryptionKeyPacket.getKeyId(); - } else { - pkESKeyPacket.publicKeyId = type_keyid.wildcard(); - } + pkESKeyPacket.publicKeyId = useWildcard ? type_keyid.wildcard() : encryptionKeyPacket.getKeyId(); pkESKeyPacket.publicKeyAlgorithm = encryptionKeyPacket.algorithm; pkESKeyPacket.sessionKey = sessionKey; pkESKeyPacket.sessionKeyAlgorithm = symAlgo; diff --git a/src/openpgp.js b/src/openpgp.js index fa36b8ef..f0cc7892 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -196,6 +196,7 @@ export function decryptKey({ privateKey, passphrase }) { * @param {Boolean} detached (optional) if the signature should be detached (if true, signature will be added to returned object) * @param {Signature} signature (optional) a detached signature to add to the encrypted message * @param {Boolean} returnSessionKey (optional) if the unencrypted session key should be added to returned object + * @param {Boolean} useWildcard (optional) use a key ID of 0 instead of the public key IDs * @return {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} @@ -217,11 +218,7 @@ export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey, if (privateKeys.length || signature) { // sign the message only if private keys or signature is specified if (detached) { var detachedSignature = await message.signDetached(privateKeys, signature); - if (armor) { - result.signature = detachedSignature.armor(); - } else { - result.signature = detachedSignature; - } + result.signature = armor ? detachedSignature.armor() : detachedSignature; } else { message = await message.sign(privateKeys, signature); } @@ -245,25 +242,25 @@ export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey, /** * Decrypts a message with the user's private key, a session key or a password. Either a private key, * a session key or a password must be specified. - * @param {Message} message the message object with the encrypted data - * @param {Key|Array} privateKeys (optional) private key with decrypted secret key data or session key - * @param {String|Array} passwords (optional) single password to decrypt the message - * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String } - * @param {Key|Array} publicKeys (optional) array of public keys or single key, to verify signatures - * @param {String} format (optional) return data format either as 'utf8' or 'binary' - * @param {Signature} signature (optional) detached signature for verification + * @param {Message} message the message object with the encrypted data + * @param {Key|Array} privateKeys (optional) private keys with decrypted secret key data or session key + * @param {String|Array} passwords (optional) passwords to decrypt the message + * @param {Object|Array} sessionKeys (optional) session keys in the form: { data:Uint8Array, algorithm:String } + * @param {Key|Array} publicKeys (optional) array of public keys or single key, to verify signatures + * @param {String} format (optional) return data format either as 'utf8' or 'binary' + * @param {Signature} signature (optional) detached signature for verification * @return {Promise} decrypted and verified message in the form: * { data:Uint8Array|String, filename:String, signatures:[{ keyid:String, valid:Boolean }] } * @static */ -export function decrypt({ message, privateKeys, passwords, sessionKey, publicKeys, format='utf8', signature=null }) { - checkMessage(message); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords); +export function decrypt({ message, privateKeys, passwords, sessionKeys, publicKeys, format='utf8', signature=null }) { + checkMessage(message); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords); sessionKeys = toArray(sessionKeys); if (!nativeAEAD() && asyncProxy) { // use web worker if web crypto apis are not supported - return asyncProxy.delegate('decrypt', { message, privateKeys, passwords, sessionKey, publicKeys, format, signature }); + return asyncProxy.delegate('decrypt', { message, privateKeys, passwords, sessionKeys, publicKeys, format, signature }); } - return message.decrypt(privateKeys, passwords, sessionKey).then(async function(message) { + return message.decrypt(privateKeys, passwords, sessionKeys).then(async function(message) { const result = parseMessage(message, format); @@ -271,13 +268,7 @@ export function decrypt({ message, privateKeys, passwords, sessionKey, publicKey publicKeys = []; } - if (signature) { - //detached signature - result.signatures = await message.verifyDetached(signature, publicKeys); - } else { - result.signatures = await message.verify(publicKeys); - } - + result.signatures = signature ? await message.verifyDetached(signature, publicKeys) : await message.verify(publicKeys); return result; }).catch(onError.bind(null, 'Error decrypting message')); @@ -312,21 +303,11 @@ export function sign({ data, privateKeys, armor=true, detached=false}) { var result = {}; return Promise.resolve().then(async function() { - var message; - - if (util.isString(data)) { - message = new CleartextMessage(data); - } else { - message = messageLib.fromBinary(data); - } + var message = util.isString(data) ? new CleartextMessage(data) : messageLib.fromBinary(data); if (detached) { var signature = await message.signDetached(privateKeys); - if (armor) { - result.signature = signature.armor(); - } else { - result.signature = signature; - } + result.signature = armor ? signature.armor() : signature; } else { message = await message.sign(privateKeys); if (armor) { @@ -360,18 +341,8 @@ export function verify({ message, publicKeys, signature=null }) { return Promise.resolve().then(async function() { var result = {}; - if (CleartextMessage.prototype.isPrototypeOf(message)) { - result.data = message.getText(); - } else { - result.data = message.getLiteralData(); - } - - if (signature) { - //detached signature - result.signatures = await message.verifyDetached(signature, publicKeys); - } else { - result.signatures = await message.verify(publicKeys); - } + result.data = CleartextMessage.prototype.isPrototypeOf(message) ? message.getText() : message.getLiteralData(); + result.signatures = signature ? await message.verifyDetached(signature, publicKeys) : await message.verify(publicKeys); return result; }).catch(onError.bind(null, 'Error verifying cleartext signed message')); @@ -392,6 +363,7 @@ export function verify({ message, publicKeys, signature=null }) { * @param {String} algorithm algorithm of the symmetric session key e.g. 'aes128' or 'aes256' * @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} useWildcard (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 * @static */ @@ -410,7 +382,7 @@ export function encryptSessionKey({ data, algorithm, publicKeys, passwords, useW } /** - * Decrypt a symmetric session key with a private key or password. Either a private key or + * Decrypt symmetric session keys with a private key or password. Either a private key or * a password must be specified. * @param {Message} message a message object containing the encrypted session key packets * @param {Key|Array Date: Mon, 12 Feb 2018 19:31:47 +0100 Subject: [PATCH 6/6] useWildcard -> wildcard --- src/message.js | 12 ++++++------ src/openpgp.js | 16 ++++++++-------- test/general/openpgp.js | 4 ++-- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/message.js b/src/message.js index 04009b55..2d9adf48 100644 --- a/src/message.js +++ b/src/message.js @@ -245,10 +245,10 @@ Message.prototype.getText = function() { * @param {Array} keys (optional) public key(s) for message encryption * @param {Array} passwords (optional) password(s) for message encryption * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String } - * @param {Boolean} useWildcard (optional) use a key ID of 0 instead of the public key IDs + * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs * @return {Message} new message with encrypted content */ -Message.prototype.encrypt = function(keys, passwords, sessionKey, useWildcard=false) { +Message.prototype.encrypt = function(keys, passwords, sessionKey, wildcard=false) { let symAlgo, msg, symEncryptedPacket; return Promise.resolve().then(async () => { if (sessionKey) { @@ -269,7 +269,7 @@ Message.prototype.encrypt = function(keys, passwords, sessionKey, useWildcard=fa sessionKey = crypto.generateSessionKey(symAlgo); } - msg = await encryptSessionKey(sessionKey, symAlgo, keys, passwords, useWildcard); + msg = await encryptSessionKey(sessionKey, symAlgo, keys, passwords, wildcard); if (config.aead_protect) { symEncryptedPacket = new packet.SymEncryptedAEADProtected(); @@ -301,10 +301,10 @@ Message.prototype.encrypt = function(keys, passwords, sessionKey, useWildcard=fa * @param {String} symAlgo session key algorithm * @param {Array} publicKeys (optional) public key(s) for message encryption * @param {Array} passwords (optional) for message encryption - * @param {Boolean} useWildcard (optional) use a key ID of 0 instead of the public key IDs + * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs * @return {Message} new message with encrypted content */ -export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, useWildcard=false) { +export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, wildcard=false) { var results, packetlist = new packet.List(); return Promise.resolve().then(async () => { @@ -316,7 +316,7 @@ export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords, us throw new Error('Could not find valid key packet for encryption in key ' + key.primaryKey.getKeyId().toHex()); } var pkESKeyPacket = new packet.PublicKeyEncryptedSessionKey(); - pkESKeyPacket.publicKeyId = useWildcard ? type_keyid.wildcard() : encryptionKeyPacket.getKeyId(); + pkESKeyPacket.publicKeyId = wildcard ? type_keyid.wildcard() : encryptionKeyPacket.getKeyId(); pkESKeyPacket.publicKeyAlgorithm = encryptionKeyPacket.algorithm; pkESKeyPacket.sessionKey = sessionKey; pkESKeyPacket.sessionKeyAlgorithm = symAlgo; diff --git a/src/openpgp.js b/src/openpgp.js index f0cc7892..e2476a15 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -196,17 +196,17 @@ export function decryptKey({ privateKey, passphrase }) { * @param {Boolean} detached (optional) if the signature should be detached (if true, signature will be added to returned object) * @param {Signature} signature (optional) a detached signature to add to the encrypted message * @param {Boolean} returnSessionKey (optional) if the unencrypted session key should be added to returned object - * @param {Boolean} useWildcard (optional) use a key ID of 0 instead of the public key IDs + * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs * @return {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 */ -export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey, filename, armor=true, detached=false, signature=null, returnSessionKey=false, useWildcard=false}) { +export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey, filename, armor=true, detached=false, signature=null, returnSessionKey=false, wildcard=false}) { checkData(data); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords); if (!nativeAEAD() && asyncProxy) { // use web worker if web crypto apis are not supported - return asyncProxy.delegate('encrypt', { data, publicKeys, privateKeys, passwords, sessionKey, filename, armor, detached, signature, returnSessionKey, useWildcard }); + return asyncProxy.delegate('encrypt', { data, publicKeys, privateKeys, passwords, sessionKey, filename, armor, detached, signature, returnSessionKey, wildcard }); } var result = {}; return Promise.resolve().then(async function() { @@ -223,7 +223,7 @@ export function encrypt({ data, publicKeys, privateKeys, passwords, sessionKey, message = await message.sign(privateKeys, signature); } } - return message.encrypt(publicKeys, passwords, sessionKey, useWildcard); + return message.encrypt(publicKeys, passwords, sessionKey, wildcard); }).then(encrypted => { if (armor) { @@ -363,20 +363,20 @@ export function verify({ message, publicKeys, signature=null }) { * @param {String} algorithm algorithm of the symmetric session key e.g. 'aes128' or 'aes256' * @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} useWildcard (optional) use a key ID of 0 instead of the public key IDs + * @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 * @static */ -export function encryptSessionKey({ data, algorithm, publicKeys, passwords, useWildcard=false }) { +export function encryptSessionKey({ data, algorithm, publicKeys, passwords, wildcard=false }) { checkBinary(data); checkString(algorithm, 'algorithm'); publicKeys = toArray(publicKeys); passwords = toArray(passwords); if (asyncProxy) { // use web worker if available - return asyncProxy.delegate('encryptSessionKey', { data, algorithm, publicKeys, passwords, useWildcard }); + return asyncProxy.delegate('encryptSessionKey', { data, algorithm, publicKeys, passwords, wildcard }); } return Promise.resolve().then(async function() { - return { message: await messageLib.encryptSessionKey(data, algorithm, publicKeys, passwords, useWildcard) }; + return { message: await messageLib.encryptSessionKey(data, algorithm, publicKeys, passwords, wildcard) }; }).catch(onError.bind(null, 'Error encrypting session key')); } diff --git a/test/general/openpgp.js b/test/general/openpgp.js index a86fc46b..5bd11f81 100644 --- a/test/general/openpgp.js +++ b/test/general/openpgp.js @@ -730,7 +730,7 @@ describe('OpenPGP.js public api tests', function() { var encOpt = { data: plaintext, publicKeys: publicKey.keys, - useWildcard: true + wildcard: true }; var decOpt = { privateKeys: privateKey.keys @@ -753,7 +753,7 @@ describe('OpenPGP.js public api tests', function() { var encOpt = { data: plaintext, publicKeys: publicKey.keys, - useWildcard: true + wildcard: true }; var decOpt = { privateKeys: [privKeyDE, privateKey.keys[0]]