Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2021 The Bitcoin Core developers
3 : // Copyright (c) 2017 The Zcash developers
4 : // Distributed under the MIT software license, see the accompanying
5 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 :
7 : #ifndef BITCOIN_PUBKEY_H
8 : #define BITCOIN_PUBKEY_H
9 :
10 : #include <hash.h>
11 : #include <serialize.h>
12 : #include <uint256.h>
13 :
14 : #include <array>
15 : #include <cstring>
16 : #include <vector>
17 :
18 : const unsigned int BIP32_EXTKEY_SIZE = 74;
19 : const unsigned int BIP32_EXTKEY_WITH_VERSION_SIZE = 78;
20 :
21 : /** A reference to a CKey: the Hash160 of its serialized public key */
22 : class CKeyID : public uint160
23 : {
24 : public:
25 91146 : CKeyID() : uint160() {}
26 883470 : explicit CKeyID(const uint160& in) : uint160(in) {}
27 : };
28 :
29 : typedef uint256 ChainCode;
30 :
31 : /** An encapsulated public key. */
32 : class CPubKey
33 : {
34 : public:
35 : /**
36 : * secp256k1:
37 : */
38 : static constexpr unsigned int SIZE = 65;
39 : static constexpr unsigned int COMPRESSED_SIZE = 33;
40 : static constexpr unsigned int SIGNATURE_SIZE = 72;
41 : static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65;
42 : /**
43 : * see www.keylength.com
44 : * script supports up to 75 for single byte push
45 : */
46 : static_assert(
47 : SIZE >= COMPRESSED_SIZE,
48 : "COMPRESSED_SIZE is larger than SIZE");
49 :
50 : private:
51 :
52 : /**
53 : * Just store the serialized data.
54 : * Its length can very cheaply be computed from the first byte.
55 : */
56 : unsigned char vch[SIZE];
57 :
58 : //! Compute the length of a pubkey with a given first byte.
59 3071122 : unsigned int static GetLen(unsigned char chHeader)
60 : {
61 3071122 : if (chHeader == 2 || chHeader == 3)
62 2829039 : return COMPRESSED_SIZE;
63 242083 : if (chHeader == 4 || chHeader == 6 || chHeader == 7)
64 241478 : return SIZE;
65 605 : return 0;
66 3071122 : }
67 :
68 : //! Set this key data to be invalid
69 294581 : void Invalidate()
70 : {
71 294581 : vch[0] = 0xFF;
72 294581 : }
73 :
74 : public:
75 :
76 3015 : bool static ValidSize(const std::vector<unsigned char> &vch) {
77 3015 : return vch.size() > 0 && GetLen(vch[0]) == vch.size();
78 : }
79 :
80 : //! Construct an invalid public key.
81 588518 : CPubKey()
82 294259 : {
83 294259 : Invalidate();
84 588518 : }
85 :
86 : //! Initialize a public key using begin/end iterators to byte data.
87 : template <typename T>
88 146526 : void Set(const T pbegin, const T pend)
89 : {
90 146526 : int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
91 146526 : if (len && len == (pend - pbegin))
92 146199 : memcpy(vch, (unsigned char*)&pbegin[0], len);
93 : else
94 327 : Invalidate();
95 146526 : }
96 :
97 : //! Construct a public key using begin/end iterators to byte data.
98 : template <typename T>
99 256 : CPubKey(const T pbegin, const T pend)
100 128 : {
101 128 : Set(pbegin, pend);
102 256 : }
103 :
104 : //! Construct a public key from a byte vector.
105 120749 : explicit CPubKey(Span<const uint8_t> _vch)
106 60377 : {
107 60372 : Set(_vch.begin(), _vch.end());
108 120749 : }
109 :
110 : //! Simple read-only vector-like interface to the pubkey data.
111 2922043 : unsigned int size() const { return GetLen(vch[0]); }
112 30126 : const unsigned char* data() const { return vch; }
113 241026 : const unsigned char* begin() const { return vch; }
114 24976 : const unsigned char* end() const { return vch + size(); }
115 6604 : const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
116 :
117 : //! Comparator implementation.
118 928 : friend bool operator==(const CPubKey& a, const CPubKey& b)
119 : {
120 1856 : return a.vch[0] == b.vch[0] &&
121 928 : memcmp(a.vch, b.vch, a.size()) == 0;
122 : }
123 0 : friend bool operator!=(const CPubKey& a, const CPubKey& b)
124 : {
125 0 : return !(a == b);
126 : }
127 2112952 : friend bool operator<(const CPubKey& a, const CPubKey& b)
128 : {
129 4110158 : return a.vch[0] < b.vch[0] ||
130 1997206 : (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
131 : }
132 0 : friend bool operator>(const CPubKey& a, const CPubKey& b)
133 : {
134 0 : return a.vch[0] > b.vch[0] ||
135 0 : (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) > 0);
136 : }
137 :
138 : //! Implement serialization, as if this was a byte vector.
139 : template <typename Stream>
140 28293 : void Serialize(Stream& s) const
141 : {
142 28293 : unsigned int len = size();
143 28293 : ::WriteCompactSize(s, len);
144 28293 : s.write(AsBytes(Span{vch, len}));
145 28293 : }
146 : template <typename Stream>
147 6492 : void Unserialize(Stream& s)
148 : {
149 6492 : const unsigned int len(::ReadCompactSize(s));
150 6492 : if (len <= SIZE) {
151 6492 : s.read(AsWritableBytes(Span{vch, len}));
152 6492 : if (len != size()) {
153 6 : Invalidate();
154 6 : }
155 6492 : } else {
156 : // invalid pubkey, skip available data
157 0 : s.ignore(len);
158 0 : Invalidate();
159 : }
160 6492 : }
161 :
162 : //! Get the KeyID of this public key (hash of its serialization)
163 426158 : CKeyID GetID() const
164 : {
165 426158 : return CKeyID(Hash160(Span{vch}.first(size())));
166 : }
167 :
168 : //! Get the 256-bit hash of this public key.
169 0 : uint256 GetHash() const
170 : {
171 0 : return Hash(Span{vch}.first(size()));
172 : }
173 :
174 : /*
175 : * Check syntactic correctness.
176 : *
177 : * Note that this is consensus critical as CheckSig() calls it!
178 : */
179 199380 : bool IsValid() const
180 : {
181 199380 : 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 : //! Check whether this is a compressed public key.
188 9525 : bool IsCompressed() const
189 : {
190 9525 : return size() == COMPRESSED_SIZE;
191 : }
192 :
193 : /**
194 : * Verify a DER signature (~72 bytes).
195 : * If this public key is not fully valid, the return value will be false.
196 : */
197 : bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
198 :
199 : /**
200 : * Check whether a signature is normalized (lower-S).
201 : */
202 : static bool CheckLowS(const std::vector<unsigned char>& vchSig);
203 :
204 : //! Recover a public key from a compact signature.
205 : bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
206 :
207 : //! Turn this public key into an uncompressed public key.
208 : bool Decompress();
209 :
210 : //! Derive BIP32 child pubkey.
211 : [[nodiscard]] bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
212 : };
213 :
214 : /** An ElligatorSwift-encoded public key. */
215 : struct EllSwiftPubKey
216 : {
217 : private:
218 : static constexpr size_t SIZE = 64;
219 : std::array<std::byte, SIZE> m_pubkey;
220 :
221 : public:
222 : /** Default constructor creates all-zero pubkey (which is valid). */
223 : EllSwiftPubKey() noexcept = default;
224 :
225 : /** Construct a new ellswift public key from a given serialization. */
226 : EllSwiftPubKey(Span<const std::byte> ellswift) noexcept;
227 :
228 : /** Decode to normal compressed CPubKey (for debugging purposes). */
229 : CPubKey Decode() const;
230 :
231 : // Read-only access for serialization.
232 576 : const std::byte* data() const { return m_pubkey.data(); }
233 1097 : static constexpr size_t size() { return SIZE; }
234 77 : auto begin() const { return m_pubkey.cbegin(); }
235 77 : auto end() const { return m_pubkey.cend(); }
236 :
237 98 : bool friend operator==(const EllSwiftPubKey& a, const EllSwiftPubKey& b)
238 : {
239 98 : return a.m_pubkey == b.m_pubkey;
240 : }
241 :
242 : bool friend operator!=(const EllSwiftPubKey& a, const EllSwiftPubKey& b)
243 : {
244 : return a.m_pubkey != b.m_pubkey;
245 : }
246 : };
247 :
248 : struct CExtPubKey {
249 : unsigned char version[4];
250 : unsigned char nDepth;
251 : unsigned char vchFingerprint[4];
252 : unsigned int nChild;
253 : ChainCode chaincode;
254 : CPubKey pubkey;
255 :
256 27 : friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
257 : {
258 54 : return a.nDepth == b.nDepth &&
259 27 : memcmp(a.vchFingerprint, b.vchFingerprint, sizeof(vchFingerprint)) == 0 &&
260 27 : a.nChild == b.nChild &&
261 27 : a.chaincode == b.chaincode &&
262 27 : a.pubkey == b.pubkey;
263 : }
264 :
265 0 : friend bool operator!=(const CExtPubKey &a, const CExtPubKey &b)
266 : {
267 0 : return !(a == b);
268 : }
269 :
270 0 : friend bool operator<(const CExtPubKey &a, const CExtPubKey &b)
271 : {
272 0 : if (a.pubkey < b.pubkey) {
273 0 : return true;
274 0 : } else if (a.pubkey > b.pubkey) {
275 0 : return false;
276 : }
277 0 : return a.chaincode < b.chaincode;
278 0 : }
279 :
280 : void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
281 : void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
282 : void EncodeWithVersion(unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]) const;
283 : void DecodeWithVersion(const unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]);
284 : [[nodiscard]] bool Derive(CExtPubKey& out, unsigned int nChild) const;
285 :
286 : void Serialize(CSizeComputer& s) const
287 : {
288 : // Optimized implementation for ::GetSerializeSize that avoids copying.
289 : s.seek(BIP32_EXTKEY_SIZE + 1); // add one byte for the size (compact int)
290 : }
291 : template <typename Stream>
292 0 : void Serialize(Stream& s) const
293 : {
294 0 : unsigned int len = BIP32_EXTKEY_SIZE;
295 0 : ::WriteCompactSize(s, len);
296 : unsigned char code[BIP32_EXTKEY_SIZE];
297 0 : Encode(code);
298 0 : s.write(AsBytes(Span{&code[0], len}));
299 0 : }
300 : template <typename Stream>
301 0 : void Unserialize(Stream& s)
302 : {
303 0 : unsigned int len = ::ReadCompactSize(s);
304 : unsigned char code[BIP32_EXTKEY_SIZE];
305 0 : if (len != BIP32_EXTKEY_SIZE)
306 0 : throw std::runtime_error("Invalid extended key size\n");
307 0 : s.read(AsWritableBytes(Span{&code[0], len}));
308 0 : Decode(code);
309 0 : }
310 : };
311 :
312 : #endif // BITCOIN_PUBKEY_H
|