Add missing includes to key.h
[novacoin.git] / src / key.h
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
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 #ifndef BITCOIN_KEY_H
5 #define BITCOIN_KEY_H
6
7 #include <stdexcept>
8 #include <vector>
9
10 #include <openssl/ec.h>
11 #include <openssl/ecdsa.h>
12 #include <openssl/obj_mac.h>
13
14 #include "serialize.h"
15 #include "uint256.h"
16 #include "base58.h"
17
18 // secp160k1
19 // const unsigned int PRIVATE_KEY_SIZE = 192;
20 // const unsigned int PUBLIC_KEY_SIZE  = 41;
21 // const unsigned int SIGNATURE_SIZE   = 48;
22 //
23 // secp192k1
24 // const unsigned int PRIVATE_KEY_SIZE = 222;
25 // const unsigned int PUBLIC_KEY_SIZE  = 49;
26 // const unsigned int SIGNATURE_SIZE   = 57;
27 //
28 // secp224k1
29 // const unsigned int PRIVATE_KEY_SIZE = 250;
30 // const unsigned int PUBLIC_KEY_SIZE  = 57;
31 // const unsigned int SIGNATURE_SIZE   = 66;
32 //
33 // secp256k1:
34 // const unsigned int PRIVATE_KEY_SIZE = 279;
35 // const unsigned int PUBLIC_KEY_SIZE  = 65;
36 // const unsigned int SIGNATURE_SIZE   = 72;
37 //
38 // see www.keylength.com
39 // script supports up to 75 for single byte push
40
41 int static inline EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
42 {
43     int ok = 0;
44     BN_CTX *ctx = NULL;
45     EC_POINT *pub_key = NULL;
46
47     if (!eckey) return 0;
48
49     const EC_GROUP *group = EC_KEY_get0_group(eckey);
50
51     if ((ctx = BN_CTX_new()) == NULL)
52         goto err;
53
54     pub_key = EC_POINT_new(group);
55
56     if (pub_key == NULL)
57         goto err;
58
59     if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
60         goto err;
61
62     EC_KEY_set_private_key(eckey,priv_key);
63     EC_KEY_set_public_key(eckey,pub_key);
64
65     ok = 1;
66
67 err:
68
69     if (pub_key)
70         EC_POINT_free(pub_key);
71     if (ctx != NULL)
72         BN_CTX_free(ctx);
73
74     return(ok);
75 }
76
77
78 class key_error : public std::runtime_error
79 {
80 public:
81     explicit key_error(const std::string& str) : std::runtime_error(str) {}
82 };
83
84
85 // secure_allocator is defined in serialize.h
86 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
87 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret;
88
89 class CKey
90 {
91 protected:
92     EC_KEY* pkey;
93     bool fSet;
94
95 public:
96     CKey()
97     {
98         pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
99         if (pkey == NULL)
100             throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
101         fSet = false;
102     }
103
104     CKey(const CKey& b)
105     {
106         pkey = EC_KEY_dup(b.pkey);
107         if (pkey == NULL)
108             throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
109         fSet = b.fSet;
110     }
111
112     CKey& operator=(const CKey& b)
113     {
114         if (!EC_KEY_copy(pkey, b.pkey))
115             throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
116         fSet = b.fSet;
117         return (*this);
118     }
119
120     ~CKey()
121     {
122         EC_KEY_free(pkey);
123     }
124
125     bool IsNull() const
126     {
127         return !fSet;
128     }
129
130     void MakeNewKey()
131     {
132         if (!EC_KEY_generate_key(pkey))
133             throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
134         fSet = true;
135     }
136
137     bool SetPrivKey(const CPrivKey& vchPrivKey)
138     {
139         const unsigned char* pbegin = &vchPrivKey[0];
140         if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
141             return false;
142         fSet = true;
143         return true;
144     }
145
146     bool SetSecret(const CSecret& vchSecret)
147     {
148         EC_KEY_free(pkey);
149         pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
150         if (pkey == NULL)
151             throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
152         if (vchSecret.size() != 32)
153             throw key_error("CKey::SetSecret() : secret must be 32 bytes");
154         BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
155         if (bn == NULL) 
156             throw key_error("CKey::SetSecret() : BN_bin2bn failed");
157         if (!EC_KEY_regenerate_key(pkey,bn))
158             throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
159         BN_clear_free(bn);
160         fSet = true;
161         return true;
162     }
163
164     CSecret GetSecret() const
165     {
166         CSecret vchRet;
167         vchRet.resize(32);
168         const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
169         int nBytes = BN_num_bytes(bn);
170         if (bn == NULL)
171             throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
172         int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
173         if (n != nBytes) 
174             throw key_error("CKey::GetSecret(): BN_bn2bin failed");
175         return vchRet;
176     }
177
178     CPrivKey GetPrivKey() const
179     {
180         unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
181         if (!nSize)
182             throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
183         CPrivKey vchPrivKey(nSize, 0);
184         unsigned char* pbegin = &vchPrivKey[0];
185         if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
186             throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
187         return vchPrivKey;
188     }
189
190     bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
191     {
192         const unsigned char* pbegin = &vchPubKey[0];
193         if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
194             return false;
195         fSet = true;
196         return true;
197     }
198
199     std::vector<unsigned char> GetPubKey() const
200     {
201         unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
202         if (!nSize)
203             throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
204         std::vector<unsigned char> vchPubKey(nSize, 0);
205         unsigned char* pbegin = &vchPubKey[0];
206         if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
207             throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
208         return vchPubKey;
209     }
210
211     bool Sign(uint256 hash, std::vector<unsigned char>& vchSig)
212     {
213         vchSig.clear();
214         unsigned char pchSig[10000];
215         unsigned int nSize = 0;
216         if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey))
217             return false;
218         vchSig.resize(nSize);
219         memcpy(&vchSig[0], pchSig, nSize);
220         return true;
221     }
222
223     bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
224     {
225         // -1 = error, 0 = bad sig, 1 = good
226         if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
227             return false;
228         return true;
229     }
230
231     CBitcoinAddress GetAddress() const
232     {
233         return CBitcoinAddress(GetPubKey());
234     }
235 };
236
237 #endif