github.com/consensys/gnark-crypto@v0.14.0/ecc/bw6-761/hash_to_g2_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  // Code generated by consensys/gnark-crypto DO NOT EDIT
    16  
    17  package bw6761
    18  
    19  import (
    20  	"github.com/consensys/gnark-crypto/ecc/bw6-761/fp"
    21  	"github.com/leanovate/gopter"
    22  	"github.com/leanovate/gopter/prop"
    23  	"math/rand"
    24  	"testing"
    25  )
    26  
    27  func TestG2SqrtRatio(t *testing.T) {
    28  	t.Parallel()
    29  	parameters := gopter.DefaultTestParameters()
    30  	if testing.Short() {
    31  		parameters.MinSuccessfulTests = nbFuzzShort
    32  	} else {
    33  		parameters.MinSuccessfulTests = nbFuzz
    34  	}
    35  
    36  	properties := gopter.NewProperties(parameters)
    37  
    38  	gen := GenFp()
    39  
    40  	properties.Property("G2SqrtRatio must square back to the right value", prop.ForAll(
    41  		func(u fp.Element, v fp.Element) bool {
    42  
    43  			var seen fp.Element
    44  			qr := g2SqrtRatio(&seen, &u, &v) == 0
    45  
    46  			seen.
    47  				Square(&seen).
    48  				Mul(&seen, &v)
    49  
    50  			var ref fp.Element
    51  			if qr {
    52  				ref = u
    53  			} else {
    54  				g2MulByZ(&ref, &u)
    55  			}
    56  
    57  			return seen.Equal(&ref)
    58  		}, gen, gen))
    59  
    60  	properties.TestingRun(t, gopter.ConsoleReporter(false))
    61  }
    62  
    63  func TestHashToFpG2(t *testing.T) {
    64  	for _, c := range encodeToG2Vector.cases {
    65  		elems, err := fp.Hash([]byte(c.msg), encodeToG2Vector.dst, 1)
    66  		if err != nil {
    67  			t.Error(err)
    68  		}
    69  		g2TestMatchCoord(t, "u", c.msg, c.u, g2CoordAt(elems, 0))
    70  	}
    71  
    72  	for _, c := range hashToG2Vector.cases {
    73  		elems, err := fp.Hash([]byte(c.msg), hashToG2Vector.dst, 2*1)
    74  		if err != nil {
    75  			t.Error(err)
    76  		}
    77  		g2TestMatchCoord(t, "u0", c.msg, c.u0, g2CoordAt(elems, 0))
    78  		g2TestMatchCoord(t, "u1", c.msg, c.u1, g2CoordAt(elems, 1))
    79  	}
    80  }
    81  
    82  func TestMapToCurve2(t *testing.T) {
    83  	t.Parallel()
    84  	parameters := gopter.DefaultTestParameters()
    85  	if testing.Short() {
    86  		parameters.MinSuccessfulTests = nbFuzzShort
    87  	} else {
    88  		parameters.MinSuccessfulTests = nbFuzz
    89  	}
    90  
    91  	properties := gopter.NewProperties(parameters)
    92  
    93  	properties.Property("[G2] mapping output must be on curve", prop.ForAll(
    94  		func(a fp.Element) bool {
    95  
    96  			g := MapToCurve2(&a)
    97  
    98  			if !isOnE2Prime(g) {
    99  				t.Log("Mapping output not on E' curve")
   100  				return false
   101  			}
   102  			g2Isogeny(&g)
   103  
   104  			if !g.IsOnCurve() {
   105  				t.Log("Isogeny∘SSWU output not on curve")
   106  				return false
   107  			}
   108  
   109  			return true
   110  		},
   111  		GenFp(),
   112  	))
   113  
   114  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   115  
   116  	for _, c := range encodeToG2Vector.cases {
   117  		var u fp.Element
   118  		g2CoordSetString(&u, c.u)
   119  		q := MapToCurve2(&u)
   120  		g2Isogeny(&q)
   121  		g2TestMatchPoint(t, "Q", c.msg, c.Q, &q)
   122  	}
   123  
   124  	for _, c := range hashToG2Vector.cases {
   125  		var u fp.Element
   126  		g2CoordSetString(&u, c.u0)
   127  		q := MapToCurve2(&u)
   128  		g2Isogeny(&q)
   129  		g2TestMatchPoint(t, "Q0", c.msg, c.Q0, &q)
   130  
   131  		g2CoordSetString(&u, c.u1)
   132  		q = MapToCurve2(&u)
   133  		g2Isogeny(&q)
   134  		g2TestMatchPoint(t, "Q1", c.msg, c.Q1, &q)
   135  	}
   136  }
   137  
   138  func TestMapToG2(t *testing.T) {
   139  	t.Parallel()
   140  	parameters := gopter.DefaultTestParameters()
   141  	if testing.Short() {
   142  		parameters.MinSuccessfulTests = nbFuzzShort
   143  	} else {
   144  		parameters.MinSuccessfulTests = nbFuzz
   145  	}
   146  
   147  	properties := gopter.NewProperties(parameters)
   148  
   149  	properties.Property("[G2] mapping to curve should output point on the curve", prop.ForAll(
   150  		func(a fp.Element) bool {
   151  			g := MapToG2(a)
   152  			return g.IsInSubGroup()
   153  		},
   154  		GenFp(),
   155  	))
   156  
   157  	properties.Property("[G2] mapping to curve should be deterministic", prop.ForAll(
   158  		func(a fp.Element) bool {
   159  			g1 := MapToG2(a)
   160  			g2 := MapToG2(a)
   161  			return g1.Equal(&g2)
   162  		},
   163  		GenFp(),
   164  	))
   165  
   166  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   167  }
   168  
   169  func TestEncodeToG2(t *testing.T) {
   170  	t.Parallel()
   171  	for _, c := range encodeToG2Vector.cases {
   172  		p, err := EncodeToG2([]byte(c.msg), encodeToG2Vector.dst)
   173  		if err != nil {
   174  			t.Fatal(err)
   175  		}
   176  		g2TestMatchPoint(t, "P", c.msg, c.P, &p)
   177  	}
   178  }
   179  
   180  func TestHashToG2(t *testing.T) {
   181  	t.Parallel()
   182  	for _, c := range hashToG2Vector.cases {
   183  		p, err := HashToG2([]byte(c.msg), hashToG2Vector.dst)
   184  		if err != nil {
   185  			t.Fatal(err)
   186  		}
   187  		g2TestMatchPoint(t, "P", c.msg, c.P, &p)
   188  	}
   189  }
   190  
   191  func BenchmarkEncodeToG2(b *testing.B) {
   192  	const size = 54
   193  	bytes := make([]byte, size)
   194  	dst := encodeToG2Vector.dst
   195  	b.ResetTimer()
   196  
   197  	for i := 0; i < b.N; i++ {
   198  
   199  		bytes[rand.Int()%size] = byte(rand.Int()) //#nosec G404 weak rng is fine here
   200  
   201  		if _, err := EncodeToG2(bytes, dst); err != nil {
   202  			b.Fail()
   203  		}
   204  	}
   205  }
   206  
   207  func BenchmarkHashToG2(b *testing.B) {
   208  	const size = 54
   209  	bytes := make([]byte, size)
   210  	dst := hashToG2Vector.dst
   211  	b.ResetTimer()
   212  
   213  	for i := 0; i < b.N; i++ {
   214  
   215  		bytes[rand.Int()%size] = byte(rand.Int()) //#nosec G404 weak rng is fine here
   216  
   217  		if _, err := HashToG2(bytes, dst); err != nil {
   218  			b.Fail()
   219  		}
   220  	}
   221  }
   222  
   223  // TODO: Crude. Do something clever in Jacobian
   224  func isOnE2Prime(p G2Affine) bool {
   225  
   226  	var A, B fp.Element
   227  
   228  	A.SetString(
   229  		"6429719010846137499474887978131198018330761288163789627290055406883908067119696591103101123992665411263189240363728172709848698522760005194862816392151436104205214136976570209818204605171075531070134198773930389453798390056516896",
   230  	)
   231  
   232  	B.SetString(
   233  		"5348306863922295212600474030012704926780090705412552782187041272079620891140642329199277344037019889626771397168162938103438296026272884909103171857394985776682488984714989551922989188985164920238405955336107390943902906254560160",
   234  	)
   235  
   236  	var LHS fp.Element
   237  	LHS.
   238  		Square(&p.Y).
   239  		Sub(&LHS, &B)
   240  
   241  	var RHS fp.Element
   242  	RHS.
   243  		Square(&p.X).
   244  		Add(&RHS, &A).
   245  		Mul(&RHS, &p.X)
   246  
   247  	return LHS.Equal(&RHS)
   248  }
   249  
   250  // Only works on simple extensions (two-story towers)
   251  func g2CoordSetString(z *fp.Element, s string) {
   252  	z.SetString(s)
   253  }
   254  
   255  func g2CoordAt(slice []fp.Element, i int) fp.Element {
   256  	return slice[i]
   257  }
   258  
   259  func g2TestMatchCoord(t *testing.T, coordName string, msg string, expectedStr string, seen fp.Element) {
   260  	var expected fp.Element
   261  
   262  	g2CoordSetString(&expected, expectedStr)
   263  
   264  	if !expected.Equal(&seen) {
   265  		t.Errorf("mismatch on \"%s\", %s:\n\texpected %s\n\tsaw      %s", msg, coordName, expected.String(), &seen)
   266  	}
   267  }
   268  
   269  func g2TestMatchPoint(t *testing.T, pointName string, msg string, expected point, seen *G2Affine) {
   270  	g2TestMatchCoord(t, pointName+".x", msg, expected.x, seen.X)
   271  	g2TestMatchCoord(t, pointName+".y", msg, expected.y, seen.Y)
   272  }
   273  
   274  var encodeToG2Vector encodeTestVector
   275  var hashToG2Vector hashTestVector