implemented public key cloud storage methods

This commit is contained in:
Tankred Hase 2013-04-19 13:55:21 +02:00
parent f4ed6010e6
commit e943dfd304
6 changed files with 136 additions and 30 deletions

View File

@ -75,6 +75,17 @@ app.crypto.Crypto = function(window, util) {
}
};
/**
* Derive an asymmetric keypait from the user's secret
*/
this.deriveKeyPair = function(naclCrypto, id) {
var keys = naclCrypto.generateKeypair(symmetricUserKey);
if (id) {
keys.id = id;
}
return keys;
};
//
// En/Decrypts single item
//

View File

@ -5,23 +5,30 @@
app.dao.CloudStorage = function(window, $) {
'use strict';
/**
* Lists the encrypted items
* @param type [String] The type of item e.g. 'email'
* @param offset [Number] The offset of items to fetch (0 is the last stored item)
* @param num [Number] The number of items to fetch (null means fetch all)
*/
this.listEncryptedItems = function(type, emailAddress, folderName, callback) {
var folder, uri, self = this;
//
// Public Key
//
// fetch encrypted json objects from cloud service
uri = app.config.cloudUrl + '/' + type + '/user/' + emailAddress + '/folder/' + folderName;
/**
* Find the user's corresponding public key
*/
this.getPublicKey = function(emailAddress, callback) {
var uri;
uri = app.config.cloudUrl + '/publickey/user/' + emailAddress;
$.ajax({
url: uri,
type: 'GET',
dataType: 'json',
success: function(list) {
callback(list);
if (!list || list.length === 0) {
callback({
error: 'No public key for that user!'
});
return;
}
callback(null, list[0]);
},
error: function(xhr, textStatus, err) {
callback({
@ -32,14 +39,74 @@ app.dao.CloudStorage = function(window, $) {
});
};
/**
* Persist the user's publc key
*/
this.putPublicKey = function(pubkey, callback) {
var uri;
uri = app.config.cloudUrl + '/publickey/user/' + pubkey.userId + '/key/' + pubkey._id;
$.ajax({
url: uri,
type: 'PUT',
data: JSON.stringify(pubkey),
contentType: 'application/json',
success: function() {
callback();
},
error: function(xhr, textStatus, err) {
callback({
error: err,
status: textStatus
});
}
});
};
//
// Encrypted Mails
//
/**
* Lists the encrypted items
* @param type [String] The type of item e.g. 'email'
* @param offset [Number] The offset of items to fetch (0 is the last stored item)
* @param num [Number] The number of items to fetch (null means fetch all)
*/
this.listEncryptedItems = function(type, emailAddress, folderName, callback) {
var uri;
// fetch encrypted json objects from cloud service
uri = app.config.cloudUrl + '/' + type + '/user/' + emailAddress + '/folder/' + folderName;
$.ajax({
url: uri,
type: 'GET',
dataType: 'json',
success: function(list) {
callback(null, list);
},
error: function(xhr, textStatus, err) {
callback({
error: err,
status: textStatus
});
}
});
};
//
// Secret Key
//
/**
* Persist encrypted user key to cloud service
*/
this.persistUserSecretKey = function(emailAddress, callback) {
this.putUserSecretKey = function(emailAddress, callback) {
// fetch user's encrypted secret key from keychain/storage
var keyStore = new app.dao.LocalStorageDAO(window),
storageId = emailAddress + '_encryptedSymmetricKey',
storedKey = keyStore.read(storageId);
storedKey = keyStore.read(storageId),
uri;
if (!storedKey) {
callback({
@ -49,8 +116,9 @@ app.dao.CloudStorage = function(window, $) {
return;
}
uri = app.config.cloudUrl + '/secretkey/user/' + emailAddress + '/key/' + storedKey._id;
$.ajax({
url: app.config.cloudUrl + '/secretkey/user/' + emailAddress + '/key/' + storedKey._id,
url: uri,
type: 'PUT',
data: JSON.stringify(storedKey),
contentType: 'application/json',
@ -74,10 +142,12 @@ app.dao.CloudStorage = function(window, $) {
var self = this,
keyStore = new app.dao.LocalStorageDAO(window),
storageId = emailAddress + '_encryptedSymmetricKey',
storedKey = keyStore.read(storageId);
storedKey = keyStore.read(storageId),
uri;
uri = app.config.cloudUrl + '/secretkey/user/' + emailAddress;
$.ajax({
url: app.config.cloudUrl + '/secretkey/user/' + emailAddress,
url: uri,
type: 'GET',
dataType: 'json',
success: function(keys) {
@ -107,14 +177,14 @@ app.dao.CloudStorage = function(window, $) {
} else if (storedKey && fetchedKey && (storedKey.encryptedKey !== fetchedKey.encryptedKey || storedKey.keyIV !== fetchedKey.keyIV)) {
// local and fetched keys are not equal
if (confirm('Swap local key?')) {
if (window.confirm('Swap local key?')) {
// replace local key with fetched key
keyStore.persist(storageId, fetchedKey);
replaceCallback();
} else {
if (confirm('Swap cloud key?')) {
if (window.confirm('Swap cloud key?')) {
// upload local key to cloud
self.persistUserSecretKey(emailAddress, callback);
self.putUserSecretKey(emailAddress, callback);
} else {
callback({
error: 'err',

View File

@ -91,10 +91,12 @@ app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage) {
this.syncFromCloud = function(folderName, callback) {
var folder, self = this;
cloudstorage.listEncryptedItems('email', this.account.get('emailAddress'), folderName, function(res) {
cloudstorage.listEncryptedItems('email', this.account.get('emailAddress'), folderName, function(err, res) {
// return if an error occured or if fetched list from cloud storage is empty
if (!res || res.status || res.length === 0) {
callback(res); // error
if (err || !res || res.status || res.length === 0) {
callback({
error: err
}); // error
return;
}

View File

@ -33,12 +33,12 @@
textVisible: true
});
// sync from cloud
this.dao.syncFromCloud(this.folder, function(res) {
this.dao.syncFromCloud(this.folder, function(err) {
$.mobile.loading('hide');
// check for error
if (res && res.status) {
alert('Syncing failed!');
if (err) {
window.alert('Syncing failed!');
return;
}

View File

@ -4,7 +4,13 @@ var cloudstoragedao_test = {
user: 'test@atlasdev.onmicrosoft.com',
password: 'Xoza76645',
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() {
@ -24,6 +30,22 @@ asyncTest("Init", 1, function() {
});
});
asyncTest("Persist public key to cloud", 1, function() {
cloudstoragedao_test.cloudstorage.putPublicKey(cloudstoragedao_test.publicKey.toJSON(), function(err) {
ok(!err, 'Persist key to cloud');
start();
});
});
asyncTest("Get Public key from cloud", 2, function() {
cloudstoragedao_test.cloudstorage.getPublicKey(cloudstoragedao_test.user, function(err, data) {
ok(!err && data && data.publicKey, 'Get public key from cloud');
deepEqual(data, cloudstoragedao_test.publicKey.toJSON(), 'Public key is equal');
start();
});
});
asyncTest("Get user secret key from cloud", 1, function() {
cloudstoragedao_test.cloudstorage.getUserSecretKey(cloudstoragedao_test.user, function(err) {
@ -40,7 +62,7 @@ asyncTest("Get user secret key from cloud", 1, function() {
});
asyncTest("Persist user secret key to cloud", 1, function() {
cloudstoragedao_test.cloudstorage.persistUserSecretKey(cloudstoragedao_test.user, function(err) {
cloudstoragedao_test.cloudstorage.putUserSecretKey(cloudstoragedao_test.user, function(err) {
ok(!err, 'Persist key to cloud');
start();
@ -58,8 +80,8 @@ asyncTest("Sync emails from cloud", 3, function() {
cloudstoragedao_test.emailDao.init(account, cloudstoragedao_test.password, function() {
ok(true, 'Init complete');
cloudstoragedao_test.emailDao.syncFromCloud('inbox', function(res) {
ok(!res, 'Synced items');
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');

View File

@ -47,12 +47,13 @@
<script src="../js/app-config.js"></script>
<script>
app.config.workerPath = '../js';
//app.config.cloudUrl = 'http://localhost:8888';
app.config.cloudUrl = 'http://localhost:8888';
</script>
<script src="../js/model/email-model.js"></script>
<script src="../js/model/folder-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/pbkdf2.js"></script>