mirror of
https://github.com/keepassxreboot/keepassxc-browser.git
synced 2026-03-11 08:54:43 +00:00
Merge branch 'develop'
This commit is contained in:
commit
75e1e1a2f8
11 changed files with 79 additions and 105 deletions
|
|
@ -1,3 +1,9 @@
|
|||
0.4.0 (13-11-2017)
|
||||
=========================
|
||||
- Fixed showing context menu on password fields with Firefox
|
||||
- Ignore XML files on content scripts (Firefox shows them incorrectly)
|
||||
- UDP features removed as KeePassXC switched them to Unix domain sockets and named pipes
|
||||
|
||||
0.3.9 (04-11-2017)
|
||||
=========================
|
||||
- Removed incorrect timeout waiting on init
|
||||
|
|
|
|||
13
README.md
13
README.md
|
|
@ -1,13 +1,13 @@
|
|||
# keepassxc-browser
|
||||
Chrome extension for [KeePassXC](https://keepassxc.org/) with Native Messaging.
|
||||
Browser extension for [KeePassXC](https://keepassxc.org/) with Native Messaging.
|
||||
|
||||
This is a heavily forked version of [pfn](https://github.com/pfn)'s [chromeIPass](https://github.com/pfn/passifox).
|
||||
Some changes merged also from [smorks'](https://github.com/smorks/keepasshttp-connector) KeePassHttp-Connector fork.
|
||||
For testing purposes, please use following unofficial KeePassXC [release's](https://github.com/varjolintu/keepassxc/releases).
|
||||
For testing purposes, please use only the following unofficial KeePassXC [release's](https://github.com/varjolintu/keepassxc/releases).
|
||||
|
||||
Get the extension for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/) or [Chrome/Chromium](https://chrome.google.com/webstore/detail/keepassxc-browser/iopaggbpplllidnfmcghoonnokmjoicf).
|
||||
|
||||
The extension is supported with Firefox 55 and newer. If you want to load it as a temporary plugin with Firefox 54 you can just change the minimum version from the manifest file before loading it.
|
||||
The extension is supported with Firefox 55 and newer. If you want to load it as a temporary plugin with Firefox 54 or ESR you can just change the minimum version from the manifest file before loading it.
|
||||
|
||||
Please thee this [wiki page](hhttps://github.com/varjolintu/keepassxc-browser/wiki/Connecting-the-database-with-keepassxc-browser) for instructions how to configure this KeePassXC fork in order to connect the database correctly.
|
||||
|
||||
|
|
@ -17,10 +17,11 @@ There are two methods which you can use keepassxc-browser to connect to KeePassX
|
|||
1. keepassxc-browser communicates directly with KeePassXC via stdin/stdout. This method launches KeePassXC every time you start the browser and closes when you exit.
|
||||
This can cause unsaved changes not to be saved. If you use this method it's important to enable `Automatically save after every change` from KeePassXC's preferences.
|
||||
|
||||
2. keepassxc-browser communicated with KeePassXC through [keepassxc-proxy](https://github.com/varjolintu/keepassxc-proxy) or [keepassxc-proxy-rust](https://github.com/varjolintu/keepassxc-proxy-rust). The proxy handles listening stdin/stdout
|
||||
2. keepassxc-browser communicated with KeePassXC through [keepassxc-proxy](https://github.com/varjolintu/keepassxc-proxy). The proxy handles listening stdin/stdout
|
||||
and transfers these messages through Unix domain sockets / named pipes to KeePassXC. This means KeePassXC can be used and started normally without inteference from
|
||||
Native Messaging API. keepassxc-browser starts only the proxy application and there's no risk of shutting down KeePassXC or losing any unsaved changes. keepassxc-proxy
|
||||
is still under development. If you want, you are free to write your own proxy that handles the traffic.
|
||||
is still under development. If you want, you are free to write your own proxy that handles the traffic. You don't need to install keepassxc-proxy separately. It is
|
||||
included in the latest KeePassXC fork. Use it if you want to make your own proxy or improve/extend it.
|
||||
|
||||
## Improvements
|
||||
The following improvements and features have been made after the fork. At this point some features are only available with the KeePassXC fork:
|
||||
|
|
@ -77,4 +78,4 @@ Feel free to support this project:
|
|||
- Donate via [PayPal](https://paypal.me/varjolintu)
|
||||
- Donate via Bitcoin: 1LHbD69CcmpLW5hjUXs2MGJhw3GxwqLdw3
|
||||
|
||||
Also consider donating to [KeePassXC](https://flattr.com/submit/auto?fid=x7yqz0&url=https%3A%2F%2Fkeepassxc.org) and passifox teams [(1)](https://github.com/smorks/passifox),[(2)](https://github.com/projectgus/passifox),[(3)](https://github.com/pfn/passifox). They are doing great job.
|
||||
Also consider donating to [KeePassXC](https://flattr.com/submit/auto?fid=x7yqz0&url=https%3A%2F%2Fkeepassxc.org) and passifox teams [(1)](https://github.com/smorks/passifox),[(2)](https://github.com/pfn/passifox). They are doing great job.
|
||||
|
|
|
|||
|
|
@ -128,17 +128,24 @@ kpxcEvent.onSaveSettings = function(callback, tab, settings) {
|
|||
});
|
||||
};
|
||||
|
||||
kpxcEvent.onGetStatus = function(callback, tab) {
|
||||
keepass.testAssociation((response) => {
|
||||
if (!response) {
|
||||
kpxcEvent.showStatus(false, tab, callback);
|
||||
return;
|
||||
}
|
||||
kpxcEvent.onGetStatus = function(callback, tab, internalPoll = false) {
|
||||
// When internalPoll is true the event is triggered from content script in intervals -> don't poll KeePassXC
|
||||
if (!internalPoll) {
|
||||
keepass.testAssociation((response) => {
|
||||
if (!response) {
|
||||
kpxcEvent.showStatus(false, tab, callback);
|
||||
return;
|
||||
}
|
||||
|
||||
keepass.isConfigured().then((configured) => {
|
||||
kpxcEvent.showStatus(configured, tab, callback);
|
||||
});
|
||||
}, tab, true);
|
||||
} else {
|
||||
keepass.isConfigured().then((configured) => {
|
||||
kpxcEvent.showStatus(configured, tab, callback);
|
||||
});
|
||||
}, tab, true);
|
||||
}
|
||||
};
|
||||
|
||||
kpxcEvent.onReconnect = function(callback, tab) {
|
||||
|
|
|
|||
|
|
@ -92,17 +92,23 @@ if (browser.webRequest.onAuthRequired) {
|
|||
browser.runtime.onMessage.addListener(kpxcEvent.onMessage);
|
||||
|
||||
const contextMenuItems = [
|
||||
{title: 'Fill &User + Pass', action: 'fill_user_pass'},
|
||||
{title: 'Fill &Pass Only', action: 'fill_pass_only'},
|
||||
{title: 'Show Password &Generator Icons', action: 'activate_password_generator'},
|
||||
{title: '&Save credentials', action: 'remember_credentials'}
|
||||
{title: 'Fill User + Pass', action: 'fill_user_pass'},
|
||||
{title: 'Fill Pass Only', action: 'fill_pass_only'},
|
||||
{title: 'Show Password Generator Icons', action: 'activate_password_generator'},
|
||||
{title: 'Save credentials', action: 'remember_credentials'}
|
||||
];
|
||||
|
||||
let menuContexts = ['editable'];
|
||||
|
||||
if (isFirefox()) {
|
||||
menuContexts.push('password');
|
||||
}
|
||||
|
||||
// Create context menu items
|
||||
for (const item of contextMenuItems) {
|
||||
browser.contextMenus.create({
|
||||
title: item.title,
|
||||
contexts: [ 'editable' ],
|
||||
contexts: menuContexts,
|
||||
onclick: (info, tab) => {
|
||||
browser.tabs.sendMessage(tab.id, {
|
||||
action: item.action
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ keepass.updateCredentials = function(callback, tab, entryId, username, password,
|
|||
const request = {
|
||||
action: kpAction,
|
||||
message: keepass.encrypt(messageData, nonce),
|
||||
nonce: keepass.b64e(nonce),
|
||||
nonce: nacl.util.encodeBase64(nonce),
|
||||
clientID: keepass.clientID
|
||||
};
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ keepass.retrieveCredentials = function(callback, tab, url, submiturl, forceCallb
|
|||
const request = {
|
||||
action: kpAction,
|
||||
message: keepass.encrypt(messageData, nonce),
|
||||
nonce: keepass.b64e(nonce),
|
||||
nonce: nacl.util.encodeBase64(nonce),
|
||||
clientID: keepass.clientID
|
||||
};
|
||||
|
||||
|
|
@ -285,7 +285,7 @@ keepass.generatePassword = function(callback, tab, forceCallback) {
|
|||
|
||||
const request = {
|
||||
action: kpAction,
|
||||
nonce: keepass.b64e(nonce),
|
||||
nonce: nacl.util.encodeBase64(nonce),
|
||||
clientID: keepass.clientID
|
||||
};
|
||||
|
||||
|
|
@ -334,7 +334,7 @@ keepass.associate = function(callback, tab) {
|
|||
page.tabs[tab.id].errorMessage = null;
|
||||
|
||||
const kpAction = kpActions.ASSOCIATE;
|
||||
const key = keepass.b64e(keepass.keyPair.publicKey);
|
||||
const key = nacl.util.encodeBase64(keepass.keyPair.publicKey);
|
||||
const nonce = nacl.randomBytes(keepass.keySize);
|
||||
|
||||
const messageData = {
|
||||
|
|
@ -345,7 +345,7 @@ keepass.associate = function(callback, tab) {
|
|||
const request = {
|
||||
action: kpAction,
|
||||
message: keepass.encrypt(messageData, nonce),
|
||||
nonce: keepass.b64e(nonce),
|
||||
nonce: nacl.util.encodeBase64(nonce),
|
||||
clientID: keepass.clientID
|
||||
};
|
||||
|
||||
|
|
@ -427,7 +427,7 @@ keepass.testAssociation = function(callback, tab, enableTimeout = false) {
|
|||
const request = {
|
||||
action: kpAction,
|
||||
message: keepass.encrypt(messageData, nonce),
|
||||
nonce: keepass.b64e(nonce),
|
||||
nonce: nacl.util.encodeBase64(nonce),
|
||||
clientID: keepass.clientID
|
||||
};
|
||||
|
||||
|
|
@ -494,7 +494,7 @@ keepass.getDatabaseHash = function(callback, tab, enableTimeout = false) {
|
|||
const request = {
|
||||
action: kpAction,
|
||||
message: encrypted,
|
||||
nonce: keepass.b64e(nonce),
|
||||
nonce: nacl.util.encodeBase64(nonce),
|
||||
clientID: keepass.clientID
|
||||
};
|
||||
|
||||
|
|
@ -545,19 +545,19 @@ keepass.getDatabaseHash = function(callback, tab, enableTimeout = false) {
|
|||
keepass.changePublicKeys = function(tab, enableTimeout = false) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!keepass.isConnected) {
|
||||
keepass.handleError(tab, kpErrors.TIMEOUT_OR_NOT_CONNECTED);
|
||||
reject(false);
|
||||
}
|
||||
|
||||
const kpAction = kpActions.CHANGE_PUBLIC_KEYS;
|
||||
const key = keepass.b64e(keepass.keyPair.publicKey);
|
||||
const key = nacl.util.encodeBase64(keepass.keyPair.publicKey);
|
||||
let nonce = nacl.randomBytes(keepass.keySize);
|
||||
nonce = keepass.b64e(nonce);
|
||||
keepass.clientID = keepass.b64e(nacl.randomBytes(keepass.keySize));
|
||||
nonce = nacl.util.encodeBase64(nonce);
|
||||
keepass.clientID = nacl.util.encodeBase64(nacl.randomBytes(keepass.keySize));
|
||||
|
||||
const request = {
|
||||
action: kpAction,
|
||||
publicKey: key,
|
||||
proxyPort: (page.settings.port ? page.settings.port : 19700),
|
||||
nonce: nonce,
|
||||
clientID: keepass.clientID
|
||||
};
|
||||
|
|
@ -573,7 +573,7 @@ keepass.changePublicKeys = function(tab, enableTimeout = false) {
|
|||
}
|
||||
else {
|
||||
keepass.isKeePassXCAvailable = true;
|
||||
console.log('Server public key: ' + keepass.b64e(keepass.serverPublicKey));
|
||||
console.log('Server public key: ' + nacl.util.encodeBase64(keepass.serverPublicKey));
|
||||
}
|
||||
resolve(true);
|
||||
});
|
||||
|
|
@ -597,7 +597,7 @@ keepass.lockDatabase = function(tab) {
|
|||
const request = {
|
||||
action: kpAction,
|
||||
message: keepass.encrypt(messageData, nonce),
|
||||
nonce: keepass.b64e(nonce),
|
||||
nonce: nacl.util.encodeBase64(nonce),
|
||||
clientID: keepass.clientID
|
||||
};
|
||||
|
||||
|
|
@ -627,12 +627,12 @@ keepass.lockDatabase = function(tab) {
|
|||
|
||||
keepass.generateNewKeyPair = function() {
|
||||
keepass.keyPair = nacl.box.keyPair();
|
||||
//console.log(keepass.b64e(keepass.keyPair.publicKey) + ' ' + keepass.b64e(keepass.keyPair.secretKey));
|
||||
//console.log(nacl.util.encodeBase64(keepass.keyPair.publicKey) + ' ' + nacl.util.encodeBase64(keepass.keyPair.secretKey));
|
||||
};
|
||||
|
||||
keepass.isConfigured = function() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof(keepass.databaseHash) === 'undefined' || keepass.databaseHash === 'no-hash') {
|
||||
if (typeof(keepass.databaseHash) === 'undefined') {
|
||||
keepass.getDatabaseHash((hash) => {
|
||||
resolve(hash in keepass.keyRing);
|
||||
});
|
||||
|
|
@ -810,13 +810,14 @@ keepass.verifyKeyResponse = function(response, key, nonce) {
|
|||
}
|
||||
|
||||
let reply = false;
|
||||
if (keepass.b64d(nonce).length !== nacl.secretbox.nonceLength)
|
||||
if (nacl.util.decodeBase64(nonce).length !== nacl.secretbox.nonceLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
reply = (response.nonce === nonce);
|
||||
|
||||
if (response.publicKey) {
|
||||
keepass.serverPublicKey = keepass.b64d(response.publicKey);
|
||||
keepass.serverPublicKey = nacl.util.decodeBase64(response.publicKey);
|
||||
reply = true;
|
||||
}
|
||||
|
||||
|
|
@ -832,8 +833,9 @@ keepass.verifyResponse = function(response, nonce, id) {
|
|||
|
||||
keepass.associated.hash = keepass.databaseHash;
|
||||
|
||||
if (keepass.b64d(response.nonce).length !== nacl.secretbox.nonceLength)
|
||||
if (nacl.util.decodeBase64(response.nonce).length !== nacl.secretbox.nonceLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
keepass.associated.value = (response.nonce === nonce);
|
||||
|
||||
|
|
@ -856,14 +858,6 @@ keepass.handleError = function(tab, errorCode, errorMessage = '') {
|
|||
}
|
||||
};
|
||||
|
||||
keepass.b64e = function(d) {
|
||||
return nacl.util.encodeBase64(d);
|
||||
};
|
||||
|
||||
keepass.b64d = function(d) {
|
||||
return nacl.util.decodeBase64(d);
|
||||
};
|
||||
|
||||
keepass.getCryptoKey = function() {
|
||||
let dbkey = null;
|
||||
let dbid = null;
|
||||
|
|
@ -890,15 +884,15 @@ keepass.encrypt = function(input, nonce) {
|
|||
if (keepass.serverPublicKey) {
|
||||
const message = nacl.box(messageData, nonce, keepass.serverPublicKey, keepass.keyPair.secretKey);
|
||||
if (message) {
|
||||
return keepass.b64e(message);
|
||||
return nacl.util.encodeBase64(message);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
keepass.decrypt = function(input, nonce, toStr) {
|
||||
const m = keepass.b64d(input);
|
||||
const n = keepass.b64d(nonce);
|
||||
const m = nacl.util.decodeBase64(input);
|
||||
const n = nacl.util.decodeBase64(nonce);
|
||||
const res = nacl.box.open(m, n, keepass.serverPublicKey, keepass.keyPair.secretKey);
|
||||
return res;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ const defaultSettings = {
|
|||
autoFillAndSend: true,
|
||||
usePasswordGenerator: true,
|
||||
autoFillSingleEntry: false,
|
||||
autoRetrieveCredentials: true,
|
||||
proxyPort: '19700'
|
||||
autoRetrieveCredentials: true
|
||||
};
|
||||
|
||||
var page = {};
|
||||
|
|
@ -35,9 +34,6 @@ page.initSettings = function() {
|
|||
if (!('autoRetrieveCredentials' in page.settings)) {
|
||||
page.settings.autoRetrieveCredentials = defaultSettings.autoRetrieveCredentials;
|
||||
}
|
||||
if (!('port' in page.settings)) {
|
||||
page.settings.port = defaultSettings.proxyPort;
|
||||
}
|
||||
browser.storage.local.set({'settings': page.settings});
|
||||
resolve();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -396,7 +396,6 @@ cipPassword.callbackPasswordCopied = function(bool) {
|
|||
|
||||
cipPassword.callbackGeneratedPassword = function(entries) {
|
||||
if (entries && entries.length >= 1) {
|
||||
console.log(entries[0]);
|
||||
jQuery('#cip-genpw-btn-clipboard:first').removeClass('btn-success');
|
||||
jQuery('input#cip-genpw-textfield-password:first').val(entries[0].password);
|
||||
if (isNaN(entries[0].login)) {
|
||||
|
|
@ -408,7 +407,7 @@ cipPassword.callbackGeneratedPassword = function(entries) {
|
|||
}
|
||||
else {
|
||||
if (jQuery('div#cip-genpw-error:first').length === 0) {
|
||||
jQuery('button#cip-genpw-btn-generate:first').after('<div style=\'block\' id=\'cip-genpw-error\'>Cannot receive generated password.<br />Is your version of KeePassXC up-to-date?<br /><br /><a href=\'https://keepassxc.org\'>Please visit the KeePassXC homepage</a></div>');
|
||||
jQuery('button#cip-genpw-btn-generate:first').after('<div style=\'block\' id=\'cip-genpw-error\'>Cannot receive generated password.<br />Is KeePassXC opened?<br /></div>');
|
||||
jQuery('input#cip-genpw-textfield-password:first').parent().hide();
|
||||
jQuery('input#cip-genpw-checkbox-next-field:first').parent('label').hide();
|
||||
jQuery('button#cip-genpw-btn-generate').hide();
|
||||
|
|
@ -1117,21 +1116,15 @@ cip.init = function() {
|
|||
};
|
||||
|
||||
cip.detectNewActiveFields = function() {
|
||||
const hiddenFields = cipFields.getHiddenFieldCount();
|
||||
|
||||
// If hidden fields aren't detected, setInterval is being looped in each frame of the page
|
||||
//if (hiddenFields > 0) {
|
||||
const divDetect = setInterval(function() {
|
||||
const fields = cipFields.getAllFields();
|
||||
if (fields.length > 1) {
|
||||
cip.initCredentialFields(true);
|
||||
clearInterval(divDetect);
|
||||
}
|
||||
}, 1000);
|
||||
//}
|
||||
const divDetect = setInterval(function() {
|
||||
const fields = cipFields.getAllFields();
|
||||
if (fields.length > 1) {
|
||||
cip.initCredentialFields(true);
|
||||
clearInterval(divDetect);
|
||||
}
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
// 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() {
|
||||
let dbDetectInterval = setInterval(function() {
|
||||
|
|
@ -1148,7 +1141,8 @@ cip.detectDatabaseChange = function() {
|
|||
|
||||
// Switch back to default popup
|
||||
browser.runtime.sendMessage({
|
||||
action: 'get_status'
|
||||
action: 'get_status',
|
||||
args: [ true ] // Set polling to true, this is an internal function call
|
||||
});
|
||||
} else {
|
||||
if (response.new !== 'no-hash' && response.new !== response.old) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "keepassxc-browser",
|
||||
"version": "0.3.9",
|
||||
"version": "0.4.0",
|
||||
"description": "KeePassXC integration for modern web browsers",
|
||||
"author": "Sami Vänttinen",
|
||||
"icons": {
|
||||
|
|
@ -41,6 +41,9 @@
|
|||
"matches": [
|
||||
"<all_urls>"
|
||||
],
|
||||
"exclude_matches": [
|
||||
"*://*/*.xml"
|
||||
],
|
||||
"js": [
|
||||
"browser-polyfill.min.js",
|
||||
"global.js",
|
||||
|
|
@ -67,8 +70,8 @@
|
|||
"fill-password": {
|
||||
"description": "Insert a password",
|
||||
"suggested_key": {
|
||||
"default": "Ctrl+Shift+P",
|
||||
"mac": "Command+Shift+P"
|
||||
"default": "Alt+Shift+P",
|
||||
"mac": "Alt+Shift+P"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -84,24 +84,6 @@
|
|||
</span>
|
||||
</div>
|
||||
</p>
|
||||
<p>
|
||||
<div class="form-group">
|
||||
<label for="port">UDP port for proxy applications:</label>
|
||||
<div class="control-group">
|
||||
<div class="input-append">
|
||||
<input type="number" id="port" placeholder="19700" value="19700" />
|
||||
<button class="btn btn-sm btn-primary" id="portButton" type="button"><span class="glyphicon glyphicon-floppy-disk"></span> Save</button>
|
||||
</div>
|
||||
<span class="help-inline">
|
||||
Change the port if you have trouble with running KeePassXC on the default port.
|
||||
<br />
|
||||
You have to set the same port number in KeePassXC options.
|
||||
<br />
|
||||
Default: 19700
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</p>
|
||||
<hr />
|
||||
<p>
|
||||
<div class="checkbox">
|
||||
|
|
|
|||
|
|
@ -88,24 +88,10 @@ options.initGeneralSettings = function() {
|
|||
}).then(options.showKeePassXCVersions);
|
||||
});
|
||||
|
||||
$('#port').val(options.settings['port']);
|
||||
$('#blinkTimeout').val(options.settings['blinkTimeout']);
|
||||
$('#blinkMinTimeout').val(options.settings['blinkMinTimeout']);
|
||||
$('#allowedRedirect').val(options.settings['allowedRedirect']);
|
||||
|
||||
$('#portButton').click(function() {
|
||||
const port = $.trim($('#port').val());
|
||||
const portNumber = Number(port);
|
||||
if (isNaN(port) || portNumber < 1025 || portNumber > 99999) {
|
||||
$('#port').closest('.control-group').addClass('error');
|
||||
alert('The port number has to be in range 1025 - 99999.\nNothing saved!');
|
||||
return;
|
||||
}
|
||||
|
||||
options.settings['port'] = String(portNumber);
|
||||
options.saveSetting('port');
|
||||
});
|
||||
|
||||
$('#blinkTimeoutButton').click(function(){
|
||||
const blinkTimeout = $.trim($('#blinkTimeout').val());
|
||||
const blinkTimeoutval = Number(blinkTimeout);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ Request:
|
|||
{
|
||||
"action": "change-public-keys",
|
||||
"publicKey": "<current public key>",
|
||||
"proxyPort": "<UDP port for proxy applications>",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q",
|
||||
"clientID": "<clientID>"
|
||||
}
|
||||
|
|
@ -250,4 +249,4 @@ Response message data (success always returns an error, decrypted):
|
|||
"error": "Database not opened",
|
||||
"nonce": "tZvLrBzkQ9GxXq9PvKJj4iAnfPT0VZ3Q"
|
||||
}
|
||||
```
|
||||
```
|
||||
|
|
|
|||
Loading…
Reference in a new issue