btcd/btcec/schnorr/pubkey.go
Olaoluwa Osuntokun d6d38ad4ae
btcec/v2/schnorr: add initial BIP-340 schnorr sig implementation
In this commit, we add an initial implementation of BIP-340. Mirroring
the recently added `ecsda` package, we create a new `schnorr` package
with a unique `Signature` type and `ParsePubkey` function. The new
`Signature` type implements the fixed-sized 64-byte signatures, and the
`ParsePubkey` method only accepts pubkeys that are 32-bytes in length,
with an implicit sign byte.

The signing implementation by default, deviates from BIP-340 as it opts
to use rfc6979 deterministic signatures by default, which means callers
don't need to always pass in their own `auxNonce` randomness. A set of
functional arguments allows callers to pass in their own value, which is
the way all the included test vectors function.

The other optional functional argument added is the `FastSign` option
that allows callers to skip the final step of verifying each signature
they generate.
2022-01-31 14:25:47 -08:00

50 lines
1.5 KiB
Go

// Copyright (c) 2013-2017 The btcsuite developers
// Copyright (c) 2015-2021 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package schnorr
import (
"fmt"
"github.com/btcsuite/btcd/btcec/v2"
secp "github.com/decred/dcrd/dcrec/secp256k1/v4"
)
// These constants define the lengths of serialized public keys.
const (
PubKeyBytesLen = 32
)
// ParsePubKey parses a public key for a koblitz curve from a bytestring into a
// btcec.Publickey, verifying that it is valid. It only supports public keys in
// the BIP-340 32-byte format.
func ParsePubKey(pubKeyStr []byte) (*btcec.PublicKey, error) {
if pubKeyStr == nil {
err := fmt.Errorf("nil pubkey byte string")
return nil, err
}
if len(pubKeyStr) != PubKeyBytesLen {
err := fmt.Errorf("bad pubkey byte string size (want %v, have %v)",
PubKeyBytesLen, len(pubKeyStr))
return nil, err
}
// We'll manually prepend the compressed byte so we can re-use the
// existing pubkey parsing routine of the main btcec package.
var keyCompressed [btcec.PubKeyBytesLenCompressed]byte
keyCompressed[0] = secp.PubKeyFormatCompressedEven
copy(keyCompressed[1:], pubKeyStr)
return btcec.ParsePubKey(keyCompressed[:])
}
// SerializePubKey serializes a public key as specified by BIP 340. Public keys
// in this format are 32 bytes in length, and are assumed to have an even y
// coordinate.
func SerializePubKey(pub *btcec.PublicKey) []byte {
pBytes := pub.SerializeCompressed()
return pBytes[1:]
}