Add GetSecret() and GetKeys() to CKeyStore
[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 license.txt 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[CBitcoinAddress(key.GetPubKey())] = 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             CKey key;
75             key.SetSecret(vchSecret);
76             if (key.GetPubKey() == vchPubKey)
77                 break;
78             return false;
79         }
80         vMasterKey = vMasterKeyIn;
81     }
82     return true;
83 }
84
85 bool CCryptoKeyStore::AddKey(const CKey& key)
86 {
87     CRITICAL_BLOCK(cs_KeyStore)
88     {
89         if (!IsCrypted())
90             return CBasicKeyStore::AddKey(key);
91
92         if (IsLocked())
93             return false;
94
95         std::vector<unsigned char> vchCryptedSecret;
96         std::vector<unsigned char> vchPubKey = key.GetPubKey();
97         if (!EncryptSecret(vMasterKey, key.GetSecret(), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
98             return false;
99
100         if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
101             return false;
102     }
103     return true;
104 }
105
106
107 bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
108 {
109     CRITICAL_BLOCK(cs_KeyStore)
110     {
111         if (!SetCrypted())
112             return false;
113
114         mapCryptedKeys[CBitcoinAddress(vchPubKey)] = make_pair(vchPubKey, vchCryptedSecret);
115     }
116     return true;
117 }
118
119 bool CCryptoKeyStore::GetSecret(const CBitcoinAddress &address, CSecret& vchSecretOut) const
120 {
121     CRITICAL_BLOCK(cs_KeyStore)
122     {
123         if (!IsCrypted())
124             return CBasicKeyStore::GetSecret(address, vchSecretOut);
125
126         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
127         if (mi != mapCryptedKeys.end())
128         {
129             const std::vector<unsigned char> &vchPubKey = (*mi).second.first;
130             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
131             return DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecretOut);
132         }
133     }
134     return false;
135 }
136
137 bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const
138 {
139     CRITICAL_BLOCK(cs_KeyStore)
140     {
141         if (!IsCrypted())
142             return CKeyStore::GetPubKey(address, vchPubKeyOut);
143
144         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
145         if (mi != mapCryptedKeys.end())
146         {
147             vchPubKeyOut = (*mi).second.first;
148             return true;
149         }
150     }
151     return false;
152 }
153
154 bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
155 {
156     CRITICAL_BLOCK(cs_KeyStore)
157     {
158         if (!mapCryptedKeys.empty() || IsCrypted())
159             return false;
160
161         fUseCrypto = true;
162         CKey key;
163         BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
164         {
165             if (!key.SetSecret(mKey.second))
166                 return false;
167             const std::vector<unsigned char> vchPubKey = key.GetPubKey();
168             std::vector<unsigned char> vchCryptedSecret;
169             if (!EncryptSecret(vMasterKeyIn, key.GetSecret(), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
170                 return false;
171             if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
172                 return false;
173         }
174         mapKeys.clear();
175     }
176     return true;
177 }