github.com/consensys/gnark-crypto@v0.14.0/ecc/bls12-378/hash_to_g2.go (about)

     1  // Copyright 2020 ConsenSys AG
     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  package bls12378
    16  
    17  import (
    18  	"github.com/consensys/gnark-crypto/ecc/bls12-378/fp"
    19  	"github.com/consensys/gnark-crypto/ecc/bls12-378/internal/fptower"
    20  )
    21  
    22  // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-4.1
    23  // Shallue and van de Woestijne method, works for any elliptic curve in Weierstrass curve
    24  func MapToCurve2(u fptower.E2) G2Affine {
    25  
    26  	var res G2Affine
    27  
    28  	// constants
    29  	// sage script to find z: https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#appendix-E.1
    30  	var z, c1, c2, c3, c4 fptower.E2
    31  	z.A0.SetOne()
    32  	z.A1.SetOne()
    33  	c1.A0.SetString("605248206075306171733248481581800960739847691770924913753520744034740935903401304776283802348837311170974282940403")
    34  	c1.A1.SetString("605248206075306171733248481581800960739847691770924913753520744034740935903401304776283802348837311170974282940416")
    35  	c2.A0.SetString("302624103037653085866624240790900480369923845885462456876760372017370467951700652388141901174418655585487141470208")
    36  	c2.A1.SetString("302624103037653085866624240790900480369923845885462456876760372017370467951700652388141901174418655585487141470208")
    37  	c3.A0.SetString("296552843788751288906244499216725356684281694271241895700730864223961612014909088554048735457137528455181151573749")
    38  	c3.A1.SetString("181388265705333345538985517067130917207305732282979825233670477511990909086507141331244586890249042878909613862256")
    39  	c4.A0.SetString("224166002250113396938240178363629985459202848804046264353155831123978124408667149917142149018087893026286771459412")
    40  	c4.A1.SetString("313832403150158755713536249709081979642883988325664770094418163573569374172134009883999008625323050236801480043178")
    41  
    42  	var tv1, tv2, tv3, tv4, one, x1, gx1, x2, gx2, x3, x, gx, y fptower.E2
    43  	one.SetOne()
    44  	tv1.Square(&u).Mul(&tv1, &c1)
    45  	tv2.Add(&one, &tv1)
    46  	tv1.Sub(&one, &tv1)
    47  	tv3.Mul(&tv2, &tv1).Inverse(&tv3)
    48  	tv4.Mul(&u, &tv1)
    49  	tv4.Mul(&tv4, &tv3)
    50  	tv4.Mul(&tv4, &c3)
    51  	x1.Sub(&c2, &tv4)
    52  	gx1.Square(&x1)
    53  	// 12. gx1 = gx1 + A
    54  	gx1.Mul(&gx1, &x1)
    55  	gx1.Add(&gx1, &bTwistCurveCoeff)
    56  	e1 := gx1.Legendre()
    57  	x2.Add(&c2, &tv4)
    58  	gx2.Square(&x2)
    59  	// 18. gx2 = gx2 + A
    60  	gx2.Mul(&gx2, &x2)
    61  	gx2.Add(&gx2, &bTwistCurveCoeff)
    62  	e2 := gx2.Legendre() - e1 // 2 if is_square(gx2) AND NOT e1
    63  	x3.Square(&tv2)
    64  	x3.Mul(&x3, &tv3)
    65  	x3.Square(&x3)
    66  	x3.Mul(&x3, &c4)
    67  	x3.Add(&x3, &z)
    68  	if e1 == 1 {
    69  		x.Set(&x1)
    70  	} else {
    71  		x.Set(&x3)
    72  	}
    73  	if e2 == 2 {
    74  		x.Set(&x2)
    75  	}
    76  	gx.Square(&x)
    77  	// gx = gx + A
    78  	gx.Mul(&gx, &x)
    79  	gx.Add(&gx, &bTwistCurveCoeff)
    80  	y.Sqrt(&gx)
    81  	e3 := sign0(u.A0) && sign0(y.A0)
    82  	if !e3 {
    83  		y.Neg(&y)
    84  	}
    85  	res.X.Set(&x)
    86  	res.Y.Set(&y)
    87  
    88  	return res
    89  }
    90  
    91  // MapToG2 maps an fp.Element to a point on the curve using the Shallue and van de Woestijne map
    92  // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-2.2.1
    93  func MapToG2(t fptower.E2) G2Affine {
    94  	res := MapToCurve2(t)
    95  	res.ClearCofactor(&res)
    96  	return res
    97  }
    98  
    99  // EncodeToG2 maps an fp.Element to a point on the curve using the Shallue and van de Woestijne map
   100  // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-2.2.2
   101  func EncodeToG2(msg, dst []byte) (G2Affine, error) {
   102  	var res G2Affine
   103  	_t, err := fp.Hash(msg, dst, 2)
   104  	if err != nil {
   105  		return res, err
   106  	}
   107  	var t fptower.E2
   108  	t.A0.Set(&_t[0])
   109  	t.A1.Set(&_t[1])
   110  	res = MapToG2(t)
   111  	return res, nil
   112  }
   113  
   114  // HashToG2 maps an fp.Element to a point on the curve using the Shallue and van de Woestijne map
   115  // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-3
   116  func HashToG2(msg, dst []byte) (G2Affine, error) {
   117  	var res G2Affine
   118  	u, err := fp.Hash(msg, dst, 4)
   119  	if err != nil {
   120  		return res, err
   121  	}
   122  	var u0, u1 fptower.E2
   123  	u0.A0.Set(&u[0])
   124  	u0.A1.Set(&u[1])
   125  	u1.A0.Set(&u[2])
   126  	u1.A1.Set(&u[3])
   127  	Q0 := MapToG2(u0)
   128  	Q1 := MapToG2(u1)
   129  	var _Q0, _Q1, _res G2Jac
   130  	_Q0.FromAffine(&Q0)
   131  	_Q1.FromAffine(&Q1)
   132  	_res.Set(&_Q1).AddAssign(&_Q0)
   133  	res.FromJacobian(&_res)
   134  	return res, nil
   135  }
   136  
   137  // returns false if u>-u when seen as a bigInt
   138  func sign0(u fp.Element) bool {
   139  	return !u.LexicographicallyLargest()
   140  }