Skip to content

Commit

Permalink
btcec/v2/schnorr: add initial BIP-340 schnorr sig implementation
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Roasbeef committed Jan 12, 2022
1 parent 7edc8c8 commit 162926e
Show file tree
Hide file tree
Showing 6 changed files with 875 additions and 17 deletions.
6 changes: 6 additions & 0 deletions btcec/go.mod
Expand Up @@ -7,3 +7,9 @@ require (
github.com/davecgh/go-spew v1.1.1
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1
)

require github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect

// We depend on chainhash as is, so we need to raplce to use the version of
// chainhash included in the version of btcd we're buidling in.
replace github.com/btcsuite/btcd => ../../
25 changes: 25 additions & 0 deletions btcec/schnorr/error.go
@@ -0,0 +1,25 @@
// 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 (
ecdsa_schnorr "github.com/decred/dcrd/dcrec/secp256k1/v4/schnorr"
)

// ErrorKind identifies a kind of error. It has full support for errors.Is
// and errors.As, so the caller can directly check against an error kind
// when determining the reason for an error.
type ErrorKind = ecdsa_schnorr.ErrorKind

// Error identifies an error related to a schnorr signature. It has full
// support for errors.Is and errors.As, so the caller can ascertain the
// specific reason for the error by checking the underlying error.
type Error = ecdsa_schnorr.Error

// signatureError creates an Error given a set of arguments.
func signatureError(kind ErrorKind, desc string) Error {
return Error{Err: kind, Description: desc}
}
48 changes: 48 additions & 0 deletions btcec/schnorr/pubkey.go
@@ -0,0 +1,48 @@
// 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"
)

// 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
// ecdsa.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] = btcec.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:]
}

0 comments on commit 162926e

Please sign in to comment.