key.h 5.36 KB
Newer Older
Gavin Andresen's avatar
Gavin Andresen committed
1
// Copyright (c) 2009-2010 Satoshi Nakamoto
2
3
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT 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 "serialize.h"
Vegard Nossum's avatar
Vegard Nossum committed
11
#include "uint256.h"
12
13
14

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

16
class CExtPubKey;
17
class CPubKey;
18

19
20
21
22
23
24
25
26
27
/** 
 * 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
 */
Gavin Andresen's avatar
Gavin Andresen committed
28

29
30
31
32
/**
 * secure_allocator is defined in allocators.h
 * CPrivKey is a serialized private key, with all parameters included (279 bytes)
 */
33
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
Gavin Andresen's avatar
Gavin Andresen committed
34

35
/** An encapsulated private key. */
36
37
class CKey
{
38
private:
39
40
    //! Whether this private key is valid. We check for correctness when modifying the key
    //! data, so fValid should always correspond to the actual state.
41
    bool fValid;
Pieter Wuille's avatar
Pieter Wuille committed
42

43
    //! Whether the public key corresponding to this private key is (to be) compressed.
44
45
    bool fCompressed;

46
    //! The actual byte data
47
48
    unsigned char vch[32];

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

52
public:
53
    //! Construct an invalid private key.
54
55
    CKey() : fValid(false), fCompressed(false)
    {
56
57
        LockObject(vch);
    }
Gavin Andresen's avatar
Gavin Andresen committed
58

59
    //! Copy constructor. This is necessary because of memlocking.
60
61
    CKey(const CKey& secret) : fValid(secret.fValid), fCompressed(secret.fCompressed)
    {
62
63
64
        LockObject(vch);
        memcpy(vch, secret.vch, sizeof(vch));
    }
Pieter Wuille's avatar
Pieter Wuille committed
65

66
    //! Destructor (again necessary because of memlocking).
67
68
    ~CKey()
    {
69
70
        UnlockObject(vch);
    }
Gavin Andresen's avatar
Gavin Andresen committed
71

72
73
    friend bool operator==(const CKey& a, const CKey& b)
    {
74
75
        return a.fCompressed == b.fCompressed && a.size() == b.size() &&
               memcmp(&a.vch[0], &b.vch[0], a.size()) == 0;
76
77
    }

78
    //! Initialize using begin and end iterators to byte data.
79
80
81
    template <typename T>
    void Set(const T pbegin, const T pend, bool fCompressedIn)
    {
82
83
84
85
86
87
88
89
90
91
92
93
94
        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;
        }
    }

95
    //! Simple read-only vector-like interface.
96
    unsigned int size() const { return (fValid ? 32 : 0); }
97
98
    const unsigned char* begin() const { return vch; }
    const unsigned char* end() const { return vch + size(); }
99

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

103
    //! Check whether the public key corresponding to this private key is (to be) compressed.
104
    bool IsCompressed() const { return fCompressed; }
105

106
    //! Initialize from a CPrivKey (serialized OpenSSL private key data).
107
    bool SetPrivKey(const CPrivKey& vchPrivKey, bool fCompressed);
108

109
    //! Generate a new private key using a cryptographic PRNG.
110
    void MakeNewKey(bool fCompressed);
111

112
113
114
115
    /**
     * Convert the private key to a CPrivKey (serialized OpenSSL private key data).
     * This is expensive. 
     */
116
    CPrivKey GetPrivKey() const;
117

118
119
120
121
    /**
     * Compute the public key from a private key.
     * This is expensive.
     */
122
    CPubKey GetPubKey() const;
123

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

127
128
129
130
131
132
133
    /**
     * Create a compact signature (65 bytes), which allows reconstructing the used public key.
     * 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,
     *                  0x1D = second key with even y, 0x1E = second key with odd y,
     *                  add 0x04 for compressed keys.
     */
134
    bool SignCompact(const uint256& hash, std::vector<unsigned char>& vchSig) const;
135

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

139
    //! Load private key and check that public key matches.
140
    bool Load(CPrivKey& privkey, CPubKey& vchPubKey, bool fSkipCheck);
141

142
    //! Check whether an element of a signature (r or s) is valid.
143
    static bool CheckSignatureElement(const unsigned char* vch, int len, bool half);
144
145
146
147
148
149
150
151
152
};

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

153
154
    friend bool operator==(const CExtKey& a, const CExtKey& b)
    {
155
156
157
158
159
160
        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]);
161
    bool Derive(CExtKey& out, unsigned int nChild) const;
162
    CExtPubKey Neuter() const;
163
    void SetMaster(const unsigned char* seed, unsigned int nSeedLen);
Gavin Andresen's avatar
Gavin Andresen committed
164
};
165

166
167
168
/** Check that required EC support is available at runtime */
bool ECC_InitSanityCheck(void);

169
#endif // BITCOIN_KEY_H