KeyAux.h 29 KB

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