25 #include <boost/filesystem.hpp> 34 namespace js = json_spirit;
35 namespace fs = boost::filesystem;
37 KeyManager::KeyManager(fs::path
const& _keysFile, fs::path
const& _secretsPath):
38 m_keysFile(_keysFile), m_store(_secretsPath)
40 for (
auto const&
uuid: m_store.
keys())
43 m_addrLookup[addr] =
uuid;
44 m_uuidLookup[
uuid] = addr;
59 write(_pass, m_keysFile);
69 m_keyInfo[_address].passHash = hashPassword(_newPass);
85 unsigned version = unsigned(s[0]);
88 bool saveRequired =
false;
89 for (
auto const& i: s[1])
97 m_addrLookup[addr] =
uuid;
98 m_uuidLookup[
uuid] = addr;
99 m_keyInfo[addr] =
KeyInfo(
h256(i[2]),
string(i[3]), i.itemCount() > 4 ? string(i[4]) :
"");
107 m_keyInfo[addr] =
KeyInfo(
h256(i[2]),
string(i[3]), i.itemCount() > 4 ? string(i[4]) :
"");
113 for (
auto const& i: s[2])
114 m_passwordHint[
h256(i[0])] = string(i[1]);
115 m_defaultPasswordDeprecated = string(s[3]);
118 cachePassword(m_defaultPasswordDeprecated);
122 m_master = hashPassword(_pass);
123 cachePassword(_pass);
134 return secret(m_addrLookup.at(_address), _pass, _usePasswordCache);
139 if (_usePasswordCache)
140 return Secret(m_store.
secret(_uuid, [&](){ return getPassword(_uuid, _pass); }, _usePasswordCache));
142 return Secret(m_store.
secret(_uuid, _pass, _usePasswordCache));
148 auto ait = m_uuidLookup.find(_uuid);
149 if (ait != m_uuidLookup.end())
151 auto kit = m_keyInfo.find(ait->second);
152 if (kit != m_keyInfo.end())
153 ph = kit->second.passHash;
160 auto it = m_cachedPasswords.find(_passHash);
161 if (it != m_cachedPasswords.end())
163 for (
unsigned i = 0; i < 10; ++i)
168 if (_passHash == UnknownPassword || hashPassword(p) == _passHash)
179 auto it = m_addrLookup.find(_a);
180 if (it == m_addrLookup.end())
187 auto it = m_uuidLookup.find(_uuid);
188 if (it == m_uuidLookup.end())
196 auto passHash = hashPassword(_pass);
197 cachePassword(_pass);
198 m_passwordHint[passHash] = _passwordHint;
200 m_keyInfo[addr] =
KeyInfo{passHash, _accountName,
""};
201 m_addrLookup[addr] =
uuid;
202 m_uuidLookup[
uuid] = addr;
213 auto passHash = hashPassword(_pass);
214 if (!m_cachedPasswords.count(passHash))
215 cachePassword(_pass);
221 if (!m_passwordHint.count(_passHash))
222 m_passwordHint[_passHash] = _passwordHint;
223 m_uuidLookup[_uuid] = _address;
224 m_addrLookup[_address] = _uuid;
225 m_keyInfo[_address].passHash = _passHash;
226 m_keyInfo[_address].accountName = _accountName;
232 auto id = m_addrLookup[_a];
233 m_uuidLookup.erase(
id);
234 m_addrLookup.erase(_a);
243 json_spirit::read_string(_json, val);
244 auto obj = val.get_obj();
245 string p = _password(
true);
246 if (obj[
"encseed"].type() == js::str_type)
248 auto encseed =
fromHex(obj[
"encseed"].get_str());
252 if (obj[
"ethaddr"].type() == js::str_type)
254 Address a(obj[
"ethaddr"].get_str());
258 if ((p = _password(
false)).empty())
272 set<Address> addresses;
273 for (
auto const& i: m_keyInfo)
274 addresses.insert(i.first);
275 for (
auto const& key: m_store.
keys())
276 addresses.insert(m_store.
address(key));
285 if (m_keyInfo.count(_address))
287 for (
auto const& key: m_store.
keys())
288 if (m_store.
address(key) == _address)
297 return m_keyInfo.at(_address).accountName;
309 auto& info = m_keyInfo.at(_address);
310 if (info.passwordHint.size())
311 return info.passwordHint;
312 return m_passwordHint.at(info.passHash);
320 h256 KeyManager::hashPassword(
string const& _pass)
const 323 return h256(
pbkdf2(_pass,
asBytes(m_defaultPasswordDeprecated), 262144, 32).makeInsecure());
326 void KeyManager::cachePassword(
string const& _password)
const 328 m_cachedPasswords[hashPassword(_password)] = _password;
331 bool KeyManager::write(fs::path
const& _keysFile)
const 335 write(m_keysFileKey, _keysFile);
339 void KeyManager::write(
string const& _pass, fs::path
const& _keysFile)
const 345 cachePassword(_pass);
346 m_master = hashPassword(_pass);
347 write(key, _keysFile);
355 s.appendList(m_keyInfo.size());
356 for (
auto const& info: m_keyInfo)
359 auto const& ki = info.second;
360 s.appendList(5) << info.first <<
id << ki.passHash << ki.accountName << ki.passwordHint;
363 s.appendList(m_passwordHint.size());
364 for (
auto const& i: m_passwordHint)
365 s.appendList(2) << i.first << i.second;
366 s.append(m_defaultPasswordDeprecated);
369 m_keysFileKey = _key;
370 cachePassword(defaultPassword());
376 bool keepGoing =
true;
383 if (done % 1000 == 0)
384 cnote <<
"Tried" << done <<
"keys";
401 vector<std::thread*> ts;
402 for (
unsigned t = 0; t < std::thread::hardware_concurrency() - 1; ++t)
403 ts.push_back(
new std::thread(f));
406 for (std::thread* t: ts)
bytesConstRef ref() const
h128 uuid(Address const &_a) const
static KeyPair presaleSecret(std::string const &_json, std::function< std::string(bool)> const &_password)
Extracts the secret key from the presale wallet.
bool hasAccount(Address const &_address) const
Address address(h128 const &_uuid) const
std::string getPassword(std::string const &_prompt)
Requests the user to enter a password on the console.
bytesSec decryptSymNoAuth(SecureFixedHash< 16 > const &_k, h128 const &_iv, bytesConstRef _cipher)
Decrypts payload with specified IV/ctr using AES128-CTR.
bytesSec pbkdf2(std::string const &_pass, bytes const &_salt, unsigned _iterations, unsigned _dkLen=32)
Derive key via PBKDF2.
void noteHint(std::string const &_pass, std::string const &_hint)
std::string const & passwordHint(Address const &_address) const
std::pair< bytes, h128 > encryptSymNoAuth(SecureFixedHash< 16 > const &_k, bytesConstRef _plain)
Encrypts payload with random IV/ctr using AES128-CTR.
static KeyPair create()
Create a new, randomly generated object.
SecureFixedHash< 32 > Secret
bytesSec secret(h128 const &_uuid, std::function< std::string()> const &_pass, bool _useCache=true) const
static KeyPair newKeyPair(NewKeyType _type)
Addresses accounts() const
bytes contents(boost::filesystem::path const &_file)
h128 import(Secret const &_s, std::string const &_accountName, std::string const &_pass, std::string const &_passwordHint)
std::vector< h128 > keys() const
Returns the uuids of all stored keys.
bytes fromHex(std::string const &_s, WhenError _throw=WhenError::DontThrow)
std::string const & accountName(Address const &_address) const
Base class for all exceptions.
bool recode(Address const &_address, std::string const &_newPass, std::string const &_hint, std::function< std::string()> const &_pass=DontKnowThrow, KDF _kdf=KDF::Scrypt)
void create(std::string const &_pass)
void kill(h128 const &_id)
std::string const EmptyString
std::vector< byte > bytes
static KeyPair fromEncryptedSeed(bytesConstRef _seed, std::string const &_password)
Create from an encrypted seed.
bytes asBytes(std::string const &_b)
Converts a string to a byte array containing the string's (byte) data.
h128 importSecret(bytesSec const &_s, std::string const &_pass)
h160s Addresses
A vector of Ethereum addresses.
Address address(h128 const &_uuid) const
static FixedHash random()
void importExisting(h128 const &_uuid, std::string const &_accountName, std::string const &_pass, std::string const &_passwordHint)
void save(boost::filesystem::path const &_keysPath)
Store all keys in the directory _keysPath.
bool load(std::string const &_pass)
Address const & address() const
Retrieve the associated address of the public key.
boost::error_info< struct tag_comment, std::string > errinfo_comment
void kill(h128 const &_uuid)
Removes the key specified by _uuid from both memory and disk.
bool contains(h128 const &_k) const
Secret secret(Address const &_address, std::function< std::string()> const &_pass=DontKnowThrow, bool _usePasswordCache=true) const
bytesSec asBytesSec() const
void writeFile(boost::filesystem::path const &_file, bytesConstRef _data, bool _writeDeleteRename)
Class for writing to an RLP bytestream.
boost::filesystem::path appendToFilename(boost::filesystem::path const &_orig, std::string const &_suffix)
std::string asString(bytes const &_b)
bool noteAddress(h128 const &_uuid, Address const &_address)