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