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 // En/Decrypts single item
// //

View File

@ -5,23 +5,30 @@
app.dao.CloudStorage = function(window, $) { app.dao.CloudStorage = function(window, $) {
'use strict'; 'use strict';
/** //
* Lists the encrypted items // Public Key
* @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;
// 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({ $.ajax({
url: uri, url: uri,
type: 'GET', type: 'GET',
dataType: 'json', dataType: 'json',
success: function(list) { 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) { error: function(xhr, textStatus, err) {
callback({ 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 * 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 // fetch user's encrypted secret key from keychain/storage
var keyStore = new app.dao.LocalStorageDAO(window), var keyStore = new app.dao.LocalStorageDAO(window),
storageId = emailAddress + '_encryptedSymmetricKey', storageId = emailAddress + '_encryptedSymmetricKey',
storedKey = keyStore.read(storageId); storedKey = keyStore.read(storageId),
uri;
if (!storedKey) { if (!storedKey) {
callback({ callback({
@ -49,8 +116,9 @@ app.dao.CloudStorage = function(window, $) {
return; return;
} }
uri = app.config.cloudUrl + '/secretkey/user/' + emailAddress + '/key/' + storedKey._id;
$.ajax({ $.ajax({
url: app.config.cloudUrl + '/secretkey/user/' + emailAddress + '/key/' + storedKey._id, url: uri,
type: 'PUT', type: 'PUT',
data: JSON.stringify(storedKey), data: JSON.stringify(storedKey),
contentType: 'application/json', contentType: 'application/json',
@ -74,10 +142,12 @@ app.dao.CloudStorage = function(window, $) {
var self = this, var self = this,
keyStore = new app.dao.LocalStorageDAO(window), keyStore = new app.dao.LocalStorageDAO(window),
storageId = emailAddress + '_encryptedSymmetricKey', storageId = emailAddress + '_encryptedSymmetricKey',
storedKey = keyStore.read(storageId); storedKey = keyStore.read(storageId),
uri;
uri = app.config.cloudUrl + '/secretkey/user/' + emailAddress;
$.ajax({ $.ajax({
url: app.config.cloudUrl + '/secretkey/user/' + emailAddress, url: uri,
type: 'GET', type: 'GET',
dataType: 'json', dataType: 'json',
success: function(keys) { success: function(keys) {
@ -107,14 +177,14 @@ app.dao.CloudStorage = function(window, $) {
} else if (storedKey && fetchedKey && (storedKey.encryptedKey !== fetchedKey.encryptedKey || storedKey.keyIV !== fetchedKey.keyIV)) { } else if (storedKey && fetchedKey && (storedKey.encryptedKey !== fetchedKey.encryptedKey || storedKey.keyIV !== fetchedKey.keyIV)) {
// local and fetched keys are not equal // local and fetched keys are not equal
if (confirm('Swap local key?')) { if (window.confirm('Swap local key?')) {
// replace local key with fetched key // replace local key with fetched key
keyStore.persist(storageId, fetchedKey); keyStore.persist(storageId, fetchedKey);
replaceCallback(); replaceCallback();
} else { } else {
if (confirm('Swap cloud key?')) { if (window.confirm('Swap cloud key?')) {
// upload local key to cloud // upload local key to cloud
self.persistUserSecretKey(emailAddress, callback); self.putUserSecretKey(emailAddress, callback);
} else { } else {
callback({ callback({
error: 'err', error: 'err',

View File

@ -91,10 +91,12 @@ app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage) {
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(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 // return if an error occured or if fetched list from cloud storage is empty
if (!res || res.status || res.length === 0) { if (err || !res || res.status || res.length === 0) {
callback(res); // error callback({
error: err
}); // error
return; return;
} }

View File

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

View File

@ -4,7 +4,13 @@ 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() {
@ -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() { asyncTest("Get user secret key from cloud", 1, function() {
cloudstoragedao_test.cloudstorage.getUserSecretKey(cloudstoragedao_test.user, function(err) { 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() { 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'); ok(!err, 'Persist key to cloud');
start(); start();
@ -58,8 +80,8 @@ asyncTest("Sync emails from cloud", 3, function() {
cloudstoragedao_test.emailDao.init(account, cloudstoragedao_test.password, function() { cloudstoragedao_test.emailDao.init(account, cloudstoragedao_test.password, function() {
ok(true, 'Init complete'); ok(true, 'Init complete');
cloudstoragedao_test.emailDao.syncFromCloud('inbox', function(res) { cloudstoragedao_test.emailDao.syncFromCloud('inbox', function(err) {
ok(!res, 'Synced items'); ok(!err, 'Synced items');
cloudstoragedao_test.emailDao.listItems('inbox', 0, null, function(collection) { cloudstoragedao_test.emailDao.listItems('inbox', 0, null, function(collection) {
ok(collection.length > 0, 'Read synced items'); ok(collection.length > 0, 'Read synced items');

View File

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