Skip to content

Commit

Permalink
fixup! btcec/v2/schnorr: add initial BIP-340 schnorr sig implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Roasbeef committed Dec 6, 2021
1 parent f922c95 commit 70ae843
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 28 deletions.
6 changes: 3 additions & 3 deletions btcec/v2/schnorr/pubkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ func ParsePubKey(pubKeyStr []byte) (*btcec.PublicKey, error) {
return nil, err
}

// We'll manually append the compressed so we can re-use the existing
// pubkey parsing routine of the main btcec package.
// 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] = pubkeyCompressed
keyCompressed[0] = btcec.PubKeyFormatCompressedEven
copy(keyCompressed[1:], pubKeyStr)

return btcec.ParsePubKey(keyCompressed[:])
Expand Down
11 changes: 10 additions & 1 deletion btcec/v2/schnorr/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func (sig Signature) IsEqual(otherSig *Signature) bool {
// This differs from the exported Verify method in that it returns a specific
// error to support better testing while the exported method simply returns a
// bool indicating success or failure.
func schnorrVerify(sig *Signature, hash []byte, pubKey *btcec.PublicKey) error {
func schnorrVerify(sig *Signature, hash []byte, pub *btcec.PublicKey) error {
// The algorithm for producing a BIP-340 signature is described in
// README.md and is reproduced here for reference:
//
Expand All @@ -148,6 +148,15 @@ func schnorrVerify(sig *Signature, hash []byte, pubKey *btcec.PublicKey) error {
return signatureError(ecdsa_schnorr.ErrInvalidHashLen, str)
}

// Before we proceed, we want to ensure that the public key we're using
// for verification always has an even y-coordinate. So we'll serialize
// it, then parse it again to esure we only proceed with points that
// have an even y-coordinate.
pubKey, err := ParsePubKey(pub.SerializeCompressed()[1:])
if err != nil {
return err
}

// Step 2.
//
// Fail if Q is not a point on the curve
Expand Down
51 changes: 27 additions & 24 deletions btcec/v2/schnorr/signature_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,36 +154,38 @@ func TestSchnorrSign(t *testing.T) {
t.Parallel()

for i, test := range bip340TestVectors {
if len(test.secretKey) != 0 {
d := decodeHex(test.secretKey)
privKey, pubKey := btcec.PrivKeyFromBytes(d)
if len(test.secretKey) == 0 {
continue
}

var auxBytes [32]byte
aux := decodeHex(test.auxRand)
copy(auxBytes[:], aux)
d := decodeHex(test.secretKey)
privKey, pubKey := btcec.PrivKeyFromBytes(d)

msg := decodeHex(test.message)
var auxBytes [32]byte
aux := decodeHex(test.auxRand)
copy(auxBytes[:], aux)

sig, err := Sign(privKey, msg, CustomNonce(auxBytes))
if err != nil {
t.Fatalf("test #%v: sig generation failed: %v", i, err)
}
msg := decodeHex(test.message)

if strings.ToUpper(hex.EncodeToString(sig.Serialize())) != test.signature {
t.Fatalf("test #%v: got signature %x : "+
"want %s", i, sig.Serialize(), test.signature)
}
sig, err := Sign(privKey, msg, CustomNonce(auxBytes))
if err != nil {
t.Fatalf("test #%v: sig generation failed: %v", i, err)
}

err = schnorrVerify(sig, msg, pubKey)
if err != nil {
t.Fail()
}
if strings.ToUpper(hex.EncodeToString(sig.Serialize())) != test.signature {
t.Fatalf("test #%v: got signature %x : "+
"want %s", i, sig.Serialize(), test.signature)
}

verify := err == nil
if test.verifyResult != verify {
t.Fatalf("test #%v: verification mismatch: "+
"expected %v, got %v", i, test.verifyResult, verify)
}
err = schnorrVerify(sig, msg, pubKey)
if err != nil {
t.Fail()
}

verify := err == nil
if test.verifyResult != verify {
t.Fatalf("test #%v: verification mismatch: "+
"expected %v, got %v", i, test.verifyResult, verify)
}
}
}
Expand All @@ -192,6 +194,7 @@ func TestSchnorrVerify(t *testing.T) {
t.Parallel()

for i, test := range bip340TestVectors {

pubKeyBytes := decodeHex(test.publicKey)

pubKey, err := ParsePubKey(pubKeyBytes)
Expand Down

0 comments on commit 70ae843

Please sign in to comment.