diff --git a/static/js/controllers/mediastreamcontroller.js b/static/js/controllers/mediastreamcontroller.js index e1c1f655..99b8f80a 100644 --- a/static/js/controllers/mediastreamcontroller.js +++ b/static/js/controllers/mediastreamcontroller.js @@ -123,6 +123,7 @@ define(['underscore', 'bigscreen', 'moment', 'sjcl', 'webrtc.adapter'], function $scope.status = "initializing"; $scope.id = null; $scope.userid = null; + $scope.suserid = null; $scope.peer = null; $scope.dialing = null; $scope.conference = null; @@ -370,6 +371,7 @@ define(['underscore', 'bigscreen', 'moment', 'sjcl', 'webrtc.adapter'], function safeApply($scope, function(scope) { scope.id = scope.myid = data.Id; scope.userid = data.Userid; + scope.suserid = data.Suserid; scope.turn = data.Turn; scope.stun = data.Stun; scope.refreshWebrtcSettings(); @@ -547,7 +549,7 @@ define(['underscore', 'bigscreen', 'moment', 'sjcl', 'webrtc.adapter'], function if (opts.soft) { return; } - $scope.userid = null; + $scope.userid = $scope.suserid = null; break; case "error": if (reconnecting || connected) { @@ -623,10 +625,12 @@ define(['underscore', 'bigscreen', 'moment', 'sjcl', 'webrtc.adapter'], function }); $scope.$watch("userid", function(userid) { + var suserid; if (userid) { - console.info("Session is now authenticated:", userid); + suserid = $scope.suserid; + console.info("Session is now authenticated:", userid, suserid); } - appData.e.triggerHandler("authenticationChanged", [userid]); + appData.e.triggerHandler("authenticationChanged", [userid, suserid]); }); // Apply all layout stuff as classes to our element. diff --git a/static/js/services/buddysession.js b/static/js/services/buddysession.js index 7d153c51..d45fcd86 100644 --- a/static/js/services/buddysession.js +++ b/static/js/services/buddysession.js @@ -45,7 +45,7 @@ define(["underscore"], function(_) { } } } else { - this.set({}); + this.use(null, {}); } }; diff --git a/static/js/services/contacts.js b/static/js/services/contacts.js index 7c9f1faf..b9a49e6c 100644 --- a/static/js/services/contacts.js +++ b/static/js/services/contacts.js @@ -120,16 +120,17 @@ define(['underscore', 'jquery', 'modernizr', 'sjcl'], function(underscore, $, Mo }; // contacts - return ["appData", "contactData", function(appData, contactData) { + return ["appData", "contactData", "mediaStream", function(appData, contactData, mediaStream) { var Contacts = function() { this.e = $({}); this.userid = null; + this.key = null; this.database = null; - appData.e.on("authenticationChanged", _.bind(function(event, userid) { - var database = this.open(userid); + appData.e.on("authenticationChanged", _.bind(function(event, userid, suserid) { + var database = this.open(userid, suserid); if (database && userid) { // TODO(longsleep): This needs to be delayed util self has ha userid. if (database.ready) { @@ -150,7 +151,7 @@ define(['underscore', 'jquery', 'modernizr', 'sjcl'], function(underscore, $, Mo }; - Contacts.prototype.open = function(userid) { + Contacts.prototype.open = function(userid, suserid) { if (this.database && (!userid || this.userid !== userid)) { // Unload existing contacts. @@ -163,9 +164,10 @@ define(['underscore', 'jquery', 'modernizr', 'sjcl'], function(underscore, $, Mo if (!Modernizr.indexeddb) { return; } - // Create HMAC database name for user. - var hmac = new sjcl.misc.hmac('mediastream'); - var id = "mediastream-"+sjcl.codec.base64.fromBits(hmac.encrypt(userid)); + // Create secure key for hashing and encryption. + this.key = sjcl.codec.base64.fromBits(sjcl.hash.sha256.hash(suserid+mediaStream.config.Token)); + // Create database name for user which. + var id = "mediastream-" + this.id(userid); console.log("Open of database:", id); var database = this.database = new Database(id); return database; @@ -176,14 +178,53 @@ define(['underscore', 'jquery', 'modernizr', 'sjcl'], function(underscore, $, Mo }; + Contacts.prototype.id = function(userid) { + + var hmac = new sjcl.misc.hmac(this.key); + return sjcl.codec.base64.fromBits(hmac.encrypt(userid)); + + }; + + Contacts.prototype.encrypt = function(data) { + + return sjcl.encrypt(this.key, JSON.stringify(data)); + + }; + + Contacts.prototype.decrypt = function(data) { + + var result; + try { + var s = sjcl.decrypt(this.key, data); + result = JSON.parse(s); + } catch(err) { + console.error("Failed to decrypt contact data", err); + } + return result; + + }; + Contacts.prototype.load = function() { if (this.database) { console.log("Load contacts from storage", this); + var remove = []; this.database.all("contacts", _.bind(function(data) { - var contact = contactData.addByData(data.contact); - // TODO(longsleep): Convert buddyImage string to Blob. - this.e.triggerHandler("contactadded", contact); + var d = this.decrypt(data.contact); + if (d) { + var contact = contactData.addByData(d); + // TODO(longsleep): Convert buddyImage string to Blob. + this.e.triggerHandler("contactadded", d); + } else { + // Remove empty or invalid entries automatically. + remove.push(data.id); + } }, this)); + // Remove marked entries. + if (remove.length) { + _.each(remove, _.bind(function(id) { + this.database.delete("contacts", id); + }, this)); + } } }; @@ -198,8 +239,8 @@ define(['underscore', 'jquery', 'modernizr', 'sjcl'], function(underscore, $, Mo this.e.triggerHandler("contactadded", contact); if (this.database) { this.database.put("contacts", { - id: contact.Userid, - contact: contact + id: this.id(contact.Userid), + contact: this.encrypt(contact) }) } }; @@ -210,7 +251,7 @@ define(['underscore', 'jquery', 'modernizr', 'sjcl'], function(underscore, $, Mo if (contact) { contactData.remove(userid); if (this.database) { - this.database.delete("contacts", userid); + this.database.delete("contacts", this.id(userid)); } this.e.triggerHandler("contactremoved", contact); }