]> Git Repo - VerusCoin.git/blame - src/wallet-utility.cpp
Merge pull request #646 from jl777/jl777
[VerusCoin.git] / src / wallet-utility.cpp
CommitLineData
8b78a819
T
1#include <iostream>
2#include <string>
3
4// Include local headers
5#include "wallet/walletdb.h"
6#include "util.h"
7#include "base58.h"
8#include "wallet/crypter.h"
9#include <boost/foreach.hpp>
10
60eafafa 11#include "komodo_defs.h"
12char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
13int64_t MAX_MONEY = 200000000 * 100000000LL;
6e0857ce 14uint64_t ASSETCHAINS_SUPPLY;
05c2ba63 15uint16_t BITCOIND_RPCPORT = 7771;
16uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
6e0857ce 17uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC;
18uint32_t ASSETCHAINS_MAGIC = 2387029918;
5725f8ea 19unsigned int MAX_BLOCK_SIGOPS = 20000;
8b78a819
T
20
21void show_help()
22{
23 std::cout <<
24 "This program outputs Bitcoin addresses and private keys from a wallet.dat file" << std::endl
25 << std::endl
26 << "Usage and options: "
27 << std::endl
28 << " -datadir=<directory> to tell the program where your wallet is"
29 << std::endl
30 << " -wallet=<name> (Optional) if your wallet is not named wallet.dat"
31 << std::endl
32 << " -regtest or -testnet (Optional) dumps addresses from regtest/testnet"
33 << std::endl
34 << " -dumppass (Optional)if you want to extract private keys associated with addresses"
35 << std::endl
36 << " -pass=<walletpassphrase> if you have encrypted private keys stored in your wallet"
37 << std::endl;
38}
39
40
41class WalletUtilityDB : public CDB
42{
43 private:
44 typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
45 MasterKeyMap mapMasterKeys;
46 unsigned int nMasterKeyMaxID;
47 SecureString mPass;
48 std::vector<CKeyingMaterial> vMKeys;
49
50 public:
51 WalletUtilityDB(const std::string& strFilename, const char* pszMode = "r+", bool fFlushOnClose = true) : CDB(strFilename, pszMode, fFlushOnClose)
52 {
53 nMasterKeyMaxID = 0;
54 mPass.reserve(100);
55 }
56
57 std::string getAddress(CDataStream ssKey);
58 std::string getKey(CDataStream ssKey, CDataStream ssValue);
59 std::string getCryptedKey(CDataStream ssKey, CDataStream ssValue, std::string masterPass);
60 bool updateMasterKeys(CDataStream ssKey, CDataStream ssValue);
61 bool parseKeys(bool dumppriv, std::string masterPass);
62
63 bool DecryptSecret(const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext);
64 bool Unlock();
65 bool DecryptKey(const std::vector<unsigned char>& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key);
66};
67
68
69/*
70 * Address from a public key in base58
71 */
72std::string WalletUtilityDB::getAddress(CDataStream ssKey)
73{
74 CPubKey vchPubKey;
75 ssKey >> vchPubKey;
76 CKeyID id = vchPubKey.GetID();
77 std::string strAddr = CBitcoinAddress(id).ToString();
78
79 return strAddr;
80}
81
82
83/*
84 * Non encrypted private key in WIF
85 */
86std::string WalletUtilityDB::getKey(CDataStream ssKey, CDataStream ssValue)
87{
88 std::string strKey;
89 CPubKey vchPubKey;
90 ssKey >> vchPubKey;
91 CPrivKey pkey;
92 CKey key;
93
94 ssValue >> pkey;
95 if (key.Load(pkey, vchPubKey, true))
96 strKey = CBitcoinSecret(key).ToString();
97
98 return strKey;
99}
100
101
102bool WalletUtilityDB::DecryptSecret(const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext)
103{
104 CCrypter cKeyCrypter;
105 std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE);
106 memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE);
107
108 BOOST_FOREACH(const CKeyingMaterial vMKey, vMKeys)
109 {
110 if(!cKeyCrypter.SetKey(vMKey, chIV))
111 continue;
112 if (cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext)))
113 return true;
114 }
115 return false;
116}
117
118
119bool WalletUtilityDB::Unlock()
120{
121 CCrypter crypter;
122 CKeyingMaterial vMasterKey;
123
124 BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
125 {
126 if(!crypter.SetKeyFromPassphrase(mPass, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
127 return false;
128 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
129 continue; // try another master key
130 vMKeys.push_back(vMasterKey);
131 }
132 return true;
133}
134
135
136bool WalletUtilityDB::DecryptKey(const std::vector<unsigned char>& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key)
137{
138 CKeyingMaterial vchSecret;
139 if(!DecryptSecret(vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
140 return false;
141
142 if (vchSecret.size() != 32)
143 return false;
144
145 key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
146 return true;
147}
148
149
150/*
151 * Encrypted private key in WIF format
152 */
153std::string WalletUtilityDB::getCryptedKey(CDataStream ssKey, CDataStream ssValue, std::string masterPass)
154{
155 mPass = masterPass.c_str();
156 CPubKey vchPubKey;
157 ssKey >> vchPubKey;
158 CKey key;
159
160 std::vector<unsigned char> vKey;
161 ssValue >> vKey;
162
163 if (!Unlock())
164 return "";
165
166 if(!DecryptKey(vKey, vchPubKey, key))
167 return "";
168
169 std::string strKey = CBitcoinSecret(key).ToString();
170 return strKey;
171}
172
173
174/*
175 * Master key derivation
176 */
177bool WalletUtilityDB::updateMasterKeys(CDataStream ssKey, CDataStream ssValue)
178{
179 unsigned int nID;
180 ssKey >> nID;
181 CMasterKey kMasterKey;
182 ssValue >> kMasterKey;
183 if (mapMasterKeys.count(nID) != 0)
184 {
185 std::cout << "Error reading wallet database: duplicate CMasterKey id " << nID << std::endl;
186 return false;
187 }
188 mapMasterKeys[nID] = kMasterKey;
189
190 if (nMasterKeyMaxID < nID)
191 nMasterKeyMaxID = nID;
192
193 return true;
194}
195
196
197/*
198 * Look at all the records and parse keys for addresses and private keys
199 */
200bool WalletUtilityDB::parseKeys(bool dumppriv, std::string masterPass)
201{
202 DBErrors result = DB_LOAD_OK;
203 std::string strType;
204 bool first = true;
205
206 try {
207 Dbc* pcursor = GetCursor();
208 if (!pcursor)
209 {
210 LogPrintf("Error getting wallet database cursor\n");
211 result = DB_CORRUPT;
212 }
213
214 if (dumppriv)
215 {
216 while (result == DB_LOAD_OK && true)
217 {
218 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
219 CDataStream ssValue(SER_DISK, CLIENT_VERSION);
220 int result = ReadAtCursor(pcursor, ssKey, ssValue);
221
222 if (result == DB_NOTFOUND) {
223 break;
224 }
225 else if (result != 0)
226 {
227 LogPrintf("Error reading next record from wallet database\n");
228 result = DB_CORRUPT;
229 break;
230 }
231
232 ssKey >> strType;
233 if (strType == "mkey")
234 {
235 updateMasterKeys(ssKey, ssValue);
236 }
237 }
238 pcursor->close();
239 pcursor = GetCursor();
240 }
241
242 while (result == DB_LOAD_OK && true)
243 {
244 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
245 CDataStream ssValue(SER_DISK, CLIENT_VERSION);
246 int ret = ReadAtCursor(pcursor, ssKey, ssValue);
247
248 if (ret == DB_NOTFOUND)
249 {
250 std::cout << " ]" << std::endl;
251 first = true;
252 break;
253 }
254 else if (ret != DB_LOAD_OK)
255 {
256 LogPrintf("Error reading next record from wallet database\n");
257 result = DB_CORRUPT;
258 break;
259 }
260
261 ssKey >> strType;
262
263 if (strType == "key" || strType == "ckey")
264 {
265 std::string strAddr = getAddress(ssKey);
266 std::string strKey = "";
267
268
269 if (dumppriv && strType == "key")
270 strKey = getKey(ssKey, ssValue);
271 if (dumppriv && strType == "ckey")
272 {
273 if (masterPass == "")
274 {
275 std::cout << "Encrypted wallet, please provide a password. See help below" << std::endl;
276 show_help();
277 result = DB_LOAD_FAIL;
278 break;
279 }
280 strKey = getCryptedKey(ssKey, ssValue, masterPass);
281 }
282
283 if (strAddr != "")
284 {
285 if (first)
286 std::cout << "[ ";
287 else
288 std::cout << ", ";
289 }
290
291 if (dumppriv)
292 {
293 std::cout << "{\"addr\" : \"" + strAddr + "\", "
294 << "\"pkey\" : \"" + strKey + "\"}"
295 << std::flush;
296 }
297 else
298 {
299 std::cout << "\"" + strAddr + "\"";
300 }
301
302 first = false;
303 }
304 }
305
306 pcursor->close();
307 } catch (DbException &e) {
308 std::cout << "DBException caught " << e.get_errno() << std::endl;
309 } catch (std::exception &e) {
310 std::cout << "Exception caught " << std::endl;
311 }
312
313 if (result == DB_LOAD_OK)
314 return true;
315 else
316 return false;
317}
318
319
320int main(int argc, char* argv[])
321{
322 ParseParameters(argc, argv);
323 std::string walletFile = GetArg("-wallet", "wallet.dat");
324 std::string masterPass = GetArg("-pass", "");
325 bool fDumpPass = GetBoolArg("-dumppass", false);
326 bool help = GetBoolArg("-h", false);
327 bool result = false;
328
329 if (help)
330 {
331 show_help();
332 return 0;
333 }
334
335 try {
336 SelectParamsFromCommandLine();
337 result = WalletUtilityDB(walletFile, "r").parseKeys(fDumpPass, masterPass);
338 }
339 catch (const std::exception& e) {
340 std::cout << "Error opening wallet file " << walletFile << std::endl;
341 std::cout << e.what() << std::endl;
342 }
343
344 if (result)
345 return 0;
346 else
347 return -1;
e8972fab 348}
This page took 0.076604 seconds and 4 git commands to generate.