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