Skip to content

Commit

Permalink
removed the need to store a public key for each contact
Browse files Browse the repository at this point in the history
  • Loading branch information
Philipp Brüll committed Jan 29, 2014
1 parent 6c4fe20 commit 5e2651d
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 68 deletions.
19 changes: 18 additions & 1 deletion spec/helpers/fixtures.js
Expand Up @@ -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());
});
},

Expand All @@ -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");
Expand Down
14 changes: 6 additions & 8 deletions spec/performance/profile_spec.js
Expand Up @@ -4,20 +4,16 @@ 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;
}
, 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 () {
Expand All @@ -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());
}

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

Expand Down
22 changes: 5 additions & 17 deletions spec/src/contacts_spec.js
Expand Up @@ -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());
Expand Down Expand Up @@ -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 () {
Expand All @@ -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();
});

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

Expand Down
2 changes: 1 addition & 1 deletion spec/src/foreign/locker_spec.js
Expand Up @@ -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 () {
Expand Down
6 changes: 1 addition & 5 deletions spec/src/locker_spec.js
Expand Up @@ -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());
}
});

Expand Down Expand Up @@ -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");
});
Expand Down
18 changes: 5 additions & 13 deletions src/contacts.js
Expand Up @@ -18,10 +18,6 @@
});
};

$$.publicKeyForContactId = function (profile, contactId) {
return profile.contacts[contactId].publicKey;
};

$$.keysForContactId = function (profile, contactId) {
return profile.contacts[contactId].keys;
};
Expand All @@ -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 = [ ];
Expand All @@ -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);
}
});

Expand Down
3 changes: 1 addition & 2 deletions src/foreign/locker.js
Expand Up @@ -12,15 +12,14 @@

, _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);
$.Iterator.each(container.keys, function (id, key) {
container.keys[id] = $.Crypt.Coder.decode(key);
});
} else {
container.publicKey = $.Crypt.Coder.decode(container.publicKey);
delete(container.keys);
delete(container.sections);
}
Expand Down
42 changes: 21 additions & 21 deletions src/locker.js
Expand Up @@ -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));
}
}
});
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit 5e2651d

Please sign in to comment.