Bump version to 0.5.9
[novacoin.git] / src / keystore.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "keystore.h"
7 #include "script.h"
8 #include "base58.h"
9
10 extern bool fWalletUnlockMintOnly;
11
12 bool CKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
13 {
14     CKey key;
15     if (!GetKey(address, key))
16         return false;
17     vchPubKeyOut = key.GetPubKey();
18     return true;
19 }
20
21 bool CBasicKeyStore::AddKey(const CKey& key)
22 {
23     bool fCompressed = false;
24     CSecret secret = key.GetSecret(fCompressed);
25     {
26         LOCK(cs_KeyStore);
27         mapKeys[key.GetPubKey().GetID()] = make_pair(secret, fCompressed);
28     }
29     return true;
30 }
31
32 bool CBasicKeyStore::AddMalleableKey(const CMalleableKeyView& keyView, const CSecret& vchSecretH)
33 {
34     {
35         LOCK(cs_KeyStore);
36         mapMalleableKeys[CMalleableKeyView(keyView)] = vchSecretH;
37     }
38     return true;
39 }
40
41 bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
42 {
43     if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
44         return error("CBasicKeyStore::AddCScript() : redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE);
45
46     {
47         LOCK(cs_KeyStore);
48         mapScripts[redeemScript.GetID()] = redeemScript;
49     }
50     return true;
51 }
52
53 bool CBasicKeyStore::HaveCScript(const CScriptID& hash) const
54 {
55     bool result;
56     {
57         LOCK(cs_KeyStore);
58         result = (mapScripts.count(hash) > 0);
59     }
60     return result;
61 }
62
63
64 bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const
65 {
66     {
67         LOCK(cs_KeyStore);
68         ScriptMap::const_iterator mi = mapScripts.find(hash);
69         if (mi != mapScripts.end())
70         {
71             redeemScriptOut = (*mi).second;
72             return true;
73         }
74     }
75     return false;
76 }
77
78 bool CBasicKeyStore::AddWatchOnly(const CScript &dest)
79 {
80     LOCK(cs_KeyStore);
81
82     CTxDestination address;
83     if (ExtractDestination(dest, address)) {
84         CKeyID keyID;
85         CBitcoinAddress(address).GetKeyID(keyID);
86         if (HaveKey(keyID))
87             return false;
88     }
89
90     setWatchOnly.insert(dest);
91     return true;
92 }
93
94
95 bool CBasicKeyStore::RemoveWatchOnly(const CScript &dest)
96 {
97     LOCK(cs_KeyStore);
98     setWatchOnly.erase(dest);
99     return true;
100 }
101
102 bool CBasicKeyStore::HaveWatchOnly(const CScript &dest) const
103 {
104     LOCK(cs_KeyStore);
105     return setWatchOnly.count(dest) > 0;
106 }
107
108 bool CBasicKeyStore::HaveWatchOnly() const
109 {
110     LOCK(cs_KeyStore);
111     return (!setWatchOnly.empty());
112 }
113
114 bool CCryptoKeyStore::SetCrypted()
115 {
116     {
117         LOCK(cs_KeyStore);
118         if (fUseCrypto)
119             return true;
120         if (!mapKeys.empty())
121             return false;
122         fUseCrypto = true;
123     }
124     return true;
125 }
126
127 bool CCryptoKeyStore::Lock()
128 {
129     if (!SetCrypted())
130         return false;
131
132     {
133         LOCK(cs_KeyStore);
134         vMasterKey.clear();
135         fWalletUnlockMintOnly = false;
136     }
137
138     NotifyStatusChanged(this);
139     return true;
140 }
141
142 bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
143 {
144     {
145         LOCK(cs_KeyStore);
146         if (!SetCrypted())
147             return false;
148
149         CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
150         for (; mi != mapCryptedKeys.end(); ++mi)
151         {
152             const CPubKey &vchPubKey = (*mi).second.first;
153             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
154             CSecret vchSecret;
155             if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
156                 return false;
157             if (vchSecret.size() != 32)
158                 return false;
159             CKey key;
160             key.SetSecret(vchSecret);
161             key.SetCompressedPubKey(vchPubKey.IsCompressed());
162             if (key.GetPubKey() == vchPubKey)
163                 break;
164             return false;
165         }
166
167         vMasterKey = vMasterKeyIn;
168     }
169     NotifyStatusChanged(this);
170     return true;
171 }
172
173 bool CCryptoKeyStore::AddKey(const CKey& key)
174 {
175     {
176         LOCK(cs_KeyStore);
177
178         CScript script;
179         script.SetDestination(key.GetPubKey().GetID());
180
181         if (HaveWatchOnly(script))
182             return false;
183
184         if (!IsCrypted())
185             return CBasicKeyStore::AddKey(key);
186
187         if (IsLocked())
188             return false;
189
190         std::vector<unsigned char> vchCryptedSecret;
191         CPubKey vchPubKey = key.GetPubKey();
192         bool fCompressed;
193         if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
194             return false;
195
196         if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
197             return false;
198     }
199     return true;
200 }
201
202 bool CCryptoKeyStore::AddMalleableKey(const CMalleableKeyView& keyView, const CSecret &vchSecretH)
203 {
204     {
205         LOCK(cs_KeyStore);
206         if (!SetCrypted())
207             return CBasicKeyStore::AddMalleableKey(keyView, vchSecretH);
208
209         if (IsLocked())
210             return false;
211
212         CKey keyH;
213         keyH.SetSecret(vchSecretH, true);
214
215         std::vector<unsigned char> vchCryptedSecretH;
216         if (!EncryptSecret(vMasterKey, vchSecretH, keyH.GetPubKey().GetHash(), vchCryptedSecretH))
217             return false;
218
219         if (!AddCryptedMalleableKey(keyView, vchCryptedSecretH))
220             return false;
221     }
222     return true;
223 }
224
225 bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
226 {
227     {
228         LOCK(cs_KeyStore);
229         if (!SetCrypted())
230             return false;
231
232         mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
233     }
234     return true;
235 }
236
237 bool CCryptoKeyStore::AddCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector<unsigned char>  &vchCryptedSecretH)
238 {
239     {
240         LOCK(cs_KeyStore);
241         if (!SetCrypted())
242             return false;
243
244         mapCryptedMalleableKeys[CMalleableKeyView(keyView)] = vchCryptedSecretH;
245     }
246     return true;
247 }
248
249 bool CCryptoKeyStore::CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const
250 {
251     {
252         LOCK(cs_KeyStore);
253         if (!IsCrypted())
254             return CBasicKeyStore::CreatePrivKey(pubKeyVariant, R, privKey);
255
256         for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
257         {
258             if (mi->first.CheckKeyVariant(R, pubKeyVariant))
259             {
260                 const CPubKey H = mi->first.GetMalleablePubKey().GetH();
261
262                 CSecret vchSecretH;
263                 if (!DecryptSecret(vMasterKey, mi->second, H.GetHash(), vchSecretH))
264                     return false;
265                 if (vchSecretH.size() != 32)
266                     return false;
267
268                 CMalleableKey mKey = mi->first.GetMalleableKey(vchSecretH);
269                 return mKey.CheckKeyVariant(R, pubKeyVariant, privKey);;
270             }
271         }
272
273     }
274     return true;
275 }
276
277 bool CCryptoKeyStore::GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const
278 {
279     {
280         LOCK(cs_KeyStore);
281         if (!IsCrypted())
282             return CBasicKeyStore::GetMalleableKey(keyView, mKey);
283         CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.find(keyView);
284         if (mi != mapCryptedMalleableKeys.end())
285         {
286             const CPubKey H = keyView.GetMalleablePubKey().GetH();
287
288             CSecret vchSecretH;
289             if (!DecryptSecret(vMasterKey, mi->second, H.GetHash(), vchSecretH))
290                 return false;
291
292             if (vchSecretH.size() != 32)
293                 return false;
294             mKey = mi->first.GetMalleableKey(vchSecretH);
295
296             return true;
297         }
298     }
299     return false;
300 }
301
302 bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
303 {
304     {
305         LOCK(cs_KeyStore);
306         if (!IsCrypted())
307             return CBasicKeyStore::GetKey(address, keyOut);
308
309         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
310         if (mi != mapCryptedKeys.end())
311         {
312             const CPubKey &vchPubKey = (*mi).second.first;
313             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
314             CSecret vchSecret;
315             if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
316                 return false;
317             if (vchSecret.size() != 32)
318                 return false;
319             keyOut.SetSecret(vchSecret);
320             keyOut.SetCompressedPubKey(vchPubKey.IsCompressed());
321             return true;
322         }
323     }
324     return false;
325 }
326
327 bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
328 {
329     {
330         LOCK(cs_KeyStore);
331         if (!IsCrypted())
332             return CKeyStore::GetPubKey(address, vchPubKeyOut);
333
334         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
335         if (mi != mapCryptedKeys.end())
336         {
337             vchPubKeyOut = (*mi).second.first;
338             return true;
339         }
340     }
341     return false;
342 }
343
344 bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
345 {
346     {
347         LOCK(cs_KeyStore);
348         if (!mapCryptedKeys.empty() || IsCrypted())
349             return false;
350
351         fUseCrypto = true;
352         BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
353         {
354             CKey key;
355             if (!key.SetSecret(mKey.second.first, mKey.second.second))
356                 return false;
357             const CPubKey vchPubKey = key.GetPubKey();
358             std::vector<unsigned char> vchCryptedSecret;
359             bool fCompressed;
360             if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
361                 return false;
362             if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
363                 return false;
364         }
365         mapKeys.clear();
366
367         BOOST_FOREACH(MalleableKeyMap::value_type& mKey, mapMalleableKeys)
368         {
369             const CPubKey vchPubKeyH = mKey.first.GetMalleablePubKey().GetH();
370             std::vector<unsigned char> vchCryptedSecretH;
371             if (!EncryptSecret(vMasterKeyIn, mKey.second, vchPubKeyH.GetHash(), vchCryptedSecretH))
372                 return false;
373             if (!AddCryptedMalleableKey(mKey.first, vchCryptedSecretH))
374                 return false;
375         }
376         mapMalleableKeys.clear();
377     }
378     return true;
379 }
380
381 bool CCryptoKeyStore::DecryptKeys(const CKeyingMaterial& vMasterKeyIn)
382 {
383     {
384         LOCK(cs_KeyStore);
385         if (!IsCrypted())
386             return false;
387
388         CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
389         for (; mi != mapCryptedKeys.end(); ++mi)
390         {
391             const CPubKey &vchPubKey = (*mi).second.first;
392             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
393             CSecret vchSecret;
394             if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
395                 return false;
396             if (vchSecret.size() != 32)
397                 return false;
398             CKey key;
399             key.SetSecret(vchSecret);
400             key.SetCompressedPubKey(vchPubKey.IsCompressed());
401             if (!CBasicKeyStore::AddKey(key))
402                 return false;
403         }
404
405         mapCryptedKeys.clear();
406
407         CryptedMalleableKeyMap::const_iterator mi2 = mapCryptedMalleableKeys.begin();
408         for(; mi2 != mapCryptedMalleableKeys.end(); ++mi2)
409         {
410             const CPubKey vchPubKeyH = mi2->first.GetMalleablePubKey().GetH();
411
412             CSecret vchSecretH;
413             if(!DecryptSecret(vMasterKeyIn, mi2->second, vchPubKeyH.GetHash(), vchSecretH))
414                 return false;
415             if (vchSecretH.size() != 32)
416                 return false;
417
418             if (!CBasicKeyStore::AddMalleableKey(mi2->first, vchSecretH))
419                 return false;
420         }
421         mapCryptedMalleableKeys.clear();
422     }
423
424     return true;
425 }