github.com/consensys/gnark-crypto@v0.14.0/ecc/stark-curve/hash_to_g1_test.go (about)

     1  // Copyright 2020 ConsenSys Software Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // FOO
    16  
    17  package starkcurve
    18  
    19  import (
    20  	"github.com/consensys/gnark-crypto/ecc/stark-curve/fp"
    21  	"github.com/leanovate/gopter"
    22  	"github.com/leanovate/gopter/prop"
    23  	"math/rand"
    24  	"testing"
    25  )
    26  
    27  func TestHashToFpG1(t *testing.T) {
    28  	for _, c := range encodeToG1Vector.cases {
    29  		elems, err := fp.Hash([]byte(c.msg), encodeToG1Vector.dst, 1)
    30  		if err != nil {
    31  			t.Error(err)
    32  		}
    33  		g1TestMatchCoord(t, "u", c.msg, c.u, g1CoordAt(elems, 0))
    34  	}
    35  
    36  	for _, c := range hashToG1Vector.cases {
    37  		elems, err := fp.Hash([]byte(c.msg), hashToG1Vector.dst, 2*1)
    38  		if err != nil {
    39  			t.Error(err)
    40  		}
    41  		g1TestMatchCoord(t, "u0", c.msg, c.u0, g1CoordAt(elems, 0))
    42  		g1TestMatchCoord(t, "u1", c.msg, c.u1, g1CoordAt(elems, 1))
    43  	}
    44  }
    45  
    46  func TestMapToCurve1(t *testing.T) {
    47  	t.Parallel()
    48  	parameters := gopter.DefaultTestParameters()
    49  	if testing.Short() {
    50  		parameters.MinSuccessfulTests = nbFuzzShort
    51  	} else {
    52  		parameters.MinSuccessfulTests = nbFuzz
    53  	}
    54  
    55  	properties := gopter.NewProperties(parameters)
    56  
    57  	properties.Property("[G1] mapping output must be on curve", prop.ForAll(
    58  		func(a fp.Element) bool {
    59  
    60  			g := MapToCurve1(&a)
    61  
    62  			if !g.IsOnCurve() {
    63  				t.Log("SVDW output not on curve")
    64  				return false
    65  			}
    66  
    67  			return true
    68  		},
    69  		GenFp(),
    70  	))
    71  
    72  	properties.TestingRun(t, gopter.ConsoleReporter(false))
    73  
    74  	for _, c := range encodeToG1Vector.cases {
    75  		var u fp.Element
    76  		g1CoordSetString(&u, c.u)
    77  		q := MapToCurve1(&u)
    78  		g1TestMatchPoint(t, "Q", c.msg, c.Q, &q)
    79  	}
    80  
    81  	for _, c := range hashToG1Vector.cases {
    82  		var u fp.Element
    83  		g1CoordSetString(&u, c.u0)
    84  		q := MapToCurve1(&u)
    85  		g1TestMatchPoint(t, "Q0", c.msg, c.Q0, &q)
    86  
    87  		g1CoordSetString(&u, c.u1)
    88  		q = MapToCurve1(&u)
    89  		g1TestMatchPoint(t, "Q1", c.msg, c.Q1, &q)
    90  	}
    91  }
    92  
    93  func TestMapToG1(t *testing.T) {
    94  	t.Parallel()
    95  	parameters := gopter.DefaultTestParameters()
    96  	if testing.Short() {
    97  		parameters.MinSuccessfulTests = nbFuzzShort
    98  	} else {
    99  		parameters.MinSuccessfulTests = nbFuzz
   100  	}
   101  
   102  	properties := gopter.NewProperties(parameters)
   103  
   104  	properties.Property("[G1] mapping to curve should output point on the curve", prop.ForAll(
   105  		func(a fp.Element) bool {
   106  			g := MapToG1(a)
   107  			return g.IsInSubGroup()
   108  		},
   109  		GenFp(),
   110  	))
   111  
   112  	properties.Property("[G1] mapping to curve should be deterministic", prop.ForAll(
   113  		func(a fp.Element) bool {
   114  			g1 := MapToG1(a)
   115  			g2 := MapToG1(a)
   116  			return g1.Equal(&g2)
   117  		},
   118  		GenFp(),
   119  	))
   120  
   121  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   122  }
   123  
   124  func TestEncodeToG1(t *testing.T) {
   125  	t.Parallel()
   126  	for _, c := range encodeToG1Vector.cases {
   127  		p, err := EncodeToG1([]byte(c.msg), encodeToG1Vector.dst)
   128  		if err != nil {
   129  			t.Fatal(err)
   130  		}
   131  		g1TestMatchPoint(t, "P", c.msg, c.P, &p)
   132  	}
   133  }
   134  
   135  func TestHashToG1(t *testing.T) {
   136  	t.Parallel()
   137  	for _, c := range hashToG1Vector.cases {
   138  		p, err := HashToG1([]byte(c.msg), hashToG1Vector.dst)
   139  		if err != nil {
   140  			t.Fatal(err)
   141  		}
   142  		g1TestMatchPoint(t, "P", c.msg, c.P, &p)
   143  	}
   144  }
   145  
   146  func BenchmarkEncodeToG1(b *testing.B) {
   147  	const size = 54
   148  	bytes := make([]byte, size)
   149  	dst := encodeToG1Vector.dst
   150  	b.ResetTimer()
   151  
   152  	for i := 0; i < b.N; i++ {
   153  
   154  		bytes[rand.Int()%size] = byte(rand.Int()) //#nosec G404 weak rng is fine here
   155  
   156  		if _, err := EncodeToG1(bytes, dst); err != nil {
   157  			b.Fail()
   158  		}
   159  	}
   160  }
   161  
   162  func BenchmarkHashToG1(b *testing.B) {
   163  	const size = 54
   164  	bytes := make([]byte, size)
   165  	dst := hashToG1Vector.dst
   166  	b.ResetTimer()
   167  
   168  	for i := 0; i < b.N; i++ {
   169  
   170  		bytes[rand.Int()%size] = byte(rand.Int()) //#nosec G404 weak rng is fine here
   171  
   172  		if _, err := HashToG1(bytes, dst); err != nil {
   173  			b.Fail()
   174  		}
   175  	}
   176  }
   177  
   178  // Only works on simple extensions (two-story towers)
   179  func g1CoordSetString(z *fp.Element, s string) {
   180  	z.SetString(s)
   181  }
   182  
   183  func g1CoordAt(slice []fp.Element, i int) fp.Element {
   184  	return slice[i]
   185  }
   186  
   187  func g1TestMatchCoord(t *testing.T, coordName string, msg string, expectedStr string, seen fp.Element) {
   188  	var expected fp.Element
   189  
   190  	g1CoordSetString(&expected, expectedStr)
   191  
   192  	if !expected.Equal(&seen) {
   193  		t.Errorf("mismatch on \"%s\", %s:\n\texpected %s\n\tsaw      %s", msg, coordName, expected.String(), &seen)
   194  	}
   195  }
   196  
   197  func g1TestMatchPoint(t *testing.T, pointName string, msg string, expected point, seen *G1Affine) {
   198  	g1TestMatchCoord(t, pointName+".x", msg, expected.x, seen.X)
   199  	g1TestMatchCoord(t, pointName+".y", msg, expected.y, seen.Y)
   200  }
   201  
   202  type hashTestVector struct {
   203  	dst   []byte
   204  	cases []hashTestCase
   205  }
   206  
   207  type encodeTestVector struct {
   208  	dst   []byte
   209  	cases []encodeTestCase
   210  }
   211  
   212  type point struct {
   213  	x string
   214  	y string
   215  }
   216  
   217  type encodeTestCase struct {
   218  	msg string
   219  	P   point  //pY a coordinate of P, the final output
   220  	u   string //u hashed onto the field
   221  	Q   point  //Q map to curve output
   222  }
   223  
   224  type hashTestCase struct {
   225  	msg string
   226  	P   point  //pY a coordinate of P, the final output
   227  	u0  string //u0 hashed onto the field
   228  	u1  string //u1 extra hashed onto the field
   229  	Q0  point  //Q0 map to curve output
   230  	Q1  point  //Q1 extra map to curve output
   231  }
   232  
   233  var encodeToG1Vector encodeTestVector
   234  var hashToG1Vector hashTestVector