Fabcoin Core  0.16.2
P2P Digital Currency
KeyAux.h
Go to the documentation of this file.
1 #pragma once
2 
3 /*
4  This file is part of cpp-ethereum.
5 
6  cpp-ethereum is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  cpp-ethereum is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
18 */
25 #include <thread>
26 #include <chrono>
27 #include <fstream>
28 #include <iostream>
29 #include <boost/algorithm/string.hpp>
30 #include <boost/algorithm/string/trim_all.hpp>
31 #include <libdevcore/SHA3.h>
32 #include <libdevcore/FileSystem.h>
33 #include <libethcore/KeyManager.h>
34 #include <libethcore/ICAP.h>
35 #include <libethcore/Transaction.h>
36 
37 using namespace std;
38 using namespace dev;
39 using namespace dev::eth;
40 using namespace boost::algorithm;
41 
42 #undef RETURN
43 
44 class BadArgument: public Exception {};
45 
46 string getAccountPassword(KeyManager& keyManager, Address const& a)
47 {
48  return getPassword("Enter passphrase for address " + keyManager.accountName(a) + " (" + a.abridged() + "; hint:" + keyManager.passwordHint(a) + "): ");
49 }
50 
51 string createPassword(std::string const& _prompt)
52 {
53  string ret;
54  while (true)
55  {
56  ret = getPassword(_prompt);
57  string confirm = getPassword("Please confirm the passphrase by entering it again: ");
58  if (ret == confirm)
59  break;
60  cout << "Passwords were different. Try again." << endl;
61  }
62  return ret;
63 // cout << "Enter a hint to help you remember this passphrase: " << flush;
64 // cin >> hint;
65 // return make_pair(ret, hint);
66 }
67 
68 pair<string, string> createPassword(KeyManager& _keyManager, std::string const& _prompt, std::string const& _pass = std::string(), std::string const& _hint = std::string())
69 {
70  string pass = _pass;
71  if (pass.empty())
72  while (true)
73  {
74  pass = getPassword(_prompt);
75  string confirm = getPassword("Please confirm the passphrase by entering it again: ");
76  if (pass == confirm)
77  break;
78  cout << "Passwords were different. Try again." << endl;
79  }
80  string hint = _hint;
81  if (hint.empty() && !pass.empty() && !_keyManager.haveHint(pass))
82  {
83  cout << "Enter a hint to help you remember this passphrase: " << flush;
84  getline(cin, hint);
85  }
86  return make_pair(pass, hint);
87 }
88 
89 class KeyCLI
90 {
91 public:
92  enum class OperationMode
93  {
94  None,
95  ListBare,
96  NewBare,
97  ImportBare,
98  ExportBare,
99  RecodeBare,
100  KillBare,
101  InspectBare,
102  CreateWallet,
103  List,
104  New,
105  Import,
106  ImportWithAddress,
107  ImportPresale,
108  Export,
109  Recode,
110  Kill,
111  Inspect,
112  SignTx,
113  DecodeTx,
114  };
115 
116  KeyCLI(OperationMode _mode = OperationMode::None): m_mode(_mode) {}
117 
118  bool interpretOption(int& i, int argc, char** argv)
119  {
120  string arg = argv[i];
121  if (arg == "--wallet-path" && i + 1 < argc)
122  m_walletPath = argv[++i];
123  else if (arg == "--secrets-path" && i + 1 < argc)
124  m_secretsPath = argv[++i];
125  else if ((arg == "-m" || arg == "--master") && i + 1 < argc)
126  m_masterPassword = argv[++i];
127  else if (arg == "--unlock" && i + 1 < argc)
128  m_unlocks.push_back(argv[++i]);
129  else if (arg == "--lock" && i + 1 < argc)
130  m_lock = argv[++i];
131  else if (arg == "--kdf" && i + 1 < argc)
132  m_kdf = argv[++i];
133  else if (arg == "--kdf-param" && i + 2 < argc)
134  {
135  auto n = argv[++i];
136  auto v = argv[++i];
137  m_kdfParams[n] = v;
138  }
139  else if (arg == "newbare")
140  m_mode = OperationMode::NewBare;
141  else if (arg == "inspect")
142  m_mode = OperationMode::Inspect;
143  else if ((arg == "-s" || arg == "--sign-tx" || arg == "sign") && i + 1 < argc)
144  {
145  m_mode = OperationMode::SignTx;
146  m_signKey = argv[++i];
147  }
148  else if (arg == "--show-me-the-secret")
149  m_showSecret = true;
150  else if (arg == "--tx-data" && i + 1 < argc)
151  try
152  {
153  m_toSign.data = fromHex(argv[++i]);
154  }
155  catch (...)
156  {
157  cerr << "Invalid argument to " << arg << endl;
158  exit(-1);
159  }
160  else if (arg == "--tx-nonce" && i + 1 < argc)
161  try
162  {
163  m_toSign.nonce = u256(argv[++i]);
164  }
165  catch (...)
166  {
167  cerr << "Invalid argument to " << arg << endl;
168  exit(-1);
169  }
170  else if (arg == "--force-nonce" && i + 1 < argc)
171  try
172  {
173  m_forceNonce = u256(argv[++i]);
174  }
175  catch (...)
176  {
177  cerr << "Invalid argument to " << arg << endl;
178  exit(-1);
179  }
180  else if ((arg == "--tx-dest" || arg == "--tx-to" || arg == "--tx-destination") && i + 1 < argc)
181  try
182  {
183  m_toSign.creation = false;
184  m_toSign.to = toAddress(argv[++i]);
185  }
186  catch (...)
187  {
188  cerr << "Invalid argument to " << arg << endl;
189  exit(-1);
190  }
191  else if (arg == "--tx-gas" && i + 1 < argc)
192  try
193  {
194  m_toSign.gas = u256(argv[++i]);
195  }
196  catch (...)
197  {
198  cerr << "Invalid argument to " << arg << endl;
199  exit(-1);
200  }
201  else if (arg == "--tx-gasprice" && i + 1 < argc)
202  try
203  {
204  m_toSign.gasPrice = u256(argv[++i]);
205  }
206  catch (...)
207  {
208  cerr << "Invalid argument to " << arg << endl;
209  exit(-1);
210  }
211  else if (arg == "--tx-value" && i + 1 < argc)
212  try
213  {
214  m_toSign.value = u256(argv[++i]);
215  }
216  catch (...)
217  {
218  cerr << "Invalid argument to " << arg << endl;
219  exit(-1);
220  }
221  else if (arg == "--decode-tx" || arg == "decode")
222  m_mode = OperationMode::DecodeTx;
223  else if (arg == "--import-bare" || arg == "importbare")
224  m_mode = OperationMode::ImportBare;
225  else if (arg == "--list-bare" || arg == "listbare")
226  m_mode = OperationMode::ListBare;
227  else if (arg == "--export-bare" || arg == "exportbare")
228  m_mode = OperationMode::ExportBare;
229  else if (arg == "--inspect-bare" || arg == "inspectbare")
230  m_mode = OperationMode::InspectBare;
231  else if (arg == "--recode-bare" || arg == "recodebare")
232  m_mode = OperationMode::RecodeBare;
233  else if (arg == "--kill-bare" || arg == "killbare")
234  m_mode = OperationMode::KillBare;
235  else if (arg == "--create-wallet" || arg == "createwallet")
236  m_mode = OperationMode::CreateWallet;
237  else if (arg == "-l" || arg == "--list" || arg == "list")
238  m_mode = OperationMode::List;
239  else if ((arg == "-n" || arg == "--new" || arg == "new") && i + 1 < argc)
240  {
241  m_mode = OperationMode::New;
242  m_name = argv[++i];
243  }
244  else if ((arg == "-i" || arg == "--import" || arg == "import") && i + 2 < argc)
245  {
246  m_mode = OperationMode::Import;
247  m_inputs = strings(1, argv[++i]);
248  m_name = argv[++i];
249  }
250  else if ((arg == "--import-presale" || arg == "importpresale") && i + 2 < argc)
251  {
252  m_mode = OperationMode::ImportPresale;
253  m_inputs = strings(1, argv[++i]);
254  m_name = argv[++i];
255  }
256  else if ((arg == "--import-with-address" || arg == "importwithaddress") && i + 3 < argc)
257  {
258  m_mode = OperationMode::ImportWithAddress;
259  m_inputs = strings(1, argv[++i]);
260  m_address = Address(argv[++i]);
261  m_name = argv[++i];
262  }
263  else if (arg == "--export" || arg == "export")
264  m_mode = OperationMode::Export;
265  else if (arg == "--recode" || arg == "recode")
266  m_mode = OperationMode::Recode;
267  else if (arg == "kill")
268  m_mode = OperationMode::Kill;
269  else if (arg == "--no-icap")
270  m_icap = false;
271  else if (m_mode == OperationMode::DecodeTx || m_mode == OperationMode::Inspect || m_mode == OperationMode::Kill || m_mode == OperationMode::SignTx || m_mode == OperationMode::ImportBare || m_mode == OperationMode::InspectBare || m_mode == OperationMode::KillBare || m_mode == OperationMode::Recode || m_mode == OperationMode::Export || m_mode == OperationMode::RecodeBare || m_mode == OperationMode::ExportBare)
272  m_inputs.push_back(arg);
273  else
274  return false;
275  return true;
276  }
277 
278  KeyPair makeKey() const
279  {
280  KeyPair k(Secret::random());
281  while (m_icap && k.address()[0])
282  k = KeyPair(Secret(sha3(k.secret().ref())));
283  return k;
284  }
285 
286  Secret getSecret(std::string const& _signKey)
287  {
288  string json = contentsString(_signKey);
289  if (!json.empty())
290  return Secret(secretStore().secret(secretStore().readKeyContent(json), [&](){ return getPassword("Enter passphrase for key: "); }));
291  else
292  {
293  if (h128 u = fromUUID(_signKey))
294  return Secret(secretStore().secret(u, [&](){ return getPassword("Enter passphrase for key: "); }));
295  if (_signKey.substr(0, 6) == "brain#" && _signKey.find(":") != string::npos)
296  return KeyManager::subkey(KeyManager::brain(_signKey.substr(_signKey.find(":"))), stoul(_signKey.substr(6, _signKey.find(":") - 7)));
297  if (_signKey.substr(0, 6) == "brain:")
298  return KeyManager::brain(_signKey.substr(6));
299  if (_signKey == "brain")
300  return KeyManager::brain(getPassword("Enter brain wallet phrase: "));
301  Address a;
302  try
303  {
304  a = toAddress(_signKey);
305  }
306  catch (...)
307  {
308  for (Address const& aa: keyManager().accounts())
309  if (keyManager().accountName(aa) == _signKey)
310  {
311  a = aa;
312  break;
313  }
314  }
315  if (a)
316  return keyManager().secret(a, [&](){ return getPassword("Enter passphrase for key (hint:" + keyManager().passwordHint(a) + "): "); });
317  cerr << "Bad file, UUID or address: " << _signKey << endl;
318  exit(-1);
319  }
320  }
321 
322  std::string userVisible(Address const& _a) const { return ICAP(_a).encoded() + " (" + _a.abridged() + ")"; }
323 
324  void execute()
325  {
326  switch (m_mode)
327  {
328  case OperationMode::CreateWallet:
329  {
330  KeyManager wallet(m_walletPath, m_secretsPath);
331  if (m_masterPassword.empty())
332  m_masterPassword = createPassword("Please enter a MASTER passphrase to protect your key store (make it strong!): ");
333  try
334  {
335  wallet.create(m_masterPassword);
336  }
337  catch (Exception const& _e)
338  {
339  cerr << "unable to create wallet" << endl << boost::diagnostic_information(_e);
340  }
341  break;
342  }
343  case OperationMode::DecodeTx:
344  {
345  try
346  {
347  TransactionBase t = m_inputs.empty() ? TransactionBase(m_toSign) : TransactionBase(inputData(m_inputs[0]), CheckTransaction::None);
348  cout << "Transaction " << t.sha3().hex() << endl;
349  if (t.isCreation())
350  {
351  cout << " type: creation" << endl;
352  cout << " code: " << toHex(t.data()) << endl;
353  }
354  else
355  {
356  cout << " type: message" << endl;
357  cout << " to: " << userVisible(t.to()) << endl;
358  cout << " data: " << (t.data().empty() ? "none" : toHex(t.data())) << endl;
359  }
360  try
361  {
362  auto s = t.sender();
363  if (t.isCreation())
364  cout << " creates: " << userVisible(toAddress(s, t.nonce())) << endl;
365  cout << " from: " << userVisible(s) << endl;
366  }
367  catch (...)
368  {
369  cout << " from: <unsigned>" << endl;
370  }
371  cout << " value: " << formatBalance(t.value()) << " (" << t.value() << " wei)" << endl;
372  cout << " nonce: " << t.nonce() << endl;
373  cout << " gas: " << t.gas() << endl;
374  cout << " gas price: " << formatBalance(t.gasPrice()) << " (" << t.gasPrice() << " wei)" << endl;
375  cout << " signing hash: " << t.sha3(WithoutSignature).hex() << endl;
376  if (t.safeSender())
377  {
378  cout << " v: " << (int)t.signature().v << endl;
379  cout << " r: " << t.signature().r << endl;
380  cout << " s: " << t.signature().s << endl;
381  }
382  }
383  catch (Exception& ex)
384  {
385  cerr << "Invalid transaction: " << ex.what() << endl;
386  }
387  break;
388  }
389  case OperationMode::SignTx:
390  {
391  Secret s = getSecret(m_signKey);
392  if (m_inputs.empty())
393  m_inputs.push_back(string());
394  for (string const& i: m_inputs)
395  {
396  bool isFile = false;
397  try
398  {
399  TransactionBase t = i.empty() ? TransactionBase(m_toSign) : TransactionBase(inputData(i, &isFile), CheckTransaction::None);
400  if (m_forceNonce)
401  t.setNonce(m_forceNonce);
402  t.sign(s);
403  cout << t.sha3() << ": ";
404  if (isFile)
405  {
406  writeFile(i + ".signed", toHex(t.rlp()));
407  cout << i + ".signed" << endl;
408  }
409  else
410  cout << toHex(t.rlp()) << endl;
411  }
412  catch (Exception& ex)
413  {
414  cerr << "Invalid transaction: " << ex.what() << endl;
415  }
416  }
417  break;
418  }
419  case OperationMode::Inspect:
420  {
421  keyManager(true);
422  if (m_inputs.empty())
423  m_inputs.push_back(toAddress(KeyManager::brain(getPassword("Enter brain wallet key phrase: "))).hex());
424  for (auto i: m_inputs)
425  {
426  Address a = userToAddress(i);
427  if (!keyManager().accountName(a).empty())
428  cout << keyManager().accountName(a) << " (" << a.abridged() << ")" << endl;
429  else
430  cout << a.abridged() << endl;
431  cout << " ICAP: " << ICAP(a).encoded() << endl;
432  cout << " Raw hex: " << a.hex() << endl;
433  if (m_showSecret)
434  {
435  Secret s = keyManager(true).secret(a);
436  cout << " Secret: " << (m_showSecret ? toHex(s.ref()) : (toHex(s.ref().cropped(0, 8)) + "...")) << endl;
437  }
438  }
439  break;
440  }
441  case OperationMode::ListBare:
442  if (secretStore().keys().empty())
443  cout << "No keys found." << endl;
444  else
445  for (h128 const& u: std::set<h128>() + secretStore().keys())
446  cout << toUUID(u) << endl;
447  break;
448  case OperationMode::NewBare:
449  {
450  if (m_lock.empty())
451  m_lock = createPassword("Enter a passphrase with which to secure this account: ");
452  auto k = makeKey();
453  h128 u = secretStore().importSecret(k.secret().ref(), m_lock);
454  cout << "Created key " << toUUID(u) << endl;
455  cout << " ICAP: " << ICAP(k.address()).encoded() << endl;
456  cout << " Raw hex: " << k.address().hex() << endl;
457  break;
458  }
459  case OperationMode::ImportBare:
460  for (string const& input: m_inputs)
461  {
462  h128 u;
463  bytesSec b;
464  b.writable() = fromHex(input);
465  if (b.size() != 32)
466  {
467  std::string s = contentsString(input);
468  b.writable() = fromHex(s);
469  if (b.size() != 32)
470  u = secretStore().importKey(input);
471  }
472  if (!u && b.size() == 32)
473  u = secretStore().importSecret(b, lockPassword(toAddress(Secret(b)).abridged()));
474  if (!u)
475  {
476  cerr << "Cannot import " << input << " not a file or secret." << endl;
477  continue;
478  }
479  cout << "Successfully imported " << input << " as " << toUUID(u);
480  }
481  break;
482  case OperationMode::InspectBare:
483  for (auto const& i: m_inputs)
484  if (!contents(i).empty())
485  {
486  h128 u = secretStore().readKey(i, false);
487  bytesSec s = secretStore().secret(u, [&](){ return getPassword("Enter passphrase for key " + i + ": "); });
488  cout << "Key " << i << ":" << endl;
489  cout << " UUID: " << toUUID(u) << ":" << endl;
490  cout << " ICAP: " << ICAP(toAddress(Secret(s))).encoded() << endl;
491  cout << " Raw hex: " << toAddress(Secret(s)).hex() << endl;
492  cout << " Secret: " << (m_showSecret ? toHex(s.ref()) : (toHex(s.ref().cropped(0, 8)) + "...")) << endl;
493  }
494  else if (h128 u = fromUUID(i))
495  {
496  bytesSec s = secretStore().secret(u, [&](){ return getPassword("Enter passphrase for key " + toUUID(u) + ": "); });
497  cout << "Key " << i << ":" << endl;
498  cout << " ICAP: " << ICAP(toAddress(Secret(s))).encoded() << endl;
499  cout << " Raw hex: " << toAddress(Secret(s)).hex() << endl;
500  cout << " Secret: " << (m_showSecret ? toHex(s.ref()) : (toHex(s.ref().cropped(0, 8)) + "...")) << endl;
501  }
502  else if (Address a = toAddress(i))
503  {
504  cout << "Key " << a.abridged() << ":" << endl;
505  cout << " ICAP: " << ICAP(a).encoded() << endl;
506  cout << " Raw hex: " << a.hex() << endl;
507  }
508  else
509  cerr << "Couldn't inspect " << i << "; not found." << endl;
510  break;
511  case OperationMode::ExportBare: break;
512  case OperationMode::RecodeBare:
513  for (auto const& i: m_inputs)
514  if (h128 u = fromUUID(i))
515  if (secretStore().recode(u, lockPassword(toUUID(u)), [&](){ return getPassword("Enter passphrase for key " + toUUID(u) + ": "); }, kdf()))
516  cerr << "Re-encoded " << toUUID(u) << endl;
517  else
518  cerr << "Couldn't re-encode " << toUUID(u) << "; key corrupt or incorrect passphrase supplied." << endl;
519  else
520  cerr << "Couldn't re-encode " << i << "; not found." << endl;
521  break;
522  case OperationMode::KillBare:
523  for (auto const& i: m_inputs)
524  if (h128 u = fromUUID(i))
525  secretStore().kill(u);
526  else
527  cerr << "Couldn't kill " << i << "; not found." << endl;
528  break;
529  case OperationMode::New:
530  {
531  keyManager();
532  tie(m_lock, m_lockHint) = createPassword(keyManager(), "Enter a passphrase with which to secure this account (or nothing to use the master passphrase): ", m_lock, m_lockHint);
533  auto k = makeKey();
534  bool usesMaster = m_lock.empty();
535  h128 u = usesMaster ? keyManager().import(k.secret(), m_name) : keyManager().import(k.secret(), m_name, m_lock, m_lockHint);
536  cout << "Created key " << toUUID(u) << endl;
537  cout << " Name: " << m_name << endl;
538  if (usesMaster)
539  cout << " Uses master passphrase." << endl;
540  else
541  cout << " Password hint: " << m_lockHint << endl;
542  cout << " ICAP: " << ICAP(k.address()).encoded() << endl;
543  cout << " Raw hex: " << k.address().hex() << endl;
544  break;
545  }
547  {
548  if (m_inputs.size() != 1)
549  {
550  cerr << "Error: exactly one key must be given to import." << endl;
551  break;
552  }
553 
554  h128 u = keyManager().store().importKey(m_inputs[0]);
555  string pw;
556  bytesSec s = keyManager().store().secret(u, [&](){ return (pw = getPassword("Enter the passphrase for the key: ")); });
557  if (s.size() != 32)
558  {
559  cerr << "Error: couldn't decode key or invalid secret size." << endl;
560  break;
561  }
562 
563  bool usesMaster = true;
564  if (pw != m_masterPassword && m_lockHint.empty())
565  {
566  cout << "Enter a hint to help you remember the key's passphrase: " << flush;
567  getline(cin, m_lockHint);
568  usesMaster = false;
569  }
570  keyManager().importExisting(u, m_name, pw, m_lockHint);
571  auto a = keyManager().address(u);
572 
573  cout << "Imported key " << toUUID(u) << endl;
574  cout << " Name: " << m_name << endl;
575  if (usesMaster)
576  cout << " Uses master passphrase." << endl;
577  else
578  cout << " Password hint: " << m_lockHint << endl;
579  cout << " ICAP: " << ICAP(a).encoded() << endl;
580  cout << " Raw hex: " << a.hex() << endl;
581  break;
582  }
583  case OperationMode::ImportWithAddress:
584  {
585  if (m_inputs.size() != 1)
586  {
587  cerr << "Error: exactly one key must be given to import." << endl;
588  break;
589  }
590  keyManager();
591  string const& i = m_inputs[0];
592  h128 u;
593  bytesSec b;
594  b.writable() = fromHex(i);
595  if (b.size() != 32)
596  {
597  std::string s = contentsString(i);
598  b.writable() = fromHex(s);
599  if (b.size() != 32)
600  u = keyManager().store().importKey(i);
601  }
602  if (!u && b.size() == 32)
603  u = keyManager().store().importSecret(b, lockPassword(toAddress(Secret(b)).abridged()));
604  if (!u)
605  {
606  cerr << "Cannot import " << i << " not a file or secret." << endl;
607  break;
608  }
609  keyManager().importExisting(u, m_name, m_address);
610  cout << "Successfully imported " << i << ":" << endl;
611  cout << " Name: " << m_name << endl;
612  cout << " UUID: " << toUUID(u) << endl;
613  cout << " Raw hex: " << m_address << endl;
614  break;
615  }
616  case OperationMode::ImportPresale:
617  {
618  keyManager();
619  std::string pw;
620  KeyPair k = keyManager().presaleSecret(contentsString(m_inputs[0]), [&](bool){ return (pw = getPassword("Enter the passphrase for the presale key: ")); });
621  keyManager().import(k.secret(), m_name, pw, "Same passphrase as used for presale key");
622  break;
623  }
624  case OperationMode::Recode:
625  for (auto const& i: m_inputs)
626  if (Address a = userToAddress(i))
627  {
628  string pw;
629  Secret s = keyManager().secret(a, [&](){ return pw = getPassword("Enter old passphrase for key '" + i + "' (hint: " + keyManager().passwordHint(a) + "): "); });
630  if (!s)
631  {
632  cerr << "Invalid password for key " << userVisible(a) << endl;
633  continue;
634  }
635  pair<string, string> np = createPassword(keyManager(), "Enter new passphrase for key '" + i + "': ");
636  if (keyManager().recode(a, np.first, np.second, [&](){ return pw; }, kdf()))
637  cout << "Re-encoded key '" << i << "' successfully." << endl;
638  else
639  cerr << "Couldn't re-encode '" << i << "''; key corrupt or incorrect passphrase supplied." << endl;
640  }
641  else
642  cerr << "Couldn't re-encode " << i << "; not found." << endl;
643  break;
644  case OperationMode::Kill:
645  {
646  unsigned count = 0;
647  for (auto const& i: m_inputs)
648  {
649  if (Address a = userToAddress(i))
650  keyManager().kill(a);
651  else
652  cerr << "Couldn't kill " << i << "; not found." << endl;
653  ++count;
654  }
655  cout << count << " key(s) deleted." << endl;
656  break;
657  }
658  case OperationMode::List:
659  {
660  if (keyManager().store().keys().empty())
661  {
662  cout << "No keys found." << endl;
663  break;
664  }
665 
666  vector<u128> bare;
667  AddressHash got;
668  for (auto const& u: keyManager().store().keys())
669  if (Address a = keyManager().address(u))
670  {
671  got.insert(a);
672  cout << toUUID(u) << " " << a.abridged();
673  string s = ICAP(a).encoded();
674  cout << " " << s << string(35 - s.size(), ' ');
675  cout << " " << keyManager().accountName(a) << endl;
676  }
677  else
678  bare.push_back(u);
679  for (auto const& a: keyManager().accounts())
680  if (!got.count(a))
681  {
682  cout << " (Brain) " << a.abridged();
683  cout << " " << ICAP(a).encoded() << " ";
684  cout << " " << keyManager().accountName(a) << endl;
685  }
686  for (auto const& u: bare)
687  cout << toUUID(u) << " (Bare)" << endl;
688  }
689  default: break;
690  }
691  }
692 
693  std::string lockPassword(std::string const& _accountName)
694  {
695  return m_lock.empty() ? createPassword("Enter a passphrase with which to secure account " + _accountName + ": ") : m_lock;
696  }
697 
698  static void streamHelp(ostream& _out)
699  {
700  _out
701  << "Secret-store (\"bare\") operation modes:" << endl
702  << " listbare List all secret available in secret-store." << endl
703  << " newbare Generate and output a key without interacting with wallet and dump the JSON." << endl
704  << " importbare [ <file>|<secret-hex> , ... ] Import keys from given sources." << endl
705  << " recodebare [ <uuid>|<file> , ... ] Decrypt and re-encrypt given keys." << endl
706  << " inspectbare [ <uuid>|<file> , ... ] Output information on given keys." << endl
707 // << " exportbare [ <uuid> , ... ] Export given keys." << endl
708  << " killbare [ <uuid> , ... ] Delete given keys." << endl
709  << "Secret-store configuration:" << endl
710  << " --secrets-path <path> Specify Web3 secret-store path (default: " << SecretStore::defaultPath() << ")" << endl
711  << endl
712  << "Wallet operating modes:" << endl
713  << " createwallet Create an Ethereum master wallet." << endl
714  << " list List all keys available in wallet." << endl
715  << " new <name> Create a new key with given name and add it in the wallet." << endl
716  << " import [<uuid>|<file>|<secret-hex>] <name> Import keys from given source and place in wallet." << endl
717  << " importpresale <file> <name> Import a presale wallet into a key with the given name." << endl
718  << " importwithaddress [<uuid>|<file>|<secret-hex>] <address> <name> Import keys from given source with given address and place in wallet." << endl
719  << " export [ <address>|<uuid> , ... ] Export given keys." << endl
720  << " inspect [ <address>|<name>|<uuid>|<brainwallet> ] ... Print information on the given keys." << endl
721 // << " recode [ <address>|<uuid>|<file> , ... ] Decrypt and re-encrypt given keys." << endl
722  << " kill [ <address>|<uuid>, ... ] Delete given keys." << endl
723  << "Brain wallet operating modes:" << endl
724  << "WARNING: Brain wallets with human-generated passphrasses are highly susceptible to attack. Don't use such a thing for" << endl
725  << "anything important." << endl
726  << " newbrain [ <name>|-- ] Create a new 13-word brain wallet; argument is the name or if --, do not add to wallet." << endl
727  << " importbrain <name> Import your own brain wallet." << endl
728  << "Brainwallets are specified as: brain((#<HD-index>):<brain-phrase>), e.g. brain:PASSWORD." << endl
729  << "Wallet configuration:" << endl
730  << " --wallet-path <path> Specify Ethereum wallet path (default: " << KeyManager::defaultPath() << ")" << endl
731  << " -m, --master <passphrase> Specify wallet (master) passphrase." << endl
732  << endl
733  << "Transaction operating modes:" << endl
734  << " decode ( [ <hex>|<file> ] ) Decode given transaction." << endl
735  << " sign [ <address>|<uuid>|<file>|<brainwallet> ] ( [ <hex>|<file> , ... ] ) (Re-)Sign given transaction." << endl
736  << "Transaction specification options (to be used when no transaction hex or file is given):" << endl
737  << " --tx-dest <address> Specify the destination address for the transaction to be signed." << endl
738  << " --tx-data <hex> Specify the hex data for the transaction to be signed." << endl
739  << " --tx-nonce <n> Specify the nonce for the transaction to be signed." << endl
740  << " --tx-gas <n> Specify the gas for the transaction to be signed." << endl
741  << " --tx-gasprice <wei> Specify the gas price for the transaction to be signed." << endl
742  << " --tx-value <wei> Specify the value for the transaction to be signed." << endl
743  << "Transaction signing options:" << endl
744  << " --force-nonce <n> Override the nonce for any transactions to be signed." << endl
745  << endl
746  << "Encryption configuration:" << endl
747  << " --kdf <kdfname> Specify KDF to use when encrypting (default: sc rypt)" << endl
748  << " --kdf-param <name> <value> Specify a parameter for the KDF." << endl
749 // << " --cipher <ciphername> Specify cipher to use when encrypting (default: aes-128-ctr)" << endl
750 // << " --cipher-param <name> <value> Specify a parameter for the cipher." << endl
751  << " --lock <passphrase> Specify passphrase for when encrypting a (the) key." << endl
752  << " --hint <hint> Specify hint for the --lock passphrase." << endl
753  << endl
754  << "Decryption configuration:" << endl
755  << " --unlock <passphrase> Specify passphrase for a (the) key." << endl
756  << "Key generation configuration:" << endl
757  << " --no-icap Don't bother to make a direct-ICAP capable key." << endl
758  ;
759  }
760 
761  static bytes inputData(std::string const& _input, bool* _isFile = nullptr)
762  {
763  bytes b = fromHex(_input);
764  if (_isFile)
765  *_isFile = false;
766  if (b.empty())
767  {
768  if (_isFile)
769  *_isFile = true;
770  std::string s = boost::trim_copy_if(contentsString(_input), is_any_of(" \t\n"));
771  b = fromHex(s);
772  if (b.empty())
773  b = asBytes(s);
774  }
775  return b;
776  }
777 
778  static bool isTrue(std::string const& _m)
779  {
780  return _m == "on" || _m == "yes" || _m == "true" || _m == "1";
781  }
782 
783  static bool isFalse(std::string const& _m)
784  {
785  return _m == "off" || _m == "no" || _m == "false" || _m == "0";
786  }
787 
788 private:
790  {
791  while (true)
792  {
793  if (_w.load(m_masterPassword))
794  break;
795  if (!m_masterPassword.empty())
796  {
797  cout << "Password invalid. Try again." << endl;
798  m_masterPassword.clear();
799  }
800  m_masterPassword = getPassword("Please enter your MASTER passphrase: ");
801  }
802  }
803 
804  KDF kdf() const { return m_kdf == "pbkdf2" ? KDF::PBKDF2_SHA256 : KDF::Scrypt; }
805 
806  Address userToAddress(std::string const& _s)
807  {
808  if (h128 u = fromUUID(_s))
809  return keyManager().address(u);
810  DEV_IGNORE_EXCEPTIONS(return toAddress(_s));
811  for (Address const& a: keyManager().accounts())
812  if (keyManager().accountName(a) == _s)
813  return a;
814  return Address();
815  }
816 
817  KeyManager& keyManager(bool walletLess=false)
818  {
819  if (!m_keyManager)
820  {
821  m_keyManager.reset(new KeyManager(m_walletPath, m_secretsPath));
822  if (m_keyManager->exists())
823  openWallet(*m_keyManager);
824  else if( !walletLess )
825  {
826  cerr << "Couldn't open wallet. Does it exist?" << endl;
827  exit(-1);
828  }
829  }
830  return *m_keyManager;
831  }
832 
834  {
835  if (m_keyManager)
836  return m_keyManager->store();
837  if (!m_secretStore)
838  m_secretStore.reset(new SecretStore(m_secretsPath));
839  return *m_secretStore;
840  }
841 
843  unique_ptr<SecretStore> m_secretStore;
844  unique_ptr<KeyManager> m_keyManager;
845 
848 
850  string m_secretsPath = SecretStore::defaultPath();
851  string m_walletPath = KeyManager::defaultPath();
852 
856  string m_lock;
857  string m_lockHint;
858  bool m_icap = true;
859 
861  string m_name;
863 
865  bool m_showSecret = false;
866 
869 
871  string m_signKey;
874 
875  string m_kdf = "scrypt";
876  map<string, string> m_kdfParams;
877 // string m_cipher;
878 // map<string, string> m_cipherParams;
879 };
std::string encoded() const
Definition: ICAP.cpp:110
h128 fromUUID(std::string const &_uuid)
Definition: FixedHash.cpp:31
KeyPair makeKey() const
Definition: KeyAux.h:278
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
std::string toHex(T const &_data, int _w=2, HexPrefix _prefix=HexPrefix::DontAdd)
Definition: CommonData.h:54
vector_ref< T > ref()
Definition: Common.h:106
KeyManager & keyManager(bool walletLess=false)
Definition: KeyAux.h:817
string getAccountPassword(KeyManager &keyManager, Address const &a)
Definition: KeyAux.h:46
std::pair< Address, bytes > address(std::function< bytes(Address, bytes)> const &_call, Address const &_reg) const
Definition: ICAP.h:91
std::string const & accountName(Address const &_address) const
Definition: KeyManager.cpp:351
Secret getSecret(std::string const &_signKey)
Definition: KeyAux.h:286
strings m_unlocks
Definition: KeyAux.h:855
void writeFile(std::string const &_file, bytesConstRef _data, bool _writeDeleteRename=false)
Write the given binary data into the given file, replacing the file if it pre-exists.
Definition: CommonIO.cpp:107
static bytes inputData(std::string const &_input, bool *_isFile=nullptr)
Definition: KeyAux.h:761
void setNonce(u256 const &_n)
Sets the nonce to the given value. Clears any signature.
Definition: Transaction.h:137
Simple class that represents a "key pair".
Definition: Common.h:150
size_t count
Definition: ExecStats.cpp:37
const char * what() const noexceptoverride
Definition: Exceptions.h:42
u256 m_forceNonce
Definition: KeyAux.h:873
h160 Address
An Ethereum address: 20 bytes.
Definition: Common.h:62
Address const & sender() const
void openWallet(KeyManager &_w)
Definition: KeyAux.h:789
SecureFixedHash< 32 > Secret
Definition: Common.h:35
std::vector< std::string > strings
Definition: Common.h:147
std::hash for asio::adress
Definition: Common.h:323
std::string contentsString(std::string const &_file)
Retrieve and returns the contents of the given file as a std::string.
Address m_address
Definition: KeyAux.h:862
Secret const & secret() const
Definition: Common.h:167
vector_ref< _T > cropped(size_t _begin, size_t _count) const
Definition: vector_ref.h:62
unique_ptr< KeyManager > m_keyManager
Definition: KeyAux.h:844
void execute()
Definition: KeyAux.h:324
unique_ptr< SecretStore > m_secretStore
Where the keys are.
Definition: KeyAux.h:843
std::string const & passwordHint(Address const &_address) const
Definition: KeyManager.cpp:373
OperationMode m_mode
Operating mode.
Definition: KeyAux.h:847
SignatureStruct const & signature() const
Definition: Transaction.h:143
string m_name
Creating/importing.
Definition: KeyAux.h:861
bytes rlp(IncludeSignature _sig=WithSignature) const
Definition: Transaction.h:107
string createPassword(std::string const &_prompt)
Definition: KeyAux.h:51
#define a(i)
Do not include a signature.
Definition: Transaction.h:38
bytesConstRef ref() const
Definition: FixedHash.h:292
bool isCreation() const
Definition: Transaction.h:101
bytes fromHex(std::string const &_s, WhenError _throw=WhenError::DontThrow)
Definition: CommonData.cpp:99
Base class for all exceptions.
Definition: Exceptions.h:39
Address userToAddress(std::string const &_s)
Definition: KeyAux.h:806
string m_lockHint
Definition: KeyAux.h:857
High-level manager of password-encrypted keys for Ethereum.
Definition: KeyManager.h:72
KDF kdf() const
Definition: KeyAux.h:804
string m_masterPassword
Wallet passphrase stuff.
Definition: KeyAux.h:854
void create(std::string const &_pass)
Definition: KeyManager.cpp:56
static bool isFalse(std::string const &_m)
Definition: KeyAux.h:783
Address to() const
Synonym for receiveAddress().
Definition: Transaction.h:125
std::vector< byte > bytes
Definition: Common.h:75
h256 kdf(Secret const &_priv, h256 const &_hash)
Key derivation.
Definition: Common.cpp:322
Fixed-size raw-byte array container type, with an API optimised for storing hashes.
Definition: FixedHash.h:47
map< string, string > m_kdfParams
Definition: KeyAux.h:876
bytes const & data() const
Definition: Transaction.h:131
string m_lock
Definition: KeyAux.h:856
bytes asBytes(std::string const &_b)
Converts a string to a byte array containing the string&#39;s (byte) data.
Definition: CommonData.h:92
h256 sha3(IncludeSignature _sig=WithSignature) const
static void streamHelp(ostream &_out)
Definition: KeyAux.h:698
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void >> u256
Definition: Common.h:125
std::string formatBalance(bigint const &_b)
User-friendly string representation of the amount _b in wei.
Definition: Common.cpp:102
Address toAddress(Public const &_public)
Convert a public key to address.
Definition: Common.cpp:87
#define b(i, j)
std::vector< T > & writable()
Definition: Common.h:101
Address const & address() const
Retrieve the associated address of the public key.
Definition: Common.h:173
std::string userVisible(Address const &_a) const
Definition: KeyAux.h:322
TransactionSkeleton m_toSign
Definition: KeyAux.h:872
Address const & safeSender() const noexcept
Like sender() but will never throw.
Definition: Transaction.cpp:98
static bool isTrue(std::string const &_m)
Definition: KeyAux.h:778
Encapsulation of an ICAP address.
Definition: ICAP.h:45
#define pass(a, b, c, mul, X)
bool load(std::string const &_pass)
Definition: KeyManager.cpp:88
bool sha3(bytesConstRef _input, bytesRef o_output)
Calculate SHA3-256 hash of the given input and load it into the given output.
Definition: SHA3.cpp:214
Manages encrypted keys stored in a certain directory on disk.
Definition: SecretStore.h:46
OperationMode
Definition: KeyAux.h:92
SecretStore & secretStore()
Definition: KeyAux.h:833
std::string abridged() const
Definition: FixedHash.h:124
size_t size() const
Definition: Common.h:109
bool haveHint(std::string const &_pass) const
Definition: KeyManager.h:91
strings m_inputs
Importing.
Definition: KeyAux.h:868
std::string getPassword(std::string const &_prompt)
Requests the user to enter a password on the console.
Definition: CommonIO.cpp:135
struct evm_uint160be address(struct evm_env *env)
Definition: capi.c:13
KeyCLI(OperationMode _mode=OperationMode::None)
Definition: KeyAux.h:116
std::string lockPassword(std::string const &_accountName)
Definition: KeyAux.h:693
bytes contents(std::string const &_file)
Retrieve and returns the contents of the given file.
Definition: KeyAux.h:89
#define DEV_IGNORE_EXCEPTIONS(X)
Definition: Common.h:63
void sign(Secret const &_priv)
Sign the transaction.
Encodes a transaction, ready to be exported to or freshly imported from RLP.
Definition: Transaction.h:50
string m_signKey
Signing.
Definition: KeyAux.h:871
std::string toUUID(h128 const &_uuid)
Definition: FixedHash.cpp:43
bool interpretOption(int &i, int argc, char **argv)
Definition: KeyAux.h:118
std::string hex() const
Definition: FixedHash.h:130
std::unordered_set< h160 > AddressHash
A hash set of Ethereum addresses.
Definition: Common.h:71