func keyPairFromTestCase(test ecTestCase) (*eckey.SecretKey, *eckey.PublicKey) { d, _ := new(big.Int).SetString(test.D, 10) x, _ := new(big.Int).SetString(test.X, 16) y, _ := new(big.Int).SetString(test.Y, 16) // Serialize secret key sk, _ := eckey.NewSecretKeyInt(d) // Serialize public key pk, _ := eckey.NewPublicKeyCoords(x, y) return sk, pk }
// Child computes the descendant of an HDKey at the specified child number. func (k *HDKey) Child(i uint32) (*HDKey, error) { // Verify that child derivation is possible isChildHardened := i >= HardenedKeyStart if !k.IsPrivate() && isChildHardened { return nil, ErrDeriveHardenedFromPublic } // Assemble seed data for HMAC seed := make([]byte, childKeySize+childNumberSize) if isChildHardened { copy(seed, k[childKeyOffset:]) // Copy 0x00 || 32-byte secret key } else { copy(seed, k.CompressedPublicKey()[:]) // Copy HEADER || 32-byte X-coord } // Copy child number as uint32 binary.BigEndian.PutUint32(seed[childKeySize:], i) // il, ir = HMAC-512(chainCode, seed), clean up intermediary state il, childChainCode := util.HMAC512Split(k.chainCode(), seed) defer func() { util.Zero(il); util.Zero(childChainCode) }() // Left 32 bytes becomes intermediate secret key, defer clean up ilInt := new(big.Int).SetBytes(il) defer ilInt.SetUint64(0) // Check that ilInt creates valid SecretKey, clean up intermediary SecretKey isk, err := eckey.NewSecretKeyInt(ilInt) if err != nil { return nil, ErrUnusableSeed } defer isk.Zero() ver := k.version() parentCPK := k.CompressedPublicKey() fpBytes := util.Hash256d(parentCPK[:])[:fingerprintSize] fp := binary.BigEndian.Uint32(fpBytes) // If key is private, derive a child secret key if k.IsPrivate() { sk := k.computeChildSecret(ilInt) return newHDSecretKey(ver, k.depth()+1, fp, i, childChainCode, sk), nil } // Otherwise, derive child public key cpk, err := computeChildPublic(parentCPK, isk) if err != nil { return nil, err } return newHDPublicKey(ver, k.depth()+1, fp, i, childChainCode, cpk), nil }