Documentation ¶
Overview ¶
Package hdkeychain provides an API for bitcoin hierarchical deterministic extended keys (BIP0032).
Overview ¶
The ability to implement hierarchical deterministic wallets depends on the ability to create and derive hierarchical deterministic extended keys.
At a high level, this package provides support for those hierarchical deterministic extended keys by providing an ExtendedKey type and supporting functions. Each extended key can either be a private or public extended key which itself is capable of deriving a child extended key.
Determining the Extended Key Type ¶
Whether an extended key is a private or public extended key can be determined with the IsPrivate function.
Transaction Signing Keys and Payment Addresses ¶
In order to create and sign transactions, or provide others with addresses to send funds to, the underlying key and address material must be accessible. This package provides the ECPubKey, ECPrivKey, and Address functions for this purpose.
The Master Node ¶
As previously mentioned, the extended keys are hierarchical meaning they are used to form a tree. The root of that tree is called the master node and this package provides the NewMaster function to create it from a cryptographically random seed. The GenerateSeed function is provided as a convenient way to create a random seed for use with the NewMaster function.
Deriving Children ¶
Once you have created a tree root (or have deserialized an extended key as discussed later), the child extended keys can be derived by using the Child function. The Child function supports deriving both normal (non-hardened) and hardened child extended keys. In order to derive a hardened extended key, use the HardenedKeyStart constant + the hardened key number as the index to the Child function. This provides the ability to cascade the keys into a tree and hence generate the hierarchical deterministic key chains.
Normal vs Hardened Child Extended Keys ¶
A private extended key can be used to derive both hardened and non-hardened (normal) child private and public extended keys. A public extended key can only be used to derive non-hardened child public extended keys. As enumerated in BIP0032 "knowledge of the extended public key plus any non-hardened private key descending from it is equivalent to knowing the extended private key (and thus every private and public key descending from it). This means that extended public keys must be treated more carefully than regular public keys. It is also the reason for the existence of hardened keys, and why they are used for the account level in the tree. This way, a leak of an account-specific (or below) private key never risks compromising the master or other accounts."
Neutering a Private Extended Key ¶
A private extended key can be converted to a new instance of the corresponding public extended key with the Neuter function. The original extended key is not modified. A public extended key is still capable of deriving non-hardened child public extended keys.
Serializing and Deserializing Extended Keys ¶
Extended keys are serialized and deserialized with the String and NewKeyFromString functions. The serialized key is a Base58-encoded string which looks like the following:
public key: xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw private key: xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7
Network ¶
Extended keys are much like normal Bitcoin addresses in that they have version bytes which tie them to a specific network. The SetNet and IsForNet functions are provided to set and determinine which network an extended key is associated with.
Index ¶
- Constants
- Variables
- func GenerateSeed(length uint8) ([]byte, error)
- func HDPrivateKeyToPublicKeyID(id []byte) ([]byte, error)
- func Hash160(buf []byte) []byte
- type ExtendedKey
- func (k *ExtendedKey) Address(pkhaid [2]byte) (*address.AddressPubKeyHash, error)
- func (k *ExtendedKey) Child(i uint32) (*ExtendedKey, error)
- func (k *ExtendedKey) ECPrivKey() (*btcec.PrivateKey, error)
- func (k *ExtendedKey) ECPubKey() (*btcec.PublicKey, error)
- func (k *ExtendedKey) IsForNet(hdId [4]byte) bool
- func (k *ExtendedKey) IsPrivate() bool
- func (k *ExtendedKey) Neuter() (*ExtendedKey, error)
- func (k *ExtendedKey) ParentFingerprint() uint32
- func (k *ExtendedKey) SetNet(hdIdPriv, hdIdPub [4]byte)
- func (k *ExtendedKey) String() (string, error)
- func (k *ExtendedKey) Zero()
Constants ¶
const ( // RecommendedSeedLen is the recommended length in bytes for a seed // to a master node. RecommendedSeedLen = 32 // 256 bits // HardenedKeyStart is the index at which a hardended key starts. Each // extended key has 2^31 normal child keys and 2^31 hardned child keys. // Thus the range for normal child keys is [0, 2^31 - 1] and the range // for hardened child keys is [2^31, 2^32 - 1]. HardenedKeyStart = 0x80000000 // 2^31 // MinSeedBytes is the minimum number of bytes allowed for a seed to // a master node. MinSeedBytes = 16 // 128 bits // MaxSeedBytes is the maximum number of bytes allowed for a seed to // a master node. MaxSeedBytes = 64 // 512 bits )
Variables ¶
var ( // ErrDeriveHardFromPublic describes an error in which the caller // attempted to derive a hardened extended key from a public key. ErrDeriveHardFromPublic = errors.New("cannot derive a hardened key " + "from a public key") // ErrNotPrivExtKey describes an error in which the caller attempted // to extract a private key from a public extended key. ErrNotPrivExtKey = errors.New("unable to create private keys from a " + "public extended key") // ErrInvalidChild describes an error in which the child at a specific // index is invalid due to the derived key falling outside of the valid // range for secp256k1 private keys. This error indicates the caller // should simply ignore the invalid child extended key at this index and // increment to the next index. ErrInvalidChild = errors.New("the extended key at this index is invalid") // ErrUnusableSeed describes an error in which the provided seed is not // usable due to the derived key falling outside of the valid range for // secp256k1 private keys. This error indicates the caller must choose // another seed. ErrUnusableSeed = errors.New("unusable seed") // ErrInvalidSeedLen describes an error in which the provided seed or // seed length is not in the allowed range. ErrInvalidSeedLen = fmt.Errorf("seed length must be between %d and %d "+ "bits", MinSeedBytes*8, MaxSeedBytes*8) // ErrBadChecksum describes an error in which the checksum encoded with // a serialized extended key does not match the calculated value. ErrBadChecksum = errors.New("bad extended key checksum") // ErrInvalidKeyLen describes an error in which the provided serialized // key is not the expected length. ErrInvalidKeyLen = errors.New("the provided serialized extended key " + "length is invalid") )
var MainHDCoinType = uint32(20)
var MainHDPrivateKeyID = [4]byte{0x02, 0xfd, 0xa4, 0xe8} // starts with dprv
Magics.
var MainHDPublicKeyID = [4]byte{0x02, 0xfd, 0xa9, 0x26} // starts with dpub
var RegHDCoinType = uint32(10)
var RegHDPrivateKeyID = [4]byte{0x02, 0x2d, 0xbb, 0x24} // starts with Tprv
var RegHDPublicKeyID = [4]byte{0x02, 0x2d, 0xbf, 0x5d} // starts with Tpub
var SimHDCoinType = uint32(115)
var SimHDPrivateKeyID = [4]byte{0x04, 0x20, 0xb9, 0x03} // starts with sprv
var SimHDPublicKeyID = [4]byte{0x04, 0x20, 0xbd, 0x3d} // starts with spub
var TestHDCoinType = uint32(11)
var TestHDPrivateKeyID = [4]byte{0x04, 0x35, 0x83, 0x97} // starts with tprv
var TestHDPublicKeyID = [4]byte{0x04, 0x35, 0x87, 0xd1} // starts with tpub
Functions ¶
func GenerateSeed ¶
GenerateSeed returns a cryptographically secure random seed that can be used as the input for the NewMaster function to generate a new master node.
The length is in bytes and it must be between 16 and 64 (128 to 512 bits). The recommended length is 32 (256 bits) as defined by the RecommendedSeedLen constant.
func HDPrivateKeyToPublicKeyID ¶
HDPrivateKeyToPublicKeyID accepts a private hierarchical deterministic extended key id and returns the associated public key id. When the provided id is not registered, the ErrUnknownHDKeyID error will be returned.
Types ¶
type ExtendedKey ¶
type ExtendedKey struct {
// contains filtered or unexported fields
}
ExtendedKey houses all the information needed to support a hierarchical deterministic extended key. See the package overview documentation for more details on how to use extended keys.
func NewKeyFromString ¶
func NewKeyFromString(key string) (*ExtendedKey, error)
NewKeyFromString returns a new extended key instance from a base58-encoded extended key.
func NewMaster ¶
func NewMaster(seed []byte, hdPrivateKeyID [4]byte) (*ExtendedKey, error)
NewMaster creates a new master node for use in creating a hierarchical deterministic key chain. The seed must be between 128 and 512 bits and should be generated by a cryptographically secure random generation source.
NOTE: There is an extremely small chance (< 1 in 2^127) the provided seed will derive to an unusable secret key. The ErrUnusable error will be returned if this should occur, so the caller must check for it and generate a new seed accordingly.
func (*ExtendedKey) Address ¶
func (k *ExtendedKey) Address(pkhaid [2]byte) (*address.AddressPubKeyHash, error)
Address converts the extended key to a standard bitcoin pay-to-pubkey-hash address for the passed network.
func (*ExtendedKey) Child ¶
func (k *ExtendedKey) Child(i uint32) (*ExtendedKey, error)
Child returns a derived child extended key at the given index. When this extended key is a private extended key (as determined by the IsPrivate function), a private extended key will be derived. Otherwise, the derived extended key will be also be a public extended key.
When the index is greater to or equal than the HardenedKeyStart constant, the derived extended key will be a hardened extended key. It is only possible to derive a hardended extended key from a private extended key. Consequently, this function will return ErrDeriveHardFromPublic if a hardened child extended key is requested from a public extended key.
A hardened extended key is useful since, as previously mentioned, it requires a parent private extended key to derive. In other words, normal child extended public keys can be derived from a parent public extended key (no knowledge of the parent private key) whereas hardened extended keys may not be.
NOTE: There is an extremely small chance (< 1 in 2^127) the specific child index does not derive to a usable child. The ErrInvalidChild error will be returned if this should occur, and the caller is expected to ignore the invalid child and simply increment to the next index.
func (*ExtendedKey) ECPrivKey ¶
func (k *ExtendedKey) ECPrivKey() (*btcec.PrivateKey, error)
ECPrivKey converts the extended key to a btcec private key and returns it. As you might imagine this is only possible if the extended key is a private extended key (as determined by the IsPrivate function). The ErrNotPrivExtKey error will be returned if this function is called on a public extended key.
func (*ExtendedKey) ECPubKey ¶
func (k *ExtendedKey) ECPubKey() (*btcec.PublicKey, error)
ECPubKey converts the extended key to a btcec public key and returns it.
func (*ExtendedKey) IsForNet ¶
func (k *ExtendedKey) IsForNet(hdId [4]byte) bool
IsForNet returns whether or not the extended key is associated with the passed bitcoin network.
func (*ExtendedKey) IsPrivate ¶
func (k *ExtendedKey) IsPrivate() bool
IsPrivate returns whether or not the extended key is a private extended key.
A private extended key can be used to derive both hardened and non-hardened child private and public extended keys. A public extended key can only be used to derive non-hardened child public extended keys.
func (*ExtendedKey) Neuter ¶
func (k *ExtendedKey) Neuter() (*ExtendedKey, error)
Neuter returns a new extended public key from this extended private key. The same extended key will be returned unaltered if it is already an extended public key.
As the name implies, an extended public key does not have access to the private key, so it is not capable of signing transactions or deriving child extended private keys. However, it is capable of deriving further child extended public keys.
func (*ExtendedKey) ParentFingerprint ¶
func (k *ExtendedKey) ParentFingerprint() uint32
ParentFingerprint returns a fingerprint of the parent extended key from which this one was derived.
func (*ExtendedKey) SetNet ¶
func (k *ExtendedKey) SetNet(hdIdPriv, hdIdPub [4]byte)
SetNet associates the extended key, and any child keys yet to be derived from it, with the passed network.
func (*ExtendedKey) String ¶
func (k *ExtendedKey) String() (string, error)
String returns the extended key as a human-readable base58-encoded string.
func (*ExtendedKey) Zero ¶
func (k *ExtendedKey) Zero()
Zero manually clears all fields and bytes in the extended key. This can be used to explicitly clear key material from memory for enhanced security against memory scraping. This function only clears this particular key and not any children that have already been derived.