auth hash

This commit is contained in:
Mo Bitar
2016-12-18 21:11:55 -06:00
parent 3794d0496c
commit 47b986f15f
7 changed files with 165 additions and 168 deletions

View File

@@ -6,7 +6,7 @@ class BaseCtrl {
// data.password = new_keys.pw; // data.password = new_keys.pw;
// data.password_confirmation = new_keys.pw; // data.password_confirmation = new_keys.pw;
// $auth.updatePassword(data); // $auth.updatePassword(data);
// apiController.setGk(new_keys.gk); // apiController.setMk(new_keys.mk);
// } // }
// var note = new Note(); // var note = new Note();

View File

@@ -82,7 +82,7 @@ class Item {
} }
encryptionEnabled() { encryptionEnabled() {
return this.loc_eek; return this.enc_item_key;
} }
presentationURL() { presentationURL() {

View File

@@ -6,7 +6,6 @@ angular.module('app.frontend')
abstract: true, abstract: true,
}) })
// Homepage
.state('home', { .state('home', {
url: '/', url: '/',
parent: 'base', parent: 'base',
@@ -18,39 +17,6 @@ angular.module('app.frontend')
} }
}) })
// Auth routes
// .state('auth', {
// abstract: true,
// url: '/auth',
// parent: 'base',
// views: {
// 'content@' : {
// templateUrl: 'frontend/auth/wrapper.html',
// }
// }
// })
// .state('auth.login', {
// url: '/login',
// templateUrl: 'frontend/auth/login.html',
// })
// .state('auth.forgot', {
// url: '/forgot',
// templateUrl: 'frontend/auth/forgot.html',
// })
// .state('auth.reset', {
// url: '/reset?reset_password_token&email',
// templateUrl: 'frontend/auth/reset.html',
// controller: function($rootScope, $stateParams) {
// $rootScope.resetData = {reset_password_token: $stateParams.reset_password_token, email: $stateParams.email};
//
// // Clear reset_password_token on change state
// $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams, options) {
// $rootScope.reset_password_token = null;
// });
// },
// })
// 404 Error // 404 Error
.state('404', { .state('404', {
parent: 'base', parent: 'base',

View File

@@ -78,6 +78,7 @@ angular.module('app.frontend')
callback(user, items); callback(user, items);
}.bind(this)) }.bind(this))
.catch(function(error){ .catch(function(error){
console.log("Error getting current user", error);
callback(null); callback(null);
}) })
} }
@@ -85,7 +86,7 @@ angular.module('app.frontend')
this.login = function(email, password, callback) { this.login = function(email, password, callback) {
this.getAuthParamsForEmail(email, function(authParams){ this.getAuthParamsForEmail(email, function(authParams){
Neeto.crypto.computeEncryptionKeysForUser(_.merge({email: email, password: password}, authParams), function(keys){ Neeto.crypto.computeEncryptionKeysForUser(_.merge({email: email, password: password}, authParams), function(keys){
this.setGk(keys.gk); this.setMk(keys.mk);
var request = Restangular.one("auth/sign_in"); var request = Restangular.one("auth/sign_in");
request.user = {password: keys.pw, email: email}; request.user = {password: keys.pw, email: email};
request.post().then(function(response){ request.post().then(function(response){
@@ -98,8 +99,8 @@ angular.module('app.frontend')
this.register = function(email, password, callback) { this.register = function(email, password, callback) {
Neeto.crypto.generateInitialEncryptionKeysForUser({password: password, email: email}, function(keys){ Neeto.crypto.generateInitialEncryptionKeysForUser({password: password, email: email}, function(keys){
this.setGk(keys.gk); this.setMk(keys.mk);
keys.gk = null; keys.mk = null;
var request = Restangular.one("auth"); var request = Restangular.one("auth");
request.user = _.merge({password: keys.pw, email: email}, keys); request.user = _.merge({password: keys.pw, email: email}, keys);
request.post().then(function(response){ request.post().then(function(response){
@@ -123,10 +124,10 @@ angular.module('app.frontend')
this._performPasswordChange(currentKeys, newKeys, function(response){ this._performPasswordChange(currentKeys, newKeys, function(response){
if(response && !response.errors) { if(response && !response.errors) {
// this.showNewPasswordForm = false; // this.showNewPasswordForm = false;
// reencrypt data with new gk // reencrypt data with new mk
this.reencryptAllItemsAndSave(user, newKeys.gk, currentKeys.gk, function(success){ this.reencryptAllItemsAndSave(user, newKeys.mk, currentKeys.mk, function(success){
if(success) { if(success) {
this.setGk(newKeys.gk); this.setMk(newKeys.mk);
alert("Your password has been changed and your data re-encrypted."); alert("Your password has been changed and your data re-encrypted.");
} else { } else {
// rollback password // rollback password
@@ -258,14 +259,16 @@ angular.module('app.frontend')
}) })
if(encrypted) { if(encrypted) {
this.encryptSingleItem(itemCopy, this.retrieveGk()); this.encryptSingleItem(itemCopy, this.retrieveMk());
params.content = itemCopy.content; params.content = itemCopy.content;
params.loc_eek = itemCopy.loc_eek; params.enc_item_key = itemCopy.enc_item_key;
params.auth_hash = itemCopy.auth_hash;
} }
else { else {
params.content = forExportFile ? itemCopy.content : JSON.stringify(itemCopy.content); params.content = forExportFile ? itemCopy.content : JSON.stringify(itemCopy.content);
if(!forExportFile) { if(!forExportFile) {
params.loc_eek = null; params.enc_item_key = null;
params.auth_hash = null;
} }
} }
@@ -450,87 +453,104 @@ angular.module('app.frontend')
Encrpytion Encrpytion
*/ */
this.retrieveGk = function() { this.retrieveMk = function() {
if(!this.gk) { if(!this.mk) {
this.gk = localStorage.getItem("gk"); this.mk = localStorage.getItem("mk");
} }
return this.gk; return this.mk;
} }
this.setGk = function(gk) { this.setMk = function(mk) {
localStorage.setItem('gk', gk); localStorage.setItem('mk', mk);
} }
this.signout = function() { this.signout = function() {
localStorage.removeItem("jwt"); localStorage.removeItem("jwt");
localStorage.removeItem("gk"); localStorage.removeItem("mk");
} }
this.encryptSingleItem = function(item, key) { this.encryptSingleItem = function(item, masterKey) {
var ek = null; var item_key = null;
if(item.loc_eek) { if(item.enc_item_key) {
ek = Neeto.crypto.decryptText(item.loc_eek, key); item_key = Neeto.crypto.decryptText(item.enc_item_key, masterKey);
} else { } else {
ek = Neeto.crypto.generateRandomEncryptionKey(); item_key = Neeto.crypto.generateRandomEncryptionKey();
item.loc_eek = Neeto.crypto.encryptText(ek, key); item.enc_item_key = Neeto.crypto.encryptText(item_key, masterKey);
}
item.content = Neeto.crypto.encryptText(JSON.stringify(item.content), ek);
item.local_encryption_scheme = "1.0";
} }
this.encryptItems = function(items, key) { var ek = Neeto.crypto.firstHalfOfKey(item_key);
var ak = Neeto.crypto.secondHalfOfKey(item_key);
var encryptedContent = Neeto.crypto.encryptText(JSON.stringify(item.content), ek);
var authHash = Neeto.crypto.hmac256(encryptedContent, ak);
item.content = encryptedContent;
item.auth_hash = authHash;
item.local_encryption_scheme = "1.0";
console.log("Encrypting item. itemKey:", item_key, "authHash:", item.auth_hash);
}
this.encryptItems = function(items, masterKey) {
items.forEach(function(item){ items.forEach(function(item){
this.encryptSingleItem(item, key); this.encryptSingleItem(item, masterKey);
}.bind(this)); }.bind(this));
} }
this.encryptSingleItemWithLocalKey = function(item) { this.encryptSingleItemWithLocalKey = function(item) {
this.encryptSingleItem(item, this.retrieveGk()); this.encryptSingleItem(item, this.retrieveMk());
} }
this.encryptItemsWithLocalKey = function(items) { this.encryptItemsWithLocalKey = function(items) {
this.encryptItems(items, this.retrieveGk()); this.encryptItems(items, this.retrieveMk());
} }
this.encryptNonPublicItemsWithLocalKey = function(items) { this.encryptNonPublicItemsWithLocalKey = function(items) {
var nonpublic = items.filter(function(item){ var nonpublic = items.filter(function(item){
return !item.isPublic() && !item.pending_share; return !item.isPublic() && !item.pending_share;
}) })
this.encryptItems(nonpublic, this.retrieveGk()); this.encryptItems(nonpublic, this.retrieveMk());
} }
this.decryptSingleItemWithLocalKey = function(item) { this.decryptSingleItemWithLocalKey = function(item) {
this.decryptSingleItem(item, this.retrieveGk()); this.decryptSingleItem(item, this.retrieveMk());
}
this.decryptSingleItem = function(item, masterKey) {
var item_key = Neeto.crypto.decryptText(item.enc_item_key, masterKey);
var ek = Neeto.crypto.firstHalfOfKey(item_key);
var ak = Neeto.crypto.secondHalfOfKey(item_key);
var authHash = Neeto.crypto.hmac256(item.content, ak);
if(authHash !== item.auth_hash || !item.auth_hash) {
console.log("Authentication hash does not match.")
return;
} }
this.decryptSingleItem = function(item, key) {
var ek = Neeto.crypto.decryptText(item.loc_eek || item.local_eek, key);
var content = Neeto.crypto.decryptText(item.content, ek); var content = Neeto.crypto.decryptText(item.content, ek);
// console.log("decrypted contnet", content);
item.content = content; item.content = content;
} }
this.decryptItems = function(items, key) { this.decryptItems = function(items, masterKey) {
items.forEach(function(item){ items.forEach(function(item){
// console.log("is encrypted?", item); // console.log("is encrypted?", item);
if(item.loc_eek && typeof item.content === 'string') { if(item.enc_item_key && typeof item.content === 'string') {
this.decryptSingleItem(item, key); this.decryptSingleItem(item, masterKey);
} }
}.bind(this)); }.bind(this));
} }
this.decryptItemsWithLocalKey = function(items) { this.decryptItemsWithLocalKey = function(items) {
this.decryptItems(items, this.retrieveGk()); this.decryptItems(items, this.retrieveMk());
} }
this.reencryptAllItemsAndSave = function(user, newKey, oldKey, callback) { this.reencryptAllItemsAndSave = function(user, newMasterKey, oldMasterKey, callback) {
var items = user.filteredItems(); var items = user.filteredItems();
items.forEach(function(item){ items.forEach(function(item){
if(item.loc_eek && typeof item.content === 'string') { if(item.enc_item_key && typeof item.content === 'string') {
// first decrypt eek with old key // first decrypt item_key with old key
var ek = Neeto.crypto.decryptText(item.loc_eek, oldKey); var item_key = Neeto.crypto.decryptText(item.enc_item_key, oldMasterKey);
// now encrypt ek with new key // now encrypt item_key with new key
item.loc_eek = Neeto.crypto.encryptText(ek, newKey); item.enc_item_key = Neeto.crypto.encryptText(item_key, newMasterKey);
} }
}); });

View File

@@ -31,6 +31,14 @@ class SNCrypto {
return CryptoJS.PBKDF2(passphrase, salt, { keySize: 256/32 }).toString(); return CryptoJS.PBKDF2(passphrase, salt, { keySize: 256/32 }).toString();
} }
firstHalfOfKey(key) {
return key.substring(0, key.length/2);
}
secondHalfOfKey(key) {
return key.substring(key.length/2, key.length);
}
sha256(text) { sha256(text) {
return CryptoJS.SHA256(text).toString(); return CryptoJS.SHA256(text).toString();
} }
@@ -39,13 +47,17 @@ class SNCrypto {
return CryptoJS.SHA1(text).toString(); return CryptoJS.SHA1(text).toString();
} }
hmac256(message, secret) {
return CryptoJS.HmacSHA256(message, secret).toString();
}
computeEncryptionKeysForUser({email, password, pw_salt, pw_func, pw_alg, pw_cost, pw_key_size} = {}, callback) { computeEncryptionKeysForUser({email, password, pw_salt, pw_func, pw_alg, pw_cost, pw_key_size} = {}, callback) {
this.generateSymmetricKeyPair({password: password, pw_salt: pw_salt, this.generateSymmetricKeyPair({password: password, pw_salt: pw_salt,
pw_func: pw_func, pw_alg: pw_alg, pw_cost: pw_cost, pw_key_size: pw_key_size}, function(keys){ pw_func: pw_func, pw_alg: pw_alg, pw_cost: pw_cost, pw_key_size: pw_key_size}, function(keys){
var pw = keys[0]; var pw = keys[0];
var gk = keys[1]; var mk = keys[1];
callback({pw: pw, gk: gk}); callback({pw: pw, mk: mk});
}); });
} }
@@ -56,9 +68,9 @@ class SNCrypto {
var pw_salt = this.sha1(email + "SN" + pw_nonce); var pw_salt = this.sha1(email + "SN" + pw_nonce);
this.generateSymmetricKeyPair(_.merge({email: email, password: password, pw_salt: pw_salt}, defaults), function(keys){ this.generateSymmetricKeyPair(_.merge({email: email, password: password, pw_salt: pw_salt}, defaults), function(keys){
var pw = keys[0]; var pw = keys[0];
var gk = keys[1]; var mk = keys[1];
callback(_.merge({pw: pw, gk: gk, pw_nonce: pw_nonce}, defaults)); callback(_.merge({pw: pw, mk: mk, pw_nonce: pw_nonce}, defaults));
}); });
} }
} }

View File

@@ -58,6 +58,16 @@ var SNCrypto = function () {
var passphrase = Neeto.crypto.generateRandomKey(); var passphrase = Neeto.crypto.generateRandomKey();
return CryptoJS.PBKDF2(passphrase, salt, { keySize: 256 / 32 }).toString(); return CryptoJS.PBKDF2(passphrase, salt, { keySize: 256 / 32 }).toString();
} }
}, {
key: 'firstHalfOfKey',
value: function firstHalfOfKey(key) {
return key.substring(0, key.length / 2);
}
}, {
key: 'secondHalfOfKey',
value: function secondHalfOfKey(key) {
return key.substring(key.length / 2, key.length);
}
}, { }, {
key: 'sha256', key: 'sha256',
value: function sha256(text) { value: function sha256(text) {
@@ -68,6 +78,11 @@ var SNCrypto = function () {
value: function sha1(text) { value: function sha1(text) {
return CryptoJS.SHA1(text).toString(); return CryptoJS.SHA1(text).toString();
} }
}, {
key: 'hmac256',
value: function hmac256(message, secret) {
return CryptoJS.HmacSHA256(message, secret).toString();
}
}, { }, {
key: 'computeEncryptionKeysForUser', key: 'computeEncryptionKeysForUser',
value: function computeEncryptionKeysForUser() { value: function computeEncryptionKeysForUser() {
@@ -85,9 +100,9 @@ var SNCrypto = function () {
this.generateSymmetricKeyPair({ password: password, pw_salt: pw_salt, this.generateSymmetricKeyPair({ password: password, pw_salt: pw_salt,
pw_func: pw_func, pw_alg: pw_alg, pw_cost: pw_cost, pw_key_size: pw_key_size }, function (keys) { pw_func: pw_func, pw_alg: pw_alg, pw_cost: pw_cost, pw_key_size: pw_key_size }, function (keys) {
var pw = keys[0]; var pw = keys[0];
var gk = keys[1]; var mk = keys[1];
callback({ pw: pw, gk: gk }); callback({ pw: pw, mk: mk });
}); });
} }
}, { }, {
@@ -109,9 +124,9 @@ var SNCrypto = function () {
var pw_salt = this.sha1(email + "SN" + pw_nonce); var pw_salt = this.sha1(email + "SN" + pw_nonce);
this.generateSymmetricKeyPair(_.merge({ email: email, password: password, pw_salt: pw_salt }, defaults), function (keys) { this.generateSymmetricKeyPair(_.merge({ email: email, password: password, pw_salt: pw_salt }, defaults), function (keys) {
var pw = keys[0]; var pw = keys[0];
var gk = keys[1]; var mk = keys[1];
callback(_.merge({ pw: pw, gk: gk, pw_nonce: pw_nonce }, defaults)); callback(_.merge({ pw: pw, mk: mk, pw_nonce: pw_nonce }, defaults));
}); });
} }
}]); }]);
@@ -362,10 +377,7 @@ angular.module('app.frontend', ['ui.router', 'restangular', 'oc.lazyLoad', 'angu
$stateProvider.state('base', { $stateProvider.state('base', {
abstract: true abstract: true
}) }).state('home', {
// Homepage
.state('home', {
url: '/', url: '/',
parent: 'base', parent: 'base',
views: { views: {
@@ -376,39 +388,6 @@ angular.module('app.frontend', ['ui.router', 'restangular', 'oc.lazyLoad', 'angu
} }
}) })
// Auth routes
// .state('auth', {
// abstract: true,
// url: '/auth',
// parent: 'base',
// views: {
// 'content@' : {
// templateUrl: 'frontend/auth/wrapper.html',
// }
// }
// })
// .state('auth.login', {
// url: '/login',
// templateUrl: 'frontend/auth/login.html',
// })
// .state('auth.forgot', {
// url: '/forgot',
// templateUrl: 'frontend/auth/forgot.html',
// })
// .state('auth.reset', {
// url: '/reset?reset_password_token&email',
// templateUrl: 'frontend/auth/reset.html',
// controller: function($rootScope, $stateParams) {
// $rootScope.resetData = {reset_password_token: $stateParams.reset_password_token, email: $stateParams.email};
//
// // Clear reset_password_token on change state
// $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams, options) {
// $rootScope.reset_password_token = null;
// });
// },
// })
// 404 Error // 404 Error
.state('404', { .state('404', {
parent: 'base', parent: 'base',
@@ -437,7 +416,7 @@ var BaseCtrl = function BaseCtrl($rootScope, modelManager) {
// data.password = new_keys.pw; // data.password = new_keys.pw;
// data.password_confirmation = new_keys.pw; // data.password_confirmation = new_keys.pw;
// $auth.updatePassword(data); // $auth.updatePassword(data);
// apiController.setGk(new_keys.gk); // apiController.setMk(new_keys.mk);
// } // }
// var note = new Note(); // var note = new Note();
@@ -1375,7 +1354,7 @@ var Item = function () {
}, { }, {
key: 'encryptionEnabled', key: 'encryptionEnabled',
value: function encryptionEnabled() { value: function encryptionEnabled() {
return this.loc_eek; return this.enc_item_key;
} }
}, { }, {
key: 'presentationURL', key: 'presentationURL',
@@ -1582,6 +1561,7 @@ var User = function User(json_obj) {
var user = _.omit(plain, ["items"]); var user = _.omit(plain, ["items"]);
callback(user, items); callback(user, items);
}.bind(this)).catch(function (error) { }.bind(this)).catch(function (error) {
console.log("Error getting current user", error);
callback(null); callback(null);
}); });
}; };
@@ -1589,7 +1569,7 @@ var User = function User(json_obj) {
this.login = function (email, password, callback) { this.login = function (email, password, callback) {
this.getAuthParamsForEmail(email, function (authParams) { this.getAuthParamsForEmail(email, function (authParams) {
Neeto.crypto.computeEncryptionKeysForUser(_.merge({ email: email, password: password }, authParams), function (keys) { Neeto.crypto.computeEncryptionKeysForUser(_.merge({ email: email, password: password }, authParams), function (keys) {
this.setGk(keys.gk); this.setMk(keys.mk);
var request = Restangular.one("auth/sign_in"); var request = Restangular.one("auth/sign_in");
request.user = { password: keys.pw, email: email }; request.user = { password: keys.pw, email: email };
request.post().then(function (response) { request.post().then(function (response) {
@@ -1602,8 +1582,8 @@ var User = function User(json_obj) {
this.register = function (email, password, callback) { this.register = function (email, password, callback) {
Neeto.crypto.generateInitialEncryptionKeysForUser({ password: password, email: email }, function (keys) { Neeto.crypto.generateInitialEncryptionKeysForUser({ password: password, email: email }, function (keys) {
this.setGk(keys.gk); this.setMk(keys.mk);
keys.gk = null; keys.mk = null;
var request = Restangular.one("auth"); var request = Restangular.one("auth");
request.user = _.merge({ password: keys.pw, email: email }, keys); request.user = _.merge({ password: keys.pw, email: email }, keys);
request.post().then(function (response) { request.post().then(function (response) {
@@ -1627,10 +1607,10 @@ var User = function User(json_obj) {
this._performPasswordChange(currentKeys, newKeys, function (response) { this._performPasswordChange(currentKeys, newKeys, function (response) {
if (response && !response.errors) { if (response && !response.errors) {
// this.showNewPasswordForm = false; // this.showNewPasswordForm = false;
// reencrypt data with new gk // reencrypt data with new mk
this.reencryptAllItemsAndSave(user, newKeys.gk, currentKeys.gk, function (success) { this.reencryptAllItemsAndSave(user, newKeys.mk, currentKeys.mk, function (success) {
if (success) { if (success) {
this.setGk(newKeys.gk); this.setMk(newKeys.mk);
alert("Your password has been changed and your data re-encrypted."); alert("Your password has been changed and your data re-encrypted.");
} else { } else {
// rollback password // rollback password
@@ -1759,13 +1739,15 @@ var User = function User(json_obj) {
}); });
if (encrypted) { if (encrypted) {
this.encryptSingleItem(itemCopy, this.retrieveGk()); this.encryptSingleItem(itemCopy, this.retrieveMk());
params.content = itemCopy.content; params.content = itemCopy.content;
params.loc_eek = itemCopy.loc_eek; params.enc_item_key = itemCopy.enc_item_key;
params.auth_hash = itemCopy.auth_hash;
} else { } else {
params.content = forExportFile ? itemCopy.content : JSON.stringify(itemCopy.content); params.content = forExportFile ? itemCopy.content : JSON.stringify(itemCopy.content);
if (!forExportFile) { if (!forExportFile) {
params.loc_eek = null; params.enc_item_key = null;
params.auth_hash = null;
} }
} }
@@ -1944,87 +1926,104 @@ var User = function User(json_obj) {
Encrpytion Encrpytion
*/ */
this.retrieveGk = function () { this.retrieveMk = function () {
if (!this.gk) { if (!this.mk) {
this.gk = localStorage.getItem("gk"); this.mk = localStorage.getItem("mk");
} }
return this.gk; return this.mk;
}; };
this.setGk = function (gk) { this.setMk = function (mk) {
localStorage.setItem('gk', gk); localStorage.setItem('mk', mk);
}; };
this.signout = function () { this.signout = function () {
localStorage.removeItem("jwt"); localStorage.removeItem("jwt");
localStorage.removeItem("gk"); localStorage.removeItem("mk");
}; };
this.encryptSingleItem = function (item, key) { this.encryptSingleItem = function (item, masterKey) {
var ek = null; var item_key = null;
if (item.loc_eek) { if (item.enc_item_key) {
ek = Neeto.crypto.decryptText(item.loc_eek, key); item_key = Neeto.crypto.decryptText(item.enc_item_key, masterKey);
} else { } else {
ek = Neeto.crypto.generateRandomEncryptionKey(); item_key = Neeto.crypto.generateRandomEncryptionKey();
item.loc_eek = Neeto.crypto.encryptText(ek, key); item.enc_item_key = Neeto.crypto.encryptText(item_key, masterKey);
} }
item.content = Neeto.crypto.encryptText(JSON.stringify(item.content), ek);
var ek = Neeto.crypto.firstHalfOfKey(item_key);
var ak = Neeto.crypto.secondHalfOfKey(item_key);
var encryptedContent = Neeto.crypto.encryptText(JSON.stringify(item.content), ek);
var authHash = Neeto.crypto.hmac256(encryptedContent, ak);
item.content = encryptedContent;
item.auth_hash = authHash;
item.local_encryption_scheme = "1.0"; item.local_encryption_scheme = "1.0";
console.log("Encrypting item. itemKey:", item_key, "authHash:", item.auth_hash);
}; };
this.encryptItems = function (items, key) { this.encryptItems = function (items, masterKey) {
items.forEach(function (item) { items.forEach(function (item) {
this.encryptSingleItem(item, key); this.encryptSingleItem(item, masterKey);
}.bind(this)); }.bind(this));
}; };
this.encryptSingleItemWithLocalKey = function (item) { this.encryptSingleItemWithLocalKey = function (item) {
this.encryptSingleItem(item, this.retrieveGk()); this.encryptSingleItem(item, this.retrieveMk());
}; };
this.encryptItemsWithLocalKey = function (items) { this.encryptItemsWithLocalKey = function (items) {
this.encryptItems(items, this.retrieveGk()); this.encryptItems(items, this.retrieveMk());
}; };
this.encryptNonPublicItemsWithLocalKey = function (items) { this.encryptNonPublicItemsWithLocalKey = function (items) {
var nonpublic = items.filter(function (item) { var nonpublic = items.filter(function (item) {
return !item.isPublic() && !item.pending_share; return !item.isPublic() && !item.pending_share;
}); });
this.encryptItems(nonpublic, this.retrieveGk()); this.encryptItems(nonpublic, this.retrieveMk());
}; };
this.decryptSingleItemWithLocalKey = function (item) { this.decryptSingleItemWithLocalKey = function (item) {
this.decryptSingleItem(item, this.retrieveGk()); this.decryptSingleItem(item, this.retrieveMk());
}; };
this.decryptSingleItem = function (item, key) { this.decryptSingleItem = function (item, masterKey) {
var ek = Neeto.crypto.decryptText(item.loc_eek || item.local_eek, key); var item_key = Neeto.crypto.decryptText(item.enc_item_key, masterKey);
var ek = Neeto.crypto.firstHalfOfKey(item_key);
var ak = Neeto.crypto.secondHalfOfKey(item_key);
var authHash = Neeto.crypto.hmac256(item.content, ak);
if (authHash !== item.auth_hash || !item.auth_hash) {
console.log("Authentication hash does not match.");
return;
}
var content = Neeto.crypto.decryptText(item.content, ek); var content = Neeto.crypto.decryptText(item.content, ek);
// console.log("decrypted contnet", content);
item.content = content; item.content = content;
}; };
this.decryptItems = function (items, key) { this.decryptItems = function (items, masterKey) {
items.forEach(function (item) { items.forEach(function (item) {
// console.log("is encrypted?", item); // console.log("is encrypted?", item);
if (item.loc_eek && typeof item.content === 'string') { if (item.enc_item_key && typeof item.content === 'string') {
this.decryptSingleItem(item, key); this.decryptSingleItem(item, masterKey);
} }
}.bind(this)); }.bind(this));
}; };
this.decryptItemsWithLocalKey = function (items) { this.decryptItemsWithLocalKey = function (items) {
this.decryptItems(items, this.retrieveGk()); this.decryptItems(items, this.retrieveMk());
}; };
this.reencryptAllItemsAndSave = function (user, newKey, oldKey, callback) { this.reencryptAllItemsAndSave = function (user, newMasterKey, oldMasterKey, callback) {
var items = user.filteredItems(); var items = user.filteredItems();
items.forEach(function (item) { items.forEach(function (item) {
if (item.loc_eek && typeof item.content === 'string') { if (item.enc_item_key && typeof item.content === 'string') {
// first decrypt eek with old key // first decrypt item_key with old key
var ek = Neeto.crypto.decryptText(item.loc_eek, oldKey); var item_key = Neeto.crypto.decryptText(item.enc_item_key, oldMasterKey);
// now encrypt ek with new key // now encrypt item_key with new key
item.loc_eek = Neeto.crypto.encryptText(ek, newKey); item.enc_item_key = Neeto.crypto.encryptText(item_key, newMasterKey);
} }
}); });

File diff suppressed because one or more lines are too long