Fabcoin Core  0.16.2
P2P Digital Currency
AccountManager.cpp
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
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 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
22 #include <libdevcore/SHA3.h>
23 #include <libdevcore/FileSystem.h>
24 #include <libethcore/ICAP.h>
25 #include <libethcore/KeyManager.h>
26 #include "AccountManager.h"
27 using namespace std;
28 using namespace dev;
29 using namespace dev::eth;
30 
32 {
33  _out
34  << " account list List all keys available in wallet." << endl
35  << " account new Create a new key and add it to the wallet." << endl
36  << " account update [<uuid>|<address> , ... ] Decrypt and re-encrypt given keys." << endl
37  << " account import [<uuid>|<file>|<secret-hex>] Import keys from given source and place in wallet." << endl;
38 }
39 
41 {
42  _out
43  << " wallet import <file> Import a presale wallet." << endl;
44 }
45 
46 bool AccountManager::execute(int argc, char** argv)
47 {
48  if (string(argv[1]) == "wallet")
49  {
50  if (3 < argc && string(argv[2]) == "import")
51  {
52  if (!openWallet())
53  return false;
54  string file = argv[3];
55  string name = "presale wallet";
56  string pw;
57  try
58  {
59  KeyPair k = m_keyManager->presaleSecret(
60  contentsString(file),
61  [&](bool){ return (pw = getPassword("Enter the passphrase for the presale key: "));}
62  );
63  m_keyManager->import(k.secret(), name, pw, "Same passphrase as used for presale key");
64  cout << " Address: {" << k.address().hex() << "}" << endl;
65  }
66  catch (Exception const& _e)
67  {
68  if (auto err = boost::get_error_info<errinfo_comment>(_e))
69  cout << " Decryption failed: " << *err << endl;
70  else
71  cout << " Decryption failed: Unknown reason." << endl;
72  return false;
73  }
74  }
75  else
76  streamWalletHelp(cout);
77  return true;
78  }
79  else if (string(argv[1]) == "account")
80  {
81  if (argc < 3 || string(argv[2]) == "list")
82  {
83  openWallet();
84  if (m_keyManager->store().keys().empty())
85  cout << "No keys found." << endl;
86  else
87  {
88  vector<u128> bare;
89  AddressHash got;
90  int k = 0;
91  for (auto const& u: m_keyManager->store().keys())
92  {
93  if (Address a = m_keyManager->address(u))
94  {
95  got.insert(a);
96  cout << "Account #" << k << ": {" << a.hex() << "}" << endl;
97  k++;
98  }
99  else
100  bare.push_back(u);
101  }
102  for (auto const& a: m_keyManager->accounts())
103  if (!got.count(a))
104  {
105  cout << "Account #" << k << ": {" << a.hex() << "}" << " (Brain)" << endl;
106  k++;
107  }
108  for (auto const& u: bare)
109  {
110  cout << "Account #" << k << ": " << toUUID(u) << " (Bare)" << endl;
111  k++;
112  }
113  }
114  }
115  else if (2 < argc && string(argv[2]) == "new")
116  {
117  openWallet();
118  string name;
119  string lock;
120  string lockHint;
121  lock = createPassword("Enter a passphrase with which to secure this account:");
122  auto k = makeKey();
123  h128 u = m_keyManager->import(k.secret(), name, lock, lockHint);
124  cout << "Created key " << toUUID(u) << endl;
125  cout << " ICAP: " << ICAP(k.address()).encoded() << endl;
126  cout << " Address: {" << k.address().hex() << "}" << endl;
127  }
128  else if (3 < argc && string(argv[2]) == "import")
129  {
130  openWallet();
131  h128 u = m_keyManager->store().importKey(argv[3]);
132  if (!u)
133  {
134  cerr << "Error: reading key file failed" << endl;
135  return false;
136  }
137  string pw;
138  bytesSec s = m_keyManager->store().secret(u, [&](){ return (pw = getPassword("Enter the passphrase for the key: ")); });
139  if (s.empty())
140  {
141  cerr << "Error: couldn't decode key or invalid secret size." << endl;
142  return false;
143  }
144  else
145  {
146  string lockHint;
147  string name;
148  m_keyManager->importExisting(u, name, pw, lockHint);
149  auto a = m_keyManager->address(u);
150  cout << "Imported key " << toUUID(u) << endl;
151  cout << " ICAP: " << ICAP(a).encoded() << endl;
152  cout << " Address: {" << a.hex() << "}" << endl;
153  }
154  }
155  else if (3 < argc && string(argv[2]) == "update")
156  {
157  openWallet();
158  for (int k = 3; k < argc; k++)
159  {
160  string i = argv[k];
161  h128 u = fromUUID(i);
162  if (isHex(i) || u != h128())
163  {
164  string newP = createPassword("Enter the new passphrase for the account " + i);
165  auto oldP = [&](){ return getPassword("Enter the current passphrase for the account " + i + ": "); };
166  bool recoded = false;
167  if (isHex(i))
168  {
169  recoded = m_keyManager->store().recode(
170  Address(i),
171  newP,
172  oldP,
174  );
175  }
176  else if (u != h128())
177  {
178  recoded = m_keyManager->store().recode(
179  u,
180  newP,
181  oldP,
183  );
184  }
185  if (recoded)
186  cerr << "Re-encoded " << i << endl;
187  else
188  cerr << "Couldn't re-encode " << i << "; key does not exist, corrupt or incorrect passphrase supplied." << endl;
189  }
190  else
191  cerr << "Couldn't re-encode " << i << "; does not represent an address or uuid." << endl;
192  }
193  }
194  else
195  streamAccountHelp(cout);
196  return true;
197  }
198  else
199  return false;
200 }
201 
202 string AccountManager::createPassword(string const& _prompt) const
203 {
204  string ret;
205  while (true)
206  {
207  ret = getPassword(_prompt);
208  string confirm = getPassword("Please confirm the passphrase by entering it again: ");
209  if (ret == confirm)
210  break;
211  cout << "Passwords were different. Try again." << endl;
212  }
213  return ret;
214 }
215 
217 {
218  bool icap = true;
219  KeyPair k(Secret::random());
220  while (icap && k.address()[0])
221  k = KeyPair(Secret(sha3(k.secret().ref())));
222  return k;
223 }
224 
226 {
227  if (!m_keyManager)
228  {
229  m_keyManager.reset(new KeyManager());
230  if (m_keyManager->exists())
231  {
232  if (m_keyManager->load(std::string()) || m_keyManager->load(getPassword("Please enter your MASTER passphrase: ")))
233  return true;
234  else
235  {
236  cerr << "Couldn't open wallet. Please check passphrase." << endl;
237  return false;
238  }
239  }
240  else
241  {
242  cerr << "Couldn't open wallet. Does it exist?" << endl;
243  return false;
244  }
245  }
246  return true;
247 }
std::string encoded() const
Definition: ICAP.cpp:110
h128 fromUUID(std::string const &_uuid)
Definition: FixedHash.cpp:31
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
std::pair< Address, bytes > address(std::function< bytes(Address, bytes)> const &_call, Address const &_reg) const
Definition: ICAP.h:91
static void streamWalletHelp(std::ostream &_out)
stream wallet help section
Simple class that represents a "key pair".
Definition: Common.h:150
h160 Address
An Ethereum address: 20 bytes.
Definition: Common.h:62
SecureFixedHash< 32 > Secret
Definition: Common.h:35
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.
Secret const & secret() const
Definition: Common.h:167
std::string createPassword(std::string const &_prompt) const
ask end user to create a password.
string createPassword(std::string const &_prompt)
Definition: KeyAux.h:51
#define a(i)
dev::KeyPair makeKey() const
creates a ramdom secret/address pair. It uses ICAP.
bytesConstRef ref() const
Definition: FixedHash.h:292
Base class for all exceptions.
Definition: Exceptions.h:39
static void streamAccountHelp(std::ostream &_out)
stream account help section
High-level manager of password-encrypted keys for Ethereum.
Definition: KeyManager.h:72
bool isHex(std::string const &_s) noexcept
const char * name
Definition: rest.cpp:36
Fixed-size raw-byte array container type, with an API optimised for storing hashes.
Definition: FixedHash.h:47
bool execute(int argc, char **argv)
uses argc, argv provided by the CLI and executes implemented options.
Address const & address() const
Retrieve the associated address of the public key.
Definition: Common.h:173
Encapsulation of an ICAP address.
Definition: ICAP.h:45
FixedHash< 16 > h128
Definition: FixedHash.h:342
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
std::string getPassword(std::string const &_prompt)
Requests the user to enter a password on the console.
Definition: CommonIO.cpp:135
bool openWallet()
instanciate KeyManager and open the wallet.
std::string toUUID(h128 const &_uuid)
Definition: FixedHash.cpp:43
std::string hex() const
Definition: FixedHash.h:130
bool empty() const
Definition: Common.h:110
std::unordered_set< h160 > AddressHash
A hash set of Ethereum addresses.
Definition: Common.h:71