mirror of
https://github.com/keepassxreboot/keepassxc-browser.git
synced 2026-03-11 08:54:43 +00:00
Improved credentials check
This commit is contained in:
parent
9e7a4c43ba
commit
dc15e61304
8 changed files with 276 additions and 250 deletions
|
|
@ -1,3 +1,7 @@
|
|||
0.3.7 (22-10-2017)
|
||||
=========================
|
||||
- Improved credentials check (does not use protocol requests for polling)
|
||||
|
||||
0.3.6 (20-10-2017)
|
||||
=========================
|
||||
- Restricted page credentials polling to active tab
|
||||
|
|
|
|||
240
README.md
240
README.md
|
|
@ -37,245 +37,7 @@ The following improvements and features have been made after the fork. At this p
|
|||
|
||||
## Protocol
|
||||
|
||||
Transmitting messages between KeePassXC and keepassxc-browser is totally rewritten. This is still under development.
|
||||
Now the requests are encrypted by [TweetNaCl.js](https://github.com/dchest/tweetnacl-js) box method and does the following:
|
||||
|
||||
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 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.
|
||||
|
||||
Encrypted messages are built with these JSON parameters:
|
||||
- action - `test-associate`, `associate`, `get-logins`, `get-logins-count`, `set-login`...
|
||||
- message - Encrypted message, base64 encoded
|
||||
- nonce - 24 bytes long random data, base64 encoded. This must be the same when responding to a request.
|
||||
- clientID - 24 bytes long random data, base64 encoded. This is used to identify different browsers if multiple are used with proxy application.
|
||||
|
||||
### change-public-keys
|
||||
Request:
|
||||
```javascript
|
||||
{
|
||||
"action": "change-public-keys",
|
||||
"publicKey": "<current public key>",
|
||||
"proxyPort": "<UDP port for proxy applications>",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"clientID": "<clientID>"
|
||||
}
|
||||
```
|
||||
|
||||
Response (success):
|
||||
```javascript
|
||||
{
|
||||
"action": "change-public-keys",
|
||||
"version": "2.2.0",
|
||||
"publicKey": "<host public key>",
|
||||
"success": "true"
|
||||
}
|
||||
```
|
||||
|
||||
### get-databasehash
|
||||
Request (unencrypted):
|
||||
```javascript
|
||||
{
|
||||
"action": "get-databasehash"
|
||||
}
|
||||
```
|
||||
|
||||
Response message data (success, decrypted):
|
||||
```javascript
|
||||
{
|
||||
"action": "hash",
|
||||
"hash": "29234e32274a32276e25666a42",
|
||||
"version": "2.2.0"
|
||||
}
|
||||
```
|
||||
|
||||
### associate
|
||||
Unencrypted message:
|
||||
```javascript
|
||||
{
|
||||
"action": "associate",
|
||||
"key": "<current public key>"
|
||||
}
|
||||
```
|
||||
|
||||
Request:
|
||||
```javascript
|
||||
{
|
||||
"action": "associate",
|
||||
"message": encryptedMessage
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"clientID": "<clientID>"
|
||||
}
|
||||
```
|
||||
|
||||
Response message data (success, decrypted):
|
||||
```javascript
|
||||
{
|
||||
"hash": "29234e32274a32276e25666a42",
|
||||
"version": "2.2.0",
|
||||
"success": "true",
|
||||
"id": "testclient",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q"
|
||||
}
|
||||
```
|
||||
|
||||
### test-associate
|
||||
Unencrypted message:
|
||||
```javascript
|
||||
{
|
||||
"action": "test-associate",
|
||||
"id": "<saved database identifier>",
|
||||
"key": "<saved database public key>",
|
||||
"clientID": "<clientID>"
|
||||
}
|
||||
```
|
||||
|
||||
Request:
|
||||
```javascript
|
||||
{
|
||||
"action": "test-associate",
|
||||
"message": encryptedMessage
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q"
|
||||
}
|
||||
```
|
||||
|
||||
Response message data (success, decrypted):
|
||||
```javascript
|
||||
{
|
||||
"version": "2.2.0",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"hash": "29234e32274a32276e25666a42",
|
||||
"id": "testclient",
|
||||
"success": "true"
|
||||
}
|
||||
```
|
||||
|
||||
### generate-password
|
||||
Request:
|
||||
```javascript
|
||||
{
|
||||
"action": "generate-password",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"clientID": "<clientID>"
|
||||
}
|
||||
```
|
||||
|
||||
Response message data (success, decrypted):
|
||||
```javascript
|
||||
{
|
||||
"version": "2.2.0",
|
||||
"entries": [
|
||||
{
|
||||
"login": 144,
|
||||
"password": "testclientpassword"
|
||||
}
|
||||
],
|
||||
"success": "true",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q"
|
||||
}
|
||||
```
|
||||
|
||||
### get-logins
|
||||
Unencrypted message:
|
||||
```javascript
|
||||
{
|
||||
"action": "get-logins",
|
||||
"url": "<snip>",
|
||||
"submitUrl": optional
|
||||
}
|
||||
```
|
||||
|
||||
Request:
|
||||
```javascript
|
||||
{
|
||||
"action": "get-logins",
|
||||
"message": encryptedMessage
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"clientID": "<clientID>"
|
||||
}
|
||||
```
|
||||
|
||||
Response message data (success, decrypted):
|
||||
```javascript
|
||||
{
|
||||
"count": "2",
|
||||
"entries" : [
|
||||
{
|
||||
"login": "user1",
|
||||
"name": "user1",
|
||||
"password": "passwd1"
|
||||
},
|
||||
{
|
||||
"login": "user2",
|
||||
"name": "user2",
|
||||
"password": "passwd2"
|
||||
}],
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"success": "true",
|
||||
"hash": "29234e32274a32276e25666a42",
|
||||
"version": "2.2.0"
|
||||
}
|
||||
```
|
||||
|
||||
### set-login
|
||||
Unencrypted message:
|
||||
```javascript
|
||||
{
|
||||
"action": "set-login",
|
||||
"url": "<snip>",
|
||||
"submitUrl": "<snip>",
|
||||
"id": "testclient",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"login": "user1",
|
||||
"password": "passwd1"
|
||||
}
|
||||
```
|
||||
|
||||
Request:
|
||||
```javascript
|
||||
{
|
||||
"action": "set-login",
|
||||
"message": encryptedMessage
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"clientID": "<clientID>"
|
||||
}
|
||||
```
|
||||
|
||||
Response message data (success, decrypted):
|
||||
```javascript
|
||||
{
|
||||
"count": null,
|
||||
"entries" : null,
|
||||
"error": "",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"success": "true",
|
||||
"hash": "29234e32274a32276e25666a42",
|
||||
"version": "2.2.0"
|
||||
}
|
||||
```
|
||||
|
||||
### lock-database
|
||||
Request:
|
||||
```javascript
|
||||
{
|
||||
"action": "lock-database",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"clientID": "<clientID>"
|
||||
}
|
||||
```
|
||||
|
||||
Response message data (success always returns an error, decrypted):
|
||||
```javascript
|
||||
{
|
||||
"action": "lock-database",
|
||||
"errorCode": 1,
|
||||
"error": "Database not opened",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q"
|
||||
}
|
||||
```
|
||||
The details about the messaging protocol used with the browser extension and KeePassXC can be found [here](https://github.com/varjolintu/keepassxc-browser/blob/master/keepassxc-protocol.md).
|
||||
|
||||
## Licenses
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ kpxcEvent.invoke = function(handler, callback, senderTabId, args, secondTime) {
|
|||
else {
|
||||
console.log('undefined handler for tab ' + tab.id);
|
||||
}
|
||||
});
|
||||
}).catch((e) => {console.log(e);});
|
||||
};
|
||||
|
||||
kpxcEvent.onShowAlert = function(callback, tab, message) {
|
||||
|
|
@ -240,7 +240,7 @@ kpxcEvent.pageClearLogins = function(callback, tab) {
|
|||
|
||||
kpxcEvent.oldDatabaseHash = 'no-hash';
|
||||
kpxcEvent.checkDatabaseHash = function(callback, tab) {
|
||||
keepass.getDatabaseHash((response) => {
|
||||
keepass.checkDatabaseHash((response) => {
|
||||
callback({old: kpxcEvent.oldDatabaseHash, new: response});
|
||||
kpxcEvent.oldDatabaseHash = response;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -632,6 +632,10 @@ keepass.isConfigured = function(callback) {
|
|||
}
|
||||
};
|
||||
|
||||
keepass.checkDatabaseHash = function(callback, tab) {
|
||||
callback(keepass.databaseHash);
|
||||
};
|
||||
|
||||
keepass.isAssociated = function() {
|
||||
return (keepass.associated.value && keepass.associated.hash && keepass.associated.hash === keepass.databaseHash);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ page.isValidProtocol = function(url) {
|
|||
|
||||
page.switchTab = function(callback, tab) {
|
||||
browserAction.showDefault(null, tab);
|
||||
browser.tabs.sendMessage(tab.id, {action: 'activated_tab'}).catch((e) => {console.log(e);});
|
||||
browser.tabs.sendMessage(tab.id, {action: 'activated_tab'}).catch((e) => {});
|
||||
};
|
||||
|
||||
page.clearCredentials = function(tabId, complete) {
|
||||
|
|
@ -82,7 +82,7 @@ page.clearCredentials = function(tabId, complete) {
|
|||
|
||||
browser.tabs.sendMessage(tabId, {
|
||||
action: 'clear_credentials'
|
||||
}).catch((e) => {console.log(e);});
|
||||
}).catch((e) => {});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ page.createTabEntry = function(tabId) {
|
|||
page.removePageInformationFromNotExistingTabs = function() {
|
||||
let rand = Math.floor(Math.random()*1001);
|
||||
if (rand === 28) {
|
||||
browser.tabs.query({}, (tabs) => {
|
||||
browser.tabs.query({}).then(function(tabs) {
|
||||
let $tabIds = {};
|
||||
const $infoIds = Object.keys(page.tabs);
|
||||
|
||||
|
|
|
|||
|
|
@ -46,9 +46,11 @@ browser.runtime.onMessage.addListener(function(req, sender, callback) {
|
|||
}
|
||||
else if (req.action === 'clear_credentials') {
|
||||
cipEvents.clearCredentials();
|
||||
callback();
|
||||
}
|
||||
else if (req.action === 'activated_tab') {
|
||||
cipEvents.triggerActivatedTab();
|
||||
callback();
|
||||
}
|
||||
else if (req.action === 'redetect_fields') {
|
||||
browser.runtime.sendMessage({
|
||||
|
|
@ -254,7 +256,7 @@ cipPassword.createDialog = function() {
|
|||
e.preventDefault();
|
||||
browser.runtime.sendMessage({
|
||||
action: 'generate_password'
|
||||
}).then(cipPassword.callbackGeneratedPassword);
|
||||
}).then(cipPassword.callbackGeneratedPassword).catch((e) => {console.log(e);});
|
||||
}
|
||||
},
|
||||
'Copy':
|
||||
|
|
@ -1129,6 +1131,7 @@ cip.detectNewActiveFields = function() {
|
|||
//}
|
||||
};
|
||||
|
||||
// Try to do this in a way that database value if checked without polling the KeePassXC.. too many messages jumping around
|
||||
// Switch credentials if database is changed or closed
|
||||
cip.detectDatabaseChange = function() {
|
||||
const dbDetectInterval = setInterval(function() {
|
||||
|
|
@ -1157,9 +1160,9 @@ cip.detectDatabaseChange = function() {
|
|||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}).catch((e) => {console.log(e);});
|
||||
}
|
||||
}, 2000);
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
cip.initCredentialFields = function(forceCall) {
|
||||
|
|
@ -1193,7 +1196,7 @@ cip.initCredentialFields = function(forceCall) {
|
|||
browser.runtime.sendMessage({
|
||||
action: 'retrieve_credentials',
|
||||
args: [ cip.url, cip.submitUrl ]
|
||||
}).then(cip.retrieveCredentialsCallback);
|
||||
}).then(cip.retrieveCredentialsCallback).catch((e) => {console.log(e);});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -1747,6 +1750,6 @@ cipEvents.triggerActivatedTab = function() {
|
|||
browser.runtime.sendMessage({
|
||||
action: 'retrieve_credentials',
|
||||
args: [ cip.url, cip.submitUrl ]
|
||||
}).then(cip.retrieveCredentialsCallback);
|
||||
}).then(cip.retrieveCredentialsCallback).catch((e) => {console.log(e);});
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "keepassxc-browser",
|
||||
"version": "0.3.6",
|
||||
"version": "0.3.7",
|
||||
"description": "KeePassXC integration for modern web browsers",
|
||||
"author": "Sami Vänttinen",
|
||||
"icons": {
|
||||
|
|
|
|||
253
keepassxc-protocol.md
Normal file
253
keepassxc-protocol.md
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
## keepassxc-protocol
|
||||
|
||||
Transmitting messages between KeePassXC and keepassxc-browser is totally rewritten. This is still under development.
|
||||
Now the requests are encrypted by [TweetNaCl.js](https://github.com/dchest/tweetnacl-js) box method and does the following:
|
||||
|
||||
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 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.
|
||||
|
||||
Encrypted messages are built with these JSON parameters:
|
||||
- action - `test-associate`, `associate`, `get-logins`, `get-logins-count`, `set-login`...
|
||||
- message - Encrypted message, base64 encoded
|
||||
- nonce - 24 bytes long random data, base64 encoded. This must be the same when responding to a request.
|
||||
- clientID - 24 bytes long random data, base64 encoded. This is used to identify different browsers if multiple are used with proxy application.
|
||||
|
||||
Currently these messages are implemented:
|
||||
- `change-public-keys`: Request for passing public keys from client to server and back.
|
||||
- `get-databasehash`: Request for receiving the database hash (SHA256) of the current active database.
|
||||
- `associate`: Request for associating a new client with KeePassXC.
|
||||
- `test-associate`: Request for testing if the client has been associated with KeePassXC.
|
||||
- `generate-password`: Request for generating a password. KeePassXC's settings are used.
|
||||
- `get-logins`: Requests for receiving credentials for the current URL match.
|
||||
- `set-login`: Request for adding or updating credentials to the database.
|
||||
- `lock-database`: Request for locking the database from client.
|
||||
- `database-locked`: A signal from KeePassXC, the current active database is locked.
|
||||
- `database-unlocked`: A signal from KeePassXC, the current active database is unlocked.
|
||||
|
||||
### change-public-keys
|
||||
Request:
|
||||
```javascript
|
||||
{
|
||||
"action": "change-public-keys",
|
||||
"publicKey": "<current public key>",
|
||||
"proxyPort": "<UDP port for proxy applications>",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"clientID": "<clientID>"
|
||||
}
|
||||
```
|
||||
|
||||
Response (success):
|
||||
```javascript
|
||||
{
|
||||
"action": "change-public-keys",
|
||||
"version": "2.2.0",
|
||||
"publicKey": "<host public key>",
|
||||
"success": "true"
|
||||
}
|
||||
```
|
||||
|
||||
### get-databasehash
|
||||
Request (unencrypted):
|
||||
```javascript
|
||||
{
|
||||
"action": "get-databasehash"
|
||||
}
|
||||
```
|
||||
|
||||
Response message data (success, decrypted):
|
||||
```javascript
|
||||
{
|
||||
"action": "hash",
|
||||
"hash": "29234e32274a32276e25666a42",
|
||||
"version": "2.2.0"
|
||||
}
|
||||
```
|
||||
|
||||
### associate
|
||||
Unencrypted message:
|
||||
```javascript
|
||||
{
|
||||
"action": "associate",
|
||||
"key": "<current public key>"
|
||||
}
|
||||
```
|
||||
|
||||
Request:
|
||||
```javascript
|
||||
{
|
||||
"action": "associate",
|
||||
"message": encryptedMessage
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"clientID": "<clientID>"
|
||||
}
|
||||
```
|
||||
|
||||
Response message data (success, decrypted):
|
||||
```javascript
|
||||
{
|
||||
"hash": "29234e32274a32276e25666a42",
|
||||
"version": "2.2.0",
|
||||
"success": "true",
|
||||
"id": "testclient",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q"
|
||||
}
|
||||
```
|
||||
|
||||
### test-associate
|
||||
Unencrypted message:
|
||||
```javascript
|
||||
{
|
||||
"action": "test-associate",
|
||||
"id": "<saved database identifier>",
|
||||
"key": "<saved database public key>",
|
||||
"clientID": "<clientID>"
|
||||
}
|
||||
```
|
||||
|
||||
Request:
|
||||
```javascript
|
||||
{
|
||||
"action": "test-associate",
|
||||
"message": encryptedMessage
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q"
|
||||
}
|
||||
```
|
||||
|
||||
Response message data (success, decrypted):
|
||||
```javascript
|
||||
{
|
||||
"version": "2.2.0",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"hash": "29234e32274a32276e25666a42",
|
||||
"id": "testclient",
|
||||
"success": "true"
|
||||
}
|
||||
```
|
||||
|
||||
### generate-password
|
||||
Request:
|
||||
```javascript
|
||||
{
|
||||
"action": "generate-password",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"clientID": "<clientID>"
|
||||
}
|
||||
```
|
||||
|
||||
Response message data (success, decrypted):
|
||||
```javascript
|
||||
{
|
||||
"version": "2.2.0",
|
||||
"entries": [
|
||||
{
|
||||
"login": 144,
|
||||
"password": "testclientpassword"
|
||||
}
|
||||
],
|
||||
"success": "true",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q"
|
||||
}
|
||||
```
|
||||
|
||||
### get-logins
|
||||
Unencrypted message:
|
||||
```javascript
|
||||
{
|
||||
"action": "get-logins",
|
||||
"url": "<snip>",
|
||||
"submitUrl": optional
|
||||
}
|
||||
```
|
||||
|
||||
Request:
|
||||
```javascript
|
||||
{
|
||||
"action": "get-logins",
|
||||
"message": encryptedMessage
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"clientID": "<clientID>"
|
||||
}
|
||||
```
|
||||
|
||||
Response message data (success, decrypted):
|
||||
```javascript
|
||||
{
|
||||
"count": "2",
|
||||
"entries" : [
|
||||
{
|
||||
"login": "user1",
|
||||
"name": "user1",
|
||||
"password": "passwd1"
|
||||
},
|
||||
{
|
||||
"login": "user2",
|
||||
"name": "user2",
|
||||
"password": "passwd2"
|
||||
}],
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"success": "true",
|
||||
"hash": "29234e32274a32276e25666a42",
|
||||
"version": "2.2.0"
|
||||
}
|
||||
```
|
||||
|
||||
### set-login
|
||||
Unencrypted message:
|
||||
```javascript
|
||||
{
|
||||
"action": "set-login",
|
||||
"url": "<snip>",
|
||||
"submitUrl": "<snip>",
|
||||
"id": "testclient",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"login": "user1",
|
||||
"password": "passwd1"
|
||||
}
|
||||
```
|
||||
|
||||
Request:
|
||||
```javascript
|
||||
{
|
||||
"action": "set-login",
|
||||
"message": encryptedMessage
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"clientID": "<clientID>"
|
||||
}
|
||||
```
|
||||
|
||||
Response message data (success, decrypted):
|
||||
```javascript
|
||||
{
|
||||
"count": null,
|
||||
"entries" : null,
|
||||
"error": "",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"success": "true",
|
||||
"hash": "29234e32274a32276e25666a42",
|
||||
"version": "2.2.0"
|
||||
}
|
||||
```
|
||||
|
||||
### lock-database
|
||||
Request:
|
||||
```javascript
|
||||
{
|
||||
"action": "lock-database",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"clientID": "<clientID>"
|
||||
}
|
||||
```
|
||||
|
||||
Response message data (success always returns an error, decrypted):
|
||||
```javascript
|
||||
{
|
||||
"action": "lock-database",
|
||||
"errorCode": 1,
|
||||
"error": "Database not opened",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q"
|
||||
}
|
||||
```
|
||||
Loading…
Reference in a new issue