mirror of
https://github.com/moparisthebest/mail
synced 2025-02-07 02:20:14 -05:00
implemented public key cloud storage methods
This commit is contained in:
parent
f4ed6010e6
commit
e943dfd304
@ -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
|
||||||
//
|
//
|
||||||
|
@ -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',
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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');
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user