Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto 2 : // Copyright (c) 2009-2014 The Bitcoin developers 3 : // Copyright (c) 2016-2021 The PIVX Core 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 PIVX_PUBKEY_H 8 : #define PIVX_PUBKEY_H 9 : 10 : #include "hash.h" 11 : #include "serialize.h" 12 : #include "uint256.h" 13 : 14 : #include <stdexcept> 15 : #include <vector> 16 : 17 : const unsigned int BIP32_EXTKEY_SIZE = 74; 18 : 19 : /** A reference to a CKey: the Hash160 of its serialized public key */ 20 : class CKeyID : public uint160 21 : { 22 : public: 23 24181649 : CKeyID() : uint160() {} 24 12745114 : explicit CKeyID(const uint160& in) : uint160(in) {} 25 : }; 26 : 27 : /** A reference to a CKey: the Hash160 of its serialized public key, special case for exchange key */ 28 : 29 : class CExchangeKeyID : public uint160 30 : { 31 : public: 32 : CExchangeKeyID() : uint160() {} 33 17 : explicit CExchangeKeyID(const uint160& in) : uint160(in) {} 34 : 35 15 : operator CKeyID() const { 36 15 : return CKeyID(static_cast<const uint160&>(*this)); 37 : } 38 : }; 39 : 40 : typedef uint256 ChainCode; 41 : 42 : /** An encapsulated public key. */ 43 : class CPubKey 44 : { 45 : public: 46 : /** 47 : * secp256k1: 48 : */ 49 : static constexpr unsigned int PUBLIC_KEY_SIZE = 65; 50 : static constexpr unsigned int COMPRESSED_PUBLIC_KEY_SIZE = 33; 51 : static constexpr unsigned int SIGNATURE_SIZE = 72; 52 : static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65; 53 : /** 54 : * see www.keylength.com 55 : * script supports up to 75 for single byte push 56 : */ 57 : static_assert( 58 : PUBLIC_KEY_SIZE >= COMPRESSED_PUBLIC_KEY_SIZE, 59 : "COMPRESSED_PUBLIC_KEY_SIZE is larger than PUBLIC_KEY_SIZE"); 60 : 61 : private: 62 : /** 63 : * Just store the serialized data. 64 : * Its length can very cheaply be computed from the first byte. 65 : */ 66 : unsigned char vch[PUBLIC_KEY_SIZE]; 67 : 68 : //! Compute the length of a pubkey with a given first byte. 69 18290297 : unsigned int static GetLen(unsigned char chHeader) 70 : { 71 18290297 : if (chHeader == 2 || chHeader == 3) 72 : return COMPRESSED_PUBLIC_KEY_SIZE; 73 71979 : if (chHeader == 4 || chHeader == 6 || chHeader == 7) 74 47804 : return PUBLIC_KEY_SIZE; 75 : return 0; 76 : } 77 : 78 : //! Set this key data to be invalid 79 7460455 : void Invalidate() 80 : { 81 7460455 : vch[0] = 0xFF; 82 12 : } 83 : 84 : public: 85 : 86 24838 : bool static ValidSize(const std::vector<unsigned char> &vch) { 87 26103 : return vch.size() > 0 && GetLen(vch[0]) == vch.size(); 88 : } 89 : 90 : //! Construct an invalid public key. 91 7460443 : CPubKey() 92 7460443 : { 93 7441837 : Invalidate(); 94 : } 95 : 96 : //! Initialize a public key using begin/end iterators to byte data. 97 : template <typename T> 98 1895121 : void Set(const T pbegin, const T pend) 99 : { 100 1895123 : int len = pend == pbegin ? 0 : GetLen(pbegin[0]); 101 1895111 : if (len && len == (pend - pbegin)) 102 1895109 : memcpy(vch, (unsigned char*)&pbegin[0], len); 103 : else 104 1895121 : Invalidate(); 105 1895121 : } 106 : 107 : //! Construct a public key using begin/end iterators to byte data. 108 : template <typename T> 109 6708 : CPubKey(const T pbegin, const T pend) 110 : { 111 6708 : Set(pbegin, pend); 112 : } 113 : 114 : //! Construct a public key from a byte vector. 115 1863423 : explicit CPubKey(const std::vector<unsigned char>& _vch) 116 1863423 : { 117 1863423 : Set(_vch.begin(), _vch.end()); 118 1863423 : } 119 : 120 : //! Simple read-only vector-like interface to the pubkey data. 121 19063587 : unsigned int size() const { return GetLen(vch[0]); } 122 1419420 : const unsigned char* data() const { return vch; } 123 7277903 : const unsigned char* begin() const { return vch; } 124 3576762 : const unsigned char* end() const { return vch + size(); } 125 923 : const unsigned char& operator[](unsigned int pos) const { return vch[pos]; } 126 : 127 : //! Comparator implementation. 128 18908 : friend bool operator==(const CPubKey& a, const CPubKey& b) 129 : { 130 18908 : return a.vch[0] == b.vch[0] && 131 9838 : memcmp(a.vch, b.vch, a.size()) == 0; 132 : } 133 : friend bool operator!=(const CPubKey& a, const CPubKey& b) 134 : { 135 : return !(a == b); 136 : } 137 : friend bool operator<(const CPubKey& a, const CPubKey& b) 138 : { 139 : return a.vch[0] < b.vch[0] || 140 : (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0); 141 : } 142 : 143 : //! Implement serialization, as if this was a byte vector. 144 : template <typename Stream> 145 43773 : void Serialize(Stream& s) const 146 : { 147 43773 : unsigned int len = size(); 148 43773 : ::WriteCompactSize(s, len); 149 43773 : s.write((char*)vch, len); 150 43773 : } 151 : template <typename Stream> 152 26021 : void Unserialize(Stream& s) 153 : { 154 26021 : unsigned int len = ::ReadCompactSize(s); 155 26021 : if (len <= PUBLIC_KEY_SIZE) { 156 26021 : s.read((char*)vch, len); 157 : } else { 158 : // invalid pubkey, skip available data 159 : char dummy; 160 0 : while (len--) 161 0 : s.read(&dummy, 1); 162 0 : Invalidate(); 163 : } 164 26021 : } 165 : 166 : //! Get the KeyID of this public key (hash of its serialization) 167 299495 : CKeyID GetID() const 168 : { 169 308229 : return CKeyID(Hash160(vch, vch + size())); 170 : } 171 : 172 : //! Get the 256-bit hash of this public key. 173 4781 : uint256 GetHash() const 174 : { 175 4781 : return Hash(vch, vch + size()); 176 : } 177 : 178 : /* 179 : * Check syntactic correctness. 180 : * 181 : * Note that this is consensus critical as CheckSig() calls it! 182 : */ 183 6408985 : bool IsValid() const 184 : { 185 8270548 : return size() > 0; 186 : } 187 : 188 : //! fully validate whether this is a valid public key (more expensive than IsValid()) 189 : bool IsFullyValid() const; 190 : 191 : //! Check whether this is a compressed public key. 192 27031 : bool IsCompressed() const 193 : { 194 27046 : return size() == COMPRESSED_PUBLIC_KEY_SIZE; 195 : } 196 : 197 : /** 198 : * Verify a DER signature (~72 bytes). 199 : * If this public key is not fully valid, the return value will be false. 200 : */ 201 : bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const; 202 : 203 : /** 204 : * Check whether a signature is normalized (lower-S). 205 : */ 206 : static bool CheckLowS(const std::vector<unsigned char>& vchSig); 207 : 208 : //! Recover a public key from a compact signature. 209 : bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig); 210 : 211 : //! Turn this public key into an uncompressed public key. 212 : bool Decompress(); 213 : 214 : //! Derive BIP32 child pubkey. 215 : bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const; 216 : 217 20 : std::vector<unsigned char> Raw() const 218 : { 219 20 : return std::vector<unsigned char>(vch, vch + size()); 220 : } 221 : 222 : }; 223 : 224 18200 : struct CExtPubKey { 225 : unsigned char nDepth; 226 : unsigned char vchFingerprint[4]; 227 : unsigned int nChild; 228 : ChainCode chaincode; 229 : CPubKey pubkey; 230 : 231 23 : friend bool operator==(const CExtPubKey& a, const CExtPubKey& b) 232 : { 233 46 : return a.nDepth == b.nDepth && 234 23 : memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], sizeof(vchFingerprint)) == 0 && 235 23 : a.nChild == b.nChild && 236 46 : a.chaincode == b.chaincode && 237 23 : a.pubkey == b.pubkey; 238 : } 239 : 240 : void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const; 241 : void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]); 242 : bool Derive(CExtPubKey& out, unsigned int nChild) const; 243 : 244 : void Serialize(CSizeComputer& s) const 245 : { 246 : // Optimized implementation for ::GetSerializeSize that avoids copying. 247 : s.seek(BIP32_EXTKEY_SIZE + 1); // add one byte for the size (compact int) 248 : } 249 : template <typename Stream> 250 : void Serialize(Stream& s) const 251 : { 252 : unsigned int len = BIP32_EXTKEY_SIZE; 253 : ::WriteCompactSize(s, len); 254 : unsigned char code[BIP32_EXTKEY_SIZE]; 255 : Encode(code); 256 : s.write((const char *)&code[0], len); 257 : } 258 : template <typename Stream> 259 : void Unserialize(Stream& s) 260 : { 261 : unsigned int len = ::ReadCompactSize(s); 262 : unsigned char code[BIP32_EXTKEY_SIZE]; 263 : if (len != BIP32_EXTKEY_SIZE) 264 : throw std::runtime_error("Invalid extended key size\n"); 265 : s.read((char *)&code[0], len); 266 : Decode(code); 267 : } 268 : }; 269 : 270 : /** Users of this module must hold an ECCVerifyHandle. The constructor and 271 : * destructor of these are not allowed to run in parallel, though. */ 272 : class ECCVerifyHandle 273 : { 274 : static int refcount; 275 : 276 : public: 277 : ECCVerifyHandle(); 278 : ~ECCVerifyHandle(); 279 : }; 280 : 281 : #endif // PIVX_PUBKEY_H