Move signature verification functions to CPubKey.
[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             if (vchPubKey.size() == 33)
162                 key.SetCompressedPubKey();
163             if (key.GetPubKey() == vchPubKey)
164                 break;
165             return false;
166         }
167
168         vMasterKey = vMasterKeyIn;
169     }
170     NotifyStatusChanged(this);
171     return true;
172 }
173
174 bool CCryptoKeyStore::AddKey(const CKey& key)
175 {
176     {
177         LOCK(cs_KeyStore);
178
179         CScript script;
180         script.SetDestination(key.GetPubKey().GetID());
181
182         if (HaveWatchOnly(script))
183             return false;
184
185         if (!IsCrypted())
186             return CBasicKeyStore::AddKey(key);
187
188         if (IsLocked())
189             return false;
190
191         std::vector<unsigned char> vchCryptedSecret;
192         CPubKey vchPubKey = key.GetPubKey();
193         bool fCompressed;
194         if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
195             return false;
196
197         if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
198             return false;
199     }
200     return true;
201 }
202
203 bool CCryptoKeyStore::AddMalleableKey(const CMalleableKeyView& keyView, const CSecret &vchSecretH)
204 {
205     {
206         LOCK(cs_KeyStore);
207         if (!SetCrypted())
208             return CBasicKeyStore::AddMalleableKey(keyView, vchSecretH);
209
210         if (IsLocked())
211             return false;
212
213         CKey keyH;
214         keyH.SetSecret(vchSecretH, true);
215
216         std::vector<unsigned char> vchCryptedSecretH;
217         if (!EncryptSecret(vMasterKey, vchSecretH, keyH.GetPubKey().GetHash(), vchCryptedSecretH))
218             return false;
219
220         if (!AddCryptedMalleableKey(keyView, vchCryptedSecretH))
221             return false;
222     }
223     return true;
224 }
225
226 bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
227 {
228     {
229         LOCK(cs_KeyStore);
230         if (!SetCrypted())
231             return false;
232
233         mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
234     }
235     return true;
236 }
237
238 bool CCryptoKeyStore::AddCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector<unsigned char>  &vchCryptedSecretH)
239 {
240     {
241         LOCK(cs_KeyStore);
242         if (!SetCrypted())
243             return false;
244
245         mapCryptedMalleableKeys[CMalleableKeyView(keyView)] = vchCryptedSecretH;
246     }
247     return true;
248 }
249
250 bool CCryptoKeyStore::CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const
251 {
252     {
253         LOCK(cs_KeyStore);
254         if (!IsCrypted())
255             return CBasicKeyStore::CreatePrivKey(pubKeyVariant, R, privKey);
256
257         for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
258         {
259             if (mi->first.CheckKeyVariant(R, pubKeyVariant))
260             {
261                 const CPubKey H = mi->first.GetMalleablePubKey().GetH();
262
263                 CSecret vchSecretH;
264                 if (!DecryptSecret(vMasterKey, mi->second, H.GetHash(), vchSecretH))
265                     return false;
266                 if (vchSecretH.size() != 32)
267                     return false;
268
269                 CMalleableKey mKey = mi->first.GetMalleableKey(vchSecretH);
270                 return mKey.CheckKeyVariant(R, pubKeyVariant, privKey);;
271             }
272         }
273
274     }
275     return true;
276 }
277
278 bool CCryptoKeyStore::GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const
279 {
280     {
281         LOCK(cs_KeyStore);
282         if (!IsCrypted())
283             return CBasicKeyStore::GetMalleableKey(keyView, mKey);
284         CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.find(keyView);
285         if (mi != mapCryptedMalleableKeys.end())
286         {
287             const CPubKey H = keyView.GetMalleablePubKey().GetH();
288
289             CSecret vchSecretH;
290             if (!DecryptSecret(vMasterKey, mi->second, H.GetHash(), vchSecretH))
291                 return false;
292
293             if (vchSecretH.size() != 32)
294                 return false;
295             mKey = mi->first.GetMalleableKey(vchSecretH);
296
297             return true;
298         }
299     }
300     return false;
301 }
302
303 bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
304 {
305     {
306         LOCK(cs_KeyStore);
307         if (!IsCrypted())
308             return CBasicKeyStore::GetKey(address, keyOut);
309
310         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
311         if (mi != mapCryptedKeys.end())
312         {
313             const CPubKey &vchPubKey = (*mi).second.first;
314             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
315             CSecret vchSecret;
316             if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
317                 return false;
318             if (vchSecret.size() != 32)
319                 return false;
320             keyOut.SetSecret(vchSecret);
321             if (vchPubKey.size() == 33)
322                 keyOut.SetCompressedPubKey();
323             return true;
324         }
325     }
326     return false;
327 }
328
329 bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
330 {
331     {
332         LOCK(cs_KeyStore);
333         if (!IsCrypted())
334             return CKeyStore::GetPubKey(address, vchPubKeyOut);
335
336         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
337         if (mi != mapCryptedKeys.end())
338         {
339             vchPubKeyOut = (*mi).second.first;
340             return true;
341         }
342     }
343     return false;
344 }
345
346 bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
347 {
348     {
349         LOCK(cs_KeyStore);
350         if (!mapCryptedKeys.empty() || IsCrypted())
351             return false;
352
353         fUseCrypto = true;
354         BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
355         {
356             CKey key;
357             if (!key.SetSecret(mKey.second.first, mKey.second.second))
358                 return false;
359             const CPubKey vchPubKey = key.GetPubKey();
360             std::vector<unsigned char> vchCryptedSecret;
361             bool fCompressed;
362             if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
363                 return false;
364             if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
365                 return false;
366         }
367         mapKeys.clear();
368
369         BOOST_FOREACH(MalleableKeyMap::value_type& mKey, mapMalleableKeys)
370         {
371             const CPubKey vchPubKeyH = mKey.first.GetMalleablePubKey().GetH();
372             std::vector<unsigned char> vchCryptedSecretH;
373             if (!EncryptSecret(vMasterKeyIn, mKey.second, vchPubKeyH.GetHash(), vchCryptedSecretH))
374                 return false;
375             if (!AddCryptedMalleableKey(mKey.first, vchCryptedSecretH))
376                 return false;
377         }
378         mapMalleableKeys.clear();
379     }
380     return true;
381 }
382
383 bool CCryptoKeyStore::DecryptKeys(const CKeyingMaterial& vMasterKeyIn)
384 {
385     {
386         LOCK(cs_KeyStore);
387         if (!IsCrypted())
388             return false;
389
390         CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
391         for (; mi != mapCryptedKeys.end(); ++mi)
392         {
393             const CPubKey &vchPubKey = (*mi).second.first;
394             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
395             CSecret vchSecret;
396             if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
397                 return false;
398             if (vchSecret.size() != 32)
399                 return false;
400             CKey key;
401             key.SetSecret(vchSecret);
402             if (vchPubKey.size() == 33)
403                 key.SetCompressedPubKey();
404             if (!CBasicKeyStore::AddKey(key))
405                 return false;
406         }
407
408         mapCryptedKeys.clear();
409
410         CryptedMalleableKeyMap::const_iterator mi2 = mapCryptedMalleableKeys.begin();
411         for(; mi2 != mapCryptedMalleableKeys.end(); ++mi2)
412         {
413             const CPubKey vchPubKeyH = mi2->first.GetMalleablePubKey().GetH();
414
415             CSecret vchSecretH;
416             if(!DecryptSecret(vMasterKeyIn, mi2->second, vchPubKeyH.GetHash(), vchSecretH))
417                 return false;
418             if (vchSecretH.size() != 32)
419                 return false;
420
421             if (!CBasicKeyStore::AddMalleableKey(mi2->first, vchSecretH))
422                 return false;
423         }
424         mapCryptedMalleableKeys.clear();
425     }
426
427     return true;
428 }