68f57e7e0efa90b8b9ac8f4f986cc1afc6437d07
[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[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             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::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
120 {
121     CRITICAL_BLOCK(cs_KeyStore)
122     {
123         if (!IsCrypted())
124             return CBasicKeyStore::GetKey(address, keyOut);
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             CSecret vchSecret;
132             if (!DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
133                 return false;
134             keyOut.SetSecret(vchSecret);
135             return true;
136         }
137     }
138     return false;
139 }
140
141 bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const
142 {
143     CRITICAL_BLOCK(cs_KeyStore)
144     {
145         if (!IsCrypted())
146             return CKeyStore::GetPubKey(address, vchPubKeyOut);
147
148         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
149         if (mi != mapCryptedKeys.end())
150         {
151             vchPubKeyOut = (*mi).second.first;
152             return true;
153         }
154     }
155     return false;
156 }
157
158 bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
159 {
160     CRITICAL_BLOCK(cs_KeyStore)
161     {
162         if (!mapCryptedKeys.empty() || IsCrypted())
163             return false;
164
165         fUseCrypto = true;
166         CKey key;
167         BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
168         {
169             if (!key.SetSecret(mKey.second))
170                 return false;
171             const std::vector<unsigned char> vchPubKey = key.GetPubKey();
172             std::vector<unsigned char> vchCryptedSecret;
173             if (!EncryptSecret(vMasterKeyIn, key.GetSecret(), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
174                 return false;
175             if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
176                 return false;
177         }
178         mapKeys.clear();
179     }
180     return true;
181 }