diff --git a/CHANGELOG b/CHANGELOG index acca343..3ad9b35 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +0.2.1 (2017-06-27) +========================= +- get-databasehash request/response is now encrypted + 0.2.0 (2017-06-26) ========================= - Added JSON install files and script for Windows diff --git a/README.md b/README.md index 09ad6c4..d81b36e 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Now the requests are encrypted by [TweetNaCl.js](https://github.com/dchest/tweet 1. keepassxc-browser generates a key pair (with public and secret key) and transfers the public key to KeePassXC 2. When KeePassXC receives the public key it generates its own key pair and transfers the public key to keepassxc-browser -3. All messages (excluding get-databasehash) are now encrypted. +3. All messages between the browser extension and KeePassXC are now encrypted. 4. When keepassxc-browser sends a message it is encrypted with KeePassXC's public key, a random generated nonce and keepassxc-browser's secret key. 5. When KeePassXC sends a message it is encrypted with keepassxc-browser's public key etc. 6. Databases are stored based on the current public key used with `associate`. A new key pair for data transfer is generated each time keepassxc-browser is launched. @@ -48,7 +48,7 @@ Response (success): ```javascript { "action": "change-public-keys", - "version": "2.1.2", + "version": "2.2.0", "publicKey": "", "success": "true" } @@ -62,12 +62,12 @@ Request: } ``` -Response (success): +Response message data (success, decrypted): ```javascript { "action": "hash", "hash": "29234e32274a32276e25666a42", - "version": "2.1.2" + "version": "2.2.0" } ``` @@ -93,7 +93,7 @@ Response message data (success, decrypted): ```javascript { "hash": "29234e32274a32276e25666a42", - "version": "2.1.2", + "version": "2.2.0", "success": "true", "id": "testclient", "nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q" @@ -122,7 +122,7 @@ Request: Response message data (success, decrypted): ```javascript { - "version": "2.1.2", + "version": "2.2.0", "nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q", "hash": "29234e32274a32276e25666a42", "id": "testclient", @@ -142,7 +142,7 @@ Request: Response message data (success, decrypted): ```javascript { - "version": "2.1.2", + "version": "2.2.0", "entries": [ { "login": 144, @@ -191,7 +191,7 @@ Response message data (success, decrypted): "nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q", "success": "true", "hash": "29234e32274a32276e25666a42", - "version": "2.1.2" + "version": "2.2.0" } ``` @@ -227,7 +227,7 @@ Response message data (success, decrypted): "nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q", "success": "true", "hash": "29234e32274a32276e25666a42", - "version": "2.1.2" + "version": "2.2.0" } ``` diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js index 79e2256..6f852fe 100644 --- a/keepassxc-browser/background/keepass.js +++ b/keepassxc-browser/background/keepass.js @@ -31,7 +31,6 @@ keepass.addCredentials = function(callback, tab, username, password, url) { keepass.updateCredentials(callback, tab, null, username, password, url); } -// Not tested keepass.updateCredentials = function(callback, tab, entryId, username, password, url) { page.debug("keepass.updateCredentials(callback, {1}, {2}, {3}, [password], {4})", tab.id, entryId, username, url); @@ -191,7 +190,7 @@ keepass.retrieveCredentials = function (callback, tab, url, submiturl, forceCall keepass.callbackOnId = function (ev, id, callback) { var listener = ( function(port, id) { var handler = function(msg) { - if(msg.action == id) { + if (msg && msg.action == id) { ev.removeListener(handler); callback(msg); } @@ -465,32 +464,61 @@ keepass.getDatabaseHash = function (callback, tab, triggerUnlock) { keepass.changePublicKeys(tab, function(res) {}); } - var message = { "action": "get-databasehash" }; + var key = keepass.b64e(keepass.keyPair.publicKey); + var nonce = nacl.randomBytes(keepass.keySize); + + var messageData = { + action: "get-databasehash" + }; + + var request = { + action: "get-databasehash", + message: keepass.encrypt(messageData, nonce), + nonce: keepass.b64e(nonce) + }; + + //var message = { "action": "get-databasehash" }; keepass.callbackOnId(keepass.nativePort.onMessage, "get-databasehash", function(response) { - if (response.hash) - { - console.log("hash reply received: "+ response.hash); - var oldDatabaseHash = keepass.databaseHash; - keepass.setcurrentKeePassXCVersion(response.version); - keepass.databaseHash = response.hash || "no-hash"; - - if (oldDatabaseHash && oldDatabaseHash != keepass.databaseHash) { - keepass.associated.value = false; - keepass.associated.hash = null; + if (response.message && response.nonce) { + var res = keepass.decrypt(response.message, response.nonce); + if (!res) + { + console.log("Failed to decrypt message"); } + else + { + var message = nacl.util.encodeUTF8(res); + var parsed = JSON.parse(message); - statusOK(); - callback(response.hash); + if (parsed.hash) + { + console.log("hash reply received: "+ parsed.hash); + var oldDatabaseHash = keepass.databaseHash; + keepass.setcurrentKeePassXCVersion(parsed.version); + keepass.databaseHash = parsed.hash || "no-hash"; + + if (oldDatabaseHash && oldDatabaseHash != keepass.databaseHash) { + keepass.associated.value = false; + keepass.associated.hash = null; + } + + statusOK(); + callback(parsed.hash); + } + else if (parsed.errorCode) + { + keepass.databaseHash = "no-hash"; + keepass.isDatabaseClosed = true; + console.log("Error: KeePass database is not opened."); + if (tab && page.tabs[tab.id]) { + page.tabs[tab.id].errorMessage = "KeePass database is not opened."; + } + callback(keepass.databaseHash); + } + } } - else if (response.errorCode) - { - keepass.databaseHash = "no-hash"; - keepass.isDatabaseClosed = true; - console.log("Error: KeePass database is not opened."); - if (tab && page.tabs[tab.id]) { - page.tabs[tab.id].errorMessage = "KeePass database is not opened."; - } - callback(keepass.databaseHash); + else if (response.error && response.errorCode) { + keepass.handleError(tab.id, response.error, response.errorCode); } else { @@ -499,9 +527,9 @@ keepass.getDatabaseHash = function (callback, tab, triggerUnlock) { page.tabs[tab.id].errorMessage = "Database hash not received."; } callback(keepass.databaseHash); - } + } }); - keepass.nativePort.postMessage(message); + keepass.nativePort.postMessage(request); } keepass.changePublicKeys = function(tab, callback) { @@ -776,11 +804,15 @@ keepass.setCryptoKey = function(id, key) { keepass.encrypt = function(input, nonce) { var messageData = nacl.util.decodeUTF8(JSON.stringify(input)); - var message = nacl.box(messageData, nonce, keepass.serverPublicKey, keepass.keyPair.secretKey); - if (!message) { - return ""; + + if (keepass.serverPublicKey) { + var message = nacl.box(messageData, nonce, keepass.serverPublicKey, keepass.keyPair.secretKey); + if (message) { + return keepass.b64e(message); + } } - return keepass.b64e(message); + console.log("Cannot encrypt message! Server public key needed."); + return ""; } keepass.decrypt = function(input, nonce, toStr) { diff --git a/keepassxc-browser/manifest.json b/keepassxc-browser/manifest.json index cd03c88..fc95e21 100644 --- a/keepassxc-browser/manifest.json +++ b/keepassxc-browser/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "keepassxc-browser", - "version": "0.2.0", + "version": "0.2.1", "description": "KeePassXC integration for modern web browsers", "author": "Sami Vänttinen", "icons": { @@ -70,7 +70,7 @@ "tabs", "webRequest", "webRequestBlocking", - "https://raw.github.com/" + "https://api.github.com/" ], "applications": { "gecko": {