// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_PUBKEY_H #define BITCOIN_PUBKEY_H #include "hash.h" #include "serialize.h" #include "uint256.h" #include #include /** * 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 */ /** A reference to a CKey: the Hash160 of its serialized public key */ class CKeyID : public uint160 { public: CKeyID() : uint160() {} CKeyID(const uint160& in) : uint160(in) {} }; typedef uint256 ChainCode; /** An encapsulated public key. */ class CPubKey { private: /** * Just store the serialized data. * Its length can very cheaply be computed from the first byte. */ unsigned char vch[65]; //! Compute the length of a pubkey with a given first byte. unsigned int static GetLen(unsigned char chHeader) { if (chHeader == 2 || chHeader == 3) return 33; if (chHeader == 4 || chHeader == 6 || chHeader == 7) return 65; return 0; } //! Set this key data to be invalid void Invalidate() { vch[0] = 0xFF; } public: //! Construct an invalid public key. CPubKey() { Invalidate(); } //! Initialize a public key using begin/end iterators to byte data. template void Set(const T pbegin, const T pend) { int len = pend == pbegin ? 0 : GetLen(pbegin[0]); if (len && len == (pend - pbegin)) memcpy(vch, (unsigned char*)&pbegin[0], len); else Invalidate(); } //! Construct a public key using begin/end iterators to byte data. template CPubKey(const T pbegin, const T pend) { Set(pbegin, pend); } //! Construct a public key from a byte vector. CPubKey(const std::vector& vch) { Set(vch.begin(), vch.end()); } //! Simple read-only vector-like interface to the pubkey data. unsigned int size() const { return GetLen(vch[0]); } const unsigned char* begin() const { return vch; } const unsigned char* end() const { return vch + size(); } const unsigned char& operator[](unsigned int pos) const { return vch[pos]; } //! Comparator implementation. friend bool operator==(const CPubKey& a, const CPubKey& b) { return a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) == 0; } friend bool operator!=(const CPubKey& a, const CPubKey& b) { return !(a == b); } friend bool operator<(const CPubKey& a, const CPubKey& b) { return a.vch[0] < b.vch[0] || (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0); } //! Implement serialization, as if this was a byte vector. unsigned int GetSerializeSize(int nType, int nVersion) const { return size() + 1; } template void Serialize(Stream& s, int nType, int nVersion) const { unsigned int len = size(); ::WriteCompactSize(s, len); s.write((char*)vch, len); } template void Unserialize(Stream& s, int nType, int nVersion) { unsigned int len = ::ReadCompactSize(s); if (len <= 65) { s.read((char*)vch, len); } else { // invalid pubkey, skip available data char dummy; while (len--) s.read(&dummy, 1); Invalidate(); } } //! Get the KeyID of this public key (hash of its serialization) CKeyID GetID() const { return CKeyID(Hash160(vch, vch + size())); } //! Get the 256-bit hash of this public key. uint256 GetHash() const { return Hash(vch, vch + size()); } /* * Check syntactic correctness. * * Note that this is consensus critical as CheckSig() calls it! */ bool IsValid() const { return size() > 0; } //! fully validate whether this is a valid public key (more expensive than IsValid()) bool IsFullyValid() const; //! Check whether this is a compressed public key. bool IsCompressed() const { return size() == 33; } /** * Verify a DER signature (~72 bytes). * If this public key is not fully valid, the return value will be false. */ bool Verify(const uint256& hash, const std::vector& vchSig) const; /** * Check whether a signature is normalized (lower-S). */ static bool CheckLowS(const std::vector& vchSig); //! Recover a public key from a compact signature. bool RecoverCompact(const uint256& hash, const std::vector& vchSig); //! Turn this public key into an uncompressed public key. bool Decompress(); //! Derive BIP32 child pubkey. bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const; }; struct CExtPubKey { unsigned char nDepth; unsigned char vchFingerprint[4]; unsigned int nChild; ChainCode chaincode; CPubKey pubkey; friend bool operator==(const CExtPubKey &a, const CExtPubKey &b) { return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild && a.chaincode == b.chaincode && a.pubkey == b.pubkey; } void Encode(unsigned char code[74]) const; void Decode(const unsigned char code[74]); bool Derive(CExtPubKey& out, unsigned int nChild) const; unsigned int GetSerializeSize(int nType, int nVersion) const { return 74+1; //add one byte for the size (compact int) } template void Serialize(Stream& s, int nType, int nVersion) const { unsigned int len = 74; ::WriteCompactSize(s, len); unsigned char code[74]; Encode(code); s.write((const char *)&code[0], len); } template void Unserialize(Stream& s, int nType, int nVersion) { unsigned int len = ::ReadCompactSize(s); unsigned char code[74]; if (len != 74) throw std::runtime_error("Invalid extended key size\n"); s.read((char *)&code[0], len); Decode(code); } }; /** Users of this module must hold an ECCVerifyHandle. The constructor and * destructor of these are not allowed to run in parallel, though. */ class ECCVerifyHandle { static int refcount; public: ECCVerifyHandle(); ~ECCVerifyHandle(); }; #endif // BITCOIN_PUBKEY_H