diff --git a/src/js/crypto/crypto.js b/src/js/crypto/crypto.js index facabec..d087e62 100644 --- a/src/js/crypto/crypto.js +++ b/src/js/crypto/crypto.js @@ -6,6 +6,7 @@ app.crypto.Crypto = function(window, util) { 'use strict'; var symmetricUserKey = null, // the user's secret key used to encrypt item-keys + keyId = null, // the key ID linking the user's key set aes = new app.crypto.AesCCM(sjcl); // use authenticated AES-CCM mode by default /** @@ -31,16 +32,18 @@ app.crypto.Crypto = function(window, util) { symmetricUserKey = util.random(keySize); var iv = util.random(ivSize); var key = aes.encrypt(symmetricUserKey, pbkdf2, iv); - keyStore.persist(storageId, { + storedKey = { _id: util.UUID(), userId: emailAddress, encryptedKey: key, keyIV: iv - }); + }; + keyStore.persist(storageId, storedKey); } else { // decrypt key symmetricUserKey = aes.decrypt(storedKey.encryptedKey, pbkdf2, storedKey.keyIV); } + keyId = storedKey._id; callback(); }); @@ -78,10 +81,10 @@ app.crypto.Crypto = function(window, util) { /** * Derive an asymmetric keypait from the user's secret */ - this.deriveKeyPair = function(naclCrypto, id) { + this.deriveKeyPair = function(naclCrypto) { var keys = naclCrypto.generateKeypair(symmetricUserKey); - if (id) { - keys.id = id; + if (keyId) { + keys.id = keyId; } return keys; }; diff --git a/src/js/dao/email-dao.js b/src/js/dao/email-dao.js index fad3a7e..bf0d5ba 100644 --- a/src/js/dao/email-dao.js +++ b/src/js/dao/email-dao.js @@ -2,9 +2,11 @@ * A high-level Data-Access Api for handling Email synchronization * between the cloud service and the device's local storage */ -app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage) { +app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage, naclCrypto) { 'use strict'; + var keypair; // the user's keypair + /** * Inits all dependencies */ @@ -14,7 +16,8 @@ app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage) { // sync user's cloud key with local storage cloudstorage.getUserSecretKey(account.get('emailAddress'), function(err) { if (err) { - console.log('Could not sync user key from server: ' + JSON.stringify(err)); + callback(err); + return; } // init crypto initCrypto(); @@ -28,7 +31,21 @@ app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage) { function initCrypto() { crypto.init(account.get('emailAddress'), password, account.get('symKeySize'), account.get('symIvSize'), function() { - callback(); + initNaclCrypto(); + }); + } + + function initNaclCrypto() { + // derive keypair from user's secret key + keypair = crypto.deriveKeyPair(naclCrypto); + //publish public key to cloud service + var pubkey = new app.model.PublicKey({ + _id: keypair.id, + userId: account.get('emailAddress'), + publicKey: keypair.boxPk + }); + cloudstorage.putPublicKey(pubkey.toJSON(), function(err) { + callback(err); }); } }; diff --git a/test/integration/cloudstorage-dao-test.js b/test/integration/cloudstorage-dao-test.js index 2168edc..30444a4 100644 --- a/test/integration/cloudstorage-dao-test.js +++ b/test/integration/cloudstorage-dao-test.js @@ -4,23 +4,18 @@ var cloudstoragedao_test = { user: 'test@atlasdev.onmicrosoft.com', password: 'Xoza76645', keySize: 128, - ivSize: 104, - privateKey: "Bv51afjeuH8CatKo75HOHQRT1B3amvF+DEwijka79nA=", - publicKey: new app.model.PublicKey({ - _id: "da4bfa93-ba87-490e-877c-e4020a6f6729", - userId: 'test@atlasdev.onmicrosoft.com', - publicKey: "yHUhh3Pcbjmh2k367pSXfE8hDwPsAxQs0QETm9mfmz0=" - }) + ivSize: 104 }; asyncTest("Init", 1, function() { // init dependencies var util = new app.crypto.Util(window, uuid); var jsonDao = new app.dao.LawnchairDAO(window); - cloudstoragedao_test.crypto = new app.crypto.Crypto(window, util); - cloudstoragedao_test.storage = new app.dao.DeviceStorage(util, cloudstoragedao_test.crypto, jsonDao, null); + var crypto = new app.crypto.Crypto(window, util); + var naclCrypto = new app.crypto.NaclCrypto(nacl, util); + cloudstoragedao_test.storage = new app.dao.DeviceStorage(util, crypto, jsonDao, null); cloudstoragedao_test.cloudstorage = new app.dao.CloudStorage(window, $); - cloudstoragedao_test.emailDao = new app.dao.EmailDAO(_, cloudstoragedao_test.crypto, cloudstoragedao_test.storage, cloudstoragedao_test.cloudstorage); + cloudstoragedao_test.emailDao = new app.dao.EmailDAO(_, crypto, cloudstoragedao_test.storage, cloudstoragedao_test.cloudstorage, naclCrypto); // clear db before tests jsonDao.clear(function(err) { @@ -31,6 +26,15 @@ asyncTest("Init", 1, function() { }); asyncTest("Persist public key to cloud", 1, function() { + + // testdata + cloudstoragedao_test.privateKey = "Bv51afjeuH8CatKo75HOHQRT1B3amvF+DEwijka79nA="; + cloudstoragedao_test.publicKey = new app.model.PublicKey({ + _id: "da4bfa93-ba87-490e-877c-e4020a6f6729", + userId: 'integration@atlasdev.onmicrosoft.com', + publicKey: "yHUhh3Pcbjmh2k367pSXfE8hDwPsAxQs0QETm9mfmz0=" + }); + cloudstoragedao_test.cloudstorage.putPublicKey(cloudstoragedao_test.publicKey.toJSON(), function(err) { ok(!err, 'Persist key to cloud'); @@ -39,7 +43,7 @@ asyncTest("Persist public key to cloud", 1, function() { }); asyncTest("Get Public key from cloud", 2, function() { - cloudstoragedao_test.cloudstorage.getPublicKey(cloudstoragedao_test.user, function(err, data) { + cloudstoragedao_test.cloudstorage.getPublicKey(cloudstoragedao_test.publicKey.get('userId'), function(err, data) { ok(!err && data && data.publicKey, 'Get public key from cloud'); deepEqual(data, cloudstoragedao_test.publicKey.toJSON(), 'Public key is equal'); @@ -69,7 +73,10 @@ asyncTest("Persist user secret key to cloud", 1, function() { }); }); -asyncTest("Sync emails from cloud", 3, function() { + +module("Email DAO"); + +asyncTest("Init", 1, function() { var account = new app.model.Account({ emailAddress: cloudstoragedao_test.user, @@ -77,17 +84,22 @@ asyncTest("Sync emails from cloud", 3, function() { symIvSize: cloudstoragedao_test.ivSize }); - cloudstoragedao_test.emailDao.init(account, cloudstoragedao_test.password, function() { - ok(true, 'Init complete'); + cloudstoragedao_test.emailDao.init(account, cloudstoragedao_test.password, function(err) { + ok(!err, 'Init complete'); - cloudstoragedao_test.emailDao.syncFromCloud('inbox', function(err) { - ok(!err, 'Synced items'); + start(); + }); +}); - cloudstoragedao_test.emailDao.listItems('inbox', 0, null, function(collection) { - ok(collection.length > 0, 'Read synced items'); +asyncTest("Sync emails from cloud", 3, function() { - start(); - }); + cloudstoragedao_test.emailDao.syncFromCloud('inbox', function(err) { + ok(!err, 'Synced items'); + + cloudstoragedao_test.emailDao.listItems('inbox', 0, null, function(collection) { + ok(collection.length > 0, 'Read synced items'); + + start(); }); }); }); \ No newline at end of file diff --git a/test/integration/index.html b/test/integration/index.html index 94c7f27..50265ad 100644 --- a/test/integration/index.html +++ b/test/integration/index.html @@ -40,6 +40,8 @@ + + @@ -60,7 +62,8 @@ - + + diff --git a/test/unit/email-dao-test.js b/test/unit/email-dao-test.js index e07f619..112f7a2 100644 --- a/test/unit/email-dao-test.js +++ b/test/unit/email-dao-test.js @@ -12,14 +12,18 @@ asyncTest("Init", 2, function() { var util = new app.crypto.Util(window, uuid); var jsonDao = new app.dao.LawnchairDAO(window); emaildao_test.crypto = new app.crypto.Crypto(window, util); + var naclCrypto = new app.crypto.NaclCrypto(nacl, util); emaildao_test.storage = new app.dao.DeviceStorage(util, emaildao_test.crypto, jsonDao, null); // cloud storage stub var cloudstorageStub = { getUserSecretKey: function(emailAdress, callback) { callback(); + }, + putPublicKey: function(pk, callback) { + callback(); } }; - emaildao_test.emailDao = new app.dao.EmailDAO(_, emaildao_test.crypto, emaildao_test.storage, cloudstorageStub); + emaildao_test.emailDao = new app.dao.EmailDAO(_, emaildao_test.crypto, emaildao_test.storage, cloudstorageStub, naclCrypto); // generate test data emaildao_test.list = new TestData().getEmailCollection(100); diff --git a/test/unit/index.html b/test/unit/index.html index 52e283a..439a1e9 100644 --- a/test/unit/index.html +++ b/test/unit/index.html @@ -58,6 +58,7 @@ +