Documentation
¶
Overview ¶
Package hdwallet implements the BIP32 and BIP44 specifications for hierarchical deterministic wallets. BIP32 defines a method for creating a hierarchical deterministic wallet, where keys are derived from a single master key using a tree structure. BIP44 defines a specific derivation path structure for interoperability between wallets.
The implementation includes:
- Creating master keys from seeds
- Deriving child keys (normal and hardened)
- Deriving keys using derivation paths
- Support for BIP44 standard paths
- Serialization to Base58Check format (xprv/xpub)
- Conversion to Wallet Import Format (WIF)
For more information, see:
Index ¶
- Constants
- Variables
- type Key
- func (k *Key) B58Serialize(isPublic bool) string
- func (k *Key) Derive(index uint32) (*Key, error)
- func (k *Key) DerivePath(path string) (*Key, error)
- func (k *Key) Fingerprint() []byte
- func (k *Key) PrivateKey() ([]byte, error)
- func (k *Key) PublicKey() []byte
- func (k *Key) SerializedSize() int
- func (k *Key) String() string
- func (k *Key) ToECDSA() (*ecdsa.PrivateKey, error)
- func (k *Key) ToWIF() (string, error)
Constants ¶
const ( // HardenedKeyStart is the index where hardened keys start HardenedKeyStart = 0x80000000 // FirstHardenedChild is the index of the first hardened child FirstHardenedChild = HardenedKeyStart // PublicKeyCompressedLength is the length of a compressed public key PublicKeyCompressedLength = 33 // PrivateKeyLength is the length of a private key PrivateKeyLength = 32 )
Variables ¶
var ( // ErrInvalidKey is returned when a key is invalid ErrInvalidKey = errors.New("hdwallet: invalid key") // ErrInvalidSeed is returned when a seed is invalid ErrInvalidSeed = errors.New("hdwallet: invalid seed") // ErrDerivingHardenedFromPublic is returned when trying to derive a hardened child from a public key ErrDerivingHardenedFromPublic = errors.New("hdwallet: cannot derive hardened child from public key") // ErrInvalidPath is returned when a derivation path is invalid ErrInvalidPath = errors.New("hdwallet: invalid derivation path") // ErrInvalidCurve is returned when the curve is invalid ErrInvalidCurve = errors.New("hdwallet: invalid curve") )
Functions ¶
This section is empty.
Types ¶
type Key ¶
type Key struct {
// ChainCode is the 32-byte chain code used in key derivation.
ChainCode []byte
// Depth is the key derivation depth (0 for master key).
Depth byte
// Index is the child index of this key (0x80000000 or higher for hardened keys).
Index uint32
// ParentFingerprint is the first 4 bytes of the parent key's hash.
ParentFingerprint []byte
// IsPrivate indicates whether this Key holds a private key (true) or a public key (false).
IsPrivate bool
// contains filtered or unexported fields
}
Key represents a BIP32 hierarchical deterministic wallet key. It contains all the information needed to derive child keys and serialize the key in various formats.
func NewMasterKey ¶
NewMasterKey creates a new master key from a seed according to the BIP32 specification. The seed must be between 16 and 64 bytes as per BIP32 requirements.
This function implements the master key generation algorithm:
- Calculate I = HMAC-SHA512(Key = "Bitcoin seed", Data = S)
- Split I into two 32-byte sequences, IL and IR
- Use IL as master secret key, and IR as master chain code
- Verify that IL is in the range [1, n-1] where n is the curve order
Parameters:
seed: A cryptographically secure random seed between 16-64 bytes
Returns:
*Key: A new master key that can be used to derive child keys error: ErrInvalidSeed if seed length is invalid, or ErrInvalidKey if the generated key is invalid
func (*Key) B58Serialize ¶
B58Serialize serializes the extended key into a Base58Check-encoded string. If isPublic is true, it serializes the extended public key; otherwise, it serializes the extended private key. The serialized format follows the BIP32 specification with version bytes:
- xprv prefix for private keys (0x0488ADE4)
- xpub prefix for public keys (0x0488B21E)
Parameters:
isPublic: If true, serialize as extended public key; if false, serialize as extended private key
Returns:
Base58Check-encoded string representation of the extended key
func (*Key) Derive ¶
Derive derives a child key at the given index according to the BIP32 specification. The index can be a normal child (0-0x7FFFFFFF) or a hardened child (0x80000000-0xFFFFFFFF).
For normal child derivation:
- Data = serP(Kpar) || ser32(i)
- Uses the parent's public key
For hardened child derivation:
- Data = 0x00 || ser256(kpar) || ser32(i)
- Uses the parent's private key and can only be done with private keys
Parameters:
index: The child index to derive. Use HardenedKeyStart (0x80000000) or higher for hardened keys
Returns:
*Key: The derived child key
error: ErrDerivingHardenedFromPublic if trying to derive a hardened child from a public key,
or ErrInvalidKey if the derived key is invalid
func (*Key) DerivePath ¶
DerivePath derives a child key at the given path according to BIP32/BIP44 specifications. Path should be in the format "m/44'/0'/0'/0/0" where:
- m: Master key
- 44': BIP44 purpose (hardened)
- 0': Coin type (hardened, 0 for Bitcoin)
- 0': Account number (hardened)
- 0: Change chain (0 for external, 1 for internal)
- 0: Address index
Hardened indices are denoted with either an apostrophe (') or 'H'.
Parameters:
path: The derivation path string in BIP32/BIP44 format
Returns:
*Key: The derived child key at the specified path error: ErrInvalidPath for invalid path formats, or errors from the Derive method
func (*Key) Fingerprint ¶
Fingerprint returns the key fingerprint as the first 4 bytes of the RIPEMD-160 hash of the SHA-256 hash of the public key, as specified in BIP32. This fingerprint is used to identify the parent key in child key derivation.
The algorithm follows BIP32 specification:
- Serialize the public key in compressed format
- Perform SHA-256 hashing on the public key
- Perform RIPEMD-160 hashing on the SHA-256 hash
- Return the first 4 bytes of the RIPEMD-160 hash
Returns:
[]byte: The 4-byte key fingerprint
func (*Key) PrivateKey ¶ added in v1.0.1
PrivateKey returns the raw 32-byte private key bytes if this Key is a private key. This method explicitly indicates that the key is intended for private operations.
Returns:
[]byte: The 32-byte private key. error: An error if the Key is not a private key (i.e., IsPrivate is false).
func (*Key) PublicKey ¶
PublicKey returns the compressed public key for this key. If the key is already a public key, it returns the keyData directly. If the key is a private key, it derives and returns the corresponding compressed public key. This method ensures that a 33-byte compressed public key is always returned.
Returns:
[]byte: The 33-byte compressed public key.
func (*Key) SerializedSize ¶
SerializedSize returns the size in bytes of the serialized extended key. Both private and public extended keys serialize to 78 bytes as per BIP32 specification. The serialization format consists of:
- 4 bytes: version
- 1 byte: depth
- 4 bytes: parent fingerprint
- 4 bytes: child number
- 32 bytes: chain code
- 33 bytes: key data (public key or 0x00 + private key)
func (*Key) String ¶
String returns a human-readable string representation of the key. It displays the type of key (private or public) along with its key data and chain code. This method is primarily intended for debugging and logging purposes.
func (*Key) ToECDSA ¶ added in v1.0.1
func (k *Key) ToECDSA() (*ecdsa.PrivateKey, error)
ToECDSA converts the private key to a standard *ecdsa.PrivateKey object. This method is useful for integrating with other Go cryptography functions that expect the standard library's ECDSA private key type.
Returns:
*ecdsa.PrivateKey: The standard library ECDSA private key. error: An error if the Key is not a private key or if the conversion fails.
func (*Key) ToWIF ¶
ToWIF converts a private key to Wallet Import Format (WIF). WIF is a format for encoding Bitcoin private keys that includes a version byte, the private key, and a checksum.
This method only works on private keys. Attempting to convert a public key will return an error.
Returns:
string: The WIF-encoded private key with a '5' prefix for mainnet error: An error if the key is not a private key