cb5a7122c27aaba0ed30d44366c5bfeacc2ddc38
[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 "allocators.h"
12 #include "serialize.h"
13 #include "uint256.h"
14 #include "hash.h"
15 #include "bignum.h"
16 #include "ies.h"
17
18 #include <openssl/ec.h> // for EC_KEY definition
19
20 // secp160k1
21 // const unsigned int PRIVATE_KEY_SIZE = 192;
22 // const unsigned int PUBLIC_KEY_SIZE  = 41;
23 // const unsigned int SIGNATURE_SIZE   = 48;
24 //
25 // secp192k1
26 // const unsigned int PRIVATE_KEY_SIZE = 222;
27 // const unsigned int PUBLIC_KEY_SIZE  = 49;
28 // const unsigned int SIGNATURE_SIZE   = 57;
29 //
30 // secp224k1
31 // const unsigned int PRIVATE_KEY_SIZE = 250;
32 // const unsigned int PUBLIC_KEY_SIZE  = 57;
33 // const unsigned int SIGNATURE_SIZE   = 66;
34 //
35 // secp256k1:
36 // const unsigned int PRIVATE_KEY_SIZE = 279;
37 // const unsigned int PUBLIC_KEY_SIZE  = 65;
38 // const unsigned int SIGNATURE_SIZE   = 72;
39 //
40 // see www.keylength.com
41 // script supports up to 75 for single byte push
42
43 class key_error : public std::runtime_error
44 {
45 public:
46     explicit key_error(const std::string& str) : std::runtime_error(str) {}
47 };
48
49 /** A reference to a CKey: the Hash160 of its serialized public key */
50 class CKeyID : public uint160
51 {
52 public:
53     CKeyID() : uint160(0) { }
54     CKeyID(const uint160 &in) : uint160(in) { }
55 };
56
57 /** A reference to a CScript: the Hash160 of its serialization (see script.h) */
58 class CScriptID : public uint160
59 {
60 public:
61     CScriptID() : uint160(0) { }
62     CScriptID(const uint160 &in) : uint160(in) { }
63 };
64
65 /** An encapsulated OpenSSL Elliptic Curve key (public) */
66 class CPubKey
67 {
68 private:
69
70     /**
71      * Just store the serialized data.
72      * Its length can very cheaply be computed from the first byte.
73      */
74     unsigned char vbytes[65];
75
76     //! Compute the length of a pubkey with a given first byte.
77     unsigned int static GetLen(unsigned char chHeader)
78     {
79         if (chHeader == 2 || chHeader == 3)
80             return 33;
81         if (chHeader == 4 || chHeader == 6 || chHeader == 7)
82             return 65;
83         return 0;
84     }
85
86     // Set this key data to be invalid
87     void Invalidate()
88     {
89         vbytes[0] = 0xFF;
90     }
91
92 public:
93     // Construct an invalid public key.
94     CPubKey()
95     {
96         Invalidate();
97     }
98
99     // Initialize a public key using begin/end iterators to byte data.
100     template <typename T>
101     void Set(const T pbegin, const T pend)
102     {
103         int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
104         if (len && len == (pend - pbegin))
105             memcpy(vbytes, (unsigned char*)&pbegin[0], len);
106         else
107             Invalidate();
108     }
109
110     void Set(const std::vector<unsigned char>& vch)
111     {
112         Set(vch.begin(), vch.end());
113     }
114
115     template <typename T>
116     CPubKey(const T pbegin, const T pend)
117     {
118         Set(pbegin, pend);
119     }
120
121     CPubKey(const std::vector<unsigned char>& vch)
122     {
123         Set(vch.begin(), vch.end());
124     }
125
126     // Read-only vector-like interface to the data.
127     unsigned int size() const { return GetLen(vbytes[0]); }
128     const unsigned char* begin() const { return vbytes; }
129     const unsigned char* end() const { return vbytes + size(); }
130     const unsigned char& operator[](unsigned int pos) const { return vbytes[pos]; }
131
132     friend bool operator==(const CPubKey& a, const CPubKey& b) { return a.vbytes[0] == b.vbytes[0] && memcmp(a.vbytes, b.vbytes, a.size()) == 0; }
133     friend bool operator!=(const CPubKey& a, const CPubKey& b) { return !(a == b); }
134     friend bool operator<(const CPubKey& a, const CPubKey& b)  { return a.vbytes[0] < b.vbytes[0] || (a.vbytes[0] == b.vbytes[0] && memcmp(a.vbytes, b.vbytes, a.size()) < 0); }
135
136     //! Implement serialization, as if this was a byte vector.
137     unsigned int GetSerializeSize(int nType, int nVersion) const
138     {
139         return size() + 1;
140     }
141     template <typename Stream>
142     void Serialize(Stream& s, int nType, int nVersion) const
143     {
144         unsigned int len = size();
145         ::WriteCompactSize(s, len);
146         s.write((char*)vbytes, len);
147     }
148     template <typename Stream>
149     void Unserialize(Stream& s, int nType, int nVersion)
150     {
151         unsigned int len = ::ReadCompactSize(s);
152         if (len <= 65) {
153             s.read((char*)vbytes, len);
154         } else {
155             // invalid pubkey, skip available data
156             char dummy;
157             while (len--)
158                 s.read(&dummy, 1);
159             Invalidate();
160         }
161     }
162
163     CKeyID GetID() const
164     {
165         return CKeyID(Hash160(vbytes, vbytes + size()));
166     }
167
168     uint256 GetHash() const
169     {
170         return Hash(vbytes, vbytes + size());
171     }
172
173     /*
174      * Check syntactic correctness.
175      *
176      * Note that this is consensus critical as CheckSig() calls it!
177      */
178     bool IsValid() const
179     {
180         return size() > 0;
181     }
182
183     //! fully validate whether this is a valid public key (more expensive than IsValid())
184     bool IsFullyValid() const
185     {
186         const unsigned char* pbegin = &vbytes[0];
187         EC_KEY *pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
188         if (o2i_ECPublicKey(&pkey, &pbegin, size()))
189         {
190             EC_KEY_free(pkey);
191             return true;
192         }
193         return false;
194     }
195
196     //! Check whether this is a compressed public key.
197     bool IsCompressed() const
198     {
199         return size() == 33;
200     }
201
202     bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
203     bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig);
204
205     bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig);
206
207     // Reserialize to DER
208     static bool ReserealizeSignature(std::vector<unsigned char>& vchSig);
209
210     // Encrypt data
211     void EncryptData(const std::vector<unsigned char>& data, std::vector<unsigned char>& encrypted);
212 };
213
214 // secure_allocator is defined in allocators.h
215 // CPrivKey is a serialized private key, with all parameters included (279 bytes)
216 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
217 // CSecret is a serialization of just the secret parameter (32 bytes)
218 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret;
219
220 /** An encapsulated OpenSSL Elliptic Curve key (private) */
221 class CKey
222 {
223 protected:
224     EC_KEY* pkey;
225     bool fSet;
226
227 public:
228
229     void Reset();
230
231     CKey();
232     CKey(const CKey& b);
233     CKey(const CSecret& b, bool fCompressed=true);
234
235     CKey& operator=(const CKey& b);
236
237     ~CKey();
238
239     bool IsNull() const;
240     bool IsCompressed() const;
241
242     void SetCompressedPubKey(bool fCompressed=true);
243     void MakeNewKey(bool fCompressed=true);
244     bool SetPrivKey(const CPrivKey& vchPrivKey);
245     bool SetSecret(const CSecret& vchSecret, bool fCompressed = true);
246     CSecret GetSecret(bool &fCompressed) const;
247     CSecret GetSecret() const;
248     CPrivKey GetPrivKey() const;
249     CPubKey GetPubKey() const;
250     bool WritePEM(BIO *streamObj, const SecureString &strPassKey) const;
251
252     bool Sign(uint256 hash, std::vector<unsigned char>& vchSig);
253
254     // create a compact signature (65 bytes), which allows reconstructing the used public key
255     // The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
256     // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
257     //                  0x1D = second key with even y, 0x1E = second key with odd y
258     bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig);
259
260     bool IsValid();
261
262     // Check whether an element of a signature (r or s) is valid.
263     static bool CheckSignatureElement(const unsigned char *vch, int len, bool half);
264
265     // Decrypt data
266     void DecryptData(const std::vector<unsigned char>& encrypted, std::vector<unsigned char>& data);
267 };
268
269 class CPoint
270 {
271 private:
272     EC_POINT *point;
273     EC_GROUP* group;
274     BN_CTX* ctx;
275
276 public:
277     CPoint();
278     bool operator!=(const CPoint &a);
279     ~CPoint();
280
281     // Initialize from octets stream
282     bool setBytes(const std::vector<unsigned char> &vchBytes);
283
284     // Initialize from pubkey
285     bool setPubKey(const CPubKey &vchPubKey);
286
287     // Serialize to octets stream
288     bool getBytes(std::vector<unsigned char> &vchBytes);
289
290     // ECC multiplication by specified multiplier
291     bool ECMUL(const CBigNum &bnMultiplier);
292
293     // Calculate G*m + q
294     bool ECMULGEN(const CBigNum &bnMultiplier, const CPoint &qPoint);
295
296     bool IsInfinity() { return EC_POINT_is_at_infinity(group, point) != 0; }
297 };
298
299 class CMalleablePubKey
300 {
301 private:
302     CPubKey pubKeyL;
303     CPubKey pubKeyH;
304     friend class CMalleableKey;
305
306     static const unsigned char CURRENT_VERSION = 1;
307
308 public:
309     CMalleablePubKey() { }
310     CMalleablePubKey(const CMalleablePubKey& mpk)
311     {
312         pubKeyL = mpk.pubKeyL;
313         pubKeyH = mpk.pubKeyH;
314     }
315     CMalleablePubKey(const std::vector<unsigned char> &vchPubKeyPair) { setvch(vchPubKeyPair); }
316     CMalleablePubKey(const std::string& strMalleablePubKey) { SetString(strMalleablePubKey); }
317     CMalleablePubKey(const CPubKey &pubKeyInL, const CPubKey &pubKeyInH) : pubKeyL(pubKeyInL), pubKeyH(pubKeyInH) { }
318
319     IMPLEMENT_SERIALIZE(
320         READWRITE(pubKeyL);
321         READWRITE(pubKeyH);
322     )
323
324     bool IsValid() const {
325         return pubKeyL.IsValid() && pubKeyH.IsValid();
326     }
327
328     bool operator==(const CMalleablePubKey &b);
329     bool operator!=(const CMalleablePubKey &b) { return !(*this == b); }
330     CMalleablePubKey& operator=(const CMalleablePubKey& mpk) {
331         pubKeyL = mpk.pubKeyL;
332         pubKeyH = mpk.pubKeyH;
333         return *this;
334     }
335
336     std::string ToString() const;
337     bool SetString(const std::string& strMalleablePubKey);
338
339     CKeyID GetID() const {
340         return pubKeyL.GetID();
341     }
342
343     bool setvch(const std::vector<unsigned char> &vchPubKeyPair);
344     std::vector<unsigned char> Raw() const;
345
346     CPubKey& GetL() { return pubKeyL; }
347     CPubKey& GetH() { return pubKeyH; }
348     void GetVariant(CPubKey &R, CPubKey &vchPubKeyVariant);
349 };
350
351 class CMalleableKey
352 {
353 private:
354     CSecret vchSecretL;
355     CSecret vchSecretH;
356
357     friend class CMalleableKeyView;
358
359 public:
360     CMalleableKey();
361     CMalleableKey(const CMalleableKey &b);
362     CMalleableKey(const CSecret &L, const CSecret &H);
363     ~CMalleableKey();
364
365     IMPLEMENT_SERIALIZE(
366         READWRITE(vchSecretL);
367         READWRITE(vchSecretH);
368     )
369
370     std::string ToString() const;
371     bool SetString(const std::string& strMalleablePubKey);
372     std::vector<unsigned char> Raw() const;
373     CMalleableKey& operator=(const CMalleableKey& mk) {
374         vchSecretL = mk.vchSecretL;
375         vchSecretH = mk.vchSecretH;
376         return *this;
377     }
378
379     void Reset();
380     void MakeNewKeys();
381     bool IsNull() const;
382     bool IsValid() const { return !IsNull() && GetMalleablePubKey().IsValid(); }
383     bool SetSecrets(const CSecret &pvchSecretL, const CSecret &pvchSecretH);
384
385     CSecret GetSecretL() const { return vchSecretL; }
386     CSecret GetSecretH() const { return vchSecretH; }
387
388     CKeyID GetID() const {
389         return GetMalleablePubKey().GetID();
390     }
391     CMalleablePubKey GetMalleablePubKey() const;
392     bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant) const;
393     bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant, CKey &privKeyVariant) const;
394 };
395
396 class CMalleableKeyView
397 {
398 private:
399     CSecret vchSecretL;
400     CPubKey vchPubKeyH;
401
402 public:
403     CMalleableKeyView() { };
404     CMalleableKeyView(const CMalleableKey &b);
405     CMalleableKeyView(const std::string &strMalleableKey);
406
407     CMalleableKeyView(const CMalleableKeyView &b);
408     CMalleableKeyView& operator=(const CMalleableKey &b);
409     ~CMalleableKeyView();
410
411     IMPLEMENT_SERIALIZE(
412         READWRITE(vchSecretL);
413         READWRITE(vchPubKeyH);
414     )
415
416     bool IsValid() const;
417     std::string ToString() const;
418     bool SetString(const std::string& strMalleablePubKey);
419     std::vector<unsigned char> Raw() const;
420     CMalleableKeyView& operator=(const CMalleableKeyView& mkv) {
421         vchSecretL = mkv.vchSecretL;
422         vchPubKeyH = mkv.vchPubKeyH;
423         return *this;
424     }
425
426     CKeyID GetID() const {
427         return GetMalleablePubKey().GetID();
428     }
429     CMalleablePubKey GetMalleablePubKey() const;
430     CMalleableKey GetMalleableKey(const CSecret &vchSecretH) const { return CMalleableKey(vchSecretL, vchSecretH); }
431     bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant) const;
432
433     bool operator <(const CMalleableKeyView& kv) const { return vchPubKeyH.GetID() < kv.vchPubKeyH.GetID(); }
434 };
435
436 #endif