mirror of
https://github.com/moparisthebest/mail
synced 2024-12-22 15:28:49 -05:00
user keypair is now derived on email dao init and pub key pushed to the cloud
This commit is contained in:
parent
e943dfd304
commit
65e0a7d520
@ -6,6 +6,7 @@ app.crypto.Crypto = function(window, util) {
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var symmetricUserKey = null, // the user's secret key used to encrypt item-keys
|
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
|
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);
|
symmetricUserKey = util.random(keySize);
|
||||||
var iv = util.random(ivSize);
|
var iv = util.random(ivSize);
|
||||||
var key = aes.encrypt(symmetricUserKey, pbkdf2, iv);
|
var key = aes.encrypt(symmetricUserKey, pbkdf2, iv);
|
||||||
keyStore.persist(storageId, {
|
storedKey = {
|
||||||
_id: util.UUID(),
|
_id: util.UUID(),
|
||||||
userId: emailAddress,
|
userId: emailAddress,
|
||||||
encryptedKey: key,
|
encryptedKey: key,
|
||||||
keyIV: iv
|
keyIV: iv
|
||||||
});
|
};
|
||||||
|
keyStore.persist(storageId, storedKey);
|
||||||
} else {
|
} else {
|
||||||
// decrypt key
|
// decrypt key
|
||||||
symmetricUserKey = aes.decrypt(storedKey.encryptedKey, pbkdf2, storedKey.keyIV);
|
symmetricUserKey = aes.decrypt(storedKey.encryptedKey, pbkdf2, storedKey.keyIV);
|
||||||
}
|
}
|
||||||
|
keyId = storedKey._id;
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
@ -78,10 +81,10 @@ app.crypto.Crypto = function(window, util) {
|
|||||||
/**
|
/**
|
||||||
* Derive an asymmetric keypait from the user's secret
|
* Derive an asymmetric keypait from the user's secret
|
||||||
*/
|
*/
|
||||||
this.deriveKeyPair = function(naclCrypto, id) {
|
this.deriveKeyPair = function(naclCrypto) {
|
||||||
var keys = naclCrypto.generateKeypair(symmetricUserKey);
|
var keys = naclCrypto.generateKeypair(symmetricUserKey);
|
||||||
if (id) {
|
if (keyId) {
|
||||||
keys.id = id;
|
keys.id = keyId;
|
||||||
}
|
}
|
||||||
return keys;
|
return keys;
|
||||||
};
|
};
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
* A high-level Data-Access Api for handling Email synchronization
|
* A high-level Data-Access Api for handling Email synchronization
|
||||||
* between the cloud service and the device's local storage
|
* 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';
|
'use strict';
|
||||||
|
|
||||||
|
var keypair; // the user's keypair
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inits all dependencies
|
* Inits all dependencies
|
||||||
*/
|
*/
|
||||||
@ -14,7 +16,8 @@ app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage) {
|
|||||||
// sync user's cloud key with local storage
|
// sync user's cloud key with local storage
|
||||||
cloudstorage.getUserSecretKey(account.get('emailAddress'), function(err) {
|
cloudstorage.getUserSecretKey(account.get('emailAddress'), function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log('Could not sync user key from server: ' + JSON.stringify(err));
|
callback(err);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// init crypto
|
// init crypto
|
||||||
initCrypto();
|
initCrypto();
|
||||||
@ -28,7 +31,21 @@ app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage) {
|
|||||||
|
|
||||||
function initCrypto() {
|
function initCrypto() {
|
||||||
crypto.init(account.get('emailAddress'), password, account.get('symKeySize'), account.get('symIvSize'), function() {
|
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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -4,23 +4,18 @@ var cloudstoragedao_test = {
|
|||||||
user: 'test@atlasdev.onmicrosoft.com',
|
user: 'test@atlasdev.onmicrosoft.com',
|
||||||
password: 'Xoza76645',
|
password: 'Xoza76645',
|
||||||
keySize: 128,
|
keySize: 128,
|
||||||
ivSize: 104,
|
ivSize: 104
|
||||||
privateKey: "Bv51afjeuH8CatKo75HOHQRT1B3amvF+DEwijka79nA=",
|
|
||||||
publicKey: new app.model.PublicKey({
|
|
||||||
_id: "da4bfa93-ba87-490e-877c-e4020a6f6729",
|
|
||||||
userId: 'test@atlasdev.onmicrosoft.com',
|
|
||||||
publicKey: "yHUhh3Pcbjmh2k367pSXfE8hDwPsAxQs0QETm9mfmz0="
|
|
||||||
})
|
|
||||||
};
|
};
|
||||||
|
|
||||||
asyncTest("Init", 1, function() {
|
asyncTest("Init", 1, function() {
|
||||||
// init dependencies
|
// init dependencies
|
||||||
var util = new app.crypto.Util(window, uuid);
|
var util = new app.crypto.Util(window, uuid);
|
||||||
var jsonDao = new app.dao.LawnchairDAO(window);
|
var jsonDao = new app.dao.LawnchairDAO(window);
|
||||||
cloudstoragedao_test.crypto = new app.crypto.Crypto(window, util);
|
var crypto = new app.crypto.Crypto(window, util);
|
||||||
cloudstoragedao_test.storage = new app.dao.DeviceStorage(util, cloudstoragedao_test.crypto, jsonDao, null);
|
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.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
|
// clear db before tests
|
||||||
jsonDao.clear(function(err) {
|
jsonDao.clear(function(err) {
|
||||||
@ -31,6 +26,15 @@ asyncTest("Init", 1, function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("Persist public key to cloud", 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) {
|
cloudstoragedao_test.cloudstorage.putPublicKey(cloudstoragedao_test.publicKey.toJSON(), function(err) {
|
||||||
ok(!err, 'Persist key to cloud');
|
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() {
|
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');
|
ok(!err && data && data.publicKey, 'Get public key from cloud');
|
||||||
deepEqual(data, cloudstoragedao_test.publicKey.toJSON(), 'Public key is equal');
|
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({
|
var account = new app.model.Account({
|
||||||
emailAddress: cloudstoragedao_test.user,
|
emailAddress: cloudstoragedao_test.user,
|
||||||
@ -77,17 +84,22 @@ asyncTest("Sync emails from cloud", 3, function() {
|
|||||||
symIvSize: cloudstoragedao_test.ivSize
|
symIvSize: cloudstoragedao_test.ivSize
|
||||||
});
|
});
|
||||||
|
|
||||||
cloudstoragedao_test.emailDao.init(account, cloudstoragedao_test.password, function() {
|
cloudstoragedao_test.emailDao.init(account, cloudstoragedao_test.password, function(err) {
|
||||||
ok(true, 'Init complete');
|
ok(!err, 'Init complete');
|
||||||
|
|
||||||
cloudstoragedao_test.emailDao.syncFromCloud('inbox', function(err) {
|
start();
|
||||||
ok(!err, 'Synced items');
|
});
|
||||||
|
});
|
||||||
|
|
||||||
cloudstoragedao_test.emailDao.listItems('inbox', 0, null, function(collection) {
|
asyncTest("Sync emails from cloud", 3, function() {
|
||||||
ok(collection.length > 0, 'Read synced items');
|
|
||||||
|
|
||||||
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();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
@ -41,6 +41,8 @@
|
|||||||
<script src="../lib/sjcl/aes.js"></script>
|
<script src="../lib/sjcl/aes.js"></script>
|
||||||
<script src="../lib/sjcl/ccm.js"></script>
|
<script src="../lib/sjcl/ccm.js"></script>
|
||||||
|
|
||||||
|
<script src="../lib/nacl.js"></script>
|
||||||
|
|
||||||
<script src="../lib/uuid.js"></script>
|
<script src="../lib/uuid.js"></script>
|
||||||
<script src="../lib/openpgp.min.js"></script>
|
<script src="../lib/openpgp.min.js"></script>
|
||||||
|
|
||||||
@ -60,6 +62,7 @@
|
|||||||
<script src="../js/crypto/aes-cbc.js"></script>
|
<script src="../js/crypto/aes-cbc.js"></script>
|
||||||
<script src="../js/crypto/aes-ccm.js"></script>
|
<script src="../js/crypto/aes-ccm.js"></script>
|
||||||
<script src="../js/crypto/aes-gcm.js"></script>
|
<script src="../js/crypto/aes-gcm.js"></script>
|
||||||
|
<script src="../js/crypto/nacl-crypto.js"></script>
|
||||||
<script src="../js/crypto/crypto.js"></script>
|
<script src="../js/crypto/crypto.js"></script>
|
||||||
|
|
||||||
<script src="../js/dao/localstorage-dao.js"></script>
|
<script src="../js/dao/localstorage-dao.js"></script>
|
||||||
|
@ -12,14 +12,18 @@ asyncTest("Init", 2, function() {
|
|||||||
var util = new app.crypto.Util(window, uuid);
|
var util = new app.crypto.Util(window, uuid);
|
||||||
var jsonDao = new app.dao.LawnchairDAO(window);
|
var jsonDao = new app.dao.LawnchairDAO(window);
|
||||||
emaildao_test.crypto = new app.crypto.Crypto(window, util);
|
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);
|
emaildao_test.storage = new app.dao.DeviceStorage(util, emaildao_test.crypto, jsonDao, null);
|
||||||
// cloud storage stub
|
// cloud storage stub
|
||||||
var cloudstorageStub = {
|
var cloudstorageStub = {
|
||||||
getUserSecretKey: function(emailAdress, callback) {
|
getUserSecretKey: function(emailAdress, callback) {
|
||||||
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
|
// generate test data
|
||||||
emaildao_test.list = new TestData().getEmailCollection(100);
|
emaildao_test.list = new TestData().getEmailCollection(100);
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
<script src="../js/model/email-model.js"></script>
|
<script src="../js/model/email-model.js"></script>
|
||||||
<script src="../js/model/folder-model.js"></script>
|
<script src="../js/model/folder-model.js"></script>
|
||||||
<script src="../js/model/account-model.js"></script>
|
<script src="../js/model/account-model.js"></script>
|
||||||
|
<script src="../js/model/publickey-model.js"></script>
|
||||||
|
|
||||||
<script src="../js/crypto/util.js"></script>
|
<script src="../js/crypto/util.js"></script>
|
||||||
<script src="../js/crypto/pbkdf2.js"></script>
|
<script src="../js/crypto/pbkdf2.js"></script>
|
||||||
|
Loading…
Reference in New Issue
Block a user