Better handling for errorDecrypting

This commit is contained in:
Mo Bitar
2018-01-03 00:56:31 -06:00
parent fdbd2638a4
commit d8b1559d84
7 changed files with 59 additions and 18 deletions

View File

@@ -31,20 +31,27 @@ class ItemParams {
console.assert(!this.item.dummy, "Item is dummy, should not have gotten here.", this.item.dummy)
var params = {uuid: this.item.uuid, content_type: this.item.content_type, deleted: this.item.deleted, created_at: this.item.created_at};
if(this.keys && !this.item.doNotEncrypt()) {
var encryptedParams = EncryptionHelper.encryptItem(this.item, this.keys, this.version);
_.merge(params, encryptedParams);
if(!this.item.errorDecrypting) {
if(this.keys && !this.item.doNotEncrypt()) {
var encryptedParams = EncryptionHelper.encryptItem(this.item, this.keys, this.version);
_.merge(params, encryptedParams);
if(this.version !== "001") {
params.auth_hash = null;
if(this.version !== "001") {
params.auth_hash = null;
}
}
}
else {
params.content = this.forExportFile ? this.item.createContentJSONFromProperties() : "000" + Neeto.crypto.base64(JSON.stringify(this.item.createContentJSONFromProperties()));
if(!this.forExportFile) {
params.enc_item_key = null;
params.auth_hash = null;
else {
params.content = this.forExportFile ? this.item.createContentJSONFromProperties() : "000" + Neeto.crypto.base64(JSON.stringify(this.item.createContentJSONFromProperties()));
if(!this.forExportFile) {
params.enc_item_key = null;
params.auth_hash = null;
}
}
} else {
// Error decrypting, keep "content" and related fields as is (and do not try to encrypt, otherwise that would be undefined behavior)
params.content = this.item.content;
params.enc_item_key = this.item.enc_item_key;
params.auth_hash = this.item.auth_hash;
}
if(this.additionalFields) {

View File

@@ -197,7 +197,8 @@ angular.module('app.frontend')
this.saveKeys = function(keys) {
this._keys = keys;
storageManager.setItem("pw", keys.pw);
// Doesn't need to be saved.
// storageManager.setItem("pw", keys.pw);
storageManager.setItem("mk", keys.mk);
storageManager.setItem("ak", keys.ak);
}

View File

@@ -149,6 +149,7 @@ class AccountMenu {
var block = function() {
$timeout(function(){
$scope.onSuccessfulAuth()();
syncManager.refreshErroredItems();
syncManager.sync();
})
}

View File

@@ -92,6 +92,7 @@ class EncryptionHelper {
// return if uuid in auth hash does not match item uuid. Signs of tampering.
if(keyParams.uuid && keyParams.uuid !== item.uuid) {
if(!item.errorDecrypting) { item.errorDecryptingValueChanged = true;}
item.errorDecrypting = true;
return;
}
@@ -99,6 +100,7 @@ class EncryptionHelper {
var item_key = Neeto.crypto.decryptText(keyParams, requiresAuth);
if(!item_key) {
if(!item.errorDecrypting) { item.errorDecryptingValueChanged = true;}
item.errorDecrypting = true;
return;
}
@@ -110,6 +112,7 @@ class EncryptionHelper {
// return if uuid in auth hash does not match item uuid. Signs of tampering.
if(itemParams.uuid && itemParams.uuid !== item.uuid) {
if(!item.errorDecrypting) { item.errorDecryptingValueChanged = true;}
item.errorDecrypting = true;
return;
}
@@ -121,11 +124,14 @@ class EncryptionHelper {
var content = Neeto.crypto.decryptText(itemParams, true);
if(!content) {
if(!item.errorDecrypting) { item.errorDecryptingValueChanged = true;}
item.errorDecrypting = true;
} else {
if(item.errorDecrypting == true) { item.errorDecryptingValueChanged = true;}
// Content should only be set if it was successfully decrypted, and should otherwise remain unchanged.
item.errorDecrypting = false;
item.content = content;
}
item.content = content;
}
static decryptMultipleItems(items, keys, throws) {
@@ -139,6 +145,7 @@ class EncryptionHelper {
try {
this.decryptItem(item, keys);
} catch (e) {
if(!item.errorDecrypting) { item.errorDecryptingValueChanged = true;}
item.errorDecrypting = true;
if(throws) {
throw e;

View File

@@ -118,7 +118,14 @@ class ModelManager {
continue;
}
json_obj = _.omit(json_obj, omitFields || [])
// Lodash's _.omit, which was previously used, seems to cause unexpected behavior
// when json_obj is an ES6 item class. So we instead manually omit each key.
if(Array.isArray(omitFields)) {
for(var key of omitFields) {
delete json_obj[key];
}
}
var item = this.findItem(json_obj.uuid);
if(item) {

View File

@@ -77,7 +77,7 @@ class SyncManager {
markAllItemsDirtyAndSaveOffline(callback, alternateUUIDs) {
// use a copy, as alternating uuid will affect array
var originalItems = this.modelManager.allItems.slice();
var originalItems = this.modelManager.allItems.filter((item) => {return !item.errorDecrypting}).slice();
var block = () => {
var allItems = this.modelManager.allItems;
@@ -359,9 +359,30 @@ class SyncManager {
var keys = this.authManager.keys() || this.passcodeManager.keys();
EncryptionHelper.decryptMultipleItems(responseItems, keys);
var items = this.modelManager.mapResponseItemsToLocalModelsOmittingFields(responseItems, omitFields, source);
// During the decryption process, items may be marked as "errorDecrypting". If so, we want to be sure
// to persist this new state by writing these items back to local storage. When an item's "errorDecrypting"
// flag is changed, its "errorDecryptingValueChanged" flag will be set, so we can find these items by filtering (then unsetting) below:
var itemsWithErrorStatusChange = items.filter((item) => {
var valueChanged = item.errorDecryptingValueChanged;
// unset after consuming value
item.errorDecryptingValueChanged = false;
return valueChanged;
});
if(itemsWithErrorStatusChange.length > 0) {
this.writeItemsToLocalStorage(itemsWithErrorStatusChange, false, null);
}
return items;
}
refreshErroredItems() {
var erroredItems = this.modelManager.allItems.filter((item) => {return item.errorDecrypting == true});
if(erroredItems.length > 0) {
this.handleItemsResponse(erroredItems, null, ModelManager.MappingSourceLocalRetrieved);
}
}
handleUnsavedItemsResponse(unsaved) {
if(unsaved.length == 0) {
return;

View File

@@ -89,9 +89,6 @@
%label.block
Encryption key:
.wrap.normal.mt-1.selectable {{encryptionKey()}}
%label.block.mt-5.mb-0
Server password:
.wrap.normal.mt-1.selectable {{serverPassword() ? serverPassword() : 'Not available. Sign out then sign back in to compute.'}}
%label.block.mt-5.mb-0
Authentication key:
.wrap.normal.mt-1.selectable {{authKey() ? authKey() : 'Not available. Sign out then sign back in to compute.'}}