// Sign creates a signature on the hash under the given secret key. func Sign(sk *eckey.SecretKey, hash []byte) (*Signature, error) { // Generate random nonce nonce: k, kG, err := eckey.GenerateKeyPair() if err != nil { return nil, err } // Try again if kG is nil (point at infinity) if kG == nil { goto nonce } // Clear nonce after completion defer k.Zero() // Compute non-interactive challenge e := util.Hash256d(append([]byte(hash), kG[:]...)) kInt := new(big.Int).SetBytes(k[:]) eInt := new(big.Int).SetBytes(e[:]) rInt := new(big.Int).SetBytes(sk[:]) // Compute s = k - er s := new(big.Int) s.Mul(eInt, rInt) s.Sub(kInt, s) s.Mod(s, eckey.S256.N) // Serialize signature sig := new(Signature) copy(sig[:SignatureSize/2], e[:]) util.PaddedCopy(sig[SignatureSize/2:], s.Bytes(), SignatureSize/2) return sig, nil }
// Verify determines whether or not the signature is on the given hash and // belongs to the public key. func Verify(sig *Signature, pk *eckey.PublicKey, hash []byte) error { // Deserialize public key pkx, pky := pk.Coords() // Compute sG + ePK = (k-er)G + erG = kG sGx, sGy := eckey.S256.ScalarBaseMult(sig[SignatureSize/2:]) ePKx, ePKy := eckey.S256.ScalarMult(pkx, pky, sig[:SignatureSize/2]) kGx, kGy := eckey.S256.Add(sGx, sGy, ePKx, ePKy) // Serialize point kG, err := eckey.NewPublicKeyCoords(kGx, kGy) if err != nil { return err } // Compute non-interactive challenge e := util.Hash256d(append([]byte(hash), kG[:]...)) // Compare digest with first half of signature for i, b := range e { if sig[i] != b { return ErrECSchnorrVerify } } return nil }
// 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 }