Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto 2 : // Copyright (c) 2009-2014 The Bitcoin developers 3 : // Copyright (c) 2015-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_KEY_H 8 : #define PIVX_KEY_H 9 : 10 : #include "serialize.h" 11 : #include "support/allocators/secure.h" 12 : #include "uint256.h" 13 : #include "pubkey.h" 14 : 15 : #include <stdexcept> 16 : #include <vector> 17 : 18 : class CPubKey; 19 : 20 : struct CExtPubKey; 21 : 22 : /** 23 : * CPrivKey is a serialized private key, with all parameters included 24 : * (PRIVATE_KEY_SIZE bytes) 25 : */ 26 : typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey; 27 : 28 : /** An encapsulated private key. */ 29 11436920 : class CKey 30 : { 31 : public: 32 : /** 33 : * secp256k1: 34 : */ 35 : static const unsigned int PRIVATE_KEY_SIZE = 279; 36 : static const unsigned int COMPRESSED_PRIVATE_KEY_SIZE = 214; 37 : /** 38 : * see www.keylength.com 39 : * script supports up to 75 for single byte push 40 : */ 41 : static_assert( 42 : PRIVATE_KEY_SIZE >= COMPRESSED_PRIVATE_KEY_SIZE, 43 : "COMPRESSED_PRIVATE_KEY_SIZE is larger than PRIVATE_KEY_SIZE"); 44 : 45 : private: 46 : //! Whether this private key is valid. We check for correctness when modifying the key 47 : //! data, so fValid should always correspond to the actual state. 48 : bool fValid; 49 : 50 : //! Whether the public key corresponding to this private key is (to be) compressed. 51 : bool fCompressed; 52 : 53 : //! The actual byte data 54 : std::vector<unsigned char, secure_allocator<unsigned char> > keydata; 55 : 56 : //! Check whether the 32-byte array pointed to be vch is valid keydata. 57 : bool static Check(const unsigned char* vch); 58 : 59 : public: 60 : //! Construct an invalid private key. 61 3898296 : CKey() : fValid(false), fCompressed(false) 62 : { 63 : // Important: vch must be 32 bytes in length to not break serialization 64 3898296 : keydata.resize(32); 65 3898296 : } 66 : 67 14 : friend bool operator==(const CKey& a, const CKey& b) 68 : { 69 28 : return a.fCompressed == b.fCompressed && 70 28 : a.size() == b.size() && 71 28 : memcmp(a.keydata.data(), b.keydata.data(), a.size()) == 0; 72 : } 73 : 74 : //! Initialize using begin and end iterators to byte data. 75 : template <typename T> 76 15784 : void Set(const T pbegin, const T pend, bool fCompressedIn) 77 : { 78 15784 : if (size_t(pend - pbegin) != keydata.size()) { 79 0 : fValid = false; 80 15784 : } else if (Check(&pbegin[0])) { 81 15784 : memcpy(keydata.data(), (unsigned char*)&pbegin[0], keydata.size()); 82 15784 : fValid = true; 83 15784 : fCompressed = fCompressedIn; 84 : } else { 85 0 : fValid = false; 86 : } 87 15784 : } 88 : 89 : //! Simple read-only vector-like interface. 90 90954 : unsigned int size() const { return (fValid ? keydata.size() : 0); } 91 4032353 : const unsigned char* begin() const { return keydata.data(); } 92 7614 : const unsigned char* end() const { return keydata.data() + size(); } 93 : 94 : //! Check whether this private key is valid. 95 89104 : bool IsValid() const { return fValid; } 96 : 97 : //! Check whether the public key corresponding to this private key is (to be) compressed. 98 86660 : bool IsCompressed() const { return fCompressed; } 99 : 100 : //! Generate a new private key using a cryptographic PRNG. 101 : void MakeNewKey(bool fCompressed); 102 : 103 : uint256 GetPrivKey_256(); 104 : 105 : /** 106 : * Convert the private key to a CPrivKey (serialized secp256k1 private key data). 107 : * This is expensive. 108 : */ 109 : CPrivKey GetPrivKey() const; 110 : 111 : /** 112 : * Compute the public key from a private key. 113 : * This is expensive. 114 : */ 115 : CPubKey GetPubKey() const; 116 : 117 : /** 118 : * Create a DER-serialized signature. 119 : * The test_case parameter tweaks the deterministic nonce. 120 : */ 121 : bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, uint32_t test_case = 0) const; 122 : 123 : /** 124 : * Create a compact signature (65 bytes), which allows reconstructing the used public key. 125 : * The format is one header byte, followed by two times 32 bytes for the serialized r and s values. 126 : * The header byte: 0x1B = first key with even y, 0x1C = first key with odd y, 127 : * 0x1D = second key with even y, 0x1E = second key with odd y, 128 : * add 0x04 for compressed keys. 129 : */ 130 : bool SignCompact(const uint256& hash, std::vector<unsigned char>& vchSig) const; 131 : 132 : //! Derive BIP32 child key. 133 : bool Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const; 134 : 135 : /** 136 : * Verify thoroughly whether a private key and a public key match. 137 : * This is done using a different mechanism than just regenerating it. 138 : */ 139 : bool VerifyPubKey(const CPubKey& vchPubKey) const; 140 : 141 : //! Load private key and check that public key matches. 142 : bool Load(const CPrivKey& privkey, const CPubKey& vchPubKey, bool fSkipCheck); 143 : 144 : //! Check whether an element of a signature (r or s) is valid. 145 : static bool CheckSignatureElement(const unsigned char* vch, int len, bool half); 146 : }; 147 : 148 197380 : struct CExtKey { 149 : unsigned char nDepth; 150 : unsigned char vchFingerprint[4]; 151 : unsigned int nChild; 152 : ChainCode chaincode; 153 : CKey key; 154 : 155 14 : friend bool operator==(const CExtKey& a, const CExtKey& b) 156 : { 157 28 : return a.nDepth == b.nDepth && 158 14 : memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], sizeof(vchFingerprint)) == 0 && 159 14 : a.nChild == b.nChild && 160 28 : a.chaincode == b.chaincode && 161 14 : a.key == b.key; 162 : } 163 : 164 : void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const; 165 : void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]); 166 : bool Derive(CExtKey& out, unsigned int nChild) const; 167 : CExtPubKey Neuter() const; 168 : void SetSeed(const unsigned char* seed, unsigned int nSeedLen); 169 : }; 170 : 171 : /** Initialize the elliptic curve support. May not be called twice without calling ECC_Stop first. */ 172 : void ECC_Start(void); 173 : 174 : /** Deinitialize the elliptic curve support. No-op if ECC_Start wasn't called first. */ 175 : void ECC_Stop(void); 176 : 177 : /** Check that required EC support is available at runtime. */ 178 : bool ECC_InitSanityCheck(void); 179 : 180 : #endif // PIVX_KEY_H