fix #10: use webcrypto for keyfile encryption if it's available

This commit is contained in:
Antelle 2015-11-04 00:59:57 +03:00
parent 73b51c2dae
commit 3b0c0f9f89
3 changed files with 87 additions and 69 deletions

View File

@ -51,13 +51,18 @@ var FileModel = Backbone.Model.extend({
password = new kdbxweb.ProtectedValue(value.buffer.slice(0, byteLength), salt.buffer.slice(0, byteLength)); password = new kdbxweb.ProtectedValue(value.buffer.slice(0, byteLength), salt.buffer.slice(0, byteLength));
try { try {
var credentials = new kdbxweb.Credentials(password, keyFileData); var credentials = new kdbxweb.Credentials(password, keyFileData);
this.db = kdbxweb.Kdbx.load(fileData, credentials); kdbxweb.Kdbx.load(fileData, credentials, (function(db, err) {
if (err) {
this.set({error: true, opening: false});
} else {
this.db = db;
this.readModel(this.get('name'));
this.setOpenFile({ passwordLength: len });
}
}).bind(this));
} catch (e) { } catch (e) {
this.set({ error: true, opening: false }); this.set({ error: true, opening: false });
return;
} }
this.readModel(this.get('name'));
this.setOpenFile({ passwordLength: len });
}, },
create: function(name) { create: function(name) {
@ -72,9 +77,11 @@ var FileModel = Backbone.Model.extend({
var password = kdbxweb.ProtectedValue.fromString('demo'); var password = kdbxweb.ProtectedValue.fromString('demo');
var credentials = new kdbxweb.Credentials(password); var credentials = new kdbxweb.Credentials(password);
var demoFile = kdbxweb.ByteUtils.arrayToBuffer(kdbxweb.ByteUtils.base64ToBytes(demoFileData)); var demoFile = kdbxweb.ByteUtils.arrayToBuffer(kdbxweb.ByteUtils.base64ToBytes(demoFileData));
this.db = kdbxweb.Kdbx.load(demoFile, credentials); kdbxweb.Kdbx.load(demoFile, credentials, (function(db) {
this.readModel(); this.db = db;
this.setOpenFile({ passwordLength: 4, demo: true, name: 'Demo' }); this.readModel();
this.setOpenFile({passwordLength: 4, demo: true, name: 'Demo'});
}).bind(this));
}, },
setOpenFile: function(props) { setOpenFile: function(props) {
@ -164,27 +171,31 @@ var FileModel = Backbone.Model.extend({
this.set('syncing', true); this.set('syncing', true);
switch (this.get('storage')) { switch (this.get('storage')) {
case 'file': case 'file':
Launcher.writeFile(this.get('path'), this.getData()); this.getData(function(data) {
this.saved(this.get('path'), this.get('storage')); Launcher.writeFile(this.get('path'), data);
this.saved(this.get('path'), this.get('storage'));
});
break; break;
case 'dropbox': case 'dropbox':
DropboxLink.saveFile(this.get('path'), this.getData(), true, (function(err) { this.getData(function(data) {
if (!err) { DropboxLink.saveFile(this.get('path'), data, true, (function (err) {
this.saved(this.get('path'), this.get('storage')); if (!err) {
} this.saved(this.get('path'), this.get('storage'));
}).bind(this)); }
}).bind(this));
});
break; break;
default: default:
throw 'Unknown storage; cannot auto save'; throw 'Unknown storage; cannot auto save';
} }
}, },
getData: function() { getData: function(cb) {
return this.db.save(); return this.db.save(cb);
}, },
getXml: function() { getXml: function(cb) {
return this.db.saveXml(); this.db.saveXml(cb);
}, },
saved: function(path, storage) { saved: function(path, storage) {

View File

@ -98,26 +98,28 @@ var SettingsAboutView = Backbone.View.extend({
if (!this.validate()) { if (!this.validate()) {
return; return;
} }
var data = this.model.getData(); var that = this;
var fileName = this.model.get('name') + '.kdbx'; this.model.getData(function(data) {
if (Launcher) { var fileName = that.model.get('name') + '.kdbx';
if (this.model.get('path')) { if (Launcher) {
this.saveToFileWithPath(this.model.get('path'), data); if (that.model.get('path')) {
that.saveToFileWithPath(that.model.get('path'), data);
} else {
Launcher.getSaveFileName(fileName, function (path) {
if (path) {
that.saveToFileWithPath(path, data);
}
});
}
} else { } else {
Launcher.getSaveFileName(fileName, (function (path) { var blob = new Blob([data], {type: 'application/octet-stream'});
if (path) { FileSaver.saveAs(blob, fileName);
this.saveToFileWithPath(path, data); that.passwordChanged = false;
} if (that.model.get('storage') !== 'dropbox') {
}).bind(this)); that.model.saved();
}
} }
} else { });
var blob = new Blob([data], {type: 'application/octet-stream'});
FileSaver.saveAs(blob, fileName);
this.passwordChanged = false;
if (this.model.get('storage') !== 'dropbox') {
this.model.saved();
}
}
}, },
saveToFileWithPath: function(path, data) { saveToFileWithPath: function(path, data) {
@ -140,9 +142,10 @@ var SettingsAboutView = Backbone.View.extend({
if (!this.validate()) { if (!this.validate()) {
return; return;
} }
var data = this.model.getXml(); this.model.getXml((function(xml) {
var blob = new Blob([data], {type: 'text/xml'}); var blob = new Blob([xml], {type: 'text/xml'});
FileSaver.saveAs(blob, this.model.get('name') + '.xml'); FileSaver.saveAs(blob, this.model.get('name') + '.xml');
}).bind(this));
}, },
saveToDropboxClick: function() { saveToDropboxClick: function() {
@ -155,37 +158,41 @@ var SettingsAboutView = Backbone.View.extend({
if (this.model.get('syncing') || !this.validate()) { if (this.model.get('syncing') || !this.validate()) {
return; return;
} }
var data = this.model.getData(); var that = this;
var fileName = this.model.get('name') + '.kdbx'; this.model.getData(function(data) {
this.model.set('syncing', true); var fileName = that.model.get('name') + '.kdbx';
this.render(); that.model.set('syncing', true);
DropboxLink.saveFile(fileName, data, overwrite, (function(err) { that.render();
if (err) { DropboxLink.saveFile(fileName, data, overwrite, function (err) {
this.model.set('syncing', false); if (err) {
if (err.exists) { that.model.set('syncing', false);
Alerts.alert({ if (err.exists) {
header: 'Already exists', Alerts.alert({
body: 'File ' + fileName + ' already exists in your Dropbox.', header: 'Already exists',
icon: 'question', body: 'File ' + fileName + ' already exists in your Dropbox.',
buttons: [{result: 'yes', title: 'Overwrite it'}, {result: '', title: 'I\'ll choose another name'}], icon: 'question',
esc: '', buttons: [{result: 'yes', title: 'Overwrite it'}, {result: '', title: 'I\'ll choose another name'}],
click: '', esc: '',
enter: 'yes', click: '',
success: this.saveToDropbox.bind(this, true), enter: 'yes',
cancel: (function() { this.$el.find('#settings__file-name').focus(); }).bind(this) success: that.saveToDropbox.bind(that, true),
}); cancel: function () {
that.$el.find('#settings__file-name').focus();
}
});
} else {
Alerts.error({
header: 'Save error',
body: 'Error saving to Dropbox: \n' + err
});
}
} else { } else {
Alerts.error({ that.passwordChanged = false;
header: 'Save error', that.model.saved(fileName, 'dropbox');
body: 'Error saving to Dropbox: \n' + err that.render();
});
} }
} else { });
this.passwordChanged = false; });
this.model.saved(fileName, 'dropbox');
this.render();
}
}).bind(this));
}, },
keyFileChange: function(e) { keyFileChange: function(e) {

View File

@ -29,7 +29,7 @@
"dropbox": "antelle/dropbox-js#0.10.4", "dropbox": "antelle/dropbox-js#0.10.4",
"font-awesome": "~4.4.0", "font-awesome": "~4.4.0",
"install": "~1.0.4", "install": "~1.0.4",
"kdbxweb": "~0.1.12", "kdbxweb": "~0.2.0",
"normalize.css": "~3.0.3", "normalize.css": "~3.0.3",
"pikaday": "~1.3.3", "pikaday": "~1.3.3",
"zepto": "~1.1.6", "zepto": "~1.1.6",