key.h 10.2 KB
Newer Older
Gavin Andresen's avatar
Gavin Andresen committed
1
// Copyright (c) 2009-2010 Satoshi Nakamoto
2
// Copyright (c) 2009-2013 The Bitcoin developers
Gavin Andresen's avatar
Gavin Andresen committed
3
// Distributed under the MIT/X11 software license, see the accompanying
Fordy's avatar
Fordy committed
4
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5

6
7
#ifndef BITCOIN_KEY_H
#define BITCOIN_KEY_H
Gavin Andresen's avatar
Gavin Andresen committed
8

9
#include "allocators.h"
10
#include "hash.h"
11
#include "serialize.h"
Vegard Nossum's avatar
Vegard Nossum committed
12
#include "uint256.h"
13
14
15

#include <stdexcept>
#include <vector>
Vegard Nossum's avatar
Vegard Nossum committed
16

Gavin Andresen's avatar
Gavin Andresen committed
17
18
19
20
21
22
23
24
// secp256k1:
// const unsigned int PRIVATE_KEY_SIZE = 279;
// const unsigned int PUBLIC_KEY_SIZE  = 65;
// const unsigned int SIGNATURE_SIZE   = 72;
//
// see www.keylength.com
// script supports up to 75 for single byte push

25
26
27
28
/** A reference to a CKey: the Hash160 of its serialized public key */
class CKeyID : public uint160
{
public:
29
30
    CKeyID() : uint160(0) {}
    CKeyID(const uint160& in) : uint160(in) {}
31
32
33
};

/** An encapsulated public key. */
34
35
class CPubKey
{
36
private:
37
38
    // Just store the serialized data.
    // Its length can very cheaply be computed from the first byte.
39
40
    unsigned char vch[65];

41
    // Compute the length of a pubkey with a given first byte.
42
43
    unsigned int static GetLen(unsigned char chHeader)
    {
44
45
46
47
48
49
50
        if (chHeader == 2 || chHeader == 3)
            return 33;
        if (chHeader == 4 || chHeader == 6 || chHeader == 7)
            return 65;
        return 0;
    }

51
    // Set this key data to be invalid
52
53
    void Invalidate()
    {
54
        vch[0] = 0xFF;
55
56
    }

57
public:
58
    // Construct an invalid public key.
59
60
    CPubKey()
    {
61
        Invalidate();
62
63
    }

64
    // Initialize a public key using begin/end iterators to byte data.
65
66
67
    template <typename T>
    void Set(const T pbegin, const T pend)
    {
68
        int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
69
        if (len && len == (pend - pbegin))
70
71
72
            memcpy(vch, (unsigned char*)&pbegin[0], len);
        else
            Invalidate();
73
74
    }

75
    // Construct a public key using begin/end iterators to byte data.
76
77
78
    template <typename T>
    CPubKey(const T pbegin, const T pend)
    {
79
        Set(pbegin, pend);
80
    }
81

82
    // Construct a public key from a byte vector.
83
84
    CPubKey(const std::vector<unsigned char>& vch)
    {
85
        Set(vch.begin(), vch.end());
86
87
    }

88
    // Simple read-only vector-like interface to the pubkey data.
89
    unsigned int size() const { return GetLen(vch[0]); }
90
91
92
    const unsigned char* begin() const { return vch; }
    const unsigned char* end() const { return vch + size(); }
    const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
93
94

    // Comparator implementation.
95
96
    friend bool operator==(const CPubKey& a, const CPubKey& b)
    {
97
98
99
        return a.vch[0] == b.vch[0] &&
               memcmp(a.vch, b.vch, a.size()) == 0;
    }
100
101
    friend bool operator!=(const CPubKey& a, const CPubKey& b)
    {
102
103
        return !(a == b);
    }
104
105
    friend bool operator<(const CPubKey& a, const CPubKey& b)
    {
106
        return a.vch[0] < b.vch[0] ||
107
               (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
108
109
    }

110
    // Implement serialization, as if this was a byte vector.
111
112
    unsigned int GetSerializeSize(int nType, int nVersion) const
    {
113
114
        return size() + 1;
    }
115
116
117
    template <typename Stream>
    void Serialize(Stream& s, int nType, int nVersion) const
    {
118
        unsigned int len = size();
119
        ::WriteCompactSize(s, len);
120
121
        s.write((char*)vch, len);
    }
122
123
124
    template <typename Stream>
    void Unserialize(Stream& s, int nType, int nVersion)
    {
125
        unsigned int len = ::ReadCompactSize(s);
126
127
128
        if (len <= 65) {
            s.read((char*)vch, len);
        } else {
129
            // invalid pubkey, skip available data
130
131
132
            char dummy;
            while (len--)
                s.read(&dummy, 1);
133
            Invalidate();
134
135
        }
    }
136

137
    // Get the KeyID of this public key (hash of its serialization)
138
139
140
    CKeyID GetID() const
    {
        return CKeyID(Hash160(vch, vch + size()));
141
142
    }

143
    // Get the 256-bit hash of this public key.
144
145
146
    uint256 GetHash() const
    {
        return Hash(vch, vch + size());
147
148
    }

149
150
151
    // Check syntactic correctness.
    //
    // Note that this is consensus critical as CheckSig() calls it!
152
153
    bool IsValid() const
    {
154
        return size() > 0;
155
156
    }

157
158
159
160
    // fully validate whether this is a valid public key (more expensive than IsValid())
    bool IsFullyValid() const;

    // Check whether this is a compressed public key.
161
162
    bool IsCompressed() const
    {
163
        return size() == 33;
164
165
    }

166
167
    // Verify a DER signature (~72 bytes).
    // If this public key is not fully valid, the return value will be false.
168
    bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
169
170

    // Recover a public key from a compact signature.
171
    bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
172
173
174

    // Turn this public key into an uncompressed public key.
    bool Decompress();
175
176
177

    // Derive BIP32 child pubkey.
    bool Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const;
178
179
};

Gavin Andresen's avatar
Gavin Andresen committed
180

181
// secure_allocator is defined in allocators.h
Pieter Wuille's avatar
Pieter Wuille committed
182
// CPrivKey is a serialized private key, with all parameters included (279 bytes)
183
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
Gavin Andresen's avatar
Gavin Andresen committed
184

185
/** An encapsulated private key. */
186
187
class CKey
{
188
189
190
191
private:
    // Whether this private key is valid. We check for correctness when modifying the key
    // data, so fValid should always correspond to the actual state.
    bool fValid;
Pieter Wuille's avatar
Pieter Wuille committed
192

193
194
195
196
197
198
199
    // Whether the public key corresponding to this private key is (to be) compressed.
    bool fCompressed;

    // The actual byte data
    unsigned char vch[32];

    // Check whether the 32-byte array pointed to be vch is valid keydata.
200
    bool static Check(const unsigned char* vch);
Pieter Wuille's avatar
Pieter Wuille committed
201

202
public:
203
    // Construct an invalid private key.
204
205
    CKey() : fValid(false), fCompressed(false)
    {
206
207
        LockObject(vch);
    }
Gavin Andresen's avatar
Gavin Andresen committed
208

209
    // Copy constructor. This is necessary because of memlocking.
210
211
    CKey(const CKey& secret) : fValid(secret.fValid), fCompressed(secret.fCompressed)
    {
212
213
214
        LockObject(vch);
        memcpy(vch, secret.vch, sizeof(vch));
    }
Pieter Wuille's avatar
Pieter Wuille committed
215

216
    // Destructor (again necessary because of memlocking).
217
218
    ~CKey()
    {
219
220
        UnlockObject(vch);
    }
Gavin Andresen's avatar
Gavin Andresen committed
221

222
223
    friend bool operator==(const CKey& a, const CKey& b)
    {
224
225
        return a.fCompressed == b.fCompressed && a.size() == b.size() &&
               memcmp(&a.vch[0], &b.vch[0], a.size()) == 0;
226
227
    }

228
    // Initialize using begin and end iterators to byte data.
229
230
231
    template <typename T>
    void Set(const T pbegin, const T pend, bool fCompressedIn)
    {
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
        if (pend - pbegin != 32) {
            fValid = false;
            return;
        }
        if (Check(&pbegin[0])) {
            memcpy(vch, (unsigned char*)&pbegin[0], 32);
            fValid = true;
            fCompressed = fCompressedIn;
        } else {
            fValid = false;
        }
    }

    // Simple read-only vector-like interface.
    unsigned int size() const { return (fValid ? 32 : 0); }
247
248
    const unsigned char* begin() const { return vch; }
    const unsigned char* end() const { return vch + size(); }
249
250
251

    // Check whether this private key is valid.
    bool IsValid() const { return fValid; }
Gavin Andresen's avatar
Gavin Andresen committed
252

253
254
    // Check whether the public key corresponding to this private key is (to be) compressed.
    bool IsCompressed() const { return fCompressed; }
255

256
    // Initialize from a CPrivKey (serialized OpenSSL private key data).
257
    bool SetPrivKey(const CPrivKey& vchPrivKey, bool fCompressed);
258
259

    // Generate a new private key using a cryptographic PRNG.
260
    void MakeNewKey(bool fCompressed);
261
262
263

    // Convert the private key to a CPrivKey (serialized OpenSSL private key data).
    // This is expensive.
264
    CPrivKey GetPrivKey() const;
265
266
267

    // Compute the public key from a private key.
    // This is expensive.
268
    CPubKey GetPubKey() const;
269

270
    // Create a DER-serialized signature.
271
    bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, bool lowS = true) const;
Gavin Andresen's avatar
Gavin Andresen committed
272

273
    // Create a compact signature (65 bytes), which allows reconstructing the used public key.
Pieter Wuille's avatar
Pieter Wuille committed
274
275
    // The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
    // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
276
277
    //                  0x1D = second key with even y, 0x1E = second key with odd y,
    //                  add 0x04 for compressed keys.
278
    bool SignCompact(const uint256& hash, std::vector<unsigned char>& vchSig) const;
279
280
281

    // Derive BIP32 child key.
    bool Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const;
282

283
    // Load private key and check that public key matches.
284
    bool Load(CPrivKey& privkey, CPubKey& vchPubKey, bool fSkipCheck);
285
286

    // Check whether an element of a signature (r or s) is valid.
287
    static bool CheckSignatureElement(const unsigned char* vch, int len, bool half);
288
289
290
291
292
293
294
295
296
};

struct CExtPubKey {
    unsigned char nDepth;
    unsigned char vchFingerprint[4];
    unsigned int nChild;
    unsigned char vchChainCode[32];
    CPubKey pubkey;

297
298
    friend bool operator==(const CExtPubKey& a, const CExtPubKey& b)
    {
299
300
301
302
303
304
        return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild &&
               memcmp(&a.vchChainCode[0], &b.vchChainCode[0], 32) == 0 && a.pubkey == b.pubkey;
    }

    void Encode(unsigned char code[74]) const;
    void Decode(const unsigned char code[74]);
305
    bool Derive(CExtPubKey& out, unsigned int nChild) const;
306
307
308
309
310
311
312
313
314
};

struct CExtKey {
    unsigned char nDepth;
    unsigned char vchFingerprint[4];
    unsigned int nChild;
    unsigned char vchChainCode[32];
    CKey key;

315
316
    friend bool operator==(const CExtKey& a, const CExtKey& b)
    {
317
318
319
320
321
322
        return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild &&
               memcmp(&a.vchChainCode[0], &b.vchChainCode[0], 32) == 0 && a.key == b.key;
    }

    void Encode(unsigned char code[74]) const;
    void Decode(const unsigned char code[74]);
323
    bool Derive(CExtKey& out, unsigned int nChild) const;
324
    CExtPubKey Neuter() const;
325
    void SetMaster(const unsigned char* seed, unsigned int nSeedLen);
Gavin Andresen's avatar
Gavin Andresen committed
326
};
327

328
329
330
/** Check that required EC support is available at runtime */
bool ECC_InitSanityCheck(void);

331
#endif // BITCOIN_KEY_H