auth hash
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
encryptionEnabled() {
|
encryptionEnabled() {
|
||||||
return this.loc_eek;
|
return this.enc_item_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
presentationURL() {
|
presentationURL() {
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
169
vendor/assets/javascripts/transpiled.js
vendored
169
vendor/assets/javascripts/transpiled.js
vendored
@@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
2
vendor/assets/javascripts/transpiled.js.map
vendored
2
vendor/assets/javascripts/transpiled.js.map
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user