github.com/consensys/gnark-crypto@v0.14.0/ecc/bls12-381/hash_to_g2.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 bls12381 18 19 import ( 20 "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" 21 "github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower" 22 23 "math/big" 24 ) 25 26 //Note: This only works for simple extensions 27 28 func g2IsogenyXNumerator(dst *fptower.E2, x *fptower.E2) { 29 g2EvalPolynomial(dst, 30 false, 31 []fptower.E2{ 32 { 33 A0: fp.Element{5185457120960601698, 494647221959407934, 8971396042087821730, 324544954362548322, 14214792730224113654, 1405280679127738945}, 34 A1: fp.Element{5185457120960601698, 494647221959407934, 8971396042087821730, 324544954362548322, 14214792730224113654, 1405280679127738945}, 35 }, 36 { 37 A0: fp.Element{0}, 38 A1: fp.Element{6910023028261548496, 9745789443900091043, 7668299866710145304, 2432656849393633605, 2897729527445498821, 776645607375592125}, 39 }, 40 { 41 A0: fp.Element{724047465092313539, 15783990863276714670, 12824896677063784855, 15246381572572671516, 13186611051602728692, 1485475813959743803}, 42 A1: fp.Element{12678383550985550056, 4872894721950045521, 13057521970209848460, 10439700461551592610, 10672236800577525218, 388322803687796062}, 43 }, 44 { 45 A0: fp.Element{4659755689450087917, 1804066951354704782, 15570919779568036803, 15592734958806855601, 7597208057374167129, 1841438384006890194}, 46 A1: fp.Element{0}, 47 }, 48 }, 49 x) 50 } 51 52 func g2IsogenyXDenominator(dst *fptower.E2, x *fptower.E2) { 53 g2EvalPolynomial(dst, 54 true, 55 []fptower.E2{ 56 { 57 A0: fp.Element{0}, 58 A1: fp.Element{2250392438786206615, 17463829474098544446, 14571211649711714824, 4495761442775821336, 258811604141191305, 357646605018048850}, 59 }, 60 { 61 A0: fp.Element{4933130441833534766, 15904462746612662304, 8034115857496836953, 12755092135412849606, 7007796720291435703, 252692002104915169}, 62 A1: fp.Element{8469300574244328829, 4752422838614097887, 17848302789776796362, 12930989898711414520, 16851051131888818207, 1621106615542624696}, 63 }, 64 }, 65 x) 66 } 67 68 func g2IsogenyYNumerator(dst *fptower.E2, x *fptower.E2, y *fptower.E2) { 69 var _dst fptower.E2 70 g2EvalPolynomial(&_dst, 71 false, 72 []fptower.E2{ 73 { 74 A0: fp.Element{10869708750642247614, 13056187057366814946, 1750362034917495549, 6326189602300757217, 1140223926335695785, 632761649765668291}, 75 A1: fp.Element{10869708750642247614, 13056187057366814946, 1750362034917495549, 6326189602300757217, 1140223926335695785, 632761649765668291}, 76 }, 77 { 78 A0: fp.Element{0}, 79 A1: fp.Element{13765940311003083782, 5579209876153186557, 11349908400803699438, 11707848830955952341, 199199289641242246, 899896674917908607}, 80 }, 81 { 82 A0: fp.Element{15562563812347550836, 2436447360975022760, 6528760985104924230, 5219850230775796305, 5336118400288762609, 194161401843898031}, 83 A1: fp.Element{16286611277439864375, 18220438224251737430, 906913588459157469, 2019487729638916206, 75985378181939686, 1679637215803641835}, 84 }, 85 { 86 A0: fp.Element{11849179119594500956, 13906615243538674725, 14543197362847770509, 2041759640812427310, 2879701092679313252, 1259985822978576468}, 87 A1: fp.Element{0}, 88 }, 89 }, 90 x) 91 92 dst.Mul(&_dst, y) 93 } 94 95 func g2IsogenyYDenominator(dst *fptower.E2, x *fptower.E2) { 96 g2EvalPolynomial(dst, 97 true, 98 []fptower.E2{ 99 { 100 A0: fp.Element{99923616639376095, 10339114964526300021, 6204619029868000785, 1288486622530663893, 14587509920085997152, 272081012460753233}, 101 A1: fp.Element{99923616639376095, 10339114964526300021, 6204619029868000785, 1288486622530663893, 14587509920085997152, 272081012460753233}, 102 }, 103 { 104 A0: fp.Element{0}, 105 A1: fp.Element{6751177316358619845, 15498000274876530106, 6820146801716041242, 13487284328327464010, 776434812423573915, 1072939815054146550}, 106 }, 107 { 108 A0: fp.Element{7399695662750302149, 14633322083064217648, 12051173786245255430, 9909266166264498601, 1288323043582377747, 379038003157372754}, 109 A1: fp.Element{6002735353327561446, 6023563502162542543, 13831244861028377885, 15776815867859765525, 4123780734888324547, 1494760614490167112}, 110 }, 111 }, 112 x) 113 } 114 115 func g2Isogeny(p *G2Affine) { 116 117 den := make([]fptower.E2, 2) 118 119 g2IsogenyYDenominator(&den[1], &p.X) 120 g2IsogenyXDenominator(&den[0], &p.X) 121 122 g2IsogenyYNumerator(&p.Y, &p.X, &p.Y) 123 g2IsogenyXNumerator(&p.X, &p.X) 124 125 den = fptower.BatchInvertE2(den) 126 127 p.X.Mul(&p.X, &den[0]) 128 p.Y.Mul(&p.Y, &den[1]) 129 } 130 131 // g2SqrtRatio computes the square root of u/v and returns 0 iff u/v was indeed a quadratic residue 132 // if not, we get sqrt(Z * u / v). Recall that Z is non-residue 133 // If v = 0, u/v is meaningless and the output is unspecified, without raising an error. 134 // 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 135 func g2SqrtRatio(z *fptower.E2, u *fptower.E2, v *fptower.E2) uint64 { 136 137 // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-sqrt_ratio-for-any-field 138 139 tv1 := fptower.E2{ 140 A0: fp.Element{8921533702591418330, 15859389534032789116, 3389114680249073393, 15116930867080254631, 3288288975085550621, 1021049300055853010}, 141 A1: fp.Element{8921533702591418330, 15859389534032789116, 3389114680249073393, 15116930867080254631, 3288288975085550621, 1021049300055853010}, 142 } //tv1 = c6 143 144 var tv2, tv3, tv4, tv5 fptower.E2 145 var exp big.Int 146 // c4 = 7 = 2³ - 1 147 // q is odd so c1 is at least 1. 148 exp.SetBytes([]byte{7}) 149 150 tv2.Exp(*v, &exp) // 2. tv2 = vᶜ⁴ 151 tv3.Square(&tv2) // 3. tv3 = tv2² 152 tv3.Mul(&tv3, v) // 4. tv3 = tv3 * v 153 tv5.Mul(u, &tv3) // 5. tv5 = u * tv3 154 155 // c3 = 1001205140483106588246484290269935788605945006208159541241399033561623546780709821462541004956387089373434649096260670658193992783731681621012512651314777238193313314641988297376025498093520728838658813979860931248214124593092835 156 exp.SetBytes([]byte{42, 67, 122, 75, 140, 53, 252, 116, 189, 39, 142, 170, 34, 242, 94, 158, 45, 201, 14, 80, 231, 4, 107, 70, 110, 89, 228, 147, 73, 232, 189, 5, 10, 98, 207, 209, 109, 220, 166, 239, 83, 20, 147, 48, 151, 142, 240, 17, 214, 134, 25, 200, 97, 133, 199, 178, 146, 232, 90, 135, 9, 26, 4, 150, 107, 249, 30, 211, 231, 27, 116, 49, 98, 195, 56, 54, 33, 19, 207, 215, 206, 214, 177, 215, 99, 130, 234, 178, 106, 160, 0, 1, 199, 24, 227}) 157 158 tv5.Exp(tv5, &exp) // 6. tv5 = tv5ᶜ³ 159 tv5.Mul(&tv5, &tv2) // 7. tv5 = tv5 * tv2 160 tv2.Mul(&tv5, v) // 8. tv2 = tv5 * v 161 tv3.Mul(&tv5, u) // 9. tv3 = tv5 * u 162 tv4.Mul(&tv3, &tv2) // 10. tv4 = tv3 * tv2 163 164 // c5 = 4 165 exp.SetBytes([]byte{4}) 166 tv5.Exp(tv4, &exp) // 11. tv5 = tv4ᶜ⁵ 167 isQNr := g2NotOne(&tv5) // 12. isQR = tv5 == 1 168 c7 := fptower.E2{ 169 A0: fp.Element{1921729236329761493, 9193968980645934504, 9862280504246317678, 6861748847800817560, 10375788487011937166, 4460107375738415}, 170 A1: fp.Element{16821121318233475459, 10183025025229892778, 1779012082459463630, 3442292649700377418, 1061500799026501234, 1352426537312017168}, 171 } 172 tv2.Mul(&tv3, &c7) // 13. tv2 = tv3 * c7 173 tv5.Mul(&tv4, &tv1) // 14. tv5 = tv4 * tv1 174 tv3.Select(int(isQNr), &tv3, &tv2) // 15. tv3 = CMOV(tv2, tv3, isQR) 175 tv4.Select(int(isQNr), &tv4, &tv5) // 16. tv4 = CMOV(tv5, tv4, isQR) 176 exp.Lsh(big.NewInt(1), 3-2) // 18, 19: tv5 = 2ⁱ⁻² for i = c1 177 178 for i := 3; i >= 2; i-- { // 17. for i in (c1, c1 - 1, ..., 2): 179 180 tv5.Exp(tv4, &exp) // 20. tv5 = tv4ᵗᵛ⁵ 181 nE1 := g2NotOne(&tv5) // 21. e1 = tv5 == 1 182 tv2.Mul(&tv3, &tv1) // 22. tv2 = tv3 * tv1 183 tv1.Mul(&tv1, &tv1) // 23. tv1 = tv1 * tv1 Why not write square? 184 tv5.Mul(&tv4, &tv1) // 24. tv5 = tv4 * tv1 185 tv3.Select(int(nE1), &tv3, &tv2) // 25. tv3 = CMOV(tv2, tv3, e1) 186 tv4.Select(int(nE1), &tv4, &tv5) // 26. tv4 = CMOV(tv5, tv4, e1) 187 188 if i > 2 { 189 exp.Rsh(&exp, 1) // 18, 19. tv5 = 2ⁱ⁻² 190 } 191 } 192 193 *z = tv3 194 return isQNr 195 } 196 197 func g2NotOne(x *fptower.E2) uint64 { 198 199 //Assuming hash is implemented for G1 and that the curve is over Fp 200 var one fp.Element 201 return one.SetOne().NotEqual(&x.A0) | g1NotZero(&x.A1) 202 203 } 204 205 // g2MulByZ multiplies x by [-2, -1] and stores the result in z 206 func g2MulByZ(z *fptower.E2, x *fptower.E2) { 207 208 z.Mul(x, &fptower.E2{ 209 A0: fp.Element{9794203289623549276, 7309342082925068282, 1139538881605221074, 15659550692327388916, 16008355200866287827, 582484205531694093}, 210 A1: fp.Element{4897101644811774638, 3654671041462534141, 569769440802610537, 17053147383018470266, 17227549637287919721, 291242102765847046}, 211 }) 212 213 } 214 215 // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-simplified-swu-method 216 // MapToCurve2 implements the SSWU map 217 // No cofactor clearing or isogeny 218 func MapToCurve2(u *fptower.E2) G2Affine { 219 220 var sswuIsoCurveCoeffA = fptower.E2{ 221 A0: fp.Element{0}, 222 A1: fp.Element{16517514583386313282, 74322656156451461, 16683759486841714365, 815493829203396097, 204518332920448171, 1306242806803223655}, 223 } 224 var sswuIsoCurveCoeffB = fptower.E2{ 225 A0: fp.Element{2515823342057463218, 7982686274772798116, 7934098172177393262, 8484566552980779962, 4455086327883106868, 1323173589274087377}, 226 A1: fp.Element{2515823342057463218, 7982686274772798116, 7934098172177393262, 8484566552980779962, 4455086327883106868, 1323173589274087377}, 227 } 228 229 var tv1 fptower.E2 230 tv1.Square(u) // 1. tv1 = u² 231 232 //mul tv1 by Z 233 g2MulByZ(&tv1, &tv1) // 2. tv1 = Z * tv1 234 235 var tv2 fptower.E2 236 tv2.Square(&tv1) // 3. tv2 = tv1² 237 tv2.Add(&tv2, &tv1) // 4. tv2 = tv2 + tv1 238 239 var tv3 fptower.E2 240 var tv4 fptower.E2 241 tv4.SetOne() 242 tv3.Add(&tv2, &tv4) // 5. tv3 = tv2 + 1 243 tv3.Mul(&tv3, &sswuIsoCurveCoeffB) // 6. tv3 = B * tv3 244 245 tv2NZero := g2NotZero(&tv2) 246 247 // tv4 = Z 248 tv4 = fptower.E2{ 249 A0: fp.Element{9794203289623549276, 7309342082925068282, 1139538881605221074, 15659550692327388916, 16008355200866287827, 582484205531694093}, 250 A1: fp.Element{4897101644811774638, 3654671041462534141, 569769440802610537, 17053147383018470266, 17227549637287919721, 291242102765847046}, 251 } 252 253 tv2.Neg(&tv2) 254 tv4.Select(int(tv2NZero), &tv4, &tv2) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) 255 tv4.Mul(&tv4, &sswuIsoCurveCoeffA) // 8. tv4 = A * tv4 256 257 tv2.Square(&tv3) // 9. tv2 = tv3² 258 259 var tv6 fptower.E2 260 tv6.Square(&tv4) // 10. tv6 = tv4² 261 262 var tv5 fptower.E2 263 tv5.Mul(&tv6, &sswuIsoCurveCoeffA) // 11. tv5 = A * tv6 264 265 tv2.Add(&tv2, &tv5) // 12. tv2 = tv2 + tv5 266 tv2.Mul(&tv2, &tv3) // 13. tv2 = tv2 * tv3 267 tv6.Mul(&tv6, &tv4) // 14. tv6 = tv6 * tv4 268 269 tv5.Mul(&tv6, &sswuIsoCurveCoeffB) // 15. tv5 = B * tv6 270 tv2.Add(&tv2, &tv5) // 16. tv2 = tv2 + tv5 271 272 var x fptower.E2 273 x.Mul(&tv1, &tv3) // 17. x = tv1 * tv3 274 275 var y1 fptower.E2 276 gx1NSquare := g2SqrtRatio(&y1, &tv2, &tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) 277 278 var y fptower.E2 279 y.Mul(&tv1, u) // 19. y = tv1 * u 280 281 y.Mul(&y, &y1) // 20. y = y * y1 282 283 x.Select(int(gx1NSquare), &tv3, &x) // 21. x = CMOV(x, tv3, is_gx1_square) 284 y.Select(int(gx1NSquare), &y1, &y) // 22. y = CMOV(y, y1, is_gx1_square) 285 286 y1.Neg(&y) 287 y.Select(int(g2Sgn0(u)^g2Sgn0(&y)), &y, &y1) 288 289 // 23. e1 = sgn0(u) == sgn0(y) 290 // 24. y = CMOV(-y, y, e1) 291 292 x.Div(&x, &tv4) // 25. x = x / tv4 293 294 return G2Affine{x, y} 295 } 296 297 func g2EvalPolynomial(z *fptower.E2, monic bool, coefficients []fptower.E2, x *fptower.E2) { 298 dst := coefficients[len(coefficients)-1] 299 300 if monic { 301 dst.Add(&dst, x) 302 } 303 304 for i := len(coefficients) - 2; i >= 0; i-- { 305 dst.Mul(&dst, x) 306 dst.Add(&dst, &coefficients[i]) 307 } 308 309 z.Set(&dst) 310 } 311 312 // g2Sgn0 is an algebraic substitute for the notion of sign in ordered fields 313 // Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign 314 // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-the-sgn0-function 315 // The sign of an element is not obviously related to that of its Montgomery form 316 func g2Sgn0(z *fptower.E2) uint64 { 317 318 nonMont := z.Bits() 319 320 sign := uint64(0) // 1. sign = 0 321 zero := uint64(1) // 2. zero = 1 322 var signI uint64 323 var zeroI uint64 324 325 // 3. i = 1 326 signI = nonMont.A0[0] % 2 // 4. sign_i = x_i mod 2 327 zeroI = g1NotZero(&nonMont.A0) 328 zeroI = 1 ^ (zeroI|-zeroI)>>63 // 5. zero_i = x_i == 0 329 sign = sign | (zero & signI) // 6. sign = sign OR (zero AND sign_i) # Avoid short-circuit logic ops 330 zero = zero & zeroI // 7. zero = zero AND zero_i 331 // 3. i = 2 332 signI = nonMont.A1[0] % 2 // 4. sign_i = x_i mod 2 333 // 5. zero_i = x_i == 0 334 sign = sign | (zero & signI) // 6. sign = sign OR (zero AND sign_i) # Avoid short-circuit logic ops 335 // 7. zero = zero AND zero_i 336 return sign 337 338 } 339 340 // MapToG2 invokes the SSWU map, and guarantees that the result is in g2 341 func MapToG2(u fptower.E2) G2Affine { 342 res := MapToCurve2(&u) 343 //this is in an isogenous curve 344 g2Isogeny(&res) 345 res.ClearCofactor(&res) 346 return res 347 } 348 349 // EncodeToG2 hashes a message to a point on the G2 curve using the SSWU map. 350 // It is faster than HashToG2, but the result is not uniformly distributed. Unsuitable as a random oracle. 351 // dst stands for "domain separation tag", a string unique to the construction using the hash function 352 // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap 353 func EncodeToG2(msg, dst []byte) (G2Affine, error) { 354 355 var res G2Affine 356 u, err := fp.Hash(msg, dst, 2) 357 if err != nil { 358 return res, err 359 } 360 361 res = MapToCurve2(&fptower.E2{ 362 A0: u[0], 363 A1: u[1], 364 }) 365 366 //this is in an isogenous curve 367 g2Isogeny(&res) 368 res.ClearCofactor(&res) 369 return res, nil 370 } 371 372 // HashToG2 hashes a message to a point on the G2 curve using the SSWU map. 373 // Slower than EncodeToG2, but usable as a random oracle. 374 // dst stands for "domain separation tag", a string unique to the construction using the hash function 375 // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap 376 func HashToG2(msg, dst []byte) (G2Affine, error) { 377 u, err := fp.Hash(msg, dst, 2*2) 378 if err != nil { 379 return G2Affine{}, err 380 } 381 382 Q0 := MapToCurve2(&fptower.E2{ 383 A0: u[0], 384 A1: u[1], 385 }) 386 Q1 := MapToCurve2(&fptower.E2{ 387 A0: u[2+0], 388 A1: u[2+1], 389 }) 390 391 //TODO (perf): Add in E' first, then apply isogeny 392 g2Isogeny(&Q0) 393 g2Isogeny(&Q1) 394 395 var _Q0, _Q1 G2Jac 396 _Q0.FromAffine(&Q0) 397 _Q1.FromAffine(&Q1).AddAssign(&_Q0) 398 399 _Q1.ClearCofactor(&_Q1) 400 401 Q1.FromJacobian(&_Q1) 402 return Q1, nil 403 } 404 405 func g2NotZero(x *fptower.E2) uint64 { 406 //Assuming G1 is over Fp and that if hashing is available for G2, it also is for G1 407 return g1NotZero(&x.A0) | g1NotZero(&x.A1) 408 409 }