1 // Aleth: Ethereum C++ client, tools and libraries.
2 // Copyright 2015-2019 Aleth Authors.
3 // Licensed under the GNU General Public License, Version 3.
4 
5 
6 #include "KeyManager.h"
7 #include <thread>
8 #include <mutex>
9 #include <boost/filesystem.hpp>
10 #include <json_spirit/JsonSpiritHeaders.h>
11 #include <libdevcore/Log.h>
12 #include <libdevcore/Guards.h>
13 #include <libdevcore/RLP.h>
14 #include <libdevcore/SHA3.h>
15 using namespace std;
16 using namespace dev;
17 using namespace eth;
18 namespace js = json_spirit;
19 namespace fs = boost::filesystem;
20 
KeyManager(fs::path const & _keysFile,fs::path const & _secretsPath)21 KeyManager::KeyManager(fs::path const& _keysFile, fs::path const& _secretsPath):
22 	m_keysFile(_keysFile), m_store(_secretsPath)
23 {
24 	for (auto const& uuid: m_store.keys())
25 	{
26 		auto addr = m_store.address(uuid);
27 		m_addrLookup[addr] = uuid;
28 		m_uuidLookup[uuid] = addr;
29 	}
30 }
31 
~KeyManager()32 KeyManager::~KeyManager()
33 {}
34 
exists() const35 bool KeyManager::exists() const
36 {
37 	return !contents(appendToFilename(m_keysFile, ".salt")).empty() && !contents(m_keysFile).empty();
38 }
39 
create(string const & _pass)40 void KeyManager::create(string const& _pass)
41 {
42 	m_defaultPasswordDeprecated = asString(h256::random().asBytes());
43 	write(_pass, m_keysFile);
44 }
45 
recode(Address const & _address,string const & _newPass,string const & _hint,function<string ()> const & _pass,KDF _kdf)46 bool KeyManager::recode(Address const& _address, string const& _newPass, string const& _hint, function<string()> const& _pass, KDF _kdf)
47 {
48 	noteHint(_newPass, _hint);
49 	h128 u = uuid(_address);
50 	if (!store().recode(u, _newPass, [&](){ return getPassword(u, _pass); }, _kdf))
51 		return false;
52 
53 	m_keyInfo[_address].passHash = hashPassword(_newPass);
54 	write();
55 	return true;
56 }
57 
load(string const & _pass)58 bool KeyManager::load(string const& _pass)
59 {
60 	try
61 	{
62 		bytes salt = contents(appendToFilename(m_keysFile, ".salt"));
63 		bytes encKeys = contents(m_keysFile);
64 		if (encKeys.empty())
65 			return false;
66 		m_keysFileKey = SecureFixedHash<16>(pbkdf2(_pass, salt, 262144, 16));
67 		bytesSec bs = decryptSymNoAuth(m_keysFileKey, h128(), &encKeys);
68 		RLP s(bs.ref());
69 		unsigned version = unsigned(s[0]);
70 		if (version == 1)
71 		{
72 			bool saveRequired = false;
73 			for (auto const& i: s[1])
74 			{
75 				h128 uuid(i[1]);
76 				Address addr(i[0]);
77 				if (uuid)
78 				{
79 					if (m_store.contains(uuid))
80 					{
81 						m_addrLookup[addr] = uuid;
82 						m_uuidLookup[uuid] = addr;
83 						m_keyInfo[addr] = KeyInfo(h256(i[2]), string(i[3]), i.itemCount() > 4 ? string(i[4]) : "");
84 						if (m_store.noteAddress(uuid, addr))
85 							saveRequired = true;
86 					}
87 					else
88 						cwarn << "Missing key:" << uuid << addr;
89 				}
90 				else
91 					m_keyInfo[addr] = KeyInfo(h256(i[2]), string(i[3]), i.itemCount() > 4 ? string(i[4]) : "");
92 //				cdebug << toString(addr) << toString(uuid) << toString((h256)i[2]) << (string)i[3];
93 			}
94 			if (saveRequired)
95 				m_store.save();
96 
97 			for (auto const& i: s[2])
98 				m_passwordHint[h256(i[0])] = string(i[1]);
99 			m_defaultPasswordDeprecated = string(s[3]);
100 		}
101 //		cdebug << hashPassword(m_password) << toHex(m_password);
102 		cachePassword(m_defaultPasswordDeprecated);
103 //		cdebug << hashPassword(asString(m_key.ref())) << m_key.hex();
104 		cachePassword(asString(m_keysFileKey.ref()));
105 //		cdebug << hashPassword(_pass) << _pass;
106 		m_master = hashPassword(_pass);
107 		cachePassword(_pass);
108 		return true;
109 	}
110 	catch (...)
111 	{
112 		return false;
113 	}
114 }
115 
secret(Address const & _address,function<string ()> const & _pass,bool _usePasswordCache) const116 Secret KeyManager::secret(Address const& _address, function<string()> const& _pass, bool _usePasswordCache) const
117 {
118 	return secret(m_addrLookup.at(_address), _pass, _usePasswordCache);
119 }
120 
secret(h128 const & _uuid,function<string ()> const & _pass,bool _usePasswordCache) const121 Secret KeyManager::secret(h128 const& _uuid, function<string()> const& _pass, bool _usePasswordCache) const
122 {
123 	if (_usePasswordCache)
124 		return Secret(m_store.secret(_uuid, [&](){ return getPassword(_uuid, _pass); }, _usePasswordCache));
125 	else
126 		return Secret(m_store.secret(_uuid, _pass, _usePasswordCache));
127 }
128 
getPassword(h128 const & _uuid,function<string ()> const & _pass) const129 string KeyManager::getPassword(h128 const& _uuid, function<string()> const& _pass) const
130 {
131 	h256 ph;
132 	auto ait = m_uuidLookup.find(_uuid);
133 	if (ait != m_uuidLookup.end())
134 	{
135 		auto kit = m_keyInfo.find(ait->second);
136 		if (kit != m_keyInfo.end())
137 			ph = kit->second.passHash;
138 	}
139 	return getPassword(ph, _pass);
140 }
141 
getPassword(h256 const & _passHash,function<string ()> const & _pass) const142 string KeyManager::getPassword(h256 const& _passHash, function<string()> const& _pass) const
143 {
144 	auto it = m_cachedPasswords.find(_passHash);
145 	if (it != m_cachedPasswords.end())
146 		return it->second;
147 	for (unsigned i = 0; i < 10; ++i)
148 	{
149 		string p = _pass();
150 		if (p.empty())
151 			break;
152 		if (_passHash == UnknownPassword || hashPassword(p) == _passHash)
153 		{
154 			cachePassword(p);
155 			return p;
156 		}
157 	}
158 	return string();
159 }
160 
uuid(Address const & _a) const161 h128 KeyManager::uuid(Address const& _a) const
162 {
163 	auto it = m_addrLookup.find(_a);
164 	if (it == m_addrLookup.end())
165 		return h128();
166 	return it->second;
167 }
168 
address(h128 const & _uuid) const169 Address KeyManager::address(h128 const& _uuid) const
170 {
171 	auto it = m_uuidLookup.find(_uuid);
172 	if (it == m_uuidLookup.end())
173 		return Address();
174 	return it->second;
175 }
176 
import(Secret const & _s,string const & _accountName,string const & _pass,string const & _passwordHint)177 h128 KeyManager::import(Secret const& _s, string const& _accountName, string const& _pass, string const& _passwordHint)
178 {
179 	Address addr = KeyPair(_s).address();
180 	auto passHash = hashPassword(_pass);
181 	cachePassword(_pass);
182 	m_passwordHint[passHash] = _passwordHint;
183 	auto uuid = m_store.importSecret(_s.asBytesSec(), _pass);
184 	m_keyInfo[addr] = KeyInfo{passHash, _accountName, ""};
185 	m_addrLookup[addr] = uuid;
186 	m_uuidLookup[uuid] = addr;
187 	write(m_keysFile);
188 	return uuid;
189 }
190 
importExisting(h128 const & _uuid,string const & _info,string const & _pass,string const & _passwordHint)191 void KeyManager::importExisting(h128 const& _uuid, string const& _info, string const& _pass, string const& _passwordHint)
192 {
193 	bytesSec key = m_store.secret(_uuid, [&](){ return _pass; });
194 	if (key.empty())
195 		return;
196 	Address a = KeyPair(Secret(key)).address();
197 	auto passHash = hashPassword(_pass);
198 	if (!m_cachedPasswords.count(passHash))
199 		cachePassword(_pass);
200 	importExisting(_uuid, _info, a, passHash, _passwordHint);
201 }
202 
importExisting(h128 const & _uuid,string const & _accountName,Address const & _address,h256 const & _passHash,string const & _passwordHint)203 void KeyManager::importExisting(h128 const& _uuid, string const& _accountName, Address const& _address, h256 const& _passHash, string const& _passwordHint)
204 {
205 	if (!m_passwordHint.count(_passHash))
206 		m_passwordHint[_passHash] = _passwordHint;
207 	m_uuidLookup[_uuid] = _address;
208 	m_addrLookup[_address] = _uuid;
209 	m_keyInfo[_address].passHash = _passHash;
210 	m_keyInfo[_address].accountName = _accountName;
211 	write(m_keysFile);
212 }
213 
kill(Address const & _a)214 void KeyManager::kill(Address const& _a)
215 {
216 	auto id = m_addrLookup[_a];
217 	m_uuidLookup.erase(id);
218 	m_addrLookup.erase(_a);
219 	m_keyInfo.erase(_a);
220 	m_store.kill(id);
221 	write(m_keysFile);
222 }
223 
presaleSecret(std::string const & _json,function<string (bool)> const & _password)224 KeyPair KeyManager::presaleSecret(std::string const& _json, function<string(bool)> const& _password)
225 {
226 	js::mValue val;
227 	json_spirit::read_string(_json, val);
228 	auto obj = val.get_obj();
229 	string p = _password(true);
230 	if (obj["encseed"].type() == js::str_type)
231 	{
232 		auto encseed = fromHex(obj["encseed"].get_str());
233 		while (true)
234 		{
235 			KeyPair k = KeyPair::fromEncryptedSeed(&encseed, p);
236 			if (obj["ethaddr"].type() == js::str_type)
237 			{
238 				Address a(obj["ethaddr"].get_str());
239 				Address b = k.address();
240 				if (a != b)
241 				{
242 					if ((p = _password(false)).empty())
243 						BOOST_THROW_EXCEPTION(PasswordUnknown());
244 					continue;
245 				}
246 			}
247 			return k;
248 		}
249 	}
250 	else
251 		BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("encseed type is not js::str_type"));
252 }
253 
accounts() const254 Addresses KeyManager::accounts() const
255 {
256 	set<Address> addresses;
257 	for (auto const& i: m_keyInfo)
258 		addresses.insert(i.first);
259 	for (auto const& key: m_store.keys())
260 		addresses.insert(m_store.address(key));
261 	// Remove the zero address if present
262 	return Addresses{addresses.upper_bound(Address()), addresses.end()};
263 }
264 
hasAccount(Address const & _address) const265 bool KeyManager::hasAccount(Address const& _address) const
266 {
267 	if (!_address)
268 		return false;
269 	if (m_keyInfo.count(_address))
270 		return true;
271 	for (auto const& key: m_store.keys())
272 		if (m_store.address(key) == _address)
273 			return true;
274 	return false;
275 }
276 
accountName(Address const & _address) const277 string const& KeyManager::accountName(Address const& _address) const
278 {
279 	try
280 	{
281 		return m_keyInfo.at(_address).accountName;
282 	}
283 	catch (...)
284 	{
285 		return EmptyString;
286 	}
287 }
288 
passwordHint(Address const & _address) const289 string const& KeyManager::passwordHint(Address const& _address) const
290 {
291 	try
292 	{
293 		auto& info = m_keyInfo.at(_address);
294 		if (info.passwordHint.size())
295 			return info.passwordHint;
296 		return m_passwordHint.at(info.passHash);
297 	}
298 	catch (...)
299 	{
300 		return EmptyString;
301 	}
302 }
303 
hashPassword(string const & _pass) const304 h256 KeyManager::hashPassword(string const& _pass) const
305 {
306 	// TODO SECURITY: store this a bit more securely; Scrypt perhaps?
307 	return h256(pbkdf2(_pass, asBytes(m_defaultPasswordDeprecated), 262144, 32).makeInsecure());
308 }
309 
cachePassword(string const & _password) const310 void KeyManager::cachePassword(string const& _password) const
311 {
312 	m_cachedPasswords[hashPassword(_password)] = _password;
313 }
314 
write(fs::path const & _keysFile) const315 bool KeyManager::write(fs::path const& _keysFile) const
316 {
317 	if (!m_keysFileKey)
318 		return false;
319 	write(m_keysFileKey, _keysFile);
320 	return true;
321 }
322 
write(string const & _pass,fs::path const & _keysFile) const323 void KeyManager::write(string const& _pass, fs::path const& _keysFile) const
324 {
325 	bytes salt = h256::random().asBytes();
326 	writeFile(appendToFilename(_keysFile, ".salt"), salt, true);
327 	auto key = SecureFixedHash<16>(pbkdf2(_pass, salt, 262144, 16));
328 
329 	cachePassword(_pass);
330 	m_master = hashPassword(_pass);
331 	write(key, _keysFile);
332 }
333 
write(SecureFixedHash<16> const & _key,fs::path const & _keysFile) const334 void KeyManager::write(SecureFixedHash<16> const& _key, fs::path const& _keysFile) const
335 {
336 	RLPStream s(4);
337 	s << 1; // version
338 
339 	s.appendList(m_keyInfo.size());
340 	for (auto const& info: m_keyInfo)
341 	{
342 		h128 id = uuid(info.first);
343 		auto const& ki = info.second;
344 		s.appendList(5) << info.first << id << ki.passHash << ki.accountName << ki.passwordHint;
345 	}
346 
347 	s.appendList(m_passwordHint.size());
348 	for (auto const& i: m_passwordHint)
349 		s.appendList(2) << i.first << i.second;
350 	s.append(m_defaultPasswordDeprecated);
351 
352 	writeFile(_keysFile, encryptSymNoAuth(_key, h128(), &s.out()), true);
353 	m_keysFileKey = _key;
354 	cachePassword(defaultPassword());
355 }
356 
newKeyPair(KeyManager::NewKeyType _type)357 KeyPair KeyManager::newKeyPair(KeyManager::NewKeyType _type)
358 {
359 	KeyPair p = KeyPair::create();
360 	bool keepGoing = true;
361 	unsigned done = 0;
362 	auto f = [&]() {
363 		KeyPair lp = KeyPair::create();
364 		while (keepGoing)
365 		{
366 			done++;
367 			if (done % 1000 == 0)
368 				cnote << "Tried" << done << "keys";
369 			lp = KeyPair::create();
370 			auto a = lp.address();
371 			if (_type == NewKeyType::NoVanity ||
372 				(_type == NewKeyType::DirectICAP && !a[0]) ||
373 				(_type == NewKeyType::FirstTwo && a[0] == a[1]) ||
374 				(_type == NewKeyType::FirstTwoNextTwo && a[0] == a[1] && a[2] == a[3]) ||
375 				(_type == NewKeyType::FirstThree && a[0] == a[1] && a[1] == a[2]) ||
376 				(_type == NewKeyType::FirstFour && a[0] == a[1] && a[1] == a[2] && a[2] == a[3])
377 			)
378 				break;
379 		}
380 		if (keepGoing)
381 			p = lp;
382 		keepGoing = false;
383 	};
384 
385 	vector<std::thread*> ts;
386 	for (unsigned t = 0; t < std::thread::hardware_concurrency() - 1; ++t)
387 		ts.push_back(new std::thread(f));
388 	f();
389 
390 	for (std::thread* t: ts)
391 	{
392 		t->join();
393 		delete t;
394 	}
395 	return p;
396 }
397