github.com/consensys/gnark-crypto@v0.14.0/ecc/bw6-633/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 bw6633 18 19 import ( 20 "github.com/consensys/gnark-crypto/ecc/bw6-633/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 {7272862494598035149, 17938690902425062231, 17767077323866067514, 4042726381719152827, 18265955203653031758, 7989828268732772972, 18236438619995713786, 9293367820166308923, 579132017742513255, 61135481787611126}, 32 {14103265042103244800, 8689209911719872644, 4354557994639147275, 10015585990482518164, 7421596411839167820, 4090839137155710457, 11608543132371831098, 13726191584359776921, 5686323290725750987, 81414521630725786}, 33 {18168148533207762438, 11427550061515796123, 18288052689977291309, 17549058602874803907, 1811835605999111241, 14482385559564730468, 18371679523324113956, 7570413432649696247, 5685594971732218569, 10775296935876024}, 34 {17728445431987990123, 8760786791117372111, 2573782286514545042, 1334017444068088326, 13467298694204265433, 6851979702063838450, 988626161393389398, 16562654212673250360, 12282014862309670411, 80101036366709613}, 35 {2326830949067553368, 3529405818358416595, 146860478980129391, 1676900901388419777, 1082703688237676999, 7387945513834349563, 9650183203768502904, 11145522862419582316, 13264718987205403361, 13256495642676566}, 36 {12664678546015998202, 10045674430418935451, 7730403065839041631, 8219534329550967867, 1124289072196216451, 14392018765708614948, 16565553149614556003, 15197943132749823589, 12019150165746003035, 24988392243039541}, 37 {6694676015950629658, 7127563144408641267, 7082407350490358984, 17809866550737839973, 8771033794417365609, 10016426335785311067, 12427530939245540241, 3052758539102218458, 11641228273074855077, 25565165552182336}, 38 {9724060856090837937, 991577158671892474, 8081435887940851138, 17002015655933157445, 16512917147008832308, 4279771572102941926, 2249177714740675361, 7317077314484777626, 9914066020430477973, 6118378914363629}, 39 }, 40 x) 41 } 42 43 func g1IsogenyXDenominator(dst *fp.Element, x *fp.Element) { 44 g1EvalPolynomial(dst, 45 true, 46 []fp.Element{ 47 {7689367989221506360, 8466465815454855662, 5983600713003646820, 2581385575943478091, 9916432639299762387, 10803845534690581303, 13766744687398880084, 15045951258274284650, 10804811560468246090, 29872680157072640}, 48 {17931533655233022896, 2616834597954890161, 15297975164914689963, 12590465759698493931, 10233486349520996474, 735196127439996935, 3560747164676852194, 10735851124747749259, 17674946501015660508, 3306627583693497}, 49 {17716592541637989415, 2308856258992909515, 12321274951566722095, 15518009541869506179, 17585856967648697577, 13662172177461470988, 11485518780630966140, 8578584312450957544, 6227931909735105992, 33357481697750278}, 50 {16987009127955058020, 9531687309899711333, 8408043309689180103, 607401699215863109, 18292924216570439182, 13998767425014867069, 5338398210358867446, 14267801732372066290, 6813736547055367223, 61325738952091138}, 51 {13421066935948937976, 12318222198047014607, 14834312436015053872, 16700627760283291334, 4891844673141485395, 6252497771692828833, 11433160297376574630, 9870447387776384328, 11354566386586086837, 63511274412395176}, 52 {3111070609570438967, 6386169732085448708, 3204145000601381420, 17010231417177763314, 8617715899066662393, 536344151661697031, 7755071729129494035, 3825968914207782957, 2784415075519314680, 9751775967500675}, 53 }, 54 x) 55 } 56 57 func g1IsogenyYNumerator(dst *fp.Element, x *fp.Element, y *fp.Element) { 58 var _dst fp.Element 59 g1EvalPolynomial(&_dst, 60 false, 61 []fp.Element{ 62 {9878447280690208476, 18035489718126671479, 16185036754982099195, 7328840215175603832, 3327555148021634143, 4731603924914666172, 14264314873550791027, 4538983491650033364, 1173609413709250348, 10349586991384491}, 63 {6013373483158194119, 10820801813182078326, 14598847571665760046, 11500540534236838924, 7782052717321334748, 14140166529189609834, 2964884042771384841, 16207414686346775778, 4629732333568574423, 4878794148730819}, 64 {12584528423975290756, 5798690717935596347, 6840751821254968468, 4803032538791716164, 4985526036624269917, 1479700245295912748, 13313798593102419181, 4969411887124120857, 3015920959041820281, 44921547284500425}, 65 {10461467081920196626, 16934070357422525213, 9517834684613575055, 2313584312088805570, 9031354913035368886, 12671644525466129236, 15886041369872958427, 16719536892038789270, 3829106597473744278, 1931735510244152}, 66 {14746212271987435353, 16614700088184332548, 12732527948961695321, 8527366302977827323, 17516184175149545265, 16732051276961112757, 13204423237463486744, 5000382421388638456, 7180920511183622623, 11555120281504263}, 67 {8663947747845995257, 16792483225373063374, 18268521190375255935, 4876326292498032031, 736768499122237671, 18244916601541093591, 4363883771233911261, 8989384718461158638, 12859624057357757038, 80977983165161056}, 68 {1888392448147101547, 278604480652219071, 18128419606300115944, 9201243398782896594, 6846159496103160821, 18248972704629781971, 8579402342792036543, 10976917330220264136, 11266589230198511881, 51029070295934750}, 69 {14247728228070040725, 11277441241513723962, 13278074988262372791, 5925040732263282901, 4830744489723491604, 13429219773244868874, 9574076864314497862, 15801710222777129423, 8208683544227273702, 13968877296974686}, 70 {10004935117279285226, 17549535430748601812, 12561470574481243390, 17245589729476447997, 6611491938405591356, 8408236954437324051, 8684479128757933086, 15579257205718648740, 13276819376284075144, 6359286773003154}, 71 {12326780164586609392, 5644226856352746503, 15218547976647793114, 1423996738351226436, 17696389932683702646, 16585810622359183722, 11617060654723736714, 10287699425090206986, 6288819172487953077, 58313628540302044}, 72 }, 73 x) 74 75 dst.Mul(&_dst, y) 76 } 77 78 func g1IsogenyYDenominator(dst *fp.Element, x *fp.Element) { 79 g1EvalPolynomial(dst, 80 true, 81 []fp.Element{ 82 {14197616310547505477, 13248972589415769338, 5655590928954867770, 14499450495178324765, 10477012947100229518, 18368542199165419613, 2341453125094301785, 13165751376957884540, 2845217790110152808, 67501159738732262}, 83 {10329124799877583249, 8756876257370047475, 2027304531048772658, 14136513784278359146, 10612935083520178707, 6207950952294049860, 5989834420685599066, 16200344836864102349, 17989931768761686572, 36605130150858281}, 84 {15712638640355571572, 6911732328807606292, 10176318194353482793, 3635851365566106398, 9892567339900120038, 14461612377214612955, 16389615241393274057, 12651838945236028812, 13536083907098569269, 18515749350944921}, 85 {5076827480350464506, 18249575656742683023, 7202276925283013655, 1675474444887786899, 14564549657361301580, 13651349150863069141, 5233748578191063137, 10057693774177509688, 2263095285762743999, 44987482788755588}, 86 {2313434157949960381, 15493925599360292661, 12462877951536944165, 3484089169656765135, 16631132581765223246, 9606226240817426378, 9081464327451896874, 7882188674703192698, 14480525291200472943, 32841521205681759}, 87 {14971360958626235018, 6354257353819984162, 16708799287338381112, 2926594902781714529, 10489049316241960411, 18330102542973983952, 12044258370667954725, 2704306777095480810, 11580584760279813236, 24375418591899070}, 88 {6032389327291386739, 3861083195237077814, 3011703309625364553, 6313989484955116904, 10381012665260180778, 3855632300083161044, 11508306303084133188, 7774069649892635363, 13752428322375589071, 7164666883386632}, 89 {18309283861373580155, 15569853377733268658, 16820330372723914620, 7813464936948997015, 12356527369467981372, 7637946307109476197, 15283013241197161945, 1140793393437432174, 149111516692432071, 15556285163230785}, 90 {12423083707804413657, 2561324669216553892, 3354623821752926293, 11610276741867222767, 10363268849840872219, 5463863190870447699, 14455444601362058804, 2604004256097566119, 13259551450805497295, 56059041820898806}, 91 }, 92 x) 93 } 94 95 func g1Isogeny(p *G1Affine) { 96 97 den := make([]fp.Element, 2) 98 99 g1IsogenyYDenominator(&den[1], &p.X) 100 g1IsogenyXDenominator(&den[0], &p.X) 101 102 g1IsogenyYNumerator(&p.Y, &p.X, &p.Y) 103 g1IsogenyXNumerator(&p.X, &p.X) 104 105 den = fp.BatchInvert(den) 106 107 p.X.Mul(&p.X, &den[0]) 108 p.Y.Mul(&p.Y, &den[1]) 109 } 110 111 // g1SqrtRatio computes the square root of u/v and returns 0 iff u/v was indeed a quadratic residue 112 // if not, we get sqrt(Z * u / v). Recall that Z is non-residue 113 // If v = 0, u/v is meaningless and the output is unspecified, without raising an error. 114 // 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 115 func g1SqrtRatio(z *fp.Element, u *fp.Element, v *fp.Element) uint64 { 116 117 // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-optimized-sqrt_ratio-for-q-5 (mod 8) 118 119 var tv1, tv2 fp.Element 120 tv1.Square(v) // 1. tv1 = v² 121 tv2.Mul(&tv1, v) // 2. tv2 = tv1 * v 122 tv1.Square(&tv1) // 3. tv1 = tv1² 123 tv2.Mul(&tv2, u) // 4. tv2 = tv2 * u 124 tv1.Mul(&tv1, &tv2) // 5. tv1 = tv1 * tv2 125 126 var c1 big.Int 127 // c1 = (q - 5) / 8 = 2561809830520971834851673423317370187208698865113597259441094318876502093964723972342941881295000173427447071280550850682906970629308555147846507041252715387332745928667496467633282424373249 128 c1.SetBytes([]byte{36, 204, 103, 152, 30, 107, 236, 127, 131, 66, 233, 224, 58, 229, 86, 181, 31, 155, 24, 235, 175, 58, 88, 233, 203, 46, 211, 91, 55, 123, 69, 240, 42, 84, 216, 31, 91, 212, 146, 23, 27, 83, 235, 208, 126, 175, 137, 47, 193, 209, 10, 29, 183, 180, 128, 250, 246, 185, 207, 87, 7, 56, 68, 167, 166, 211, 122, 98, 40, 254, 231, 154, 233, 34, 221, 72, 174, 0, 1}) 129 var y1 fp.Element 130 y1.Exp(tv1, &c1) // 6. y1 = tv1ᶜ¹ 131 y1.Mul(&y1, &tv2) // 7. y1 = y1 * tv2 132 // c2 = sqrt(-1) 133 c2 := fp.Element{7899625277197386435, 5217716493391639390, 7472932469883704682, 7632350077606897049, 9296070723299766388, 14353472371414671016, 14644604696869838127, 11421353192299464576, 237964513547175570, 46667570639865841} 134 tv1.Mul(&y1, &c2) // 8. tv1 = y1 * c2 135 tv2.Square(&tv1) // 9. tv2 = tv1² 136 tv2.Mul(&tv2, v) // 10. tv2 = tv2 * v 137 // 11. e1 = tv2 == u 138 y1.Select(int(tv2.NotEqual(u)), &tv1, &y1) // 12. y1 = CMOV(y1, tv1, e1) 139 tv2.Square(&y1) // 13. tv2 = y1² 140 tv2.Mul(&tv2, v) // 14. tv2 = tv2 * v 141 isQNr := tv2.NotEqual(u) // 15. isQR = tv2 == u 142 // c3 = sqrt(Z / c2) 143 y2 := fp.Element{17779787117422825675, 4939796438941267298, 17917495165866445585, 10745325761140663972, 1801762923695319826, 15143865745144854318, 15159144602769454149, 1697730798702809869, 18119907780441139825, 48351383131100009} 144 y2.Mul(&y1, &y2) // 16. y2 = y1 * c3 145 tv1.Mul(&y2, &c2) // 17. tv1 = y2 * c2 146 tv2.Square(&tv1) // 18. tv2 = tv1² 147 tv2.Mul(&tv2, v) // 19. tv2 = tv2 * v 148 var tv3 fp.Element 149 // Z = [11] 150 g1MulByZ(&tv3, u) // 20. tv3 = Z * u 151 // 21. e2 = tv2 == tv3 152 y2.Select(int(tv2.NotEqual(&tv3)), &tv1, &y2) // 22. y2 = CMOV(y2, tv1, e2) 153 z.Select(int(isQNr), &y1, &y2) // 23. y = CMOV(y2, y1, isQR) 154 return isQNr 155 } 156 157 // g1MulByZ multiplies x by [11] and stores the result in z 158 func g1MulByZ(z *fp.Element, x *fp.Element) { 159 160 res := *x 161 162 res.Double(&res) 163 res.Double(&res) 164 res.Add(&res, x) 165 res.Double(&res) 166 res.Add(&res, x) 167 168 *z = res 169 } 170 171 // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-simplified-swu-method 172 // MapToCurve1 implements the SSWU map 173 // No cofactor clearing or isogeny 174 func MapToCurve1(u *fp.Element) G1Affine { 175 176 var sswuIsoCurveCoeffA = fp.Element{12925890271846221020, 6355149021182850637, 12305199997029221454, 3176370205483940054, 1111744716227392272, 1674946515969267914, 9082444721826297409, 17859522351279563418, 11442187008395780520, 4206825732020662} 177 var sswuIsoCurveCoeffB = fp.Element{1447342806075484185, 5642327672839545870, 16783436050687675045, 2630023864181351186, 5909133526915342434, 1057352115267779153, 1923190814798170064, 13280701548970829092, 3305076617946573429, 29606717104036842} 178 179 var tv1 fp.Element 180 tv1.Square(u) // 1. tv1 = u² 181 182 //mul tv1 by Z 183 g1MulByZ(&tv1, &tv1) // 2. tv1 = Z * tv1 184 185 var tv2 fp.Element 186 tv2.Square(&tv1) // 3. tv2 = tv1² 187 tv2.Add(&tv2, &tv1) // 4. tv2 = tv2 + tv1 188 189 var tv3 fp.Element 190 var tv4 fp.Element 191 tv4.SetOne() 192 tv3.Add(&tv2, &tv4) // 5. tv3 = tv2 + 1 193 tv3.Mul(&tv3, &sswuIsoCurveCoeffB) // 6. tv3 = B * tv3 194 195 tv2NZero := g1NotZero(&tv2) 196 197 // tv4 = Z 198 tv4 = fp.Element{6130771042861286320, 11947466704102345269, 5006184736040647654, 10738967583325648129, 6155303802163134778, 6459686480506411032, 14448065740527999419, 1019798761927372322, 5080373183861200608, 66158761009468389} 199 200 tv2.Neg(&tv2) 201 tv4.Select(int(tv2NZero), &tv4, &tv2) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) 202 tv4.Mul(&tv4, &sswuIsoCurveCoeffA) // 8. tv4 = A * tv4 203 204 tv2.Square(&tv3) // 9. tv2 = tv3² 205 206 var tv6 fp.Element 207 tv6.Square(&tv4) // 10. tv6 = tv4² 208 209 var tv5 fp.Element 210 tv5.Mul(&tv6, &sswuIsoCurveCoeffA) // 11. tv5 = A * tv6 211 212 tv2.Add(&tv2, &tv5) // 12. tv2 = tv2 + tv5 213 tv2.Mul(&tv2, &tv3) // 13. tv2 = tv2 * tv3 214 tv6.Mul(&tv6, &tv4) // 14. tv6 = tv6 * tv4 215 216 tv5.Mul(&tv6, &sswuIsoCurveCoeffB) // 15. tv5 = B * tv6 217 tv2.Add(&tv2, &tv5) // 16. tv2 = tv2 + tv5 218 219 var x fp.Element 220 x.Mul(&tv1, &tv3) // 17. x = tv1 * tv3 221 222 var y1 fp.Element 223 gx1NSquare := g1SqrtRatio(&y1, &tv2, &tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) 224 225 var y fp.Element 226 y.Mul(&tv1, u) // 19. y = tv1 * u 227 228 y.Mul(&y, &y1) // 20. y = y * y1 229 230 x.Select(int(gx1NSquare), &tv3, &x) // 21. x = CMOV(x, tv3, is_gx1_square) 231 y.Select(int(gx1NSquare), &y1, &y) // 22. y = CMOV(y, y1, is_gx1_square) 232 233 y1.Neg(&y) 234 y.Select(int(g1Sgn0(u)^g1Sgn0(&y)), &y, &y1) 235 236 // 23. e1 = sgn0(u) == sgn0(y) 237 // 24. y = CMOV(-y, y, e1) 238 239 x.Div(&x, &tv4) // 25. x = x / tv4 240 241 return G1Affine{x, y} 242 } 243 244 func g1EvalPolynomial(z *fp.Element, monic bool, coefficients []fp.Element, x *fp.Element) { 245 dst := coefficients[len(coefficients)-1] 246 247 if monic { 248 dst.Add(&dst, x) 249 } 250 251 for i := len(coefficients) - 2; i >= 0; i-- { 252 dst.Mul(&dst, x) 253 dst.Add(&dst, &coefficients[i]) 254 } 255 256 z.Set(&dst) 257 } 258 259 // g1Sgn0 is an algebraic substitute for the notion of sign in ordered fields 260 // Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign 261 // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-the-sgn0-function 262 // The sign of an element is not obviously related to that of its Montgomery form 263 func g1Sgn0(z *fp.Element) uint64 { 264 265 nonMont := z.Bits() 266 267 // m == 1 268 return nonMont[0] % 2 269 270 } 271 272 // MapToG1 invokes the SSWU map, and guarantees that the result is in g1 273 func MapToG1(u fp.Element) G1Affine { 274 res := MapToCurve1(&u) 275 //this is in an isogenous curve 276 g1Isogeny(&res) 277 res.ClearCofactor(&res) 278 return res 279 } 280 281 // EncodeToG1 hashes a message to a point on the G1 curve using the SSWU map. 282 // It is faster than HashToG1, but the result is not uniformly distributed. Unsuitable as a random oracle. 283 // dst stands for "domain separation tag", a string unique to the construction using the hash function 284 // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap 285 func EncodeToG1(msg, dst []byte) (G1Affine, error) { 286 287 var res G1Affine 288 u, err := fp.Hash(msg, dst, 1) 289 if err != nil { 290 return res, err 291 } 292 293 res = MapToCurve1(&u[0]) 294 295 //this is in an isogenous curve 296 g1Isogeny(&res) 297 res.ClearCofactor(&res) 298 return res, nil 299 } 300 301 // HashToG1 hashes a message to a point on the G1 curve using the SSWU map. 302 // Slower than EncodeToG1, but usable as a random oracle. 303 // dst stands for "domain separation tag", a string unique to the construction using the hash function 304 // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap 305 func HashToG1(msg, dst []byte) (G1Affine, error) { 306 u, err := fp.Hash(msg, dst, 2*1) 307 if err != nil { 308 return G1Affine{}, err 309 } 310 311 Q0 := MapToCurve1(&u[0]) 312 Q1 := MapToCurve1(&u[1]) 313 314 //TODO (perf): Add in E' first, then apply isogeny 315 g1Isogeny(&Q0) 316 g1Isogeny(&Q1) 317 318 var _Q0, _Q1 G1Jac 319 _Q0.FromAffine(&Q0) 320 _Q1.FromAffine(&Q1).AddAssign(&_Q0) 321 322 _Q1.ClearCofactor(&_Q1) 323 324 Q1.FromJacobian(&_Q1) 325 return Q1, nil 326 } 327 328 func g1NotZero(x *fp.Element) uint64 { 329 330 return x[0] | x[1] | x[2] | x[3] | x[4] | x[5] | x[6] | x[7] | x[8] | x[9] 331 332 }