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
This commit is contained in:
Tankred Hase 2014-06-18 10:02:33 +02:00
parent 77ad3613cf
commit b7a4c13766
15 changed files with 242 additions and 73 deletions

View File

@ -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) {

View File

@ -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]);
});

View File

@ -57,6 +57,7 @@ define(function(require) {
var privateKey = {
_id: keyParams._id,
userId: keyParams.userId,
userIds: keyParams.userIds,
encryptedKey: newPrivateKeyArmored
};

View File

@ -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();

View File

@ -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) {

View File

@ -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;
});
});

View File

@ -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);

View File

@ -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-----'
}
};

View File

@ -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() {

View File

@ -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({

View File

@ -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'

View File

@ -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'

View File

@ -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");
});
});

View File

@ -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();

View File

@ -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() {