Repository: NethermindEth/juno (go)

Issue:
[Bug/Security] Invalid Felt value is not rejected
# Invalid Felt value is not rejected

We (@fuzzinglabs) found a bug while doing differential fuzzing against Juno Pedersen's hash and felt implementation.

For this specific felt value (`0xfb01012100000000000000000000000000000000000000000000000000000000`), the following Pedersen/Felt implementations return: 
- Pathfinder: OverflowError
- starknet-rs: FromByteArrayError
- starkware-crypto-sys: Error code (1)
- Juno: 0xfb01012100000000000000000000000000000000000000000000000000000000

The Juno implementation of a felt object authorizes the creation with a value superior to the prime number used.

```
Prime number: 
0x800000000000011000000000000000000000000000000000000000000000001

Created Felt:
0xfb01012100000000000000000000000000000000000000000000000000000000
```

This can lead to creating a Pedersen Hash based on this invalid felt value.

## Expected Behavior

The program should reject the creation of the Felt.

## Your Environment

- <!-- snarkVM Version --> Juno commit: c5cc5578235cf9b875dceb23fa229e6467c3d660
- <!-- Rust Version --> cargo 1.66.0-nightly (082503982 2022-09-13) 
- <!-- Computer OS --> Ubuntu 20.04


## Steps to Reproduce

Testing program:
``` go
package main

import (
	"fmt"

	"github.com/NethermindEth/juno/pkg/crypto/pedersen"
	"github.com/NethermindEth/juno/pkg/felt"
)

func main() {

	a := new(felt.Felt).SetHex("fb01012100000000000000000000000000000000000000000000000000000000")
	b := new(felt.Felt).SetHex("0000000000000000000000000000000000000000000000000000000000000000")


	fmt.Printf("%s\n", pedersen.Digest(a, b).Hex())
}
```

Pull request description:
 Make felt error on setting values bigger than the modulus 
Fixes #439

Patch:
diff --git a/core/felt/felt.go b/core/felt/felt.go
index 5045c42b..1337024d 100644
--- a/core/felt/felt.go
+++ b/core/felt/felt.go
@@ -60,20 +60,8 @@ func (z *Felt) UnmarshalJSON(data []byte) error {
 		s = s[:len(s)-1]
 	}
 
-	// get temporary big int from the pool
-	vv := bigIntPool.Get().(*big.Int)
-
-	if _, ok := vv.SetString(s, 0); !ok {
-		if _, ok := vv.SetString(s, 16); !ok {
-			return errors.New("can't parse into a big.Int: " + s)
-		}
-	}
-
-	z.val.SetBigInt(vv)
-
-	// release object into pool
-	bigIntPool.Put(vv)
-	return nil
+	_, err := z.SetString(s)
+	return err
 }
 
 // MarshalJSON forwards the call to underlying field element implementation
@@ -81,12 +69,6 @@ func (z *Felt) MarshalJSON() ([]byte, error) {
 	return z.val.MarshalJSON()
 }
 
-// SetInterface forwards the call to underlying field element implementation
-func (z *Felt) SetInterface(i1 interface{}) (*Felt, error) {
-	_, err := z.val.SetInterface(i1)
-	return z, err
-}
-
 // SetBytes forwards the call to underlying field element implementation
 func (z *Felt) SetBytes(e []byte) *Felt {
 	z.val.SetBytes(e)
@@ -95,8 +77,24 @@ func (z *Felt) SetBytes(e []byte) *Felt {
 
 // SetString forwards the call to underlying field element implementation
 func (z *Felt) SetString(number string) (*Felt, error) {
-	_, err := z.val.SetString(number)
-	return z, err
+	// get temporary big int from the pool
+	vv := bigIntPool.Get().(*big.Int)
+	// release object into pool
+	defer bigIntPool.Put(vv)
+
+	if _, ok := vv.SetString(number, 0); !ok {
+		if _, ok := vv.SetString(number, 16); !ok {
+			return z, errors.New("can't parse into a big.Int: " + number)
+		}
+	}
+
+	if vv.BitLen() > fp.Bits {
+		return z, errors.New("can't fit in felt: " + number)
+	}
+
+	var bytes [32]byte
+	vv.FillBytes(bytes[:])
+	return z, z.val.SetBytesCanonical(bytes[:])
 }
 
 // SetUint64 forwards the call to underlying field element implementation
@@ -146,11 +144,6 @@ func (z *Felt) IsZero() bool {
 	return z.val.IsZero()
 }
 
-// Bit forwards the call to underlying field element implementation
-func (z *Felt) Bit(i uint64) uint64 {
-	return z.val.Bit(i)
-}
-
 // Add forwards the call to underlying field element implementation
 func (z *Felt) Add(x, y *Felt) *Felt {
 	z.val.Add(&x.val, &y.val)
diff --git a/go.mod b/go.mod
index b1006dc5..28f4c130 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.18
 require (
 	github.com/bits-and-blooms/bitset v1.5.0
 	github.com/cockroachdb/pebble v0.0.0-20230209222158-0568b5fd3d14
-	github.com/consensys/gnark-crypto v0.9.1-0.20230203170247-e77b0919d1aa
+	github.com/consensys/gnark-crypto v0.9.1
 	github.com/ethereum/go-ethereum v1.10.26
 	github.com/fxamacker/cbor/v2 v2.4.0
 	github.com/sourcegraph/conc v0.2.0
diff --git a/go.sum b/go.sum
index 09aa7e06..76ff75ac 100644
--- a/go.sum
+++ b/go.sum
@@ -93,8 +93,8 @@ github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk
 github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
 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.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/consensys/gnark-crypto v0.9.1 h1:mru55qKdWl3E035hAoh1jj9d7hVnYY5pfb6tmovSmII=
+github.com/consensys/gnark-crypto v0.9.1/go.mod h1:a2DQL4+5ywF6safEeZFEPGRiiGbjzGFRUN2sg06VuU4=
 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
 github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
 github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=


Test patch:
diff --git a/core/felt/felt_test.go b/core/felt/felt_test.go
index 299a77f4..80a32dd0 100644
--- a/core/felt/felt_test.go
+++ b/core/felt/felt_test.go
@@ -15,6 +15,11 @@ func TestUnmarshalJson(t *testing.T) {
 	var without felt.Felt
 	assert.NoError(t, without.UnmarshalJSON([]byte("4437ab")))
 	assert.Equal(t, true, without.Equal(&with))
+
+	var fails felt.Felt
+	assert.Error(t, fails.UnmarshalJSON([]byte("0x2000000000000000000000000000000000000000000000000000000000000000000")))
+	assert.Error(t, fails.UnmarshalJSON([]byte("0x800000000000011000000000000000000000000000000000000000000000001")))
+	assert.Error(t, fails.UnmarshalJSON([]byte("0xfb01012100000000000000000000000000000000000000000000000000000000")))
 }
 
 func TestFeltCbor(t *testing.T) {