Update License in File Headers
[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 "headers.h"
7 #include "crypter.h"
8 #include "db.h"
9 #include "script.h"
10
11 bool CKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char> &vchPubKeyOut) const
12 {
13     CKey key;
14     if (!GetKey(address, key))
15         return false;
16     vchPubKeyOut = key.GetPubKey();
17     return true;
18 }
19
20 bool CBasicKeyStore::AddKey(const CKey& key)
21 {
22     bool fCompressed = false;
23     CSecret secret = key.GetSecret(fCompressed);
24     CRITICAL_BLOCK(cs_KeyStore)
25         mapKeys[CBitcoinAddress(key.GetPubKey())] = make_pair(secret, fCompressed);
26     return true;
27 }
28
29 bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
30 {
31     CRITICAL_BLOCK(cs_KeyStore)
32         mapScripts[Hash160(redeemScript)] = redeemScript;
33     return true;
34 }
35
36 bool CBasicKeyStore::HaveCScript(const uint160& hash) const
37 {
38     bool result;
39     CRITICAL_BLOCK(cs_KeyStore)
40         result = (mapScripts.count(hash) > 0);
41     return result;
42 }
43
44
45 bool CBasicKeyStore::GetCScript(const uint160 &hash, CScript& redeemScriptOut) const
46 {
47     CRITICAL_BLOCK(cs_KeyStore)
48     {
49         ScriptMap::const_iterator mi = mapScripts.find(hash);
50         if (mi != mapScripts.end())
51         {
52             redeemScriptOut = (*mi).second;
53             return true;
54         }
55     }
56     return false;
57 }
58
59 bool CCryptoKeyStore::SetCrypted()
60 {
61     CRITICAL_BLOCK(cs_KeyStore)
62     {
63         if (fUseCrypto)
64             return true;
65         if (!mapKeys.empty())
66             return false;
67         fUseCrypto = true;
68     }
69     return true;
70 }
71
72 bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
73 {
74     CRITICAL_BLOCK(cs_KeyStore)
75     {
76         if (!SetCrypted())
77             return false;
78
79         CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
80         for (; mi != mapCryptedKeys.end(); ++mi)
81         {
82             const std::vector<unsigned char> &vchPubKey = (*mi).second.first;
83             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
84             CSecret vchSecret;
85             if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
86                 return false;
87             if (vchSecret.size() != 32)
88                 return false;
89             CKey key;
90             key.SetPubKey(vchPubKey);
91             key.SetSecret(vchSecret);
92             if (key.GetPubKey() == vchPubKey)
93                 break;
94             return false;
95         }
96         vMasterKey = vMasterKeyIn;
97     }
98     return true;
99 }
100
101 bool CCryptoKeyStore::AddKey(const CKey& key)
102 {
103     CRITICAL_BLOCK(cs_KeyStore)
104     {
105         if (!IsCrypted())
106             return CBasicKeyStore::AddKey(key);
107
108         if (IsLocked())
109             return false;
110
111         std::vector<unsigned char> vchCryptedSecret;
112         std::vector<unsigned char> vchPubKey = key.GetPubKey();
113         bool fCompressed;
114         if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
115             return false;
116
117         if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
118             return false;
119     }
120     return true;
121 }
122
123
124 bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
125 {
126     CRITICAL_BLOCK(cs_KeyStore)
127     {
128         if (!SetCrypted())
129             return false;
130
131         mapCryptedKeys[CBitcoinAddress(vchPubKey)] = make_pair(vchPubKey, vchCryptedSecret);
132     }
133     return true;
134 }
135
136 bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
137 {
138     CRITICAL_BLOCK(cs_KeyStore)
139     {
140         if (!IsCrypted())
141             return CBasicKeyStore::GetKey(address, keyOut);
142
143         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
144         if (mi != mapCryptedKeys.end())
145         {
146             const std::vector<unsigned char> &vchPubKey = (*mi).second.first;
147             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
148             CSecret vchSecret;
149             if (!DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
150                 return false;
151             if (vchSecret.size() != 32)
152                 return false;
153             keyOut.SetPubKey(vchPubKey);
154             keyOut.SetSecret(vchSecret);
155             return true;
156         }
157     }
158     return false;
159 }
160
161 bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const
162 {
163     CRITICAL_BLOCK(cs_KeyStore)
164     {
165         if (!IsCrypted())
166             return CKeyStore::GetPubKey(address, vchPubKeyOut);
167
168         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
169         if (mi != mapCryptedKeys.end())
170         {
171             vchPubKeyOut = (*mi).second.first;
172             return true;
173         }
174     }
175     return false;
176 }
177
178 bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
179 {
180     CRITICAL_BLOCK(cs_KeyStore)
181     {
182         if (!mapCryptedKeys.empty() || IsCrypted())
183             return false;
184
185         fUseCrypto = true;
186         BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
187         {
188             CKey key;
189             if (!key.SetSecret(mKey.second.first, mKey.second.second))
190                 return false;
191             const std::vector<unsigned char> vchPubKey = key.GetPubKey();
192             std::vector<unsigned char> vchCryptedSecret;
193             bool fCompressed;
194             if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
195                 return false;
196             if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
197                 return false;
198         }
199         mapKeys.clear();
200     }
201     return true;
202 }