diff --git a/babyjub/eddsa.go b/babyjub/eddsa.go index f855b0f..640491f 100644 --- a/babyjub/eddsa.go +++ b/babyjub/eddsa.go @@ -180,11 +180,11 @@ func (k *PrivateKey) SignMimc7(msg *big.Int) *Signature { r.Mod(r, SubOrder) R8 := NewPoint().Mul(r, B8) // R8 = r * 8 * B A := k.Public().Point() - hmInput, err := mimc7.BigIntsToRElems([]*big.Int{R8.X, R8.Y, A.X, A.Y, msg}) + hmInput := []*big.Int{R8.X, R8.Y, A.X, A.Y, msg} + hm, err := mimc7.Hash(hmInput, nil) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg) if err != nil { panic(err) } - hm := mimc7.Hash(hmInput, nil) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg) S := new(big.Int).Lsh(k.Scalar().BigInt(), 3) S = S.Mul(hm, S) S.Add(r, S) @@ -196,11 +196,11 @@ func (k *PrivateKey) SignMimc7(msg *big.Int) *Signature { // VerifyMimc7 verifies the signature of a message encoded as a big.Int in Zq // using blake-512 hash for buffer hashing and mimc7 for big.Int hashing. func (p *PublicKey) VerifyMimc7(msg *big.Int, sig *Signature) bool { - hmInput, err := mimc7.BigIntsToRElems([]*big.Int{sig.R8.X, sig.R8.Y, p.X, p.Y, msg}) + hmInput := []*big.Int{sig.R8.X, sig.R8.Y, p.X, p.Y, msg} + hm, err := mimc7.Hash(hmInput, nil) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg) if err != nil { panic(err) } - hm := mimc7.Hash(hmInput, nil) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg) left := NewPoint().Mul(sig.S, B8) // left = s * 8 * B r1 := big.NewInt(8) diff --git a/mimc7/mimc7.go b/mimc7/mimc7.go index 0169405..6ee158a 100644 --- a/mimc7/mimc7.go +++ b/mimc7/mimc7.go @@ -2,19 +2,16 @@ package mimc7 import ( "errors" - "fmt" "math/big" "github.com/ethereum/go-ethereum/crypto" _constants "github.com/iden3/go-iden3-crypto/constants" "github.com/iden3/go-iden3-crypto/field" + "github.com/iden3/go-iden3-crypto/utils" ) const SEED = "mimc" -// RElem is a big.Int of maximum 253 bits -type RElem *big.Int - var constants = generateConstantsData() type constantsData struct { @@ -45,36 +42,6 @@ func generateConstantsData() constantsData { return constants } -// BigIntToRElem checks if given big.Int fits in a Field R element, and returns the RElem type -func BigIntToRElem(a *big.Int) (RElem, error) { - if a.Cmp(constants.maxFieldVal) != -1 { - return RElem(a), errors.New("Given big.Int don't fits in the Finite Field over R") - } - return RElem(a), nil -} - -//BigIntsToRElems converts from array of *big.Int to array of RElem -func BigIntsToRElems(arr []*big.Int) ([]RElem, error) { - o := make([]RElem, len(arr)) - for i, a := range arr { - e, err := BigIntToRElem(a) - if err != nil { - return o, fmt.Errorf("element in position %v don't fits in Finite Field over R", i) - } - o[i] = e - } - return o, nil -} - -// RElemsToBigInts converts from array of RElem to array of *big.Int -func RElemsToBigInts(arr []RElem) []*big.Int { - o := make([]*big.Int, len(arr)) - for i, a := range arr { - o[i] = a - } - return o -} - func getConstants(fqR field.Fq, seed string, nRounds int) []*big.Int { cts := make([]*big.Int, nRounds) cts[0] = big.NewInt(int64(0)) @@ -88,7 +55,7 @@ func getConstants(fqR field.Fq, seed string, nRounds int) []*big.Int { return cts } -// MIMC7HashGeneric performs the MIMC7 hash over a RElem, in a generic way, where it can be specified the Finite Field over R, and the number of rounds +// MIMC7HashGeneric performs the MIMC7 hash over a *big.Int, in a generic way, where it can be specified the Finite Field over R, and the number of rounds func MIMC7HashGeneric(fqR field.Fq, xIn, k *big.Int, nRounds int) *big.Int { cts := getConstants(fqR, SEED, nRounds) var r *big.Int @@ -106,9 +73,11 @@ func MIMC7HashGeneric(fqR field.Fq, xIn, k *big.Int, nRounds int) *big.Int { return fqR.Affine(fqR.Add(r, k)) } -// HashGeneric performs the MIMC7 hash over a RElem array, in a generic way, where it can be specified the Finite Field over R, and the number of rounds -func HashGeneric(iv *big.Int, arrEl []RElem, fqR field.Fq, nRounds int) (RElem, error) { - arr := RElemsToBigInts(arrEl) +// HashGeneric performs the MIMC7 hash over a *big.Int array, in a generic way, where it can be specified the Finite Field over R, and the number of rounds +func HashGeneric(iv *big.Int, arr []*big.Int, fqR field.Fq, nRounds int) (*big.Int, error) { + if !utils.CheckBigIntArrayInField(arr, constants.fqR.Q) { + return nil, errors.New("inputs values not inside Finite Field") + } r := iv var err error for i := 0; i < len(arr); i++ { @@ -117,10 +86,10 @@ func HashGeneric(iv *big.Int, arrEl []RElem, fqR field.Fq, nRounds int) (RElem, return r, err } } - return RElem(r), nil + return r, nil } -// MIMC7Hash performs the MIMC7 hash over a RElem, using the Finite Field over R and the number of rounds setted in the `constants` variable +// MIMC7Hash performs the MIMC7 hash over a *big.Int, using the Finite Field over R and the number of rounds setted in the `constants` variable func MIMC7Hash(xIn, k *big.Int) *big.Int { var r *big.Int for i := 0; i < constants.nRounds; i++ { @@ -137,16 +106,17 @@ func MIMC7Hash(xIn, k *big.Int) *big.Int { return constants.fqR.Affine(constants.fqR.Add(r, k)) } -// Hash performs the MIMC7 hash over a RElem array -func Hash(arrEl []RElem, key *big.Int) RElem { - arr := RElemsToBigInts(arrEl) +// Hash performs the MIMC7 hash over a *big.Int array +func Hash(arr []*big.Int, key *big.Int) (*big.Int, error) { + if !utils.CheckBigIntArrayInField(arr, constants.fqR.Q) { + return nil, errors.New("inputs values not inside Finite Field") + } var r *big.Int if key == nil { r = constants.fqR.Zero() } else { r = key } - // r := constants.iv for i := 0; i < len(arr); i++ { r = constants.fqR.Add( constants.fqR.Add( @@ -155,5 +125,5 @@ func Hash(arrEl []RElem, key *big.Int) RElem { ), MIMC7Hash(arr[i], r)) } - return RElem(r) + return r, nil } diff --git a/mimc7/mimc7_test.go b/mimc7/mimc7_test.go index 893cc9d..a5ee769 100644 --- a/mimc7/mimc7_test.go +++ b/mimc7/mimc7_test.go @@ -10,40 +10,6 @@ import ( "github.com/stretchr/testify/assert" ) -func TestUtils(t *testing.T) { - b1 := big.NewInt(int64(1)) - b2 := big.NewInt(int64(2)) - b3 := big.NewInt(int64(3)) - arrBigInt := []*big.Int{b1, b2, b3} - - // *big.Int array to RElem array - rElems, err := BigIntsToRElems(arrBigInt) - assert.Nil(t, err) - - // RElem array to *big.Int array - bElems := RElemsToBigInts(rElems) - - assert.Equal(t, arrBigInt, bElems) - - r, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10) - assert.True(t, ok) - - // greater or equal than R will give error when passing bigInts to RElems, to fit in the R Finite Field - overR, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495618", 10) - assert.True(t, ok) - _, err = BigIntsToRElems([]*big.Int{b1, overR, b2}) - assert.True(t, err != nil) - - _, err = BigIntsToRElems([]*big.Int{b1, r, b2}) - assert.True(t, err != nil) - - // smaller than R will not give error when passing bigInts to RElems, to fit in the R Finite Field - underR, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495616", 10) - assert.True(t, ok) - _, err = BigIntsToRElems([]*big.Int{b1, underR, b2}) - assert.Nil(t, err) -} - func TestKeccak256(t *testing.T) { res := crypto.Keccak256([]byte(SEED)) assert.Equal(t, "b6e489e6b37224a50bebfddbe7d89fa8fdcaa84304a70bd13f79b5d9f7951e9e", hex.EncodeToString(res)) @@ -61,14 +27,11 @@ func TestMIMC7Generic(t *testing.T) { fqR := field.NewFq(r) bigArray := []*big.Int{b1, b2, b3} - elementsArray, err := BigIntsToRElems(bigArray) - assert.Nil(t, err) // Generic Hash mhg := MIMC7HashGeneric(fqR, b1, b2, 91) - assert.Nil(t, err) assert.Equal(t, "10594780656576967754230020536574539122676596303354946869887184401991294982664", mhg.String()) - hg, err := HashGeneric(fqR.Zero(), elementsArray, fqR, 91) + hg, err := HashGeneric(fqR.Zero(), bigArray, fqR, 91) assert.Nil(t, err) assert.Equal(t, "6464402164086696096195815557694604139393321133243036833927490113253119343397", (*big.Int)(hg).String()) } @@ -81,44 +44,36 @@ func TestMIMC7(t *testing.T) { // h1, hash of 1 elements bigArray1 := []*big.Int{b12} - elementsArray1, err := BigIntsToRElems(bigArray1) - assert.Nil(t, err) - h1 := Hash(elementsArray1, nil) + h1, err := Hash(bigArray1, nil) assert.Nil(t, err) // same hash value than the iden3js and circomlib tests: assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h1).Bytes()), "0x237c92644dbddb86d8a259e0e923aaab65a93f1ec5758b8799988894ac0958fd") // h2a, hash of 2 elements bigArray2a := []*big.Int{b78, b41} - elementsArray2a, err := BigIntsToRElems(bigArray2a) - assert.Nil(t, err) - h2a := Hash(elementsArray2a, nil) + h2a, err := Hash(bigArray2a, nil) assert.Nil(t, err) // same hash value than the iden3js and circomlib tests: assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h2a).Bytes()), "0x067f3202335ea256ae6e6aadcd2d5f7f4b06a00b2d1e0de903980d5ab552dc70") // h2b, hash of 2 elements bigArray2b := []*big.Int{b12, b45} - elementsArray2b, err := BigIntsToRElems(bigArray2b) - assert.Nil(t, err) mh2b := MIMC7Hash(b12, b45) assert.Nil(t, err) assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(mh2b).Bytes()), "0x2ba7ebad3c6b6f5a20bdecba2333c63173ca1a5f2f49d958081d9fa7179c44e4") - h2b := Hash(elementsArray2b, nil) + h2b, err := Hash(bigArray2b, nil) assert.Nil(t, err) // same hash value than the iden3js and circomlib tests: assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h2b).Bytes()), "0x15ff7fe9793346a17c3150804bcb36d161c8662b110c50f55ccb7113948d8879") // h4, hash of 4 elements bigArray4 := []*big.Int{b12, b45, b78, b41} - elementsArray4, err := BigIntsToRElems(bigArray4) - assert.Nil(t, err) - h4 := Hash(elementsArray4, nil) + h4, err := Hash(bigArray4, nil) assert.Nil(t, err) // same hash value than the iden3js and circomlib tests: assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h4).Bytes()), "0x284bc1f34f335933a23a433b6ff3ee179d682cd5e5e2fcdd2d964afa85104beb") @@ -130,12 +85,10 @@ func BenchmarkMIMC7(b *testing.B) { b78 := big.NewInt(int64(78)) b41 := big.NewInt(int64(41)) bigArray4 := []*big.Int{b12, b45, b78, b41} - elementsArray4, err := BigIntsToRElems(bigArray4) - assert.Nil(b, err) - var h4 RElem + var h4 *big.Int for i := 0; i < b.N; i++ { - h4 = Hash(elementsArray4, nil) + h4, _ = Hash(bigArray4, nil) } println(h4) }