AccountManager.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. This file is part of cpp-ethereum.
  3. cpp-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. cpp-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /** @file AccountManager.cpp
  15. * @author Yann <yann@ethdev.com>
  16. * @date 2016
  17. */
  18. #include <libdevcore/SHA3.h>
  19. #include <libdevcore/FileSystem.h>
  20. #include <libethcore/ICAP.h>
  21. #include <libethcore/KeyManager.h>
  22. #include "AccountManager.h"
  23. using namespace std;
  24. using namespace dev;
  25. using namespace dev::eth;
  26. void AccountManager::streamAccountHelp(ostream& _out)
  27. {
  28. _out
  29. << " account list List all keys available in wallet." << endl
  30. << " account new Create a new key and add it to the wallet." << endl
  31. << " account update [<uuid>|<address> , ... ] Decrypt and re-encrypt given keys." << endl
  32. << " account import [<uuid>|<file>|<secret-hex>] Import keys from given source and place in wallet." << endl;
  33. }
  34. void AccountManager::streamWalletHelp(ostream& _out)
  35. {
  36. _out
  37. << " wallet import <file> Import a presale wallet." << endl;
  38. }
  39. bool AccountManager::execute(int argc, char** argv)
  40. {
  41. if (string(argv[1]) == "wallet")
  42. {
  43. if (3 < argc && string(argv[2]) == "import")
  44. {
  45. if (!openWallet())
  46. return false;
  47. string file = argv[3];
  48. string name = "presale wallet";
  49. string pw;
  50. KeyPair k;
  51. try
  52. {
  53. k = m_keyManager->presaleSecret(
  54. contentsString(file),
  55. [&](bool){ return (pw = getPassword("Enter the passphrase for the presale key: "));}
  56. );
  57. }
  58. catch (Exception const& _e)
  59. {
  60. if (auto err = boost::get_error_info<errinfo_comment>(_e))
  61. cout << " Decryption failed: " << *err << endl;
  62. else
  63. cout << " Decryption failed: Unknown reason." << endl;
  64. return false;
  65. }
  66. m_keyManager->import(k.secret(), name, pw, "Same passphrase as used for presale key");
  67. cout << " Address: {" << k.address().hex() << "}" << endl;
  68. }
  69. else
  70. streamWalletHelp(cout);
  71. return true;
  72. }
  73. else if (string(argv[1]) == "account")
  74. {
  75. if (argc < 3 || string(argv[2]) == "list")
  76. {
  77. openWallet();
  78. if (m_keyManager->store().keys().empty())
  79. cout << "No keys found." << endl;
  80. else
  81. {
  82. vector<u128> bare;
  83. AddressHash got;
  84. int k = 0;
  85. for (auto const& u: m_keyManager->store().keys())
  86. {
  87. if (Address a = m_keyManager->address(u))
  88. {
  89. got.insert(a);
  90. cout << "Account #" << k << ": {" << a.hex() << "}" << endl;
  91. k++;
  92. }
  93. else
  94. bare.push_back(u);
  95. }
  96. for (auto const& a: m_keyManager->accounts())
  97. if (!got.count(a))
  98. {
  99. cout << "Account #" << k << ": {" << a.hex() << "}" << " (Brain)" << endl;
  100. k++;
  101. }
  102. for (auto const& u: bare)
  103. {
  104. cout << "Account #" << k << ": " << toUUID(u) << " (Bare)" << endl;
  105. k++;
  106. }
  107. }
  108. }
  109. else if (2 < argc && string(argv[2]) == "new")
  110. {
  111. openWallet();
  112. string name;
  113. string lock;
  114. string lockHint;
  115. lock = createPassword("Enter a passphrase with which to secure this account:");
  116. auto k = makeKey();
  117. h128 u = m_keyManager->import(k.secret(), name, lock, lockHint);
  118. cout << "Created key " << toUUID(u) << endl;
  119. cout << " ICAP: " << ICAP(k.address()).encoded() << endl;
  120. cout << " Address: {" << k.address().hex() << "}" << endl;
  121. }
  122. else if (3 < argc && string(argv[2]) == "import")
  123. {
  124. openWallet();
  125. h128 u = m_keyManager->store().importKey(argv[3]);
  126. if (!u)
  127. {
  128. cerr << "Error: reading key file failed" << endl;
  129. return false;
  130. }
  131. string pw;
  132. bytesSec s = m_keyManager->store().secret(u, [&](){ return (pw = getPassword("Enter the passphrase for the key: ")); });
  133. if (s.empty())
  134. {
  135. cerr << "Error: couldn't decode key or invalid secret size." << endl;
  136. return false;
  137. }
  138. else
  139. {
  140. string lockHint;
  141. string name;
  142. m_keyManager->importExisting(u, name, pw, lockHint);
  143. auto a = m_keyManager->address(u);
  144. cout << "Imported key " << toUUID(u) << endl;
  145. cout << " ICAP: " << ICAP(a).encoded() << endl;
  146. cout << " Address: {" << a.hex() << "}" << endl;
  147. }
  148. }
  149. else if (3 < argc && string(argv[2]) == "update")
  150. {
  151. openWallet();
  152. for (int k = 3; k < argc; k++)
  153. {
  154. string i = argv[k];
  155. h128 u = fromUUID(i);
  156. if (isHex(i) || u != h128())
  157. {
  158. string newP = createPassword("Enter the new passphrase for the account " + i);
  159. auto oldP = [&](){ return getPassword("Enter the current passphrase for the account " + i + ": "); };
  160. bool recoded = false;
  161. if (isHex(i))
  162. {
  163. recoded = m_keyManager->store().recode(
  164. Address(i),
  165. newP,
  166. oldP,
  167. dev::KDF::Scrypt
  168. );
  169. }
  170. else if (u != h128())
  171. {
  172. recoded = m_keyManager->store().recode(
  173. u,
  174. newP,
  175. oldP,
  176. dev::KDF::Scrypt
  177. );
  178. }
  179. if (recoded)
  180. cerr << "Re-encoded " << i << endl;
  181. else
  182. cerr << "Couldn't re-encode " << i << "; key does not exist, corrupt or incorrect passphrase supplied." << endl;
  183. }
  184. else
  185. cerr << "Couldn't re-encode " << i << "; does not represent an address or uuid." << endl;
  186. }
  187. }
  188. else
  189. streamAccountHelp(cout);
  190. return true;
  191. }
  192. else
  193. return false;
  194. }
  195. string AccountManager::createPassword(string const& _prompt) const
  196. {
  197. string ret;
  198. while (true)
  199. {
  200. ret = getPassword(_prompt);
  201. string confirm = getPassword("Please confirm the passphrase by entering it again: ");
  202. if (ret == confirm)
  203. break;
  204. cout << "Passwords were different. Try again." << endl;
  205. }
  206. return ret;
  207. }
  208. KeyPair AccountManager::makeKey() const
  209. {
  210. bool icap = true;
  211. KeyPair k(Secret::random());
  212. while (icap && k.address()[0])
  213. k = KeyPair(Secret(sha3(k.secret().ref())));
  214. return k;
  215. }
  216. bool AccountManager::openWallet()
  217. {
  218. if (!m_keyManager)
  219. {
  220. m_keyManager.reset(new KeyManager());
  221. if (m_keyManager->exists())
  222. {
  223. if (m_keyManager->load(std::string()) || m_keyManager->load(getPassword("Please enter your MASTER passphrase: ")))
  224. return true;
  225. else
  226. {
  227. cerr << "Couldn't open wallet. Please check passphrase." << endl;
  228. return false;
  229. }
  230. }
  231. else
  232. {
  233. cerr << "Couldn't open wallet. Does it exist?" << endl;
  234. return false;
  235. }
  236. }
  237. return true;
  238. }