From b7a4c13766abe6497e012a59526cb2c1496cf6d2 Mon Sep 17 00:00:00 2001 From: Tankred Hase Date: Wed, 18 Jun 2014 10:02:33 +0200 Subject: [PATCH] Parse multiple user IDs for imported PGP keys Use all pgp (sub) keys when en/decrypting a pgp message Improve input validation for key import Mark manually imported keys so that key refresh does not revoke them --- src/js/controller/contacts.js | 6 ++- src/js/controller/login-new-device.js | 39 ++++++++++++--- src/js/controller/set-passphrase.js | 1 + src/js/controller/write.js | 14 ++++-- src/js/crypto/pgp.js | 22 ++++++--- src/js/dao/email-dao.js | 38 +++++++++------ src/js/dao/keychain-dao.js | 22 ++++++++- test/integration/email-dao-test.js | 12 ++++- test/new-unit/contacts-ctrl-test.js | 7 ++- test/new-unit/email-dao-test.js | 6 ++- test/new-unit/keychain-dao-test.js | 46 ++++++++++++++++-- test/new-unit/login-new-device-ctrl-test.js | 20 +++++++- test/new-unit/pgp-test.js | 54 +++++++++++---------- test/new-unit/set-passphrase-ctrl-test.js | 2 + test/new-unit/write-ctrl-test.js | 26 +++++++++- 15 files changed, 242 insertions(+), 73 deletions(-) diff --git a/src/js/controller/contacts.js b/src/js/controller/contacts.js index db97fb6..9fb6791 100644 --- a/src/js/controller/contacts.js +++ b/src/js/controller/contacts.js @@ -69,14 +69,16 @@ define(function(require) { try { keyParams = pgp.getKeyParams(publicKeyArmored); } catch (e) { - $scope.onError(e); + $scope.onError(new Error('Error reading public key params!')); return; } pubkey = { _id: keyParams._id, userId: keyParams.userId, - publicKey: publicKeyArmored + userIds: keyParams.userIds, + publicKey: publicKeyArmored, + imported: true // mark manually imported keys }; keychain.saveLocalPublicKey(pubkey, function(err) { diff --git a/src/js/controller/login-new-device.js b/src/js/controller/login-new-device.js index f3f274b..3918ff8 100644 --- a/src/js/controller/login-new-device.js +++ b/src/js/controller/login-new-device.js @@ -26,18 +26,29 @@ define(function(require) { keypair = keypair || {}; + var privKeyParams, pubKeyParams; + try { + privKeyParams = pgp.getKeyParams($scope.key.privateKeyArmored); + pubKeyParams = pgp.getKeyParams($scope.key.publicKeyArmored); + } catch (e) { + $scope.onError(new Error('Error reading key params!')); + return; + } + // set parsed private key keypair.privateKey = { - _id: pgp.getKeyId($scope.key.privateKeyArmored), + _id: privKeyParams._id, userId: userId, + userIds: privKeyParams.userIds, encryptedKey: $scope.key.privateKeyArmored }; if (!keypair.publicKey) { // there is no public key on the key server yet... use parsed keypair.publicKey = { - _id: pgp.getKeyId($scope.key.publicKeyArmored), + _id: pubKeyParams._id, userId: userId, + userIds: pubKeyParams.userIds, publicKey: $scope.key.publicKeyArmored }; } @@ -82,18 +93,30 @@ define(function(require) { reader.onload = function(e) { var rawKeys = e.target.result, - index = rawKeys.indexOf('-----BEGIN PGP PRIVATE KEY BLOCK-----'); + privKeyPrexix = '-----BEGIN PGP PRIVATE KEY BLOCK-----', + pubKeyPrefix = '-----BEGIN PGP PUBLIC KEY BLOCK-----', + index = rawKeys.indexOf(privKeyPrexix), + errMsg = 'Keyfile must be formatted like so:\n' + pubKeyPrefix + '\n ... \n' + privKeyPrexix, + keyParts; if (index === -1) { - console.error('Erroneous key file format!'); + scope.onError(new Error(errMsg)); return; } - scope.key = { - publicKeyArmored: rawKeys.substring(0, index), - privateKeyArmored: rawKeys.substring(index, rawKeys.length) + keyParts = { + publicKeyArmored: rawKeys.substring(0, index).trim(), + privateKeyArmored: rawKeys.substring(index, rawKeys.length).trim() }; - scope.$apply(); + + if (keyParts.publicKeyArmored.indexOf(pubKeyPrefix) < 0 || keyParts.privateKeyArmored.indexOf(privKeyPrexix) < 0) { + scope.onError(new Error(errMsg)); + return; + } + + scope.$apply(function() { + scope.key = keyParts; + }); }; reader.readAsText(files[0]); }); diff --git a/src/js/controller/set-passphrase.js b/src/js/controller/set-passphrase.js index d1eb1b6..811a55b 100644 --- a/src/js/controller/set-passphrase.js +++ b/src/js/controller/set-passphrase.js @@ -57,6 +57,7 @@ define(function(require) { var privateKey = { _id: keyParams._id, userId: keyParams.userId, + userIds: keyParams.userIds, encryptedKey: newPrivateKeyArmored }; diff --git a/src/js/controller/write.js b/src/js/controller/write.js index 34a7709..d1c6593 100644 --- a/src/js/controller/write.js +++ b/src/js/controller/write.js @@ -194,10 +194,16 @@ define(function(require) { return; } - // compare again since model could have changed during the roundtrip - if (key && key.userId === recipient.address) { - recipient.key = key; - recipient.secure = true; + if (key) { + // compare again since model could have changed during the roundtrip + var matchingUserId = _.findWhere(key.userIds, { + emailAddress: recipient.address + }); + // compare either primary userId or (if available) multiple IDs + if (key.userId === recipient.address || matchingUserId) { + recipient.key = key; + recipient.secure = true; + } } $scope.checkSendStatus(); diff --git a/src/js/crypto/pgp.js b/src/js/crypto/pgp.js index 649e0b3..e7e1331 100644 --- a/src/js/crypto/pgp.js +++ b/src/js/crypto/pgp.js @@ -100,7 +100,7 @@ define(function(require) { * Read all relevant params of an armored key. */ PGP.prototype.getKeyParams = function(keyArmored) { - var key, packet; + var key, packet, userIds; // process armored key input if (keyArmored) { @@ -113,9 +113,19 @@ define(function(require) { packet = key.getKeyPacket(); + // read user names and email addresses + userIds = []; + key.getUserIds().forEach(function(userId) { + userIds.push({ + name: userId.split('<')[0].trim(), + emailAddress: userId.split('<')[1].split('>')[0].trim() + }); + }); + return { _id: packet.getKeyId().toHex().toUpperCase(), - userId: key.getUserIds()[0].split('<')[1].split('>')[0], + userId: userIds[0].emailAddress, // the primary (first) email address of the key + userIds: userIds, // a dictonary of all the key's name/address pairs fingerprint: packet.getFingerprint().toUpperCase(), algorithm: packet.algorithm, bitSize: packet.getBitSize(), @@ -277,7 +287,7 @@ define(function(require) { // parse armored public keys try { publicKeysArmored.forEach(function(pubkeyArmored) { - publicKeys.push(openpgp.key.readArmored(pubkeyArmored).keys[0]); + publicKeys = publicKeys.concat(openpgp.key.readArmored(pubkeyArmored).keys); }); } catch (err) { callback({ @@ -295,7 +305,7 @@ define(function(require) { * Decrypt and verify a pgp message for a single sender */ PGP.prototype.decrypt = function(ciphertext, publicKeyArmored, callback) { - var publicKey, message, signaturesValid; + var publicKeys, message, signaturesValid; // check keys if (!this._privateKey || !publicKeyArmored) { @@ -307,7 +317,7 @@ define(function(require) { // read keys and ciphertext message try { - publicKey = openpgp.key.readArmored(publicKeyArmored).keys[0]; + publicKeys = openpgp.key.readArmored(publicKeyArmored).keys; message = openpgp.message.readArmored(ciphertext); } catch (err) { callback({ @@ -318,7 +328,7 @@ define(function(require) { } // decrypt and verify pgp message - openpgp.decryptAndVerifyMessage(this._privateKey, [publicKey], message, onDecrypted); + openpgp.decryptAndVerifyMessage(this._privateKey, publicKeys, message, onDecrypted); function onDecrypted(err, decrypted) { if (err) { diff --git a/src/js/dao/email-dao.js b/src/js/dao/email-dao.js index 8fa1c56..c803cb7 100644 --- a/src/js/dao/email-dao.js +++ b/src/js/dao/email-dao.js @@ -119,23 +119,31 @@ define(function(require) { }); function handleExistingKeypair(keypair) { - var pubUserID, privUserID; - - // check if key IDs match - if (!keypair.privateKey._id || keypair.privateKey._id !== keypair.publicKey._id) { - callback({ - errMsg: 'Key IDs dont match!' - }); + var privKeyParams, pubKeyParams; + try { + privKeyParams = self._crypto.getKeyParams(keypair.privateKey.encryptedKey); + pubKeyParams = self._crypto.getKeyParams(keypair.publicKey.publicKey); + } catch (e) { + callback(new Error('Error reading key params!')); return; } - // check if the key's user ID matches the current account - pubUserID = self._crypto.getKeyParams(keypair.publicKey.publicKey).userId; - privUserID = self._crypto.getKeyParams(keypair.privateKey.encryptedKey).userId; - if (pubUserID.indexOf(self._account.emailAddress) === -1 || privUserID.indexOf(self._account.emailAddress) === -1) { - callback({ - errMsg: 'User IDs dont match!' - }); + // check if key IDs match + if (!keypair.privateKey._id || keypair.privateKey._id !== keypair.publicKey._id || keypair.privateKey._id !== privKeyParams._id || keypair.publicKey._id !== pubKeyParams._id) { + callback(new Error('Key IDs dont match!')); + return; + } + + // check that key userIds contain email address of user account + var matchingPrivUserId = _.findWhere(privKeyParams.userIds, { + emailAddress: self._account.emailAddress + }); + var matchingPubUserId = _.findWhere(pubKeyParams.userIds, { + emailAddress: self._account.emailAddress + }); + + if (!matchingPrivUserId || !matchingPubUserId || keypair.privateKey.userId !== self._account.emailAddress || keypair.publicKey.userId !== self._account.emailAddress) { + callback(new Error('User IDs dont match!')); return; } @@ -1453,4 +1461,4 @@ define(function(require) { } return EmailDAO; -}); +}); \ No newline at end of file diff --git a/src/js/dao/keychain-dao.js b/src/js/dao/keychain-dao.js index 2ee4e69..d649012 100644 --- a/src/js/dao/keychain-dao.js +++ b/src/js/dao/keychain-dao.js @@ -42,7 +42,7 @@ define(function(require) { }); _.each(ids, function(i) { - // lookup locally and in storage + // lookup locally and in storage self.lookupPublicKey(i._id, function(err, pubkey) { if (err || !pubkey) { callback({ @@ -82,6 +82,12 @@ define(function(require) { return; } + // no need to refresh manually imported public keys + if (localKey.imported) { + callback(null, localKey); + return; + } + // check if the key id still exists on the key server checkKeyExists(localKey); }); @@ -170,10 +176,24 @@ define(function(require) { return; } + // query primary email address var pubkey = _.findWhere(allPubkeys, { userId: userId }); + // query mutliple userIds (for imported public keys) + if (!pubkey) { + for (var i = 0, match; i < allPubkeys.length; i++) { + match = _.findWhere(allPubkeys[i].userIds, { + emailAddress: userId + }); + if (match) { + pubkey = allPubkeys[i]; + break; + } + } + } + if (pubkey && pubkey._id) { // that user's public key is already in local storage callback(null, pubkey); diff --git a/test/integration/email-dao-test.js b/test/integration/email-dao-test.js index 1401339..be93cf1 100644 --- a/test/integration/email-dao-test.js +++ b/test/integration/email-dao-test.js @@ -122,13 +122,21 @@ define(function(require) { mockKeyPair = { privateKey: { - _id: '0A45D6B44958B0AC', + _id: 'D7FB93FCDFBFC23C', userId: testAccount.user, + userIds: [{ + name: 'John Doe', + emailAddress: testAccount.user + }], encryptedKey: '-----BEGIN PGP PRIVATE KEY BLOCK-----\r\nVersion: OpenPGP.js v.1.20131116\r\nComment: Whiteout Mail - http://whiteout.io\r\n\r\nxcL+BFKODs4BB/9iOF4THsjQMY+WEpT7ShgKxj4bHzRRaQkqczS4nZvP0U3g\r\nqeqCnbpagyeKXA+bhWFQW4GmXtgAoeD5PXs6AZYrw3tWNxLKu2Oe6Tp9K/XI\r\nxTMQ2wl4qZKDXHvuPsJ7cmgaWqpPyXtxA4zHHS3WrkI/6VzHAcI/y6x4szSB\r\nKgSuhI3hjh3s7TybUC1U6AfoQGx/S7e3WwlCOrK8GTClirN/2mCPRC5wuIft\r\nnkoMfA6jK8d2OPrJ63shy5cgwHOjQg/xuk46dNS7tkvGmbaa+X0PgqSKB+Hf\r\nYPPNS/ylg911DH9qa8BqYU2QpNh9jUKXSF+HbaOM+plWkCSAL7czV+R3ABEB\r\nAAH+AwMI8l5bp5J/xgpguvHaT2pX/6D8eU4dvODsvYE9Y4Clj0Nvm2nu4VML\r\nniNb8qpzCXXfFqi1FWGrZ2msClxA1eiXfk2IEe5iAiY3a+FplTevBn6rkAMw\r\nly8wGyiNdE3TVWgCEN5YRaTLpfV02c4ECyKk713EXRAtQCmdty0yxv5ak9ey\r\nXDUVd4a8T3QMgHcAOTXWMFJNUjeeiIdiThDbURJEv+9F+DW+4w5py2iw0PYJ\r\nNm6iAHCjoPQTbGLxstl2BYSocZWxG1usoPKhbugGZK0Vr8rdpsfakjJ9cJUg\r\nYHIH3VT+y+u5mhY681NrB5koRUxDT6ridbytMcoK8xpqYG3FhC8CiVnzpDQ3\r\no1KRkWuxUq66oJhu0wungXcqaDzDUEfeUjMuKVI/d9/ViXy8IH/XdlOy0lLY\r\nOac0ovRjb7zgeVOp2e7N4eTu0dts3SE+Do1gyqZo2rf1dwsJQI9YUtpjYAtr\r\nNBkKyRvBAhg9KPh1y2Y1u3ra5OS0yGuNDD8pXdiN3kxMt5OBlnWeFjL6ll7+\r\nvgiKZooPUZPbFIWi4XBXTv7D5T9THDYmuJpcOffn1AA7j2FM8fkFvtiFyw9J\r\n2S14penv2R7TeybxR6ktD7HtZd34gmGvmOxhWRNU/vfp4SisUcu9jzQq+cJt\r\njoWuJiZ8xvWEC2DD32n9bWyIlGhS4hATqz/gEdSha8hxzT+GJi29jYjp8Hnc\r\n9HwxOArz6Q5h/nDN2Xt5PuCM65J0dathzAm0A7BLRQI+4OjTW575sRKvarzH\r\n8JZ+UYK2BgP4Kbh9JqhnD/2NKD/csuL6No5guyOH8+zekdBtFE394SV8e9N+\r\nzYgzVex4SDG8y/YO7W7Tp6afNb+sqyzEw5Bknypn0Hc3cr9wy1P8jLMM2woL\r\nGRDZ5IutCAV/D/h881dHJs0tV2hpdGVvdXQgVXNlciA8c2FmZXdpdGhtZS50\r\nZXN0dXNlckBnbWFpbC5jb20+wsBcBBABCAAQBQJSjg7aCRDX+5P837/CPAAA\r\n3ZwH/2AVGYB+8RDarP5a5uZPYSxJKeM8zHMbi7LKQWhr5NpkJajZdra1CCGZ\r\nTXTeQSRBvU4SNGOmDAlhf0qCGeXwMHIzrzovkBedHIc/vypEkItdJeXQAaJx\r\nuhQOnmyi9priuzBBx4e9x1aBn+aAdNGiJB4l13L2T4fow8WLIVpVwXB6BWya\r\nlz50JwLzJP6qHxkhvIZElTrQ+Yoo3stS6w/7wNtK/f3MIYkIGVVUrIDgzN0X\r\nm4z6ypN1dsrM6tPkMZ0JlqjHiz7DXpKrWsfNkoVZ9A98osMH2nIDS58JVEDc\r\nAXoFSLsbdmqFmIc2Ew828TjlX+FLU9tlx89WhSMTapzUjHU=\r\n=wxuK\r\n-----END PGP PRIVATE KEY BLOCK-----' }, publicKey: { - _id: '0A45D6B44958B0AC', + _id: 'D7FB93FCDFBFC23C', userId: testAccount.user, + userIds: [{ + name: 'John Doe', + emailAddress: testAccount.user + }], publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: OpenPGP.js v.1.20131116\r\nComment: Whiteout Mail - http://whiteout.io\r\n\r\nxsBNBFKODs4BB/9iOF4THsjQMY+WEpT7ShgKxj4bHzRRaQkqczS4nZvP0U3g\r\nqeqCnbpagyeKXA+bhWFQW4GmXtgAoeD5PXs6AZYrw3tWNxLKu2Oe6Tp9K/XI\r\nxTMQ2wl4qZKDXHvuPsJ7cmgaWqpPyXtxA4zHHS3WrkI/6VzHAcI/y6x4szSB\r\nKgSuhI3hjh3s7TybUC1U6AfoQGx/S7e3WwlCOrK8GTClirN/2mCPRC5wuIft\r\nnkoMfA6jK8d2OPrJ63shy5cgwHOjQg/xuk46dNS7tkvGmbaa+X0PgqSKB+Hf\r\nYPPNS/ylg911DH9qa8BqYU2QpNh9jUKXSF+HbaOM+plWkCSAL7czV+R3ABEB\r\nAAHNLVdoaXRlb3V0IFVzZXIgPHNhZmV3aXRobWUudGVzdHVzZXJAZ21haWwu\r\nY29tPsLAXAQQAQgAEAUCUo4O2gkQ1/uT/N+/wjwAAN2cB/9gFRmAfvEQ2qz+\r\nWubmT2EsSSnjPMxzG4uyykFoa+TaZCWo2Xa2tQghmU103kEkQb1OEjRjpgwJ\r\nYX9Kghnl8DByM686L5AXnRyHP78qRJCLXSXl0AGicboUDp5sovaa4rswQceH\r\nvcdWgZ/mgHTRoiQeJddy9k+H6MPFiyFaVcFwegVsmpc+dCcC8yT+qh8ZIbyG\r\nRJU60PmKKN7LUusP+8DbSv39zCGJCBlVVKyA4MzdF5uM+sqTdXbKzOrT5DGd\r\nCZaox4s+w16Sq1rHzZKFWfQPfKLDB9pyA0ufCVRA3AF6BUi7G3ZqhZiHNhMP\r\nNvE45V/hS1PbZcfPVoUjE2qc1Ix1\r\n=7Wpe\r\n-----END PGP PUBLIC KEY BLOCK-----' } }; diff --git a/test/new-unit/contacts-ctrl-test.js b/test/new-unit/contacts-ctrl-test.js index b4989b3..2e52d51 100644 --- a/test/new-unit/contacts-ctrl-test.js +++ b/test/new-unit/contacts-ctrl-test.js @@ -94,13 +94,16 @@ define(function(require) { cryptoMock.getKeyParams.returns({ _id: '12345', - userId: 'max@example.com' + userId: 'max@example.com', + userIds: [] }); keychainMock.saveLocalPublicKey.withArgs({ _id: '12345', userId: 'max@example.com', - publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----' + userIds: [], + publicKey: '-----BEGIN PGP PUBLIC KEY BLOCK-----', + imported: true }).yields(); scope.listKeys = function() { diff --git a/test/new-unit/email-dao-test.js b/test/new-unit/email-dao-test.js index c6fdda3..93a0f6e 100644 --- a/test/new-unit/email-dao-test.js +++ b/test/new-unit/email-dao-test.js @@ -168,7 +168,11 @@ define(function(require) { describe('#unlock', function() { it('should unlock', function(done) { pgpStub.getKeyParams.returns({ - userId: emailAddress + _id: mockKeyPair.publicKey._id, + userId: emailAddress, + userIds: [{ + emailAddress: emailAddress + }] }); pgpStub.importKeys.withArgs({ diff --git a/test/new-unit/keychain-dao-test.js b/test/new-unit/keychain-dao-test.js index 153cff4..da15115 100644 --- a/test/new-unit/keychain-dao-test.js +++ b/test/new-unit/keychain-dao-test.js @@ -60,8 +60,13 @@ define(function(require) { var getPubKeyStub, oldKey = { _id: 123 - }, newKey = { + }, + newKey = { _id: 456 + }, + importedKey = { + _id: 789, + imported: true }; beforeEach(function() { @@ -196,6 +201,20 @@ define(function(require) { }); }); + it('should not remove manually imported key', function(done) { + getPubKeyStub.yields(null, importedKey); + + keychainDao.refreshKeyForUserId(testUser, function(err, key) { + expect(err).to.not.exist; + expect(key).to.equal(importedKey); + + expect(getPubKeyStub.calledOnce).to.be.true; + expect(pubkeyDaoStub.get.calledOnce).to.be.false; + + done(); + }); + }); + it('should update not the key when offline', function(done) { getPubKeyStub.yields(null, oldKey); pubkeyDaoStub.get.withArgs(oldKey._id).yields({ @@ -429,8 +448,27 @@ define(function(require) { }); }); + it('should work for keys with secondary userIds', function(done) { + lawnchairDaoStub.list.yields(null, [{ + _id: '12345', + userId: 'not testUser', + userIds: [{ + emailAddress: testUser + }], + publicKey: 'asdf' + }]); + + keychainDao.getReceiverPublicKey(testUser, function(err, key) { + expect(err).to.not.exist; + expect(key).to.exist; + expect(key._id).to.equal('12345'); + expect(lawnchairDaoStub.list.calledOnce).to.be.true; + done(); + }); + }); + it('should fail due to error in pubkey dao', function(done) { - lawnchairDaoStub.list.yields(); + lawnchairDaoStub.list.yields(null, []); pubkeyDaoStub.getByUserId.yields({}); keychainDao.getReceiverPublicKey(testUser, function(err, key) { @@ -443,7 +481,7 @@ define(function(require) { }); it('should work from pubkey dao with empty result', function(done) { - lawnchairDaoStub.list.yields(); + lawnchairDaoStub.list.yields(null, []); pubkeyDaoStub.getByUserId.yields(); keychainDao.getReceiverPublicKey(testUser, function(err, key) { @@ -456,7 +494,7 @@ define(function(require) { }); it('should work from pubkey dao', function(done) { - lawnchairDaoStub.list.yields(); + lawnchairDaoStub.list.yields(null, []); pubkeyDaoStub.getByUserId.yields(null, { _id: '12345', publicKey: 'asdf' diff --git a/test/new-unit/login-new-device-ctrl-test.js b/test/new-unit/login-new-device-ctrl-test.js index d9ce2ca..83ad0a9 100644 --- a/test/new-unit/login-new-device-ctrl-test.js +++ b/test/new-unit/login-new-device-ctrl-test.js @@ -64,7 +64,10 @@ define(function(require) { privateKeyArmored: 'b' }; - pgpMock.getKeyId.returns(keyId); + pgpMock.getKeyParams.returns({ + _id: 'id', + userIds: [] + }); keychainMock.getUserKeyPair.withArgs(emailAddress).yields(null, { _id: keyId, @@ -86,7 +89,10 @@ define(function(require) { publicKeyArmored: 'a' }; - pgpMock.getKeyId.returns(keyId); + pgpMock.getKeyParams.returns({ + _id: 'id', + userIds: [] + }); keychainMock.getUserKeyPair.withArgs(emailAddress).yields(); emailDaoMock.unlock.withArgs(sinon.match.any, passphrase).yields(); @@ -104,6 +110,11 @@ define(function(require) { privateKeyArmored: 'b' }; + pgpMock.getKeyParams.returns({ + _id: 'id', + userIds: [] + }); + keychainMock.getUserKeyPair.withArgs(emailAddress).yields(null, { _id: keyId, publicKey: 'a' @@ -131,6 +142,11 @@ define(function(require) { privateKeyArmored: 'b' }; + pgpMock.getKeyParams.returns({ + _id: 'id', + userIds: [] + }); + keychainMock.getUserKeyPair.withArgs(emailAddress).yields(null, { _id: keyId, publicKey: 'a' diff --git a/test/new-unit/pgp-test.js b/test/new-unit/pgp-test.js index 3ef57d4..57aadf1 100644 --- a/test/new-unit/pgp-test.js +++ b/test/new-unit/pgp-test.js @@ -13,32 +13,32 @@ define(function(require) { keySize = 512, keyId = 'F6F60E9B42CDFF4C', pubkey = '-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n' + - 'Version: OpenPGP.js v0.5.1\r\n' + - 'Comment: http://openpgpjs.org\r\n' + - '\r\n' + - 'xk0EUlhMvAEB/2MZtCUOAYvyLFjDp3OBMGn3Ev8FwjzyPbIF0JUw+L7y2XR5\r\n' + - 'RVGvbK88unV3cU/1tOYdNsXI6pSp/Ztjyv7vbBUAEQEAAc0pV2hpdGVvdXQg\r\n' + - 'VXNlciA8d2hpdGVvdXQudGVzdEB0LW9ubGluZS5kZT7CXAQQAQgAEAUCUlhM\r\n' + - 'vQkQ9vYOm0LN/0wAAAW4Af9C+kYW1AvNWmivdtr0M0iYCUjM9DNOQH1fcvXq\r\n' + - 'IiN602mWrkd8jcEzLsW5IUNzVPLhrFIuKyBDTpLnC07Loce1\r\n' + - '=6XMW\r\n' + - '-----END PGP PUBLIC KEY BLOCK-----\r\n\r\n', + 'Version: OpenPGP.js v0.5.1\r\n' + + 'Comment: http://openpgpjs.org\r\n' + + '\r\n' + + 'xk0EUlhMvAEB/2MZtCUOAYvyLFjDp3OBMGn3Ev8FwjzyPbIF0JUw+L7y2XR5\r\n' + + 'RVGvbK88unV3cU/1tOYdNsXI6pSp/Ztjyv7vbBUAEQEAAc0pV2hpdGVvdXQg\r\n' + + 'VXNlciA8d2hpdGVvdXQudGVzdEB0LW9ubGluZS5kZT7CXAQQAQgAEAUCUlhM\r\n' + + 'vQkQ9vYOm0LN/0wAAAW4Af9C+kYW1AvNWmivdtr0M0iYCUjM9DNOQH1fcvXq\r\n' + + 'IiN602mWrkd8jcEzLsW5IUNzVPLhrFIuKyBDTpLnC07Loce1\r\n' + + '=6XMW\r\n' + + '-----END PGP PUBLIC KEY BLOCK-----\r\n\r\n', privkey = '-----BEGIN PGP PRIVATE KEY BLOCK-----\r\n' + - 'Version: OpenPGP.js v0.5.1\r\n' + - 'Comment: http://openpgpjs.org\r\n' + - '\r\n' + - 'xcBeBFJYTLwBAf9jGbQlDgGL8ixYw6dzgTBp9xL/BcI88j2yBdCVMPi+8tl0\r\n' + - 'eUVRr2yvPLp1d3FP9bTmHTbFyOqUqf2bY8r+72wVABEBAAH+AwMIhNB4ivtv\r\n' + - 'Y2xg6VeMcjjHxZayESHACV+nQx5Tx6ev6xzIF1Qh72fNPDppLhFSFOuTTMsU\r\n' + - 'kTN4c+BVYt29spH+cA1jcDAxQ2ULrNAXo+hheOqhpedTs8aCbcLFkJAS16hk\r\n' + - 'YSk4OnJgp/z24rVju1SHRSFbgundPzmNgXeX9e8IkviGhhQ11Wc5YwVkx03t\r\n' + - 'Z3MdDMF0jyhopbPIoBdyJB0dhvBh98w3JmwpYh9wjUA9MBHD1tvHpRmSZ3BM\r\n' + - 'UCmATn2ZLWBRWiYqFbgDnL1GM80pV2hpdGVvdXQgVXNlciA8d2hpdGVvdXQu\r\n' + - 'dGVzdEB0LW9ubGluZS5kZT7CXAQQAQgAEAUCUlhMvQkQ9vYOm0LN/0wAAAW4\r\n' + - 'Af9C+kYW1AvNWmivdtr0M0iYCUjM9DNOQH1fcvXqIiN602mWrkd8jcEzLsW5\r\n' + - 'IUNzVPLhrFIuKyBDTpLnC07Loce1\r\n' + - '=ULta\r\n' + - '-----END PGP PRIVATE KEY BLOCK-----\r\n'; + 'Version: OpenPGP.js v0.5.1\r\n' + + 'Comment: http://openpgpjs.org\r\n' + + '\r\n' + + 'xcBeBFJYTLwBAf9jGbQlDgGL8ixYw6dzgTBp9xL/BcI88j2yBdCVMPi+8tl0\r\n' + + 'eUVRr2yvPLp1d3FP9bTmHTbFyOqUqf2bY8r+72wVABEBAAH+AwMIhNB4ivtv\r\n' + + 'Y2xg6VeMcjjHxZayESHACV+nQx5Tx6ev6xzIF1Qh72fNPDppLhFSFOuTTMsU\r\n' + + 'kTN4c+BVYt29spH+cA1jcDAxQ2ULrNAXo+hheOqhpedTs8aCbcLFkJAS16hk\r\n' + + 'YSk4OnJgp/z24rVju1SHRSFbgundPzmNgXeX9e8IkviGhhQ11Wc5YwVkx03t\r\n' + + 'Z3MdDMF0jyhopbPIoBdyJB0dhvBh98w3JmwpYh9wjUA9MBHD1tvHpRmSZ3BM\r\n' + + 'UCmATn2ZLWBRWiYqFbgDnL1GM80pV2hpdGVvdXQgVXNlciA8d2hpdGVvdXQu\r\n' + + 'dGVzdEB0LW9ubGluZS5kZT7CXAQQAQgAEAUCUlhMvQkQ9vYOm0LN/0wAAAW4\r\n' + + 'Af9C+kYW1AvNWmivdtr0M0iYCUjM9DNOQH1fcvXqIiN602mWrkd8jcEzLsW5\r\n' + + 'IUNzVPLhrFIuKyBDTpLnC07Loce1\r\n' + + '=ULta\r\n' + + '-----END PGP PRIVATE KEY BLOCK-----\r\n'; beforeEach(function() { pgp = new PGP(); @@ -215,6 +215,8 @@ define(function(require) { expect(params._id).to.equal("F6F60E9B42CDFF4C"); expect(params.bitSize).to.equal(keySize); expect(params.userId).to.equal("whiteout.test@t-online.de"); + expect(params.userIds[0].name).to.equal("Whiteout User"); + expect(params.userIds[0].emailAddress).to.equal("whiteout.test@t-online.de"); expect(params.algorithm).to.equal("rsa_encrypt_sign"); }); @@ -224,6 +226,8 @@ define(function(require) { expect(params._id).to.equal("F6F60E9B42CDFF4C"); expect(params.bitSize).to.equal(keySize); expect(params.userId).to.equal("whiteout.test@t-online.de"); + expect(params.userIds[0].name).to.equal("Whiteout User"); + expect(params.userIds[0].emailAddress).to.equal("whiteout.test@t-online.de"); expect(params.algorithm).to.equal("rsa_encrypt_sign"); }); }); diff --git a/test/new-unit/set-passphrase-ctrl-test.js b/test/new-unit/set-passphrase-ctrl-test.js index fdc1393..8709556 100644 --- a/test/new-unit/set-passphrase-ctrl-test.js +++ b/test/new-unit/set-passphrase-ctrl-test.js @@ -32,6 +32,7 @@ define(function(require) { _id: dummyKeyId, fingerprint: dummyFingerprint, userId: emailAddress, + userIds: [], bitSize: keySize }); @@ -66,6 +67,7 @@ define(function(require) { keychainMock.saveLocalPrivateKey.withArgs({ _id: dummyKeyId, userId: emailAddress, + userIds: [], encryptedKey: 'newArmoredKey' }).yields(); diff --git a/test/new-unit/write-ctrl-test.js b/test/new-unit/write-ctrl-test.js index 78e9f08..a8706ec 100644 --- a/test/new-unit/write-ctrl-test.js +++ b/test/new-unit/write-ctrl-test.js @@ -232,7 +232,7 @@ define(function(require) { scope.verify(recipient); }); - it('should work', function(done) { + it('should work for main userId', function(done) { var recipient = { address: 'asdf@example.com' }; @@ -253,6 +253,30 @@ define(function(require) { scope.verify(recipient); }); + + it('should work for secondary userId', function(done) { + var recipient = { + address: 'asdf@example.com' + }; + var key = { + userId: 'qwer@example.com', + userIds: [{ + emailAddress: 'asdf@example.com' + }] + }; + + keychainMock.refreshKeyForUserId.withArgs(recipient.address).yields(null, key); + + scope.$digest = function() { + expect(recipient.key).to.deep.equal(key); + expect(recipient.secure).to.be.true; + expect(scope.checkSendStatus.callCount).to.equal(2); + expect(keychainMock.refreshKeyForUserId.calledOnce).to.be.true; + done(); + }; + + scope.verify(recipient); + }); }); describe('checkSendStatus', function() {