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 }