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 }