|
|
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
|
|
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
|
|
|
// Copyright (c) 2017 The Zcash developers
|
|
|
|
// Distributed under the MIT software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
|
|
|
#ifndef BITCOIN_KEY_H
|
|
|
|
#define BITCOIN_KEY_H
|
|
|
|
|
|
|
|
#include <pubkey.h>
|
|
|
|
#include <serialize.h>
|
|
|
|
#include <support/allocators/secure.h>
|
|
|
|
#include <uint256.h>
|
|
|
|
|
|
|
|
#include <stdexcept>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* secure_allocator is defined in allocators.h
|
|
|
|
* CPrivKey is a serialized private key, with all parameters included
|
|
|
|
* (PRIVATE_KEY_SIZE bytes)
|
|
|
|
*/
|
|
|
|
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
|
|
|
|
|
|
|
|
/** An encapsulated private key. */
|
|
|
|
class CKey
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* secp256k1:
|
|
|
|
*/
|
|
|
|
static const unsigned int PRIVATE_KEY_SIZE = 279;
|
|
|
|
static const unsigned int COMPRESSED_PRIVATE_KEY_SIZE = 214;
|
|
|
|
/**
|
|
|
|
* see www.keylength.com
|
|
|
|
* script supports up to 75 for single byte push
|
|
|
|
*/
|
|
|
|
static_assert(
|
|
|
|
PRIVATE_KEY_SIZE >= COMPRESSED_PRIVATE_KEY_SIZE,
|
|
|
|
"COMPRESSED_PRIVATE_KEY_SIZE is larger than PRIVATE_KEY_SIZE");
|
|
|
|
|
|
|
|
private:
|
|
|
|
//! Whether this private key is valid. We check for correctness when modifying the key
|
|
|
|
//! data, so fValid should always correspond to the actual state.
|
|
|
|
bool fValid;
|
|
|
|
|
|
|
|
//! Whether the public key corresponding to this private key is (to be) compressed.
|
|
|
|
bool fCompressed;
|
|
|
|
|
|
|
|
//! The actual byte data
|
|
|
|
std::vector<unsigned char, secure_allocator<unsigned char> > keydata;
|
|
|
|
|
|
|
|
//! Check whether the 32-byte array pointed to by vch is valid keydata.
|
|
|
|
bool static Check(const unsigned char* vch);
|
|
|
|
|
|
|
|
public:
|
|
|
|
//! Construct an invalid private key.
|
|
|
|
CKey() : fValid(false), fCompressed(false)
|
|
|
|
{
|
|
|
|
// Important: vch must be 32 bytes in length to not break serialization
|
|
|
|
keydata.resize(32);
|
|
|
|
}
|
|
|
|
|
|
|
|
friend bool operator==(const CKey& a, const CKey& b)
|
|
|
|
{
|
|
|
|
return a.fCompressed == b.fCompressed &&
|
|
|
|
a.size() == b.size() &&
|
|
|
|
memcmp(a.keydata.data(), b.keydata.data(), a.size()) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Initialize using begin and end iterators to byte data.
|
|
|
|
template <typename T>
|
|
|
|
void Set(const T pbegin, const T pend, bool fCompressedIn)
|
|
|
|
{
|
|
|
|
if (size_t(pend - pbegin) != keydata.size()) {
|
|
|
|
fValid = false;
|
|
|
|
} else if (Check(&pbegin[0])) {
|
|
|
|
memcpy(keydata.data(), (unsigned char*)&pbegin[0], keydata.size());
|
|
|
|
fValid = true;
|
|
|
|
fCompressed = fCompressedIn;
|
|
|
|
} else {
|
|
|
|
fValid = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Simple read-only vector-like interface.
|
|
|
|
unsigned int size() const { return (fValid ? keydata.size() : 0); }
|
|
|
|
const unsigned char* begin() const { return keydata.data(); }
|
|
|
|
const unsigned char* end() const { return keydata.data() + size(); }
|
|
|
|
|
|
|
|
//! Check whether this private key is valid.
|
|
|
|
bool IsValid() const { return fValid; }
|
|
|
|
|
|
|
|
//! Check whether the public key corresponding to this private key is (to be) compressed.
|
|
|
|
bool IsCompressed() const { return fCompressed; }
|
|
|
|
|
|
|
|
//! Generate a new private key using a cryptographic PRNG.
|
|
|
|
void MakeNewKey(bool fCompressed);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert the private key to a CPrivKey (serialized OpenSSL private key data).
|
|
|
|
* This is expensive.
|
|
|
|
*/
|
|
|
|
CPrivKey GetPrivKey() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Compute the public key from a private key.
|
|
|
|
* This is expensive.
|
|
|
|
*/
|
|
|
|
CPubKey GetPubKey() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a DER-serialized signature.
|
|
|
|
* The test_case parameter tweaks the deterministic nonce.
|
|
|
|
*/
|
|
|
|
bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, bool grind = true, uint32_t test_case = 0) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a compact signature (65 bytes), which allows reconstructing the used public key.
|
|
|
|
* The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
|
|
|
|
* The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
|
|
|
|
* 0x1D = second key with even y, 0x1E = second key with odd y,
|
|
|
|
* add 0x04 for compressed keys.
|
|
|
|
*/
|
|
|
|
bool SignCompact(const uint256& hash, std::vector<unsigned char>& vchSig) const;
|
|
|
|
|
|
|
|
//! Derive BIP32 child key.
|
|
|
|
bool Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Verify thoroughly whether a private key and a public key match.
|
|
|
|
* This is done using a different mechanism than just regenerating it.
|
|
|
|
*/
|
|
|
|
bool VerifyPubKey(const CPubKey& vchPubKey) const;
|
|
|
|
|
|
|
|
//! Load private key and check that public key matches.
|
|
|
|
bool Load(const CPrivKey& privkey, const CPubKey& vchPubKey, bool fSkipCheck);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CExtKey {
|
|
|
|
unsigned char nDepth;
|
|
|
|
unsigned char vchFingerprint[4];
|
|
|
|
unsigned int nChild;
|
|
|
|
ChainCode chaincode;
|
|
|
|
CKey key;
|
|
|
|
|
|
|
|
friend bool operator==(const CExtKey& a, const CExtKey& b)
|
|
|
|
{
|
|
|
|
return a.nDepth == b.nDepth &&
|
|
|
|
memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], sizeof(vchFingerprint)) == 0 &&
|
|
|
|
a.nChild == b.nChild &&
|
|
|
|
a.chaincode == b.chaincode &&
|
|
|
|
a.key == b.key;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
|
|
|
|
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
|
|
|
|
bool Derive(CExtKey& out, unsigned int nChild) const;
|
|
|
|
CExtPubKey Neuter() const;
|
|
|
|
void SetSeed(const unsigned char* seed, unsigned int nSeedLen);
|
|
|
|
template <typename Stream>
|
|
|
|
void Serialize(Stream& s) const
|
|
|
|
{
|
|
|
|
unsigned int len = BIP32_EXTKEY_SIZE;
|
|
|
|
::WriteCompactSize(s, len);
|
|
|
|
unsigned char code[BIP32_EXTKEY_SIZE];
|
|
|
|
Encode(code);
|
|
|
|
s.write((const char *)&code[0], len);
|
|
|
|
}
|
|
|
|
template <typename Stream>
|
|
|
|
void Unserialize(Stream& s)
|
|
|
|
{
|
|
|
|
unsigned int len = ::ReadCompactSize(s);
|
|
|
|
unsigned char code[BIP32_EXTKEY_SIZE];
|
|
|
|
if (len != BIP32_EXTKEY_SIZE)
|
|
|
|
throw std::runtime_error("Invalid extended key size\n");
|
|
|
|
s.read((char *)&code[0], len);
|
|
|
|
Decode(code);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
Update key.cpp to use new libsecp256k1
libsecp256k1's API changed, so update key.cpp to use it.
Libsecp256k1 now has explicit context objects, which makes it completely thread-safe.
In turn, keep an explicit context object in key.cpp, which is explicitly initialized
destroyed. This is not really pretty now, but it's more efficient than the static
initialized object in key.cpp (which made for example bitcoin-tx slow, as for most of
its calls, libsecp256k1 wasn't actually needed).
This also brings in the new blinding support in libsecp256k1. By passing in a random
seed, temporary variables during the elliptic curve computations are altered, in such
a way that if an attacker does not know the blind, observing the internal operations
leaks less information about the keys used. This was implemented by Greg Maxwell.
10 years ago
|
|
|
/** Initialize the elliptic curve support. May not be called twice without calling ECC_Stop first. */
|
|
|
|
void ECC_Start();
|
Update key.cpp to use new libsecp256k1
libsecp256k1's API changed, so update key.cpp to use it.
Libsecp256k1 now has explicit context objects, which makes it completely thread-safe.
In turn, keep an explicit context object in key.cpp, which is explicitly initialized
destroyed. This is not really pretty now, but it's more efficient than the static
initialized object in key.cpp (which made for example bitcoin-tx slow, as for most of
its calls, libsecp256k1 wasn't actually needed).
This also brings in the new blinding support in libsecp256k1. By passing in a random
seed, temporary variables during the elliptic curve computations are altered, in such
a way that if an attacker does not know the blind, observing the internal operations
leaks less information about the keys used. This was implemented by Greg Maxwell.
10 years ago
|
|
|
|
|
|
|
/** Deinitialize the elliptic curve support. No-op if ECC_Start wasn't called first. */
|
|
|
|
void ECC_Stop();
|
Update key.cpp to use new libsecp256k1
libsecp256k1's API changed, so update key.cpp to use it.
Libsecp256k1 now has explicit context objects, which makes it completely thread-safe.
In turn, keep an explicit context object in key.cpp, which is explicitly initialized
destroyed. This is not really pretty now, but it's more efficient than the static
initialized object in key.cpp (which made for example bitcoin-tx slow, as for most of
its calls, libsecp256k1 wasn't actually needed).
This also brings in the new blinding support in libsecp256k1. By passing in a random
seed, temporary variables during the elliptic curve computations are altered, in such
a way that if an attacker does not know the blind, observing the internal operations
leaks less information about the keys used. This was implemented by Greg Maxwell.
10 years ago
|
|
|
|
|
|
|
/** Check that required EC support is available at runtime. */
|
|
|
|
bool ECC_InitSanityCheck();
|
|
|
|
|
|
|
|
#endif // BITCOIN_KEY_H
|