pull from vinbox, reencrypt, push to inbox works

This commit is contained in:
Tankred Hase 2013-04-19 19:13:27 +02:00
parent 65e0a7d520
commit 9dec074b0c
3 changed files with 130 additions and 12 deletions

View File

@ -12,23 +12,23 @@ app.dao.CloudStorage = function(window, $) {
/**
* Find the user's corresponding public key
*/
this.getPublicKey = function(emailAddress, callback) {
this.getPublicKey = function(keyId, callback) {
var uri;
uri = app.config.cloudUrl + '/publickey/user/' + emailAddress;
uri = app.config.cloudUrl + '/publickey/key/' + keyId;
$.ajax({
url: uri,
type: 'GET',
dataType: 'json',
success: function(list) {
if (!list || list.length === 0) {
success: function(key) {
if (!key || !key._id) {
callback({
error: 'No public key for that user!'
});
return;
}
callback(null, list[0]);
callback(null, key);
},
error: function(xhr, textStatus, err) {
callback({
@ -67,6 +67,31 @@ app.dao.CloudStorage = function(window, $) {
// 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
* @param type [String] The type of item e.g. 'email'

View File

@ -2,7 +2,7 @@
* 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, naclCrypto) {
app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage, naclCrypto, util) {
'use strict';
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
* @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) {
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
if (err || !res || res.status || res.length === 0) {
if (err || !data || data.status || data.length === 0) {
callback({
error: err
}); // error
@ -120,7 +206,7 @@ app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage, naclCrypto)
// TODO: remove old folder items from devicestorage
// persist encrypted list in device storage
devicestorage.storeEcryptedList(res, 'email_' + folderName, function() {
devicestorage.storeEcryptedList(data, 'email_' + folderName, function() {
// remove cached folder in account model
folder = self.account.get('folders').where({
name: folderName

View File

@ -15,7 +15,7 @@ asyncTest("Init", 1, function() {
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(_, 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
jsonDao.clear(function(err) {
@ -43,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.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');
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) {
ok(!err, 'Synced items');