github.com/consensys/gnark-crypto@v0.14.0/ecc/bw6-756/hash_to_g1.go (about) 1 // Copyright 2020 Consensys Software Inc. 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 // Code generated by consensys/gnark-crypto DO NOT EDIT 16 17 package bw6756 18 19 import ( 20 "github.com/consensys/gnark-crypto/ecc/bw6-756/fp" 21 22 "math/big" 23 ) 24 25 //Note: This only works for simple extensions 26 27 func g1IsogenyXNumerator(dst *fp.Element, x *fp.Element) { 28 g1EvalPolynomial(dst, 29 false, 30 []fp.Element{ 31 {15061764643505403874, 13688922241935764410, 13945096449919150208, 8436067060318510061, 4337050741185236015, 1993211805393091759, 13630591835847640353, 16993584682990519360, 8971204976640521592, 11479362202198843551, 7505613342680806802, 2623277435220162}, 32 {2256652953469429710, 7986151259564652590, 7173717765514014760, 5325211358772542105, 11720722258571317741, 1827380411336239380, 2945628459421726487, 15684476260997112721, 16275963394068506199, 3647627339057733797, 6840443943923060230, 2788437309956548}, 33 {18446744073709550557, 14704964401664098303, 11309681711681649385, 14698000069680550214, 13454959400917254747, 10801466177653926084, 15239716878514852502, 16581223703780321416, 14202840701532685566, 17948097119401515826, 5922093086188465715, 2268644466718328}, 34 }, 35 x) 36 } 37 38 func g1IsogenyXDenominator(dst *fp.Element, x *fp.Element) { 39 g1EvalPolynomial(dst, 40 true, 41 []fp.Element{ 42 {9026611813877718838, 6035453010921316536, 17062904658006647585, 11643627583491349159, 14230214847810026090, 5797047097534633924, 14807366920250713864, 14779814887555727504, 10347853169840149009, 1246596934729393539, 13141619286505907834, 2448522848965627}, 43 }, 44 x) 45 } 46 47 func g1IsogenyYNumerator(dst *fp.Element, x *fp.Element, y *fp.Element) { 48 var _dst fp.Element 49 g1EvalPolynomial(&_dst, 50 false, 51 []fp.Element{ 52 {7417, 4223785464154554368, 17883137121165483676, 8662155583981545100, 8014120713948809746, 1201662146881371066, 16399484201235277962, 16741102533822300073, 10092115902138952610, 11731609449449782212, 5432405448762957777, 1529941514692833}, 53 {17685820612365145165, 10133590496207434412, 4439341389815863358, 16237166311366871531, 12586675296657379027, 5752817071182370007, 18238899548945746049, 5474128448956424977, 4657871854268244383, 3092250989713984389, 13902867206193867696, 2147032802810159}, 54 {3384979430204144565, 11979226889346978885, 1537204611416246332, 17211189075013588966, 17581083387856976611, 11964442653859134878, 13641814725987365538, 14303342354640893273, 15190573054247983491, 5471441008586600696, 10260665915884590345, 4182655964934822}, 55 {18446744073709551087, 18441456226093760511, 13174518475280565460, 9763304497739979922, 14890648247077438592, 5778851725779543941, 6863645168616474272, 15668448372570953649, 6955362397092648018, 12310026665076143326, 11127771683818204033, 3310628831074305}, 56 }, 57 x) 58 59 dst.Mul(&_dst, y) 60 } 61 62 func g1IsogenyYDenominator(dst *fp.Element, x *fp.Element) { 63 g1EvalPolynomial(dst, 64 true, 65 []fp.Element{ 66 {33905, 17146720447904350208, 4439688729395715465, 17578719130422492408, 13009726419073394047, 17697253371943596573, 3126642749599797879, 15395188361529500510, 1711728968787230262, 252749604653387985, 14374699731745910598, 1397801387328302}, 67 {17266182735847260650, 2756724634261996626, 1058985484926618486, 5542736661445693400, 1636838704864690045, 12564472000181253073, 6593938171842885778, 4786584001734410359, 1113513889954172149, 12176975388293072748, 6351201184167411439, 1553692990780230}, 68 {8633091367923604897, 14375155055950078505, 17702614661430909603, 11655529750965086232, 7917563376482904218, 16634904018698739975, 9041039154614942318, 11137027547596045016, 12888931343158284942, 15514578667146961408, 4644663504360229534, 2992955351466600}, 69 }, 70 x) 71 } 72 73 func g1Isogeny(p *G1Affine) { 74 75 den := make([]fp.Element, 2) 76 77 g1IsogenyYDenominator(&den[1], &p.X) 78 g1IsogenyXDenominator(&den[0], &p.X) 79 80 g1IsogenyYNumerator(&p.Y, &p.X, &p.Y) 81 g1IsogenyXNumerator(&p.X, &p.X) 82 83 den = fp.BatchInvert(den) 84 85 p.X.Mul(&p.X, &den[0]) 86 p.Y.Mul(&p.Y, &den[1]) 87 } 88 89 // g1SqrtRatio computes the square root of u/v and returns 0 iff u/v was indeed a quadratic residue 90 // if not, we get sqrt(Z * u / v). Recall that Z is non-residue 91 // If v = 0, u/v is meaningless and the output is unspecified, without raising an error. 92 // The main idea is that since the computation of the square root involves taking large powers of u/v, the inversion of v can be avoided 93 func g1SqrtRatio(z *fp.Element, u *fp.Element, v *fp.Element) uint64 { 94 95 // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-sqrt_ratio-for-any-field 96 97 tv1 := fp.Element{17302715199413996045, 15077845457253267709, 8842885729139027579, 12189878420705505575, 12380986790262239346, 585111498723936856, 4947215576903759546, 1186632482028566920, 14543050817583235372, 5644943604719368358, 9440830989708189862, 1039766423535362} //tv1 = c6 98 99 var tv2, tv3, tv4, tv5 fp.Element 100 var exp big.Int 101 // c4 = 4835703278458516698824703 = 2⁸² - 1 102 // q is odd so c1 is at least 1. 103 exp.SetBytes([]byte{3, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}) 104 105 tv2.Exp(*v, &exp) // 2. tv2 = vᶜ⁴ 106 tv3.Square(&tv2) // 3. tv3 = tv2² 107 tv3.Mul(&tv3, v) // 4. tv3 = tv3 * v 108 tv5.Mul(u, &tv3) // 5. tv5 = u * tv3 109 110 // c3 = 37877157660731232732990269576663233239936484746509109593426423261538632780449313352717366389444912082695314931794809746268936574949192324351273838279701014606648452884726586254167471840902479876056412368 111 exp.SetBytes([]byte{1, 238, 213, 183, 107, 119, 49, 92, 85, 130, 79, 195, 198, 173, 25, 235, 146, 241, 154, 95, 88, 89, 209, 63, 126, 70, 68, 40, 170, 44, 116, 217, 152, 213, 206, 120, 133, 72, 219, 61, 96, 89, 2, 93, 64, 159, 85, 65, 79, 214, 57, 103, 160, 220, 200, 220, 82, 89, 162, 189, 182, 200, 212, 168, 96, 85, 71, 132, 177, 188, 251, 218, 22, 208, 189, 13, 10, 73, 216, 6, 120, 252, 199, 240, 208}) 112 113 tv5.Exp(tv5, &exp) // 6. tv5 = tv5ᶜ³ 114 tv5.Mul(&tv5, &tv2) // 7. tv5 = tv5 * tv2 115 tv2.Mul(&tv5, v) // 8. tv2 = tv5 * v 116 tv3.Mul(&tv5, u) // 9. tv3 = tv5 * u 117 tv4.Mul(&tv3, &tv2) // 10. tv4 = tv3 * tv2 118 119 // c5 = 2417851639229258349412352 120 exp.SetBytes([]byte{2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) 121 tv5.Exp(tv4, &exp) // 11. tv5 = tv4ᶜ⁵ 122 isQNr := g1NotOne(&tv5) // 12. isQR = tv5 == 1 123 c7 := fp.Element{13990906742184113945, 15879050380504523621, 13768460034940508157, 12337541071329853620, 6296858130192020747, 9289986178217863086, 18403114759403589657, 4546259071787184045, 5504643400205978814, 13830311104669138548, 96107744534255859, 1024735223965534} 124 tv2.Mul(&tv3, &c7) // 13. tv2 = tv3 * c7 125 tv5.Mul(&tv4, &tv1) // 14. tv5 = tv4 * tv1 126 tv3.Select(int(isQNr), &tv3, &tv2) // 15. tv3 = CMOV(tv2, tv3, isQR) 127 tv4.Select(int(isQNr), &tv4, &tv5) // 16. tv4 = CMOV(tv5, tv4, isQR) 128 exp.Lsh(big.NewInt(1), 82-2) // 18, 19: tv5 = 2ⁱ⁻² for i = c1 129 130 for i := 82; i >= 2; i-- { // 17. for i in (c1, c1 - 1, ..., 2): 131 132 tv5.Exp(tv4, &exp) // 20. tv5 = tv4ᵗᵛ⁵ 133 nE1 := g1NotOne(&tv5) // 21. e1 = tv5 == 1 134 tv2.Mul(&tv3, &tv1) // 22. tv2 = tv3 * tv1 135 tv1.Mul(&tv1, &tv1) // 23. tv1 = tv1 * tv1 Why not write square? 136 tv5.Mul(&tv4, &tv1) // 24. tv5 = tv4 * tv1 137 tv3.Select(int(nE1), &tv3, &tv2) // 25. tv3 = CMOV(tv2, tv3, e1) 138 tv4.Select(int(nE1), &tv4, &tv5) // 26. tv4 = CMOV(tv5, tv4, e1) 139 140 if i > 2 { 141 exp.Rsh(&exp, 1) // 18, 19. tv5 = 2ⁱ⁻² 142 } 143 } 144 145 *z = tv3 146 return isQNr 147 } 148 149 func g1NotOne(x *fp.Element) uint64 { 150 151 var one fp.Element 152 return one.SetOne().NotEqual(x) 153 154 } 155 156 // g1MulByZ multiplies x by [11] and stores the result in z 157 func g1MulByZ(z *fp.Element, x *fp.Element) { 158 159 res := *x 160 161 res.Double(&res) 162 res.Double(&res) 163 res.Add(&res, x) 164 res.Double(&res) 165 res.Add(&res, x) 166 167 *z = res 168 } 169 170 // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-simplified-swu-method 171 // MapToCurve1 implements the SSWU map 172 // No cofactor clearing or isogeny 173 func MapToCurve1(u *fp.Element) G1Affine { 174 175 var sswuIsoCurveCoeffA = fp.Element{6087387690755251612, 7643068232434215576, 6195945763281467660, 97569654519975969, 1505434147110560758, 12342644747290341982, 14059794106692380317, 15229664573794943703, 16908793757593141664, 1949816925291208189, 9451095697369482684, 234190359239853} 176 var sswuIsoCurveCoeffB = fp.Element{18446744073709458379, 881299893533802495, 4886355625346099349, 6225448195760991771, 6629400315996169345, 12607886696045185322, 7201730065066775519, 1932403901886200506, 8616600553259348813, 6369175937589644082, 7499857803942196586, 3773119276850162} 177 178 var tv1 fp.Element 179 tv1.Square(u) // 1. tv1 = u² 180 181 //mul tv1 by Z 182 g1MulByZ(&tv1, &tv1) // 2. tv1 = Z * tv1 183 184 var tv2 fp.Element 185 tv2.Square(&tv1) // 3. tv2 = tv1² 186 tv2.Add(&tv2, &tv1) // 4. tv2 = tv2 + tv1 187 188 var tv3 fp.Element 189 var tv4 fp.Element 190 tv4.SetOne() 191 tv3.Add(&tv2, &tv4) // 5. tv3 = tv2 + 1 192 tv3.Mul(&tv3, &sswuIsoCurveCoeffB) // 6. tv3 = B * tv3 193 194 tv2NZero := g1NotZero(&tv2) 195 196 // tv4 = Z 197 tv4 = fp.Element{18446744073709504998, 11529623972028612607, 739483395258014634, 5527028560780200701, 11477868704616895891, 15905434021829949368, 2844651761892435780, 17567410508478669002, 4162242322955979641, 15743938111024983262, 11916654042695069468, 4062866236140222} 198 199 tv2.Neg(&tv2) 200 tv4.Select(int(tv2NZero), &tv4, &tv2) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) 201 tv4.Mul(&tv4, &sswuIsoCurveCoeffA) // 8. tv4 = A * tv4 202 203 tv2.Square(&tv3) // 9. tv2 = tv3² 204 205 var tv6 fp.Element 206 tv6.Square(&tv4) // 10. tv6 = tv4² 207 208 var tv5 fp.Element 209 tv5.Mul(&tv6, &sswuIsoCurveCoeffA) // 11. tv5 = A * tv6 210 211 tv2.Add(&tv2, &tv5) // 12. tv2 = tv2 + tv5 212 tv2.Mul(&tv2, &tv3) // 13. tv2 = tv2 * tv3 213 tv6.Mul(&tv6, &tv4) // 14. tv6 = tv6 * tv4 214 215 tv5.Mul(&tv6, &sswuIsoCurveCoeffB) // 15. tv5 = B * tv6 216 tv2.Add(&tv2, &tv5) // 16. tv2 = tv2 + tv5 217 218 var x fp.Element 219 x.Mul(&tv1, &tv3) // 17. x = tv1 * tv3 220 221 var y1 fp.Element 222 gx1NSquare := g1SqrtRatio(&y1, &tv2, &tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) 223 224 var y fp.Element 225 y.Mul(&tv1, u) // 19. y = tv1 * u 226 227 y.Mul(&y, &y1) // 20. y = y * y1 228 229 x.Select(int(gx1NSquare), &tv3, &x) // 21. x = CMOV(x, tv3, is_gx1_square) 230 y.Select(int(gx1NSquare), &y1, &y) // 22. y = CMOV(y, y1, is_gx1_square) 231 232 y1.Neg(&y) 233 y.Select(int(g1Sgn0(u)^g1Sgn0(&y)), &y, &y1) 234 235 // 23. e1 = sgn0(u) == sgn0(y) 236 // 24. y = CMOV(-y, y, e1) 237 238 x.Div(&x, &tv4) // 25. x = x / tv4 239 240 return G1Affine{x, y} 241 } 242 243 func g1EvalPolynomial(z *fp.Element, monic bool, coefficients []fp.Element, x *fp.Element) { 244 dst := coefficients[len(coefficients)-1] 245 246 if monic { 247 dst.Add(&dst, x) 248 } 249 250 for i := len(coefficients) - 2; i >= 0; i-- { 251 dst.Mul(&dst, x) 252 dst.Add(&dst, &coefficients[i]) 253 } 254 255 z.Set(&dst) 256 } 257 258 // g1Sgn0 is an algebraic substitute for the notion of sign in ordered fields 259 // Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign 260 // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-the-sgn0-function 261 // The sign of an element is not obviously related to that of its Montgomery form 262 func g1Sgn0(z *fp.Element) uint64 { 263 264 nonMont := z.Bits() 265 266 // m == 1 267 return nonMont[0] % 2 268 269 } 270 271 // MapToG1 invokes the SSWU map, and guarantees that the result is in g1 272 func MapToG1(u fp.Element) G1Affine { 273 res := MapToCurve1(&u) 274 //this is in an isogenous curve 275 g1Isogeny(&res) 276 res.ClearCofactor(&res) 277 return res 278 } 279 280 // EncodeToG1 hashes a message to a point on the G1 curve using the SSWU map. 281 // It is faster than HashToG1, but the result is not uniformly distributed. Unsuitable as a random oracle. 282 // dst stands for "domain separation tag", a string unique to the construction using the hash function 283 // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap 284 func EncodeToG1(msg, dst []byte) (G1Affine, error) { 285 286 var res G1Affine 287 u, err := fp.Hash(msg, dst, 1) 288 if err != nil { 289 return res, err 290 } 291 292 res = MapToCurve1(&u[0]) 293 294 //this is in an isogenous curve 295 g1Isogeny(&res) 296 res.ClearCofactor(&res) 297 return res, nil 298 } 299 300 // HashToG1 hashes a message to a point on the G1 curve using the SSWU map. 301 // Slower than EncodeToG1, but usable as a random oracle. 302 // dst stands for "domain separation tag", a string unique to the construction using the hash function 303 // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap 304 func HashToG1(msg, dst []byte) (G1Affine, error) { 305 u, err := fp.Hash(msg, dst, 2*1) 306 if err != nil { 307 return G1Affine{}, err 308 } 309 310 Q0 := MapToCurve1(&u[0]) 311 Q1 := MapToCurve1(&u[1]) 312 313 //TODO (perf): Add in E' first, then apply isogeny 314 g1Isogeny(&Q0) 315 g1Isogeny(&Q1) 316 317 var _Q0, _Q1 G1Jac 318 _Q0.FromAffine(&Q0) 319 _Q1.FromAffine(&Q1).AddAssign(&_Q0) 320 321 _Q1.ClearCofactor(&_Q1) 322 323 Q1.FromJacobian(&_Q1) 324 return Q1, nil 325 } 326 327 func g1NotZero(x *fp.Element) uint64 { 328 329 return x[0] | x[1] | x[2] | x[3] | x[4] | x[5] | x[6] | x[7] | x[8] | x[9] | x[10] | x[11] 330 331 }