Add wallet privkey encryption.
[novacoin.git] / src / keystore.cpp
1 // Copyright (c) 2009-2011 Satoshi Nakamoto & Bitcoin developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
4
5 #include "headers.h"
6 #include "db.h"
7 #include "crypter.h"
8
9 std::vector<unsigned char> CKeyStore::GenerateNewKey()
10 {
11     RandAddSeedPerfmon();
12     CKey key;
13     key.MakeNewKey();
14     if (!AddKey(key))
15         throw std::runtime_error("CKeyStore::GenerateNewKey() : AddKey failed");
16     return key.GetPubKey();
17 }
18
19 bool CBasicKeyStore::AddKey(const CKey& key)
20 {
21     CRITICAL_BLOCK(cs_mapPubKeys)
22     CRITICAL_BLOCK(cs_KeyStore)
23     {
24         mapKeys[key.GetPubKey()] = key.GetPrivKey();
25         mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();
26     }
27     return true;
28 }
29
30 std::vector<unsigned char> CCryptoKeyStore::GenerateNewKey()
31 {
32     RandAddSeedPerfmon();
33     CKey key;
34     key.MakeNewKey();
35     if (!AddKey(key))
36         throw std::runtime_error("CCryptoKeyStore::GenerateNewKey() : AddKey failed");
37     return key.GetPubKey();
38 }
39
40 bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
41 {
42     CRITICAL_BLOCK(cs_vMasterKey)
43     {
44         if (!SetCrypted())
45             return false;
46
47         std::map<std::vector<unsigned char>, std::vector<unsigned char> >::const_iterator mi = mapCryptedKeys.begin();
48         for (; mi != mapCryptedKeys.end(); ++mi)
49         {
50             const std::vector<unsigned char> &vchPubKey = (*mi).first;
51             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second;
52             CSecret vchSecret;
53             if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
54                 return false;
55             CKey key;
56             key.SetSecret(vchSecret);
57             if (key.GetPubKey() == vchPubKey)
58                 break;
59             return false;
60         }
61         vMasterKey = vMasterKeyIn;
62     }
63     return true;
64 }
65
66 bool CCryptoKeyStore::AddKey(const CKey& key)
67 {
68     CRITICAL_BLOCK(cs_KeyStore)
69     CRITICAL_BLOCK(cs_vMasterKey)
70     {
71         if (!IsCrypted())
72             return CBasicKeyStore::AddKey(key);
73
74         if (IsLocked())
75             return false;
76
77         std::vector<unsigned char> vchCryptedSecret;
78         std::vector<unsigned char> vchPubKey = key.GetPubKey();
79         if (!EncryptSecret(vMasterKey, key.GetSecret(), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
80             return false;
81
82         if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
83             return false;
84     }
85     return true;
86 }
87
88
89 bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
90 {
91     CRITICAL_BLOCK(cs_mapPubKeys)
92     CRITICAL_BLOCK(cs_KeyStore)
93     {
94         if (!SetCrypted())
95             return false;
96
97         mapCryptedKeys[vchPubKey] = vchCryptedSecret;
98         mapPubKeys[Hash160(vchPubKey)] = vchPubKey;
99     }
100     return true;
101 }
102
103 bool CCryptoKeyStore::GetPrivKey(const std::vector<unsigned char> &vchPubKey, CPrivKey& keyOut) const
104 {
105     CRITICAL_BLOCK(cs_vMasterKey)
106     {
107         if (!IsCrypted())
108             return CBasicKeyStore::GetPrivKey(vchPubKey, keyOut);
109
110         std::map<std::vector<unsigned char>, std::vector<unsigned char> >::const_iterator mi = mapCryptedKeys.find(vchPubKey);
111         if (mi != mapCryptedKeys.end())
112         {
113             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second;
114             CSecret vchSecret;
115             if (!DecryptSecret(vMasterKey, (*mi).second, Hash((*mi).first.begin(), (*mi).first.end()), vchSecret))
116                 return false;
117             CKey key;
118             key.SetSecret(vchSecret);
119             keyOut = key.GetPrivKey();
120             return true;
121         }
122     }
123     return false;
124 }
125
126 bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
127 {
128     CRITICAL_BLOCK(cs_KeyStore)
129     CRITICAL_BLOCK(cs_vMasterKey)
130     {
131         if (!mapCryptedKeys.empty() || IsCrypted())
132             return false;
133
134         fUseCrypto = true;
135         CKey key;
136         BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
137         {
138             if (!key.SetPrivKey(mKey.second))
139                 return false;
140             std::vector<unsigned char> vchCryptedSecret;
141             if (!EncryptSecret(vMasterKeyIn, key.GetSecret(), Hash(mKey.first.begin(), mKey.first.end()), vchCryptedSecret))
142                 return false;
143             if (!AddCryptedKey(mKey.first, vchCryptedSecret))
144                 return false;
145         }
146         mapKeys.clear();
147     }
148     return true;
149 }