Ethereum  PoC-8
The C++ Implementation of Ethereum
KeyManager.h
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16  */
22 #pragma once
23 
24 #include <functional>
25 #include <mutex>
26 #include <libdevcore/FileSystem.h>
27 #include <libdevcore/CommonData.h>
29 
30 #include <boost/filesystem.hpp>
31 
32 namespace dev
33 {
34 namespace eth
35 {
36 class PasswordUnknown: public Exception {};
37 
38 struct KeyInfo
39 {
40  KeyInfo() = default;
41  KeyInfo(h256 const& _passHash, std::string const& _accountName, std::string const& _passwordHint = std::string()): passHash(_passHash), accountName(_accountName), passwordHint(_passwordHint) {}
42 
46  std::string accountName;
48  std::string passwordHint;
49 };
50 
51 static h256 const UnknownPassword;
53 static auto const DontKnowThrow = [](){ throw PasswordUnknown(); return std::string(); };
54 
55 enum class SemanticPassword
56 {
57  Existing,
58  Master
59 };
60 
61 // TODO: This one is specifically for Ethereum, but we can make it generic in due course.
62 // TODO: hidden-partition style key-store.
75 {
76 public:
78 
79  KeyManager(boost::filesystem::path const& _keysFile = defaultPath(), boost::filesystem::path const& _secretsPath = SecretStore::defaultPath());
80  ~KeyManager();
81 
82  void setKeysFile(boost::filesystem::path const& _keysFile) { m_keysFile = _keysFile; }
83  boost::filesystem::path const& keysFile() const { return m_keysFile; }
84 
85  bool exists() const;
86  void create(std::string const& _pass);
87  bool load(std::string const& _pass);
88  void save(std::string const& _pass) const { write(_pass, m_keysFile); }
89 
90  void notePassword(std::string const& _pass) { m_cachedPasswords[hashPassword(_pass)] = _pass; }
91  void noteHint(std::string const& _pass, std::string const& _hint) { if (!_hint.empty()) m_passwordHint[hashPassword(_pass)] = _hint; }
92  bool haveHint(std::string const& _pass) const { auto h = hashPassword(_pass); return m_cachedPasswords.count(h) && !m_cachedPasswords.at(h).empty(); }
93 
95  Addresses accounts() const;
97  AddressHash accountsHash() const { return AddressHash() + accounts(); }
98  bool hasAccount(Address const& _address) const;
100  std::string const& accountName(Address const& _address) const;
102  std::string const& passwordHint(Address const& _address) const;
103 
105  h128 uuid(Address const& _a) const;
107  Address address(h128 const& _uuid) const;
108 
109  h128 import(Secret const& _s, std::string const& _accountName, std::string const& _pass, std::string const& _passwordHint);
110  h128 import(Secret const& _s, std::string const& _accountName) { return import(_s, _accountName, defaultPassword(), std::string()); }
111 
112  SecretStore& store() { return m_store; }
113  void importExisting(h128 const& _uuid, std::string const& _accountName, std::string const& _pass, std::string const& _passwordHint);
114  void importExisting(h128 const& _uuid, std::string const& _accountName, Address const& _addr, h256 const& _passHash = h256(), std::string const& _passwordHint = std::string());
115 
118  Secret secret(Address const& _address, std::function<std::string()> const& _pass = DontKnowThrow, bool _usePasswordCache = true) const;
121  Secret secret(h128 const& _uuid, std::function<std::string()> const& _pass = DontKnowThrow, bool _usePasswordCache = true) const;
122 
123  bool recode(Address const& _address, std::string const& _newPass, std::string const& _hint, std::function<std::string()> const& _pass = DontKnowThrow, KDF _kdf = KDF::Scrypt);
124 
125  void kill(h128 const& _id) { kill(address(_id)); }
126  void kill(Address const& _a);
127 
128  static boost::filesystem::path defaultPath() { return getDataDir("ethereum") / boost::filesystem::path("keys.info"); }
129 
131  static KeyPair presaleSecret(std::string const& _json, std::function<std::string(bool)> const& _password);
132 
134  static KeyPair newKeyPair(NewKeyType _type);
135 private:
136  std::string getPassword(h128 const& _uuid, std::function<std::string()> const& _pass = DontKnowThrow) const;
137  std::string getPassword(h256 const& _passHash, std::function<std::string()> const& _pass = DontKnowThrow) const;
138  std::string defaultPassword(std::function<std::string()> const& _pass = DontKnowThrow) const { return getPassword(m_master, _pass); }
139  h256 hashPassword(std::string const& _pass) const;
140 
142  void cachePassword(std::string const& _password) const;
143 
144  // Only use if previously loaded ok.
145  // @returns false if wasn't previously loaded ok.
146  bool write() const { return write(m_keysFile); }
147  bool write(boost::filesystem::path const& _keysFile) const;
148  void write(std::string const& _pass, boost::filesystem::path const& _keysFile) const; // TODO: all passwords should be a secure string.
149  void write(SecureFixedHash<16> const& _key, boost::filesystem::path const& _keysFile) const;
150 
151  // Ethereum keys.
152 
154  std::unordered_map<h128, Address> m_uuidLookup;
156  std::unordered_map<Address, h128> m_addrLookup;
158  std::unordered_map<Address, KeyInfo> m_keyInfo;
160  std::unordered_map<h256, std::string> m_passwordHint;
161 
162  // Passwords that we're storing. Mapping password hash -> password.
163  mutable std::unordered_map<h256, std::string> m_cachedPasswords;
164 
165  // DEPRECATED.
166  // Used to be the default password for keys in the keystore, stored in the keys file.
167  // Now the default password is based off the key of the keys file directly, so this is redundant
168  // except for the fact that people have existing keys stored with it. Leave for now until/unless
169  // we have an upgrade strategy.
170  std::string m_defaultPasswordDeprecated;
171 
172  mutable boost::filesystem::path m_keysFile;
173  mutable SecureFixedHash<16> m_keysFileKey;
174  mutable h256 m_master;
175  SecretStore m_store;
176 };
177 
178 }
179 }
void save(std::string const &_pass) const
Definition: KeyManager.h:88
Definition: Address.cpp:20
boost::filesystem::path getDataDir(std::string _prefix="ethereum")
bool exists() const
Definition: KeyManager.cpp:51
h128 uuid(Address const &_a) const
Definition: KeyManager.cpp:177
static KeyPair presaleSecret(std::string const &_json, std::function< std::string(bool)> const &_password)
Extracts the secret key from the presale wallet.
Definition: KeyManager.cpp:240
bool hasAccount(Address const &_address) const
Definition: KeyManager.cpp:281
void notePassword(std::string const &_pass)
Definition: KeyManager.h:90
void noteHint(std::string const &_pass, std::string const &_hint)
Definition: KeyManager.h:91
std::string const & passwordHint(Address const &_address) const
Definition: KeyManager.cpp:305
AddressHash accountsHash() const
Definition: KeyManager.h:97
static KeyPair newKeyPair(NewKeyType _type)
Definition: KeyManager.cpp:373
Addresses accounts() const
Definition: KeyManager.cpp:270
std::string accountName
Name of the key, or JSON key info if begins with &#39;{&#39;.
Definition: KeyManager.h:46
SemanticPassword
Definition: KeyManager.h:55
std::string const & accountName(Address const &_address) const
Definition: KeyManager.cpp:293
Base class for all exceptions.
Definition: Exceptions.h:38
bool recode(Address const &_address, std::string const &_newPass, std::string const &_hint, std::function< std::string()> const &_pass=DontKnowThrow, KDF _kdf=KDF::Scrypt)
Definition: KeyManager.cpp:62
High-level manager of password-encrypted keys for Ethereum. Usage:
Definition: KeyManager.h:74
std::string passwordHint
Hint of the password. Alternative place for storage than the hash-based lookup.
Definition: KeyManager.h:48
void create(std::string const &_pass)
Definition: KeyManager.cpp:56
void kill(h128 const &_id)
Definition: KeyManager.h:125
FixedHash< 32 > h256
Definition: FixedHash.h:354
h160s Addresses
A vector of Ethereum addresses.
Definition: Address.h:33
static boost::filesystem::path defaultPath()
Definition: KeyManager.h:128
Address address(h128 const &_uuid) const
Definition: KeyManager.cpp:185
KeyManager(boost::filesystem::path const &_keysFile=defaultPath(), boost::filesystem::path const &_secretsPath=SecretStore::defaultPath())
Definition: KeyManager.cpp:37
h256 passHash
Hash of the password or h256() / UnknownPassword if unknown.
Definition: KeyManager.h:44
void importExisting(h128 const &_uuid, std::string const &_accountName, std::string const &_pass, std::string const &_passwordHint)
bool haveHint(std::string const &_pass) const
Definition: KeyManager.h:92
bool load(std::string const &_pass)
Definition: KeyManager.cpp:74
Secret secret(Address const &_address, std::function< std::string()> const &_pass=DontKnowThrow, bool _usePasswordCache=true) const
static boost::filesystem::path defaultPath()
Definition: SecretStore.h:124
KeyInfo(h256 const &_passHash, std::string const &_accountName, std::string const &_passwordHint=std::string())
Definition: KeyManager.h:41
SecretStore & store()
Definition: KeyManager.h:112
void setKeysFile(boost::filesystem::path const &_keysFile)
Definition: KeyManager.h:82
boost::filesystem::path const & keysFile() const
Definition: KeyManager.h:83
std::unordered_set< h160 > AddressHash
A hash set of Ethereum addresses.
Definition: Address.h:36