From 7542fa526880e24f525a1985c4b60ffeba980387 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 19 Mar 2020 17:50:07 -0500 Subject: [PATCH] schnorr: Accept sig type in internal verify func. This modifies the internal schnorrVerify function to accept the signature as a type instead of its raw serialized form. This will ultimately facilitate making it easier to switch over to more efficient types for the r and s components. --- dcrec/secp256k1/schnorr/signature.go | 33 +++++++++-------------- dcrec/secp256k1/schnorr/signature_test.go | 2 +- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/dcrec/secp256k1/schnorr/signature.go b/dcrec/secp256k1/schnorr/signature.go index 635c0ffa..f43a194b 100644 --- a/dcrec/secp256k1/schnorr/signature.go +++ b/dcrec/secp256k1/schnorr/signature.go @@ -86,7 +86,7 @@ func (sig Signature) IsEqual(otherSig *Signature) bool { // schnorrVerify is the internal function for verification of a secp256k1 // Schnorr signature. A secure hash function may be passed for the calculation // of r. -func schnorrVerify(sig []byte, pubkey *secp256k1.PublicKey, msg []byte, hashFunc func([]byte) []byte) (bool, error) { +func schnorrVerify(sig *Signature, pubkey *secp256k1.PublicKey, msg []byte, hashFunc func([]byte) []byte) (bool, error) { curve := secp256k1.S256() if len(msg) != scalarSize { str := fmt.Sprintf("wrong size for message (got %v, want %v)", @@ -94,11 +94,6 @@ func schnorrVerify(sig []byte, pubkey *secp256k1.PublicKey, msg []byte, hashFunc return false, schnorrError(ErrBadInputSize, str) } - if len(sig) != SignatureSize { - str := fmt.Sprintf("wrong size for signature (got %v, want %v)", - len(sig), SignatureSize) - return false, schnorrError(ErrBadInputSize, str) - } if pubkey == nil { str := fmt.Sprintf("nil pubkey") return false, schnorrError(ErrInputValue, str) @@ -109,11 +104,10 @@ func schnorrVerify(sig []byte, pubkey *secp256k1.PublicKey, msg []byte, hashFunc return false, schnorrError(ErrPointNotOnCurve, str) } - sigR := sig[:32] - sigS := sig[32:] - sigRCopy := make([]byte, scalarSize) - copy(sigRCopy, sigR) - toHash := append(sigRCopy, msg...) + rBytes := bigIntToEncodedBytes(sig.r) + toHash := make([]byte, 0, len(msg)+scalarSize) + toHash = append(toHash, rBytes[:]...) + toHash = append(toHash, msg...) h := hashFunc(toHash) hBig := new(big.Int).SetBytes(h) @@ -128,25 +122,22 @@ func schnorrVerify(sig []byte, pubkey *secp256k1.PublicKey, msg []byte, hashFunc return false, schnorrError(ErrSchnorrHashValue, str) } - // Convert s to big int. - sBig := encodedBytesToBigInt(copyBytes(sigS)) - // We also can't have s greater than the order of the curve. - if sBig.Cmp(curve.N) >= 0 { + if sig.s.Cmp(curve.N) >= 0 { str := fmt.Sprintf("s value is too big") return false, schnorrError(ErrInputValue, str) } // r can't be larger than the curve prime. - rBig := encodedBytesToBigInt(copyBytes(sigR)) - if rBig.Cmp(curve.P) == 1 { + if sig.r.Cmp(curve.P) == 1 { str := fmt.Sprintf("given R was greater than curve prime") return false, schnorrError(ErrBadSigRNotOnCurve, str) } // r' = hQ + sG + sBytes := bigIntToEncodedBytes(sig.s) lx, ly := curve.ScalarMult(pubkey.X(), pubkey.Y(), h) - rx, ry := curve.ScalarBaseMult(sigS) + rx, ry := curve.ScalarBaseMult(sBytes[:]) rlx, rly := curve.Add(lx, ly, rx, ry) if rly.Bit(0) == 1 { @@ -160,7 +151,7 @@ func schnorrVerify(sig []byte, pubkey *secp256k1.PublicKey, msg []byte, hashFunc rlxB := bigIntToEncodedBytes(rlx) // r == r' --> valid signature - if !bytes.Equal(sigR, rlxB[:]) { + if !bytes.Equal(rBytes[:], rlxB[:]) { str := fmt.Sprintf("calculated R point was not given R") return false, schnorrError(ErrUnequalRValues, str) } @@ -170,8 +161,8 @@ func schnorrVerify(sig []byte, pubkey *secp256k1.PublicKey, msg []byte, hashFunc // Verify is the generalized and exported function for the verification of a // secp256k1 Schnorr signature. BLAKE256 is used as the hashing function. -func (sig Signature) Verify(msg []byte, pubkey *secp256k1.PublicKey) bool { - ok, _ := schnorrVerify(sig.Serialize(), pubkey, msg, chainhash.HashB) +func (sig *Signature) Verify(msg []byte, pubkey *secp256k1.PublicKey) bool { + ok, _ := schnorrVerify(sig, pubkey, msg, chainhash.HashB) return ok } diff --git a/dcrec/secp256k1/schnorr/signature_test.go b/dcrec/secp256k1/schnorr/signature_test.go index 494a27a2..3d95e4af 100644 --- a/dcrec/secp256k1/schnorr/signature_test.go +++ b/dcrec/secp256k1/schnorr/signature_test.go @@ -237,7 +237,7 @@ func TestSchnorrSignAndVerify(t *testing.T) { // Ensure the produced signature verifies as well. pubKey := secp256k1.NewPrivateKey(hexToModNScalar(test.key)).PubKey() - ok, err := schnorrVerify(gotSigBytes, pubKey, hash, chainhash.HashB) + ok, err := schnorrVerify(gotSig, pubKey, hash, chainhash.HashB) if err != nil { t.Errorf("%s: signature failed to verify with error: %v", test.name, err)