From 9ce64a05e3a23d73e5fab06ee6b89c00f879cc70 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Fri, 12 Apr 2024 13:01:57 +0000 Subject: [PATCH 1/4] feat: return constant error for quadratic non residues --- internal/generator/ecdsa/template/ecdsa.go.tmpl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/internal/generator/ecdsa/template/ecdsa.go.tmpl b/internal/generator/ecdsa/template/ecdsa.go.tmpl index 1dda1ed34..31ab83580 100644 --- a/internal/generator/ecdsa/template/ecdsa.go.tmpl +++ b/internal/generator/ecdsa/template/ecdsa.go.tmpl @@ -30,6 +30,15 @@ const ( sizeSignature = 2 * sizeFr ) +{{- if or (eq .Name "secp256k1") (eq .Name "bn254") (eq .Name "stark-curve") }} +var ( + // ErrNoSqrtR is returned when x^3+ax+b is not a square in the field. This + // is used for public key recovery and allows to detect if the signature is + // valid or not. + ErrNoSqrtR = errors.New("x^3+ax+b is not a square in the field") +) +{{- end }} + var order = fr.Modulus() // PublicKey represents an ECDSA public key @@ -135,7 +144,8 @@ func RecoverP(v uint, r *big.Int) (*{{ .CurvePackage }}.G1Affine, error) { y.Mod(y, fp.Modulus()) // y = sqrt(y^2) if y.ModSqrt(y, fp.Modulus()) == nil { - return nil, errors.New("no square root") + // there is no square root, return error constant + return nil, ErrNoSqrtR } // check that y has same oddity as defined by v if y.Bit(0) != yChoice { From 23120285b03c88579fed1fbe29d0e5b19767418d Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Fri, 12 Apr 2024 13:47:49 +0000 Subject: [PATCH 2/4] chore: go generate --- ecc/bn254/ecdsa/ecdsa.go | 10 +++++++++- ecc/secp256k1/ecdsa/ecdsa.go | 10 +++++++++- ecc/stark-curve/ecdsa/ecdsa.go | 10 +++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/ecc/bn254/ecdsa/ecdsa.go b/ecc/bn254/ecdsa/ecdsa.go index dcde60137..f0b5a5c68 100644 --- a/ecc/bn254/ecdsa/ecdsa.go +++ b/ecc/bn254/ecdsa/ecdsa.go @@ -42,6 +42,13 @@ const ( sizeSignature = 2 * sizeFr ) +var ( + // ErrNoSqrtR is returned when x^3+ax+b is not a square in the field. This + // is used for public key recovery and allows to detect if the signature is + // valid or not. + ErrNoSqrtR = errors.New("x^3+ax+b is not a square in the field") +) + var order = fr.Modulus() // PublicKey represents an ECDSA public key @@ -139,7 +146,8 @@ func RecoverP(v uint, r *big.Int) (*bn254.G1Affine, error) { y.Mod(y, fp.Modulus()) // y = sqrt(y^2) if y.ModSqrt(y, fp.Modulus()) == nil { - return nil, errors.New("no square root") + // there is no square root, return error constant + return nil, ErrNoSqrtR } // check that y has same oddity as defined by v if y.Bit(0) != yChoice { diff --git a/ecc/secp256k1/ecdsa/ecdsa.go b/ecc/secp256k1/ecdsa/ecdsa.go index 6c633fc99..7c1ac8c72 100644 --- a/ecc/secp256k1/ecdsa/ecdsa.go +++ b/ecc/secp256k1/ecdsa/ecdsa.go @@ -42,6 +42,13 @@ const ( sizeSignature = 2 * sizeFr ) +var ( + // ErrNoSqrtR is returned when x^3+ax+b is not a square in the field. This + // is used for public key recovery and allows to detect if the signature is + // valid or not. + ErrNoSqrtR = errors.New("x^3+ax+b is not a square in the field") +) + var order = fr.Modulus() // PublicKey represents an ECDSA public key @@ -139,7 +146,8 @@ func RecoverP(v uint, r *big.Int) (*secp256k1.G1Affine, error) { y.Mod(y, fp.Modulus()) // y = sqrt(y^2) if y.ModSqrt(y, fp.Modulus()) == nil { - return nil, errors.New("no square root") + // there is no square root, return error constant + return nil, ErrNoSqrtR } // check that y has same oddity as defined by v if y.Bit(0) != yChoice { diff --git a/ecc/stark-curve/ecdsa/ecdsa.go b/ecc/stark-curve/ecdsa/ecdsa.go index 5d94cd791..5fa150b09 100644 --- a/ecc/stark-curve/ecdsa/ecdsa.go +++ b/ecc/stark-curve/ecdsa/ecdsa.go @@ -42,6 +42,13 @@ const ( sizeSignature = 2 * sizeFr ) +var ( + // ErrNoSqrtR is returned when x^3+ax+b is not a square in the field. This + // is used for public key recovery and allows to detect if the signature is + // valid or not. + ErrNoSqrtR = errors.New("x^3+ax+b is not a square in the field") +) + var order = fr.Modulus() // PublicKey represents an ECDSA public key @@ -139,7 +146,8 @@ func RecoverP(v uint, r *big.Int) (*starkcurve.G1Affine, error) { y.Mod(y, fp.Modulus()) // y = sqrt(y^2) if y.ModSqrt(y, fp.Modulus()) == nil { - return nil, errors.New("no square root") + // there is no square root, return error constant + return nil, ErrNoSqrtR } // check that y has same oddity as defined by v if y.Bit(0) != yChoice { From bb4c9d925624cc2077941f4666b0a63ed60c6607 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Fri, 12 Apr 2024 13:49:12 +0000 Subject: [PATCH 3/4] chore: make recoverP internal --- internal/generator/ecdsa/template/ecdsa.go.tmpl | 4 ++-- internal/generator/ecdsa/template/marshal.go.tmpl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/generator/ecdsa/template/ecdsa.go.tmpl b/internal/generator/ecdsa/template/ecdsa.go.tmpl index 31ab83580..aa0e3868c 100644 --- a/internal/generator/ecdsa/template/ecdsa.go.tmpl +++ b/internal/generator/ecdsa/template/ecdsa.go.tmpl @@ -112,10 +112,10 @@ func HashToInt(hash []byte) *big.Int { } {{- if or (eq .Name "secp256k1") (eq .Name "bn254") (eq .Name "stark-curve") }} -// RecoverP recovers the value P (prover commitment) when creating a signature. +// recoverP recovers the value P (prover commitment) when creating a signature. // It uses the recovery information v and part of the decomposed signature r. It // is used internally for recovering the public key. -func RecoverP(v uint, r *big.Int) (*{{ .CurvePackage }}.G1Affine, error) { +func recoverP(v uint, r *big.Int) (*{{ .CurvePackage }}.G1Affine, error) { if r.Cmp(fr.Modulus()) >= 0 { return nil, errors.New("r is larger than modulus") } diff --git a/internal/generator/ecdsa/template/marshal.go.tmpl b/internal/generator/ecdsa/template/marshal.go.tmpl index 5ca1f0cbc..12729f3b1 100644 --- a/internal/generator/ecdsa/template/marshal.go.tmpl +++ b/internal/generator/ecdsa/template/marshal.go.tmpl @@ -62,7 +62,7 @@ func (pk *PublicKey) RecoverFrom(msg []byte, v uint, r, s *big.Int) error { if s.Cmp(big.NewInt(0)) <= 0 { return errors.New("s is negative") } - P, err := RecoverP(v, r) + P, err := recoverP(v, r) if err != nil { return err } From 3c411258187a3df5c2e41078bef5e81702e5afe6 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Fri, 12 Apr 2024 13:49:25 +0000 Subject: [PATCH 4/4] chore: go generate --- ecc/bn254/ecdsa/ecdsa.go | 4 ++-- ecc/bn254/ecdsa/marshal.go | 2 +- ecc/secp256k1/ecdsa/ecdsa.go | 4 ++-- ecc/secp256k1/ecdsa/marshal.go | 2 +- ecc/stark-curve/ecdsa/ecdsa.go | 4 ++-- ecc/stark-curve/ecdsa/marshal.go | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ecc/bn254/ecdsa/ecdsa.go b/ecc/bn254/ecdsa/ecdsa.go index f0b5a5c68..414a7e940 100644 --- a/ecc/bn254/ecdsa/ecdsa.go +++ b/ecc/bn254/ecdsa/ecdsa.go @@ -116,10 +116,10 @@ func HashToInt(hash []byte) *big.Int { return ret } -// RecoverP recovers the value P (prover commitment) when creating a signature. +// recoverP recovers the value P (prover commitment) when creating a signature. // It uses the recovery information v and part of the decomposed signature r. It // is used internally for recovering the public key. -func RecoverP(v uint, r *big.Int) (*bn254.G1Affine, error) { +func recoverP(v uint, r *big.Int) (*bn254.G1Affine, error) { if r.Cmp(fr.Modulus()) >= 0 { return nil, errors.New("r is larger than modulus") } diff --git a/ecc/bn254/ecdsa/marshal.go b/ecc/bn254/ecdsa/marshal.go index 1bbad0786..eb618f2d6 100644 --- a/ecc/bn254/ecdsa/marshal.go +++ b/ecc/bn254/ecdsa/marshal.go @@ -73,7 +73,7 @@ func (pk *PublicKey) RecoverFrom(msg []byte, v uint, r, s *big.Int) error { if s.Cmp(big.NewInt(0)) <= 0 { return errors.New("s is negative") } - P, err := RecoverP(v, r) + P, err := recoverP(v, r) if err != nil { return err } diff --git a/ecc/secp256k1/ecdsa/ecdsa.go b/ecc/secp256k1/ecdsa/ecdsa.go index 7c1ac8c72..689bc5003 100644 --- a/ecc/secp256k1/ecdsa/ecdsa.go +++ b/ecc/secp256k1/ecdsa/ecdsa.go @@ -116,10 +116,10 @@ func HashToInt(hash []byte) *big.Int { return ret } -// RecoverP recovers the value P (prover commitment) when creating a signature. +// recoverP recovers the value P (prover commitment) when creating a signature. // It uses the recovery information v and part of the decomposed signature r. It // is used internally for recovering the public key. -func RecoverP(v uint, r *big.Int) (*secp256k1.G1Affine, error) { +func recoverP(v uint, r *big.Int) (*secp256k1.G1Affine, error) { if r.Cmp(fr.Modulus()) >= 0 { return nil, errors.New("r is larger than modulus") } diff --git a/ecc/secp256k1/ecdsa/marshal.go b/ecc/secp256k1/ecdsa/marshal.go index 886c3dace..bc2be013c 100644 --- a/ecc/secp256k1/ecdsa/marshal.go +++ b/ecc/secp256k1/ecdsa/marshal.go @@ -73,7 +73,7 @@ func (pk *PublicKey) RecoverFrom(msg []byte, v uint, r, s *big.Int) error { if s.Cmp(big.NewInt(0)) <= 0 { return errors.New("s is negative") } - P, err := RecoverP(v, r) + P, err := recoverP(v, r) if err != nil { return err } diff --git a/ecc/stark-curve/ecdsa/ecdsa.go b/ecc/stark-curve/ecdsa/ecdsa.go index 5fa150b09..de997d8ae 100644 --- a/ecc/stark-curve/ecdsa/ecdsa.go +++ b/ecc/stark-curve/ecdsa/ecdsa.go @@ -116,10 +116,10 @@ func HashToInt(hash []byte) *big.Int { return ret } -// RecoverP recovers the value P (prover commitment) when creating a signature. +// recoverP recovers the value P (prover commitment) when creating a signature. // It uses the recovery information v and part of the decomposed signature r. It // is used internally for recovering the public key. -func RecoverP(v uint, r *big.Int) (*starkcurve.G1Affine, error) { +func recoverP(v uint, r *big.Int) (*starkcurve.G1Affine, error) { if r.Cmp(fr.Modulus()) >= 0 { return nil, errors.New("r is larger than modulus") } diff --git a/ecc/stark-curve/ecdsa/marshal.go b/ecc/stark-curve/ecdsa/marshal.go index 47888049f..8860f427e 100644 --- a/ecc/stark-curve/ecdsa/marshal.go +++ b/ecc/stark-curve/ecdsa/marshal.go @@ -73,7 +73,7 @@ func (pk *PublicKey) RecoverFrom(msg []byte, v uint, r, s *big.Int) error { if s.Cmp(big.NewInt(0)) <= 0 { return errors.New("s is negative") } - P, err := RecoverP(v, r) + P, err := recoverP(v, r) if err != nil { return err }