github.com/consensys/gnark-crypto@v0.14.0/ecc/bls24-317/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 bls24317
    16  
    17  import (
    18  	"github.com/consensys/gnark-crypto/ecc/bls24-317/fp"
    19  	"github.com/consensys/gnark-crypto/ecc/bls24-317/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.E4) 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.E4
    31  	z.B0.A0.SetOne()
    32  	z.B1.A0.SetOne()
    33  	c1.B0.A0.SetString("4")
    34  	c1.B0.A1.SetString("3")
    35  	c1.B1.A0.SetString("8")
    36  	c1.B1.A1.SetOne()
    37  	c2.B0.A0.SetString("68196535552147955757549882954137028530972556060709796988605069651952986598616012809013078365525")
    38  	c2.B1.A0.SetString("68196535552147955757549882954137028530972556060709796988605069651952986598616012809013078365525")
    39  	c3.B0.A0.SetString("25710473854271083900266173357439657657737168361084633536126117969329631844210973452609964652920")
    40  	c3.B0.A1.SetString("97726383423614678023078817471231282096435936120492353286347028233584612721291548146704405526838")
    41  	c3.B1.A0.SetString("31017010388646627031356727289998252571046265059138887207088052022600004087627603083210545186274")
    42  	c3.B1.A1.SetString("74637498440051236880963727555084502172097851690589624852957691761203766904143491322222931488114")
    43  	c4.B0.A0.SetString("136393071104295911515099765908274057061945112121419593977210139303905973197232025618026156731039")
    44  	c4.B0.A1.SetString("90928714069530607676733177272182704707963408080946395984806759535937315464821350412017437820690")
    45  	c4.B1.A0.SetString("90928714069530607676733177272182704707963408080946395984806759535937315464821350412017437820710")
    46  	c4.B1.A1.SetString("90928714069530607676733177272182704707963408080946395984806759535937315464821350412017437820706")
    47  
    48  	var tv1, tv2, tv3, tv4, one, x1, gx1, x2, gx2, x3, x, gx, y fptower.E4
    49  	one.SetOne()
    50  	tv1.Square(&u).Mul(&tv1, &c1)
    51  	tv2.Add(&one, &tv1)
    52  	tv1.Sub(&one, &tv1)
    53  	tv3.Mul(&tv2, &tv1).Inverse(&tv3)
    54  	tv4.Mul(&u, &tv1)
    55  	tv4.Mul(&tv4, &tv3)
    56  	tv4.Mul(&tv4, &c3)
    57  	x1.Sub(&c2, &tv4)
    58  	gx1.Square(&x1)
    59  	// 12. gx1 = gx1 + A
    60  	gx1.Mul(&gx1, &x1)
    61  	gx1.Add(&gx1, &bTwistCurveCoeff)
    62  	e1 := gx1.Legendre()
    63  	x2.Add(&c2, &tv4)
    64  	gx2.Square(&x2)
    65  	// 18. gx2 = gx2 + A
    66  	gx2.Mul(&gx2, &x2)
    67  	gx2.Add(&gx2, &bTwistCurveCoeff)
    68  	e2 := gx2.Legendre() - e1 // 2 if is_square(gx2) AND NOT e1
    69  	x3.Square(&tv2)
    70  	x3.Mul(&x3, &tv3)
    71  	x3.Square(&x3)
    72  	x3.Mul(&x3, &c4)
    73  	x3.Add(&x3, &z)
    74  	if e1 == 1 {
    75  		x.Set(&x1)
    76  	} else {
    77  		x.Set(&x3)
    78  	}
    79  	if e2 == 2 {
    80  		x.Set(&x2)
    81  	}
    82  	gx.Square(&x)
    83  	// gx = gx + A
    84  	gx.Mul(&gx, &x)
    85  	gx.Add(&gx, &bTwistCurveCoeff)
    86  	y.Sqrt(&gx)
    87  	e3 := sign0(u.B0.A0) && sign0(y.B0.A0)
    88  	if !e3 {
    89  		y.Neg(&y)
    90  	}
    91  	res.X.Set(&x)
    92  	res.Y.Set(&y)
    93  
    94  	return res
    95  }
    96  
    97  // MapToG2 maps an fp.Element to a point on the curve using the Shallue and van de Woestijne map
    98  // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-2.2.1
    99  func MapToG2(t fptower.E4) G2Affine {
   100  	res := MapToCurve2(t)
   101  	res.ClearCofactor(&res)
   102  	return res
   103  }
   104  
   105  // EncodeToG2 maps an fp.Element to a point on the curve using the Shallue and van de Woestijne map
   106  // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-2.2.2
   107  func EncodeToG2(msg, dst []byte) (G2Affine, error) {
   108  	var res G2Affine
   109  	_t, err := fp.Hash(msg, dst, 2)
   110  	if err != nil {
   111  		return res, err
   112  	}
   113  	var t fptower.E4
   114  	t.B0.A0.Set(&_t[0])
   115  	t.B1.A0.Set(&_t[1])
   116  	res = MapToG2(t)
   117  	return res, nil
   118  }
   119  
   120  // HashToG2 maps an fp.Element to a point on the curve using the Shallue and van de Woestijne map
   121  // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-3
   122  func HashToG2(msg, dst []byte) (G2Affine, error) {
   123  	var res G2Affine
   124  	u, err := fp.Hash(msg, dst, 4)
   125  	if err != nil {
   126  		return res, err
   127  	}
   128  	var u0, u1 fptower.E4
   129  	u0.B0.A0.Set(&u[0])
   130  	u0.B1.A0.Set(&u[1])
   131  	u1.B0.A0.Set(&u[2])
   132  	u1.B1.A0.Set(&u[3])
   133  	Q0 := MapToG2(u0)
   134  	Q1 := MapToG2(u1)
   135  	var _Q0, _Q1, _res G2Jac
   136  	_Q0.FromAffine(&Q0)
   137  	_Q1.FromAffine(&Q1)
   138  	_res.Set(&_Q1).AddAssign(&_Q0)
   139  	res.FromJacobian(&_res)
   140  	return res, nil
   141  }
   142  
   143  // returns false if u>-u when seen as a bigInt
   144  func sign0(u fp.Element) bool {
   145  	return !u.LexicographicallyLargest()
   146  }