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