waddrmgr: add ability to store encrypt master HD priv/pub keys

In this commit, we create new key spaces to allow users to store the
encrypted master priv/pub keys. This is required as in order to create
new scopes, we must do hardened derivation from the root key.
This commit is contained in:
Olaoluwa Osuntokun 2018-02-13 21:00:44 -08:00
parent e8755c2bc2
commit 946ca2da1e

View file

@ -229,6 +229,17 @@ var (
// flag, the master private key (encrypted), the master HD private key // flag, the master private key (encrypted), the master HD private key
// (encrypted), and also versioning information. // (encrypted), and also versioning information.
mainBucketName = []byte("main") mainBucketName = []byte("main")
// masterHDPrivName is the name of the key that stores the master HD
// private key. This key is encrypted with the master private crypto
// encryption key. This resides under the main bucket.
masterHDPrivName = []byte("mhdpriv")
// masterHDPubName is the name of the key that stores the master HD
// public key. This key is encrypted with the master public crypto
// encryption key. This reside under the main bucket.
masterHDPubName = []byte("mhdpub")
// syncBucketName is the name of the bucket that stores the current // syncBucketName is the name of the bucket that stores the current
// sync state of the root manager. // sync state of the root manager.
syncBucketName = []byte("sync") syncBucketName = []byte("sync")
@ -522,6 +533,62 @@ func putCoinTypeKeys(ns walletdb.ReadWriteBucket, scope *KeyScope,
return nil return nil
} }
// putMasterHDKeys stores the encrypted master HD keys in the top level main
// bucket. These are required in order to create any new manager scopes, as
// those are created via hardened derivation of the children of this key.
func putMasterHDKeys(ns walletdb.ReadWriteBucket, masterHDPrivEnc, masterHDPubEnc []byte) error {
// As this is the key for the root manager, we don't need to fetch any
// particular scope, and can insert directly within the main bucket.
bucket := ns.NestedReadWriteBucket(mainBucketName)
// Now that we have the main bucket, we can directly store each of the
// relevant keys. If we're in watch only mode, then some or all of
// these keys might not be available.
if masterHDPrivEnc != nil {
err := bucket.Put(masterHDPrivName, masterHDPrivEnc)
if err != nil {
str := "failed to store encrypted master HD private key"
return managerError(ErrDatabase, str, err)
}
}
if masterHDPubEnc != nil {
err := bucket.Put(masterHDPubName, masterHDPubEnc)
if err != nil {
str := "failed to store encrypted master HD public key"
return managerError(ErrDatabase, str, err)
}
}
return nil
}
// fetchMasterHDKeys attempts to fetch both the master HD private and public
// keys from the database. If this is a watch only wallet, then it's possible
// that the master private key isn't stored.
func fetchMasterHDKeys(ns walletdb.ReadBucket) ([]byte, []byte, error) {
bucket := ns.NestedReadBucket(mainBucketName)
var masterHDPrivEnc, masterHDPubEnc []byte
// First, we'll try to fetch the master private key. If this database
// is watch only, or the master has been neutered, then this won't be
// found on disk.
key := bucket.Get(masterHDPrivName)
if key != nil {
masterHDPrivEnc = make([]byte, len(key))
copy(masterHDPrivEnc[:], key)
}
key = bucket.Get(masterHDPubName)
if key != nil {
masterHDPubEnc = make([]byte, len(key))
copy(masterHDPubEnc[:], key)
}
return masterHDPrivEnc, masterHDPubEnc, nil
}
// fetchCryptoKeys loads the encrypted crypto keys which are in turn used to // fetchCryptoKeys loads the encrypted crypto keys which are in turn used to
// protect the extended keys, imported keys, and scripts. Any of the returned // protect the extended keys, imported keys, and scripts. Any of the returned
// values can be nil, but in practice only the crypto private and script keys // values can be nil, but in practice only the crypto private and script keys