Skip to content

Commit 0175dde

Browse files
committed
more doc
1 parent 4f04b68 commit 0175dde

16 files changed

+195
-102
lines changed

bytes.go

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package bip32
22

3+
// ReverseCopy works in the opposite direction as the built-in copy()
34
func ReverseCopy(dst, src []byte) {
45
for i, j := len(dst)-1, len(src)-1; i >= 0 && j >= 0; i, j = i-1, j-1 {
56
dst[i] = src[j]

conf.go

-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
package bip32
22

3-
// masterKey is the master key used along with a random seed used to generate
4-
// the master node in the hierarchical tree.
5-
var masterKey = []byte("Bitcoin seed")
6-
73
// masterHMACKey is the key used along with a random seed used to generate
84
// the master key in the hierarchical tree.
95
var masterHMACKey = []byte("Bitcoin seed")

constant.go

+5-10
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,6 @@ const (
1818
// MaxSeedBytes is the maximum number of bytes allowed for a seed to
1919
// a master node.
2020
MaxSeedBytes = 64 // 512 bits
21-
22-
// serializedKeyLen is the length of a serialized public or private
23-
// extended key. It consists of 4 bytes version, 1 byte depth, 4 bytes
24-
// fingerprint, 4 bytes child number, 32 bytes chain code, and 33 bytes
25-
// public/private key data.
26-
serializedKeyLen = 4 + 1 + 4 + 4 + 32 + 33 // 78 bytes
27-
28-
// maxUint8 is the max positive integer which can be serialized in a uint8
29-
maxUint8 = 1<<8 - 1
3021
)
3122

3223
// length constants about fields of key serialization
@@ -37,6 +28,10 @@ const (
3728
ChildIndexLen = 4
3829
ChainCodeLen = 32
3930
KeyDataLen = 33
40-
KeyLen = VersionLen + DepthLen + FingerprintLen +
31+
// KeyLen is the length of a serialized public or private
32+
// extended key. It consists of 4 bytes version, 1 byte depth, 4 bytes
33+
// fingerprint, 4 bytes child number, 32 bytes chain code, and 33 bytes
34+
// public/private key data.
35+
KeyLen = VersionLen + DepthLen + FingerprintLen +
4136
ChildIndexLen + ChainCodeLen + KeyDataLen
4237
)

doc.go

+18-15
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Copyright (c) 2018 sammy00
12
// Copyright (c) 2014 The btcsuite developers
23
// Use of this source code is governed by an ISC
34
// license that can be found in the LICENSE file.
@@ -12,39 +13,41 @@ The ability to implement hierarchical deterministic wallets depends on the
1213
ability to create and derive hierarchical deterministic extended keys.
1314
1415
At a high level, this package provides support for those hierarchical
15-
deterministic extended keys by providing an ExtendedKey type and supporting
16-
functions. Each extended key can either be a private or public extended key
17-
which itself is capable of deriving a child extended key.
16+
deterministic extended keys specified as the ExtendedKey interface, which is
17+
implemented by PrivateKey and PublicKey.Therefore, each extended key can either
18+
be a private or public extended key which itself is capable of deriving a child
19+
extended key.
1820
1921
Determining the Extended Key Type
2022
21-
Whether an extended key is a private or public extended key can be determined
22-
with the IsPrivate function.
23+
Whether an extended key is a private or public extended key can be type assertion against the PrivateKey type.
2324
2425
Transaction Signing Keys and Payment Addresses
2526
2627
In order to create and sign transactions, or provide others with addresses to
2728
send funds to, the underlying key and address material must be accessible. This
28-
package provides the ECPubKey, ECPrivKey, and Address functions for this
29-
purpose.
29+
package provides the ECPubKey, ECPrivKey, and AddressPubKeyHash functions for
30+
this purpose.
3031
3132
The Master Node
3233
3334
As previously mentioned, the extended keys are hierarchical meaning they are
3435
used to form a tree. The root of that tree is called the master node and this
35-
package provides the NewMaster function to create it from a cryptographically
36-
random seed. The GenerateSeed function is provided as a convenient way to
37-
create a random seed for use with the NewMaster function.
36+
package provides the NewMasterKey function to create it from a cryptographically
37+
random seed. The GenerateMasterKey function is provided as a convenient way to
38+
create a random extended private key for use where the seed would be read from
39+
the provided rand entropy reader.
3840
3941
Deriving Children
4042
4143
Once you have created a tree root (or have deserialized an extended key as
4244
discussed later), the child extended keys can be derived by using the Child
4345
function. The Child function supports deriving both normal (non-hardened) and
4446
hardened child extended keys. In order to derive a hardened extended key, use
45-
the HardenedKeyStart constant + the hardened key number as the index to the
46-
Child function. This provides the ability to cascade the keys into a tree and
47-
hence generate the hierarchical deterministic key chains.
47+
the mapping function HardenIndex(i) to get the corresponding index for
48+
generating harden child to the Child function. This provides the ability to
49+
cascade the keys into a tree and hence generate the hierarchical deterministic
50+
key chains.
4851
4952
Normal vs Hardened Child Extended Keys
5053
@@ -69,8 +72,8 @@ public extended keys.
6972
Serializing and Deserializing Extended Keys
7073
7174
Extended keys are serialized and deserialized with the String and
72-
NewKeyFromString functions. The serialized key is a Base58-encoded string which
73-
looks like the following:
75+
ParsePrivateKey/ParsePublicKey functions. The serialized key is a
76+
Base58-encoded string which looks like the following:
7477
public key: xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw
7578
private key: xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7
7679

errors.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@ var (
1616
ErrDeriveBeyondMaxDepth = errors.New("cannot derive a key with more than " +
1717
"255 indices in its path")
1818

19-
// ErrNotPrivExtKey describes an error in which the caller attempted
20-
// to extract a private key from a public extended key.
21-
ErrNotPrivExtKey = errors.New("unable to create private keys from a " +
22-
"public extended key")
23-
2419
// ErrInvalidChild describes an error in which the child at a specific
2520
// index is invalid due to the derived key falling outside of the valid
2621
// range for secp256k1 private keys. This error indicates the caller
@@ -48,5 +43,6 @@ var (
4843
ErrInvalidKeyLen = errors.New("the provided serialized extended key " +
4944
"length is invalid")
5045

46+
// ErrNoEnoughEntropy signals more entropy is needed
5147
ErrNoEnoughEntropy = errors.New("more entropy is needed")
5248
)

extended_key.go

+53
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,68 @@ package bip32
22

33
import "github.com/btcsuite/btcd/btcec"
44

5+
// ExtendedKey specifies the basic api for a extended private or public key.
6+
// TODO: add the Zero method manually clears all fields and bytes in the
7+
// extended key. This can be used to explicitly clear key material from memory
8+
// for enhanced security against memory scraping. This function only clears
9+
// this particular key and not any children that have already been derived.
510
type ExtendedKey interface {
11+
// AddressPubKeyHash returns the public key hash (20 bytes) derived from the
12+
// key, which would be itself for public keys and the extended public key
13+
// bound to it for private keys
614
AddressPubKeyHash() []byte
15+
// Child returns a derived child extended key at the given index. When this
16+
// extended key is a private extended key (as determined by the IsPrivate
17+
// function), a private extended key will be derived. Otherwise, the derived
18+
// extended key will be also be a public extended key.
19+
//
20+
// When the index is greater to or equal than the HardenedKeyStart constant,
21+
// the derived extended key will be a hardened extended key. It is only
22+
// possible to derive a hardended extended key from a private extended key.
23+
// Consequently, this function will return ErrDeriveHardFromPublic if a
24+
// hardened child extended key is requested from a public extended key.
25+
//
26+
// A hardened extended key is useful since, as previously mentioned, it
27+
// requires a parent private extended key to derive. In other words, normal
28+
// child extended public keys can be derived from a parent public extended
29+
// key (no knowledge of the parent private key) whereas hardened extended
30+
// keys may not be.
31+
//
32+
// NOTE: There is an extremely small chance (< 1 in 2^127) the specific child
33+
// index does not derive to a usable child. The ErrInvalidChild error should
34+
// be returned if this should occur, and the caller is expected to ignore the
35+
// invalid child and simply increment to the next index.
736
Child(i uint32) (ExtendedKey, error)
37+
// Depth returns the current derivation level with respect to the root.
38+
//
39+
// The root key has depth zero, and the field has a maximum of 255 due to
40+
// how depth is serialized.
841
Depth() uint8
42+
// Hardened tells if the key of interest is hardened, whose index is greater
43+
// than HardenedKeyStart.
944
Hardened() bool
45+
// Index returns the index of the key seen from its parent.
1046
Index() uint32
47+
// IsForNet checks if this key is in use for a given net specified by keyID
1148
IsForNet(keyID Magic) bool
49+
50+
// Neuter returns a new extended public key from a extended private key. The
51+
// same extended key will be returned unaltered if it is already an extended
52+
// public key.
53+
//
54+
// As the name implies, an extended public key does not have access to the
55+
// private key, so it is not capable of signing transactions or deriving
56+
// child extended private keys. However, it is capable of deriving further
57+
// child extended public keys.
58+
Neuter() (*PublicKey, error)
59+
// ParentFingerprint returns a fingerprint of the parent extended key from
60+
// which this one was derived.
1261
ParentFingerprint() uint32
62+
// Public converts the extended key to a btcec public key and returns it.
1363
Public() (*btcec.PublicKey, error)
64+
// SetNet associates the extended key, and any child keys yet to be derived
65+
// from it, with the passed network.
1466
SetNet(keyID Magic)
67+
// String returns the extended key as a human-readable base58-encoded string.
1568
String() string
1669
}

golden.go

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
// +build ignore
2+
// Package main is a utility to format the test vectors provided in
3+
// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vectors
4+
// into the golden file for testing.
25

36
package main
47

goldie_test.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ import (
88
)
99

1010
type childGoldie struct {
11-
parent string
12-
//index uint32
11+
parent string
1312
ChildIndex *bip32.ChildIndex
1413
child string // the expected child string
1514
}

internal.go

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import (
77
"github.com/sammy00/base58"
88
)
99

10+
// appendMeta serialize the meta part of the given public key
11+
// into bytes sequence and then append them to the buf, the address
12+
// of which will be return.
1013
func appendMeta(buf []byte, pub *PublicKey) []byte {
1114
var childIndex [ChildIndexLen]byte
1215
binary.BigEndian.PutUint32(childIndex[:], pub.ChildIndex)
@@ -69,6 +72,8 @@ func decodePublicKey(data58 string) (*PublicKey, error) {
6972
return pub, nil
7073
}
7174

75+
// derivePublicKey calculates the public key corresponding to the input
76+
// private key, and output the public key data in compressed form.
7277
func derivePublicKey(priv []byte) []byte {
7378
// load the public key data eagerly
7479
x, y := secp256k1Curve.ScalarBaseMult(priv)

magics.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package bip32
22

3+
// MagicLen is the length of magic bytes for generating human-readble prefix
4+
// of the base58-encoded key
35
const MagicLen = 4
46

7+
// Magic represents the buffer to hold the magic bytes.
58
type Magic [MagicLen]byte
69

7-
// magic bytes as version prefix for serialization
10+
// magic bytes as version prefix for serialization, and their application goes
11+
// as named.
812
var (
913
MainNetPrivateKey = &Magic{0x04, 0x88, 0xad, 0xe4} // starts with xprv
1014
MainNetPublicKey = &Magic{0x04, 0x88, 0xb2, 0x1e} // starts with xpub

master_key.go

+8-37
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import (
66
"io"
77
)
88

9+
// GenerateMasterKey is a more convinient implemenation w.r.t to
10+
// NewMasterKey. The seed needed is read from the given entropy source
11+
// rand, and the seed length is optional which would be RecommendedSeedLen
12+
// if omitted.
913
func GenerateMasterKey(rand io.Reader, keyID Magic,
1014
strength ...int) (*PrivateKey, error) {
1115
seedLen := RecommendedSeedLen
@@ -43,45 +47,14 @@ func GenerateMasterKey(rand io.Reader, keyID Magic,
4347
return newMaster(seed, keyID)
4448
}
4549

46-
/*
47-
// NewMaster creates a new master node for use in creating a hierarchical
50+
// NewMasterKey creates a new master node for use in creating a hierarchical
4851
// deterministic key chain. The seed must be between 128 and 512 bits and
4952
// should be generated by a cryptographically secure random generation source.
5053
//
5154
// NOTE: There is an extremely small chance (< 1 in 2^127) the provided seed
5255
// will derive to an unusable secret key. The ErrUnusable error will be
5356
// returned if this should occur, so the caller must check for it and generate a
5457
// new seed accordingly.
55-
func NewMaster(seed []byte, net *chaincfg.Params) (*ExtendedKey, error) {
56-
// Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes].
57-
if len(seed) < MinSeedBytes || len(seed) > MaxSeedBytes {
58-
return nil, ErrInvalidSeedLen
59-
}
60-
61-
// First take the HMAC-SHA512 of the master key and the seed data:
62-
// I = HMAC-SHA512(Key = "Bitcoin seed", Data = S)
63-
hmac512 := hmac.New(sha512.New, masterKey)
64-
hmac512.Write(seed)
65-
lr := hmac512.Sum(nil)
66-
67-
// Split "I" into two 32-byte sequences Il and Ir where:
68-
// Il = master secret key
69-
// Ir = master chain code
70-
secretKey := lr[:len(lr)/2]
71-
chainCode := lr[len(lr)/2:]
72-
73-
// Ensure the key in usable.
74-
secretKeyNum := new(big.Int).SetBytes(secretKey)
75-
if secretKeyNum.Cmp(btcec.S256().N) >= 0 || secretKeyNum.Sign() == 0 {
76-
return nil, ErrUnusableSeed
77-
}
78-
79-
parentFP := []byte{0x00, 0x00, 0x00, 0x00}
80-
return NewExtendedKey(net.HDPrivateKeyID[:], secretKey, chainCode,
81-
parentFP, 0, 0, true), nil
82-
}
83-
*/
84-
8558
func NewMasterKey(seed []byte, keyID Magic) (*PrivateKey, error) {
8659
// Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes].
8760
if len(seed) < MinSeedBytes || len(seed) > MaxSeedBytes {
@@ -91,24 +64,22 @@ func NewMasterKey(seed []byte, keyID Magic) (*PrivateKey, error) {
9164
return newMaster(seed, keyID)
9265
}
9366

67+
// newMaster is helper function to derives a extended private key based on the
68+
// given valid seed and the provided keyID
9469
func newMaster(seed []byte, keyID Magic) (*PrivateKey, error) {
9570
// I = HMAC-SHA512(Key = "Bitcoin seed", Data = S)
96-
hmac512 := hmac.New(sha512.New, masterKey)
71+
hmac512 := hmac.New(sha512.New, masterHMACKey)
9772
hmac512.Write(seed)
9873
I := hmac512.Sum(nil)
9974

10075
secretKey, chainCode := I[:len(I)/2], I[len(I)/2:]
10176
// Ensure the key in usable.
10277
if _, ok := ToUsableScalar(secretKey); !ok {
103-
//if !ScalarUsable(secretKey) {
10478
return nil, ErrUnusableSeed
10579
}
10680

10781
// fingerprint of parent
10882
parentFP := []byte{0x00, 0x00, 0x00, 0x00}
10983

110-
//return NewExtendedKey(keyID[:], secretKey, chainCode,
111-
// parentFP, 0, 0, true), nil
112-
11384
return NewPrivateKey(keyID[:], 0, parentFP, 0, chainCode, secretKey), nil
11485
}

0 commit comments

Comments
 (0)