mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-02-08 05:04:24 +00:00
![Andrew Chow](/assets/img/avatar_default.png)
Removes vchDefaultKey which was only used for first run detection. Improves wallet first run detection by checking to see if any keys were read from the database. This will now also check for a valid defaultkey for backwards compatibility reasons and to check for any corruption. Keys will stil be generated on the first one, but there won't be any shown in the address book as was previously done.
197 lines
5.9 KiB
C++
197 lines
5.9 KiB
C++
// Copyright (c) 2009-2016 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#ifndef BITCOIN_WALLET_CRYPTER_H
|
|
#define BITCOIN_WALLET_CRYPTER_H
|
|
|
|
#include "keystore.h"
|
|
#include "serialize.h"
|
|
#include "support/allocators/secure.h"
|
|
|
|
const unsigned int WALLET_CRYPTO_KEY_SIZE = 32;
|
|
const unsigned int WALLET_CRYPTO_SALT_SIZE = 8;
|
|
const unsigned int WALLET_CRYPTO_IV_SIZE = 16;
|
|
|
|
/**
|
|
* Private key encryption is done based on a CMasterKey,
|
|
* which holds a salt and random encryption key.
|
|
*
|
|
* CMasterKeys are encrypted using AES-256-CBC using a key
|
|
* derived using derivation method nDerivationMethod
|
|
* (0 == EVP_sha512()) and derivation iterations nDeriveIterations.
|
|
* vchOtherDerivationParameters is provided for alternative algorithms
|
|
* which may require more parameters (such as scrypt).
|
|
*
|
|
* Wallet Private Keys are then encrypted using AES-256-CBC
|
|
* with the double-sha256 of the public key as the IV, and the
|
|
* master key's key as the encryption key (see keystore.[ch]).
|
|
*/
|
|
|
|
/** Master key for wallet encryption */
|
|
class CMasterKey
|
|
{
|
|
public:
|
|
std::vector<unsigned char> vchCryptedKey;
|
|
std::vector<unsigned char> vchSalt;
|
|
//! 0 = EVP_sha512()
|
|
//! 1 = scrypt()
|
|
unsigned int nDerivationMethod;
|
|
unsigned int nDeriveIterations;
|
|
//! Use this for more parameters to key derivation,
|
|
//! such as the various parameters to scrypt
|
|
std::vector<unsigned char> vchOtherDerivationParameters;
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
template <typename Stream, typename Operation>
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
READWRITE(vchCryptedKey);
|
|
READWRITE(vchSalt);
|
|
READWRITE(nDerivationMethod);
|
|
READWRITE(nDeriveIterations);
|
|
READWRITE(vchOtherDerivationParameters);
|
|
}
|
|
|
|
CMasterKey()
|
|
{
|
|
// 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M
|
|
// ie slightly lower than the lowest hardware we need bother supporting
|
|
nDeriveIterations = 25000;
|
|
nDerivationMethod = 0;
|
|
vchOtherDerivationParameters = std::vector<unsigned char>(0);
|
|
}
|
|
};
|
|
|
|
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
|
|
|
|
namespace wallet_crypto
|
|
{
|
|
class TestCrypter;
|
|
}
|
|
|
|
/** Encryption/decryption context with key information */
|
|
class CCrypter
|
|
{
|
|
friend class wallet_crypto::TestCrypter; // for test access to chKey/chIV
|
|
private:
|
|
std::vector<unsigned char, secure_allocator<unsigned char>> vchKey;
|
|
std::vector<unsigned char, secure_allocator<unsigned char>> vchIV;
|
|
bool fKeySet;
|
|
|
|
int BytesToKeySHA512AES(const std::vector<unsigned char>& chSalt, const SecureString& strKeyData, int count, unsigned char *key,unsigned char *iv) const;
|
|
|
|
public:
|
|
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod);
|
|
bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext) const;
|
|
bool Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext) const;
|
|
bool SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV);
|
|
|
|
void CleanKey()
|
|
{
|
|
memory_cleanse(vchKey.data(), vchKey.size());
|
|
memory_cleanse(vchIV.data(), vchIV.size());
|
|
fKeySet = false;
|
|
}
|
|
|
|
CCrypter()
|
|
{
|
|
fKeySet = false;
|
|
vchKey.resize(WALLET_CRYPTO_KEY_SIZE);
|
|
vchIV.resize(WALLET_CRYPTO_IV_SIZE);
|
|
}
|
|
|
|
~CCrypter()
|
|
{
|
|
CleanKey();
|
|
}
|
|
};
|
|
|
|
/** Keystore which keeps the private keys encrypted.
|
|
* It derives from the basic key store, which is used if no encryption is active.
|
|
*/
|
|
class CCryptoKeyStore : public CBasicKeyStore
|
|
{
|
|
private:
|
|
|
|
CKeyingMaterial vMasterKey;
|
|
|
|
//! if fUseCrypto is true, mapKeys must be empty
|
|
//! if fUseCrypto is false, vMasterKey must be empty
|
|
bool fUseCrypto;
|
|
|
|
//! keeps track of whether Unlock has run a thorough check before
|
|
bool fDecryptionThoroughlyChecked;
|
|
|
|
protected:
|
|
bool SetCrypted();
|
|
|
|
//! will encrypt previously unencrypted keys
|
|
bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
|
|
|
|
bool Unlock(const CKeyingMaterial& vMasterKeyIn);
|
|
CryptedKeyMap mapCryptedKeys;
|
|
|
|
public:
|
|
CCryptoKeyStore() : fUseCrypto(false), fDecryptionThoroughlyChecked(false)
|
|
{
|
|
}
|
|
|
|
bool IsCrypted() const
|
|
{
|
|
return fUseCrypto;
|
|
}
|
|
|
|
bool IsLocked() const
|
|
{
|
|
if (!IsCrypted())
|
|
return false;
|
|
bool result;
|
|
{
|
|
LOCK(cs_KeyStore);
|
|
result = vMasterKey.empty();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
bool Lock();
|
|
|
|
virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
|
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;
|
|
bool HaveKey(const CKeyID &address) const override
|
|
{
|
|
{
|
|
LOCK(cs_KeyStore);
|
|
if (!IsCrypted())
|
|
return CBasicKeyStore::HaveKey(address);
|
|
return mapCryptedKeys.count(address) > 0;
|
|
}
|
|
return false;
|
|
}
|
|
bool GetKey(const CKeyID &address, CKey& keyOut) const override;
|
|
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
|
|
void GetKeys(std::set<CKeyID> &setAddress) const override
|
|
{
|
|
if (!IsCrypted())
|
|
{
|
|
CBasicKeyStore::GetKeys(setAddress);
|
|
return;
|
|
}
|
|
setAddress.clear();
|
|
CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
|
|
while (mi != mapCryptedKeys.end())
|
|
{
|
|
setAddress.insert((*mi).first);
|
|
mi++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Wallet status (encrypted, locked) changed.
|
|
* Note: Called without locks held.
|
|
*/
|
|
boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged;
|
|
};
|
|
|
|
#endif // BITCOIN_WALLET_CRYPTER_H
|