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