mirror of
https://github.com/moparisthebest/mail
synced 2024-11-25 10:22:18 -05:00
pull from vinbox, reencrypt, push to inbox works
This commit is contained in:
parent
65e0a7d520
commit
9dec074b0c
@ -12,23 +12,23 @@ app.dao.CloudStorage = function(window, $) {
|
|||||||
/**
|
/**
|
||||||
* Find the user's corresponding public key
|
* Find the user's corresponding public key
|
||||||
*/
|
*/
|
||||||
this.getPublicKey = function(emailAddress, callback) {
|
this.getPublicKey = function(keyId, callback) {
|
||||||
var uri;
|
var uri;
|
||||||
|
|
||||||
uri = app.config.cloudUrl + '/publickey/user/' + emailAddress;
|
uri = app.config.cloudUrl + '/publickey/key/' + keyId;
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: uri,
|
url: uri,
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function(list) {
|
success: function(key) {
|
||||||
if (!list || list.length === 0) {
|
if (!key || !key._id) {
|
||||||
callback({
|
callback({
|
||||||
error: 'No public key for that user!'
|
error: 'No public key for that user!'
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(null, list[0]);
|
callback(null, key);
|
||||||
},
|
},
|
||||||
error: function(xhr, textStatus, err) {
|
error: function(xhr, textStatus, err) {
|
||||||
callback({
|
callback({
|
||||||
@ -67,6 +67,31 @@ app.dao.CloudStorage = function(window, $) {
|
|||||||
// Encrypted Mails
|
// Encrypted Mails
|
||||||
//
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes an encrypted item to the user's cloud storage
|
||||||
|
* @param type [String] The type of item e.g. 'email'
|
||||||
|
*/
|
||||||
|
this.putEncryptedItem = function(item, type, emailAddress, folderName, callback) {
|
||||||
|
var uri;
|
||||||
|
|
||||||
|
uri = app.config.cloudUrl + '/' + type + '/user/' + emailAddress + '/folder/' + folderName + '/' + item.id;
|
||||||
|
$.ajax({
|
||||||
|
url: uri,
|
||||||
|
type: 'PUT',
|
||||||
|
data: JSON.stringify(item),
|
||||||
|
contentType: 'application/json',
|
||||||
|
success: function() {
|
||||||
|
callback();
|
||||||
|
},
|
||||||
|
error: function(xhr, textStatus, err) {
|
||||||
|
callback({
|
||||||
|
error: err,
|
||||||
|
status: textStatus
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists the encrypted items
|
* Lists the encrypted items
|
||||||
* @param type [String] The type of item e.g. 'email'
|
* @param type [String] The type of item e.g. 'email'
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* 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, naclCrypto) {
|
app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage, naclCrypto, util) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var keypair; // the user's keypair
|
var keypair; // the user's keypair
|
||||||
@ -101,6 +101,92 @@ app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage, naclCrypto)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the user virtual inbox containing end-2-end encrypted mail items
|
||||||
|
*/
|
||||||
|
this.checkVInbox = function(callback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
cloudstorage.listEncryptedItems('email', this.account.get('emailAddress'), 'vinbox', function(err, data) {
|
||||||
|
// if virtual inbox is emtpy just callback
|
||||||
|
if (err || !data || data.status || data.length === 0) {
|
||||||
|
callback(); // error
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// asynchronously iterate over the encrypted items
|
||||||
|
var after = _.after(data.length, function() {
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
|
||||||
|
_.each(data, function(asymCt) {
|
||||||
|
// asymmetric decrypt
|
||||||
|
asymDecryptMail(asymCt, function(err, pt) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// symmetric encrypt and push to cloud
|
||||||
|
symEncryptAndUpload(pt, function(err) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: delete items from virtual inbox
|
||||||
|
|
||||||
|
after(); // asynchronously iterate through objects
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function asymDecryptMail(m, callback) {
|
||||||
|
var pubKeyId = m.senderPk.split(';')[1];
|
||||||
|
// pull the sender's public key
|
||||||
|
cloudstorage.getPublicKey(pubKeyId, function(err, senderPk) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do authenticated decryption
|
||||||
|
naclCrypto.asymDecrypt(m.ciphertext, m.itemIV, senderPk.publicKey, keypair.boxSk, function(plaintext) {
|
||||||
|
callback(null, JSON.parse(plaintext));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function symEncryptAndUpload(email, callback) {
|
||||||
|
var itemKey = util.random(self.account.get('symKeySize')),
|
||||||
|
itemIV = util.random(self.account.get('symIvSize')),
|
||||||
|
keyIV = util.random(self.account.get('symIvSize')),
|
||||||
|
json = JSON.stringify(email),
|
||||||
|
envelope, encryptedKey;
|
||||||
|
|
||||||
|
// symmetrically encrypt item
|
||||||
|
crypto.aesEncrypt(json, itemKey, itemIV, function(ct) {
|
||||||
|
|
||||||
|
// encrypt item key for user
|
||||||
|
encryptedKey = crypto.aesEncryptForUserSync(itemKey, keyIV);
|
||||||
|
envelope = {
|
||||||
|
id: email.id,
|
||||||
|
crypto: 'aes-128-ccm',
|
||||||
|
ciphertext: ct,
|
||||||
|
encryptedKey: encryptedKey,
|
||||||
|
keyIV: keyIV,
|
||||||
|
itemIV: itemIV
|
||||||
|
};
|
||||||
|
|
||||||
|
// push encrypted item to cloud
|
||||||
|
cloudstorage.putEncryptedItem(envelope, 'email', self.account.get('emailAddress'), 'inbox', function(err) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronize a folder's items from the cloud to the device-storage
|
* Synchronize a folder's items from the cloud to the device-storage
|
||||||
* @param folderName [String] The name of the folder e.g. 'inbox'
|
* @param folderName [String] The name of the folder e.g. 'inbox'
|
||||||
@ -108,9 +194,9 @@ app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage, naclCrypto)
|
|||||||
this.syncFromCloud = function(folderName, callback) {
|
this.syncFromCloud = function(folderName, callback) {
|
||||||
var folder, self = this;
|
var folder, self = this;
|
||||||
|
|
||||||
cloudstorage.listEncryptedItems('email', this.account.get('emailAddress'), folderName, function(err, res) {
|
cloudstorage.listEncryptedItems('email', this.account.get('emailAddress'), folderName, function(err, data) {
|
||||||
// return if an error occured or if fetched list from cloud storage is empty
|
// return if an error occured or if fetched list from cloud storage is empty
|
||||||
if (err || !res || res.status || res.length === 0) {
|
if (err || !data || data.status || data.length === 0) {
|
||||||
callback({
|
callback({
|
||||||
error: err
|
error: err
|
||||||
}); // error
|
}); // error
|
||||||
@ -120,7 +206,7 @@ app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage, naclCrypto)
|
|||||||
// TODO: remove old folder items from devicestorage
|
// TODO: remove old folder items from devicestorage
|
||||||
|
|
||||||
// persist encrypted list in device storage
|
// persist encrypted list in device storage
|
||||||
devicestorage.storeEcryptedList(res, 'email_' + folderName, function() {
|
devicestorage.storeEcryptedList(data, 'email_' + folderName, function() {
|
||||||
// remove cached folder in account model
|
// remove cached folder in account model
|
||||||
folder = self.account.get('folders').where({
|
folder = self.account.get('folders').where({
|
||||||
name: folderName
|
name: folderName
|
||||||
|
@ -15,7 +15,7 @@ asyncTest("Init", 1, function() {
|
|||||||
var naclCrypto = new app.crypto.NaclCrypto(nacl, util);
|
var naclCrypto = new app.crypto.NaclCrypto(nacl, util);
|
||||||
cloudstoragedao_test.storage = new app.dao.DeviceStorage(util, crypto, jsonDao, null);
|
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(_, crypto, cloudstoragedao_test.storage, cloudstoragedao_test.cloudstorage, naclCrypto);
|
cloudstoragedao_test.emailDao = new app.dao.EmailDAO(_, crypto, cloudstoragedao_test.storage, cloudstoragedao_test.cloudstorage, naclCrypto, util);
|
||||||
|
|
||||||
// clear db before tests
|
// clear db before tests
|
||||||
jsonDao.clear(function(err) {
|
jsonDao.clear(function(err) {
|
||||||
@ -43,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.publicKey.get('userId'), function(err, data) {
|
cloudstoragedao_test.cloudstorage.getPublicKey(cloudstoragedao_test.publicKey.get('_id'), 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');
|
||||||
|
|
||||||
@ -91,8 +91,15 @@ asyncTest("Init", 1, function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("Sync emails from cloud", 3, function() {
|
asyncTest("Check virtual inbox, re-encrypt and push to cloud", 1, function() {
|
||||||
|
cloudstoragedao_test.emailDao.checkVInbox(function(err) {
|
||||||
|
ok(!err, 'Synced items');
|
||||||
|
|
||||||
|
start();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest("Sync emails from cloud", 2, function() {
|
||||||
cloudstoragedao_test.emailDao.syncFromCloud('inbox', function(err) {
|
cloudstoragedao_test.emailDao.syncFromCloud('inbox', function(err) {
|
||||||
ok(!err, 'Synced items');
|
ok(!err, 'Synced items');
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user