From 5e2651dc18b3d00f6358b05f31b89b3ebaee8c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Br=C3=BCll?= Date: Wed, 29 Jan 2014 18:05:32 +0100 Subject: [PATCH] removed the need to store a public key for each contact --- spec/helpers/fixtures.js | 19 ++++++++++++++- spec/performance/profile_spec.js | 14 +++++------ spec/src/contacts_spec.js | 22 ++++------------- spec/src/foreign/locker_spec.js | 2 +- spec/src/locker_spec.js | 6 +---- src/contacts.js | 18 ++++---------- src/foreign/locker.js | 3 +-- src/locker.js | 42 ++++++++++++++++---------------- 8 files changed, 58 insertions(+), 68 deletions(-) diff --git a/spec/helpers/fixtures.js b/spec/helpers/fixtures.js index e077c77..b8ad1ef 100644 --- a/spec/helpers/fixtures.js +++ b/spec/helpers/fixtures.js @@ -151,7 +151,7 @@ var fixtures = { lockedProfile: function () { return this._getOrGenerate("lockedProfile", function () { - return epdRoot.Locker.lock(this.profile(), this.password()); + return epdRoot.Locker.lock(this.profile(), this.password(), this.publicKeyResolver()); }); }, @@ -167,6 +167,23 @@ var fixtures = { }); }, + publicKeyResolver: function () { + return this._getOrGenerate("publicKeyResolver", function () { + var scope = this; + return function (documentId) { + switch (documentId) { + case scope.profile().id: + return scope.profile().publicKey; + case scope.anotherProfile().id: + return scope.anotherProfile().publicKey; + default: + console.error("cannot resolve public key of id " + documentId + " --- " + scope.profile().id); + return null; + } + }; + }); + }, + testHangOutId: function () { return this._getOrGenerate("testHangOutId", function () { var hangOutId = epdRoot.Sections.HangOuts.add(this.profile(), "Test hang out", "test_hang_out"); diff --git a/spec/performance/profile_spec.js b/spec/performance/profile_spec.js index ca44002..c88acb9 100644 --- a/spec/performance/profile_spec.js +++ b/spec/performance/profile_spec.js @@ -4,9 +4,8 @@ describe("Performance", function () { describe("Profile", function () { var profile - , keyPair , profileSize = function () { - var lockedProfile = epdRoot.Locker.lock(profile, fixtures.password()) + var lockedProfile = epdRoot.Locker.lock(profile, fixtures.password(), fixtures.publicKeyResolver()) , lockedProfileString = JSON.stringify(lockedProfile); return lockedProfileString.length; @@ -14,10 +13,7 @@ describe("Performance", function () { , difference = function (a, b) { return b - a; }; beforeEach(function () { - if (!profile) { - profile = epdRoot.Object.clone(fixtures.profile()); - keyPair = epdRoot.Crypt.Asymmetric.generateKeyPair(); - } + profile = epdRoot.Object.clone(fixtures.profile()); }); it("should not grow to much if new contacts are added", function () { @@ -26,7 +22,7 @@ describe("Performance", function () { sizes.push(profileSize()); for (var index = 0; index < 10; index++) { var contactProfileId = epdRoot.Crypt.Object.generateId(); - epdRoot.Contacts.add(profile, contactProfileId, keyPair.publicKey); + epdRoot.Contacts.add(profile, contactProfileId); sizes.push(profileSize()); } @@ -46,7 +42,9 @@ describe("Performance", function () { sizes.push(profileSize()); for (var index = 0; index < 10; index++) { - profile = epdRoot.Locker.unlock(epdRoot.Locker.lock(profile, fixtures.password()), fixtures.password()); + profile = epdRoot.Locker.unlock( + epdRoot.Locker.lock(profile, fixtures.password(), fixtures.publicKeyResolver()), + fixtures.password()); sizes.push(profileSize()); } diff --git a/spec/src/contacts_spec.js b/spec/src/contacts_spec.js index acd001e..5705efe 100644 --- a/spec/src/contacts_spec.js +++ b/spec/src/contacts_spec.js @@ -3,10 +3,7 @@ describe("Contacts", function () { var namespace = epdRoot.Contacts , profile - , otherProfile - , profileGetFunction = function (id) { - return otherProfile && otherProfile.id === id ? otherProfile : undefined; - }; + , otherProfile; beforeEach(function () { profile = epdRoot.Object.clone(fixtures.profile()); @@ -34,15 +31,6 @@ describe("Contacts", function () { }); - describe("#publicKeyForContactId", function () { - - it("should return the public key for the given contact id", function () { - var publicKey = namespace.publicKeyForContactId(profile, fixtures.anotherProfile().id); - expect(publicKey).toEqual(fixtures.anotherProfile().publicKey); - }); - - }); - describe("#keysForContactId", function () { it("should return the keys for the given contact", function () { @@ -64,17 +52,17 @@ describe("Contacts", function () { describe("#add", function () { it("should add the given profile to the contacts", function () { - profile = namespace.add(profile, otherProfile.id, otherProfile.publicKey); + profile = namespace.add(profile, otherProfile.id); expect(namespace.ids(profile)).toContain(otherProfile.id); }); it("should do nothing if the contact has been added before", function () { - profile = namespace.add(profile, fixtures.anotherProfile().id, fixtures.anotherProfile().publicKey); + profile = namespace.add(profile, fixtures.anotherProfile().id); expect(namespace.ids(profile)).toEqual([ fixtures.anotherProfile().id ]); }); it("should not add a sections key if the contact is the profile owner", function () { - profile = namespace.add(profile, profile.id, profile.publicKey); + profile = namespace.add(profile, profile.id); expect(profile.contacts[ profile.id ].sections).toBeUndefined(); }); @@ -92,7 +80,7 @@ describe("Contacts", function () { describe("#ensureAdded", function () { it("should add the given contact if missing", function () { - profile = namespace.ensureAdded(profile, [ otherProfile.id ], profileGetFunction); + profile = namespace.ensureAdded(profile, [ otherProfile.id ]); expect(namespace.ids(profile)).toContain(otherProfile.id); }); diff --git a/spec/src/foreign/locker_spec.js b/spec/src/foreign/locker_spec.js index 085e002..7259f6d 100644 --- a/spec/src/foreign/locker_spec.js +++ b/spec/src/foreign/locker_spec.js @@ -29,7 +29,7 @@ describe("Foreign.Locker", function () { var otherProfile = epdRoot.Generator.generate() , unlockProfile = namespace.unlock(fixtures.lockedProfile(), otherProfile); - expect(unlockProfile.contacts[ fixtures.anotherProfile().id ]).toEqual({ publicKey: fixtures.anotherProfile().publicKey }); + expect(unlockProfile.contacts[ fixtures.anotherProfile().id ]).toEqual({ }); }); it("should return a profile where the right keys are unlocked", function () { diff --git a/spec/src/locker_spec.js b/spec/src/locker_spec.js index 591d8d5..56bd695 100644 --- a/spec/src/locker_spec.js +++ b/spec/src/locker_spec.js @@ -9,7 +9,7 @@ describe("Locker", function () { beforeEach(function () { if (!lockedProfile) { - lockedProfile = namespace.lock(fixtures.profile(), fixtures.password()); + lockedProfile = namespace.lock(fixtures.profile(), fixtures.password(), fixtures.publicKeyResolver()); } }); @@ -97,10 +97,6 @@ describe("Locker", function () { expect(epdRoot.Sections.byId(unlockedProfile, "closed")).toEqual({ modules: { } }); }); - it("should decode each contact public key", function () { - expect(epdRoot.Contacts.publicKeyForContactId(unlockedProfile, fixtures.anotherProfile().id)).toBeOfType("rsaKey"); - }); - it("should reconstruct each contact keys", function () { expect(epdRoot.Contacts.keyForContactIdAndSectionId(unlockedProfile, fixtures.anotherProfile().id, "test")).toBeOfType("aesKey"); }); diff --git a/src/contacts.js b/src/contacts.js index a1c528a..740dda6 100644 --- a/src/contacts.js +++ b/src/contacts.js @@ -18,10 +18,6 @@ }); }; - $$.publicKeyForContactId = function (profile, contactId) { - return profile.contacts[contactId].publicKey; - }; - $$.keysForContactId = function (profile, contactId) { return profile.contacts[contactId].keys; }; @@ -30,17 +26,14 @@ return profile.contacts[contactId].keys[sectionId]; }; - $$.add = function (profile, id, publicKey) { + $$.add = function (profile, id) { var contacts = profile.contacts; if (contacts[id]) { return profile; } - contacts[id] = { - publicKey: publicKey, - keys: { } - }; + contacts[id] = { keys: { } }; if (profile.id !== id) { contacts[id].sections = [ ]; @@ -54,13 +47,12 @@ return profile; }; - $$.ensureAdded = function (profile, ids, profileGetFunction) { + $$.ensureAdded = function (profile, ids) { var contactIds = $$.ids(profile); $.Iterator.each(ids, function (_, id) { - var contactProfile = profileGetFunction(id); - if (contactProfile && !$.Collection.include(contactIds, id)) { - profile = $$.add(profile, contactProfile.id, contactProfile.publicKey); + if (!$.Collection.include(contactIds, id)) { + profile = $$.add(profile, id); } }); diff --git a/src/foreign/locker.js b/src/foreign/locker.js index 8e2bf59..fbfeba1 100644 --- a/src/foreign/locker.js +++ b/src/foreign/locker.js @@ -12,7 +12,7 @@ , _decryptContactKeys = function (foreignProfile, profile) { $.Iterator.each(foreignProfile.contacts, function (contactId, container) { - if (profile && profile.publicKey && container.publicKey === $.Crypt.Coder.encode(profile.publicKey)) { + if (profile && profile.id && profile.id === contactId) { container.keys = $.Crypt.Asymmetric.Object.decrypt( $.Crypt.Coder.decode(container.keys), profile.publicKey, profile.privateKey); @@ -20,7 +20,6 @@ container.keys[id] = $.Crypt.Coder.decode(key); }); } else { - container.publicKey = $.Crypt.Coder.decode(container.publicKey); delete(container.keys); delete(container.sections); } diff --git a/src/locker.js b/src/locker.js index 7cb36ab..f914474 100644 --- a/src/locker.js +++ b/src/locker.js @@ -14,26 +14,28 @@ }); } - , _encryptContactKeys = function (profile, closedSectionKey) { + , _encryptContactKeys = function (profile, closedSectionKey, publicKeyResolver) { $.Iterator.each(profile.contacts, function (contactId, contact) { - var keys = contact.keys; - if (keys) { - $.Iterator.each(keys, function (id, key) { - keys[id] = $.Crypt.Coder.encode(key); - }); - contact.keys = $.Crypt.Coder.encode( - $.Crypt.Asymmetric.Object.encrypt(keys, contact.publicKey)); - } - contact.publicKey = $.Crypt.Coder.encode(contact.publicKey); + var publicKey = publicKeyResolver(contactId); + if (publicKey) { + var keys = contact.keys; + if (keys) { + $.Iterator.each(keys, function (id, key) { + keys[id] = $.Crypt.Coder.encode(key); + }); + contact.keys = $.Crypt.Coder.encode( + $.Crypt.Asymmetric.Object.encrypt(keys, publicKey)); + } - // fix for old profiles that still have this obsolete sections key - if (contactId === profile.id) { - delete(contact.sections); - } + // fix for old profiles that still have this obsolete sections key + if (contactId === profile.id) { + delete(contact.sections); + } - if (contact.sections) { - contact.sections = $.Crypt.Coder.encode( - $.Crypt.Symmetric.Object.encrypt(contact.sections, closedSectionKey)); + if (contact.sections) { + contact.sections = $.Crypt.Coder.encode( + $.Crypt.Symmetric.Object.encrypt(contact.sections, closedSectionKey)); + } } }); } @@ -88,7 +90,6 @@ , _decryptOwnContactKeys = function (profile) { var contact = profile.contacts[profile.id]; - contact.publicKey = $.Crypt.Coder.decode(contact.publicKey); contact.keys = $.Crypt.Asymmetric.Object.decrypt( $.Crypt.Coder.decode(contact.keys), profile.publicKey, profile.privateKey); $.Iterator.each(contact.keys, function (id, key) { @@ -103,7 +104,6 @@ contact.sections = $.Crypt.Symmetric.Object.decrypt( $.Crypt.Coder.decode(contact.sections), closedSectionKey); } - contact.publicKey = $.Crypt.Coder.decode(contact.publicKey); contact.keys = { }; $.Iterator.each(contact.sections, function (index, sectionId) { contact.keys[sectionId] = $.Sections.findKey(profile.contacts, sectionId); @@ -127,10 +127,10 @@ }); }; - $$.lock = function (unlockedProfile, password) { + $$.lock = function (unlockedProfile, password, publicKeyResolver) { var profile = $.Object.clone(unlockedProfile); _encryptSections(profile); - _encryptContactKeys(profile, $.Sections.findKey(unlockedProfile.contacts, "closed")); + _encryptContactKeys(profile, $.Sections.findKey(unlockedProfile.contacts, "closed"), publicKeyResolver); _encryptPrivateKey(profile, password); _encodePublicKey(profile); _sign(profile, unlockedProfile.publicKey, unlockedProfile.privateKey);