mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
Remove KeePass integration (#4628)
* Remove KeePass integration This integration is not actively supported. It has zero tests, little documentation, and has not really been actively maintained. As far as I can tell, noone uses this integration, and even if they do, they will simply have to copy/paste password from keepass instead of using this integration. * continued
This commit is contained in:
parent
e95c13c207
commit
5bc79fefc9
@ -1,58 +0,0 @@
|
||||
### What is it about
|
||||
|
||||
More info regarding KeePass: http://keepass.info/
|
||||
|
||||
KeePass integration use KeePassHttp (https://github.com/pfn/keepasshttp/) to facilitate communications between the client and KeePass. KeePassHttp is a plugin for KeePass 2.x and provides a secure means of exposing KeePass entries via HTTP for clients to consume.
|
||||
|
||||
The implementation is dependent on the following:
|
||||
- crypter.h for AES encryption helper functions.
|
||||
- rpcprotocol.h for handling RPC communications. Could only be used partially however due some static values in the code.
|
||||
- OpenSSL for base64 encoding. regular util.h libraries were not used for base64 encoding/decoding since they do not use secure allocation.
|
||||
- JSON Spirit for reading / writing RPC communications
|
||||
|
||||
### A note about security
|
||||
|
||||
Every connection to KeePassHTTP server is done via plain HTTP and even though protocol uses some internal encryption it should not be considered to be a highly secure one. This protocol has certain flaw which allow an attacker to decrypt your passwords when they manage to intercept communication between a KeePassHTTP server over a network connection (see [here](https://github.com/pfn/keepasshttp/issues/258) and [here](https://github.com/keepassxreboot/keepassxc/issues/147)). Dash Core therefore strictly limits communication between itself and KeePassHttp to your local computer. As long as your computer is not compromised, your wallet passphrase is as safe as if you would enter it directly.
|
||||
|
||||
### What's new
|
||||
|
||||
The following new options are available for dashd and dash-qt:
|
||||
- _-keepass_ Use KeePass 2 integration using KeePassHttp plugin (default: 0)
|
||||
- _-keepassport=_ Connect to KeePassHttp on port (default: 19455)
|
||||
- _-keepasskey=_ KeePassHttp key for AES encrypted communication with KeePass
|
||||
- _-keepassid=_ KeePassHttp id for the established association
|
||||
- _-keepassname=_ Name to construct url for KeePass entry that stores the wallet passphrase
|
||||
|
||||
The following rpc commands are available:
|
||||
|
||||
- _keepass genkey_: generates a base64 encoded 256 bit AES key that can be used for the communication with KeePassHttp. Only necessary for manual configuration. Use init for automatic configuration.
|
||||
- _keepass init_: sets up the association between dashd and keepass by generating an AES key and sending an association message to KeePassHttp. This will trigger KeePass to ask for an Id for the association. Returns the association and the base64 encoded string for the AES key.
|
||||
- _keepass setpassphrase_: updates the passphrase in KeePassHttp to a new value. This should match the passphrase you intend to use for the wallet. Please note that the standard RPC commands _walletpassphrasechange_ and the wallet encryption from the QT GUI already send the updates to KeePassHttp, so this is only necessary for manual manipulation of the password.
|
||||
|
||||
### How to setup
|
||||
|
||||
Sample initialization flow from _dash-qt_ console (this needs to be done only once to set up the association):
|
||||
|
||||
- Have KeePass running with an open database
|
||||
- Start _dash-qt_
|
||||
- Open console
|
||||
- Type "_keepass init_" in dash-qt console
|
||||
- Keepass pops up and asks for an association id, fill that in, for example, "_mydrkwallet_"
|
||||
- You should get a response like this "_Association successful. Id: mydrkwalletdash - Key: AgQkcs6cI7v9tlSYKjG/+s8wJrGALHl3jLosJpPLzUE=_"
|
||||
- Edit _dash.conf_ and fill in these values
|
||||
```
|
||||
keepass=1
|
||||
keepasskey=AgQkcs6cI7v9tlSYKjG/+s8wJrGALHl3jLosJpPLzUE=
|
||||
keepassid=mydrkwallet
|
||||
keepassname=testwallet
|
||||
```
|
||||
- Restart _dash-qt_
|
||||
|
||||
At this point, the association is made. The next action depends on your particular situation:
|
||||
|
||||
- current wallet is not yet encrypted. Encrypting the wallet will trigger the integration and stores the password in KeePass (Under the '_KeePassHttp Passwords_' group, named after _keepassname_.
|
||||
- current wallet is already encrypted: use "_keepass setpassphrase_" to store the passphrase in KeePass.
|
||||
|
||||
At this point, the passphrase is stored in KeePassHttp. When Unlocking the wallet, one can use _keepass_ as the passphrase to trigger retrieval of the password. This works from the RPC commands as well as the GUI.
|
||||
|
||||
Extended guide with screenshots is also available: https://www.dash.org/forum/threads/keepass-integration.3620/
|
@ -199,7 +199,6 @@ BITCOIN_CORE_H = \
|
||||
interfaces/wallet.h \
|
||||
key.h \
|
||||
key_io.h \
|
||||
keepass.h \
|
||||
keystore.h \
|
||||
dbwrapper.h \
|
||||
limitedmap.h \
|
||||
@ -463,7 +462,6 @@ libdash_wallet_a_SOURCES = \
|
||||
coinjoin/options.cpp \
|
||||
coinjoin/util.cpp \
|
||||
interfaces/wallet.cpp \
|
||||
keepass.cpp \
|
||||
wallet/coincontrol.cpp \
|
||||
wallet/crypter.cpp \
|
||||
wallet/db.cpp \
|
||||
|
@ -23,7 +23,6 @@ public:
|
||||
// Dash Specific WalletInitInterface InitCoinJoinSettings
|
||||
void AutoLockMasternodeCollaterals() const override {}
|
||||
void InitCoinJoinSettings() const override {}
|
||||
void InitKeePass() const override {}
|
||||
bool InitAutoBackup() const override {return true;}
|
||||
};
|
||||
|
||||
@ -55,11 +54,6 @@ void DummyWalletInit::AddWalletOptions() const
|
||||
"-mnemonic=<text>",
|
||||
"-mnemonicpassphrase=<text>",
|
||||
"-usehd",
|
||||
"-keepass",
|
||||
"-keepassid=<id>",
|
||||
"-keepasskey=<key>",
|
||||
"-keepassname=<name>",
|
||||
"-keepassport=<port>",
|
||||
"-enablecoinjoin",
|
||||
"-coinjoinamount=<n>",
|
||||
"-coinjoinautostart",
|
||||
|
@ -1757,8 +1757,6 @@ bool AppInitMain(InitInterfaces& interfaces)
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize KeePass Integration
|
||||
g_wallet_init_interface.InitKeePass();
|
||||
// ********************************************************* Step 6: network initialization
|
||||
// Note that we absolutely cannot open any actual connections
|
||||
// until the very end ("start node") as the UTXO/block state
|
||||
|
568
src/keepass.cpp
568
src/keepass.cpp
@ -1,568 +0,0 @@
|
||||
// Copyright (c) 2014-2020 The Dash Core developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <keepass.h>
|
||||
|
||||
#include <wallet/crypter.h>
|
||||
#include <clientversion.h>
|
||||
#include <protocol.h>
|
||||
#include <random.h>
|
||||
#include <rpc/protocol.h>
|
||||
|
||||
// Necessary to prevent compile errors due to forward declaration of
|
||||
//CScript in serialize.h (included from crypter.h)
|
||||
#include <script/script.h>
|
||||
#include <script/standard.h>
|
||||
|
||||
#include <util/system.h>
|
||||
#include <util/strencodings.h>
|
||||
|
||||
#include <event2/event.h>
|
||||
#include <event2/http.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/keyvalq_struct.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include <support/cleanse.h> // for OPENSSL_cleanse()
|
||||
|
||||
const char* CKeePassIntegrator::KEEPASS_HTTP_HOST = "localhost";
|
||||
|
||||
CKeePassIntegrator keePassInt;
|
||||
|
||||
// Base64 decoding with secure memory allocation
|
||||
SecureString DecodeBase64Secure(const SecureString& sInput)
|
||||
{
|
||||
SecureString output;
|
||||
|
||||
// Init openssl BIO with base64 filter and memory input
|
||||
BIO *b64, *mem;
|
||||
b64 = BIO_new(BIO_f_base64());
|
||||
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer
|
||||
mem = BIO_new_mem_buf((void *) sInput.data(), sInput.size());
|
||||
BIO_push(b64, mem);
|
||||
|
||||
// Prepare buffer to receive decoded data
|
||||
if(sInput.size() % 4 != 0) {
|
||||
throw std::runtime_error("Input length should be a multiple of 4");
|
||||
}
|
||||
size_t nMaxLen = sInput.size() / 4 * 3; // upper bound, guaranteed divisible by 4
|
||||
output.resize(nMaxLen);
|
||||
|
||||
// Decode the string
|
||||
size_t nLen;
|
||||
nLen = BIO_read(b64, (void *) output.data(), sInput.size());
|
||||
output.resize(nLen);
|
||||
|
||||
// Free memory
|
||||
BIO_free_all(b64);
|
||||
return output;
|
||||
}
|
||||
|
||||
// Base64 encoding with secure memory allocation
|
||||
SecureString EncodeBase64Secure(const SecureString& sInput)
|
||||
{
|
||||
// Init openssl BIO with base64 filter and memory output
|
||||
BIO *b64, *mem;
|
||||
b64 = BIO_new(BIO_f_base64());
|
||||
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); // No newlines in output
|
||||
mem = BIO_new(BIO_s_mem());
|
||||
BIO_push(b64, mem);
|
||||
|
||||
// Decode the string
|
||||
BIO_write(b64, sInput.data(), sInput.size());
|
||||
(void) BIO_flush(b64);
|
||||
|
||||
// Create output variable from buffer mem ptr
|
||||
BUF_MEM *bptr;
|
||||
BIO_get_mem_ptr(b64, &bptr);
|
||||
SecureString output(bptr->data, bptr->length);
|
||||
|
||||
// Cleanse secure data buffer from memory
|
||||
memory_cleanse((void *) bptr->data, bptr->length);
|
||||
|
||||
// Free memory
|
||||
BIO_free_all(b64);
|
||||
return output;
|
||||
}
|
||||
|
||||
CKeePassIntegrator::CKeePassIntegrator()
|
||||
:sKeyBase64(" "), sKey(" "), sUrl(" ") // Prevent LockedPageManagerBase complaints
|
||||
{
|
||||
sKeyBase64.clear(); // Prevent LockedPageManagerBase complaints
|
||||
sKey.clear(); // Prevent LockedPageManagerBase complaints
|
||||
sUrl.clear(); // Prevent LockedPageManagerBase complaints
|
||||
bIsActive = false;
|
||||
nPort = DEFAULT_KEEPASS_HTTP_PORT;
|
||||
}
|
||||
|
||||
// Initialize from application context
|
||||
void CKeePassIntegrator::init()
|
||||
{
|
||||
bIsActive = gArgs.GetBoolArg("-keepass", false);
|
||||
nPort = gArgs.GetArg("-keepassport", DEFAULT_KEEPASS_HTTP_PORT);
|
||||
sKeyBase64 = SecureString(gArgs.GetArg("-keepasskey", "").c_str());
|
||||
strKeePassId = gArgs.GetArg("-keepassid", "");
|
||||
strKeePassEntryName = gArgs.GetArg("-keepassname", "");
|
||||
// Convert key if available
|
||||
if(sKeyBase64.size() > 0)
|
||||
{
|
||||
sKey = DecodeBase64Secure(sKeyBase64);
|
||||
}
|
||||
// Construct url if available
|
||||
if(strKeePassEntryName.size() > 0)
|
||||
{
|
||||
sUrl = SecureString("http://");
|
||||
sUrl += SecureString(strKeePassEntryName.c_str());
|
||||
sUrl += SecureString("/");
|
||||
}
|
||||
}
|
||||
|
||||
void CKeePassIntegrator::CKeePassRequest::addStrParameter(const std::string& strName, const std::string& strValue)
|
||||
{
|
||||
requestObj.pushKV(strName, strValue);
|
||||
}
|
||||
|
||||
void CKeePassIntegrator::CKeePassRequest::addStrParameter(const std::string& strName, const SecureString& sValue)
|
||||
{
|
||||
std::string sCipherValue;
|
||||
|
||||
if(!EncryptAES256(sKey, sValue, strIV, sCipherValue))
|
||||
{
|
||||
throw std::runtime_error("Unable to encrypt Verifier");
|
||||
}
|
||||
|
||||
addStrParameter(strName, EncodeBase64(sCipherValue));
|
||||
}
|
||||
|
||||
std::string CKeePassIntegrator::CKeePassRequest::getJson()
|
||||
{
|
||||
return requestObj.write();
|
||||
}
|
||||
|
||||
void CKeePassIntegrator::CKeePassRequest::init()
|
||||
{
|
||||
SecureString sIVSecure = generateRandomKey(KEEPASS_CRYPTO_BLOCK_SIZE);
|
||||
strIV = std::string(sIVSecure.data(), sIVSecure.size());
|
||||
// Generate Nonce, Verifier and RequestType
|
||||
SecureString sNonceBase64Secure = EncodeBase64Secure(sIVSecure);
|
||||
addStrParameter("Nonce", std::string(sNonceBase64Secure.data(), sNonceBase64Secure.size())); // Plain
|
||||
addStrParameter("Verifier", sNonceBase64Secure); // Encoded
|
||||
addStrParameter("RequestType", strType);
|
||||
}
|
||||
|
||||
void CKeePassIntegrator::CKeePassResponse::parseResponse(const std::string& strResponse)
|
||||
{
|
||||
UniValue responseValue;
|
||||
if(!responseValue.read(strResponse))
|
||||
{
|
||||
throw std::runtime_error("Unable to parse KeePassHttp response");
|
||||
}
|
||||
|
||||
responseObj = responseValue;
|
||||
|
||||
// retrieve main values
|
||||
bSuccess = responseObj["Success"].get_bool();
|
||||
strType = getStr("RequestType");
|
||||
strIV = DecodeBase64(getStr("Nonce"));
|
||||
}
|
||||
|
||||
std::string CKeePassIntegrator::CKeePassResponse::getStr(const std::string& strName)
|
||||
{
|
||||
return responseObj[strName].get_str();
|
||||
}
|
||||
|
||||
SecureString CKeePassIntegrator::CKeePassResponse::getSecureStr(const std::string& strName)
|
||||
{
|
||||
std::string strValueBase64Encrypted(responseObj[strName].get_str());
|
||||
SecureString sValue;
|
||||
try
|
||||
{
|
||||
sValue = decrypt(strValueBase64Encrypted);
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::string strError = "Exception occurred while decrypting ";
|
||||
strError += strName + ": " + e.what();
|
||||
throw std::runtime_error(strError);
|
||||
}
|
||||
return sValue;
|
||||
}
|
||||
|
||||
SecureString CKeePassIntegrator::CKeePassResponse::decrypt(const std::string& strValueBase64Encrypted)
|
||||
{
|
||||
std::string strValueEncrypted = DecodeBase64(strValueBase64Encrypted);
|
||||
SecureString sValue;
|
||||
if(!DecryptAES256(sKey, strValueEncrypted, strIV, sValue))
|
||||
{
|
||||
throw std::runtime_error("Unable to decrypt value.");
|
||||
}
|
||||
return sValue;
|
||||
}
|
||||
|
||||
std::vector<CKeePassIntegrator::CKeePassEntry> CKeePassIntegrator::CKeePassResponse::getEntries()
|
||||
{
|
||||
|
||||
std::vector<CKeePassEntry> vEntries;
|
||||
|
||||
UniValue aEntries = responseObj["Entries"].get_array();
|
||||
for(size_t i = 0; i < aEntries.size(); i++)
|
||||
{
|
||||
SecureString sEntryUuid(decrypt(aEntries[i]["Uuid"].get_str().c_str()));
|
||||
SecureString sEntryName(decrypt(aEntries[i]["Name"].get_str().c_str()));
|
||||
SecureString sEntryLogin(decrypt(aEntries[i]["Login"].get_str().c_str()));
|
||||
SecureString sEntryPassword(decrypt(aEntries[i]["Password"].get_str().c_str()));
|
||||
CKeePassEntry entry(sEntryUuid, sEntryName, sEntryLogin, sEntryPassword);
|
||||
vEntries.push_back(entry);
|
||||
}
|
||||
|
||||
return vEntries;
|
||||
|
||||
}
|
||||
|
||||
SecureString CKeePassIntegrator::generateRandomKey(size_t nSize)
|
||||
{
|
||||
// Generates random key
|
||||
SecureString sKey;
|
||||
sKey.resize(nSize);
|
||||
|
||||
GetStrongRandBytes((unsigned char *) sKey.data(), nSize);
|
||||
|
||||
return sKey;
|
||||
}
|
||||
|
||||
// Construct POST body for RPC JSON call
|
||||
std::string CKeePassIntegrator::constructHTTPPost(const std::string& strMsg, const std::map<std::string,std::string>& mapRequestHeaders)
|
||||
{
|
||||
std::ostringstream streamOut;
|
||||
streamOut << "POST / HTTP/1.1\r\n"
|
||||
<< "User-Agent: dash-json-rpc/" << FormatFullVersion() << "\r\n"
|
||||
<< "Host: localhost\r\n"
|
||||
<< "Content-Type: application/json\r\n"
|
||||
<< "Content-Length: " << strMsg.size() << "\r\n"
|
||||
<< "Connection: close\r\n"
|
||||
<< "Accept: application/json\r\n";
|
||||
for (const auto& item : mapRequestHeaders)
|
||||
streamOut << item.first << ": " << item.second << "\r\n";
|
||||
streamOut << "\r\n" << strMsg;
|
||||
|
||||
return streamOut.str();
|
||||
}
|
||||
|
||||
/** Reply structure for request_done to fill in */
|
||||
struct HTTPReply
|
||||
{
|
||||
int nStatus;
|
||||
std::string strBody;
|
||||
};
|
||||
|
||||
static void http_request_done(struct evhttp_request *req, void *ctx)
|
||||
{
|
||||
HTTPReply *reply = static_cast<HTTPReply*>(ctx);
|
||||
|
||||
if (req == nullptr) {
|
||||
/* If req is nullptr, it means an error occurred while connecting, but
|
||||
* I'm not sure how to find out which one. We also don't really care.
|
||||
*/
|
||||
reply->nStatus = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
reply->nStatus = evhttp_request_get_response_code(req);
|
||||
|
||||
struct evbuffer *buf = evhttp_request_get_input_buffer(req);
|
||||
if (buf)
|
||||
{
|
||||
size_t size = evbuffer_get_length(buf);
|
||||
const char *data = (const char*)evbuffer_pullup(buf, size);
|
||||
if (data)
|
||||
reply->strBody = std::string(data, size);
|
||||
evbuffer_drain(buf, size);
|
||||
}
|
||||
}
|
||||
|
||||
// Send RPC message to KeePassHttp
|
||||
void CKeePassIntegrator::doHTTPPost(const std::string& sRequest, int& nStatusRet, std::string& strResponseRet)
|
||||
{
|
||||
// Create event base
|
||||
struct event_base *base = event_base_new(); // TODO RAII
|
||||
if (!base)
|
||||
throw std::runtime_error("cannot create event_base");
|
||||
|
||||
// Synchronously look up hostname
|
||||
struct evhttp_connection *evcon = evhttp_connection_base_new(base, nullptr, KEEPASS_HTTP_HOST, DEFAULT_KEEPASS_HTTP_PORT); // TODO RAII
|
||||
if (evcon == nullptr)
|
||||
throw std::runtime_error("create connection failed");
|
||||
evhttp_connection_set_timeout(evcon, KEEPASS_HTTP_CONNECT_TIMEOUT);
|
||||
|
||||
HTTPReply response;
|
||||
struct evhttp_request *req = evhttp_request_new(http_request_done, (void*)&response); // TODO RAII
|
||||
if (req == nullptr)
|
||||
throw std::runtime_error("create http request failed");
|
||||
|
||||
struct evkeyvalq *output_headers = evhttp_request_get_output_headers(req);
|
||||
assert(output_headers);
|
||||
evhttp_add_header(output_headers, "User-Agent", ("dash-json-rpc/" + FormatFullVersion()).c_str());
|
||||
evhttp_add_header(output_headers, "Host", KEEPASS_HTTP_HOST);
|
||||
evhttp_add_header(output_headers, "Accept", "application/json");
|
||||
evhttp_add_header(output_headers, "Content-Type", "application/json");
|
||||
evhttp_add_header(output_headers, "Connection", "close");
|
||||
|
||||
LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::doHTTPPost -- send POST data\n");
|
||||
|
||||
struct evbuffer * output_buffer = evhttp_request_get_output_buffer(req);
|
||||
assert(output_buffer);
|
||||
evbuffer_add(output_buffer, sRequest.data(), sRequest.size());
|
||||
|
||||
int r = evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/");
|
||||
if (r != 0) {
|
||||
evhttp_connection_free(evcon);
|
||||
event_base_free(base);
|
||||
throw std::runtime_error("send http request failed");
|
||||
}
|
||||
|
||||
event_base_dispatch(base);
|
||||
evhttp_connection_free(evcon);
|
||||
event_base_free(base);
|
||||
|
||||
nStatusRet = response.nStatus;
|
||||
if (response.nStatus == 0)
|
||||
throw std::runtime_error("couldn't connect to server");
|
||||
else if (response.nStatus >= 400 && response.nStatus != HTTP_BAD_REQUEST && response.nStatus != HTTP_NOT_FOUND && response.nStatus != HTTP_INTERNAL_SERVER_ERROR)
|
||||
throw std::runtime_error(strprintf("server returned HTTP error %d", response.nStatus));
|
||||
else if (response.strBody.empty())
|
||||
throw std::runtime_error("no response from server");
|
||||
|
||||
// Parse reply
|
||||
UniValue valReply(UniValue::VSTR);
|
||||
if (!valReply.read(response.strBody))
|
||||
throw std::runtime_error("couldn't parse reply from server");
|
||||
const UniValue& reply = valReply.get_obj();
|
||||
if (reply.empty())
|
||||
throw std::runtime_error("expected reply to have result, error and id properties");
|
||||
|
||||
strResponseRet = valReply.get_str();
|
||||
}
|
||||
|
||||
void CKeePassIntegrator::rpcTestAssociation(bool bTriggerUnlock)
|
||||
{
|
||||
CKeePassRequest request(sKey, "test-associate");
|
||||
request.addStrParameter("TriggerUnlock", std::string(bTriggerUnlock ? "true" : "false"));
|
||||
|
||||
int nStatus;
|
||||
std::string strResponse;
|
||||
|
||||
doHTTPPost(request.getJson(), nStatus, strResponse);
|
||||
|
||||
LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcTestAssociation -- send result: status: %d response: %s\n", nStatus, strResponse);
|
||||
}
|
||||
|
||||
std::vector<CKeePassIntegrator::CKeePassEntry> CKeePassIntegrator::rpcGetLogins()
|
||||
{
|
||||
|
||||
// Convert key format
|
||||
SecureString sKey = DecodeBase64Secure(sKeyBase64);
|
||||
|
||||
CKeePassRequest request(sKey, "get-logins");
|
||||
request.addStrParameter("addStrParameter", std::string("true"));
|
||||
request.addStrParameter("TriggerUnlock", std::string("true"));
|
||||
request.addStrParameter("Id", strKeePassId);
|
||||
request.addStrParameter("Url", sUrl);
|
||||
|
||||
int nStatus;
|
||||
std::string strResponse;
|
||||
|
||||
doHTTPPost(request.getJson(), nStatus, strResponse);
|
||||
|
||||
LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcGetLogins -- send result: status: %d\n", nStatus);
|
||||
|
||||
if(nStatus != 200)
|
||||
{
|
||||
std::string strError = "Error returned by KeePassHttp: HTTP code ";
|
||||
strError += itostr(nStatus);
|
||||
strError += " - Response: ";
|
||||
strError += " response: [";
|
||||
strError += strResponse;
|
||||
strError += "]";
|
||||
throw std::runtime_error(strError);
|
||||
}
|
||||
|
||||
// Parse the response
|
||||
CKeePassResponse response(sKey, strResponse);
|
||||
|
||||
if(!response.getSuccess())
|
||||
{
|
||||
std::string strError = "KeePassHttp returned failure status";
|
||||
throw std::runtime_error(strError);
|
||||
}
|
||||
|
||||
return response.getEntries();
|
||||
}
|
||||
|
||||
void CKeePassIntegrator::rpcSetLogin(const SecureString& sWalletPass, const SecureString& sEntryId)
|
||||
{
|
||||
|
||||
// Convert key format
|
||||
SecureString sKey = DecodeBase64Secure(sKeyBase64);
|
||||
|
||||
CKeePassRequest request(sKey, "set-login");
|
||||
request.addStrParameter("Id", strKeePassId);
|
||||
request.addStrParameter("Url", sUrl);
|
||||
|
||||
LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcSetLogin -- send Url: %s\n", sUrl);
|
||||
|
||||
//request.addStrParameter("SubmitUrl", sSubmitUrl); // Is used to construct the entry title
|
||||
request.addStrParameter("Login", SecureString("dash"));
|
||||
request.addStrParameter("Password", sWalletPass);
|
||||
if(sEntryId.size() != 0)
|
||||
{
|
||||
request.addStrParameter("Uuid", sEntryId); // Update existing
|
||||
}
|
||||
|
||||
int nStatus;
|
||||
std::string strResponse;
|
||||
|
||||
doHTTPPost(request.getJson(), nStatus, strResponse);
|
||||
|
||||
|
||||
LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcSetLogin -- send result: status: %d response: %s\n", nStatus, strResponse);
|
||||
|
||||
if(nStatus != 200)
|
||||
{
|
||||
std::string strError = "Error returned: HTTP code ";
|
||||
strError += itostr(nStatus);
|
||||
strError += " - Response: ";
|
||||
strError += " response: [";
|
||||
strError += strResponse;
|
||||
strError += "]";
|
||||
throw std::runtime_error(strError);
|
||||
}
|
||||
|
||||
// Parse the response
|
||||
CKeePassResponse response(sKey, strResponse);
|
||||
|
||||
if(!response.getSuccess())
|
||||
{
|
||||
throw std::runtime_error("KeePassHttp returned failure status");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SecureString CKeePassIntegrator::generateKeePassKey()
|
||||
{
|
||||
SecureString sKey = generateRandomKey(KEEPASS_CRYPTO_KEY_SIZE);
|
||||
SecureString sKeyBase64 = EncodeBase64Secure(sKey);
|
||||
return sKeyBase64;
|
||||
}
|
||||
|
||||
void CKeePassIntegrator::rpcAssociate(std::string& strIdRet, SecureString& sKeyBase64Ret)
|
||||
{
|
||||
sKey = generateRandomKey(KEEPASS_CRYPTO_KEY_SIZE);
|
||||
CKeePassRequest request(sKey, "associate");
|
||||
|
||||
sKeyBase64Ret = EncodeBase64Secure(sKey);
|
||||
request.addStrParameter("Key", std::string(sKeyBase64Ret.data(), sKeyBase64Ret.size()));
|
||||
|
||||
int nStatus;
|
||||
std::string strResponse;
|
||||
|
||||
doHTTPPost(request.getJson(), nStatus, strResponse);
|
||||
|
||||
LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcAssociate -- send result: status: %d response: %s\n", nStatus, strResponse);
|
||||
|
||||
if(nStatus != 200)
|
||||
{
|
||||
std::string strError = "Error returned: HTTP code ";
|
||||
strError += itostr(nStatus);
|
||||
strError += " - Response: ";
|
||||
strError += " response: [";
|
||||
strError += strResponse;
|
||||
strError += "]";
|
||||
throw std::runtime_error(strError);
|
||||
}
|
||||
|
||||
// Parse the response
|
||||
CKeePassResponse response(sKey, strResponse);
|
||||
|
||||
if(!response.getSuccess())
|
||||
{
|
||||
throw std::runtime_error("KeePassHttp returned failure status");
|
||||
}
|
||||
|
||||
// If we got here, we were successful. Return the information
|
||||
strIdRet = response.getStr("Id");
|
||||
}
|
||||
|
||||
// Retrieve wallet passphrase from KeePass
|
||||
SecureString CKeePassIntegrator::retrievePassphrase()
|
||||
{
|
||||
|
||||
// Check we have all required information
|
||||
if(sKey.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("keepasskey parameter is not defined. Please specify the configuration parameter.");
|
||||
}
|
||||
if(strKeePassId.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("keepassid parameter is not defined. Please specify the configuration parameter.");
|
||||
}
|
||||
if(strKeePassEntryName == "")
|
||||
{
|
||||
throw std::runtime_error("keepassname parameter is not defined. Please specify the configuration parameter.");
|
||||
}
|
||||
|
||||
// Retrieve matching logins from KeePass
|
||||
std::vector<CKeePassIntegrator::CKeePassEntry> vecEntries = rpcGetLogins();
|
||||
|
||||
// Only accept one unique match
|
||||
if(vecEntries.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("KeePassHttp returned 0 matches, please verify the keepassurl setting.");
|
||||
}
|
||||
if(vecEntries.size() > 1)
|
||||
{
|
||||
throw std::runtime_error("KeePassHttp returned multiple matches, bailing out.");
|
||||
}
|
||||
|
||||
return vecEntries[0].getPassword();
|
||||
}
|
||||
|
||||
// Update wallet passphrase in keepass
|
||||
void CKeePassIntegrator::updatePassphrase(const SecureString& sWalletPassphrase)
|
||||
{
|
||||
// Check we have all required information
|
||||
if(sKey.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("keepasskey parameter is not defined. Please specify the configuration parameter.");
|
||||
}
|
||||
if(strKeePassId.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("keepassid parameter is not defined. Please specify the configuration parameter.");
|
||||
}
|
||||
if(strKeePassEntryName == "")
|
||||
{
|
||||
throw std::runtime_error("keepassname parameter is not defined. Please specify the configuration parameter.");
|
||||
}
|
||||
|
||||
SecureString sEntryId("");
|
||||
|
||||
std::string strError;
|
||||
|
||||
// Lookup existing entry
|
||||
std::vector<CKeePassIntegrator::CKeePassEntry> vecEntries = rpcGetLogins();
|
||||
|
||||
if(vecEntries.size() > 1)
|
||||
{
|
||||
throw std::runtime_error("KeePassHttp returned multiple matches, bailing out.");
|
||||
}
|
||||
|
||||
if(vecEntries.size() == 1)
|
||||
{
|
||||
sEntryId = vecEntries[0].getUuid();
|
||||
}
|
||||
|
||||
// Update wallet passphrase in KeePass
|
||||
rpcSetLogin(sWalletPassphrase, sEntryId);
|
||||
}
|
133
src/keepass.h
133
src/keepass.h
@ -1,133 +0,0 @@
|
||||
// Copyright (c) 2014-2020 The Dash Core developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_KEEPASS_H
|
||||
#define BITCOIN_KEEPASS_H
|
||||
|
||||
#include <support/allocators/secure.h>
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
class CKeePassIntegrator;
|
||||
|
||||
static const unsigned int DEFAULT_KEEPASS_HTTP_PORT = 19455;
|
||||
|
||||
extern CKeePassIntegrator keePassInt;
|
||||
|
||||
class CKeePassIntegrator {
|
||||
private:
|
||||
static const int KEEPASS_CRYPTO_KEY_SIZE = 32;
|
||||
static const int KEEPASS_CRYPTO_BLOCK_SIZE = 16;
|
||||
static const int KEEPASS_HTTP_CONNECT_TIMEOUT = 30;
|
||||
static const char* KEEPASS_HTTP_HOST;
|
||||
|
||||
bool bIsActive;
|
||||
unsigned int nPort;
|
||||
SecureString sKeyBase64;
|
||||
SecureString sKey;
|
||||
SecureString sUrl;
|
||||
//SecureString sSubmitUrl;
|
||||
std::string strKeePassId;
|
||||
std::string strKeePassEntryName;
|
||||
|
||||
class CKeePassRequest {
|
||||
|
||||
UniValue requestObj;
|
||||
std::string strType;
|
||||
std::string strIV;
|
||||
SecureString sKey;
|
||||
|
||||
void init();
|
||||
|
||||
public:
|
||||
void addStrParameter(const std::string& strName, const std::string& strValue); // Regular
|
||||
void addStrParameter(const std::string& strName, const SecureString& sValue); // Encrypt
|
||||
std::string getJson();
|
||||
|
||||
CKeePassRequest(const SecureString& sKey, const std::string& strType)
|
||||
{
|
||||
this->sKey = sKey;
|
||||
this->strType = strType;
|
||||
init();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
class CKeePassEntry {
|
||||
|
||||
SecureString sUuid;
|
||||
SecureString sName;
|
||||
SecureString sLogin;
|
||||
SecureString sPassword;
|
||||
|
||||
public:
|
||||
CKeePassEntry(const SecureString& sUuid, const SecureString& sName, const SecureString& sLogin, const SecureString& sPassword) :
|
||||
sUuid(sUuid), sName(sName), sLogin(sLogin), sPassword(sPassword) {
|
||||
}
|
||||
|
||||
SecureString getUuid() {
|
||||
return sUuid;
|
||||
}
|
||||
|
||||
SecureString getName() {
|
||||
return sName;
|
||||
}
|
||||
|
||||
SecureString getLogin() {
|
||||
return sLogin;
|
||||
}
|
||||
|
||||
SecureString getPassword() {
|
||||
return sPassword;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class CKeePassResponse {
|
||||
|
||||
bool bSuccess;
|
||||
std::string strType;
|
||||
std::string strIV;
|
||||
SecureString sKey;
|
||||
|
||||
void parseResponse(const std::string& strResponse);
|
||||
|
||||
public:
|
||||
UniValue responseObj;
|
||||
CKeePassResponse(const SecureString& sKey, const std::string& strResponse) {
|
||||
this->sKey = sKey;
|
||||
parseResponse(strResponse);
|
||||
}
|
||||
|
||||
bool getSuccess() {
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
SecureString getSecureStr(const std::string& strName);
|
||||
std::string getStr(const std::string& strName);
|
||||
std::vector<CKeePassEntry> getEntries();
|
||||
|
||||
SecureString decrypt(const std::string& strValue); // DecodeBase64 and decrypt arbitrary string value
|
||||
|
||||
};
|
||||
|
||||
static SecureString generateRandomKey(size_t nSize);
|
||||
static std::string constructHTTPPost(const std::string& strMsg, const std::map<std::string,std::string>& mapRequestHeaders);
|
||||
void doHTTPPost(const std::string& strRequest, int& nStatusRet, std::string& strResponseRet);
|
||||
void rpcTestAssociation(bool bTriggerUnlock);
|
||||
std::vector<CKeePassEntry> rpcGetLogins();
|
||||
void rpcSetLogin(const SecureString& sWalletPass, const SecureString& sEntryId);
|
||||
|
||||
public:
|
||||
CKeePassIntegrator();
|
||||
void init();
|
||||
static SecureString generateKeePassKey();
|
||||
void rpcAssociate(std::string& strIdRet, SecureString& sKeyBase64Ret);
|
||||
SecureString retrievePassphrase();
|
||||
void updatePassphrase(const SecureString& sWalletPassphrase);
|
||||
|
||||
};
|
||||
|
||||
#endif // BITCOIN_KEEPASS_H
|
@ -164,7 +164,6 @@ const CLogCategoryDesc LogCategories[] =
|
||||
{BCLog::CHAINLOCKS, "chainlocks"},
|
||||
{BCLog::GOBJECT, "gobject"},
|
||||
{BCLog::INSTANTSEND, "instantsend"},
|
||||
{BCLog::KEEPASS, "keepass"},
|
||||
{BCLog::LLMQ, "llmq"},
|
||||
{BCLog::LLMQ_DKG, "llmq-dkg"},
|
||||
{BCLog::LLMQ_SIGS, "llmq-sigs"},
|
||||
|
@ -61,7 +61,6 @@ namespace BCLog {
|
||||
CHAINLOCKS = ((uint64_t)1 << 32),
|
||||
GOBJECT = ((uint64_t)1 << 33),
|
||||
INSTANTSEND = ((uint64_t)1 << 34),
|
||||
KEEPASS = ((uint64_t)1 << 35),
|
||||
LLMQ = ((uint64_t)1 << 36),
|
||||
LLMQ_DKG = ((uint64_t)1 << 37),
|
||||
LLMQ_SIGS = ((uint64_t)1 << 38),
|
||||
@ -71,7 +70,7 @@ namespace BCLog {
|
||||
SPORK = ((uint64_t)1 << 42),
|
||||
NETCONN = ((uint64_t)1 << 43),
|
||||
|
||||
DASH = CHAINLOCKS | GOBJECT | INSTANTSEND | KEEPASS | LLMQ | LLMQ_DKG
|
||||
DASH = CHAINLOCKS | GOBJECT | INSTANTSEND | LLMQ | LLMQ_DKG
|
||||
| LLMQ_SIGS | MNPAYMENTS | MNSYNC | COINJOIN | SPORK | NETCONN,
|
||||
|
||||
NET_NETCONN = NET | NETCONN, // use this to have something logged in NET and NETCONN as well
|
||||
|
@ -647,9 +647,6 @@ std::string ArgsManager::GetHelpMessage() const
|
||||
case OptionsCategory::WALLET_HD:
|
||||
usage += HelpMessageGroup("HD wallet options:");
|
||||
break;
|
||||
case OptionsCategory::WALLET_KEEPASS:
|
||||
usage += HelpMessageGroup("KeePass options:");
|
||||
break;
|
||||
case OptionsCategory::WALLET_COINJOIN:
|
||||
usage += HelpMessageGroup("CoinJoin options:");
|
||||
break;
|
||||
|
@ -140,7 +140,6 @@ enum class OptionsCategory {
|
||||
WALLET,
|
||||
WALLET_FEE,
|
||||
WALLET_HD,
|
||||
WALLET_KEEPASS,
|
||||
WALLET_COINJOIN,
|
||||
WALLET_DEBUG_TEST,
|
||||
ZMQ,
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
#include <init.h>
|
||||
#include <interfaces/chain.h>
|
||||
#include <keepass.h>
|
||||
#include <net.h>
|
||||
#include <scheduler.h>
|
||||
#include <util/error.h>
|
||||
@ -36,7 +35,6 @@ public:
|
||||
// Dash Specific Wallet Init
|
||||
void AutoLockMasternodeCollaterals() const override;
|
||||
void InitCoinJoinSettings() const override;
|
||||
void InitKeePass() const override;
|
||||
bool InitAutoBackup() const override;
|
||||
};
|
||||
|
||||
@ -80,12 +78,6 @@ void WalletInit::AddWalletOptions() const
|
||||
gArgs.AddArg("-mnemonicpassphrase=<text>", "User defined mnemonic passphrase for HD wallet (BIP39). Only has effect during wallet creation/first start (default: empty string)", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET_HD);
|
||||
gArgs.AddArg("-usehd", strprintf("Use hierarchical deterministic key generation (HD) after BIP39/BIP44. Only has effect during wallet creation/first start (default: %u)", DEFAULT_USE_HD_WALLET), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET_HD);
|
||||
|
||||
gArgs.AddArg("-keepass", strprintf("Use KeePass 2 integration using KeePassHttp plugin (default: %u)", 0), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET_KEEPASS);
|
||||
gArgs.AddArg("-keepassid=<id>", "KeePassHttp id for the established association", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET_KEEPASS);
|
||||
gArgs.AddArg("-keepasskey=<key>", "KeePassHttp key for AES encrypted communication with KeePass", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET_KEEPASS);
|
||||
gArgs.AddArg("-keepassname=<name>", "Name to construct url for KeePass entry that stores the wallet passphrase", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET_KEEPASS);
|
||||
gArgs.AddArg("-keepassport=<port>", strprintf("Connect to KeePassHttp on port <port> (default: %u)", DEFAULT_KEEPASS_HTTP_PORT), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET_KEEPASS);
|
||||
|
||||
gArgs.AddArg("-enablecoinjoin", strprintf("Enable use of CoinJoin for funds stored in this wallet (0-1, default: %u)", 0), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET_COINJOIN);
|
||||
gArgs.AddArg("-coinjoinamount=<n>", strprintf("Target CoinJoin balance (%u-%u, default: %u)", MIN_COINJOIN_AMOUNT, MAX_COINJOIN_AMOUNT, DEFAULT_COINJOIN_AMOUNT), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET_COINJOIN);
|
||||
gArgs.AddArg("-coinjoinautostart", strprintf("Start CoinJoin automatically (0-1, default: %u)", DEFAULT_COINJOIN_AUTOSTART), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET_COINJOIN);
|
||||
@ -291,11 +283,6 @@ void WalletInit::InitCoinJoinSettings() const
|
||||
CCoinJoinClientOptions::GetDenomsHardCap());
|
||||
}
|
||||
|
||||
void WalletInit::InitKeePass() const
|
||||
{
|
||||
keePassInt.init();
|
||||
}
|
||||
|
||||
bool WalletInit::InitAutoBackup() const
|
||||
{
|
||||
return CWallet::InitAutoBackup();
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include <httpserver.h>
|
||||
#include <init.h>
|
||||
#include <interfaces/chain.h>
|
||||
#include <keepass.h>
|
||||
#include <policy/feerate.h>
|
||||
#include <policy/fees.h>
|
||||
#include <rpc/mining.h>
|
||||
@ -2819,61 +2818,6 @@ static UniValue upgradetohd(const JSONRPCRequest& request)
|
||||
return true;
|
||||
}
|
||||
|
||||
static UniValue keepass(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
std::string strCommand;
|
||||
|
||||
if (!request.params[0].isNull())
|
||||
strCommand = request.params[0].get_str();
|
||||
|
||||
if (request.fHelp ||
|
||||
(strCommand != "genkey" && strCommand != "init" && strCommand != "setpassphrase"))
|
||||
throw std::runtime_error(
|
||||
"keepass <genkey|init|setpassphrase>\n");
|
||||
|
||||
if (strCommand == "genkey")
|
||||
{
|
||||
SecureString sResult;
|
||||
// Generate RSA key
|
||||
SecureString sKey = CKeePassIntegrator::generateKeePassKey();
|
||||
sResult = "Generated Key: ";
|
||||
sResult += sKey;
|
||||
return sResult.c_str();
|
||||
}
|
||||
else if(strCommand == "init")
|
||||
{
|
||||
// Generate base64 encoded 256 bit RSA key and associate with KeePassHttp
|
||||
SecureString sResult;
|
||||
SecureString sKey;
|
||||
std::string strId;
|
||||
keePassInt.rpcAssociate(strId, sKey);
|
||||
sResult = "Association successful. Id: ";
|
||||
sResult += strId.c_str();
|
||||
sResult += " - Key: ";
|
||||
sResult += sKey.c_str();
|
||||
return sResult.c_str();
|
||||
}
|
||||
else if(strCommand == "setpassphrase")
|
||||
{
|
||||
if(request.params.size() != 2) {
|
||||
return "setlogin: invalid number of parameters. Requires a passphrase";
|
||||
}
|
||||
|
||||
SecureString sPassphrase = SecureString(request.params[1].get_str().c_str());
|
||||
|
||||
keePassInt.updatePassphrase(sPassphrase);
|
||||
|
||||
return "setlogin: Updated credentials.";
|
||||
}
|
||||
|
||||
return "Invalid command";
|
||||
}
|
||||
|
||||
static UniValue loadwallet(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 1)
|
||||
@ -4247,7 +4191,6 @@ static const CRPCCommand commands[] =
|
||||
{ "wallet", "importprunedfunds", &importprunedfunds, {"rawtransaction","txoutproof"} },
|
||||
{ "wallet", "importpubkey", &importpubkey, {"pubkey","label","rescan"} },
|
||||
{ "wallet", "importwallet", &importwallet, {"filename"} },
|
||||
{ "wallet", "keepass", &keepass, {} },
|
||||
{ "wallet", "keypoolrefill", &keypoolrefill, {"newsize"} },
|
||||
{ "wallet", "listaddressbalances", &listaddressbalances, {"minamount"} },
|
||||
{ "wallet", "listaddressgroupings", &listaddressgroupings, {} },
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include <coinjoin/options.h>
|
||||
#include <governance/governance.h>
|
||||
#include <evo/deterministicmns.h>
|
||||
#include <keepass.h>
|
||||
|
||||
#include <evo/providertx.h>
|
||||
|
||||
@ -599,23 +598,9 @@ bool CWallet::LoadWatchOnly(const CScript &dest)
|
||||
|
||||
bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool fForMixingOnly, bool accept_no_keys)
|
||||
{
|
||||
SecureString strWalletPassphraseFinal;
|
||||
|
||||
if (!IsLocked()) // was already fully unlocked, not only for mixing
|
||||
return true;
|
||||
|
||||
// Verify KeePassIntegration
|
||||
if (strWalletPassphrase == "keepass" && gArgs.GetBoolArg("-keepass", false)) {
|
||||
try {
|
||||
strWalletPassphraseFinal = keePassInt.retrievePassphrase();
|
||||
} catch (std::exception& e) {
|
||||
WalletLogPrintf("CWallet::Unlock could not retrieve passphrase from KeePass: Error: %s\n", e.what());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
strWalletPassphraseFinal = strWalletPassphrase;
|
||||
}
|
||||
|
||||
CCrypter crypter;
|
||||
CKeyingMaterial _vMasterKey;
|
||||
|
||||
@ -623,7 +608,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool fForMixingOnl
|
||||
LOCK(cs_wallet);
|
||||
for (const MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
|
||||
{
|
||||
if (!crypter.SetKeyFromPassphrase(strWalletPassphraseFinal, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
||||
if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
||||
return false;
|
||||
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
|
||||
continue; // try another master key
|
||||
@ -643,22 +628,6 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool fForMixingOnl
|
||||
bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
|
||||
{
|
||||
bool fWasLocked = IsLocked(true);
|
||||
bool bUseKeePass = false;
|
||||
|
||||
SecureString strOldWalletPassphraseFinal;
|
||||
|
||||
// Verify KeePassIntegration
|
||||
if(strOldWalletPassphrase == "keepass" && gArgs.GetBoolArg("-keepass", false)) {
|
||||
bUseKeePass = true;
|
||||
try {
|
||||
strOldWalletPassphraseFinal = keePassInt.retrievePassphrase();
|
||||
} catch (std::exception& e) {
|
||||
WalletLogPrintf("CWallet::ChangeWalletPassphrase -- could not retrieve passphrase from KeePass: Error: %s\n", e.what());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
strOldWalletPassphraseFinal = strOldWalletPassphrase;
|
||||
}
|
||||
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
@ -668,7 +637,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
|
||||
CKeyingMaterial _vMasterKey;
|
||||
for (MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
|
||||
{
|
||||
if(!crypter.SetKeyFromPassphrase(strOldWalletPassphraseFinal, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
||||
if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
||||
return false;
|
||||
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
|
||||
return false;
|
||||
@ -695,17 +664,6 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
|
||||
if (fWasLocked)
|
||||
Lock();
|
||||
|
||||
// Update KeePass if necessary
|
||||
if(bUseKeePass) {
|
||||
WalletLogPrintf("CWallet::ChangeWalletPassphrase -- Updating KeePass with new passphrase\n");
|
||||
try {
|
||||
keePassInt.updatePassphrase(strNewWalletPassphrase);
|
||||
} catch (std::exception& e) {
|
||||
WalletLogPrintf("CWallet::ChangeWalletPassphrase -- could not update passphrase in KeePass: Error: %s\n", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -980,16 +938,6 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
|
||||
// bits of the unencrypted private key in slack space in the database file.
|
||||
database->Rewrite();
|
||||
|
||||
// Update KeePass if necessary
|
||||
if(gArgs.GetBoolArg("-keepass", false)) {
|
||||
WalletLogPrintf("CWallet::EncryptWallet -- Updating KeePass with new passphrase\n");
|
||||
try {
|
||||
keePassInt.updatePassphrase(strWalletPassphrase);
|
||||
} catch (std::exception& e) {
|
||||
WalletLogPrintf("CWallet::EncryptWallet -- could not update passphrase in KeePass: Error: %s\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
// BDB seems to have a bad habit of writing old data into
|
||||
// slack space in .dat files; that is bad if the old data is
|
||||
// unencrypted private keys. So:
|
||||
|
@ -21,7 +21,6 @@ public:
|
||||
// Dash Specific WalletInitInterface
|
||||
virtual void AutoLockMasternodeCollaterals() const = 0;
|
||||
virtual void InitCoinJoinSettings() const = 0;
|
||||
virtual void InitKeePass() const = 0;
|
||||
virtual bool InitAutoBackup() const = 0;
|
||||
|
||||
virtual ~WalletInitInterface() {}
|
||||
|
Loading…
Reference in New Issue
Block a user