diff --git a/go.mod b/go.mod index 9ba2c81a81..5c4b671650 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,7 @@ go 1.18 require ( github.com/blang/semver/v4 v4.0.0 github.com/consensys/bavard v0.1.13 - github.com/consensys/gnark-crypto v0.9.1-0.20230126211359-1835092d6670 - github.com/ethereum/go-ethereum v1.10.26 + github.com/consensys/gnark-crypto v0.9.1-0.20230203170247-e77b0919d1aa github.com/fxamacker/cbor/v2 v2.2.0 github.com/google/go-cmp v0.5.8 github.com/google/pprof v0.0.0-20220729232143-a41b82acbcb1 @@ -17,9 +16,7 @@ require ( ) require ( - github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/kr/pretty v0.3.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/go.sum b/go.sum index 1152a9455d..c73eece722 100644 --- a/go.sum +++ b/go.sum @@ -1,25 +1,14 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= -github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.8.1-0.20221220191316-4b7364bddab8 h1:Ij6UQpKx4/Ox6L6qFPk8NhEnTsYCEXlILnh+1Hi1grY= -github.com/consensys/gnark-crypto v0.8.1-0.20221220191316-4b7364bddab8/go.mod h1:CkbdF9hbRidRJYMRzmfX8TMOr95I2pYXRHF18MzRrvA= -github.com/consensys/gnark-crypto v0.9.1-0.20230126211359-1835092d6670 h1:AkewHCm7VuiCV3nDxsFVYE8JHPi9RhR6zFq4I6Ha0Fg= -github.com/consensys/gnark-crypto v0.9.1-0.20230126211359-1835092d6670/go.mod h1:CkbdF9hbRidRJYMRzmfX8TMOr95I2pYXRHF18MzRrvA= +github.com/consensys/gnark-crypto v0.9.1-0.20230203170247-e77b0919d1aa h1:y9E8TLAKfwpj1uAnxfiUfsK/hOusP2fo2o/BBQiZxEU= +github.com/consensys/gnark-crypto v0.9.1-0.20230203170247-e77b0919d1aa/go.mod h1:CkbdF9hbRidRJYMRzmfX8TMOr95I2pYXRHF18MzRrvA= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= -github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/ethereum/go-ethereum v1.10.26 h1:i/7d9RBBwiXCEuyduBQzJw/mKmnvzsN14jqBmytw72s= -github.com/ethereum/go-ethereum v1.10.26/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ= github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= diff --git a/std/algebra/weierstrass/doc_test.go b/std/algebra/weierstrass/doc_test.go index 9313745fbd..cfa81a1fe0 100644 --- a/std/algebra/weierstrass/doc_test.go +++ b/std/algebra/weierstrass/doc_test.go @@ -5,12 +5,12 @@ import ( "math/big" "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/secp256k1" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/consensys/gnark/std/algebra/weierstrass" "github.com/consensys/gnark/std/math/emulated" - "github.com/ethereum/go-ethereum/crypto/secp256k1" ) type ExampleCurveCircuit[Base, Scalar emulated.FieldParams] struct { @@ -33,16 +33,17 @@ func (c *ExampleCurveCircuit[B, S]) Define(api frontend.API) error { } func ExampleCurve() { - secpCurve := secp256k1.S256() s := big.NewInt(9) - sx, sy := secpCurve.ScalarMult(secpCurve.Gx, secpCurve.Gy, s.Bytes()) - fmt.Printf("result (%d, %d)", sx, sy) + _, g := secp256k1.Generators() + var Q secp256k1.G1Affine + Q.ScalarMultiplication(&g, s) + fmt.Printf("result (%d, %d)", Q.X, Q.Y) circuit := ExampleCurveCircuit[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{} witness := ExampleCurveCircuit[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{ Res: weierstrass.AffinePoint[emulated.Secp256k1Fp]{ - X: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gx), - Y: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gy), + X: emulated.ValueOf[emulated.Secp256k1Fp](g.X), + Y: emulated.ValueOf[emulated.Secp256k1Fp](g.Y), }, } ccs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) diff --git a/std/algebra/weierstrass/point_test.go b/std/algebra/weierstrass/point_test.go index 931f4fd608..28faf42109 100644 --- a/std/algebra/weierstrass/point_test.go +++ b/std/algebra/weierstrass/point_test.go @@ -6,11 +6,12 @@ import ( "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark-crypto/ecc/bn254" + "github.com/consensys/gnark-crypto/ecc/secp256k1" + "github.com/consensys/gnark-crypto/ecc/secp256k1/fp" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/consensys/gnark/std/math/emulated" "github.com/consensys/gnark/test" - "github.com/ethereum/go-ethereum/crypto/secp256k1" ) var testCurve = ecc.BN254 @@ -31,16 +32,17 @@ func (c *NegTest[T, S]) Define(api frontend.API) error { func TestNeg(t *testing.T) { assert := test.NewAssert(t) - secpCurve := secp256k1.S256() - yn := new(big.Int).Sub(secpCurve.P, secpCurve.Gy) + _, g := secp256k1.Generators() + var yn fp.Element + yn.Neg(&g.Y) circuit := NegTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{} witness := NegTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{ P: AffinePoint[emulated.Secp256k1Fp]{ - X: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gx), - Y: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gy), + X: emulated.ValueOf[emulated.Secp256k1Fp](g.X), + Y: emulated.ValueOf[emulated.Secp256k1Fp](g.Y), }, Q: AffinePoint[emulated.Secp256k1Fp]{ - X: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gx), + X: emulated.ValueOf[emulated.Secp256k1Fp](g.X), Y: emulated.ValueOf[emulated.Secp256k1Fp](yn), }, } @@ -64,22 +66,27 @@ func (c *AddTest[T, S]) Define(api frontend.API) error { func TestAdd(t *testing.T) { assert := test.NewAssert(t) - secpCurve := secp256k1.S256() - xd, yd := secpCurve.Double(secpCurve.Gx, secpCurve.Gy) - xa, ya := secpCurve.Add(xd, yd, secpCurve.Gx, secpCurve.Gy) + var dJac, aJac secp256k1.G1Jac + g, _ := secp256k1.Generators() + dJac.Double(&g) + aJac.Set(&dJac). + AddAssign(&g) + var dAff, aAff secp256k1.G1Affine + dAff.FromJacobian(&dJac) + aAff.FromJacobian(&aJac) circuit := AddTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{} witness := AddTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{ P: AffinePoint[emulated.Secp256k1Fp]{ - X: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gx), - Y: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gy), + X: emulated.ValueOf[emulated.Secp256k1Fp](g.X), + Y: emulated.ValueOf[emulated.Secp256k1Fp](g.Y), }, Q: AffinePoint[emulated.Secp256k1Fp]{ - X: emulated.ValueOf[emulated.Secp256k1Fp](xd), - Y: emulated.ValueOf[emulated.Secp256k1Fp](yd), + X: emulated.ValueOf[emulated.Secp256k1Fp](dAff.X), + Y: emulated.ValueOf[emulated.Secp256k1Fp](dAff.Y), }, R: AffinePoint[emulated.Secp256k1Fp]{ - X: emulated.ValueOf[emulated.Secp256k1Fp](xa), - Y: emulated.ValueOf[emulated.Secp256k1Fp](ya), + X: emulated.ValueOf[emulated.Secp256k1Fp](aAff.X), + Y: emulated.ValueOf[emulated.Secp256k1Fp](aAff.Y), }, } err := test.IsSolved(&circuit, &witness, testCurve.ScalarField()) @@ -102,17 +109,20 @@ func (c *DoubleTest[T, S]) Define(api frontend.API) error { func TestDouble(t *testing.T) { assert := test.NewAssert(t) - secpCurve := secp256k1.S256() - xd, yd := secpCurve.Double(secpCurve.Gx, secpCurve.Gy) + g, _ := secp256k1.Generators() + var dJac secp256k1.G1Jac + dJac.Double(&g) + var dAff secp256k1.G1Affine + dAff.FromJacobian(&dJac) circuit := DoubleTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{} witness := DoubleTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{ P: AffinePoint[emulated.Secp256k1Fp]{ - X: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gx), - Y: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gy), + X: emulated.ValueOf[emulated.Secp256k1Fp](g.X), + Y: emulated.ValueOf[emulated.Secp256k1Fp](g.Y), }, Q: AffinePoint[emulated.Secp256k1Fp]{ - X: emulated.ValueOf[emulated.Secp256k1Fp](xd), - Y: emulated.ValueOf[emulated.Secp256k1Fp](yd), + X: emulated.ValueOf[emulated.Secp256k1Fp](dAff.X), + Y: emulated.ValueOf[emulated.Secp256k1Fp](dAff.Y), }, } err := test.IsSolved(&circuit, &witness, testCurve.ScalarField()) @@ -136,21 +146,22 @@ func (c *ScalarMulTest[T, S]) Define(api frontend.API) error { func TestScalarMul(t *testing.T) { assert := test.NewAssert(t) - secpCurve := secp256k1.S256() + _, g := secp256k1.Generators() s, ok := new(big.Int).SetString("44693544921776318736021182399461740191514036429448770306966433218654680512345", 10) assert.True(ok) - sx, sy := secpCurve.ScalarMult(secpCurve.Gx, secpCurve.Gy, s.Bytes()) + var S secp256k1.G1Affine + S.ScalarMultiplication(&g, s) circuit := ScalarMulTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{} witness := ScalarMulTest[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{ S: emulated.ValueOf[emulated.Secp256k1Fr](s), P: AffinePoint[emulated.Secp256k1Fp]{ - X: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gx), - Y: emulated.ValueOf[emulated.Secp256k1Fp](secpCurve.Gy), + X: emulated.ValueOf[emulated.Secp256k1Fp](g.X), + Y: emulated.ValueOf[emulated.Secp256k1Fp](g.Y), }, Q: AffinePoint[emulated.Secp256k1Fp]{ - X: emulated.ValueOf[emulated.Secp256k1Fp](sx), - Y: emulated.ValueOf[emulated.Secp256k1Fp](sy), + X: emulated.ValueOf[emulated.Secp256k1Fp](S.X), + Y: emulated.ValueOf[emulated.Secp256k1Fp](S.Y), }, } err := test.IsSolved(&circuit, &witness, testCurve.ScalarField()) @@ -171,12 +182,12 @@ func TestScalarMul2(t *testing.T) { witness := ScalarMulTest[emulated.BN254Fp, emulated.BN254Fr]{ S: emulated.ValueOf[emulated.BN254Fr](s), P: AffinePoint[emulated.BN254Fp]{ - X: emulated.ValueOf[emulated.BN254Fp](gen.X.BigInt(new(big.Int))), - Y: emulated.ValueOf[emulated.BN254Fp](gen.Y.BigInt(new(big.Int))), + X: emulated.ValueOf[emulated.BN254Fp](gen.X), + Y: emulated.ValueOf[emulated.BN254Fp](gen.Y), }, Q: AffinePoint[emulated.BN254Fp]{ - X: emulated.ValueOf[emulated.BN254Fp](res.X.BigInt(new(big.Int))), - Y: emulated.ValueOf[emulated.BN254Fp](res.Y.BigInt(new(big.Int))), + X: emulated.ValueOf[emulated.BN254Fp](res.X), + Y: emulated.ValueOf[emulated.BN254Fp](res.Y), }, } err := test.IsSolved(&circuit, &witness, testCurve.ScalarField()) diff --git a/std/signature/ecdsa/ecdsa_test.go b/std/signature/ecdsa/ecdsa_test.go index ce42942097..711ec69554 100644 --- a/std/signature/ecdsa/ecdsa_test.go +++ b/std/signature/ecdsa/ecdsa_test.go @@ -1,30 +1,19 @@ package ecdsa import ( + "crypto/rand" + "crypto/sha256" "math/big" "testing" "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/secp256k1/ecdsa" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/std/algebra/weierstrass" "github.com/consensys/gnark/std/math/emulated" "github.com/consensys/gnark/test" - "github.com/ethereum/go-ethereum/crypto" ) -var testPrivHex = "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232032" - -func sign(t *testing.T) ([]byte, []byte, error) { - t.Helper() - key, _ := crypto.HexToECDSA(testPrivHex) - msg := crypto.Keccak256([]byte("foo")) - sig, err := crypto.Sign(msg, key) - if err != nil { - t.Errorf("Sign error: %s", err) - } - return sig, msg, nil -} - type EcdsaCircuit[T, S emulated.FieldParams] struct { Sig Signature[S] Msg emulated.Element[S] @@ -36,49 +25,95 @@ func (c *EcdsaCircuit[T, S]) Define(api frontend.API) error { return nil } -func TestEcdsa(t *testing.T) { - // generate a valid signature - sig, msg, err := sign(t) - if err != nil { - t.Fatal(err) - } +func TestEcdsaPreHashed(t *testing.T) { + + // generate parameters + privKey, _ := ecdsa.GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + // sign + msg := []byte("testing ECDSA (pre-hashed)") + sigBin, _ := privKey.Sign(msg, nil) // check that the signature is correct - pub, err := crypto.Ecrecover(msg, sig) - if err != nil { - t.Fatal(err) + flag, _ := publicKey.Verify(sigBin, msg, nil) + if !flag { + t.Errorf("can't verify signature") } - sig = sig[:len(sig)-1] - if !crypto.VerifySignature(pub, msg, sig) { - t.Errorf("can't verify signature with uncompressed key") + + // unmarshal signature + var sig ecdsa.Signature + sig.SetBytes(sigBin) + r, s := new(big.Int), new(big.Int) + r.SetBytes(sig.R[:32]) + s.SetBytes(sig.S[:32]) + + hash := ecdsa.HashToInt(msg) + + circuit := EcdsaCircuit[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{} + witness := EcdsaCircuit[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{ + Sig: Signature[emulated.Secp256k1Fr]{ + R: emulated.ValueOf[emulated.Secp256k1Fr](r), + S: emulated.ValueOf[emulated.Secp256k1Fr](s), + }, + Msg: emulated.ValueOf[emulated.Secp256k1Fr](hash), + Pub: PublicKey[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{ + X: emulated.ValueOf[emulated.Secp256k1Fp](privKey.PublicKey.A.X), + Y: emulated.ValueOf[emulated.Secp256k1Fp](privKey.PublicKey.A.Y), + }, } + assert := test.NewAssert(t) + err := test.IsSolved(&circuit, &witness, ecc.BN254.ScalarField()) + assert.NoError(err) +} - r := new(big.Int).SetBytes(sig[:32]) - s := new(big.Int).SetBytes(sig[32:]) - m := new(big.Int).SetBytes(msg) +func TestEcdsaSHA256(t *testing.T) { - _pub, err := crypto.UnmarshalPubkey(pub) - if err != nil { - t.Fatal(err) + // generate parameters + privKey, _ := ecdsa.GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + // sign + msg := []byte("testing ECDSA (sha256)") + md := sha256.New() + sigBin, _ := privKey.Sign(msg, md) + + // check that the signature is correct + flag, _ := publicKey.Verify(sigBin, msg, md) + if !flag { + t.Errorf("can't verify signature") } + // unmarshal signature + var sig ecdsa.Signature + sig.SetBytes(sigBin) + r, s := new(big.Int), new(big.Int) + r.SetBytes(sig.R[:32]) + s.SetBytes(sig.S[:32]) + + // compute the hash of the message as an integer + dataToHash := make([]byte, len(msg)) + copy(dataToHash[:], msg[:]) + md.Reset() + md.Write(dataToHash[:]) + hramBin := md.Sum(nil) + hash := ecdsa.HashToInt(hramBin) + circuit := EcdsaCircuit[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{} witness := EcdsaCircuit[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{ Sig: Signature[emulated.Secp256k1Fr]{ R: emulated.ValueOf[emulated.Secp256k1Fr](r), S: emulated.ValueOf[emulated.Secp256k1Fr](s), }, - Msg: emulated.ValueOf[emulated.Secp256k1Fr](m), + Msg: emulated.ValueOf[emulated.Secp256k1Fr](hash), Pub: PublicKey[emulated.Secp256k1Fp, emulated.Secp256k1Fr]{ - X: emulated.ValueOf[emulated.Secp256k1Fp](_pub.X), - Y: emulated.ValueOf[emulated.Secp256k1Fp](_pub.Y), + X: emulated.ValueOf[emulated.Secp256k1Fp](privKey.PublicKey.A.X), + Y: emulated.ValueOf[emulated.Secp256k1Fp](privKey.PublicKey.A.Y), }, } assert := test.NewAssert(t) - err = test.IsSolved(&circuit, &witness, ecc.BN254.ScalarField()) + err := test.IsSolved(&circuit, &witness, ecc.BN254.ScalarField()) assert.NoError(err) - // _, err = frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) - // assert.NoError(err) } // Example how to verify the signature inside the circuit. @@ -104,28 +139,22 @@ func ExamplePublicKey_Verify() { // Example how to create a valid signature for secp256k1 func ExamplePublicKey_Verify_create() { - testPrivHex := "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232032" - key, _ := crypto.HexToECDSA(testPrivHex) - msg := crypto.Keccak256([]byte("foo")) - sig, err := crypto.Sign(msg, key) - if err != nil { - panic("sign") - } - _pub, err := crypto.Ecrecover(msg, sig) - if err != nil { - panic("ecrecover") - } - sig = sig[:len(sig)-1] - pub, err := crypto.UnmarshalPubkey(_pub) - if err != nil { - panic("unmarshal") - } - r := new(big.Int).SetBytes(sig[:32]) - s := new(big.Int).SetBytes(sig[32:]) - m := new(big.Int).SetBytes(msg) - pubx := pub.X - puby := pub.Y + // generate parameters + privKey, _ := ecdsa.GenerateKey(rand.Reader) + + // sign + msg := []byte("testing ECDSA") + md := sha256.New() + sigBin, _ := privKey.Sign(msg, md) + + pubx := privKey.PublicKey.A.X + puby := privKey.PublicKey.A.Y + + // unmarshal signature + var sig ecdsa.Signature + sig.SetBytes(sigBin) + // can continue in the PublicKey Verify example - _, _, _, _, _ = r, s, m, pubx, puby + _, _, _, _, _ = sig.R, sig.S, msg, pubx, puby }