Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2014 The Bitcoin Core developers
3 : // Distributed under the MIT software license, see the accompanying
4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 :
6 : #ifndef BITCOIN_PUBKEY_H
7 : #define BITCOIN_PUBKEY_H
8 :
9 : #include "hash.h"
10 : #include "serialize.h"
11 : #include "uint256.h"
12 :
13 : #include <stdexcept>
14 : #include <vector>
15 :
16 : /**
17 : * secp256k1:
18 : * const unsigned int PRIVATE_KEY_SIZE = 279;
19 : * const unsigned int PUBLIC_KEY_SIZE = 65;
20 : * const unsigned int SIGNATURE_SIZE = 72;
21 : *
22 : * see www.keylength.com
23 : * script supports up to 75 for single byte push
24 : */
25 :
26 : /** A reference to a CKey: the Hash160 of its serialized public key */
27 : class CKeyID : public uint160
28 : {
29 : public:
30 51736 : CKeyID() : uint160() {}
31 49896 : CKeyID(const uint160& in) : uint160(in) {}
32 : };
33 :
34 : typedef uint256 ChainCode;
35 :
36 : /** An encapsulated public key. */
37 : class CPubKey
38 : {
39 : private:
40 :
41 : /**
42 : * Just store the serialized data.
43 : * Its length can very cheaply be computed from the first byte.
44 : */
45 : unsigned char vch[65];
46 :
47 : //! Compute the length of a pubkey with a given first byte.
48 : unsigned int static GetLen(unsigned char chHeader)
49 : {
50 125309 : if (chHeader == 2 || chHeader == 3)
51 : return 33;
52 3827 : if (chHeader == 4 || chHeader == 6 || chHeader == 7)
53 : return 65;
54 : return 0;
55 : }
56 :
57 : //! Set this key data to be invalid
58 0 : void Invalidate()
59 : {
60 24239 : vch[0] = 0xFF;
61 0 : }
62 :
63 : public:
64 : //! Construct an invalid public key.
65 0 : CPubKey()
66 : {
67 26804 : Invalidate();
68 0 : }
69 :
70 : //! Initialize a public key using begin/end iterators to byte data.
71 : template <typename T>
72 38096 : void Set(const T pbegin, const T pend)
73 : {
74 76172 : int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
75 63904 : if (len && len == (pend - pbegin))
76 38076 : memcpy(vch, (unsigned char*)&pbegin[0], len);
77 : else
78 20 : Invalidate();
79 38096 : }
80 :
81 : //! Construct a public key using begin/end iterators to byte data.
82 : template <typename T>
83 0 : CPubKey(const T pbegin, const T pend)
84 : {
85 8 : Set(pbegin, pend);
86 0 : }
87 :
88 : //! Construct a public key from a byte vector.
89 0 : CPubKey(const std::vector<unsigned char>& vch)
90 : {
91 77238 : Set(vch.begin(), vch.end());
92 0 : }
93 :
94 : //! Simple read-only vector-like interface to the pubkey data.
95 0 : unsigned int size() const { return GetLen(vch[0]); }
96 8486 : const unsigned char* begin() const { return vch; }
97 12946 : const unsigned char* end() const { return vch + size(); }
98 : const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
99 :
100 : //! Comparator implementation.
101 84 : friend bool operator==(const CPubKey& a, const CPubKey& b)
102 : {
103 168 : return a.vch[0] == b.vch[0] &&
104 252 : memcmp(a.vch, b.vch, a.size()) == 0;
105 : }
106 : friend bool operator!=(const CPubKey& a, const CPubKey& b)
107 : {
108 : return !(a == b);
109 : }
110 10538 : friend bool operator<(const CPubKey& a, const CPubKey& b)
111 : {
112 10538 : return a.vch[0] < b.vch[0] ||
113 21056 : (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
114 : }
115 :
116 : //! Implement serialization, as if this was a byte vector.
117 : unsigned int GetSerializeSize(int nType, int nVersion) const
118 : {
119 : return size() + 1;
120 : }
121 : template <typename Stream>
122 4054 : void Serialize(Stream& s, int nType, int nVersion) const
123 : {
124 8108 : unsigned int len = size();
125 4054 : ::WriteCompactSize(s, len);
126 4054 : s.write((char*)vch, len);
127 4054 : }
128 : template <typename Stream>
129 6568 : void Unserialize(Stream& s, int nType, int nVersion)
130 : {
131 6568 : unsigned int len = ::ReadCompactSize(s);
132 6568 : if (len <= 65) {
133 6568 : s.read((char*)vch, len);
134 : } else {
135 : // invalid pubkey, skip available data
136 : char dummy;
137 0 : while (len--)
138 0 : s.read(&dummy, 1);
139 0 : Invalidate();
140 : }
141 6568 : }
142 :
143 : //! Get the KeyID of this public key (hash of its serialization)
144 33504 : CKeyID GetID() const
145 : {
146 100512 : return CKeyID(Hash160(vch, vch + size()));
147 : }
148 :
149 : //! Get the 256-bit hash of this public key.
150 258 : uint256 GetHash() const
151 : {
152 516 : return Hash(vch, vch + size());
153 : }
154 :
155 : /*
156 : * Check syntactic correctness.
157 : *
158 : * Note that this is consensus critical as CheckSig() calls it!
159 : */
160 : bool IsValid() const
161 : {
162 17089 : return size() > 0;
163 : }
164 :
165 : //! fully validate whether this is a valid public key (more expensive than IsValid())
166 : bool IsFullyValid() const;
167 :
168 : //! Check whether this is a compressed public key.
169 : bool IsCompressed() const
170 : {
171 9006 : return size() == 33;
172 : }
173 :
174 : /**
175 : * Verify a DER signature (~72 bytes).
176 : * If this public key is not fully valid, the return value will be false.
177 : */
178 : bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
179 :
180 : //! Recover a public key from a compact signature.
181 : bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
182 :
183 : //! Turn this public key into an uncompressed public key.
184 : bool Decompress();
185 :
186 : //! Derive BIP32 child pubkey.
187 : bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
188 : };
189 :
190 72 : struct CExtPubKey {
191 : unsigned char nDepth;
192 : unsigned char vchFingerprint[4];
193 : unsigned int nChild;
194 : ChainCode chaincode;
195 : CPubKey pubkey;
196 :
197 20 : friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
198 : {
199 60 : return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild &&
200 60 : a.chaincode == b.chaincode && a.pubkey == b.pubkey;
201 : }
202 :
203 : void Encode(unsigned char code[74]) const;
204 : void Decode(const unsigned char code[74]);
205 : bool Derive(CExtPubKey& out, unsigned int nChild) const;
206 : };
207 :
208 : #endif // BITCOIN_PUBKEY_H
|