示例#1
0
// 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
}
示例#2
0
// 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
}
示例#3
0
// 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
}