pax_global_header00006660000000000000000000000064144046450530014517gustar00rootroot0000000000000052 comment=7c80df9e61a54045aedb2ccad99d1e636a4b4c90 go-ristretto-1.2.3/000077500000000000000000000000001440464505300141645ustar00rootroot00000000000000go-ristretto-1.2.3/.travis.yml000066400000000000000000000002131440464505300162710ustar00rootroot00000000000000language: go go: - "1.x" - "1.8" - "1.10.x" - "1.11.x" - "1.12.x" - "1.13.x" - "1.14.x" - "1.15.x" - "1.16.x" - master go-ristretto-1.2.3/LICENSE000066400000000000000000000020571440464505300151750ustar00rootroot00000000000000MIT License Copyright (c) 2021 Bas Westerbaan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. go-ristretto-1.2.3/README.md000066400000000000000000000102761440464505300154510ustar00rootroot00000000000000go-ristretto ============ Many cryptographic schemes need a group of prime order. Popular and efficient elliptic curves like (Edwards25519 of `ed25519` fame) are rarely of prime order. There is, however, a convenient method to construct a prime order group from such curves, called [Ristretto](https://ristretto.group) proposed by [Mike Hamburg](https://www.shiftleft.org). This is a pure Go implementation of the group operations on the Ristretto prime-order group built from Edwards25519. Documentation is on [godoc](https://godoc.org/github.com/bwesterb/go-ristretto). Example: El'Gamal encryption ---------------------------- ```go // Generate an El'Gamal keypair var secretKey ristretto.Scalar var publicKey ristretto.Point secretKey.Rand() // generate a new secret key publicKey.ScalarMultBase(&secretKey) // compute public key // El'Gamal encrypt a random curve point p into a ciphertext-pair (c1,c2) var p ristretto.Point var r ristretto.Scalar var c1 ristretto.Point var c2 ristretto.Point p.Rand() r.Rand() c2.ScalarMultBase(&r) c1.PublicScalarMult(&publicKey, &r) c1.Add(&c1, &p) // Decrypt (c1,c2) back to p var blinding, p2 ristretto.Point blinding.ScalarMult(&c2, &secretKey) p2.Sub(&c1, &blinding) fmt.Printf("%v", bytes.Equal(p.Bytes(), p2.Bytes())) // Output: // true ``` Compatibility with `ristretto255` RFC draft ------------------------------------------- An [RFC has been proposed](https://datatracker.ietf.org/doc/draft-hdevalence-cfrg-ristretto/) to standardise Ristretto over Ed25519. This RFC is compatible with `go-ristretto`. There is one caveat: one should use `Point.DeriveDalek` instead of `Point.Derive` to derive a point from a string. References ---------- The curve and Ristretto implementation is based on the unpublished [PandA](https://link.springer.com/chapter/10.1007/978-3-319-04873-4_14) library by [Chuengsatiansup](https://perso.ens-lyon.fr/chitchanok.chuengsatiansup/), [Ribarski](http://panceribarski.com) and [Schwabe](https://cryptojedi.org/peter/index.shtml), see [cref/cref.c](cref/cref.c). The old generic radix 25.5 field operations borrow from [Adam Langley](https://www.imperialviolet.org)'s [ed25519](http://github.com/agl/ed25519). The amd64 optimized field arithmetic are from George Tankersley's [ed25519 patch](https://go-review.googlesource.com/c/crypto/+/71950), which in turn is based on SUPERCOP's [`amd64-51-30k`](https://github.com/floodyberry/supercop/tree/master/crypto_sign/ed25519/amd64-51-30k) by Bernstein, Duif, Lange, Schwabe and Yang. The new generic radix 51 field operations are also based on `amd64-51-30k`. The variable-time scalar multiplication code is based on that of [curve25519-dalek](https://github.com/dalek-cryptography/curve25519-dalek). The Lizard encoding was proposed by [Bram Westerbaan](https://bram.westerbaan.name/). The quick RistrettoElligator inversion for it is joint work with [Bram Westerbaan](https://bram.westerbaan.name/) and [Mike Hamburg](https://www.shiftleft.org). ### other platforms * [Rust](https://github.com/dalek-cryptography/curve25519-dalek) * [Javascript](https://github.com/jedisct1/wasm-crypto) * [C (part of `libsodium`)](https://libsodium.gitbook.io/doc/advanced/point-arithmetic/ristretto) Changes ------- ### 1.2.3 (16-03-2023) - Panic when reading randomness fails. ### 1.2.2 (29-07-2022) - Add Point.ConditionalSet() and Scalar.ConditionalSet(). ### 1.2.1 (08-11-2021) - Add Scalar.SetUint64(). ### 1.2.0 (17-02-2021) - Add Point.Double(). See issue #21. - To align more closely with the RFC, Point.SetBytes() and Point.UnmarshalBinary() will now reject points with non-canonical encodings. See #20. ### 1.1.1 (24-09-2019) - Only use bits.Add64 from Go 1.13 onwards to make sure we're constant-time on non-amd64 platforms. Thanks @Yawning; see issue #17. ### 1.1.0 (13-05-2019) - Add support for the Lizard 16-bytes-to-point-injection. See `ristretto.Point.`{`SetLizard()`, `Lizard()`,`LizardInto()`}. - Add `Scalar.DeriveShort()` to derive a half-length scalar. (Warning: half-length scalars are unsafe in almost every application.) - (internal) Add `ExtendedPoint.RistrettoElligator2Inverse()` to compute all preimages of a given point up-to Ristretto equivalence of `CompletedPoint.SetRistrettoElligator2()`. go-ristretto-1.2.3/cref/000077500000000000000000000000001440464505300151035ustar00rootroot00000000000000go-ristretto-1.2.3/cref/base_multiples.data000066400000000000000000002271251440464505300207570ustar00rootroot00000000000000{{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-14297830, -7645148, 16144683, -16471763, 27570974, -2696100, -26142465, 8378389, 20764389, 8758491}}, {{-26843541, -6710886, 13421773, -13421773, 26843546, 6710886, -13421773, 13421773, -26843546, -6710886}}}, {{{4443662, -9940086, 9171065, 2666173, 2111033, 3401644, -31605108, 9275297, 13235616, 14331105}}, {{-17259575, -3036261, -30752308, 9118147, -27466691, -6152361, 19887205, -13089868, -13594061, 9012024}}}, {{{-466321, 9574389, 17880460, 13372178, 26021472, 14338106, -27837921, -1498113, 10627369, -6374799}}, {{16102612, 14291486, 6324312, 12269856, -25404496, 2531064, -11483344, -13274075, 18317031, 4824775}}}, {{{13236336, 11113969, -22484697, 826993, 6934139, 3481849, -18195395, 2674789, 28667135, 8451747}}, {{-30273214, 2807923, 33430503, -6860424, 20170913, 13988204, -10730816, 12331234, -25382567, -14728287}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{10847451, -37118, 24323953, -2358452, -5444838, 5164948, -15290756, 3590225, 33127799, -6485115}}, {{3652020, -2692481, 9593798, -1896201, -33169164, 9106320, -21527373, 7286230, 826967, 8866840}}}, {{{2685432, 9853787, 7244598, -6341127, 2448949, 2399377, 18188932, -10627300, 6454868, 9343512}}, {{23537662, 11193840, -8062193, -233411, -20862904, 11366009, 497437, 7230451, -14145540, -4040100}}}, {{{8940436, -931910, 2216655, -16607923, 25443172, -13796962, -12136885, 56339, -24611372, -4038275}}, {{24869380, 9507835, 27335926, 9455120, -8487096, 2134990, 18474949, -13554247, 20744060, -8308626}}}, {{{-8499418, -11518554, -27293188, 8899523, -6812474, -13019522, 19598982, -10538832, -24021982, 15154610}}, {{-33107332, -11643953, 466726, -12950430, -19904488, 16288633, -11930016, -3313828, 15602381, -15674716}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{3974155, 6194156, -19980758, -1354033, -18636516, -14845527, 21527748, -14519394, -33505405, 1567121}}, {{-2488026, -5936186, -13803653, 15954025, -26753975, -5723571, -29147976, 331359, -22048160, 16017020}}}, {{{13622663, 9590524, -12055628, -14601956, -30798357, 13798328, 24469389, -2030464, -15034442, 14579451}}, {{4949756, 3799938, 10764212, 630858, 9226631, 5610492, -3364444, -12972929, -33547030, 10727040}}}, {{{-22283174, -8649257, -33076527, -12516302, 17971501, 7223924, -6719359, -16256014, 11440977, -4621221}}, {{18635055, -15919271, -25583307, -1342239, -15422778, 765833, -28318800, 16437671, -7428101, -2214506}}}, {{{12756329, 3094339, -17980393, -2249973, -11348508, 9458762, 15065235, -6816547, -19602977, -8783840}}, {{-26413369, -16249770, -13303357, 14027071, 32795894, -2939378, -17443519, 5188991, 29695760, 4019669}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-20106230, 5033761, 3820161, 14254539, 8896502, 7394342, 16578429, 9332326, 1785096, 12301054}}, {{9147387, -12723968, 956180, 4345655, 18953525, 10557878, 23911328, 5212198, -19262600, -11318415}}}, {{{-11916421, 7468375, 2339370, 2251095, -17578721, 13349755, -29467804, -6245866, 19898176, -5487383}}, {{-14171843, -11479427, -19353069, -5788723, 10851928, -11428858, 7146499, -3201577, -15362408, 7056390}}}, {{{-28768728, 9380526, 427517, -11134815, 11714395, 6667582, 27717904, -170135, -19123030, -8327533}}, {{15095996, 9086320, -11317211, 3577756, -17751304, 4637965, -26593936, -6610442, -20756435, 8351421}}}, {{{18028535, 11484911, -26690150, -11958098, -32372032, 12986430, 16419070, 7435944, 19357997, 15756189}}, {{-15649202, 354434, 22579748, 5969433, -23462534, -12191472, -16206269, 11523825, 4169086, 1339975}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{31381245, 4198026, 23797847, -2744010, -27343257, 36400, 19370825, -9896598, -28788590, -766207}}, {{5972200, 2107808, 20476580, 3962111, -25658758, -3356805, 13809211, -16559554, -21839845, -10050085}}}, {{{28428766, 8750092, 21137077, -5919069, -11942391, -6660789, -32298608, -5120856, -527559, 6248104}}, {{16166812, 3496233, 27507714, -1431683, -21885077, 15771771, 33325966, -1210248, 8207220, -3405686}}}, {{{-11985564, -14922811, -32445122, 10449431, -4747344, -4228265, -23607713, -15487120, -9900349, 2211006}}, {{23065909, -12860077, 7006688, -8107600, -29003856, -3480873, 24597121, -7070326, 16988404, -3518102}}}, {{{15158154, 11972366, 3192344, -9440681, -13758191, -13800671, -3274528, -2459685, -24381964, 2007794}}, {{-30897900, 10361481, 16803125, 1878950, -17338120, 11014920, 26644561, 5112598, 4698068, -3594401}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-13435115, -14362869, -16972213, 5821091, 26575054, -6002733, -27126943, -10230123, -11888006, -9617560}}, {{-5206695, 13210893, -8655605, 1533486, 23655399, -7421641, 13968276, -8451255, -30390640, -16535739}}}, {{{1156472, -10886495, 10105812, -6040766, -24215675, 511317, -32523035, 157163, -30481177, -8937493}}, {{5565494, -8834114, 33479665, 4489451, -16538896, -12374637, -11220682, -4106894, -29236797, 11697294}}}, {{{19846823, 16069429, 15166297, 1718221, 11449460, 9449780, 17048320, 1606288, -29423154, 12914008}}, {{14538355, 11876766, 256068, -11169848, -28604018, -15019686, 11141212, 14170405, 5744383, -6980365}}}, {{{-19902662, -16487331, -24992541, -783803, 13328850, 1167829, -13520876, 10937927, -33439429, -2913057}}, {{21898737, -6691452, -27769955, 14095006, -20202985, 15948192, -172323, -10539558, 2832974, 2200124}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{15897671, -3025639, 21496039, 5624068, 16735573, -14304697, -27784686, -16073466, 18807403, -5652747}}, {{-32057743, 8498334, 10399549, -879074, -7912058, -8884050, 559887, -8032353, 19527008, 6019041}}}, {{{-23423436, -13094530, 29655139, 16083552, 9290346, 15839894, 23187095, 11178854, 9299770, 9501382}}, {{-11738378, -1272120, 32813142, 2130958, -24416324, 11674829, 29164991, 5963837, 9772869, 14541990}}}, {{{-15540620, -5383619, 18733165, -5501213, -22125225, -10278694, 10503607, -5402963, -1923635, 10874058}}, {{2280450, -3779747, -21276671, -11367498, 2792105, 13903455, 2381790, -8368143, 16654124, 5732263}}}, {{{10139117, -563549, 15728261, -12937526, -23750857, 15540786, 2994643, -4871856, -18088235, 1756456}}, {{9135352, -4561896, -13703012, -7229378, -2800887, 4775782, 5577638, -830099, 10482658, 1999434}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{27021200, 5419014, 23018886, 11900765, 26906224, -2829985, -28746633, -10791580, 32865695, -14636749}}, {{-28397474, 5162076, -5417046, -14078168, 16532863, 5345944, -30416118, 16056680, 3677231, -3258503}}}, {{{-6320324, 13093517, 17950312, -1507333, -16929331, -8532887, 26359306, 9025929, 32497874, 15644187}}, {{25252217, 14481152, -9577462, -309419, -32485007, 4951380, 13619168, -11434639, -13653908, 12029752}}}, {{{-30803706, -15763753, 26569297, 15401822, 3746526, -7249098, 4902999, -3067146, -3678987, 10613653}}, {{26765614, -13667905, -10749606, 15462949, 28714794, 12724159, 2320124, -15293088, 10188006, 12035110}}}, {{{-9060761, -13893261, 14481131, -1944527, 10435688, 2282566, 568651, -6063427, 31217439, -15286495}}, {{-8946861, 2593366, 29648688, -15705073, 32206653, -4713425, 13682604, -7412793, -368448, -5230037}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{13908599, 3394038, -5352387, 7269973, 31943256, -12429587, -27021301, 314724, 22458211, 2870686}}, {{-6027067, 7293899, 12931110, 468405, 16214596, 9875634, -18266777, 7761426, 16782157, 8667702}}}, {{{-18412237, -4074513, -4369988, 11939076, -6896953, -10806440, -32922885, -9745277, 22005199, 11393029}}, {{-4060139, -7494228, -23312032, -10792701, 25853644, -6107433, -32993248, 6031079, -6881580, -581524}}}, {{{1161707, 9424314, -6727640, 4689567, 20771983, -6456495, 7498823, 10384724, 19996000, -15411422}}, {{14038644, -1055742, 26406741, 11280507, 14464207, 8415945, 17112776, -14928556, -31741876, -5802790}}}, {{{6019966, -14372441, 11920504, -3953210, -10753780, -7043913, 4836402, -5828855, -12481603, -6328563}}, {{20640662, -1305214, -3526770, 4311257, 3352489, 8036901, -28740635, 6687552, 33052826, 14749119}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{21267577, -12947642, 30939275, -12238509, -11202961, 6234738, -196370, 16193148, -28269388, 10987795}}, {{-11497448, -11020052, -4443180, 16562629, 12759472, -9784762, 27650189, -11430021, 9089774, -5120661}}}, {{{28294699, 13359976, 7468577, 6932231, 7144495, -16313014, 7223290, 6020407, 1313339, 7935640}}, {{31066742, -4076765, 9417000, 8527208, 18827705, -1668405, 26348867, -5498274, -28885504, 3787831}}}, {{{23816208, 14706396, -24697046, 2010568, 15625411, 15770492, -15678872, -6883333, 5322869, -11101003}}, {{11732061, -10139120, 26240518, -56585, 31979992, 1940774, -24811877, 8690243, 24582001, 1076779}}}, {{{-20343952, -10212688, -25201798, -14318604, 17915490, -5160638, 31520088, 2090072, -31673242, -8011258}}, {{-21396979, -13416320, 26418873, -9203088, -2021856, -2124382, 14587592, 11501764, -19845503, 14899790}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{22149028, 10451958, 19030056, -13369913, 26238247, 8618017, 2503062, 2826540, -6850263, -14429883}}, {{-14494368, -3423711, 19387200, 13910891, 21589919, -14012122, 7292147, 5689869, 20698530, 12930583}}}, {{{31248107, 9621310, 31818676, -2756175, -17614862, -13567523, -8192033, 15850649, 14648865, -1746303}}, {{-17373291, 10556655, -1665951, -11200024, -5710202, -6965538, -15942566, -1399857, -858253, -8672506}}}, {{{24043907, -7552534, 25161832, -7538458, -14232945, -6879262, -7209856, -5760558, 28697328, 11865179}}, {{-16631603, 13688958, 31724656, 5363722, 12902418, -3665978, -168976, -7868154, 4677840, -3598693}}}, {{{-21230386, -1709797, 31830627, 8623859, 11542640, 3309583, 32117684, -15156299, -19843562, -13338554}}, {{13220141, -7881020, 24157834, -2427822, 17801518, -16740468, -24532389, 11979673, -28715805, -4913808}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{1211688, 8724626, -24749656, -6944161, -30365306, 16311021, 30024338, 16496604, 27753094, -13799751}}, {{10123230, 15611784, 32774948, -13902752, -19219665, 6767341, -19780601, 2372367, -32819129, -3255844}}}, {{{6946015, 13617354, 8879883, 15702457, 28085076, 11049168, -8394826, -1934303, 13376414, 13565604}}, {{-19234324, -10447891, 19933300, 956296, -2968644, -16679634, -16779131, -10701835, 28717693, -11615101}}}, {{{31982202, -15914389, 2276891, 7224660, -5615075, 5039990, 8847946, 3993837, 3213589, -10814692}}, {{8846149, -6632197, 17132070, -8165418, -12977890, -9368570, -13936006, -15098987, 17256568, -5584009}}}, {{{12185561, 559856, -32627775, 14790044, -28834326, 16161349, 13282392, -6270088, -12074273, -15653723}}, {{-31628712, -16072756, 11830308, 6319065, -990122, -5931888, 26382143, -8730444, 6077403, -2236037}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{21156816, -16775301, -8027480, 9702333, 1787343, 8373461, -20357686, 11101574, -22113100, 11382309}}, {{25693413, 9654833, 19481021, -16035178, 31172070, 5408243, 9833902, -484644, 14737793, -232487}}}, {{{-30538572, 13103825, -9821659, -11182012, 21657851, -4016288, -28955727, 12786353, -8404582, 7226839}}, {{13265128, 930321, 21657991, 6400400, 3878219, 15189495, -29188362, 16534298, 33551473, 6079126}}}, {{{29929187, 6118512, 2547718, -3640606, -25047191, 3577800, -8835658, -6206306, 30533780, 14561572}}, {{28370527, 9087344, 27328816, 11854797, -16259111, -13009704, 15026624, 16247458, -23584336, -9284187}}}, {{{-22614393, 11577238, 4491987, 12741674, 25196742, 8750925, 19093250, -925918, -9961912, 318580}}, {{28724358, -12947151, 21565614, 13460178, -2028417, 15620963, -15100596, 3788594, 25383014, -3724449}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-22097019, -10227030, 30349722, -12949300, -5988533, -15319899, 12599854, -10905057, 32285159, -7408228}}, {{-30773637, -3005963, 20534336, 14952623, 14988143, 11112722, 10999056, -12403067, -13673176, 1147697}}}, {{{-12119835, -14401905, 22455840, 8041343, -23315474, -5060548, 29163904, -11373946, 23986227, 4042986}}, {{23552858, 1173240, -14216209, -13320860, 21330038, 4334830, 19246196, 13541489, -30907528, 16071264}}}, {{{9336146, -9027603, -18416932, -2396949, 25384693, -6658680, -30136995, -5442479, 24269182, -8770542}}, {{6176974, -10189393, 30939265, 7635858, -30720340, -4591634, 33299863, -4764824, 19070643, -9746615}}}, {{{-22301632, -5772422, -26653399, -11185034, 8530548, -7578346, -17080694, -5990236, 29534476, 15486748}}, {{18275412, -9468413, -28562297, -8650733, -23340009, 9425731, 1260695, 16144245, -5561215, 5383210}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-7821280, -5233543, 15816558, 1739793, -22764854, -5837948, 9152213, 689227, 11818240, 6368547}}, {{-18383821, 9662090, -24477754, -14934056, 26863256, -8327309, 6370322, 7682988, -6275645, 16483202}}}, {{{-15508409, 3731519, -16087697, -4925165, -28443130, 3941789, 13333737, 10552516, 18439903, -9956680}}, {{-20584244, 13100485, -24649776, -9526067, 23415781, 10912348, 4143864, -6709859, 9572747, -6448740}}}, {{{19480755, 455412, -17591359, -2241890, -28040763, -11003373, 21053272, 2746474, 20923281, 1349738}}, {{27477121, -1320642, -1069635, 2449655, 24965032, -14358373, -9271473, -12851258, 17649531, -1850939}}}, {{{-29841327, 9803249, 5649224, -11391033, 24977479, -11221993, 19852820, -7849035, -6808068, -11814577}}, {{27783638, 9956571, -29782542, 2928069, 26276732, -10405545, 4609705, -2551961, -1884146, -343417}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-31644616, -7857693, -14849954, 5791594, -25879754, 1993567, -24555886, 12157761, -7789344, -12550267}}, {{18673230, -12289628, -11882024, -13391679, 32323262, -9589233, 4285763, -15498197, -19997182, 12451980}}}, {{{17447784, -10844338, -31487261, 14328608, -6066969, 16737373, 27755728, 415463, -2537066, 11930196}}, {{5961252, -15369135, -6464666, 779300, -553296, 12658634, -1090387, -5108918, -22643602, 15346111}}}, {{{25645688, 5826034, -1401930, -7354869, -22898660, 8554660, 13854186, 3816355, 24152177, 11066672}}, {{15928500, -13217598, 15754181, 5541629, 18720503, -1959027, 14329693, -6918436, 14694706, -9777793}}}, {{{31775280, 5505240, -15920779, 15046521, -24580592, 10720581, 15408514, 14016531, 2520103, -10873356}}, {{17724110, -9658102, -3622320, -9948482, -4768256, 1699790, 9100907, -15053681, -26079694, 2969834}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{17104229, -1671439, 27229469, 1709836, -10061892, 16207263, -32020544, -14109830, -3692611, -11886369}}, {{-29290071, -6008349, -10791200, 9116324, 1365075, 11111558, -17227877, 4835985, 1596809, -12363496}}}, {{{-17576621, 7966754, -19748793, 13774431, 18292864, 6894155, 5757058, -8853308, -23743945, 16565178}}, {{4686723, 1406704, -15764223, 2599785, 3178856, 6327370, -33040553, -3495251, 20045139, -16447291}}}, {{{-7799587, 10364315, -7311007, 359911, 33437401, -3033873, -28219872, 5789999, -22018727, -12648593}}, {{17177766, 10049931, -15534976, -13105175, -5239120, -4210225, 25820188, -6507350, 22709153, -6029595}}}, {{{7202532, -11788468, 15669319, -10491956, -18936470, -13707162, -16362780, -12428391, 5569899, 3862755}}, {{-25805598, 16551458, -16595569, -14177172, -9476009, 10519847, 26144427, 2078332, 27209460, 1232519}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-32618021, 8656442, -21280177, -11420690, 31622394, 1886158, -17985134, -5136528, -26014263, 15586726}}, {{-26350935, -15202938, -13571041, 5530145, -1246675, 23, -3189974, -12976652, -12268242, 13844678}}}, {{{322468, 6546217, 11707630, 5941996, 10001093, -9785656, 17879359, -10020391, 22872315, 109743}}, {{17590264, 10915516, 31924541, -1997169, -20518705, 2606443, 2768772, 13985712, 2597215, -3551997}}}, {{{-25012604, -2358098, -4317456, 11356894, 23428887, -5013569, 8458539, 15378585, 25782520, 5617042}}, {{-22377533, -9307384, -29101579, 3026981, -24674344, -8314931, -3274885, -8619125, 32010348, -5206024}}}, {{{-27579432, 4733574, 32316030, 8576372, 6580903, -313688, -20698218, 14332432, -7483590, 8206885}}, {{-2483745, 1101543, 6669353, -9311639, -904221, -9132322, -10145124, -3988642, -17413639, -9819086}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{12761381, -9560900, 28934851, -13927964, 18600885, -10482642, -29200120, -13555033, -11422906, 2357816}}, {{9677816, 15634735, 19492515, 10912634, -18248519, 15592118, -26965479, -2573549, -25096371, 10281858}}}, {{{-15459212, 5846311, -20230612, 7969038, -18203683, -6666074, 5078372, -5482850, 12971819, 6852623}}, {{16611080, 15625209, 7981856, 16375443, 3180340, -5946195, 12605004, -7118782, 14204497, -2234385}}}, {{{26918440, 9318019, -21937138, 10145272, -2433562, -13104021, -30405356, -9998113, -33552981, -751813}}, {{18135679, -8078671, 7357908, 5561971, -5212259, 5320434, 15235598, -5750099, 14940730, -9197828}}}, {{{32771575, 818095, -27689566, 10841137, 14565567, -16006350, -20187590, -8375151, -1878174, -3705384}}, {{-7822319, 5558184, 223085, 14538687, -33211722, 6075744, -13377705, -3766543, 5447801, 15047977}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{5795984, -3702584, -8841651, -7460155, 19445679, 9208542, 682361, -3396073, 12412725, 12596652}}, {{5635220, -14028841, -31696967, -11765152, -1415688, -4412460, -32128540, -14577695, -3132366, -16570339}}}, {{{12503308, 6309283, -16854329, -7978303, -15995551, 13780228, 24132393, -8059699, -22701946, -16166550}}, {{3061018, 12933579, 19955571, 13662451, -20666533, 11722849, -11455267, 1554356, 14406094, -4091877}}}, {{{26016340, -1842568, 31766789, 11205500, -27821087, 7679854, -30993013, -3088471, -6877545, -369191}}, {{7037463, 2041925, -15872198, -9622441, -11907534, -12260288, 13154119, -3018368, 585759, 3806931}}}, {{{24132117, -3901168, 13993067, -874521, 9133878, 10450635, 30435088, -9818418, -29390268, -5224052}}, {{-23330689, 1819466, 2576361, 11939688, 20741826, -10354008, -22526700, 5337938, 15851765, 6611207}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-2855672, -2473012, 2617570, -5704917, -18213679, -5492733, 24190611, -13001172, -17030721, -10679892}}, {{3022663, -13503381, 12995137, -6709869, 22073478, 15561207, -8398845, -11670731, 3126505, -5433664}}}, {{{-16037643, -12013247, -27193328, -7759885, 30550663, -12599953, -18351549, 3533855, 6547428, 8481421}}, {{8861098, -2516783, -22159597, -1040285, -16957227, -2987628, 11174598, 8148947, -24197611, 13118500}}}, {{{-29028154, -6923711, 10171110, -13705277, -15502847, -12819754, -20401417, 2816566, -31807160, -6033241}}, {{-8538640, 4740779, -17339800, 8940489, 3158691, -16152544, -17546635, -11738587, -29251400, -8944264}}}, {{{33483338, 610009, 12082237, -712682, 11283043, 10207585, -11965711, -1068067, 8666274, -10178002}}, {{16823795, -2372985, 32558902, 10147121, -21234874, 14413371, -27316034, -2154448, 26068272, -16085685}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-15487198, 5107534, 12621198, -14327014, 9942495, 1433656, -25152940, 2767298, 16501392, 1077260}}, {{-8324708, 13628354, 12385590, -11408862, -7100943, -10593257, -18641357, -9479984, -27335616, -3597863}}}, {{{15573525, 14345213, -21141567, -612142, 123758, 10521238, 28338138, -12928375, 9171680, -7828746}}, {{-18590957, -4287007, 23122404, 4576385, 22037208, 1801295, 32339603, 310189, 3056877, 825069}}}, {{{5248612, -6851233, -16968897, -2985068, 31141260, -1962891, -20362183, -1523877, 31913422, -5987720}}, {{23505933, 10678491, 5677783, 6319367, -29715724, 15887385, 24018158, 10793161, 25997641, 3936363}}}, {{{-2382441, 11176803, -29285848, 13491360, 20582427, -6248431, -2943597, 9999820, -21199669, 585503}}, {{-14038527, -12290108, 28958129, 7955216, 1303854, -9304343, 1055631, -10315478, -25977137, -13324705}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{20566396, -7536913, -6416232, 12027771, -27266655, 7522376, 22161883, 9745153, 16192379, -4898405}}, {{-31874006, 13747285, 19622806, -6221451, -1751037, 12064856, 32615775, 16322677, 25338024, -11342285}}}, {{{26436284, 16396193, -33437362, 10579374, -11622078, 10349235, -6440143, -5650815, 28083971, -5400490}}, {{13276869, -7960398, -29561858, 1643266, -13005790, 4469434, 27078316, 10525843, -17592579, 6780208}}}, {{{18334304, -10868643, 7919738, -3728864, 18760742, 14946111, -16962487, 8651760, -3807863, -4454297}}, {{30987827, 15324452, -24550370, -7876558, 5357345, -9149168, 16262922, -408371, 17778957, -7134441}}}, {{{-28270023, 6064385, 27909662, 4631705, 14859164, 10819831, 6363673, -12741410, -28854756, -3755418}}, {{24432421, 6981333, 534293, 11316906, 24670894, 8274364, 31397898, 12488994, 167614, 15358731}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{4552491, 10328571, -579194, -10907345, 5480238, 15614817, -4665891, 11082334, 10599350, 8940622}}, {{830871, 9866758, -13428201, -8274437, 25320767, -6573280, -33260724, -8391538, 23047040, -1751350}}}, {{{-12624856, 12983031, 10103687, 3076416, -19610294, -5638468, -7053449, 11523690, 22918816, 7367734}}, {{-20724248, 7602855, -20912186, 5637234, -13974134, -14807337, 5633999, -6854221, -28442537, -10553992}}}, {{{-30989857, -13992076, 24916435, 3605069, -22903655, -6708851, -23864817, -13040210, -9051388, -4517559}}, {{-752215, 12938298, -24940410, 13111505, 4109551, 15363139, 20907935, -7504965, 21424117, 4128175}}}, {{{-25387174, 5299990, 30892946, -14552174, -25001298, -2575136, 6200644, -15128299, -19730692, -12709441}}, {{-1037011, -16081017, 22363918, 13600523, -26632570, 13243349, 18079077, -4967086, 13493510, 2660611}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-17678689, 15967277, 6802587, -5128472, 31048017, -9849564, 30440962, 11947653, 26001632, 8235135}}, {{23092780, 2201114, -27810252, 14772042, -18213047, 11035713, -33063878, -13289884, 126599, -2202223}}}, {{{21967487, 14102271, 13406647, 16484947, -21590556, 13957518, 3401718, -12533938, -17374987, -4445665}}, {{7223001, 4793115, 14142465, 15885969, 25110621, 8899613, 28647796, 5224825, 1265753, -5406642}}}, {{{-3336716, -5520764, -5624470, -9035608, 30545997, -10040508, -28386506, -7976241, 13166811, 15086130}}, {{-25929251, -8666041, -7913746, -3081765, 17105808, -614877, -3075863, 5027256, 10852020, -59486}}}, {{{7996772, 12898977, 30809816, 10181843, -9909843, 7697626, -21865118, -6224024, -17538802, 8274720}}, {{-29741170, 6844980, -28964977, -5160415, -524556, 9945333, 31581784, -11063486, 12468586, -7548621}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{30625306, -7552437, -4081086, -14206474, 188076, 11397259, -28918443, 3482887, -25405112, -14765812}}, {{-8746716, 2551140, 8419422, -5704061, -3224940, 1763701, -18481525, 1932611, 18044609, 10656519}}}, {{{3790284, -9885313, 29533782, -5816114, 25194669, -16384879, 7231957, 1606960, -7313518, 9145089}}, {{31566030, 1432610, -20477309, 9703536, -27649004, 14891271, -20260356, -1778947, 21340316, -7572506}}}, {{{-30569429, 10560231, 29321950, -4458123, -8076301, -4552394, -13183961, 1143194, -23220733, 6046817}}, {{22717996, -9378599, 31737399, 8370074, -15948884, 13560701, -13371837, 10923471, -21133388, -7076278}}}, {{{10147133, 5086425, -15672618, 5372437, -2678842, 10266691, 15619113, -12065633, 28985877, 6917025}}, {{13155781, 12809541, 13941821, 4754463, 22311936, -8498813, 12615739, 12261751, 26877532, 8238175}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{31783402, -2836358, 27470376, 15650536, -31668658, -2815708, 13202882, 7196353, -30666866, 14341531}}, {{20560698, -4158277, -15775619, -14933854, 24856852, -8856172, 27667141, 10236878, 17052654, 7305515}}}, {{{-7346254, 15821049, -12726695, 16761356, -15362117, 2586438, 28073630, 10243770, -27544400, 4137934}}, {{9665316, -13062835, 1681679, 12357725, -3086950, -10624335, -22170339, -3210519, 1646002, 6022258}}}, {{{-19800298, -4557481, -26039542, 4885245, -14374132, -12036651, 22139453, -11773834, -18970421, 7136543}}, {{27187782, 7966356, 28800218, -1031206, -3189197, 16252224, 26656802, 16386410, -10742136, 2088803}}}, {{{-28962553, 7646704, -20194854, 2014484, -33057936, 3995227, -21145745, 10912820, -12935318, -8243318}}, {{-26131206, -4845442, -18715879, 8136538, -9232808, -8738359, 9951554, -16558554, 18086286, 15517504}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-30091903, 15253574, -24486574, -4415643, 11814407, 11925848, -14166779, 13100511, 27474931, 2312093}}, {{-29176019, -1215700, -8878289, -13204773, -12542619, -15568554, -31538097, -12042924, 20254471, -14715314}}}, {{{22137199, -9795813, -912193, -8974174, -683462, 5169325, -27200879, -12499656, -32892441, 2932526}}, {{-13485585, 5318781, -15173443, 3977180, 13685969, -2218520, -10853558, 7392687, -24208287, -7600426}}}, {{{5413426, -13212199, 32121092, -11212493, 17616463, 15300602, 3067313, -14848349, 16285560, -13184762}}, {{-24991706, -12256688, 20987254, 7263870, -14830625, 2022523, -22584265, -11531189, 6342543, -12254490}}}, {{{30649895, -14429437, -7357113, 8148778, -10335889, -4975055, 33536722, -6748931, -18078010, 2917812}}, {{-15549738, -1406315, -16566865, -9153876, -16114303, -13069969, -21159991, 3269785, -15864747, -10960561}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-27984382, -9271803, 7148720, 10710298, -23746392, -1625457, -9328718, -9975655, 24946235, 16634392}}, {{29451294, 16192671, -7066814, 13595253, 20114594, -5657362, 5325966, 9398055, -26992388, 4175400}}}, {{{9190643, 8659168, -7731471, -66139, 9428529, 16766471, -21610160, 12355439, -26326085, 2343236}}, {{7728738, 9233554, -21643618, 854993, 13280536, 11962374, 10134427, 11032215, 9373544, 14827521}}}, {{{-6482607, 7628145, -5466265, 788653, -19185245, 8203429, 1868079, 8879104, 31239370, 4231684}}, {{-448006, 9549390, -3270229, -337296, -28885353, 15658997, -1567547, 4503709, -9439063, -14183439}}}, {{{12124349, -15900863, 24780160, 9539624, 9577961, -2011019, -12517070, -7291662, 4550433, 9833693}}, {{-3235422, 11966515, 19120194, 1659337, 31436508, -3544512, -18180586, 15044560, -10836, -7649516}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-6780899, 8328087, 12625032, -9348473, -10140069, -5082516, 4989210, -12445843, 30984102, 1495070}}, {{-6332113, 13625910, 19009936, 8336515, -24277173, -8497947, -32918285, -11865596, -31113573, 9217293}}}, {{{-17294088, -7635133, -31539536, -10875924, -17041338, -11152998, 6264981, 11375352, 32293725, -5806547}}, {{27217550, -14647799, -22952533, 14420647, -12957030, 9431372, 6626706, 13985948, 8372195, 16292690}}}, {{{27038479, 7797188, 7388702, -4675262, 10451829, -12669473, 32516005, -13623605, 5488982, 4782814}}, {{13434869, 12889404, 10038240, 12119644, -13438080, -5676540, 22235718, 16343829, -26961710, 1856607}}}, {{{30717676, -2443993, 25226774, -1249151, -7162809, 7353127, -32621495, 963567, -6339226, -7691615}}, {{22396731, -14493619, -10677527, 4590250, -27790097, 6295850, 15044427, 7885730, 6404256, 16062299}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-28307823, 12809005, -9554739, -1086957, -4017473, -6155523, 7153440, 8282685, -31437294, -13078514}}, {{-14962213, -10986276, -6183704, 16329684, 12335565, 2422419, -28825620, -11774890, 26615553, -5675997}}}, {{{5582210, 2329598, 21455646, -7260433, -272570, -1656602, -14415766, -1619671, -21735958, -23998}}, {{-9865517, 3038925, 14536200, 15423821, -30050493, 4865730, 30972917, 10510400, 30576403, 4981758}}}, {{{-32318579, 14721717, 31703904, 14835661, 32684794, -13986588, -13543022, 8371441, -2516318, -5225297}}, {{14001805, 3352427, 7335597, 15358574, 4648371, -1744806, 26459871, 11967313, -26198167, 16665233}}}, {{{-4860382, 11526406, -24872574, 10943057, -24710972, 11234989, 25734141, 12908138, -13336674, 7917841}}, {{10943609, 869101, 4831524, -11656159, -30953341, 6732437, -2317269, -2535439, -27340702, 10839383}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{32891241, 2815356, 20301173, 11960220, 19909245, -15156175, -13794475, -15976808, 29387568, -13455866}}, {{24537119, 13501824, -17899035, 7552149, -30561767, -15931162, -23291012, -211337, 25941485, 8143852}}}, {{{-15863658, 13958105, -13797715, 16153632, -26441709, -2094547, -27005869, 13923508, 17626879, -941650}}, {{-2681549, 7685792, -15168764, 6784297, -613937, -3073797, 21416066, 9730634, -22340294, 15480}}}, {{{8603871, -34460, -13283192, 13374560, 27316369, -14476209, 12117613, -946180, 978715, -2194728}}, {{-10413304, 2575870, 20864640, 678779, 18114068, 163661, -8211138, 2354569, -24296952, -3629756}}}, {{{31799852, -8946389, 9150182, -16065110, 25044621, -3521130, 9490983, 10178067, -27653044, 2864084}}, {{18966535, 146009, 21840244, 372178, 7291582, -11799099, -22009798, 2960934, -32767770, 6603009}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-11045405, -15254833, 19532483, -3816834, -2978693, 11138476, 21629584, -7152816, 12949938, -12069890}}, {{-7980351, -16667594, -6066191, -4178266, -20661758, 5435061, 13465372, 4095711, 9258724, 14070358}}}, {{{29333332, 10934940, -14778994, 7811936, -23747152, 5400624, 4239596, 13102200, 16856010, -10864742}}, {{-13616645, -9680674, -3693696, -365662, 15298234, 943540, -26336867, 13166652, 10038926, -13557624}}}, {{{27219864, 8499757, -1510410, -13117566, -26294616, -8546704, 11719293, 12996257, 7861962, -12796627}}, {{-10884812, 632677, 27150992, -13757978, 28020245, -16489791, -23526316, 8860718, 7583912, 4998526}}}, {{{-30145574, 12792090, 9932238, -7877207, -5944826, -14451467, -10727441, 4439529, -15215278, 13437714}}, {{-9881640, -9328105, 4166804, 3359603, 7561129, 8245863, -26838787, 10932651, 32509075, -12477005}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{21122458, 15275850, 22351341, -2323860, 14384970, -14548497, 29812323, 6794013, 12567819, 13523550}}, {{471974, 3314354, -4884934, -1753362, 18152114, -16266037, -23404599, 5224820, 26284993, -9225139}}}, {{{-12470203, -12457226, 30523395, 1939198, -9435791, -11468299, -13825973, 296095, 9675162, 16689320}}, {{-18116881, 7827442, 16576354, -12683470, -6088996, -11805557, -14841172, 7420237, 14340058, -1542268}}}, {{{-4198519, 7609665, -4625915, -9570636, 126335, -6772174, 21471223, 13646194, -28954603, 15000206}}, {{14066827, -9786092, -20149108, -13301388, 32694991, 16078458, -29219026, -10764436, 8959117, 13822693}}}, {{{-18291771, 13223404, -30667620, 1133116, 24528956, 13144848, 24563847, -7154377, -16290734, 12838709}}, {{12431509, -1446109, 31436746, 16644562, -33430511, -6333908, 9483304, 1625635, -22798318, 11713407}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-8491357, 2415699, 25013848, 12133263, -364390, -10928436, -24652787, -15216721, 32075362, -8273324}}, {{20866716, -6827257, 6330400, 13248178, -14764332, 7461923, 15675924, -1775864, 8827593, -1121568}}}, {{{19361853, 7075431, 7726326, -3083537, 25514177, 12839008, -10609389, -5226832, 4200014, 8061868}}, {{27536602, -13571980, 15093196, 7717112, -26838940, 10105642, 7781719, -7526323, -7655304, 16242865}}}, {{{11905636, 1662562, -19754617, -1459433, 15414674, -1507349, 23299265, -6215155, 13644417, 2772584}}, {{32613186, 257329, -21907173, -3806839, -13226976, 16484873, -8453236, -996782, 10406895, 2254153}}}, {{{30779663, -3003776, -28523254, -1716014, -33536086, 10164248, -15547349, -8237791, -23761245, 6590726}}, {{-17817122, 8315575, 18462486, 13374294, -14717492, 15435984, 28833611, -4570913, 19380189, 3291296}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-23640941, 12569140, -21460985, -5972040, -32498256, 14194940, -8272266, -5685877, -22321601, 10642431}}, {{-13298115, 15667645, -19341674, -5778818, -6795644, -7125672, 15425117, 9370859, 23770825, 2440430}}}, {{{23852890, 5489792, 9312298, -7193436, 29732871, 1559767, -22247501, 2231212, -11463312, 13863800}}, {{2087206, 15406615, 8011889, -3113938, 28704525, 13469326, -20465111, 14872299, 9140459, 7302058}}}, {{{977609, 4728016, 2967215, 3855395, 31450548, 6942063, -15563122, -8513137, -19113026, -10708085}}, {{-15800094, -10525285, -6675202, 8834378, -32349531, 15697503, -8619925, -2051806, 22412691, -1716868}}}, {{{-32088869, -5768320, 25086661, 5586170, -23594476, 14518157, 27748172, 4893464, 25417659, -13445713}}, {{27277432, -14025083, 10318327, -8070090, 20282005, -6649110, 32247120, -14513557, -12176814, -9142849}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-21196865, 10673992, 32612715, -7769163, 29159310, 4075347, -18199864, -7740793, 24961993, -14296975}}, {{31543464, -11150632, 23633255, -3444640, 30539928, 7311346, -20996291, -14033306, 31524433, 13145101}}}, {{{-2334532, -8824572, 32619588, 7437258, 2192, -12355835, -4907373, 9959161, -12169088, -7000856}}, {{-15590999, 15587995, -9913444, -12212515, -22842693, 6636565, 18507569, 4395155, -30470127, -12371472}}}, {{{-13622975, 5359317, -16574752, -1393641, -4095345, 6026803, 12851320, 2075442, 22780457, 13665869}}, {{-6395990, -4302149, 17726158, -10400929, 133520, -14902872, 6559759, 13765202, 15206059, -12242947}}}, {{{6520079, -6874205, 12314140, -8292397, 1349263, 2473300, -2686115, -8703620, -13398366, 2381847}}, {{12553415, 2837017, 32199871, 11392587, -10791425, -13670722, -14002913, 4609887, 18999714, 7852053}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-4513859, -442437, 26623889, -6011463, -2693348, -899547, 21483475, -13757839, -20615865, -15197192}}, {{-19962290, -13398764, -32187614, 11204275, 23307966, 10219258, -24653092, 4750343, -26847528, 3933032}}}, {{{3831182, 7657791, 20688837, 10144978, -23145731, -16403629, -11017770, 5284675, 6955812, -15931414}}, {{-6075615, -8412519, -25285867, -11211287, 16898559, -15695504, -10629957, -14499464, -12178513, -4972751}}}, {{{-3739178, 16488805, -23242879, -3797119, -16112108, 15390666, -28056294, 1749817, 23901845, -947065}}, {{24964012, -2548532, 12685293, -11770541, 10193478, 14820307, 18427579, 11254762, -3442436, -4010478}}}, {{{-20512258, -7100978, 28046711, -12725920, -8825454, 10944445, -18251146, -3487950, -28340506, -7811908}}, {{-4657307, -2952664, 19152821, -5466918, 2841097, -8785253, 18326521, -790579, -4185715, 16281581}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{13142850, -13347760, 8479574, 1381711, 12346501, -4221061, -4805636, -1448024, 1781281, -1148926}}, {{2852236, 16547633, 5192981, 12330529, -31725336, -426585, -8275974, -14048245, -15274088, 2416978}}}, {{{7612755, 5737450, -25915585, -1193480, -21969712, 8939931, -24069233, 5389926, -14593435, -311653}}, {{4661446, 14641435, -8565639, -591845, 28706337, 4327374, 29306892, -10499409, 30256951, 4347437}}}, {{{-15866782, -9048831, 14139226, -7561478, -23023550, -16140740, 29505539, -13302488, 17362774, 8609680}}, {{-14908841, 1617899, 33070350, -9353338, 2158682, 8751480, -325725, -2524688, -23962744, 1042796}}}, {{{-7170546, 12522521, -2843124, 1098851, -19099553, -5651847, -15125132, -1006277, 18406587, -5281714}}, {{-20837834, -9874706, 2285804, -15533686, -28581606, -12032262, -20196550, -3076190, 3872303, 11599520}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-26169014, 16394851, 4198188, 5288239, -24101585, -15094425, -30161840, -10989214, -19745355, 6733398}}, {{11967902, 11343923, 19065326, -12430637, -24728366, -12832186, 3752898, -15799674, -10503449, -8877521}}}, {{{25672196, 7270733, -18957833, 6729327, -6800912, -314223, -24174295, 13849998, -23495612, -15270711}}, {{13016697, -8687607, -24048715, 12296071, 33532398, 2228034, 18337232, 15368115, 8929397, -11897311}}}, {{{4757190, -4093299, -24661354, -6915880, -16218364, -3645885, -11461992, -6339288, 10377281, 1700298}}, {{16999730, -5660039, 30111342, -565676, -30582644, -11856802, -18907993, -6496585, -12011594, 13648976}}}, {{{19056135, 2570373, -14470068, -4361921, -14247623, -7231871, -22771384, 14876701, -24281836, 15043721}}, {{-33496325, -5784416, -22596828, 16115749, -20320868, 15117351, -22843051, 14490779, -3490856, -4364970}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-9542601, 1854823, 6715855, -5138168, -26357819, 9115066, -18369386, -5636694, 20006261, -13200888}}, {{683621, -4073879, 21855811, -5017350, 25883352, 14333668, 14567889, 5914789, 3434301, 12910680}}}, {{{23950156, -9932987, 23227274, 12595488, 23884258, 1581035, -18046550, -12890933, -7437805, 8980723}}, {{-16200249, 8963420, 27541859, -12611953, 18206495, 13541107, 16473019, -13510969, 29268968, -7735490}}}, {{{-17015918, 7257949, -7020610, -15786836, 1025278, 13904852, -17961840, 10995274, -29998817, 13302484}}, {{-7333991, 520826, 28136610, -2194999, -5858543, 14291802, 13660941, -16119913, 22529036, -16160552}}}, {{{-13497420, 4273963, -3921238, 13346905, 14011942, 2855226, 19198975, -13095203, 20681840, 1084425}}, {{18766588, -11133689, -9308973, 12186812, 11920620, -1091674, -24805085, 7589322, 26409177, 1273463}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-11085869, -6007258, -1449668, -8184331, 17701391, -2048931, -4530054, -11415176, -28786821, -7421510}}, {{9154070, 599800, 4754317, -4700538, -685585, -2828160, -25253796, 3662694, 15571284, 7102306}}}, {{{-29928058, 930020, -17390967, 10829461, 14140693, -6408124, -27587079, 13074439, 171753, 2929576}}, {{-23471363, -6240664, -19059283, 9077820, 25228279, -12466553, -9582739, -11183156, 27430202, -14701993}}}, {{{28999907, 4680582, -78027, -8721054, 11042394, -5101106, -25650176, 10588659, 28025483, -6563706}}, {{5569301, 8175982, -24303024, 3467826, -10600998, -10065159, 5501824, -5513486, 22656685, -14518287}}}, {{{-32265539, 9532282, 21705865, 12946208, 5034842, 9954820, -26901686, 14117339, 24976601, 1806149}}, {{-12227443, -1773302, 5214128, -3030397, -31271507, 15849927, 14453948, -14175641, -3551731, -3418311}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{19130916, 9115039, 10603324, 4203268, 7983466, 1306443, 33531501, -1005392, -20361084, 8146049}}, {{2580315, 8427300, 15668648, -677150, 136226, -163846, 8713215, -9445822, -11091070, -6763083}}}, {{{20317075, 3746592, 25600292, 16093738, 8671536, -7673370, -8436034, 2611396, -25189540, 7682500}}, {{29503092, 5629303, 17831290, -5719265, -30699229, 7511570, 13026015, -114358, -23998966, -1269729}}}, {{{-32214578, -10286696, -6473464, 9352860, 28581055, -270362, 13429565, 594635, -5005068, -3505462}}, {{6896462, 6115570, -19976822, -4301021, -16169316, 737837, -32489110, 12648484, 4980086, 782680}}}, {{{12052535, 1174424, 8175504, 5117753, -27026921, -11654751, -23281039, 6656678, -801697, -13590848}}, {{-678274, 11486291, 9685879, 15895846, -29146376, 12753979, 9394963, -15748418, -26925347, -8605080}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-31137640, -758515, 5062558, -7045635, -2468686, 8220389, 11271112, -10554352, 7552766, -1986676}}, {{-29481143, 12698802, 20433365, -680725, 11137059, 16582727, -7903510, -16030075, -9243830, -7018114}}}, {{{3058195, 572435, -13210217, -10528151, -15035582, -3613283, 11255982, -14255119, 300683, 8911762}}, {{9443091, 3471948, 4597260, -2864234, -17394470, 8749882, -30486360, 10725422, 29387, -12571171}}}, {{{15479927, 5318576, -19655192, -11311062, 18388164, 10298421, 13295299, 15256926, -6993587, -8981264}}, {{-1942646, -13078066, -949648, -11281443, -24310983, 10037946, -26451884, -9039672, -8950112, -10758178}}}, {{{21410802, -3875964, -20331241, -9990421, -15899977, 9734393, 13370159, -9610092, 30707888, -2098647}}, {{32834118, -9344023, 12012975, -1027670, 9089832, -14578287, 104907, 6476120, 1967007, 15813692}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-13142713, 5475592, 15532981, 12734403, 20181594, 16226149, -30857983, -15228882, -19809355, -11564396}}, {{-23341716, 14952599, 25622298, -12315990, 33307681, 6652330, 11077232, 15094905, -2251198, -9925420}}}, {{{17608885, 14609619, 21231876, -13422132, 4272876, 10275383, -3210562, -2156512, -17237223, 9986462}}, {{1261899, -16348971, 24455637, -1943308, -18050984, 11979647, 24808847, -7677666, -32890065, 11174254}}}, {{{-28890716, -1799262, -26615254, 11199896, -18441989, -13376823, -8351863, 15955474, 4192860, 10516542}}, {{24783152, -10241240, 6116791, -6094016, -23826266, -12859184, -32127553, 1349040, 26546548, -9127439}}}, {{{5205021, -3371089, -27047587, -4043255, -15999235, -9728044, -284329, -10160230, -10062835, -10897610}}, {{19378424, 10940331, -3377474, 11082199, 33041118, -12214541, -23294792, -5819921, 33292532, -12081210}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{1354376, 6627721, -12074430, -2202199, -11111549, 12217757, 29800748, -1088417, -16169014, 8734413}}, {{-29526794, -4969475, 7307364, -1684647, -29245288, -5989667, -16898818, -16342712, -1161484, 11011394}}}, {{{26665961, -45416, -33295490, 10560805, -8707732, -14831279, 19592280, -4083471, 2341552, -1166158}}, {{11472005, 5316862, 32029481, 13256638, -3747505, -1990554, -24454686, -822978, 24852005, 7411349}}}, {{{-1437041, 4715628, -20880881, -11281120, 22949556, 15163954, 2656515, -3643532, -8254906, 3619014}}, {{-20808572, -7805846, -12871750, -5329288, -6780734, -10337286, -21300345, -946188, -13744160, 7503538}}}, {{{10076571, -12120268, -25299316, -3374983, -28001061, 14468758, 19432815, -6393412, 33473820, -8484153}}, {{-6199250, 2547529, -9392856, 8780308, 16996654, 5429039, -15673047, -15225700, -27861959, 16648171}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-12059141, -6708577, 8769332, -4228077, -2379640, -16152871, 32423449, 724288, 29063034, 8265266}}, {{14960488, 5590890, -4888956, -5831311, -15241300, 12540090, 12883298, -4291770, -8606189, -10150299}}}, {{{23317191, -9809296, -3495769, -7133484, -2277347, -2184141, 13478971, -1616318, -6324398, 2332690}}, {{-14484922, -4686189, 16749280, 12271059, 7315218, 6262918, 11401847, -4606398, 9187051, 7122353}}}, {{{6437347, -15969299, -21276383, 12225439, -3218667, 7357348, -29314830, -557999, -28711684, 1692027}}, {{-21463, -6916086, 28542776, 8829976, -19114964, 2933474, 20986264, -9719897, 1488267, 9163715}}}, {{{33259537, 7446349, 8717408, 16605206, -25767672, -7077635, 23426899, 2175739, 30963572, -1958419}}, {{26278901, -7970741, 11380212, 287812, 17161585, 1638733, -25939909, 8161546, -20764621, 853714}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{29495551, -14969918, -2360737, 14933588, -24188812, -9971017, -12326374, 141671, -23437230, 6168325}}, {{-3500298, -3262836, 23036789, 4715502, 18844196, -10655189, -28246746, 5692375, -11201764, 3052420}}}, {{{13034844, -3480703, 10950603, -4302564, -22724869, 1208020, -10917163, -12242330, 25724074, 513292}}, {{-19137456, -12036503, -26224718, 3767666, -27312022, -11727416, -17334094, 1937537, 11177428, 2998588}}}, {{{-16684735, 11851546, -395087, 9092746, 326047, -3427015, -11850943, 16275141, -29379122, 1663582}}, {{-17625588, 12155951, -18155945, 14222900, -17264090, 9084147, 14726365, -11930082, -18243501, 14284868}}}, {{{15279679, -12518832, -30596906, 5148421, 31854978, 7153630, 22985587, -15344419, 425013, 12531039}}, {{31244671, -5295634, 23766961, -2371262, -1893064, 2779069, -3692880, 14893409, -19944463, 6878879}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-18006127, -2226664, 27624552, 140384, -5771360, 13751951, -13915109, -7768620, -4165450, 11359663}}, {{-15250046, 6371446, -32100581, -6719507, 16541399, 12646939, 7264692, -5167680, -14153748, -1146803}}}, {{{-12554470, 1118508, 28436598, 2160256, 24405039, -4063602, 11428602, -4153582, -11990043, 16609567}}, {{-13878333, 5029821, 21487854, -16634411, -5622110, 3787605, 33118728, 4364881, 14709800, -11668570}}}, {{{29470384, 6550115, 32436055, -16527913, -2711309, -12590485, 32604207, -10188631, 22512696, 7908469}}, {{-19482604, -9954874, -14928093, -7520989, 12442845, 10424971, -10248198, -15053625, -35477, -16311854}}}, {{{11860080, -13153238, -25909478, 9356887, 13028323, -9251695, 27601795, 13193287, -31324532, -8059804}}, {{-7482324, -12285358, -16632307, 6138428, -1403249, -11238138, -20211243, -2603662, -24946272, -7360619}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-12632143, -12765636, 1316480, -10997117, 29444261, 2362133, 11533330, -425201, 4823200, 5159558}}, {{-21487804, 3162225, 11182886, -14646528, 27047347, -14293648, -18876146, -9560196, 29936147, 2232914}}}, {{{21218535, 4911699, -8148051, 1957242, -27182879, -15864514, 8290705, 8975166, -23491840, 4049238}}, {{-15343778, 2199253, -31574512, -13337788, 19151346, 7067674, 24618879, 8030457, 17005584, 5965425}}}, {{{-20568883, 14713616, 2454067, 8229459, 24991264, -43174, 25541235, -16775070, 19723966, 11537495}}, {{18218972, -2978856, 10374214, 6662520, 16546524, -15787404, 15136108, 6213563, 28504289, 5827947}}}, {{{-12110053, 10993017, 15025565, -6179817, 18744448, 6900626, -20576121, 2845292, -4160904, 9878147}}, {{27341436, 1082433, 25901632, 5968493, 21203022, -6447011, 22937294, 3057698, 30198244, -8948961}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-29826068, 10228098, 19205072, -13632566, 10828617, -5241203, -11675886, 1031309, -29812980, -12864525}}, {{-29945227, -4355045, -8216732, -4689813, -6444537, 11273481, 19078229, -8565124, 3674229, -8750607}}}, {{{-14550532, 14519188, 328691, -7201861, 6224501, 12986928, 20138252, 1246732, -368364, 10621026}}, {{13871935, 6136509, 28919700, -11134391, -32232412, 12790296, -97226, -1592341, -24740362, 13107466}}}, {{{-31760284, 6460354, 17241924, 439765, -26236967, -11121289, 25505169, -5642797, 8595476, -9544068}}, {{-18070299, 6563650, 1733615, 8223695, -8915902, -14176763, 10068812, -2679473, 26586277, 3900765}}}, {{{32758298, 1101929, 15720325, 3625871, -13540113, 4248367, -7742986, 7973006, -14451935, 7562684}}, {{23124982, 1218355, -25304605, 6523316, -19904550, 1560281, -7133265, -9702673, -21422339, -1472084}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-6141416, -10468826, 26775654, -778362, -28035150, 16472909, 20991101, -7680823, -13945583, 10318868}}, {{-21448370, -7629182, -17803136, 9247970, -23433092, -12033061, -17869106, -2648890, -25320665, -10521195}}}, {{{20402052, -16015540, 15791544, -4499120, -5406735, 3503439, 22409043, 15156001, 19856155, 15789482}}, {{26522171, -15200677, 3997142, -5121836, 1405470, -12244332, 24428637, -10422748, -16129011, 4830502}}}, {{{7870717, -11326943, 13315536, -7624915, -32335768, -4107985, -25622123, 7056739, -16812779, 8914688}}, {{6441892, 12548499, 4079854, -1075228, 27390027, -4576650, -2575621, -16694556, 785156, 11260899}}}, {{{-11181995, 4684055, -9197170, -13400837, 11692567, 3334816, 21980964, -10423131, 6737012, 15956446}}, {{-25552630, -3088474, -7686869, -6966664, -7092222, -2927912, -12395670, 10022463, 24638452, -1586481}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{27773510, 14573269, 11229534, 8875955, -7213999, 6630085, 24965455, 12866809, -31673038, 13016429}}, {{-20588637, 3097098, -15963530, 15830555, 5577173, -481647, -24900328, -16387827, -3207094, -2358854}}}, {{{23142804, 5488002, 8245854, 3906315, 3756830, -3585214, -10721116, 15643184, -8222317, -12451977}}, {{-20934756, -682128, -4320236, -2722803, 23224813, 7919547, 9019364, -1888610, 10063758, -8394378}}}, {{{8730014, 512485, -33242446, 5729319, 26205698, -14186942, 3865196, 1285003, -33037780, 8385749}}, {{-9499032, 14429862, 10605687, -6254497, 18838156, -3086600, 1685010, -3615947, -6012681, 4006363}}}, {{{-10409309, 9861262, -12262974, -9299162, 27593475, -14769031, 25871765, 9830173, -13202899, 9562837}}, {{20125996, -13973769, 7733310, -10872895, -5627879, 11582, -22889451, -2250998, 9716451, 13578165}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{32008371, 2384848, -33398209, -10667659, -21513021, 24993, -9570364, -9729158, 23889452, -3406875}}, {{-20881345, 2673505, -3896571, -7922435, 20457266, -15646950, -33322359, 537736, 11155038, 4568324}}}, {{{-33472444, 15013269, 22103307, 13070997, -30141397, 11187662, -2810857, -8457993, 11554739, -11471341}}, {{-27660512, 13297976, 25546194, 10801687, 18600119, 2828120, -20854900, 9686312, 5989357, 877559}}}, {{{-3569357, -3729255, 9180803, 4931894, 14465804, 11827983, 33348430, -16106849, -22659960, 1908192}}, {{-15158203, -13443502, -25105573, 11337849, 17253043, -10376384, 18182802, -14750235, -17339061, -5171296}}}, {{{-10461535, 3702484, -22811314, -6272389, 14208599, 98758, -7175412, 9868421, 3697218, 700720}}, {{-2213769, -3008458, 17735169, -13981699, -193340, -14550152, -2523260, 12356961, 27247374, 429488}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{2934035, 10548459, -18534512, 337968, -31949096, -2689962, 5015064, -9212742, 3200103, 10509281}}, {{11829041, 7102365, -12383759, 3351899, -31647876, 13003489, -26966152, -12122459, -12238065, -11449581}}}, {{{-2318359, -14520240, 8711817, -227825, 15899948, -733714, -3534193, -16593808, -1684539, 3347032}}, {{-25880162, -8290084, -11670196, 10427489, -8140637, -12354886, 6943541, 15720408, -4797767, -16232902}}}, {{{24169191, -70961, 25168844, -15483296, 22406113, -13278546, 31673726, -4088704, 817855, -11395545}}, {{28224818, 1103393, -2304457, -3874814, -9610718, 7994525, -6226693, 3643116, -10350703, 11357297}}}, {{{22749274, 5319016, 6309010, -3989357, -8660649, 4709165, 25518940, 7274520, -10527351, 2662500}}, {{10099670, 9550171, 28495389, 9523828, 19699845, 1031089, -28453698, -16107679, -28725487, 6418907}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{16225530, 16118800, -19901123, -3625302, -16914225, 6550155, 16423893, -8931957, -1875156, 14837199}}, {{-19221697, 5207583, -23439021, 7655128, -18980546, -12669195, 1754960, 10908812, 19941959, -13259066}}}, {{{27827626, -10557965, 12384052, -12062851, -15880949, -8559517, -10187309, -14108076, -16761108, -6094081}}, {{8697856, 7667083, 27561332, 12235835, 25814374, -1200993, 12903674, 6325700, -1901365, -13882533}}}, {{{17129785, 14829947, 23292849, -6117274, -30932564, 2025543, 23347683, -6590773, 13083037, 2955679}}, {{29544275, 14330728, 20052414, -4135178, -1950284, 15155831, 12147071, 9224516, -21268233, 376724}}}, {{{-26506206, 1277744, -28455858, 4508603, 22932986, 16649594, 13187438, 14920990, 14142841, 14434638}}, {{-25720730, 651905, 4766901, -11385529, -14130515, 2764267, 18582442, 1802534, -2394962, -769526}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{1991837, -15351163, -20210853, 6294749, -30474851, -16187855, 6981358, 2177781, 20588625, -266985}}, {{12750042, 404276, -24720803, 15538447, 31754591, -9307977, 4776783, -1388338, 11606556, 4162662}}}, {{{9974315, -6003765, 27132502, -1597612, -7244059, -5051030, -10580956, -7716134, -27385290, -9090921}}, {{31961548, -5303401, 2627454, 13374396, -15018324, -10769425, 21574070, -5134703, 9764589, -317547}}}, {{{-24400844, 11596617, -15999693, -2689556, -16863561, -16170634, -19780509, -650672, 18489128, -4796669}}, {{30429026, -5333539, -15012113, -8612154, 16044642, -14922026, -12060664, -4817370, -20210916, 2019944}}}, {{{-30517389, 13065383, -26538547, 4481314, -29812507, -7837046, -21950039, 12658263, -11174349, -4228508}}, {{11422, 16667282, -28495637, 9101099, 9934535, 10280997, 2230753, 87869, 16505559, -5877436}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{28040373, -16037526, -27235338, -575422, 14309370, -12952772, -29293846, -16403804, 2615166, -4100252}}, {{1834690, -5023293, 30030875, -3210908, -12598750, -5420478, 19098130, 7615129, 6459068, 5267432}}}, {{{-26170738, -8465725, 11540479, -3127682, -2979978, -11512674, 29069738, 10919588, 14488106, -14894504}}, {{20101068, 3413474, -17002829, -12235574, -18106644, -11548692, -33309941, -136830, 5227818, 4284788}}}, {{{-1015071, 40548, -23373259, -9289655, -27196884, 5529719, -33427667, -205147, -1032685, -128605}}, {{-14096028, 11790642, 9576229, 5858195, -24923218, -13271565, -5846949, -14070928, -4485563, 12486433}}}, {{{30197131, 6920783, -7830764, -4474258, -5104867, 14076173, -7220062, 8419109, 22063731, 14471967}}, {{-29458676, 8289178, 29353235, -15286131, -13167204, 724240, -29458891, -16124667, 5768683, -16403923}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-1302801, 10347390, 1801566, 67611, 27098111, -16027197, 2152977, 13045012, 20590620, 15790407}}, {{-2688859, 13679571, 9000514, -290442, -17545435, -15859083, 30312955, 10707792, 5104973, -5220229}}}, {{{-1813977, -5952871, -8054659, -10308043, -17376277, 7785699, 18060259, -9498156, 17246275, 11090676}}, {{-14440451, 1589564, 31009296, 9221419, -15785145, -13773031, 31363967, 3297145, -28008219, -14229154}}}, {{{-13216341, -10945743, -20274645, 933168, 31979900, -587048, 13396994, 1711795, -26823360, 9950370}}, {{27364749, 5725207, -31603478, 11186986, -17336038, -4950780, 29666476, -7094179, -26109795, -6529233}}}, {{{-16979094, -8116569, -7906438, 15421921, -17753174, -5486266, -32956174, -66032, -32875, 1189044}}, {{-28036816, -5074553, 5863645, 6163999, -17168938, -6031121, 26381833, 2536692, -27384491, 15436457}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-15710009, -8232280, -10608817, -4487804, 21627408, 2501508, -5316015, -15321270, -8334323, -8187298}}, {{7123412, 1061314, 23850599, 15447960, 12490441, -16296105, -28244873, 4262382, -18814128, 9169172}}}, {{{-29425630, -7978710, -1692501, 7298140, -31121532, 5445272, 22266109, 16250453, -33083722, -14666234}}, {{20124561, -6215117, 32302027, -10347683, 5946463, -6729024, 29601189, 7778254, 30850468, -11226052}}}, {{{-14722839, 13623616, 3761042, -13940345, 33056215, 16277268, 7243006, -11292907, 18396573, 4981955}}, {{17004287, 6443761, -14676461, 11330435, -31176857, -113061, -18026888, 15246699, -5055734, 10946708}}}, {{{-522696, -14636285, -33197319, -12075259, 2208431, 9463424, -23888989, 10370822, 2401980, 14563938}}, {{15643790, 9434414, 22807414, -6051352, -29718367, 8098501, -21548929, -5884146, -8333790, 4524114}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{14198878, 6088385, 29071673, 5634968, -144344, -6545639, 14898473, -5984130, 18496192, 9439052}}, {{8315744, -15230834, -26904723, -12575317, 11520786, -13499558, 18916685, -3974093, -13334325, -7026540}}}, {{{-22159877, -12934385, 11949695, -9464929, -4784592, -15987534, 16291326, 14485760, -25632718, -3516107}}, {{3869128, -11947432, -6402166, -2290011, 1247385, 7750707, 14516510, 4294722, -31691918, 3855028}}}, {{{-1604222, 1701820, -11010170, -2892029, 28135594, -8035747, 752721, -13877871, -17082004, -13300552}}, {{3355004, -13371085, 15736814, 13011898, -27416665, -14647399, -7434580, -16457462, 357213, 3180313}}}, {{{-23359771, -1863489, 14217724, 5580748, -25951805, -1261790, 1585452, 10596747, 11918771, -9797206}}, {{24926420, 7817219, 19653826, 12892636, -7458847, 14824160, 20180094, -3738434, -3225902, -1802082}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-20911664, 13723007, 27144900, 10562505, 5309240, 3550276, -13505368, -9775381, -17139228, 3862056}}, {{-19103794, -14634237, -30473916, 7055172, 3981318, -11791961, -1336208, -14745163, 1317, 3767790}}}, {{{15106853, 10510053, 30790198, -14792664, -10177117, 1648009, 11579541, 2274020, 6968154, 3836705}}, {{-15924453, -3746141, -18986637, 16378249, 21135564, -4319174, 12275850, 2324312, -13127585, 15600289}}}, {{{24852154, -12932517, -10968509, -3144560, -13474193, 15270487, -14675120, -15167091, -24954784, 8392606}}, {{33512291, 8154282, -23466210, -1749727, -28239832, 877909, 12136398, 11729988, 15209178, -1737429}}}, {{{-27500720, -2134219, 27607503, 2238739, -8974310, -3758393, -19487508, -3002130, 30831521, -10980176}}, {{-9143554, -9128652, -31734979, -14973217, 28809637, -3347220, -4908667, 5077903, 19257186, 11972646}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-15264477, 11990267, -33543230, -10134384, -21808891, -11854866, -1188329, 13708483, 31767252, 5254588}}, {{-20984284, 744942, 31654985, 5434650, 4833985, 14111806, -6977684, -1410171, 26791088, -15648051}}}, {{{-10390009, 7117188, 1034020, -12439706, 10913289, -13286350, -13586678, -6722932, 2060024, 2785085}}, {{14350832, 12169441, -29060111, -3478345, -30318147, -7121214, 29154006, 7674439, -5320345, -3359020}}}, {{{26587531, -11262791, 26133031, -14520411, -6763763, -13828372, -8854972, 9353355, 5597090, 5040490}}, {{11277856, -6942065, -1521839, 9771876, -7283271, 15309975, -6245586, -12616563, -10465080, -830060}}}, {{{14795048, -221995, -13725992, -14624567, 18522856, -822427, -32191044, -13055121, -4012343, 4116450}}, {{15324663, -9562275, -32070971, 2893282, -13977661, -4446189, 24996431, -230192, -20882900, 4248401}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-28921484, -11779153, -1209099, -12661068, 31735317, -9648108, -30560360, -16275788, -27821980, -1201834}}, {{-29708077, 13031450, -16458200, 7883979, 5409974, -2390671, -23889033, 7556155, -23008569, 3333812}}}, {{{-1706895, -3931258, -1540876, -10296517, 5477679, 12571201, 686756, 3722806, -16045034, -9746078}}, {{-15287744, -14343038, 23730108, 1310281, 25618433, -12322579, 8190711, 1461256, -19089365, -6873640}}}, {{{17676947, 6934530, -24316729, -838670, 22015323, 4637816, -30116108, -15085586, -30610945, -11705965}}, {{-22429208, 5660401, 8144484, -10396774, -30997321, -1960644, 21749867, 13500337, -6589645, 2499343}}}, {{{5682896, 15439628, 8949430, -9270243, -4353018, -1673658, -33107589, -16293157, -16833802, 16539865}}, {{-2084848, -10287193, 22356761, -5677402, 2774745, 16481951, 29652962, -7838609, 15782655, -9178648}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-2436467, 11899186, -5973137, -15875860, 32143228, 8263549, -25027698, -3177038, 31687046, 7282364}}, {{3229766, 12424768, 14809438, 9640153, 7604728, -10633143, -8928323, -1708212, 25515618, -7904217}}}, {{{164692, 6611078, 16384243, -5323051, -3413466, -4676646, 1748278, -13796795, 6261798, 1766281}}, {{10731621, -14330782, -15559968, 5795652, -16046842, 7686233, 23500680, -4974299, 30265591, 16030306}}}, {{{-14064062, -10338041, 31313880, 7716587, 3326908, 8387764, -31628063, 12446856, 11203652, -2517438}}, {{-9417548, 15205267, 8547856, -3816067, 26511461, -16600055, -261336, 11065795, -3863132, -12892630}}}, {{{1496311, -10136677, -31331404, -880291, -7024268, -5970383, -25560674, -11198201, -18130427, 2631374}}, {{-10561242, 12239849, -10215820, -14245446, 1784444, 15553341, -9071145, 2180247, 23132721, 15372799}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{2924507, -5458497, -11909692, -9684940, 11389465, 7835757, 22716835, -5497073, 28707096, 1997429}}, {{13076375, 5113601, 15402784, -1762258, 26214804, 12558885, -10139096, -12016091, 18686529, 5850277}}}, {{{14109280, -15344538, -17731658, -320022, 19318304, -8642411, -30622104, -814535, -32654065, -15043546}}, {{9730251, 13728036, -19185962, 11248320, 20844515, 12437817, 11264324, 4490212, 8357507, 2980999}}}, {{{6829610, -1206273, -4426582, 96549, -12745137, -1242375, -32248335, 4358622, -31922701, 5834123}}, {{-33480299, -6888076, -13047070, -12211434, -5224663, -16365899, 33526586, -3167009, 23799295, 2141173}}}, {{{-25729115, -12588970, -32327495, 5363488, 20337448, -12747106, 5977949, 1350102, -23488365, -10205512}}, {{26560758, -2630680, -32017225, 9494530, 9919019, -5104858, -21685369, -2900351, 3318132, 1633097}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{26450226, 14460596, -6105794, 15361446, -20229145, -2909595, 30536195, -2530418, -625288, 4377620}}, {{27544505, 5993515, 32932972, -11187803, -9981545, -8002710, 7595623, 2634614, -32534068, 5169131}}}, {{{8977668, 7602959, 32123457, 6342706, -8720625, 3392897, -394018, 14395075, 29265388, 7202166}}, {{29231736, 2840020, -31387862, 11025628, -21238210, -4573108, -15390232, 1573841, 28734917, -5103656}}}, {{{-21888926, 12277082, 3259817, -7290057, -30027693, -13231362, 28185352, -8490703, -28360917, -3934819}}, {{19549968, -880976, 26935314, -8701017, 10715528, 16029392, 29421348, -10772996, -9488421, -6907561}}}, {{{12962814, 812124, 16888418, -15237498, -32915550, -12752412, 10010569, -7953188, -21826396, -8754413}}, {{28646334, -5190919, -32111326, 8336287, -17577583, 14804197, -6706867, 7968678, -5722400, -12485628}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-32646154, -13807799, -33149277, -3206128, -22640417, -6680187, 11131524, 1388305, -15068557, 12153148}}, {{-11272034, 16192383, 434937, 6668282, -7263238, 5151055, -22398380, 7523212, -10137302, -9413435}}}, {{{-1104671, -220769, -6484254, -3916821, -20988747, 7507187, -19171945, 3000683, 15246575, -13520280}}, {{-24712667, -2886543, -7010345, 734315, -15223658, 12125517, -13079700, -15708552, 32397855, 10180036}}}, {{{-3969695, -12020758, -2865975, -4212556, -31755888, 7416322, 26848796, -1697320, 18010016, -3528250}}, {{607391, 4781386, 10383865, 14037548, -11797126, -7120952, -21700398, -12456868, 26412494, -13392523}}}, {{{-11501915, -13247350, -20104510, 2206733, -30615982, 6466157, -24234173, 7183971, 28729339, -10064248}}, {{6662626, 9711906, 29849471, 664315, -11378904, -3279138, -876640, -8033037, -11471255, 2086509}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{2578929, 5682934, -26195006, 15202760, 16776116, -12626844, -20911936, 11320830, -31466308, 4666884}}, {{2284531, 8386954, -24628308, -13510295, -3703671, -1474251, 522019, -732813, 4161268, -15743899}}}, {{{16839662, 3642408, 6305496, 6939751, -20756283, 15584601, -4381432, -13291490, 26161954, 1716431}}, {{-11567669, 11930688, -7919774, 6801457, 29676753, -7072075, 16215988, -4940862, -10930046, 4246181}}}, {{{-4406276, 12523295, 33111862, -2762967, 26389549, -10784968, -26392154, -5653107, -4236796, -14606613}}, {{-12206989, 15239368, 13553159, 8178879, 27087325, 15178288, -10032333, -8091098, 18129955, -409608}}}, {{{11649159, -14948100, 22360674, 15170448, 13997817, 5139111, 26271638, 15072516, 8645753, 8040543}}, {{19001211, -5042119, -4531324, -1846082, 32119254, 7232037, -30870850, 4940648, -33523288, 1074822}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-5863255, 12116971, -2160345, -11060824, 17038026, 5731366, 15366950, -9717293, 23491320, -12873365}}, {{28541551, -7776913, 9596255, -1167339, 11453810, 16514907, 8453163, 14209544, -1770805, -4127072}}}, {{{10222299, -3607285, 7423373, -13616285, -16171743, 5493252, -17394672, -14094803, 18964843, 13411056}}, {{-17121223, 13431679, -19728152, 9215196, -15225398, -11770087, -17139703, -6926723, -26467914, 11468029}}}, {{{26011270, -13453369, -10544448, -7199206, -25828454, 16291628, 5907092, -8038108, 18523769, 12414740}}, {{-24768726, 15168981, -20305768, -6084204, -26868513, -10340537, -21862409, -12054956, -10439480, -10752854}}}, {{{9479987, -2363169, 15996067, -11486317, 5344764, -4071805, 18912953, 4091718, -22183235, 14228121}}, {{7064748, 15613535, -32800495, -6521873, -9927766, -16725369, -21375260, -12772054, 3276203, 9663512}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-27151716, -11885053, 20830965, 5975397, -7833557, -8004417, -11663443, 10914549, -4278150, 15741050}}, {{-8078014, 2966361, -3572204, -5884771, -208279, 3086708, -31282633, 12988998, -13692089, -2908005}}}, {{{26240797, -15531237, -4401126, 11203902, 23279153, -6155877, 30975454, 10977416, -1949995, -11614408}}, {{24509208, 2867325, -7664057, -6207448, -24535575, 7229449, -21391896, 1873691, 5953891, -9266307}}}, {{{1738784, 3612580, 33046491, -9225495, -4932192, -12364432, -24493136, 12216391, 20798183, -2594281}}, {{-23017337, -9684900, -24556202, -1610870, 856922, 6048357, -25525714, 14026725, -14105119, 8591179}}}, {{{-4029544, 1075214, -1341163, -2734597, 23560340, -606932, -12304575, -16737955, -4848162, 3055059}}, {{-7269580, 14589424, 16594822, 15225288, 4200951, -12063078, 17468858, -4604053, -5427963, -11343867}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-29764261, 8913619, 15992941, 4912144, 18818545, -13140751, 33001949, -7821107, 32990297, -4608941}}, {{30067010, -2256118, 28400455, 12702689, -19918903, -15025738, -1108342, -11293332, 31233324, 12832461}}}, {{{-102561, -2587877, 32385307, -3396209, 9680642, 9636017, 8111931, -2264633, -17561584, -14314941}}, {{31098973, -15653328, -9844120, 9816671, 2307452, -9048316, -23242508, -10534659, -14174627, -159678}}}, {{{-1015472, 4146619, -7231893, -16262956, -4577103, -13386863, -9133385, 3191602, 5369998, -15018041}}, {{-12326940, 13625363, -17350459, -13505167, -18680004, -15633170, -11831781, -2333120, 9758625, 8596599}}}, {{{-1480736, -14305569, -33139188, 8489679, -27374734, -13104723, -12646503, 14289851, -22938784, 1929156}}, {{-20471916, 9460472, 14845604, 8516539, -10042874, -3519354, 8527822, 16079563, -12022735, -15800099}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{6927948, -14327694, -23968141, 2221898, 23655478, 2268215, -13445808, -4696422, 2520675, 4314108}}, {{-19550174, 8122874, -12421898, 369415, 32836358, 9924624, 32319106, -2600668, 32290433, 10907523}}}, {{{-29163981, -7680629, -7567674, 943195, 2119082, -1562719, -12815700, -13951406, -18603742, 16355091}}, {{-6515080, -6278486, -30367658, 14689254, 10055429, -1197375, -21484333, -15625839, -22361985, 14050466}}}, {{{525471, 10612618, -16445413, 7143154, 25923475, -12177669, -10911545, -12940767, -6220878, 8042380}}, {{26812595, 15434394, 9031188, 2997251, 22158962, 5587779, -28920128, -11758288, -32315699, -5037215}}}, {{{17255057, 6111787, -28014088, 3374622, -12925703, -9983149, 27535877, -4526707, 12019474, 13072383}}, {{33196086, -3294145, 17727726, 11436676, 18950370, -10221778, 12257484, -5971136, 27416805, 8942190}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-21145647, -5569596, -30118196, 8478060, -5240556, -10627750, -18472363, -6919803, 7771572, -5465772}}, {{-2856144, 13259882, -22061252, -8646316, -26970279, -2785236, -24473804, -8406700, -10913073, 16645157}}}, {{{-30143179, -6689277, -26999509, -15533872, 30214672, 12953683, -31880063, 7842967, 24692860, 9942491}}, {{-29935289, -16301218, 28008098, 13386267, 21680214, 11741711, 30613464, 16147670, 19879004, 6188414}}}, {{{29172637, 9748357, -14368086, 3527732, -17983144, -15716723, 2452105, 10177091, -1113016, 14037925}}, {{4300973, 5468731, -20063657, 2808437, 7242507, -4256561, 11252492, 11666168, -31709420, 10464404}}}, {{{4372799, 9366505, 33046984, 2054032, 5139134, -4345833, 24218565, 12704110, -30140441, -3792878}}, {{-29853560, -567838, -32858668, -7472340, 15171764, -7740659, -3553409, 12290154, -6429251, -1075612}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{23411706, 11319236, -28144514, 15917945, -19200546, 5811161, 30052029, 8190894, 4138750, -2397068}}, {{5113518, -16329589, 11225944, -1491467, 5474223, -14260201, 6848900, 3924323, -26886033, 9626735}}}, {{{-8362299, -15596667, 8794354, -9763420, -19156200, -13433402, 4102064, -5876024, 28787586, 16000964}}, {{8546791, -12704913, -22108473, 12757187, -21109519, -5537753, 8407758, 3889534, -16815620, -15215991}}}, {{{32226839, -9979039, -16864550, -6155735, 19992703, -15371259, 23265316, -14383187, -15367983, 1269003}}, {{10730912, -1654351, 725508, 365475, -11996948, 12288731, 20236296, 1479986, -3262445, -15325534}}}, {{{-16393134, 987251, 25199737, -14890559, -1747548, -3722540, 32144736, -6567005, 270606, -2661109}}, {{-30037184, -9362988, 9237229, -9814751, -3262209, -15257140, -957764, 2593275, 8744156, -5917947}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{6270503, 2711266, -29221902, -14486434, -24179619, -7204907, 17599793, -5319253, 30526860, -4961405}}, {{-9388658, -14106460, 15419813, -4270557, -33276796, 359004, 29471634, 15729985, 12013534, 3502713}}}, {{{-10496620, 16705672, -25101251, -9893950, 1622535, -8281811, 15178571, 3531106, -20340036, 5965142}}, {{-17739978, 13458712, -29694718, 16107129, 1494607, -9194056, 14087669, -973885, 22108337, 9408051}}}, {{{15169862, -3933818, 176747, 2446653, 12664575, -10578572, -22174411, -10478455, 13058623, -15356035}}, {{7088554, -12398415, -8046564, 12166363, 31924034, 7627648, 1820530, -15760010, 3589775, -10592757}}}, {{{-24920523, 14684910, -3897235, 14471035, 9958050, 211853, -6351414, -9514307, 28400842, -6580021}}, {{-11865961, 11905413, 15258239, 14940080, -2524747, 4777895, -720008, -6802912, 29463757, -11716366}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-1880003, 9848130, -28298882, -10051680, 29504102, 13429863, -22229129, 15706921, -11102380, -9024364}}, {{-31764630, -3400976, 6868666, -1774625, 24339256, 13153311, 24515185, 4236547, -3156621, 4350313}}}, {{{16243619, 11580940, 31095859, 469270, -7117702, -4150496, -12382919, -9231134, 26701734, 15737538}}, {{30577450, -10844447, -29502260, -1466737, 30202283, 4471351, 22345306, 1080271, -24248972, 12749545}}}, {{{23967206, 15192001, -7232834, -1683884, -28184020, -13212751, 15252558, -15571982, 31733118, -15823397}}, {{31602075, -7565462, 16963428, 3099521, 29506749, -8517505, -4365782, 10239736, -20085078, 4484499}}}, {{{-28841038, -3176942, 25269028, -16685170, -8241248, 6651394, 31983196, 1521951, -32294519, 10445038}}, {{-26034528, -15543281, 16790895, -14275426, 28320544, -1127756, -9713802, -4668214, -17359326, 11174439}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-18609237, 11155192, 13537375, 4418192, -120504, 6997347, -30898270, 13485042, 1231979, -15082674}}, {{-25941497, 11132940, -4271645, -231754, 11163399, -8412949, -30912477, 16130211, -8960827, -645237}}}, {{{27782682, 12742123, -1455839, -15782314, -20997223, 15951830, 29245287, 741234, -20913887, -2866150}}, {{-7930648, -5714199, 25125192, -7751752, 29583727, 10944695, -28851091, -6843119, -27556974, -8308786}}}, {{{3251625, 7317693, -13322448, 4052211, 23188216, -3806248, -26698032, 7984607, 7667189, -13228885}}, {{-17639383, -3949973, -5511713, 4906069, 9643956, -15731678, -32618605, 8818129, -12671295, 1144347}}}, {{{6395930, 7641786, -22763216, 3719903, 21317847, 11355812, -1800564, -9297140, -32765116, -6671002}}, {{-8840426, -7791723, -14996746, 4466763, -19444087, 1134051, -29134015, 1457448, 24912272, -1467427}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-7740638, -12012095, -23505933, -9636754, -29884834, -16295646, -15302152, 13147916, 548468, -12441834}}, {{-28059490, 6392098, -12572091, 7739656, -21549483, 9712764, 20798360, 537311, 27046582, -12375323}}}, {{{10181570, 8833246, -880377, 12900435, 21870766, 16774673, -31375645, 1048666, -5119788, 1935040}}, {{19916464, -5743584, -8354010, 3761700, 23931158, -5466263, 17307191, 10973064, 15075073, 15316036}}}, {{{-25159525, -12486952, -6883112, 6948370, -27313803, -15387509, 3052630, -7930366, -6198079, 3460224}}, {{-30017255, -16345493, -8336510, 12082008, -992946, -10836693, 33003598, -5818908, -11093594, 2957662}}}, {{{-8987610, -12681457, 24193012, -8742128, 12060175, -3773764, 20612738, 10273189, -12782263, 9853847}}, {{11633425, -1930147, -5583371, -16276370, 23414356, 5909726, 20300410, 1208585, -20340532, -6126945}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-2749147, 1165554, 18412962, 3947232, 6447694, 10277816, -23155370, -12644679, 12665637, 9591111}}, {{6134885, 69116, 21833374, -14340223, 11500330, 1054043, -24947223, 14031004, 24909243, 671612}}}, {{{-12756547, -15968464, -24754807, 2293797, 177214, -3567690, 19817999, 117044, 27298069, 1398030}}, {{-11168912, 4499192, 11697539, -13307372, -21072834, -14241894, -21963195, -8790016, 22232901, -10430682}}}, {{{-17214171, -3067145, 4914069, -13314097, 25201696, -12998828, -12431917, -9089589, -20248327, -6373859}}, {{-28530432, 12453037, 1004806, -7189928, 24411881, 4492868, 25751101, 14747455, 19552373, 3820808}}}, {{{-22105065, 11802205, 23254293, -6780132, -9957105, 12036109, -30970188, -4850453, -10463786, 3649754}}, {{-25002880, -2798067, -5542261, -2218468, -4152292, 5526804, -26323997, -13429782, 3834373, -14423497}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{27084679, 16075130, -1111812, 2964527, 20048250, -15042209, 5853562, -5008379, 21234446, 10679523}}, {{14007311, -16295074, 22451003, -3005915, -302994, 12163509, 31618022, 7235418, 377880, -11225251}}}, {{{-8658650, -575144, 16002984, -15589067, -29425523, -4853378, 12428169, -1131901, -25538073, 3875833}}, {{-12774957, -11846677, -7883202, -10745452, 7595002, -4162756, -19107919, -11538737, -17220213, 16228599}}}, {{{21912573, 10464675, 31322992, 9127974, -4194999, -4894047, -5305411, -6628410, 3801812, 6565585}}, {{4743635, -4389422, 27927316, -7241903, -24149044, 9156373, 16422941, 2865200, 22422423, -9863043}}}, {{{-24475163, -8987874, -28614326, -9253652, 6393230, 16442236, -19862031, 16039570, 17506669, 15007439}}, {{614625, -2245285, -11533181, 10894514, 28302522, 374255, 32110539, 12274223, -3771328, -13073377}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{24081385, 12037704, -16945244, -15171187, -14973013, -7345352, 15674402, -4076408, -2518924, 8093637}}, {{-29118984, 8488433, 13974684, 12109420, 30613987, 643686, 24695436, 5002457, 834585, 12127148}}}, {{{2372750, -11652141, 2182557, 5837152, -21700464, 1670693, 16561784, 2539142, -13340831, -10187543}}, {{10554144, 7030338, -2274681, -5224166, -17609845, 10288206, 17500664, 5711844, 17326365, 15939926}}}, {{{-28636201, -15866279, 5146609, -15304755, 11025456, -1858755, 30322030, -738926, 31004719, -6179944}}, {{-15244125, 11674343, -4404185, -2134475, 10045454, -5031267, -20617718, -6077024, 16858834, 3759447}}}, {{{29354541, -7400769, -3850862, 9681852, -32285084, -8432134, 22693369, -4951366, -25645303, -13759569}}, {{-17553364, 12041615, 8928257, -16102, -25325555, 5002692, -28679965, -1334140, 23353638, 5299550}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-24064575, 1945178, 11840372, -3597396, -32860632, -5148749, -4922762, -5553394, 30660943, 6861670}}, {{-1658808, -1195619, -31515641, 9912598, -4444233, -10828057, -7516339, 9625748, -2050850, -16706837}}}, {{{26629825, 13096932, 17689239, -7318452, 17368923, 15630954, 3888394, 14806182, 18506646, 9512433}}, {{24683317, -12336012, 13507183, 8980186, -33404115, 7606357, -2833637, -16706437, -24109288, 15598561}}}, {{{27109358, -14143513, 4881850, -3617515, 6688033, 13719607, -6286334, -15183521, 2775921, -13545667}}, {{-17384518, -562332, -282081, -9155429, -6759405, 15251355, 17526752, -10971163, 22287300, -9844185}}}, {{{16750130, 4508429, 18962788, -6425556, 8026563, 11507678, 8099915, -5762775, -27324295, -10435647}}, {{-7089103, -3802986, -6982723, 1055402, -9655106, 3153495, -14446057, 8387790, -11353533, -6336186}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{31000107, -13084824, -8136129, -11651886, 5000365, 14205048, -15299701, -13028044, -28658312, 6703685}}, {{10615676, 6121895, -26472535, 2232836, -28039089, -16507270, 30198338, -16677933, -17481217, -11861200}}}, {{{24348948, 10604008, -4591795, 13727433, 30651804, -6491968, 7335578, 3110881, -26368403, 2172712}}, {{22994409, -8213483, -11959236, 434547, -28746518, 12906875, -2645994, 7493926, -3822000, 2610035}}}, {{{2875891, 2195807, 27873904, -754267, -773530, -3018802, -30108032, 8921703, 17022198, 7874115}}, {{14042525, 9533856, 21151381, 3777253, -30242202, -10320857, 1366847, 12405336, 15829023, 3843284}}}, {{{7479527, -1762465, -24606132, -6844645, 18406083, 9612815, -11618188, -4837586, 33198971, 1014529}}, {{-29928171, -16136398, 31624612, 2434642, 18388515, -10814407, 9764723, 6204706, -8071097, 5657214}}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, {{{-11265, 11272918, 33495958, 11048722, 28244187, -9616631, -20437294, -15821050, 26498847, -5754324}}, {{-14925109, 13314881, -17460800, 10046663, 10750744, -1583947, 29746792, 15121808, -8959540, -8513865}}}, {{{-18774920, 1724758, -16127155, -438898, 12848336, -6894665, 15954707, -10267896, -14327748, 13780684}}, {{-17339348, 14199066, -11114707, 15113006, -22525984, -8332097, 33211309, 8158383, 27497451, 2499323}}}, {{{27324811, -16091331, 12647511, 8389590, 21257767, 13941716, -21007087, -12284016, -30503121, 1725513}}, {{10779885, -5325565, -21939154, -7449906, 14198532, -1948663, -21894976, 12407587, 30461170, -4386046}}}, {{{-11631075, 916980, -28187486, -2568231, 4437892, -662840, 1693883, -10374440, 14074208, 1408028}}, {{-12108164, 11258662, 7278474, -3613332, 572937, 14370671, 15783957, -16075982, -33314404, -12303085}}} go-ristretto-1.2.3/cref/cref.c000066400000000000000000002414151440464505300161750ustar00rootroot00000000000000#include "cref.h" // -- scalar.c -- const group_scalar group_scalar_zero = {{0}}; const group_scalar group_scalar_one = {{1}}; static const crypto_uint32 m[32] = {0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58, 0xD6, 0x9C, 0xF7, 0xA2, 0xDE, 0xF9, 0xDE, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; static const crypto_uint32 mu[33] = {0x1B, 0x13, 0x2C, 0x0A, 0xA3, 0xE5, 0x9C, 0xED, 0xA7, 0x29, 0x63, 0x08, 0x5D, 0x21, 0x06, 0x21, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F}; static crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ { unsigned int x = a; x -= (unsigned int) b; /* 0..65535: no; 4294901761..4294967295: yes */ x >>= 31; /* 0: no; 1: yes */ return x; } /* Reduce coefficients of r before calling reduce_add_sub */ static void reduce_add_sub(group_scalar *r) { crypto_uint32 pb = 0; crypto_uint32 b; crypto_uint32 mask; int i; unsigned char t[32]; for(i=0;i<32;i++) { pb += m[i]; b = lt(r->v[i],pb); t[i] = r->v[i]-pb+(b<<8); pb = b; } mask = b - 1; for(i=0;i<32;i++) r->v[i] ^= mask & (r->v[i] ^ t[i]); } /* Reduce coefficients of x before calling barrett_reduce */ static void barrett_reduce(group_scalar *r, const crypto_uint32 x[64]) { /* See HAC, Alg. 14.42 */ int i,j; crypto_uint32 q2[66]; crypto_uint32 *q3 = q2 + 33; crypto_uint32 r1[33]; crypto_uint32 r2[33]; crypto_uint32 carry; crypto_uint32 pb = 0; crypto_uint32 b; for (i = 0;i < 66;++i) q2[i] = 0; for (i = 0;i < 33;++i) r2[i] = 0; for(i=0;i<33;i++) for(j=0;j<33;j++) if(i+j >= 31) q2[i+j] += mu[i]*x[j+31]; carry = q2[31] >> 8; q2[32] += carry; carry = q2[32] >> 8; q2[33] += carry; for(i=0;i<33;i++)r1[i] = x[i]; for(i=0;i<32;i++) for(j=0;j<33;j++) if(i+j < 33) r2[i+j] += m[i]*q3[j]; for(i=0;i<32;i++) { carry = r2[i] >> 8; r2[i+1] += carry; r2[i] &= 0xff; } for(i=0;i<32;i++) { pb += r2[i]; b = lt(r1[i],pb); r->v[i] = r1[i]-pb+(b<<8); pb = b; } /* XXX: Can it really happen that r<0?, See HAC, Alg 14.42, Step 3 * If so: Handle it here! */ reduce_add_sub(r); reduce_add_sub(r); } int group_scalar_unpack(group_scalar *r, const unsigned char x[GROUP_SCALAR_PACKEDBYTES]) { int i; for(i=0;i<32;i++) r->v[i] = x[i]; r->v[31] &= 0x1f; reduce_add_sub(r); return 0; } void group_scalar_pack(unsigned char r[GROUP_SCALAR_PACKEDBYTES], const group_scalar *x) { int i; for(i=0;i<32;i++) r[i] = x->v[i]; } void group_scalar_setzero(group_scalar *r) { int i; for(i=0;i<32;i++) r->v[i] = 0; } void group_scalar_setone(group_scalar *r) { int i; r->v[0] = 1; for(i=1;i<32;i++) r->v[i] = 0; } /* Removed to avoid dependency on platform specific randombytes void group_scalar_setrandom(group_scalar *r) { unsigned char t[64]; crypto_uint32 s[64]; int i; randombytes(t,64); for(i=0;i<64;i++) s[i] = t[i]; barrett_reduce(r,s); } */ void group_scalar_add(group_scalar *r, const group_scalar *x, const group_scalar *y) { int i, carry; for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i]; for(i=0;i<31;i++) { carry = r->v[i] >> 8; r->v[i+1] += carry; r->v[i] &= 0xff; } reduce_add_sub(r); } void group_scalar_sub(group_scalar *r, const group_scalar *x, const group_scalar *y) { crypto_uint32 b = 0; crypto_uint32 t; int i; group_scalar d; for(i=0;i<32;i++) { t = m[i] - y->v[i] - b; d.v[i] = t & 255; b = (t >> 8) & 1; } group_scalar_add(r,x,&d); } void group_scalar_negate(group_scalar *r, const group_scalar *x) { group_scalar t; group_scalar_setzero(&t); group_scalar_sub(r,&t,x); } void group_scalar_mul(group_scalar *r, const group_scalar *x, const group_scalar *y) { int i,j,carry; crypto_uint32 t[64]; for(i=0;i<64;i++)t[i] = 0; for(i=0;i<32;i++) for(j=0;j<32;j++) t[i+j] += x->v[i] * y->v[j]; /* Reduce coefficients */ for(i=0;i<63;i++) { carry = t[i] >> 8; t[i+1] += carry; t[i] &= 0xff; } barrett_reduce(r, t); } void group_scalar_square(group_scalar *r, const group_scalar *x) { group_scalar_mul(r,x,x); } void group_scalar_invert(group_scalar *r, const group_scalar *x) { group_scalar t0, t1, t2, t3, t4, t5; int i; group_scalar_square(&t1, x); group_scalar_mul(&t2, x, &t1); group_scalar_mul(&t0, &t1, &t2); group_scalar_square(&t1, &t0); group_scalar_square(&t3, &t1); group_scalar_mul(&t1, &t2, &t3); group_scalar_square(&t2, &t1); group_scalar_mul(&t3, &t0, &t2); group_scalar_square(&t0, &t3); group_scalar_mul(&t2, &t1, &t0); group_scalar_square(&t0, &t2); group_scalar_mul(&t1, &t2, &t0); group_scalar_square(&t0, &t1); group_scalar_mul(&t1, &t3, &t0); group_scalar_square(&t0, &t1); group_scalar_square(&t3, &t0); group_scalar_mul(&t0, &t1, &t3); group_scalar_mul(&t3, &t2, &t0); group_scalar_square(&t0, &t3); group_scalar_mul(&t2, &t1, &t0); group_scalar_square(&t0, &t2); group_scalar_mul(&t1, &t3, &t0); group_scalar_square(&t0, &t1); group_scalar_mul(&t3, &t1, &t0); group_scalar_mul(&t0, &t2, &t3); group_scalar_mul(&t2, &t1, &t0); group_scalar_square(&t1, &t2); group_scalar_square(&t3, &t1); group_scalar_square(&t4, &t3); group_scalar_mul(&t3, &t1, &t4); group_scalar_mul(&t1, &t0, &t3); group_scalar_mul(&t0, &t2, &t1); group_scalar_mul(&t2, &t1, &t0); group_scalar_square(&t1, &t2); group_scalar_square(&t3, &t1); group_scalar_mul(&t1, &t0, &t3); group_scalar_square(&t0, &t1); group_scalar_square(&t3, &t0); group_scalar_mul(&t0, &t1, &t3); group_scalar_mul(&t3, &t2, &t0); group_scalar_square(&t0, &t3); group_scalar_mul(&t2, &t1, &t0); group_scalar_square(&t0, &t2); group_scalar_square(&t1, &t0); group_scalar_mul(&t0, &t2, &t1); group_scalar_mul(&t1, &t3, &t0); group_scalar_square(&t0, &t1); group_scalar_square(&t3, &t0); group_scalar_square(&t0, &t3); group_scalar_square(&t3, &t0); group_scalar_square(&t0, &t3); group_scalar_square(&t3, &t0); group_scalar_mul(&t0, &t1, &t3); group_scalar_mul(&t3, &t2, &t0); group_scalar_square(&t0, &t3); group_scalar_mul(&t2, &t1, &t0); group_scalar_square(&t0, &t2); group_scalar_mul(&t1, &t2, &t0); group_scalar_square(&t0, &t1); group_scalar_mul(&t4, &t2, &t0); group_scalar_square(&t0, &t4); group_scalar_square(&t4, &t0); group_scalar_mul(&t0, &t1, &t4); group_scalar_mul(&t1, &t3, &t0); group_scalar_square(&t0, &t1); group_scalar_mul(&t3, &t1, &t0); group_scalar_square(&t0, &t3); group_scalar_square(&t4, &t0); group_scalar_mul(&t0, &t3, &t4); group_scalar_mul(&t3, &t2, &t0); group_scalar_square(&t0, &t3); group_scalar_square(&t2, &t0); group_scalar_square(&t0, &t2); group_scalar_mul(&t2, &t1, &t0); group_scalar_square(&t0, &t2); group_scalar_mul(&t1, &t3, &t0); group_scalar_mul(&t0, &t2, &t1); group_scalar_mul(&t2, &t1, &t0); group_scalar_square(&t1, &t2); group_scalar_square(&t3, &t1); group_scalar_mul(&t1, &t0, &t3); group_scalar_square(&t0, &t1); group_scalar_mul(&t3, &t2, &t0); group_scalar_mul(&t0, &t1, &t3); group_scalar_square(&t1, &t0); group_scalar_square(&t2, &t1); group_scalar_mul(&t1, &t0, &t2); group_scalar_mul(&t2, &t3, &t1); group_scalar_mul(&t1, &t0, &t2); group_scalar_mul(&t0, &t2, &t1); group_scalar_square(&t2, &t0); group_scalar_mul(&t3, &t0, &t2); group_scalar_square(&t2, &t3); group_scalar_mul(&t3, &t1, &t2); group_scalar_mul(&t1, &t0, &t3); group_scalar_square(&t0, &t1); group_scalar_mul(&t2, &t1, &t0); group_scalar_square(&t0, &t2); group_scalar_mul(&t4, &t2, &t0); group_scalar_square(&t0, &t4); group_scalar_square(&t4, &t0); group_scalar_square(&t5, &t4); group_scalar_square(&t4, &t5); group_scalar_square(&t5, &t4); group_scalar_square(&t4, &t5); group_scalar_mul(&t5, &t0, &t4); group_scalar_mul(&t0, &t2, &t5); group_scalar_mul(&t2, &t3, &t0); group_scalar_mul(&t0, &t1, &t2); group_scalar_square(&t1, &t0); group_scalar_mul(&t3, &t0, &t1); group_scalar_square(&t1, &t3); group_scalar_mul(&t4, &t0, &t1); group_scalar_square(&t1, &t4); group_scalar_square(&t4, &t1); group_scalar_square(&t1, &t4); group_scalar_mul(&t4, &t3, &t1); group_scalar_mul(&t1, &t2, &t4); group_scalar_square(&t2, &t1); group_scalar_square(&t3, &t2); group_scalar_square(&t4, &t3); group_scalar_mul(&t3, &t2, &t4); group_scalar_mul(&t2, &t1, &t3); group_scalar_mul(&t3, &t0, &t2); group_scalar_square(&t0, &t3); group_scalar_square(&t2, &t0); group_scalar_square(&t0, &t2); group_scalar_mul(&t2, &t1, &t0); group_scalar_mul(&t0, &t3, &t2); group_scalar_square(&t1, &t0); group_scalar_square(&t3, &t1); group_scalar_mul(&t4, &t1, &t3); group_scalar_square(&t3, &t4); group_scalar_square(&t4, &t3); group_scalar_mul(&t3, &t1, &t4); group_scalar_mul(&t1, &t2, &t3); group_scalar_square(&t2, &t1); group_scalar_square(&t3, &t2); group_scalar_mul(&t2, &t0, &t3); group_scalar_square(&t0, &t2); group_scalar_mul(&t3, &t1, &t0); group_scalar_square(&t0, &t3); group_scalar_mul(&t1, &t2, &t0); group_scalar_mul(&t0, &t3, &t1); group_scalar_square(&t2, &t0); group_scalar_square(&t3, &t2); group_scalar_square(&t2, &t3); group_scalar_square(&t3, &t2); group_scalar_mul(&t2, &t1, &t3); group_scalar_mul(&t1, &t0, &t2); group_scalar_square(&t0, &t1); group_scalar_square(&t3, &t0); group_scalar_square(&t4, &t3); group_scalar_mul(&t3, &t0, &t4); group_scalar_mul(&t0, &t1, &t3); group_scalar_mul(&t3, &t2, &t0); group_scalar_square(&t0, &t3); group_scalar_square(&t2, &t0); group_scalar_mul(&t0, &t1, &t2); group_scalar_square(&t1, &t0); group_scalar_mul(&t2, &t3, &t1); group_scalar_mul(&t1, &t0, &t2); group_scalar_square(&t0, &t1); group_scalar_mul(&t3, &t2, &t0); group_scalar_square(&t0, &t3); group_scalar_square(&t2, &t0); group_scalar_mul(&t0, &t1, &t2); group_scalar_mul(&t1, &t3, &t0); group_scalar_square(&t2, &t1); group_scalar_mul(&t3, &t0, &t2); group_scalar_mul(&t0, &t1, &t3); group_scalar_square(&t1, &t0); group_scalar_square(&t2, &t1); group_scalar_square(&t4, &t2); group_scalar_mul(&t2, &t1, &t4); group_scalar_square(&t4, &t2); group_scalar_square(&t2, &t4); group_scalar_square(&t4, &t2); group_scalar_mul(&t2, &t1, &t4); group_scalar_mul(&t1, &t3, &t2); group_scalar_square(&t2, &t1); group_scalar_square(&t3, &t2); group_scalar_mul(&t2, &t1, &t3); group_scalar_square(&t3, &t2); group_scalar_square(&t2, &t3); group_scalar_mul(&t3, &t1, &t2); group_scalar_mul(&t2, &t0, &t3); group_scalar_square(&t0, &t2); group_scalar_mul(&t3, &t2, &t0); group_scalar_square(&t0, &t3); group_scalar_square(&t4, &t0); group_scalar_mul(&t0, &t3, &t4); group_scalar_mul(&t3, &t1, &t0); group_scalar_square(&t0, &t3); group_scalar_mul(&t1, &t3, &t0); group_scalar_mul(&t0, &t2, &t1); for(i = 0; i < 126; i++) group_scalar_square(&t0, &t0); group_scalar_mul(r, &t3, &t0); } int group_scalar_isone(const group_scalar *x) { unsigned long long r; int i; r = 1-x->v[0]; for(i=1;i<32;i++) r |= x->v[i]; return 1-((-r)>>63); } int group_scalar_iszero(const group_scalar *x) { unsigned long long r=0; int i; for(i=0;i<32;i++) r |= x->v[i]; return 1-((-r)>>63); } int group_scalar_equals(const group_scalar *x, const group_scalar *y) { unsigned long long r=0; int i; for(i=0;i<32;i++) r |= (x->v[i] ^ y->v[i]); return 1-((-r)>>63); } // Additional functions, not required by API int scalar_tstbit(const group_scalar *x, const unsigned int pos) { return (x->v[pos >> 3] & (1ULL << (pos & 0x7))) >> (pos & 0x7); } int scalar_bitlen(const group_scalar *x) { int i; unsigned long long mask; int ctr = 256; int found = 0; int t; for(i=31;i>=0;i--) { for(mask = (1 << 7);mask>0;mask>>=1) { found = found || (mask & x->v[i]); t = ctr - 1; ctr = (found * ctr)^((1-found)*t); } } return ctr; } void scalar_window3(signed char r[85], const group_scalar *s) { char carry; int i; for(i=0;i<10;i++) { r[8*i+0] = s->v[3*i+0] & 7; r[8*i+1] = (s->v[3*i+0] >> 3) & 7; r[8*i+2] = (s->v[3*i+0] >> 6) & 7; r[8*i+2] ^= (s->v[3*i+1] << 2) & 7; r[8*i+3] = (s->v[3*i+1] >> 1) & 7; r[8*i+4] = (s->v[3*i+1] >> 4) & 7; r[8*i+5] = (s->v[3*i+1] >> 7) & 7; r[8*i+5] ^= (s->v[3*i+2] << 1) & 7; r[8*i+6] = (s->v[3*i+2] >> 2) & 7; r[8*i+7] = (s->v[3*i+2] >> 5) & 7; } r[8*i+0] = s->v[3*i+0] & 7; r[8*i+1] = (s->v[3*i+0] >> 3) & 7; r[8*i+2] = (s->v[3*i+0] >> 6) & 7; r[8*i+2] ^= (s->v[3*i+1] << 2) & 7; r[8*i+3] = (s->v[3*i+1] >> 1) & 7; r[8*i+4] = (s->v[3*i+1] >> 4) & 7; /* Making it signed */ carry = 0; for(i=0;i<84;i++) { r[i] += carry; r[i+1] += r[i] >> 3; r[i] &= 7; carry = r[i] >> 2; r[i] -= carry<<3; } r[84] += carry; } void scalar_window5(signed char r[51], const group_scalar *s) { char carry; int i; for(i=0;i<6;i++) { r[8*i+0] = s->v[5*i+0] & 31; r[8*i+1] = (s->v[5*i+0] >> 5) & 31; r[8*i+1] ^= (s->v[5*i+1] << 3) & 31; r[8*i+2] = (s->v[5*i+1] >> 2) & 31; r[8*i+3] = (s->v[5*i+1] >> 7) & 31; r[8*i+3] ^= (s->v[5*i+2] << 1) & 31; r[8*i+4] = (s->v[5*i+2] >> 4) & 31; r[8*i+4] ^= (s->v[5*i+3] << 4) & 31; r[8*i+5] = (s->v[5*i+3] >> 1) & 31; r[8*i+6] = (s->v[5*i+3] >> 6) & 31; r[8*i+6] ^= (s->v[5*i+4] << 2) & 31; r[8*i+7] = (s->v[5*i+4] >> 3) & 31; } r[8*i+0] = s->v[5*i+0] & 31; r[8*i+1] = (s->v[5*i+0] >> 5) & 31; r[8*i+1] ^= (s->v[5*i+1] << 3) & 31; r[8*i+2] = (s->v[5*i+1] >> 2) & 31; /* Making it signed */ carry = 0; for(i=0;i<50;i++) { r[i] += carry; r[i+1] += r[i] >> 5; r[i] &= 31; carry = r[i] >> 4; r[i] -= carry << 5; } r[50] += carry; } void scalar_slide(signed char r[256], const group_scalar *s, int swindowsize) { int i,j,k,b,m=(1<<(swindowsize-1))-1, soplen=256; for(i=0;i<32;i++) { r[8*i+0] = s->v[i] & 1; r[8*i+1] = (s->v[i] >> 1) & 1; r[8*i+2] = (s->v[i] >> 2) & 1; r[8*i+3] = (s->v[i] >> 3) & 1; r[8*i+4] = (s->v[i] >> 4) & 1; r[8*i+5] = (s->v[i] >> 5) & 1; r[8*i+6] = (s->v[i] >> 6) & 1; r[8*i+7] = (s->v[i] >> 7) & 1; } /* Making it sliding window */ for (j = 0;j < soplen;++j) { if (r[j]) { for (b = 1;b < soplen - j && b <= 6;++b) { if (r[j] + (r[j + b] << b) <= m) { r[j] += r[j + b] << b; r[j + b] = 0; } else if (r[j] - (r[j + b] << b) >= -m) { r[j] -= r[j + b] << b; for (k = j + b;k < soplen;++k) { if (!r[k]) { r[k] = 1; break; } r[k] = 0; } } else if (r[j + b]) break; } } } } /* void scalar_print(const group_scalar *x) { int i; for(i=0;i<31;i++) printf("%d*2^(%d*8) + ",x->v[i],i); printf("%d*2^(%d*8)\n",x->v[i],i); } */ void scalar_from64bytes(group_scalar *r, const unsigned char h[64]) { int i; crypto_uint32 t[64]; for(i=0;i<64;i++) t[i] = h[i]; barrett_reduce(r, t); } // -- fe25519.c -- const fe25519 fe25519_zero = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; const fe25519 fe25519_one = {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; const fe25519 fe25519_two = {{2, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; const fe25519 fe25519_sqrtm1 = {{-32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482}}; const fe25519 fe25519_msqrtm1 = {{32595792, 7943725, -9377950, -3500415, -12389472, 272473, 25146209, 2005654, -326686, -11406482}}; const fe25519 fe25519_m1 = {{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; static crypto_uint32 fe25519_c_static_equal(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ { crypto_uint32 x = a ^ b; /* 0: yes; 1..65535: no */ x -= 1; /* 4294967295: yes; 0..65534: no */ x >>= 31; /* 1: yes; 0: no */ return x; } static crypto_uint64 load_3(const unsigned char *in) { crypto_uint64 result; result = (crypto_uint64) in[0]; result |= ((crypto_uint64) in[1]) << 8; result |= ((crypto_uint64) in[2]) << 16; return result; } static crypto_uint64 load_4(const unsigned char *in) { crypto_uint64 result; result = (crypto_uint64) in[0]; result |= ((crypto_uint64) in[1]) << 8; result |= ((crypto_uint64) in[2]) << 16; result |= ((crypto_uint64) in[3]) << 24; return result; } /* * Ignores top bit of h. */ void fe25519_unpack(fe25519 *h,const unsigned char s[32]) { crypto_int64 h0 = load_4(s); crypto_int64 h1 = load_3(s + 4) << 6; crypto_int64 h2 = load_3(s + 7) << 5; crypto_int64 h3 = load_3(s + 10) << 3; crypto_int64 h4 = load_3(s + 13) << 2; crypto_int64 h5 = load_4(s + 16); crypto_int64 h6 = load_3(s + 20) << 7; crypto_int64 h7 = load_3(s + 23) << 5; crypto_int64 h8 = load_3(s + 26) << 4; crypto_int64 h9 = (load_3(s + 29) & 8388607) << 2; crypto_int64 carry0; crypto_int64 carry1; crypto_int64 carry2; crypto_int64 carry3; crypto_int64 carry4; crypto_int64 carry5; crypto_int64 carry6; crypto_int64 carry7; crypto_int64 carry8; crypto_int64 carry9; carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; h->v[0] = h0; h->v[1] = h1; h->v[2] = h2; h->v[3] = h3; h->v[4] = h4; h->v[5] = h5; h->v[6] = h6; h->v[7] = h7; h->v[8] = h8; h->v[9] = h9; } /* * Preconditions: * |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. * * Write p=2^255-19; q=floor(h/p). * Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). * * Proof: * Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. * Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. * * Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). * Then 0v[0]; crypto_int32 h1 = h->v[1]; crypto_int32 h2 = h->v[2]; crypto_int32 h3 = h->v[3]; crypto_int32 h4 = h->v[4]; crypto_int32 h5 = h->v[5]; crypto_int32 h6 = h->v[6]; crypto_int32 h7 = h->v[7]; crypto_int32 h8 = h->v[8]; crypto_int32 h9 = h->v[9]; crypto_int32 q; crypto_int32 carry0; crypto_int32 carry1; crypto_int32 carry2; crypto_int32 carry3; crypto_int32 carry4; crypto_int32 carry5; crypto_int32 carry6; crypto_int32 carry7; crypto_int32 carry8; crypto_int32 carry9; q = (19 * h9 + (((crypto_int32) 1) << 24)) >> 25; q = (h0 + q) >> 26; q = (h1 + q) >> 25; q = (h2 + q) >> 26; q = (h3 + q) >> 25; q = (h4 + q) >> 26; q = (h5 + q) >> 25; q = (h6 + q) >> 26; q = (h7 + q) >> 25; q = (h8 + q) >> 26; q = (h9 + q) >> 25; /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */ h0 += 19 * q; /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26; carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25; carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26; carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25; carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26; carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25; carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26; carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25; carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26; carry9 = h9 >> 25; h9 -= carry9 << 25; /* h10 = carry9 */ /* * Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. * Have h0+...+2^230 h9 between 0 and 2^255-1; * evidently 2^255 h10-2^255 q = 0. * Goal: Output h0+...+2^230 h9. */ s[0] = h0 >> 0; s[1] = h0 >> 8; s[2] = h0 >> 16; s[3] = (h0 >> 24) | (h1 << 2); s[4] = h1 >> 6; s[5] = h1 >> 14; s[6] = (h1 >> 22) | (h2 << 3); s[7] = h2 >> 5; s[8] = h2 >> 13; s[9] = (h2 >> 21) | (h3 << 5); s[10] = h3 >> 3; s[11] = h3 >> 11; s[12] = (h3 >> 19) | (h4 << 6); s[13] = h4 >> 2; s[14] = h4 >> 10; s[15] = h4 >> 18; s[16] = h5 >> 0; s[17] = h5 >> 8; s[18] = h5 >> 16; s[19] = (h5 >> 24) | (h6 << 1); s[20] = h6 >> 7; s[21] = h6 >> 15; s[22] = (h6 >> 23) | (h7 << 3); s[23] = h7 >> 5; s[24] = h7 >> 13; s[25] = (h7 >> 21) | (h8 << 4); s[26] = h8 >> 4; s[27] = h8 >> 12; s[28] = (h8 >> 20) | (h9 << 6); s[29] = h9 >> 2; s[30] = h9 >> 10; s[31] = h9 >> 18; } /* * return 1 if f == 0 * return 0 if f != 0 * * Preconditions: * |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */ static const unsigned char zero[32]; int fe25519_iszero(const fe25519 *f) { int i,r=0; unsigned char s[32]; fe25519_pack(s,f); for(i=0;i<32;i++) r |= (1-fe25519_c_static_equal(zero[i],s[i])); return 1-r; } int fe25519_isone(const fe25519 *x) { return fe25519_iseq(x, &fe25519_one); } /* * return 1 if f is in {1,3,5,...,q-2} * return 0 if f is in {0,2,4,...,q-1} * * Preconditions: * |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */ int fe25519_isnegative(const fe25519 *f) { unsigned char s[32]; fe25519_pack(s,f); return s[0] & 1; } int fe25519_iseq(const fe25519 *x, const fe25519 *y) { fe25519 t; fe25519_sub(&t, x, y); return fe25519_iszero(&t); } int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y) { return fe25519_iseq(x, y); } /* * Replace (f,g) with (g,g) if b == 1; * replace (f,g) with (f,g) if b == 0. * * Preconditions: b in {0,1}. */ void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b) { int i; crypto_uint32 mask = b; mask = -mask; for(i=0;i<10;i++) r->v[i] ^= mask & (x->v[i] ^ r->v[i]); } /* * h = 1 */ void fe25519_setone(fe25519 *h) { h->v[0] = 1; h->v[1] = 0; h->v[2] = 0; h->v[3] = 0; h->v[4] = 0; h->v[5] = 0; h->v[6] = 0; h->v[7] = 0; h->v[8] = 0; h->v[9] = 0; } /* * h = 0 */ void fe25519_setzero(fe25519 *h) { h->v[0] = 0; h->v[1] = 0; h->v[2] = 0; h->v[3] = 0; h->v[4] = 0; h->v[5] = 0; h->v[6] = 0; h->v[7] = 0; h->v[8] = 0; h->v[9] = 0; } /* * h = -f * * Preconditions: * |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. * * Postconditions: * |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. */ void fe25519_neg(fe25519 *h, const fe25519 *f) { crypto_int32 f0 = f->v[0]; crypto_int32 f1 = f->v[1]; crypto_int32 f2 = f->v[2]; crypto_int32 f3 = f->v[3]; crypto_int32 f4 = f->v[4]; crypto_int32 f5 = f->v[5]; crypto_int32 f6 = f->v[6]; crypto_int32 f7 = f->v[7]; crypto_int32 f8 = f->v[8]; crypto_int32 f9 = f->v[9]; crypto_int32 h0 = -f0; crypto_int32 h1 = -f1; crypto_int32 h2 = -f2; crypto_int32 h3 = -f3; crypto_int32 h4 = -f4; crypto_int32 h5 = -f5; crypto_int32 h6 = -f6; crypto_int32 h7 = -f7; crypto_int32 h8 = -f8; crypto_int32 h9 = -f9; h->v[0] = h0; h->v[1] = h1; h->v[2] = h2; h->v[3] = h3; h->v[4] = h4; h->v[5] = h5; h->v[6] = h6; h->v[7] = h7; h->v[8] = h8; h->v[9] = h9; } unsigned char fe25519_getparity(const fe25519 *x) { return fe25519_isnegative(x); } /* * h = f + g * Can overlap h with f or g. * * Preconditions: * |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. * |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. * * Postconditions: * |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */ void fe25519_add(fe25519 *h,const fe25519 *f,const fe25519 *g) { crypto_int32 f0 = f->v[0]; crypto_int32 f1 = f->v[1]; crypto_int32 f2 = f->v[2]; crypto_int32 f3 = f->v[3]; crypto_int32 f4 = f->v[4]; crypto_int32 f5 = f->v[5]; crypto_int32 f6 = f->v[6]; crypto_int32 f7 = f->v[7]; crypto_int32 f8 = f->v[8]; crypto_int32 f9 = f->v[9]; crypto_int32 g0 = g->v[0]; crypto_int32 g1 = g->v[1]; crypto_int32 g2 = g->v[2]; crypto_int32 g3 = g->v[3]; crypto_int32 g4 = g->v[4]; crypto_int32 g5 = g->v[5]; crypto_int32 g6 = g->v[6]; crypto_int32 g7 = g->v[7]; crypto_int32 g8 = g->v[8]; crypto_int32 g9 = g->v[9]; crypto_int32 h0 = f0 + g0; crypto_int32 h1 = f1 + g1; crypto_int32 h2 = f2 + g2; crypto_int32 h3 = f3 + g3; crypto_int32 h4 = f4 + g4; crypto_int32 h5 = f5 + g5; crypto_int32 h6 = f6 + g6; crypto_int32 h7 = f7 + g7; crypto_int32 h8 = f8 + g8; crypto_int32 h9 = f9 + g9; h->v[0] = h0; h->v[1] = h1; h->v[2] = h2; h->v[3] = h3; h->v[4] = h4; h->v[5] = h5; h->v[6] = h6; h->v[7] = h7; h->v[8] = h8; h->v[9] = h9; } void fe25519_double(fe25519 *r, const fe25519 *x) { fe25519_add(r, x, x); } void fe25519_triple(fe25519 *r, const fe25519 *x) { fe25519_add(r, x, x); fe25519_add(r, r, x); } /* * h = f - g * Can overlap h with f or g. * * Preconditions: * |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. * |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. * * Postconditions: * |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */ void fe25519_sub(fe25519 *h,const fe25519 *f,const fe25519 *g) { crypto_int32 f0 = f->v[0]; crypto_int32 f1 = f->v[1]; crypto_int32 f2 = f->v[2]; crypto_int32 f3 = f->v[3]; crypto_int32 f4 = f->v[4]; crypto_int32 f5 = f->v[5]; crypto_int32 f6 = f->v[6]; crypto_int32 f7 = f->v[7]; crypto_int32 f8 = f->v[8]; crypto_int32 f9 = f->v[9]; crypto_int32 g0 = g->v[0]; crypto_int32 g1 = g->v[1]; crypto_int32 g2 = g->v[2]; crypto_int32 g3 = g->v[3]; crypto_int32 g4 = g->v[4]; crypto_int32 g5 = g->v[5]; crypto_int32 g6 = g->v[6]; crypto_int32 g7 = g->v[7]; crypto_int32 g8 = g->v[8]; crypto_int32 g9 = g->v[9]; crypto_int32 h0 = f0 - g0; crypto_int32 h1 = f1 - g1; crypto_int32 h2 = f2 - g2; crypto_int32 h3 = f3 - g3; crypto_int32 h4 = f4 - g4; crypto_int32 h5 = f5 - g5; crypto_int32 h6 = f6 - g6; crypto_int32 h7 = f7 - g7; crypto_int32 h8 = f8 - g8; crypto_int32 h9 = f9 - g9; h->v[0] = h0; h->v[1] = h1; h->v[2] = h2; h->v[3] = h3; h->v[4] = h4; h->v[5] = h5; h->v[6] = h6; h->v[7] = h7; h->v[8] = h8; h->v[9] = h9; } /* * h = f * g * Can overlap h with f or g. * * Preconditions: * |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. * |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. * * Postconditions: * |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. */ /* * Notes on implementation strategy: * * Using schoolbook multiplication. * Karatsuba would save a little in some cost models. * * Most multiplications by 2 and 19 are 32-bit precomputations; * cheaper than 64-bit postcomputations. * * There is one remaining multiplication by 19 in the carry chain; * one *19 precomputation can be merged into this, * but the resulting data flow is considerably less clean. * * There are 12 carries below. * 10 of them are 2-way parallelizable and vectorizable. * Can get away with 11 carries, but then data flow is much deeper. * * With tighter constraints on inputs can squeeze carries into int32. */ void fe25519_mul(fe25519 *h,const fe25519 *f,const fe25519 *g) { crypto_int32 f0 = f->v[0]; crypto_int32 f1 = f->v[1]; crypto_int32 f2 = f->v[2]; crypto_int32 f3 = f->v[3]; crypto_int32 f4 = f->v[4]; crypto_int32 f5 = f->v[5]; crypto_int32 f6 = f->v[6]; crypto_int32 f7 = f->v[7]; crypto_int32 f8 = f->v[8]; crypto_int32 f9 = f->v[9]; crypto_int32 g0 = g->v[0]; crypto_int32 g1 = g->v[1]; crypto_int32 g2 = g->v[2]; crypto_int32 g3 = g->v[3]; crypto_int32 g4 = g->v[4]; crypto_int32 g5 = g->v[5]; crypto_int32 g6 = g->v[6]; crypto_int32 g7 = g->v[7]; crypto_int32 g8 = g->v[8]; crypto_int32 g9 = g->v[9]; crypto_int32 g1_19 = 19 * g1; /* 1.959375*2^29 */ crypto_int32 g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ crypto_int32 g3_19 = 19 * g3; crypto_int32 g4_19 = 19 * g4; crypto_int32 g5_19 = 19 * g5; crypto_int32 g6_19 = 19 * g6; crypto_int32 g7_19 = 19 * g7; crypto_int32 g8_19 = 19 * g8; crypto_int32 g9_19 = 19 * g9; crypto_int32 f1_2 = 2 * f1; crypto_int32 f3_2 = 2 * f3; crypto_int32 f5_2 = 2 * f5; crypto_int32 f7_2 = 2 * f7; crypto_int32 f9_2 = 2 * f9; crypto_int64 f0g0 = f0 * (crypto_int64) g0; crypto_int64 f0g1 = f0 * (crypto_int64) g1; crypto_int64 f0g2 = f0 * (crypto_int64) g2; crypto_int64 f0g3 = f0 * (crypto_int64) g3; crypto_int64 f0g4 = f0 * (crypto_int64) g4; crypto_int64 f0g5 = f0 * (crypto_int64) g5; crypto_int64 f0g6 = f0 * (crypto_int64) g6; crypto_int64 f0g7 = f0 * (crypto_int64) g7; crypto_int64 f0g8 = f0 * (crypto_int64) g8; crypto_int64 f0g9 = f0 * (crypto_int64) g9; crypto_int64 f1g0 = f1 * (crypto_int64) g0; crypto_int64 f1g1_2 = f1_2 * (crypto_int64) g1; crypto_int64 f1g2 = f1 * (crypto_int64) g2; crypto_int64 f1g3_2 = f1_2 * (crypto_int64) g3; crypto_int64 f1g4 = f1 * (crypto_int64) g4; crypto_int64 f1g5_2 = f1_2 * (crypto_int64) g5; crypto_int64 f1g6 = f1 * (crypto_int64) g6; crypto_int64 f1g7_2 = f1_2 * (crypto_int64) g7; crypto_int64 f1g8 = f1 * (crypto_int64) g8; crypto_int64 f1g9_38 = f1_2 * (crypto_int64) g9_19; crypto_int64 f2g0 = f2 * (crypto_int64) g0; crypto_int64 f2g1 = f2 * (crypto_int64) g1; crypto_int64 f2g2 = f2 * (crypto_int64) g2; crypto_int64 f2g3 = f2 * (crypto_int64) g3; crypto_int64 f2g4 = f2 * (crypto_int64) g4; crypto_int64 f2g5 = f2 * (crypto_int64) g5; crypto_int64 f2g6 = f2 * (crypto_int64) g6; crypto_int64 f2g7 = f2 * (crypto_int64) g7; crypto_int64 f2g8_19 = f2 * (crypto_int64) g8_19; crypto_int64 f2g9_19 = f2 * (crypto_int64) g9_19; crypto_int64 f3g0 = f3 * (crypto_int64) g0; crypto_int64 f3g1_2 = f3_2 * (crypto_int64) g1; crypto_int64 f3g2 = f3 * (crypto_int64) g2; crypto_int64 f3g3_2 = f3_2 * (crypto_int64) g3; crypto_int64 f3g4 = f3 * (crypto_int64) g4; crypto_int64 f3g5_2 = f3_2 * (crypto_int64) g5; crypto_int64 f3g6 = f3 * (crypto_int64) g6; crypto_int64 f3g7_38 = f3_2 * (crypto_int64) g7_19; crypto_int64 f3g8_19 = f3 * (crypto_int64) g8_19; crypto_int64 f3g9_38 = f3_2 * (crypto_int64) g9_19; crypto_int64 f4g0 = f4 * (crypto_int64) g0; crypto_int64 f4g1 = f4 * (crypto_int64) g1; crypto_int64 f4g2 = f4 * (crypto_int64) g2; crypto_int64 f4g3 = f4 * (crypto_int64) g3; crypto_int64 f4g4 = f4 * (crypto_int64) g4; crypto_int64 f4g5 = f4 * (crypto_int64) g5; crypto_int64 f4g6_19 = f4 * (crypto_int64) g6_19; crypto_int64 f4g7_19 = f4 * (crypto_int64) g7_19; crypto_int64 f4g8_19 = f4 * (crypto_int64) g8_19; crypto_int64 f4g9_19 = f4 * (crypto_int64) g9_19; crypto_int64 f5g0 = f5 * (crypto_int64) g0; crypto_int64 f5g1_2 = f5_2 * (crypto_int64) g1; crypto_int64 f5g2 = f5 * (crypto_int64) g2; crypto_int64 f5g3_2 = f5_2 * (crypto_int64) g3; crypto_int64 f5g4 = f5 * (crypto_int64) g4; crypto_int64 f5g5_38 = f5_2 * (crypto_int64) g5_19; crypto_int64 f5g6_19 = f5 * (crypto_int64) g6_19; crypto_int64 f5g7_38 = f5_2 * (crypto_int64) g7_19; crypto_int64 f5g8_19 = f5 * (crypto_int64) g8_19; crypto_int64 f5g9_38 = f5_2 * (crypto_int64) g9_19; crypto_int64 f6g0 = f6 * (crypto_int64) g0; crypto_int64 f6g1 = f6 * (crypto_int64) g1; crypto_int64 f6g2 = f6 * (crypto_int64) g2; crypto_int64 f6g3 = f6 * (crypto_int64) g3; crypto_int64 f6g4_19 = f6 * (crypto_int64) g4_19; crypto_int64 f6g5_19 = f6 * (crypto_int64) g5_19; crypto_int64 f6g6_19 = f6 * (crypto_int64) g6_19; crypto_int64 f6g7_19 = f6 * (crypto_int64) g7_19; crypto_int64 f6g8_19 = f6 * (crypto_int64) g8_19; crypto_int64 f6g9_19 = f6 * (crypto_int64) g9_19; crypto_int64 f7g0 = f7 * (crypto_int64) g0; crypto_int64 f7g1_2 = f7_2 * (crypto_int64) g1; crypto_int64 f7g2 = f7 * (crypto_int64) g2; crypto_int64 f7g3_38 = f7_2 * (crypto_int64) g3_19; crypto_int64 f7g4_19 = f7 * (crypto_int64) g4_19; crypto_int64 f7g5_38 = f7_2 * (crypto_int64) g5_19; crypto_int64 f7g6_19 = f7 * (crypto_int64) g6_19; crypto_int64 f7g7_38 = f7_2 * (crypto_int64) g7_19; crypto_int64 f7g8_19 = f7 * (crypto_int64) g8_19; crypto_int64 f7g9_38 = f7_2 * (crypto_int64) g9_19; crypto_int64 f8g0 = f8 * (crypto_int64) g0; crypto_int64 f8g1 = f8 * (crypto_int64) g1; crypto_int64 f8g2_19 = f8 * (crypto_int64) g2_19; crypto_int64 f8g3_19 = f8 * (crypto_int64) g3_19; crypto_int64 f8g4_19 = f8 * (crypto_int64) g4_19; crypto_int64 f8g5_19 = f8 * (crypto_int64) g5_19; crypto_int64 f8g6_19 = f8 * (crypto_int64) g6_19; crypto_int64 f8g7_19 = f8 * (crypto_int64) g7_19; crypto_int64 f8g8_19 = f8 * (crypto_int64) g8_19; crypto_int64 f8g9_19 = f8 * (crypto_int64) g9_19; crypto_int64 f9g0 = f9 * (crypto_int64) g0; crypto_int64 f9g1_38 = f9_2 * (crypto_int64) g1_19; crypto_int64 f9g2_19 = f9 * (crypto_int64) g2_19; crypto_int64 f9g3_38 = f9_2 * (crypto_int64) g3_19; crypto_int64 f9g4_19 = f9 * (crypto_int64) g4_19; crypto_int64 f9g5_38 = f9_2 * (crypto_int64) g5_19; crypto_int64 f9g6_19 = f9 * (crypto_int64) g6_19; crypto_int64 f9g7_38 = f9_2 * (crypto_int64) g7_19; crypto_int64 f9g8_19 = f9 * (crypto_int64) g8_19; crypto_int64 f9g9_38 = f9_2 * (crypto_int64) g9_19; crypto_int64 h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38; crypto_int64 h1 = f0g1+f1g0 +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19; crypto_int64 h2 = f0g2+f1g1_2 +f2g0 +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38; crypto_int64 h3 = f0g3+f1g2 +f2g1 +f3g0 +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19; crypto_int64 h4 = f0g4+f1g3_2 +f2g2 +f3g1_2 +f4g0 +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38; crypto_int64 h5 = f0g5+f1g4 +f2g3 +f3g2 +f4g1 +f5g0 +f6g9_19+f7g8_19+f8g7_19+f9g6_19; crypto_int64 h6 = f0g6+f1g5_2 +f2g4 +f3g3_2 +f4g2 +f5g1_2 +f6g0 +f7g9_38+f8g8_19+f9g7_38; crypto_int64 h7 = f0g7+f1g6 +f2g5 +f3g4 +f4g3 +f5g2 +f6g1 +f7g0 +f8g9_19+f9g8_19; crypto_int64 h8 = f0g8+f1g7_2 +f2g6 +f3g5_2 +f4g4 +f5g3_2 +f6g2 +f7g1_2 +f8g0 +f9g9_38; crypto_int64 h9 = f0g9+f1g8 +f2g7 +f3g6 +f4g5 +f5g4 +f6g3 +f7g2 +f8g1 +f9g0 ; crypto_int64 carry0; crypto_int64 carry1; crypto_int64 carry2; crypto_int64 carry3; crypto_int64 carry4; crypto_int64 carry5; crypto_int64 carry6; crypto_int64 carry7; crypto_int64 carry8; crypto_int64 carry9; /* * |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38)) * i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8 * |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19)) * i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 */ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; /* |h0| <= 2^25 */ /* |h4| <= 2^25 */ /* |h1| <= 1.71*2^59 */ /* |h5| <= 1.71*2^59 */ carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; /* |h1| <= 2^24; from now on fits into int32 */ /* |h5| <= 2^24; from now on fits into int32 */ /* |h2| <= 1.41*2^60 */ /* |h6| <= 1.41*2^60 */ carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; /* |h2| <= 2^25; from now on fits into int32 unchanged */ /* |h6| <= 2^25; from now on fits into int32 unchanged */ /* |h3| <= 1.71*2^59 */ /* |h7| <= 1.71*2^59 */ carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; /* |h3| <= 2^24; from now on fits into int32 unchanged */ /* |h7| <= 2^24; from now on fits into int32 unchanged */ /* |h4| <= 1.72*2^34 */ /* |h8| <= 1.41*2^60 */ carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; /* |h4| <= 2^25; from now on fits into int32 unchanged */ /* |h8| <= 2^25; from now on fits into int32 unchanged */ /* |h5| <= 1.01*2^24 */ /* |h9| <= 1.71*2^59 */ carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; /* |h9| <= 2^24; from now on fits into int32 unchanged */ /* |h0| <= 1.1*2^39 */ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; /* |h0| <= 2^25; from now on fits into int32 unchanged */ /* |h1| <= 1.01*2^24 */ h->v[0] = h0; h->v[1] = h1; h->v[2] = h2; h->v[3] = h3; h->v[4] = h4; h->v[5] = h5; h->v[6] = h6; h->v[7] = h7; h->v[8] = h8; h->v[9] = h9; } /* * h = f * f * Can overlap h with f. * * Preconditions: * |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. * * Postconditions: * |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. */ void fe25519_square(fe25519 *h,const fe25519 *f) { crypto_int32 f0 = f->v[0]; crypto_int32 f1 = f->v[1]; crypto_int32 f2 = f->v[2]; crypto_int32 f3 = f->v[3]; crypto_int32 f4 = f->v[4]; crypto_int32 f5 = f->v[5]; crypto_int32 f6 = f->v[6]; crypto_int32 f7 = f->v[7]; crypto_int32 f8 = f->v[8]; crypto_int32 f9 = f->v[9]; crypto_int32 f0_2 = 2 * f0; crypto_int32 f1_2 = 2 * f1; crypto_int32 f2_2 = 2 * f2; crypto_int32 f3_2 = 2 * f3; crypto_int32 f4_2 = 2 * f4; crypto_int32 f5_2 = 2 * f5; crypto_int32 f6_2 = 2 * f6; crypto_int32 f7_2 = 2 * f7; crypto_int32 f5_38 = 38 * f5; /* 1.959375*2^30 */ crypto_int32 f6_19 = 19 * f6; /* 1.959375*2^30 */ crypto_int32 f7_38 = 38 * f7; /* 1.959375*2^30 */ crypto_int32 f8_19 = 19 * f8; /* 1.959375*2^30 */ crypto_int32 f9_38 = 38 * f9; /* 1.959375*2^30 */ crypto_int64 f0f0 = f0 * (crypto_int64) f0; crypto_int64 f0f1_2 = f0_2 * (crypto_int64) f1; crypto_int64 f0f2_2 = f0_2 * (crypto_int64) f2; crypto_int64 f0f3_2 = f0_2 * (crypto_int64) f3; crypto_int64 f0f4_2 = f0_2 * (crypto_int64) f4; crypto_int64 f0f5_2 = f0_2 * (crypto_int64) f5; crypto_int64 f0f6_2 = f0_2 * (crypto_int64) f6; crypto_int64 f0f7_2 = f0_2 * (crypto_int64) f7; crypto_int64 f0f8_2 = f0_2 * (crypto_int64) f8; crypto_int64 f0f9_2 = f0_2 * (crypto_int64) f9; crypto_int64 f1f1_2 = f1_2 * (crypto_int64) f1; crypto_int64 f1f2_2 = f1_2 * (crypto_int64) f2; crypto_int64 f1f3_4 = f1_2 * (crypto_int64) f3_2; crypto_int64 f1f4_2 = f1_2 * (crypto_int64) f4; crypto_int64 f1f5_4 = f1_2 * (crypto_int64) f5_2; crypto_int64 f1f6_2 = f1_2 * (crypto_int64) f6; crypto_int64 f1f7_4 = f1_2 * (crypto_int64) f7_2; crypto_int64 f1f8_2 = f1_2 * (crypto_int64) f8; crypto_int64 f1f9_76 = f1_2 * (crypto_int64) f9_38; crypto_int64 f2f2 = f2 * (crypto_int64) f2; crypto_int64 f2f3_2 = f2_2 * (crypto_int64) f3; crypto_int64 f2f4_2 = f2_2 * (crypto_int64) f4; crypto_int64 f2f5_2 = f2_2 * (crypto_int64) f5; crypto_int64 f2f6_2 = f2_2 * (crypto_int64) f6; crypto_int64 f2f7_2 = f2_2 * (crypto_int64) f7; crypto_int64 f2f8_38 = f2_2 * (crypto_int64) f8_19; crypto_int64 f2f9_38 = f2 * (crypto_int64) f9_38; crypto_int64 f3f3_2 = f3_2 * (crypto_int64) f3; crypto_int64 f3f4_2 = f3_2 * (crypto_int64) f4; crypto_int64 f3f5_4 = f3_2 * (crypto_int64) f5_2; crypto_int64 f3f6_2 = f3_2 * (crypto_int64) f6; crypto_int64 f3f7_76 = f3_2 * (crypto_int64) f7_38; crypto_int64 f3f8_38 = f3_2 * (crypto_int64) f8_19; crypto_int64 f3f9_76 = f3_2 * (crypto_int64) f9_38; crypto_int64 f4f4 = f4 * (crypto_int64) f4; crypto_int64 f4f5_2 = f4_2 * (crypto_int64) f5; crypto_int64 f4f6_38 = f4_2 * (crypto_int64) f6_19; crypto_int64 f4f7_38 = f4 * (crypto_int64) f7_38; crypto_int64 f4f8_38 = f4_2 * (crypto_int64) f8_19; crypto_int64 f4f9_38 = f4 * (crypto_int64) f9_38; crypto_int64 f5f5_38 = f5 * (crypto_int64) f5_38; crypto_int64 f5f6_38 = f5_2 * (crypto_int64) f6_19; crypto_int64 f5f7_76 = f5_2 * (crypto_int64) f7_38; crypto_int64 f5f8_38 = f5_2 * (crypto_int64) f8_19; crypto_int64 f5f9_76 = f5_2 * (crypto_int64) f9_38; crypto_int64 f6f6_19 = f6 * (crypto_int64) f6_19; crypto_int64 f6f7_38 = f6 * (crypto_int64) f7_38; crypto_int64 f6f8_38 = f6_2 * (crypto_int64) f8_19; crypto_int64 f6f9_38 = f6 * (crypto_int64) f9_38; crypto_int64 f7f7_38 = f7 * (crypto_int64) f7_38; crypto_int64 f7f8_38 = f7_2 * (crypto_int64) f8_19; crypto_int64 f7f9_76 = f7_2 * (crypto_int64) f9_38; crypto_int64 f8f8_19 = f8 * (crypto_int64) f8_19; crypto_int64 f8f9_38 = f8 * (crypto_int64) f9_38; crypto_int64 f9f9_38 = f9 * (crypto_int64) f9_38; crypto_int64 h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38; crypto_int64 h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38; crypto_int64 h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19; crypto_int64 h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38; crypto_int64 h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38; crypto_int64 h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38; crypto_int64 h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19; crypto_int64 h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; crypto_int64 h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; crypto_int64 h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; crypto_int64 carry0; crypto_int64 carry1; crypto_int64 carry2; crypto_int64 carry3; crypto_int64 carry4; crypto_int64 carry5; crypto_int64 carry6; crypto_int64 carry7; crypto_int64 carry8; crypto_int64 carry9; carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; h->v[0] = h0; h->v[1] = h1; h->v[2] = h2; h->v[3] = h3; h->v[4] = h4; h->v[5] = h5; h->v[6] = h6; h->v[7] = h7; h->v[8] = h8; h->v[9] = h9; } void fe25519_invert(fe25519 *out,const fe25519 *z) { fe25519 t0; fe25519 t1; fe25519 t2; fe25519 t3; int i; /* qhasm: fe z1 */ /* qhasm: fe z2 */ /* qhasm: fe z8 */ /* qhasm: fe z9 */ /* qhasm: fe z11 */ /* qhasm: fe z22 */ /* qhasm: fe z_5_0 */ /* qhasm: fe z_10_5 */ /* qhasm: fe z_10_0 */ /* qhasm: fe z_20_10 */ /* qhasm: fe z_20_0 */ /* qhasm: fe z_40_20 */ /* qhasm: fe z_40_0 */ /* qhasm: fe z_50_10 */ /* qhasm: fe z_50_0 */ /* qhasm: fe z_100_50 */ /* qhasm: fe z_100_0 */ /* qhasm: fe z_200_100 */ /* qhasm: fe z_200_0 */ /* qhasm: fe z_250_50 */ /* qhasm: fe z_250_0 */ /* qhasm: fe z_255_5 */ /* qhasm: fe z_255_21 */ /* qhasm: enter pow225521 */ /* qhasm: z2 = z1^2^1 */ /* asm 1: fe25519_square(>z2=fe#1,z2=fe#1,>z2=fe#1); */ /* asm 2: fe25519_square(>z2=&t0,z2=&t0,>z2=&t0); */ fe25519_square(&t0,z); for (i = 1;i < 1;++i) fe25519_square(&t0,&t0); /* qhasm: z8 = z2^2^2 */ /* asm 1: fe25519_square(>z8=fe#2,z8=fe#2,>z8=fe#2); */ /* asm 2: fe25519_square(>z8=&t1,z8=&t1,>z8=&t1); */ fe25519_square(&t1,&t0); for (i = 1;i < 2;++i) fe25519_square(&t1,&t1); /* qhasm: z9 = z1*z8 */ /* asm 1: fe25519_mul(>z9=fe#2,z9=&t1,z11=fe#1,z11=&t0,z22=fe#3,z22=fe#3,>z22=fe#3); */ /* asm 2: fe25519_square(>z22=&t2,z22=&t2,>z22=&t2); */ fe25519_square(&t2,&t0); for (i = 1;i < 1;++i) fe25519_square(&t2,&t2); /* qhasm: z_5_0 = z9*z22 */ /* asm 1: fe25519_mul(>z_5_0=fe#2,z_5_0=&t1,z_10_5=fe#3,z_10_5=fe#3,>z_10_5=fe#3); */ /* asm 2: fe25519_square(>z_10_5=&t2,z_10_5=&t2,>z_10_5=&t2); */ fe25519_square(&t2,&t1); for (i = 1;i < 5;++i) fe25519_square(&t2,&t2); /* qhasm: z_10_0 = z_10_5*z_5_0 */ /* asm 1: fe25519_mul(>z_10_0=fe#2,z_10_0=&t1,z_20_10=fe#3,z_20_10=fe#3,>z_20_10=fe#3); */ /* asm 2: fe25519_square(>z_20_10=&t2,z_20_10=&t2,>z_20_10=&t2); */ fe25519_square(&t2,&t1); for (i = 1;i < 10;++i) fe25519_square(&t2,&t2); /* qhasm: z_20_0 = z_20_10*z_10_0 */ /* asm 1: fe25519_mul(>z_20_0=fe#3,z_20_0=&t2,z_40_20=fe#4,z_40_20=fe#4,>z_40_20=fe#4); */ /* asm 2: fe25519_square(>z_40_20=&t3,z_40_20=&t3,>z_40_20=&t3); */ fe25519_square(&t3,&t2); for (i = 1;i < 20;++i) fe25519_square(&t3,&t3); /* qhasm: z_40_0 = z_40_20*z_20_0 */ /* asm 1: fe25519_mul(>z_40_0=fe#3,z_40_0=&t2,z_50_10=fe#3,z_50_10=fe#3,>z_50_10=fe#3); */ /* asm 2: fe25519_square(>z_50_10=&t2,z_50_10=&t2,>z_50_10=&t2); */ fe25519_square(&t2,&t2); for (i = 1;i < 10;++i) fe25519_square(&t2,&t2); /* qhasm: z_50_0 = z_50_10*z_10_0 */ /* asm 1: fe25519_mul(>z_50_0=fe#2,z_50_0=&t1,z_100_50=fe#3,z_100_50=fe#3,>z_100_50=fe#3); */ /* asm 2: fe25519_square(>z_100_50=&t2,z_100_50=&t2,>z_100_50=&t2); */ fe25519_square(&t2,&t1); for (i = 1;i < 50;++i) fe25519_square(&t2,&t2); /* qhasm: z_100_0 = z_100_50*z_50_0 */ /* asm 1: fe25519_mul(>z_100_0=fe#3,z_100_0=&t2,z_200_100=fe#4,z_200_100=fe#4,>z_200_100=fe#4); */ /* asm 2: fe25519_square(>z_200_100=&t3,z_200_100=&t3,>z_200_100=&t3); */ fe25519_square(&t3,&t2); for (i = 1;i < 100;++i) fe25519_square(&t3,&t3); /* qhasm: z_200_0 = z_200_100*z_100_0 */ /* asm 1: fe25519_mul(>z_200_0=fe#3,z_200_0=&t2,z_250_50=fe#3,z_250_50=fe#3,>z_250_50=fe#3); */ /* asm 2: fe25519_square(>z_250_50=&t2,z_250_50=&t2,>z_250_50=&t2); */ fe25519_square(&t2,&t2); for (i = 1;i < 50;++i) fe25519_square(&t2,&t2); /* qhasm: z_250_0 = z_250_50*z_50_0 */ /* asm 1: fe25519_mul(>z_250_0=fe#2,z_250_0=&t1,z_255_5=fe#2,z_255_5=fe#2,>z_255_5=fe#2); */ /* asm 2: fe25519_square(>z_255_5=&t1,z_255_5=&t1,>z_255_5=&t1); */ fe25519_square(&t1,&t1); for (i = 1;i < 5;++i) fe25519_square(&t1,&t1); /* qhasm: z_255_21 = z_255_5*z11 */ /* asm 1: fe25519_mul(>z_255_21=fe#12,z_255_21=out,z2=fe#1,z2=fe#1,>z2=fe#1); */ /* asm 2: fe25519_square(>z2=&t0,z2=&t0,>z2=&t0); */ fe25519_square(&t0,z); for (i = 1;i < 1;++i) fe25519_square(&t0,&t0); /* qhasm: z8 = z2^2^2 */ /* asm 1: fe25519_square(>z8=fe#2,z8=fe#2,>z8=fe#2); */ /* asm 2: fe25519_square(>z8=&t1,z8=&t1,>z8=&t1); */ fe25519_square(&t1,&t0); for (i = 1;i < 2;++i) fe25519_square(&t1,&t1); /* qhasm: z9 = z1*z8 */ /* asm 1: fe25519_mul(>z9=fe#2,z9=&t1,z11=fe#1,z11=&t0,z22=fe#1,z22=fe#1,>z22=fe#1); */ /* asm 2: fe25519_square(>z22=&t0,z22=&t0,>z22=&t0); */ fe25519_square(&t0,&t0); for (i = 1;i < 1;++i) fe25519_square(&t0,&t0); /* qhasm: z_5_0 = z9*z22 */ /* asm 1: fe25519_mul(>z_5_0=fe#1,z_5_0=&t0,z_10_5=fe#2,z_10_5=fe#2,>z_10_5=fe#2); */ /* asm 2: fe25519_square(>z_10_5=&t1,z_10_5=&t1,>z_10_5=&t1); */ fe25519_square(&t1,&t0); for (i = 1;i < 5;++i) fe25519_square(&t1,&t1); /* qhasm: z_10_0 = z_10_5*z_5_0 */ /* asm 1: fe25519_mul(>z_10_0=fe#1,z_10_0=&t0,z_20_10=fe#2,z_20_10=fe#2,>z_20_10=fe#2); */ /* asm 2: fe25519_square(>z_20_10=&t1,z_20_10=&t1,>z_20_10=&t1); */ fe25519_square(&t1,&t0); for (i = 1;i < 10;++i) fe25519_square(&t1,&t1); /* qhasm: z_20_0 = z_20_10*z_10_0 */ /* asm 1: fe25519_mul(>z_20_0=fe#2,z_20_0=&t1,z_40_20=fe#3,z_40_20=fe#3,>z_40_20=fe#3); */ /* asm 2: fe25519_square(>z_40_20=&t2,z_40_20=&t2,>z_40_20=&t2); */ fe25519_square(&t2,&t1); for (i = 1;i < 20;++i) fe25519_square(&t2,&t2); /* qhasm: z_40_0 = z_40_20*z_20_0 */ /* asm 1: fe25519_mul(>z_40_0=fe#2,z_40_0=&t1,z_50_10=fe#2,z_50_10=fe#2,>z_50_10=fe#2); */ /* asm 2: fe25519_square(>z_50_10=&t1,z_50_10=&t1,>z_50_10=&t1); */ fe25519_square(&t1,&t1); for (i = 1;i < 10;++i) fe25519_square(&t1,&t1); /* qhasm: z_50_0 = z_50_10*z_10_0 */ /* asm 1: fe25519_mul(>z_50_0=fe#1,z_50_0=&t0,z_100_50=fe#2,z_100_50=fe#2,>z_100_50=fe#2); */ /* asm 2: fe25519_square(>z_100_50=&t1,z_100_50=&t1,>z_100_50=&t1); */ fe25519_square(&t1,&t0); for (i = 1;i < 50;++i) fe25519_square(&t1,&t1); /* qhasm: z_100_0 = z_100_50*z_50_0 */ /* asm 1: fe25519_mul(>z_100_0=fe#2,z_100_0=&t1,z_200_100=fe#3,z_200_100=fe#3,>z_200_100=fe#3); */ /* asm 2: fe25519_square(>z_200_100=&t2,z_200_100=&t2,>z_200_100=&t2); */ fe25519_square(&t2,&t1); for (i = 1;i < 100;++i) fe25519_square(&t2,&t2); /* qhasm: z_200_0 = z_200_100*z_100_0 */ /* asm 1: fe25519_mul(>z_200_0=fe#2,z_200_0=&t1,z_250_50=fe#2,z_250_50=fe#2,>z_250_50=fe#2); */ /* asm 2: fe25519_square(>z_250_50=&t1,z_250_50=&t1,>z_250_50=&t1); */ fe25519_square(&t1,&t1); for (i = 1;i < 50;++i) fe25519_square(&t1,&t1); /* qhasm: z_250_0 = z_250_50*z_50_0 */ /* asm 1: fe25519_mul(>z_250_0=fe#1,z_250_0=&t0,z_252_2=fe#1,z_252_2=fe#1,>z_252_2=fe#1); */ /* asm 2: fe25519_square(>z_252_2=&t0,z_252_2=&t0,>z_252_2=&t0); */ fe25519_square(&t0,&t0); for (i = 1;i < 2;++i) fe25519_square(&t0,&t0); /* qhasm: z_252_3 = z_252_2*z1 */ /* asm 1: fe25519_mul(>z_252_3=fe#12,z_252_3=out,v[0]; crypto_int32 f1 = f->v[1]; crypto_int32 f2 = f->v[2]; crypto_int32 f3 = f->v[3]; crypto_int32 f4 = f->v[4]; crypto_int32 f5 = f->v[5]; crypto_int32 f6 = f->v[6]; crypto_int32 f7 = f->v[7]; crypto_int32 f8 = f->v[8]; crypto_int32 f9 = f->v[9]; crypto_int32 f0_2 = 2 * f0; crypto_int32 f1_2 = 2 * f1; crypto_int32 f2_2 = 2 * f2; crypto_int32 f3_2 = 2 * f3; crypto_int32 f4_2 = 2 * f4; crypto_int32 f5_2 = 2 * f5; crypto_int32 f6_2 = 2 * f6; crypto_int32 f7_2 = 2 * f7; crypto_int32 f5_38 = 38 * f5; /* 1.959375*2^30 */ crypto_int32 f6_19 = 19 * f6; /* 1.959375*2^30 */ crypto_int32 f7_38 = 38 * f7; /* 1.959375*2^30 */ crypto_int32 f8_19 = 19 * f8; /* 1.959375*2^30 */ crypto_int32 f9_38 = 38 * f9; /* 1.959375*2^30 */ crypto_int64 f0f0 = f0 * (crypto_int64) f0; crypto_int64 f0f1_2 = f0_2 * (crypto_int64) f1; crypto_int64 f0f2_2 = f0_2 * (crypto_int64) f2; crypto_int64 f0f3_2 = f0_2 * (crypto_int64) f3; crypto_int64 f0f4_2 = f0_2 * (crypto_int64) f4; crypto_int64 f0f5_2 = f0_2 * (crypto_int64) f5; crypto_int64 f0f6_2 = f0_2 * (crypto_int64) f6; crypto_int64 f0f7_2 = f0_2 * (crypto_int64) f7; crypto_int64 f0f8_2 = f0_2 * (crypto_int64) f8; crypto_int64 f0f9_2 = f0_2 * (crypto_int64) f9; crypto_int64 f1f1_2 = f1_2 * (crypto_int64) f1; crypto_int64 f1f2_2 = f1_2 * (crypto_int64) f2; crypto_int64 f1f3_4 = f1_2 * (crypto_int64) f3_2; crypto_int64 f1f4_2 = f1_2 * (crypto_int64) f4; crypto_int64 f1f5_4 = f1_2 * (crypto_int64) f5_2; crypto_int64 f1f6_2 = f1_2 * (crypto_int64) f6; crypto_int64 f1f7_4 = f1_2 * (crypto_int64) f7_2; crypto_int64 f1f8_2 = f1_2 * (crypto_int64) f8; crypto_int64 f1f9_76 = f1_2 * (crypto_int64) f9_38; crypto_int64 f2f2 = f2 * (crypto_int64) f2; crypto_int64 f2f3_2 = f2_2 * (crypto_int64) f3; crypto_int64 f2f4_2 = f2_2 * (crypto_int64) f4; crypto_int64 f2f5_2 = f2_2 * (crypto_int64) f5; crypto_int64 f2f6_2 = f2_2 * (crypto_int64) f6; crypto_int64 f2f7_2 = f2_2 * (crypto_int64) f7; crypto_int64 f2f8_38 = f2_2 * (crypto_int64) f8_19; crypto_int64 f2f9_38 = f2 * (crypto_int64) f9_38; crypto_int64 f3f3_2 = f3_2 * (crypto_int64) f3; crypto_int64 f3f4_2 = f3_2 * (crypto_int64) f4; crypto_int64 f3f5_4 = f3_2 * (crypto_int64) f5_2; crypto_int64 f3f6_2 = f3_2 * (crypto_int64) f6; crypto_int64 f3f7_76 = f3_2 * (crypto_int64) f7_38; crypto_int64 f3f8_38 = f3_2 * (crypto_int64) f8_19; crypto_int64 f3f9_76 = f3_2 * (crypto_int64) f9_38; crypto_int64 f4f4 = f4 * (crypto_int64) f4; crypto_int64 f4f5_2 = f4_2 * (crypto_int64) f5; crypto_int64 f4f6_38 = f4_2 * (crypto_int64) f6_19; crypto_int64 f4f7_38 = f4 * (crypto_int64) f7_38; crypto_int64 f4f8_38 = f4_2 * (crypto_int64) f8_19; crypto_int64 f4f9_38 = f4 * (crypto_int64) f9_38; crypto_int64 f5f5_38 = f5 * (crypto_int64) f5_38; crypto_int64 f5f6_38 = f5_2 * (crypto_int64) f6_19; crypto_int64 f5f7_76 = f5_2 * (crypto_int64) f7_38; crypto_int64 f5f8_38 = f5_2 * (crypto_int64) f8_19; crypto_int64 f5f9_76 = f5_2 * (crypto_int64) f9_38; crypto_int64 f6f6_19 = f6 * (crypto_int64) f6_19; crypto_int64 f6f7_38 = f6 * (crypto_int64) f7_38; crypto_int64 f6f8_38 = f6_2 * (crypto_int64) f8_19; crypto_int64 f6f9_38 = f6 * (crypto_int64) f9_38; crypto_int64 f7f7_38 = f7 * (crypto_int64) f7_38; crypto_int64 f7f8_38 = f7_2 * (crypto_int64) f8_19; crypto_int64 f7f9_76 = f7_2 * (crypto_int64) f9_38; crypto_int64 f8f8_19 = f8 * (crypto_int64) f8_19; crypto_int64 f8f9_38 = f8 * (crypto_int64) f9_38; crypto_int64 f9f9_38 = f9 * (crypto_int64) f9_38; crypto_int64 h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38; crypto_int64 h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38; crypto_int64 h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19; crypto_int64 h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38; crypto_int64 h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38; crypto_int64 h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38; crypto_int64 h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19; crypto_int64 h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; crypto_int64 h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; crypto_int64 h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; crypto_int64 carry0; crypto_int64 carry1; crypto_int64 carry2; crypto_int64 carry3; crypto_int64 carry4; crypto_int64 carry5; crypto_int64 carry6; crypto_int64 carry7; crypto_int64 carry8; crypto_int64 carry9; h0 += h0; h1 += h1; h2 += h2; h3 += h3; h4 += h4; h5 += h5; h6 += h6; h7 += h7; h8 += h8; h9 += h9; carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; h->v[0] = h0; h->v[1] = h1; h->v[2] = h2; h->v[3] = h3; h->v[4] = h4; h->v[5] = h5; h->v[6] = h6; h->v[7] = h7; h->v[8] = h8; h->v[9] = h9; } void fe25519_sqrt(fe25519 *r, const fe25519 *x) { fe25519 t; fe25519_invsqrt(&t, x); fe25519_mul(r, &t, x); } void fe25519_invsqrt(fe25519 *r, const fe25519 *x) { fe25519 den2, den3, den4, den6, chk, t; fe25519_square(&den2, x); fe25519_mul(&den3, &den2, x); fe25519_square(&den4, &den2); fe25519_mul(&den6, &den2, &den4); fe25519_mul(&t, &den6, x); // r is now x^7 fe25519_pow2523(&t, &t); fe25519_mul(&t, &t, &den3); fe25519_square(&chk, &t); fe25519_mul(&chk, &chk, x); if(!fe25519_isone(&chk)) //XXX: Make constant time fe25519_mul(&t, &t, &fe25519_sqrtm1); *r = t; } // -- group.c -- /* * Arithmetic on the twisted Edwards curve -x^2 + y^2 = 1 + dx^2y^2 * with d = -(121665/121666) = 37095705934669439343138083508754565189542113879843219016388785533085940283555 * Base point: (15112221349535400772501151409588531511454012693041857206046113283949847762202,46316835694926478169428394003475163141307993866256225615783033603165251855960); */ static const fe25519 ge25519_ecd = {{-10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116}}; static const fe25519 ge25519_ec2d = {{-21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199}}; static const fe25519 ge25519_magic = {{-6111485, -4156064, 27798727, -12243468, 25904040, -120897, -20826367, 7060776, -6093568, 1986012}}; const group_ge group_ge_neutral = {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}; #define ge25519_p3 group_ge typedef struct { fe25519 x; fe25519 z; fe25519 y; fe25519 t; } ge25519_p1p1; typedef struct { fe25519 x; fe25519 y; fe25519 z; } ge25519_p2; typedef struct { fe25519 x; fe25519 y; } ge25519_aff; /* Multiples of the base point in affine representation */ static const ge25519_aff ge25519_base_multiples_affine[425] = { #include "base_multiples.data" }; static void ge25519_mixadd2(ge25519_p3 *r, const ge25519_aff *q) { fe25519 a,b,t1,t2,c,d,e,f,g,h,qt; fe25519_mul(&qt, &q->x, &q->y); fe25519_sub(&a, &r->y, &r->x); /* A = (Y1-X1)*(Y2-X2) */ fe25519_add(&b, &r->y, &r->x); /* B = (Y1+X1)*(Y2+X2) */ fe25519_sub(&t1, &q->y, &q->x); fe25519_add(&t2, &q->y, &q->x); fe25519_mul(&a, &a, &t1); fe25519_mul(&b, &b, &t2); fe25519_sub(&e, &b, &a); /* E = B-A */ fe25519_add(&h, &b, &a); /* H = B+A */ fe25519_mul(&c, &r->t, &qt); /* C = T1*k*T2 */ fe25519_mul(&c, &c, &ge25519_ec2d); fe25519_add(&d, &r->z, &r->z); /* D = Z1*2 */ fe25519_sub(&f, &d, &c); /* F = D-C */ fe25519_add(&g, &d, &c); /* G = D+C */ fe25519_mul(&r->x, &e, &f); fe25519_mul(&r->y, &h, &g); fe25519_mul(&r->z, &g, &f); fe25519_mul(&r->t, &e, &h); } static void p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p) { fe25519_mul(&r->x, &p->x, &p->t); fe25519_mul(&r->y, &p->y, &p->z); fe25519_mul(&r->z, &p->z, &p->t); } static void p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p) { p1p1_to_p2((ge25519_p2 *)r, p); fe25519_mul(&r->t, &p->x, &p->y); } static void add_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_p3 *q) { fe25519 a, b, c, d, t; fe25519_sub(&a, &p->y, &p->x); /* A = (Y1-X1)*(Y2-X2) */ fe25519_sub(&t, &q->y, &q->x); fe25519_mul(&a, &a, &t); fe25519_add(&b, &p->x, &p->y); /* B = (Y1+X1)*(Y2+X2) */ fe25519_add(&t, &q->x, &q->y); fe25519_mul(&b, &b, &t); fe25519_mul(&c, &p->t, &q->t); /* C = T1*k*T2 */ fe25519_mul(&c, &c, &ge25519_ec2d); fe25519_mul(&d, &p->z, &q->z); /* D = Z1*2*Z2 */ fe25519_add(&d, &d, &d); fe25519_sub(&r->x, &b, &a); /* E = B-A */ fe25519_sub(&r->t, &d, &c); /* F = D-C */ fe25519_add(&r->z, &d, &c); /* G = D+C */ fe25519_add(&r->y, &b, &a); /* H = B+A */ } /* See http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd */ static void dbl_p1p1(ge25519_p1p1 *r, const ge25519_p2 *p) { fe25519 a,b,c,d; fe25519_square(&a, &p->x); fe25519_square(&b, &p->y); fe25519_square_double(&c, &p->z); fe25519_neg(&d, &a); fe25519_add(&r->x, &p->x, &p->y); fe25519_square(&r->x, &r->x); fe25519_sub(&r->x, &r->x, &a); fe25519_sub(&r->x, &r->x, &b); fe25519_add(&r->z, &d, &b); fe25519_sub(&r->t, &r->z, &c); fe25519_sub(&r->y, &d, &b); } /* Constant-time version of: if(b) r = p */ static void cmov_aff(ge25519_aff *r, const ge25519_aff *p, unsigned char b) { fe25519_cmov(&r->x, &p->x, b); fe25519_cmov(&r->y, &p->y, b); } static unsigned char group_c_static_equal(signed char b,signed char c) { unsigned char ub = b; unsigned char uc = c; unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ crypto_uint32 y = x; /* 0: yes; 1..255: no */ y -= 1; /* 4294967295: yes; 0..254: no */ y >>= 31; /* 1: yes; 0: no */ return y; } static unsigned char negative(signed char b) { unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ x >>= 63; /* 1: yes; 0: no */ return x; } static void choose_t_aff(ge25519_aff *t, unsigned long long pos, signed char b) { fe25519 v; *t = ge25519_base_multiples_affine[5*pos+0]; cmov_aff(t, &ge25519_base_multiples_affine[5*pos+1],group_c_static_equal(b,1) | group_c_static_equal(b,-1)); cmov_aff(t, &ge25519_base_multiples_affine[5*pos+2],group_c_static_equal(b,2) | group_c_static_equal(b,-2)); cmov_aff(t, &ge25519_base_multiples_affine[5*pos+3],group_c_static_equal(b,3) | group_c_static_equal(b,-3)); cmov_aff(t, &ge25519_base_multiples_affine[5*pos+4],group_c_static_equal(b,-4)); fe25519_neg(&v, &t->x); fe25519_cmov(&t->x, &v, negative(b)); } static void choose_t(group_ge *t, const group_ge *pre, signed char b) { fe25519 v; signed char j; unsigned char c; *t = pre[0]; for(j=1;j<=16;j++) { c = group_c_static_equal(b,j) | group_c_static_equal(-b,j); fe25519_cmov(&t->x, &pre[j].x,c); fe25519_cmov(&t->y, &pre[j].y,c); fe25519_cmov(&t->z, &pre[j].z,c); fe25519_cmov(&t->t, &pre[j].t,c); } fe25519_neg(&v, &t->x); fe25519_cmov(&t->x, &v, negative(b)); fe25519_neg(&v, &t->t); fe25519_cmov(&t->t, &v, negative(b)); } // ================================================================================== // API FUNCTIONS // ================================================================================== /* const group_ge group_ge_base = {{{133, 0, 0, 37120, 137, 0, 0, 42983, 58, 0, 7808, 5998, 12, 49152, 49039, 1015}}, {{65422, 65535, 65535, 5631, 65418, 65535, 65535, 47417, 65485, 65535, 12031, 41670, 65525, 32767, 42226, 8491}}, {{65422, 65535, 65535, 5631, 65418, 65535, 65535, 47417, 65485, 65535, 12031, 41670, 65525, 32767, 42226, 8491}}}; */ const group_ge group_ge_base = {{{-14297830, -7645148, 16144683, -16471763, 27570974, -2696100, -26142465, 8378389, 20764389, 8758491}}, {{-26843541, -6710886, 13421773, -13421773, 26843546, 6710886, -13421773, 13421773, -26843546, -6710886}}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {{28827062, -6116119, -27349572, 244363, 8635006, 11264893, 19351346, 13413597, 16611511, -6414980}}}; int group_ge_unpack(group_ge *r, const unsigned char x[GROUP_GE_PACKEDBYTES]) { fe25519 s, s2, chk, yden, ynum, yden2, xden2, isr, xdeninv, ydeninv, t; int ret; unsigned char b; fe25519_unpack(&s, x); /* s = cls.bytesToGf(s,mustBePositive=True) */ ret = fe25519_isnegative(&s); /* yden = 1-a*s^2 // 1+s^2 */ /* ynum = 1+a*s^2 // 1-s^2 */ fe25519_square(&s2, &s); fe25519_add(&yden,&fe25519_one,&s2); fe25519_sub(&ynum,&fe25519_one,&s2); /* yden_sqr = yden^2 */ /* xden_sqr = a*d*ynum^2 - yden_sqr */ fe25519_square(&yden2, &yden); fe25519_square(&xden2, &ynum); fe25519_mul(&xden2, &xden2, &ge25519_ecd); // d*ynum^2 fe25519_add(&xden2, &xden2, &yden2); // d*ynum2+yden2 fe25519_neg(&xden2, &xden2); // -d*ynum2-yden2 /* isr = isqrt(xden_sqr * yden_sqr) */ fe25519_mul(&t, &xden2, &yden2); fe25519_invsqrt(&isr, &t); //Check inverse square root! fe25519_square(&chk, &isr); fe25519_mul(&chk, &chk, &t); ret |= !fe25519_isone(&chk); /* xden_inv = isr * yden */ fe25519_mul(&xdeninv, &isr, &yden); /* yden_inv = xden_inv * isr * xden_sqr */ fe25519_mul(&ydeninv, &xdeninv, &isr); fe25519_mul(&ydeninv, &ydeninv, &xden2); /* x = 2*s*xden_inv */ fe25519_mul(&r->x, &s, &xdeninv); fe25519_double(&r->x, &r->x); /* if negative(x): x = -x */ b = fe25519_isnegative(&r->x); fe25519_neg(&t, &r->x); fe25519_cmov(&r->x, &t, b); /* y = ynum * yden_inv */ fe25519_mul(&r->y, &ynum, &ydeninv); r->z = fe25519_one; /* if cls.cofactor==8 and (negative(x*y) or y==0): raise InvalidEncodingException("x*y is invalid: %d, %d" % (x,y)) */ fe25519_mul(&r->t, &r->x, &r->y); ret |= fe25519_isnegative(&r->t); ret |= fe25519_iszero(&r->y); // Zero all coordinates of point for invalid input; produce invalid point fe25519_cmov(&r->x, &fe25519_zero, ret); fe25519_cmov(&r->y, &fe25519_zero, ret); fe25519_cmov(&r->z, &fe25519_zero, ret); fe25519_cmov(&r->t, &fe25519_zero, ret); return -ret; } // Return x if x is positive, else return -x. void fe25519_abs(fe25519* x, const fe25519* y) { fe25519 negY; *x = *y; fe25519_neg(&negY, y); fe25519_cmov(x, &negY, fe25519_isnegative(x)); } // Sets r to sqrt(x) or sqrt(i * x). Returns 1 if x is a square. int fe25519_sqrti(fe25519 *r, const fe25519 *x) { int b; fe25519 t, corr; b = fe25519_invsqrti(&t, x); fe25519_setone(&corr); fe25519_cmov(&corr, &fe25519_sqrtm1, 1 - b); fe25519_mul(&t, &t, &corr); fe25519_mul(r, &t, x); return b; } // Sets r to 1/sqrt(x) or 1/sqrt(i*x). Returns whether x was a square. int fe25519_invsqrti(fe25519 *r, const fe25519 *x) { int inCaseA, inCaseB, inCaseD; fe25519 den2, den3, den4, den6, chk, t, corr; fe25519_square(&den2, x); fe25519_mul(&den3, &den2, x); fe25519_square(&den4, &den2); fe25519_mul(&den6, &den2, &den4); fe25519_mul(&t, &den6, x); // r is now x^7 fe25519_pow2523(&t, &t); fe25519_mul(&t, &t, &den3); // case A B C D // --------------------------------------------------------------- // t 1/sqrt(x) -i/sqrt(x) 1/sqrt(i*x) -i/sqrt(i*x) // chk 1 -1 -i i // corr 1 i 1 i // ret 1 1 0 0 fe25519_square(&chk, &t); fe25519_mul(&chk, &chk, x); inCaseA = fe25519_isone(&chk); inCaseD = fe25519_iseq(&chk, &fe25519_sqrtm1); fe25519_neg(&chk, &chk); inCaseB = fe25519_isone(&chk); fe25519_setone(&corr); fe25519_cmov(&corr, &fe25519_sqrtm1, inCaseB + inCaseD); fe25519_mul(&t, &t, &corr); *r = t; return inCaseA + inCaseB; } void group_ge_pack(unsigned char r[GROUP_GE_PACKEDBYTES], const group_ge *x) { fe25519 d, u1, u2, isr, i1, i2, zinv, deninv, nx, ny, s; unsigned char b; /* u1 = mneg*(z+y)*(z-y) */ fe25519_add(&d, &x->z, &x->y); fe25519_sub(&u1, &x->z, &x->y); fe25519_mul(&u1, &u1, &d); /* u2 = x*y # = t*z */ fe25519_mul(&u2, &x->x, &x->y); /* isr = isqrt(u1*u2^2) */ fe25519_square(&isr, &u2); fe25519_mul(&isr, &isr, &u1); fe25519_invsqrt(&isr, &isr); /* i1 = isr*u1 # sqrt(mneg*(z+y)*(z-y))/(x*y) */ fe25519_mul(&i1, &isr, &u1); /* i2 = isr*u2 # 1/sqrt(a*(y+z)*(y-z)) */ fe25519_mul(&i2, &isr, &u2); /* z_inv = i1*i2*t # 1/z */ fe25519_mul(&zinv, &i1, &i2); fe25519_mul(&zinv, &zinv, &x->t); /* if negative(t*z_inv): x,y = y*self.i,x*self.i den_inv = self.magic * i1 */ fe25519_mul(&d, &zinv, &x->t); b = !fe25519_isnegative(&d); fe25519_mul(&nx, &x->y, &fe25519_sqrtm1); fe25519_mul(&ny, &x->x, &fe25519_sqrtm1); fe25519_mul(&deninv, &ge25519_magic, &i1); fe25519_cmov(&nx, &x->x, b); fe25519_cmov(&ny, &x->y, b); fe25519_cmov(&deninv, &i2, b); /* if negative(x*z_inv): y = -y */ fe25519_mul(&d, &nx, &zinv); b = fe25519_isnegative(&d); fe25519_neg(&d, &ny); fe25519_cmov(&ny, &d, b); /* s = (z-y) * den_inv */ fe25519_sub(&s, &x->z, &ny); fe25519_mul(&s, &s, &deninv); /* return self.gfToBytes(s,mustBePositive=True) */ b = fe25519_isnegative(&s); fe25519_neg(&d, &s); fe25519_cmov(&s, &d, b); fe25519_pack(r, &s); } void group_ge_add(group_ge *r, const group_ge *x, const group_ge *y) { ge25519_p1p1 t; add_p1p1(&t, x, y); p1p1_to_p3(r,&t); } void group_ge_double(group_ge *r, const group_ge *x) { ge25519_p1p1 t; dbl_p1p1(&t, (ge25519_p2 *)x); p1p1_to_p3(r,&t); } void group_ge_negate(group_ge *r, const group_ge *x) { fe25519_neg(&r->x, &x->x); r->y = x->y; r->z = x->z; fe25519_neg(&r->t, &x->t); } void group_ge_scalarmult(group_ge *r, const group_ge *x, const group_scalar *s) { group_ge precomp[17],t; int i, j; signed char win5[51]; scalar_window5(win5, s); //precomputation: precomp[0] = group_ge_neutral; precomp[1] = *x; for (i = 2; i < 16; i+=2) { group_ge_double(precomp+i,precomp+i/2); group_ge_add(precomp+i+1,precomp+i,precomp+1); } group_ge_double(precomp+16,precomp+8); *r = group_ge_neutral; for (i = 50; i >= 0; i--) { for (j = 0; j < 5; j++) group_ge_double(r, r); //change to not compute t all the time choose_t(&t, precomp, win5[i]); group_ge_add(r, r, &t); } } void group_ge_scalarmult_base(group_ge *r, const group_scalar *s) { signed char b[85]; int i; ge25519_aff t; scalar_window3(b,s); choose_t_aff((ge25519_aff *)r, 0, b[0]); r->z = fe25519_one; fe25519_mul(&r->t, &r->x, &r->y); for(i=1;i<85;i++) { choose_t_aff(&t, (unsigned long long) i, b[i]); ge25519_mixadd2(r, &t); } } void group_ge_multiscalarmult(group_ge *r, const group_ge *x, const group_scalar *s, unsigned long long xlen) { //XXX: Use Strauss unsigned long long i; group_ge t; *r = group_ge_neutral; for(i=0;ix, &y->y); fe25519_mul(&x2y1, &y->x, &x->y); r = fe25519_iseq(&x1y2, &x2y1); fe25519_mul(&x1x2, &x->x, &y->x); fe25519_mul(&y1y2, &x->y, &y->y); r |= fe25519_iseq(&x1x2, &y1y2); return r; } int group_ge_isneutral(const group_ge *x) { int r; group_ge t; // double three times for decaf8 group_ge_double(&t, x); group_ge_double(&t, &t); group_ge_double(&t, &t); r = 1-fe25519_iszero(&t.x); r |= 1-fe25519_iseq(&t.y, &t.z); return 1-r; } void group_ge_add_publicinputs(group_ge *r, const group_ge *x, const group_ge *y) { group_ge_add(r,x,y); } void group_ge_double_publicinputs(group_ge *r, const group_ge *x) { group_ge_double(r,x); } void group_ge_negate_publicinputs(group_ge *r, const group_ge *x) { group_ge_negate(r,x); } void group_ge_scalarmult_publicinputs(group_ge *r, const group_ge *x, const group_scalar *s) { //XXX: Use sliding window group_ge_scalarmult(r, x, s); } void group_ge_scalarmult_base_publicinputs(group_ge *r, const group_scalar *s) { //group_ge_scalarmult_publicinputs(r,&group_ge_base,s); group_ge_scalarmult_base(r,s); } void group_ge_multiscalarmult_publicinputs(group_ge *r, const group_ge *x, const group_scalar *s, unsigned long long xlen) { //XXX: Use Bos-Coster (and something else for small values of xlen) group_ge_multiscalarmult(r,x,s,xlen); } int group_ge_equals_publicinputs(const group_ge *x, const group_ge *y) { return group_ge_equals(x,y); } int group_ge_isneutral_publicinputs(const group_ge *x) { return group_ge_isneutral(x); } /* void ge_print(const group_ge *a) { fe25519_print(&a->x); fe25519_print(&a->y); fe25519_print(&a->z); fe25519_print(&a->t); } */ void group_ge_from_jacobi_quartic(group_ge *x, const fe25519 *s, const fe25519 *t) { ge25519_p1p1 res; fe25519 s2; fe25519_square(&s2, s); // Set x to 2 * s * 1/sqrt(-d-1) fe25519_double(&res.x, s); fe25519_mul(&res.x, &res.x, &ge25519_magic); // Set z to t res.z = *t; // Set y to 1-s^2 fe25519_sub(&res.y, &fe25519_one, &s2); // Set t to 1+s^2 fe25519_add(&res.t, &fe25519_one, &s2); p1p1_to_p3(x, &res); } // Compute the point corresponding to the scalar r0 in the // Elligator2 encoding adapted to Ristretto. void group_ge_elligator(group_ge *x, const fe25519 *r0) { fe25519 r, rPlusD, rPlusOne, ecd2, D, N, ND, sqrt, twiddle, sgn; fe25519 s, t, dMinusOneSquared, rSubOne, r0i, sNeg; int b; // r := i * r0^2 fe25519_mul(&r0i, r0, &fe25519_sqrtm1); fe25519_mul(&r, r0, &r0i); // D := -((d*r)+1) * (r + d) fe25519_add(&rPlusD, &ge25519_ecd, &r); fe25519_mul(&D, &ge25519_ecd, &r); fe25519_add(&D, &D, &fe25519_one); fe25519_mul(&D, &D, &rPlusD); fe25519_neg(&D, &D); // N := -(d^2 - 1)(r + 1) fe25519_square(&ecd2, &ge25519_ecd); fe25519_sub(&N, &ecd2, &fe25519_one); fe25519_neg(&N, &N); // TODO add -(d^2-1) as a constant fe25519_add(&rPlusOne, &r, &fe25519_one); fe25519_mul(&N, &N, &rPlusOne); // sqrt is the inverse square root of N*D or of i*N*D. b=1 iff n1 is square. fe25519_mul(&ND, &N, &D); b = fe25519_invsqrti(&sqrt, &ND); fe25519_abs(&sqrt, &sqrt); fe25519_setone(&twiddle); fe25519_cmov(&twiddle, &r0i, 1 - b); fe25519_setone(&sgn); fe25519_cmov(&sgn, &fe25519_m1, 1 - b); fe25519_mul(&sqrt, &sqrt, &twiddle); // s = N * sqrt(N*D) * twiddle fe25519_mul(&s, &sqrt, &N); // t = -sgn * sqrt * s * (r-1) * (d-1)^2 - 1 fe25519_neg(&t, &sgn); fe25519_mul(&t, &sqrt, &t); fe25519_mul(&t, &s, &t); fe25519_sub(&dMinusOneSquared, &ge25519_ecd, &fe25519_one); fe25519_square(&dMinusOneSquared, &dMinusOneSquared); // TODO make constant fe25519_mul(&t, &dMinusOneSquared, &t); fe25519_sub(&rSubOne, &r, &fe25519_one); fe25519_mul(&t, &rSubOne, &t); fe25519_sub(&t, &t, &fe25519_one); fe25519_neg(&sNeg, &s); fe25519_cmov(&s, &sNeg, fe25519_isnegative(&s) == b); group_ge_from_jacobi_quartic(x, &s, &t); } go-ristretto-1.2.3/cref/cref.go000066400000000000000000000034431440464505300163550ustar00rootroot00000000000000// A C implementation of the Ristretto group based on the PandA library // by Chuengsatiansup, Ribarski and Schwabe, which we use as a reference // of our pure Go implementation. // See also https://link.springer.com/chapter/10.1007/978-3-319-04873-4_14 package cref // #include "cref.h" import "C" type Fe25519 C.fe25519 type GroupGe C.group_ge type GroupScalar C.group_scalar func (f *Fe25519) c() *C.fe25519 { return (*C.fe25519)(f) } func (f *Fe25519) Unpack(buf *[32]byte) { C.fe25519_unpack(f.c(), (*C.uchar)(&buf[0])) } func (f *Fe25519) Pack(buf *[32]byte) { C.fe25519_pack((*C.uchar)(&buf[0]), f.c()) } func (g *GroupGe) c() *C.group_ge { return (*C.group_ge)(g) } func (g *GroupGe) Pack(buf *[32]byte) { C.group_ge_pack((*C.uchar)(&buf[0]), g.c()) } func (g *GroupGe) Unpack(buf *[32]byte) int { return int(C.group_ge_unpack(g.c(), (*C.uchar)(&buf[0]))) } func (g *GroupGe) Elligator(r0 *Fe25519) { C.group_ge_elligator(g.c(), r0.c()) } func (g *GroupGe) Neg(x *GroupGe) { C.group_ge_negate(g.c(), x.c()) } func (g *GroupGe) Add(x, y *GroupGe) { C.group_ge_add(g.c(), x.c(), y.c()) } func (g *GroupGe) Double(x *GroupGe) { C.group_ge_double(g.c(), x.c()) } func (g *GroupGe) ScalarMult(x *GroupGe, s *GroupScalar) { C.group_ge_scalarmult(g.c(), x.c(), s.c()) } func (g *GroupGe) X() *Fe25519 { return (*Fe25519)(&g.c().x) } func (g *GroupGe) Y() *Fe25519 { return (*Fe25519)(&g.c().y) } func (g *GroupGe) Z() *Fe25519 { return (*Fe25519)(&g.c().z) } func (g *GroupGe) T() *Fe25519 { return (*Fe25519)(&g.c().t) } func (s *GroupScalar) c() *C.group_scalar { return (*C.group_scalar)(s) } func (s *GroupScalar) Unpack(buf *[32]byte) { C.group_scalar_unpack(s.c(), (*C.uchar)(&buf[0])) } func (s *GroupScalar) Pack(buf *[32]byte) { C.group_scalar_pack((*C.uchar)(&buf[0]), s.c()) } go-ristretto-1.2.3/cref/cref.h000066400000000000000000000123061440464505300161750ustar00rootroot00000000000000#include // -- crypto_(u)int{32,64}.h -- typedef unsigned int crypto_uint32; typedef int crypto_int32; typedef int64_t crypto_int64; typedef uint64_t crypto_uint64; // -- fe25519.h -- typedef struct { crypto_int32 v[10]; } fe25519; extern const fe25519 fe25519_zero; extern const fe25519 fe25519_one; extern const fe25519 fe25519_two; extern const fe25519 fe25519_sqrtm1; extern const fe25519 fe25519_msqrtm1; extern const fe25519 fe25519_m1; //void fe25519_freeze(fe25519 *r); void fe25519_unpack(fe25519 *r, const unsigned char x[32]); void fe25519_pack(unsigned char r[32], const fe25519 *x); int fe25519_iszero(const fe25519 *x); int fe25519_isone(const fe25519 *x); int fe25519_isnegative(const fe25519 *x); int fe25519_iseq(const fe25519 *x, const fe25519 *y); int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y); void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b); void fe25519_setone(fe25519 *r); void fe25519_setzero(fe25519 *r); void fe25519_neg(fe25519 *r, const fe25519 *x); unsigned char fe25519_getparity(const fe25519 *x); void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y); void fe25519_double(fe25519 *r, const fe25519 *x); void fe25519_triple(fe25519 *r, const fe25519 *x); void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y); void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y); void fe25519_square(fe25519 *r, const fe25519 *x); void fe25519_square_double(fe25519 *h,const fe25519 *f); void fe25519_invert(fe25519 *r, const fe25519 *x); void fe25519_pow2523(fe25519 *r, const fe25519 *x); void fe25519_invsqrt(fe25519 *r, const fe25519 *x); int fe25519_invsqrti(fe25519 *r, const fe25519 *x); int fe25519_sqrti(fe25519 *r, const fe25519 *x); void fe25519_sqrt(fe25519 *r, const fe25519 *x); //void fe25519_print(const fe25519 *x); // -- scalar.h -- #define GROUP_SCALAR_PACKEDBYTES 32 typedef struct { uint32_t v[32]; } group_scalar; extern const group_scalar group_scalar_zero; extern const group_scalar group_scalar_one; int group_scalar_unpack(group_scalar *r, const unsigned char x[GROUP_SCALAR_PACKEDBYTES]); void group_scalar_pack(unsigned char s[GROUP_SCALAR_PACKEDBYTES], const group_scalar *r); void group_scalar_setzero(group_scalar *r); void group_scalar_setone(group_scalar *r); //void group_scalar_setrandom(group_scalar *r); // Removed to avoid dependency on platform specific randombytes void group_scalar_add(group_scalar *r, const group_scalar *x, const group_scalar *y); void group_scalar_sub(group_scalar *r, const group_scalar *x, const group_scalar *y); void group_scalar_negate(group_scalar *r, const group_scalar *x); void group_scalar_mul(group_scalar *r, const group_scalar *x, const group_scalar *y); void group_scalar_square(group_scalar *r, const group_scalar *x); void group_scalar_invert(group_scalar *r, const group_scalar *x); int group_scalar_isone(const group_scalar *x); int group_scalar_iszero(const group_scalar *x); int group_scalar_equals(const group_scalar *x, const group_scalar *y); // Additional functions, not required by API int scalar_tstbit(const group_scalar *x, const unsigned int pos); int scalar_bitlen(const group_scalar *x); void scalar_window3(signed char r[85], const group_scalar *x); void scalar_window5(signed char r[51], const group_scalar *s); void scalar_slide(signed char r[256], const group_scalar *s, int swindowsize); void scalar_from64bytes(group_scalar *r, const unsigned char h[64]); // -- group.h -- #define GROUP_GE_PACKEDBYTES 32 typedef struct { fe25519 x; fe25519 y; fe25519 z; fe25519 t; } group_ge; extern const group_ge group_ge_base; extern const group_ge group_ge_neutral; // Constant-time versions int group_ge_unpack(group_ge *r, const unsigned char x[GROUP_GE_PACKEDBYTES]); void group_ge_pack(unsigned char r[GROUP_GE_PACKEDBYTES], const group_ge *x); void group_ge_add(group_ge *r, const group_ge *x, const group_ge *y); void group_ge_double(group_ge *r, const group_ge *x); void group_ge_negate(group_ge *r, const group_ge *x); void group_ge_scalarmult(group_ge *r, const group_ge *x, const group_scalar *s); void group_ge_scalarmult_base(group_ge *r, const group_scalar *s); void group_ge_multiscalarmult(group_ge *r, const group_ge *x, const group_scalar *s, unsigned long long xlen); int group_ge_equals(const group_ge *x, const group_ge *y); int group_ge_isneutral(const group_ge *x); // Non-constant-time versions void group_ge_add_publicinputs(group_ge *r, const group_ge *x, const group_ge *y); void group_ge_double_publicinputs(group_ge *r, const group_ge *x); void group_ge_negate_publicinputs(group_ge *r, const group_ge *x); void group_ge_scalarmult_publicinputs(group_ge *r, const group_ge *x, const group_scalar *s); void group_ge_scalarmult_base_publicinputs(group_ge *r, const group_scalar *s); void group_ge_multiscalarmult_publicinputs(group_ge *r, const group_ge *x, const group_scalar *s, unsigned long long xlen); int group_ge_equals_publicinputs(const group_ge *x, const group_ge *y); int group_ge_isneutral_publicinputs(const group_ge *x); // Not required by API //void ge_print(const group_ge *x); void group_ge_from_jacobi_quartic(group_ge *x, const fe25519 *s, const fe25519 *t); void group_ge_elligator(group_ge *x, const fe25519 *r0); go-ristretto-1.2.3/edwards25519/000077500000000000000000000000001440464505300162235ustar00rootroot00000000000000go-ristretto-1.2.3/edwards25519/constants_test.go000066400000000000000000000025201440464505300216240ustar00rootroot00000000000000package edwards25519 import ( "testing" ) func TestFeConstants(t *testing.T) { var dP1, dP1InvDM1 FieldElement dP1.add(&feD, &feOne) dP1InvDM1.sub(&feD, &feOne) dP1InvDM1.Inverse(&dP1InvDM1) dP1InvDM1.Mul(&dP1InvDM1, &dP1) if dP1InvDM1.EqualsI(&feDp1OverDm1) != 1 { t.Fatalf("feDp1OverDm1: %v != %v", &feDp1OverDm1, &dP1InvDM1) } var sqrtID FieldElement sqrtID.Mul(&feI, &feD) sqrtID.Sqrt(&sqrtID) if sqrtID.EqualsI(&feSqrtID) != 1 { t.Fatalf("sqrtID: %v != %v", &feSqrtID, &sqrtID) } var doubleInvSqrtMinusDMinusOne FieldElement doubleInvSqrtMinusDMinusOne.Add(&feInvSqrtMinusDMinusOne, &feInvSqrtMinusDMinusOne) if doubleInvSqrtMinusDMinusOne.EqualsI(&feDoubleInvSqrtMinusDMinusOne) != 1 { t.Fatalf("doubleInvSqrtMinusDMinusOne: %v != %v", feDoubleInvSqrtMinusDMinusOne, doubleInvSqrtMinusDMinusOne) } var doubleIInvSqrtMinusDMinusOne FieldElement doubleIInvSqrtMinusDMinusOne.Mul(&feDoubleInvSqrtMinusDMinusOne, &feI) if doubleIInvSqrtMinusDMinusOne.EqualsI(&feDoubleIInvSqrtMinusDMinusOne) != 1 { t.Fatalf("doubleIInvSqrtMinusDMinusOne: %v != %v", feDoubleIInvSqrtMinusDMinusOne, doubleIInvSqrtMinusDMinusOne) } var invSqrt1pD FieldElement invSqrt1pD.add(&feD, &feOne) invSqrt1pD.InvSqrt(&invSqrt1pD) if invSqrt1pD.EqualsI(&feInvSqrt1pD) != 1 { t.Fatalf("invSqrt1pD: %v != %v", feInvSqrt1pD, invSqrt1pD) } } go-ristretto-1.2.3/edwards25519/curve.go000066400000000000000000000233421440464505300177020ustar00rootroot00000000000000// Go implementation of the elliptic curve Edwards25519 of which the // Ristretto group is a subquotient. package edwards25519 import ( "crypto/subtle" "encoding/hex" "fmt" ) // (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, X*Y=Z*T. Aka P3. type ExtendedPoint struct { X, Y, Z, T FieldElement } // ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T. Aka P1P1. type CompletedPoint struct { X, Y, Z, T FieldElement } // (X:Y:Z) satisfying x=X/Z, y=Y/Z. type ProjectivePoint struct { X, Y, Z FieldElement } // Set p to (-i,0), a point Ristretto-equivalent to 0. Returns p. func (p *ExtendedPoint) SetTorsion3() *ExtendedPoint { p.X.Set(&feMinusI) p.Y.SetZero() p.Z.Set(&feOne) p.T.SetZero() return p } // Set p to (i,0), a point Ristretto-equivalent to 0. Returns p. func (p *ExtendedPoint) SetTorsion2() *ExtendedPoint { p.X.Set(&feI) p.Y.SetZero() p.Z.Set(&feOne) p.T.SetZero() return p } // Set p to (0,-1), a point Ristretto-equivalent to 0. Returns p. func (p *ExtendedPoint) SetTorsion1() *ExtendedPoint { p.X.SetZero() p.Y.Set(&feMinusOne) p.Z.Set(&feOne) p.T.SetZero() return p } // Set p to zero, the neutral element. Return p. func (p *ProjectivePoint) SetZero() *ProjectivePoint { p.X.SetZero() p.Y.SetOne() p.Z.SetOne() return p } // Set p to zero, the neutral element. Return p. func (p *ExtendedPoint) SetZero() *ExtendedPoint { p.X.SetZero() p.Y.SetOne() p.Z.SetOne() p.T.SetZero() return p } // Set p to the basepoint (x,4/5) with x>=0. Returns p func (p *ExtendedPoint) SetBase() *ExtendedPoint { return p.Set(&epBase) } // Set p to q. Returns p. func (p *ExtendedPoint) Set(q *ExtendedPoint) *ExtendedPoint { p.X.Set(&q.X) p.Y.Set(&q.Y) p.Z.Set(&q.Z) p.T.Set(&q.T) return p } // Set p to q if b == 1. Assumes b is 0 or 1. Returns p. func (p *ExtendedPoint) ConditionalSet(q *ExtendedPoint, b int32) *ExtendedPoint { p.X.ConditionalSet(&q.X, b) p.Y.ConditionalSet(&q.Y, b) p.Z.ConditionalSet(&q.Z, b) p.T.ConditionalSet(&q.T, b) return p } // Sets p to q+r. Returns p func (p *CompletedPoint) AddExtended(q, r *ExtendedPoint) *CompletedPoint { var a, b, c, d, t FieldElement a.sub(&q.Y, &q.X) t.sub(&r.Y, &r.X) a.Mul(&a, &t) b.add(&q.X, &q.Y) t.add(&r.X, &r.Y) b.Mul(&b, &t) c.Mul(&q.T, &r.T) c.Mul(&c, &fe2D) d.Mul(&q.Z, &r.Z) d.add(&d, &d) p.X.sub(&b, &a) p.T.sub(&d, &c) p.Z.add(&d, &c) p.Y.add(&b, &a) return p } // Sets p to q-r. Returns p func (p *CompletedPoint) SubExtended(q, r *ExtendedPoint) *CompletedPoint { var a, b, c, d, t FieldElement a.sub(&q.Y, &q.X) t.add(&r.Y, &r.X) a.Mul(&a, &t) b.add(&q.X, &q.Y) t.sub(&r.Y, &r.X) b.Mul(&b, &t) c.Mul(&q.T, &r.T) c.Mul(&c, &fe2D) d.Mul(&q.Z, &r.Z) d.add(&d, &d) p.X.sub(&b, &a) p.T.add(&d, &c) p.Z.sub(&d, &c) p.Y.add(&b, &a) return p } // Set p to 2 * q. Returns p. func (p *CompletedPoint) DoubleProjective(q *ProjectivePoint) *CompletedPoint { var t0 FieldElement p.X.Square(&q.X) p.Z.Square(&q.Y) p.T.DoubledSquare(&q.Z) p.Y.add(&q.X, &q.Y) t0.Square(&p.Y) p.Y.add(&p.Z, &p.X) p.Z.sub(&p.Z, &p.X) p.X.sub(&t0, &p.Y) p.T.sub(&p.T, &p.Z) return p } // Set p to 2 * q. Returns p. func (p *CompletedPoint) DoubleExtended(q *ExtendedPoint) *CompletedPoint { var a, b, c, d FieldElement a.Square(&q.X) b.Square(&q.Y) c.DoubledSquare(&q.Z) d.Neg(&a) p.X.add(&q.X, &q.Y) p.X.Square(&p.X) p.X.sub(&p.X, &a) p.X.sub(&p.X, &b) p.Z.add(&d, &b) p.T.sub(&p.Z, &c) p.Y.sub(&d, &b) return p } // Set p to q. Returns p. func (p *ProjectivePoint) SetExtended(q *ExtendedPoint) *ProjectivePoint { p.X.Set(&q.X) p.Y.Set(&q.Y) p.Z.Set(&q.Z) return p } // Set p to q. Returns p. func (p *ProjectivePoint) SetCompleted(q *CompletedPoint) *ProjectivePoint { p.X.Mul(&q.X, &q.T) p.Y.Mul(&q.Y, &q.Z) p.Z.Mul(&q.Z, &q.T) return p } // Set p to 2 * q. Returns p. func (p *ExtendedPoint) Double(q *ExtendedPoint) *ExtendedPoint { var tmp CompletedPoint tmp.DoubleExtended(q) p.SetCompleted(&tmp) return p } // Set p to q + r. Returns p. func (p *ExtendedPoint) Add(q, r *ExtendedPoint) *ExtendedPoint { var tmp CompletedPoint tmp.AddExtended(q, r) p.SetCompleted(&tmp) return p } // Set p to q - r. Returns p. func (p *ExtendedPoint) Sub(q, r *ExtendedPoint) *ExtendedPoint { var tmp CompletedPoint tmp.SubExtended(q, r) p.SetCompleted(&tmp) return p } // Sets p to q. Returns p. func (p *ExtendedPoint) SetCompleted(q *CompletedPoint) *ExtendedPoint { p.X.Mul(&q.X, &q.T) p.Y.Mul(&q.Y, &q.Z) p.Z.Mul(&q.Z, &q.T) p.T.Mul(&q.X, &q.Y) return p } // Set p to a point corresponding to the encoded group element of // the ristretto group. Returns whether the buffer encoded a group element. func (p *ExtendedPoint) SetRistretto(buf *[32]byte) bool { var s, s2, chk, yDen, yNum, yDen2, xDen2, isr, xDenInv FieldElement var yDenInv, t FieldElement var b, ret int32 var buf2 [32]byte s.SetBytes(buf) // ensures 0 ≤ s < 2^255-19 s.BytesInto(&buf2) ret = int32(1 - subtle.ConstantTimeCompare(buf[:], buf2[:])) ret |= int32(buf2[0] & 1) // ensure s is positive s2.Square(&s) yDen.add(&feOne, &s2) yNum.sub(&feOne, &s2) yDen2.Square(&yDen) xDen2.Square(&yNum) xDen2.Mul(&xDen2, &feD) xDen2.add(&xDen2, &yDen2) xDen2.Neg(&xDen2) t.Mul(&xDen2, &yDen2) isr.InvSqrt(&t) chk.Square(&isr) chk.Mul(&chk, &t) ret |= 1 - chk.IsOneI() xDenInv.Mul(&isr, &yDen) yDenInv.Mul(&xDenInv, &isr) yDenInv.Mul(&yDenInv, &xDen2) p.X.Mul(&s, &xDenInv) p.X.add(&p.X, &p.X) b = p.X.IsNegativeI() t.Neg(&p.X) p.X.ConditionalSet(&t, b) p.Y.Mul(&yNum, &yDenInv) p.Z.SetOne() p.T.Mul(&p.X, &p.Y) ret |= p.T.IsNegativeI() ret |= 1 - p.Y.IsNonZeroI() p.X.ConditionalSet(&feZero, ret) p.Y.ConditionalSet(&feZero, ret) p.Z.ConditionalSet(&feZero, ret) p.T.ConditionalSet(&feZero, ret) return ret == 0 } // Pack p using the Ristretto encoding and return it. // Requires p to be even. func (p *ExtendedPoint) Ristretto() []byte { var buf [32]byte p.RistrettoInto(&buf) return buf[:] } // Pack p using the Ristretto encoding and write to buf. Returns p. // Requires p to be even. func (p *ExtendedPoint) RistrettoInto(buf *[32]byte) *ExtendedPoint { var d, u1, u2, isr, i1, i2, zInv, denInv, nx, ny, s FieldElement var b int32 d.add(&p.Z, &p.Y) u1.sub(&p.Z, &p.Y) u1.Mul(&u1, &d) u2.Mul(&p.X, &p.Y) isr.Square(&u2) isr.Mul(&isr, &u1) isr.InvSqrt(&isr) i1.Mul(&isr, &u1) i2.Mul(&isr, &u2) zInv.Mul(&i1, &i2) zInv.Mul(&zInv, &p.T) d.Mul(&zInv, &p.T) nx.Mul(&p.Y, &feI) ny.Mul(&p.X, &feI) denInv.Mul(&feInvSqrtMinusDMinusOne, &i1) b = 1 - d.IsNegativeI() nx.ConditionalSet(&p.X, b) ny.ConditionalSet(&p.Y, b) denInv.ConditionalSet(&i2, b) d.Mul(&nx, &zInv) b = d.IsNegativeI() d.Neg(&ny) ny.ConditionalSet(&d, b) s.sub(&p.Z, &ny) s.Mul(&s, &denInv) b = s.IsNegativeI() d.Neg(&s) s.ConditionalSet(&d, b) s.BytesInto(buf) return p } // Compute 5-bit window for the scalar s. func computeScalarWindow5(s *[32]byte, w *[51]int8) { for i := 0; i < 6; i++ { w[8*i+0] = int8(s[5*i+0] & 31) w[8*i+1] = int8((s[5*i+0] >> 5) & 31) w[8*i+1] ^= int8((s[5*i+1] << 3) & 31) w[8*i+2] = int8((s[5*i+1] >> 2) & 31) w[8*i+3] = int8((s[5*i+1] >> 7) & 31) w[8*i+3] ^= int8((s[5*i+2] << 1) & 31) w[8*i+4] = int8((s[5*i+2] >> 4) & 31) w[8*i+4] ^= int8((s[5*i+3] << 4) & 31) w[8*i+5] = int8((s[5*i+3] >> 1) & 31) w[8*i+6] = int8((s[5*i+3] >> 6) & 31) w[8*i+6] ^= int8((s[5*i+4] << 2) & 31) w[8*i+7] = int8((s[5*i+4] >> 3) & 31) } w[8*6+0] = int8(s[5*6+0] & 31) w[8*6+1] = int8((s[5*6+0] >> 5) & 31) w[8*6+1] ^= int8((s[5*6+1] << 3) & 31) w[8*6+2] = int8((s[5*6+1] >> 2) & 31) /* Making it signed */ var carry int8 = 0 for i := 0; i < 50; i++ { w[i] += carry w[i+1] += w[i] >> 5 w[i] &= 31 carry = w[i] >> 4 w[i] -= carry << 5 } w[50] += carry } // Set p to s * q. Returns p. func (p *ExtendedPoint) ScalarMult(q *ExtendedPoint, s *[32]byte) *ExtendedPoint { // See eg. https://cryptojedi.org/peter/data/eccss-20130911b.pdf var lut [17]ExtendedPoint var t ExtendedPoint var window [51]int8 // Precomputations. computeScalarWindow5(s, &window) lut[0].SetZero() lut[1].Set(q) for i := 2; i < 16; i += 2 { lut[i].Double(&lut[i>>1]) lut[i+1].Add(&lut[i], q) } lut[16].Double(&lut[8]) // Compute! p.SetZero() for i := 50; i >= 0; i-- { var pp ProjectivePoint var cp CompletedPoint cp.DoubleExtended(p) for z := 0; z < 4; z++ { pp.SetCompleted(&cp) cp.DoubleProjective(&pp) } p.SetCompleted(&cp) t.Set(&lut[0]) b := int32(window[i]) for j := 1; j <= 16; j++ { c := equal15(b, int32(-j)) | equal15(b, int32(j)) t.ConditionalSet(&lut[j], c) } var v FieldElement c := negative(b) v.Neg(&t.X) t.X.ConditionalSet(&v, c) v.Neg(&t.T) t.T.ConditionalSet(&v, c) p.Add(p, &t) } return p } // Sets p to -q. Returns p. func (p *ExtendedPoint) Neg(q *ExtendedPoint) *ExtendedPoint { p.X.Neg(&q.X) p.Y.Set(&q.Y) p.Z.Set(&q.Z) p.T.Neg(&q.T) return p } // Returns 1 if p and q are in the same Ristretto equivalence class. // Assumes p and q are both even. func (p *ExtendedPoint) RistrettoEqualsI(q *ExtendedPoint) int32 { var x1y2, x2y1, x1x2, y1y2 FieldElement x1y2.Mul(&p.X, &q.Y) x2y1.Mul(&q.X, &p.Y) x1x2.Mul(&p.X, &q.X) y1y2.Mul(&p.Y, &q.Y) return 1 - ((1 - x1y2.EqualsI(&x2y1)) & (1 - x1x2.EqualsI(&y1y2))) } // WARNING This operation is not constant-time. Do not use for cryptography // // unless you're sure this is not an issue. func (p *ExtendedPoint) String() string { return fmt.Sprintf("ExtendedPoint(%v, %v, %v, %v; %v)", p.X, p.Y, p.Z, p.T, hex.EncodeToString(p.Ristretto())) } // WARNING This operation is not constant-time. Do not use for cryptography // // unless you're sure this is not an issue. func (p *CompletedPoint) String() string { var ep ExtendedPoint ep.SetCompleted(p) return fmt.Sprintf("CompletedPoint(%v, %v, %v, %v; %v)", p.X, p.Y, p.Z, p.T, hex.EncodeToString(ep.Ristretto())) } go-ristretto-1.2.3/edwards25519/curve_test.go000066400000000000000000000114011440464505300207320ustar00rootroot00000000000000package edwards25519_test import ( "bytes" "math/big" "testing" "github.com/bwesterb/go-ristretto/cref" "github.com/bwesterb/go-ristretto/edwards25519" ) func TestPointDouble(t *testing.T) { var buf, cBuf, goBuf [32]byte var fe edwards25519.FieldElement var cp edwards25519.CompletedPoint var ep, ep2 edwards25519.ExtendedPoint var cFe cref.Fe25519 var cP, cP2 cref.GroupGe for i := 0; i < 1000; i++ { rnd.Read(buf[:]) cFe.Unpack(&buf) cP.Elligator(&cFe) cP2.Double(&cP) cP2.Pack(&cBuf) fe.SetBytes(&buf) cp.SetRistrettoElligator2(&fe) ep.SetCompleted(&cp) ep2.Double(&ep) ep2.RistrettoInto(&goBuf) if !bytes.Equal(cBuf[:], goBuf[:]) { t.Fatalf("2*%v = %v != %v", ep, ep2, cP2) } } } func TestPointSub(t *testing.T) { var buf1, buf2, cBuf, goBuf [32]byte var fe1, fe2 edwards25519.FieldElement var cp1, cp2 edwards25519.CompletedPoint var ep1, ep2, ep3 edwards25519.ExtendedPoint var cFe1, cFe2 cref.Fe25519 var cP1, cP2, cP3 cref.GroupGe for i := 0; i < 1000; i++ { rnd.Read(buf1[:]) rnd.Read(buf2[:]) cFe1.Unpack(&buf1) cFe2.Unpack(&buf2) cP1.Elligator(&cFe1) cP2.Elligator(&cFe2) cP2.Neg(&cP2) cP3.Add(&cP1, &cP2) cP3.Pack(&cBuf) fe1.SetBytes(&buf1) fe2.SetBytes(&buf2) cp1.SetRistrettoElligator2(&fe1) cp2.SetRistrettoElligator2(&fe2) ep1.SetCompleted(&cp1) ep2.SetCompleted(&cp2) ep3.Sub(&ep1, &ep2) ep3.RistrettoInto(&goBuf) if !bytes.Equal(cBuf[:], goBuf[:]) { t.Fatalf("%v - %v = %v != %v", ep1, ep2, ep3, cP3) } } } func TestPointAdd(t *testing.T) { var buf1, buf2, cBuf, goBuf [32]byte var fe1, fe2 edwards25519.FieldElement var cp1, cp2 edwards25519.CompletedPoint var ep1, ep2, ep3 edwards25519.ExtendedPoint var cFe1, cFe2 cref.Fe25519 var cP1, cP2, cP3 cref.GroupGe for i := 0; i < 1000; i++ { rnd.Read(buf1[:]) rnd.Read(buf2[:]) cFe1.Unpack(&buf1) cFe2.Unpack(&buf2) cP1.Elligator(&cFe1) cP2.Elligator(&cFe2) cP3.Add(&cP1, &cP2) cP3.Pack(&cBuf) fe1.SetBytes(&buf1) fe2.SetBytes(&buf2) cp1.SetRistrettoElligator2(&fe1) cp2.SetRistrettoElligator2(&fe2) ep1.SetCompleted(&cp1) ep2.SetCompleted(&cp2) ep3.Add(&ep1, &ep2) ep3.RistrettoInto(&goBuf) if !bytes.Equal(cBuf[:], goBuf[:]) { t.Fatalf("%v + %v = %v != %v", ep1, ep2, ep3, cP3) } } } func TestScalarMult(t *testing.T) { var buf, sBuf, cBuf, goBuf [32]byte var biS big.Int var fe edwards25519.FieldElement var cp edwards25519.CompletedPoint var ep, ep2 edwards25519.ExtendedPoint var cFe cref.Fe25519 var cS cref.GroupScalar var cP, cP2 cref.GroupGe for i := 0; i < 1000; i++ { rnd.Read(buf[:]) biS.Rand(rnd, &biL) srBuf := biS.Bytes() for j := 0; j < len(srBuf); j++ { sBuf[j] = srBuf[len(srBuf)-j-1] } cFe.Unpack(&buf) cS.Unpack(&sBuf) cP.Elligator(&cFe) cP2.ScalarMult(&cP, &cS) cP2.Pack(&cBuf) fe.SetBytes(&buf) cp.SetRistrettoElligator2(&fe) ep.SetCompleted(&cp) ep2.ScalarMult(&ep, &sBuf) ep2.RistrettoInto(&goBuf) if !bytes.Equal(cBuf[:], goBuf[:]) { t.Fatalf("%d: %v . %v = %v != %v", i, biS, ep, ep2, cP2) } } } func TestRistrettoEqualsI(t *testing.T) { var ep1, ep2 edwards25519.ExtendedPoint var torsion [4]edwards25519.ExtendedPoint var fe edwards25519.FieldElement var cp edwards25519.CompletedPoint var buf [32]byte torsion[0].SetZero() torsion[1].SetTorsion1() torsion[2].SetTorsion2() torsion[3].SetTorsion3() for i := 0; i < 1000; i++ { rnd.Read(buf[:]) fe.SetBytes(&buf) cp.SetRistrettoElligator2(&fe) ep1.SetCompleted(&cp) for j := 0; j < 4; j++ { ep2.Add(&ep1, &torsion[j]) if ep1.RistrettoEqualsI(&ep2) != 1 { t.Fatalf("%v + %v != %v", ep1, torsion[j], ep2) } } } } func BenchmarkRistrettoPack(b *testing.B) { var fe edwards25519.FieldElement var cp edwards25519.CompletedPoint var ep edwards25519.ExtendedPoint var buf [32]byte rnd.Read(buf[:]) fe.SetBytes(&buf) cp.SetRistrettoElligator2(&fe) ep.SetCompleted(&cp) b.ResetTimer() for n := 0; n < b.N; n++ { ep.RistrettoInto(&buf) } } func BenchmarkRistrettoUnpack(b *testing.B) { var fe edwards25519.FieldElement var cp edwards25519.CompletedPoint var ep edwards25519.ExtendedPoint var buf [32]byte rnd.Read(buf[:]) fe.SetBytes(&buf) cp.SetRistrettoElligator2(&fe) ep.SetCompleted(&cp) ep.RistrettoInto(&buf) b.ResetTimer() for n := 0; n < b.N; n++ { ep.SetRistretto(&buf) } } func BenchmarkScalarMult(b *testing.B) { var buf, sBuf [32]byte var biS big.Int var cp edwards25519.CompletedPoint var ep edwards25519.ExtendedPoint var fe edwards25519.FieldElement biS.Rand(rnd, &biL) srBuf := biS.Bytes() for j := 0; j < len(srBuf); j++ { sBuf[j] = srBuf[len(srBuf)-j-1] } rnd.Read(buf[:]) fe.SetBytes(&buf) cp.SetRistrettoElligator2(&fe) ep.SetCompleted(&cp) b.ResetTimer() for n := 0; n < b.N; n++ { ep.ScalarMult(&ep, &sBuf) } } go-ristretto-1.2.3/edwards25519/elligator.go000066400000000000000000000164231440464505300205420ustar00rootroot00000000000000package edwards25519 import ( "fmt" ) // Represents a point (s, t) on the Jacobi quartic associated to // the Edwards curve type JacobiPoint struct { S, T FieldElement } // Computes the at most 8 positive FieldElements f such that p == elligator2(f). // Assumes p is even. // // Returns a bitmask of which elements in fes are set. func (p *ExtendedPoint) RistrettoElligator2Inverse(fes *[8]FieldElement) uint8 { var setMask uint8 var jcs [4]JacobiPoint var jc JacobiPoint // Elligator2 computes a Point from a FieldElement in two steps: first // it computes a (s,t) on the Jacobi quartic and then computes the // corresponding even point on the Edwards curve. // // We invert in three steps. Any Ristretto point has four representatives // as even Edwards points. For each of those even Edwards points, // there are two points on the Jacobi quartic that map to it. // Each of those eight points on the Jacobi quartic might have an // Elligator2 preimage. // // Essentially we first loop over the four representatives of our point, // then for each of them consider both points on the Jacobi quartic and // check whether they have an inverse under Elligator2. We take the // following shortcut though. // // We can compute two Jacobi quartic points for (x,y) and (-x,-y) // at the same time. The four Jacobi quartic points are two of // such pairs. p.ToJacobiQuarticRistretto(&jcs) for j := 0; j < 4; j++ { setMask |= uint8(jcs[j].elligator2Inverse(&fes[2*j]) << uint(2*j)) jc.Dual(&jcs[j]) setMask |= uint8(jc.elligator2Inverse(&fes[2*j+1]) << uint(2*j+1)) } return setMask } // Find a point on the Jacobi quartic associated to each of the four // points Ristretto equivalent to p. // // There is one exception: for (0,-1) there is no point on the quartic and // so we repeat one on the quartic equivalent to (0,1). func (p *ExtendedPoint) ToJacobiQuarticRistretto(qs *[4]JacobiPoint) *ExtendedPoint { var X2, Y2, Z2, Y4, ZmY, ZpY, Z2mY2, gamma, den, sOverX, spOverXp, tmp FieldElement X2.Square(&p.X) // X^2 Y2.Square(&p.Y) // Y^2 Y4.Square(&Y2) // Y^4 Z2.Square(&p.Z) // Z^2 ZmY.sub(&p.Z, &p.Y) // Z - Y ZpY.add(&p.Z, &p.Y) // Z + Y Z2mY2.sub(&Z2, &Y2) // Z^2 - Y^2 // gamma := 1/sqrt( Y^4 X^2 (Z^2 - Y^2) ) gamma.Mul(&Y4, &X2) gamma.Mul(&gamma, &Z2mY2) gamma.InvSqrt(&gamma) // den := gamma * Y^2 den.Mul(&gamma, &Y2) // sOverX := den * (Z - Y) // spOverXp := den * (Z + Y) sOverX.Mul(&den, &ZmY) spOverXp.Mul(&den, &ZpY) // s_0 := sOverX * X // s_1 := -spOverXp * X qs[0].S.Mul(&sOverX, &p.X) tmp.Mul(&spOverXp, &p.X) qs[1].S.Neg(&tmp) // t_0 := 2/sqrt(-d-1) * Z * sOverX // t_1 := 2/sqrt(-d-1) * Z * spOverXp tmp.Mul(&feDoubleInvSqrtMinusDMinusOne, &p.Z) qs[0].T.Mul(&tmp, &sOverX) qs[1].T.Mul(&tmp, &spOverXp) // den = 1/sqrt(1+d) (Y^2 - Z^2) gamma den.Neg(&Z2mY2) den.Mul(&den, &feInvSqrt1pD) den.Mul(&den, &gamma) // Same as before, but with the substitution (X, Y, Z) = (Y, X, i*Z) var iZ, iZmX, iZpX, sOverY, spOverYp FieldElement iZ.Mul(&feI, &p.Z) // iZ iZmX.sub(&iZ, &p.X) // iZ - X iZpX.add(&iZ, &p.X) // iZ + X // sOverY := den * (iZ - Y) // spOverYp := den * (iZ + Y) sOverY.Mul(&den, &iZmX) spOverYp.Mul(&den, &iZpX) // s_2 := sOverY * Y // s_3 := -spOverYp * Y qs[2].S.Mul(&sOverY, &p.Y) tmp.Mul(&spOverYp, &p.Y) qs[3].S.Neg(&tmp) // t_2 := 2/sqrt(-d-1) * i*Z * sOverY // t_3 := 2/sqrt(-d-1) * i*Z * spOverYp tmp.Mul(&feDoubleInvSqrtMinusDMinusOne, &iZ) qs[2].T.Mul(&tmp, &sOverY) qs[3].T.Mul(&tmp, &spOverYp) // Special case: X=0 or Y=0. Then return // // (0,1) (1,2i/sqrt(-d-1) (-1,2i/sqrt(-d-1)) // // Note that if X=0 or Y=0, then s_i = t_i = 0. XorYisZero := 1 - (p.X.IsNonZeroI() & p.Y.IsNonZeroI()) qs[0].T.ConditionalSet(&feOne, XorYisZero) qs[1].T.ConditionalSet(&feOne, XorYisZero) qs[2].T.ConditionalSet(&feDoubleIInvSqrtMinusDMinusOne, XorYisZero) qs[3].T.ConditionalSet(&feDoubleIInvSqrtMinusDMinusOne, XorYisZero) qs[2].S.ConditionalSet(&feOne, XorYisZero) qs[3].S.ConditionalSet(&feMinusOne, XorYisZero) return p } func (p *JacobiPoint) Dual(q *JacobiPoint) *JacobiPoint { p.S.Neg(&q.S) p.T.Neg(&q.T) return p } // Elligator2 is defined in two steps: first a field element is converted // to a point (s,t) on the Jacobi quartic associated to the Edwards curve. // Then this point is mapped to a point on the Edwards curve. // This function computes a field element that is mapped to a given (s,t) // with Elligator2 if it exists. // // Returns 1 if a preimage is found and 0 if none exists. func (p *JacobiPoint) elligator2Inverse(fe *FieldElement) int { var x, y, a, a2, S2, S4, invSqiY, negS2, out FieldElement // Special case: s = 0. If s is zero, either t = 1 or t = -1. // If t=1, then sqrt(i*d) is the preimage. Otherwise it's 0. sNonZero := p.S.IsNonZeroI() tEqualsOne := p.T.EqualsI(&feOne) out.Set(&feZero) out.ConditionalSet(&feSqrtID, tEqualsOne) ret := 1 - sNonZero done := 1 - sNonZero // a := (t+1) (d+1)/(d-1) a.add(&p.T, &feOne) a.Mul(&a, &feDp1OverDm1) a2.Square(&a) // y := 1/sqrt(i (s^4 - a^2)). S2.Square(&p.S) S4.Square(&S2) invSqiY.sub(&S4, &a2) // there is no preimage of the square root of i*(s^4-a^2) does not exist sq := y.InvSqrtI(&invSqiY) ret |= 1 - sq done |= sq // x := (a + sign(s)*s^2) y negS2.Neg(&S2) S2.ConditionalSet(&negS2, p.S.IsNegativeI()) x.add(&a, &S2) x.Mul(&x, &y) // fe := abs(x) x.Abs(&x) out.ConditionalSet(&x, 1-done) fe.Set(&out) return int(ret) } // Set p to the point corresponding to the given point (s,t) on the // associated Jacobi quartic. func (p *CompletedPoint) SetJacobiQuartic(jc *JacobiPoint) *CompletedPoint { var s2 FieldElement s2.Square(&jc.S) // Set x to s * 2/sqrt(-d-1) p.X.Mul(&jc.S, &feDoubleInvSqrtMinusDMinusOne) // Set z to t p.Z.Set(&jc.T) // Set y to 1-s^2 p.Y.sub(&feOne, &s2) // Set t to 1+s^2 p.T.add(&feOne, &s2) return p } // Set p to the curvepoint corresponding to r0 via Mike Hamburg's variation // on Elligator2 for Ristretto. Returns p. func (p *CompletedPoint) SetRistrettoElligator2(r0 *FieldElement) *CompletedPoint { var r, rPlusD, rPlusOne, D, N, ND, sqrt, twiddle, sgn FieldElement var rSubOne, r0i, sNeg FieldElement var jc JacobiPoint var b int32 // r := i * r0^2 r0i.Mul(r0, &feI) r.Mul(r0, &r0i) // D := -((d*r)+1) * (r + d) rPlusD.add(&feD, &r) D.Mul(&feD, &r) D.add(&D, &feOne) D.Mul(&D, &rPlusD) D.Neg(&D) // N := -(d^2 - 1)(r + 1) rPlusOne.add(&r, &feOne) N.Mul(&feOneMinusDSquared, &rPlusOne) // sqrt is the inverse square root of N*D or of i*N*D. // b=1 iff n1 is square. ND.Mul(&N, &D) b = sqrt.InvSqrtI(&ND) sqrt.Abs(&sqrt) twiddle.SetOne() twiddle.ConditionalSet(&r0i, 1-b) sgn.SetOne() sgn.ConditionalSet(&feMinusOne, 1-b) sqrt.Mul(&sqrt, &twiddle) // s = N * sqrt * twiddle jc.S.Mul(&sqrt, &N) // t = -sgn * sqrt * s * (r-1) * (d-1)^2 - 1 jc.T.Neg(&sgn) jc.T.Mul(&sqrt, &jc.T) jc.T.Mul(&jc.S, &jc.T) jc.T.Mul(&feDMinusOneSquared, &jc.T) rSubOne.sub(&r, &feOne) jc.T.Mul(&rSubOne, &jc.T) jc.T.sub(&jc.T, &feOne) sNeg.Neg(&jc.S) jc.S.ConditionalSet(&sNeg, equal30(jc.S.IsNegativeI(), b)) return p.SetJacobiQuartic(&jc) } // WARNING This operation is not constant-time. Do not use for cryptography // // unless you're sure this is not an issue. func (p *JacobiPoint) String() string { return fmt.Sprintf("JacobiPoint(%v, %v)", p.S, p.T) } go-ristretto-1.2.3/edwards25519/elligator_test.go000066400000000000000000000101171440464505300215730ustar00rootroot00000000000000package edwards25519_test import ( "bytes" "encoding/hex" "testing" "github.com/bwesterb/go-ristretto/cref" "github.com/bwesterb/go-ristretto/edwards25519" ) func TestElligatorAndRistretto(t *testing.T) { var buf, goBuf, cBuf, goBuf2, cBuf2 [32]byte var fe edwards25519.FieldElement var cp edwards25519.CompletedPoint var ep edwards25519.ExtendedPoint var ep2 edwards25519.ExtendedPoint var cP cref.GroupGe var cP2 cref.GroupGe var cFe cref.Fe25519 for i := 0; i < 1000; i++ { rnd.Read(buf[:]) cFe.Unpack(&buf) cP.Elligator(&cFe) cP.Pack(&cBuf) fe.SetBytes(&buf) cp.SetRistrettoElligator2(&fe) ep.SetCompleted(&cp) ep.RistrettoInto(&goBuf) if !bytes.Equal(cBuf[:], goBuf[:]) { t.Fatalf("pack o elligator ( %v ) = %v != %v", buf, cBuf, goBuf) } ep2.SetRistretto(&goBuf) ep2.RistrettoInto(&goBuf2) cP2.Unpack(&cBuf) cP2.Pack(&cBuf2) if !bytes.Equal(cBuf[:], goBuf[:]) { t.Fatalf("pack o unpack o pack o elligator ( %v ) = %v != %v", buf, cBuf2, goBuf2) } } } func TestToJacobiQuarticRistretto(t *testing.T) { var buf [32]byte var feZero, feOne, fe edwards25519.FieldElement var cp, cp2 edwards25519.CompletedPoint var ep, ep2 edwards25519.ExtendedPoint var jcs [4]edwards25519.JacobiPoint feOne.SetOne() feZero.SetZero() for i := 0; i < 1000; i++ { if i == 0 { ep = edwards25519.ExtendedPoint{feZero, feOne, feOne, feZero} } else if i == 1 { ep = edwards25519.ExtendedPoint{feOne, feZero, feOne, feZero} } else { rnd.Read(buf[:]) fe.SetBytes(&buf) cp.SetRistrettoElligator2(&fe) ep.SetCompleted(&cp) } ep.ToJacobiQuarticRistretto(&jcs) for j := 0; j < 4; j++ { cp2.SetJacobiQuartic(&jcs[j]) ep2.SetCompleted(&cp2) if ep2.RistrettoEqualsI(&ep) != 1 { t.Fatalf("Jacobi(ToJacobiQuarticRistretto(%v)[%d]) == %v", &ep, j, &ep2) } } } } func TestRistrettoElligator2Inverse(t *testing.T) { var buf [32]byte var fe edwards25519.FieldElement var torsion [4]edwards25519.ExtendedPoint var cp, cp2 edwards25519.CompletedPoint var ep, ep2 edwards25519.ExtendedPoint var fs [8]edwards25519.FieldElement torsion[0].SetZero() torsion[1].SetTorsion1() torsion[2].SetTorsion2() torsion[3].SetTorsion3() for i := 0; i < 1000; i++ { ok := true if i == 0 { fe.SetZero() } else if i == 1 { fe.SetBytes(&[32]byte{ 168, 27, 92, 74, 203, 42, 48, 117, 170, 109, 234, 14, 45, 169, 188, 205, 21, 110, 235, 115, 153, 84, 52, 117, 151, 235, 123, 244, 88, 85, 179, 5, }) } else { rnd.Read(buf[:]) buf[31] &= 127 buf[0] &= 254 fe.SetBytes(&buf) } cp.SetRistrettoElligator2(&fe) ep.SetCompleted(&cp) ep.Add(&ep, &torsion[i%4]) setMask := ep.RistrettoElligator2Inverse(&fs) foundOriginal := false count := 0 for j := 0; j < 8; j++ { if ((1 << uint(j)) & setMask) == 0 { continue } if fs[j].Equals(&fe) { foundOriginal = true } cp2.SetRistrettoElligator2(&fs[j]) ep2.SetCompleted(&cp2) if ep2.RistrettoEqualsI(&ep) != 1 { t.Logf("%vth preimage %v is wrong: %v", j, &fs[j], &ep2) ok = false } count++ } if !foundOriginal { t.Logf("Missing original %v among %d preimage(s):", &fe, count) for j := 0; j < 8; j++ { if (1 << uint(j) & setMask) != 0 { t.Logf(" %d: %v", j, &fs[j]) } } ok = false } if !ok { t.Fatalf("^ see errors above. fe=%v, ep=%v torsion=%d", hex.EncodeToString(buf[:]), &ep, i%4) } } } func BenchmarkElligatorInverse(b *testing.B) { var fe edwards25519.FieldElement var fs [8]edwards25519.FieldElement var ep edwards25519.ExtendedPoint var cp edwards25519.CompletedPoint var buf [32]byte rnd.Read(buf[:]) buf[0] &= 254 buf[31] &= 127 fe.SetBytes(&buf) cp.SetRistrettoElligator2(&fe) ep.SetCompleted(&cp) b.ResetTimer() for n := 0; n < b.N; n++ { ep.RistrettoElligator2Inverse(&fs) } } func BenchmarkElligator(b *testing.B) { var fe edwards25519.FieldElement var cp edwards25519.CompletedPoint var ep edwards25519.ExtendedPoint var buf [32]byte rnd.Read(buf[:]) fe.SetBytes(&buf) b.ResetTimer() for n := 0; n < b.N; n++ { cp.SetRistrettoElligator2(&fe) ep.SetCompleted(&cp) } } go-ristretto-1.2.3/edwards25519/field.go000066400000000000000000000173031440464505300176410ustar00rootroot00000000000000package edwards25519 import ( // Requires for FieldElement.[Set]BigInt(). Obviously not used for actual // implementation, as operations on big.Ints are not constant-time. "math/big" "encoding/binary" ) // Set fe to i, the root of -1. Returns fe. func (fe *FieldElement) SetI() *FieldElement { copy(fe[:], feI[:]) return fe } // Set fe to 0. Returns fe. func (fe *FieldElement) SetZero() *FieldElement { copy(fe[:], feZero[:]) return fe } // Set fe to 1. Returns fe. func (fe *FieldElement) SetOne() *FieldElement { copy(fe[:], feOne[:]) return fe } // Sets fe to 2*a without normalizing. Returns fe. func (fe *FieldElement) double(a *FieldElement) *FieldElement { return fe.add(a, a) } // Sets fe to a + b. Returns fe. func (fe *FieldElement) Add(a, b *FieldElement) *FieldElement { return fe.add(a, b).normalize() } // Sets fe to a - b. Returns fe. func (fe *FieldElement) Sub(a, b *FieldElement) *FieldElement { return fe.sub(a, b).normalize() } // Sets fe to a. Returns fe. func (fe *FieldElement) Set(a *FieldElement) *FieldElement { copy(fe[:], a[:]) return fe } // Returns little endian representation of fe. func (fe *FieldElement) Bytes() [32]byte { var ret [32]byte fe.BytesInto(&ret) return ret } // Set fe to the inverse of a. Return fe. func (fe *FieldElement) Inverse(a *FieldElement) *FieldElement { var t0, t1, t2, t3 FieldElement var i int t0.Square(a) t1.Square(&t0) t1.Square(&t1) t1.Mul(a, &t1) t0.Mul(&t0, &t1) t2.Square(&t0) t1.Mul(&t1, &t2) t2.Square(&t1) for i = 1; i < 5; i++ { t2.Square(&t2) } t1.Mul(&t2, &t1) t2.Square(&t1) for i = 1; i < 10; i++ { t2.Square(&t2) } t2.Mul(&t2, &t1) t3.Square(&t2) for i = 1; i < 20; i++ { t3.Square(&t3) } t2.Mul(&t3, &t2) t2.Square(&t2) for i = 1; i < 10; i++ { t2.Square(&t2) } t1.Mul(&t2, &t1) t2.Square(&t1) for i = 1; i < 50; i++ { t2.Square(&t2) } t2.Mul(&t2, &t1) t3.Square(&t2) for i = 1; i < 100; i++ { t3.Square(&t3) } t2.Mul(&t3, &t2) t2.Square(&t2) for i = 1; i < 50; i++ { t2.Square(&t2) } t1.Mul(&t2, &t1) t1.Square(&t1) for i = 1; i < 5; i++ { t1.Square(&t1) } return fe.Mul(&t1, &t0) } // Set fe to -x if x is negative and x otherwise. Returns fe. func (fe *FieldElement) Abs(x *FieldElement) *FieldElement { var xNeg FieldElement xNeg.Neg(x) fe.Set(x) fe.ConditionalSet(&xNeg, x.IsNegativeI()) return fe } // Returns 1 if fe is negative, otherwise 0. func (fe *FieldElement) IsNegativeI() int32 { var buf [32]byte fe.BytesInto(&buf) return int32(buf[0] & 1) } // Returns 1 if fe is non-zero, otherwise 0. func (fe *FieldElement) IsNonZeroI() int32 { var buf [32]byte fe.BytesInto(&buf) ret := (binary.LittleEndian.Uint64(buf[0:8]) | binary.LittleEndian.Uint64(buf[8:16]) | binary.LittleEndian.Uint64(buf[16:24]) | binary.LittleEndian.Uint64(buf[24:32])) ret |= ret >> 32 ret |= ret >> 16 ret |= ret >> 8 ret |= ret >> 4 ret |= ret >> 2 ret |= ret >> 1 return int32(ret & 1) } // Returns 1 if fe is equal to one, otherwise 0. func (fe *FieldElement) IsOneI() int32 { var b FieldElement return 1 - b.sub(fe, &feOne).IsNonZeroI() } // Returns 1 if fe is equal to a, otherwise 0. func (fe *FieldElement) EqualsI(a *FieldElement) int32 { var b FieldElement return 1 - b.sub(fe, a).IsNonZeroI() } // Returns whether fe equals a. func (fe *FieldElement) Equals(a *FieldElement) bool { var b FieldElement return b.sub(fe, a).IsNonZeroI() == 0 } // Returns fe as a big.Int. // // WARNING Operations on big.Ints are not constant-time: do not use them // // for cryptography unless you're sure this is not an issue. func (fe *FieldElement) BigInt() *big.Int { var ret big.Int var buf, rBuf [32]byte fe.BytesInto(&buf) for i := 0; i < 32; i++ { rBuf[i] = buf[31-i] } return ret.SetBytes(rBuf[:]) } // Writes fe as a string for debugging. // // WARNING This operation is not constant-time. Do not use for cryptography // // unless you're sure this is not an issue. func (fe FieldElement) String() string { return fe.BigInt().String() } // Sets fe to x modulo 2^255-19. // // WARNING Operations on big.Ints are not constant-time: do not use them // // for cryptography unless you're sure this is not an issue. func (fe *FieldElement) SetBigInt(x *big.Int) *FieldElement { var v, bi25519 big.Int bi25519.SetString( "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", 16) buf := v.Mod(x, &bi25519).Bytes() var rBuf [32]byte for i := 0; i < len(buf) && i < 32; i++ { rBuf[i] = buf[len(buf)-i-1] } return fe.SetBytes(&rBuf) } // Sets fe to a^( ((2^255 - 19) - 5) / 8 ) = a^(2^252 - 3). Returns fe. // // This method is useful to compute (inverse) square-roots // with the method of Lagrange. func (fe *FieldElement) Exp22523(a *FieldElement) *FieldElement { var t0, t1, t2 FieldElement var i int t0.Square(a) for i = 1; i < 1; i++ { t0.Square(&t0) } t1.Square(&t0) for i = 1; i < 2; i++ { t1.Square(&t1) } t1.Mul(a, &t1) t0.Mul(&t0, &t1) t0.Square(&t0) for i = 1; i < 1; i++ { t0.Square(&t0) } t0.Mul(&t1, &t0) t1.Square(&t0) for i = 1; i < 5; i++ { t1.Square(&t1) } t0.Mul(&t1, &t0) t1.Square(&t0) for i = 1; i < 10; i++ { t1.Square(&t1) } t1.Mul(&t1, &t0) t2.Square(&t1) for i = 1; i < 20; i++ { t2.Square(&t2) } t1.Mul(&t2, &t1) t1.Square(&t1) for i = 1; i < 10; i++ { t1.Square(&t1) } t0.Mul(&t1, &t0) t1.Square(&t0) for i = 1; i < 50; i++ { t1.Square(&t1) } t1.Mul(&t1, &t0) t2.Square(&t1) for i = 1; i < 100; i++ { t2.Square(&t2) } t1.Mul(&t2, &t1) t1.Square(&t1) for i = 1; i < 50; i++ { t1.Square(&t1) } t0.Mul(&t1, &t0) t0.Square(&t0) for i = 1; i < 2; i++ { t0.Square(&t0) } return fe.Mul(&t0, a) } // Sets fe to 1/sqrt(a). Requires a to be a square. Returns fe. func (fe *FieldElement) InvSqrt(a *FieldElement) *FieldElement { var den2, den3, den4, den6, chk, t, t2 FieldElement den2.Square(a) den3.Mul(&den2, a) den4.Square(&den2) den6.Mul(&den2, &den4) t.Mul(&den6, a) t.Exp22523(&t) t.Mul(&t, &den3) t2.Mul(&t, &feI) chk.Square(&t) chk.Mul(&chk, a) fe.Set(&t) fe.ConditionalSet(&t2, 1-chk.IsOneI()) return fe } // Sets fe to sqrt(a). Requires a to be a square. Returns fe. func (fe *FieldElement) Sqrt(a *FieldElement) *FieldElement { var aCopy FieldElement aCopy.Set(a) fe.InvSqrt(a) fe.Mul(fe, &aCopy) var feNeg FieldElement feNeg.Neg(fe) fe.ConditionalSet(&feNeg, fe.IsNegativeI()) return fe } // Sets fe to either 1/sqrt(a) or 1/sqrt(i*a). Returns 1 in the former case // and 0 in the latter. func (fe *FieldElement) InvSqrtI(a *FieldElement) int32 { var inCaseA, inCaseB, inCaseD int32 var den2, den3, den4, den6, chk, t, corr FieldElement den2.Square(a) den3.Mul(&den2, a) den4.Square(&den2) den6.Mul(&den2, &den4) t.Mul(&den6, a) t.Exp22523(&t) t.Mul(&t, &den3) // case A B C D // --------------------------------------------------------------- // t 1/sqrt(a) -i/sqrt(a) 1/sqrt(i*a) -i/sqrt(i*a) // chk 1 -1 -i i // corr 1 i 1 i // ret 1 1 0 0 chk.Square(&t) chk.Mul(&chk, a) inCaseA = chk.IsOneI() inCaseD = chk.EqualsI(&feI) chk.Neg(&chk) inCaseB = chk.IsOneI() corr.SetOne() corr.ConditionalSet(&feI, inCaseB+inCaseD) t.Mul(&t, &corr) fe.Set(&t) return inCaseA + inCaseB } // Returns 1 if b == c and 0 otherwise. Assumes 0 <= b, c < 2^30. func equal30(b, c int32) int32 { x := uint32(b ^ c) x-- return int32(x >> 31) } // Returns 1 if b == c and 0 otherwise. Assumes 2^15 <= b, c < 2^30. func equal15(b, c int32) int32 { ub := uint16(b) uc := uint16(c) x := uint32(ub ^ uc) x-- return int32(x >> 31) } // Returns 1 if b < 0 and 0 otherwise. func negative(b int32) int32 { return (b >> 31) & 1 } go-ristretto-1.2.3/edwards25519/field_amd64.go000066400000000000000000000011451440464505300206310ustar00rootroot00000000000000//go:build amd64 && !go1.13 && !forcegeneric // +build amd64,!go1.13,!forcegeneric package edwards25519 //go:noescape func feMul(out, a, b *FieldElement) //go:noescape func feSquare(out, a *FieldElement) // Sets fe to a * b. Returns fe. func (fe *FieldElement) Mul(a, b *FieldElement) *FieldElement { feMul(fe, a, b) return fe } // Sets fe to a^2. Returns fe. func (fe *FieldElement) Square(a *FieldElement) *FieldElement { feSquare(fe, a) return fe } // Sets fe to 2 * a^2. Returns fe. func (fe *FieldElement) DoubledSquare(a *FieldElement) *FieldElement { feSquare(fe, a) return fe.add(fe, fe) } go-ristretto-1.2.3/edwards25519/field_amd64.s000066400000000000000000000166311440464505300204740ustar00rootroot00000000000000//+build amd64 AND !go1.13 #include "textflag.h" // func feMul(outp *uint64, xp *uint64, yp *uint64) TEXT ·feMul(SB),NOSPLIT,$0 MOVQ outp+0(FP), DI MOVQ xp+8(FP), BX MOVQ yp+16(FP), CX // Calculate r0 MOVQ 0(BX), AX // rax <-- x0 MULQ 0(CX) // rdx, rax <-- x0*y0 MOVQ AX, SI // r00 = rax MOVQ DX, BP // r01 = rdx MOVQ 8(BX), DX // rdx <-- x1 IMUL3Q $19, DX, AX // rax <-- x1*19 MULQ 32(CX) // rdx, rax <-- x1_19*y4 ADDQ AX, SI // r00 += rax ADCQ DX, BP // r01 += rdx MOVQ 16(BX), DX // rdx <-- x2 IMUL3Q $19, DX, AX // rax <-- x2*19 MULQ 24(CX) // rdx, rax <-- x2_19*y3 ADDQ AX, SI // r00 += rax ADCQ DX, BP // r01 += rdx MOVQ 24(BX), DX // rdx <-- x3 IMUL3Q $19, DX, AX // rax <-- x3*19 MULQ 16(CX) // rdx, rax <-- x3_19 * y2 ADDQ AX, SI // r00 += rax ADCQ DX, BP // r01 += rdx MOVQ 32(BX), DX // rdx <-- x4 IMUL3Q $19, DX, AX // rax <-- x4*19 MULQ 8(CX) // rdx rax <-- x4_19*y1 ADDQ AX, SI // r00 += rax ADCQ DX, BP // r01 += rdx // Calculate r1 MOVQ 0(BX), AX MULQ 8(CX) MOVQ AX, R8 // r10 MOVQ DX, R9 // r11 MOVQ 8(BX), AX MULQ 0(CX) ADDQ AX, R8 ADCQ DX, R9 MOVQ 16(BX), DX IMUL3Q $19, DX, AX MULQ 32(CX) ADDQ AX, R8 ADCQ DX, R9 MOVQ 24(BX), DX IMUL3Q $19, DX, AX MULQ 24(CX) ADDQ AX, R8 ADCQ DX, R9 MOVQ 32(BX), DX IMUL3Q $19, DX, AX MULQ 16(CX) ADDQ AX, R8 ADCQ DX, R9 // Calculate r2 MOVQ 0(BX), AX MULQ 16(CX) MOVQ AX, R10 // r20 MOVQ DX, R11 // r21 MOVQ 8(BX), AX MULQ 8(CX) ADDQ AX, R10 ADCQ DX, R11 MOVQ 16(BX), AX MULQ 0(CX) ADDQ AX, R10 ADCQ DX, R11 MOVQ 24(BX), DX IMUL3Q $19, DX, AX MULQ 32(CX) ADDQ AX, R10 ADCQ DX, R11 MOVQ 32(BX), DX IMUL3Q $19, DX, AX MULQ 24(CX) ADDQ AX, R10 ADCQ DX, R11 // Calculate r3 MOVQ 0(BX), AX MULQ 24(CX) MOVQ AX, R12 // r30 MOVQ DX, R13 // r31 MOVQ 8(BX), AX MULQ 16(CX) ADDQ AX, R12 ADCQ DX, R13 MOVQ 16(BX), AX MULQ 8(CX) ADDQ AX, R12 ADCQ DX, R13 MOVQ 24(BX), AX MULQ 0(CX) ADDQ AX, R12 ADCQ DX, R13 MOVQ 32(BX), DX IMUL3Q $19, DX, AX MULQ 32(CX) ADDQ AX, R12 ADCQ DX, R13 // Calculate r4 MOVQ 0(BX), AX MULQ 32(CX) MOVQ AX, R14 // r40 MOVQ DX, R15 // r41 MOVQ 8(BX), AX MULQ 24(CX) ADDQ AX, R14 ADCQ DX, R15 MOVQ 16(BX), AX MULQ 16(CX) ADDQ AX, R14 ADCQ DX, R15 MOVQ 24(BX), AX MULQ 8(CX) ADDQ AX, R14 ADCQ DX, R15 MOVQ 32(BX), AX MULQ 0(CX) ADDQ AX, R14 ADCQ DX, R15 MOVQ $2251799813685247, AX // (1<<51) - 1 SHLQ $13, SI, BP // r01 = shld with r00 ANDQ AX, SI // r00 &= mask51 SHLQ $13, R8, R9 // r11 = shld with r10 ANDQ AX, R8 // r10 &= mask51 ADDQ BP, R8 // r10 += r01 SHLQ $13, R10, R11 // r21 = shld with r20 ANDQ AX, R10 // r20 &= mask51 ADDQ R9, R10 // r20 += r11 SHLQ $13, R12, R13 // r31 = shld with r30 ANDQ AX, R12 // r30 &= mask51 ADDQ R11, R12 // r30 += r21 SHLQ $13, R14, R15 // r41 = shld with r40 ANDQ AX, R14 // r40 &= mask51 ADDQ R13, R14 // r40 += r31 IMUL3Q $19, R15, R15 // r41 = r41*19 ADDQ R15, SI // r00 += r41 MOVQ SI, DX // rdx <-- r00 SHRQ $51, DX // rdx <-- r00 >> 51 ADDQ DX, R8 // r10 += r00 >> 51 MOVQ R8, DX // rdx <-- r10 SHRQ $51, DX // rdx <-- r10 >> 51 ANDQ AX, SI // r00 &= mask51 ADDQ DX, R10 // r20 += r10 >> 51 MOVQ R10, DX // rdx <-- r20 SHRQ $51, DX // rdx <-- r20 >> 51 ANDQ AX, R8 // r10 &= mask51 ADDQ DX, R12 // r30 += r20 >> 51 MOVQ R12, DX // rdx <-- r30 SHRQ $51, DX // rdx <-- r30 >> 51 ANDQ AX, R10 // r20 &= mask51 ADDQ DX, R14 // r40 += r30 >> 51 MOVQ R14, DX // rdx <-- r40 SHRQ $51, DX // rdx <-- r40 >> 51 ANDQ AX, R12 // r30 &= mask51 IMUL3Q $19, DX, DX // rdx <-- (r40 >> 51) * 19 ADDQ DX, SI // r00 += (r40 >> 51) *19 ANDQ AX, R14 // r40 &= mask51 MOVQ SI, 0(DI) MOVQ R8, 8(DI) MOVQ R10, 16(DI) MOVQ R12, 24(DI) MOVQ R14, 32(DI) RET // func feSquare(outp *uint64, xp *uint64) TEXT ·feSquare(SB),NOSPLIT,$0 MOVQ outp+0(FP), DI MOVQ xp+8(FP), SI // r0 = x0*x0 + x1*38*x4 + x2*38*x3 MOVQ 0(SI), AX MULQ 0(SI) MOVQ AX, CX // r00 MOVQ DX, R8 // r01 MOVQ 8(SI), DX IMUL3Q $38, DX, AX MULQ 32(SI) ADDQ AX, CX ADCQ DX, R8 MOVQ 16(SI), DX IMUL3Q $38, DX, AX MULQ 24(SI) ADDQ AX, CX ADCQ DX, R8 // r1 = x0*2*x1 + x2*38*x4 + x3*19*x3 MOVQ 0(SI), AX SHLQ $1, AX MULQ 8(SI) MOVQ AX, R9 // r10 MOVQ DX, R10 // r11 MOVQ 16(SI), DX IMUL3Q $38, DX, AX MULQ 32(SI) ADDQ AX, R9 ADCQ DX, R10 MOVQ 24(SI), DX IMUL3Q $19, DX, AX MULQ 24(SI) ADDQ AX, R9 ADCQ DX, R10 // r2 = x0*2*x2 + x1*x1 + x3*38*x4 MOVQ 0(SI), AX SHLQ $1, AX MULQ 16(SI) MOVQ AX, R11 // r20 MOVQ DX, R12 // r21 MOVQ 8(SI), AX MULQ 8(SI) ADDQ AX, R11 ADCQ DX, R12 MOVQ 24(SI), DX IMUL3Q $38, DX, AX MULQ 32(SI) ADDQ AX, R11 ADCQ DX, R12 // r3 = x0*2*x3 + x1*2*x2 + x4*19*x4 MOVQ 0(SI), AX SHLQ $1, AX MULQ 24(SI) MOVQ AX, R13 // r30 MOVQ DX, R14 // r31 MOVQ 8(SI), AX SHLQ $1, AX MULQ 16(SI) ADDQ AX, R13 ADCQ DX, R14 MOVQ 32(SI), DX IMUL3Q $19, DX, AX MULQ 32(SI) ADDQ AX, R13 ADCQ DX, R14 // r4 = x0*2*x4 + x1*2*x3 + x2*x2 MOVQ 0(SI), AX SHLQ $1, AX MULQ 32(SI) MOVQ AX, R15 // r40 MOVQ DX, BX // r41 MOVQ 8(SI), AX SHLQ $1, AX MULQ 24(SI) ADDQ AX, R15 ADCQ DX, BX MOVQ 16(SI), AX MULQ 16(SI) ADDQ AX, R15 ADCQ DX, BX // Reduce MOVQ $2251799813685247, AX // (1<<51) - 1 SHLQ $13, CX, R8 // r01 = shld with r00 ANDQ AX, CX // r00 &= mask51 SHLQ $13, R9, R10 // r11 = shld with r10 ANDQ AX, R9 // r10 &= mask51 ADDQ R8, R9 // r10 += r01 SHLQ $13, R11, R12 // r21 = shld with r20 ANDQ AX, R11 // r20 &= mask51 ADDQ R10, R11 // r20 += r11 SHLQ $13, R13, R14 // r31 = shld with r30 ANDQ AX, R13 // r30 &= mask51 ADDQ R12, R13 // r30 += r21 SHLQ $13, R15, BX // r41 = shld with r40 ANDQ AX, R15 // r40 &= mask51 ADDQ R14, R15 // r40 += r31 IMUL3Q $19, BX, DX // r41 = r41*19 ADDQ DX, CX // r00 += r41 MOVQ CX, DX // rdx <-- r00 SHRQ $51, DX // rdx <-- r00 >> 51 ADDQ DX, R9 // r10 += r00 >> 51 MOVQ R9, DX // rdx <-- r10 SHRQ $51, DX // rdx <-- r10 >> 51 ANDQ AX, CX // r00 &= mask51 ADDQ DX, R11 // r20 += r10 >> 51 MOVQ R11, DX // rdx <-- r20 SHRQ $51, DX // rdx <-- r20 >> 51 ANDQ AX, R9 // r10 &= mask51 ADDQ DX, R13 // r30 += r20 >> 51 MOVQ R13, DX // rdx <-- r30 SHRQ $51, DX // rdx <-- r30 >> 51 ANDQ AX, R11 // r20 &= mask51 ADDQ DX, R15 // r40 += r30 >> 51 MOVQ R15, DX // rdx <-- r40 SHRQ $51, DX // rdx <-- r40 >> 51 ANDQ AX, R13 // r30 &= mask51 IMUL3Q $19, DX, DX // rdx <-- (r40 >> 51) * 19 ADDQ DX, CX // r00 += (r40 >> 51) *19 ANDQ AX, R15 // r40 &= mask51 MOVQ CX, 0(DI) MOVQ R9, 8(DI) MOVQ R11, 16(DI) MOVQ R13, 24(DI) MOVQ R15, 32(DI) RET go-ristretto-1.2.3/edwards25519/field_generic.go000066400000000000000000000300321440464505300213270ustar00rootroot00000000000000//go:build (!amd64 && !go1.13) || forcegeneric // +build !amd64,!go1.13 forcegeneric package edwards25519 // Element of the field GF(2^255 - 19) over which the elliptic // curve Edwards25519 is defined. type FieldElement [10]int32 var ( feZero FieldElement feOne = FieldElement{1, 0, 0, 0, 0, 0, 0, 0, 0, 0} feMinusOne = FieldElement{-1, 0, 0, 0, 0, 0, 0, 0, 0, 0} // sqrt(-1) feI = FieldElement{ -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482, } // -sqrt(-1) feMinusI = FieldElement{ 32595792, 7943725, -9377950, -3500415, -12389472, 272473, 25146209, 2005654, -326686, -11406482, } // parameter d of Edwards25519 feD = FieldElement{ -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116, } // double feD fe2D = FieldElement{ -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199, } // 1 / sqrt(-1-d) feInvSqrtMinusDMinusOne = FieldElement{ -6111485, -4156064, 27798727, -12243468, 25904040, -120897, -20826367, 7060776, -6093568, 1986012, } // 2 / sqrt(-1-d) feDoubleInvSqrtMinusDMinusOne = FieldElement{ -12222970, -8312128, -11511410, 9067497, -15300785, -241793, 25456130, 14121551, -12187136, 3972024, } // 2i / sqrt(-1-d) feDoubleIInvSqrtMinusDMinusOne = FieldElement{ -8930344, -9583591, 26444492, -3752533, -26044487, 743697, 2900628, -5634116, -25139868, 5270574, } // (d-1)^2 feDMinusOneSquared = FieldElement{ 15551795, -11097455, -13425098, -10125071, -11896535, 10178284, -26634327, 4729244, -5282110, -10116402, } // 1 - d^2 feOneMinusDSquared = FieldElement{ 6275446, -16617371, -22938544, -3773710, 11667077, 7397348, -27922721, 1766195, -24433858, 672203, } // (d+1)/(d-1) feDp1OverDm1 = FieldElement{ -8275156, -1370137, -4651792, -7444191, 19032992, -6350812, 7122893, -15485473, -16089458, 3776289, } // sqrt(i*d) feSqrtID = FieldElement{ -27518040, 701139, 28659366, -9930925, -13176155, -1348074, -30782278, -9245017, 26167231, 1494357, } // 1 / sqrt(1+d) feInvSqrt1pD = FieldElement{ -29089260, 4791796, 20332186, -14900950, -20532188, -371848, -1450314, 2817058, 12569934, -2635287, } epZero = ExtendedPoint{feZero, feOne, feOne, feZero} epBase = ExtendedPoint{ FieldElement{-41032219, -27199451, -7502359, -2800332, -50176896, -33336453, -33570123, -31949908, -53948439, -29257844}, FieldElement{20163995, 28827709, 65616271, 30544542, 24400674, 29683035, 27175815, 26206403, 10372291, 5663137}, feOne, FieldElement{38281802, 6116118, 27349572, 33310069, 58473857, 22289538, 47757517, 20140834, 50497352, 6414979}, } ) // Sets fe to -a. Returns fe. func (fe *FieldElement) Neg(a *FieldElement) *FieldElement { fe[0] = -a[0] fe[1] = -a[1] fe[2] = -a[2] fe[3] = -a[3] fe[4] = -a[4] fe[5] = -a[5] fe[6] = -a[6] fe[7] = -a[7] fe[8] = -a[8] fe[9] = -a[9] return fe } // Sets fe to a + b without normalizing. Returns fe. func (fe *FieldElement) add(a, b *FieldElement) *FieldElement { fe[0] = a[0] + b[0] fe[1] = a[1] + b[1] fe[2] = a[2] + b[2] fe[3] = a[3] + b[3] fe[4] = a[4] + b[4] fe[5] = a[5] + b[5] fe[6] = a[6] + b[6] fe[7] = a[7] + b[7] fe[8] = a[8] + b[8] fe[9] = a[9] + b[9] return fe } // Sets fe to a - b without normalizing. Returns fe. func (fe *FieldElement) sub(a, b *FieldElement) *FieldElement { fe[0] = a[0] - b[0] fe[1] = a[1] - b[1] fe[2] = a[2] - b[2] fe[3] = a[3] - b[3] fe[4] = a[4] - b[4] fe[5] = a[5] - b[5] fe[6] = a[6] - b[6] fe[7] = a[7] - b[7] fe[8] = a[8] - b[8] fe[9] = a[9] - b[9] return fe } // Interprets a 3-byte unsigned little endian byte-slice as int64 func load3(in []byte) int64 { var r int64 r = int64(in[0]) r |= int64(in[1]) << 8 r |= int64(in[2]) << 16 return r } // Interprets a 4-byte unsigned little endian byte-slice as int64 func load4(in []byte) int64 { var r int64 r = int64(in[0]) r |= int64(in[1]) << 8 r |= int64(in[2]) << 16 r |= int64(in[3]) << 24 return r } // Reduce the even coefficients to below 1.01*2^25 and the odd coefficients // to below 1.01*2^24. Returns fe. func (fe *FieldElement) normalize() *FieldElement { return fe.setReduced( int64(fe[0]), int64(fe[1]), int64(fe[2]), int64(fe[3]), int64(fe[4]), int64(fe[5]), int64(fe[6]), int64(fe[7]), int64(fe[8]), int64(fe[9])) } // Set fe to h0 + h1*2^26 + h2*2^51 + ... + h9*2^230. Requires a little // headroom in the inputs to store the carries. Returns fe. func (fe *FieldElement) setReduced( h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) *FieldElement { var c0, c1, c2, c3, c4, c5, c6, c7, c8, c9 int64 c0 = (h0 + (1 << 25)) >> 26 h1 += c0 h0 -= c0 << 26 c4 = (h4 + (1 << 25)) >> 26 h5 += c4 h4 -= c4 << 26 c1 = (h1 + (1 << 24)) >> 25 h2 += c1 h1 -= c1 << 25 c5 = (h5 + (1 << 24)) >> 25 h6 += c5 h5 -= c5 << 25 c2 = (h2 + (1 << 25)) >> 26 h3 += c2 h2 -= c2 << 26 c6 = (h6 + (1 << 25)) >> 26 h7 += c6 h6 -= c6 << 26 c3 = (h3 + (1 << 24)) >> 25 h4 += c3 h3 -= c3 << 25 c7 = (h7 + (1 << 24)) >> 25 h8 += c7 h7 -= c7 << 25 c4 = (h4 + (1 << 25)) >> 26 h5 += c4 h4 -= c4 << 26 c8 = (h8 + (1 << 25)) >> 26 h9 += c8 h8 -= c8 << 26 c9 = (h9 + (1 << 24)) >> 25 h0 += c9 * 19 h9 -= c9 << 25 c0 = (h0 + (1 << 25)) >> 26 h1 += c0 h0 -= c0 << 26 fe[0] = int32(h0) fe[1] = int32(h1) fe[2] = int32(h2) fe[3] = int32(h3) fe[4] = int32(h4) fe[5] = int32(h5) fe[6] = int32(h6) fe[7] = int32(h7) fe[8] = int32(h8) fe[9] = int32(h9) return fe } // Set fe to a if b == 1. Requires b to be either 0 or 1. func (fe *FieldElement) ConditionalSet(a *FieldElement, b int32) { b = -b // b == 0b11111111111111111111111111111111 or 0. fe[0] ^= b & (fe[0] ^ a[0]) fe[1] ^= b & (fe[1] ^ a[1]) fe[2] ^= b & (fe[2] ^ a[2]) fe[3] ^= b & (fe[3] ^ a[3]) fe[4] ^= b & (fe[4] ^ a[4]) fe[5] ^= b & (fe[5] ^ a[5]) fe[6] ^= b & (fe[6] ^ a[6]) fe[7] ^= b & (fe[7] ^ a[7]) fe[8] ^= b & (fe[8] ^ a[8]) fe[9] ^= b & (fe[9] ^ a[9]) } // Write fe to s in little endian. Returns fe. func (fe *FieldElement) BytesInto(s *[32]byte) *FieldElement { var carry [10]int32 q := (19*fe[9] + (1 << 24)) >> 25 q = (fe[0] + q) >> 26 q = (fe[1] + q) >> 25 q = (fe[2] + q) >> 26 q = (fe[3] + q) >> 25 q = (fe[4] + q) >> 26 q = (fe[5] + q) >> 25 q = (fe[6] + q) >> 26 q = (fe[7] + q) >> 25 q = (fe[8] + q) >> 26 q = (fe[9] + q) >> 25 fe[0] += 19 * q carry[0] = fe[0] >> 26 fe[1] += carry[0] fe[0] -= carry[0] << 26 carry[1] = fe[1] >> 25 fe[2] += carry[1] fe[1] -= carry[1] << 25 carry[2] = fe[2] >> 26 fe[3] += carry[2] fe[2] -= carry[2] << 26 carry[3] = fe[3] >> 25 fe[4] += carry[3] fe[3] -= carry[3] << 25 carry[4] = fe[4] >> 26 fe[5] += carry[4] fe[4] -= carry[4] << 26 carry[5] = fe[5] >> 25 fe[6] += carry[5] fe[5] -= carry[5] << 25 carry[6] = fe[6] >> 26 fe[7] += carry[6] fe[6] -= carry[6] << 26 carry[7] = fe[7] >> 25 fe[8] += carry[7] fe[7] -= carry[7] << 25 carry[8] = fe[8] >> 26 fe[9] += carry[8] fe[8] -= carry[8] << 26 carry[9] = fe[9] >> 25 fe[9] -= carry[9] << 25 s[0] = byte(fe[0] >> 0) s[1] = byte(fe[0] >> 8) s[2] = byte(fe[0] >> 16) s[3] = byte((fe[0] >> 24) | (fe[1] << 2)) s[4] = byte(fe[1] >> 6) s[5] = byte(fe[1] >> 14) s[6] = byte((fe[1] >> 22) | (fe[2] << 3)) s[7] = byte(fe[2] >> 5) s[8] = byte(fe[2] >> 13) s[9] = byte((fe[2] >> 21) | (fe[3] << 5)) s[10] = byte(fe[3] >> 3) s[11] = byte(fe[3] >> 11) s[12] = byte((fe[3] >> 19) | (fe[4] << 6)) s[13] = byte(fe[4] >> 2) s[14] = byte(fe[4] >> 10) s[15] = byte(fe[4] >> 18) s[16] = byte(fe[5] >> 0) s[17] = byte(fe[5] >> 8) s[18] = byte(fe[5] >> 16) s[19] = byte((fe[5] >> 24) | (fe[6] << 1)) s[20] = byte(fe[6] >> 7) s[21] = byte(fe[6] >> 15) s[22] = byte((fe[6] >> 23) | (fe[7] << 3)) s[23] = byte(fe[7] >> 5) s[24] = byte(fe[7] >> 13) s[25] = byte((fe[7] >> 21) | (fe[8] << 4)) s[26] = byte(fe[8] >> 4) s[27] = byte(fe[8] >> 12) s[28] = byte((fe[8] >> 20) | (fe[9] << 6)) s[29] = byte(fe[9] >> 2) s[30] = byte(fe[9] >> 10) s[31] = byte(fe[9] >> 18) return fe } // Sets fe to the little endian number encoded in buf modulo 2^255-19. // Ignores the highest bit in buf. Returns fe. func (fe *FieldElement) SetBytes(buf *[32]byte) *FieldElement { return fe.setReduced( load4(buf[:]), load3(buf[4:])<<6, load3(buf[7:])<<5, load3(buf[10:])<<3, load3(buf[13:])<<2, load4(buf[16:]), load3(buf[20:])<<7, load3(buf[23:])<<5, load3(buf[26:])<<4, (load3(buf[29:])&8388607)<<2, ) } // Sets fe to a * b. Returns fe. func (fe *FieldElement) Mul(a, b *FieldElement) *FieldElement { a0 := int64(a[0]) a1 := int64(a[1]) a2 := int64(a[2]) a3 := int64(a[3]) a4 := int64(a[4]) a5 := int64(a[5]) a6 := int64(a[6]) a7 := int64(a[7]) a8 := int64(a[8]) a9 := int64(a[9]) a1_2 := int64(2 * a[1]) a3_2 := int64(2 * a[3]) a5_2 := int64(2 * a[5]) a7_2 := int64(2 * a[7]) a9_2 := int64(2 * a[9]) b0 := int64(b[0]) b1 := int64(b[1]) b2 := int64(b[2]) b3 := int64(b[3]) b4 := int64(b[4]) b5 := int64(b[5]) b6 := int64(b[6]) b7 := int64(b[7]) b8 := int64(b[8]) b9 := int64(b[9]) b1_19 := int64(19 * b[1]) b2_19 := int64(19 * b[2]) b3_19 := int64(19 * b[3]) b4_19 := int64(19 * b[4]) b5_19 := int64(19 * b[5]) b6_19 := int64(19 * b[6]) b7_19 := int64(19 * b[7]) b8_19 := int64(19 * b[8]) b9_19 := int64(19 * b[9]) h0 := a0*b0 + a1_2*b9_19 + a2*b8_19 + a3_2*b7_19 + a4*b6_19 + a5_2*b5_19 + a6*b4_19 + a7_2*b3_19 + a8*b2_19 + a9_2*b1_19 h1 := a0*b1 + a1*b0 + a2*b9_19 + a3*b8_19 + a4*b7_19 + a5*b6_19 + a6*b5_19 + a7*b4_19 + a8*b3_19 + a9*b2_19 h2 := a0*b2 + a1_2*b1 + a2*b0 + a3_2*b9_19 + a4*b8_19 + a5_2*b7_19 + a6*b6_19 + a7_2*b5_19 + a8*b4_19 + a9_2*b3_19 h3 := a0*b3 + a1*b2 + a2*b1 + a3*b0 + a4*b9_19 + a5*b8_19 + a6*b7_19 + a7*b6_19 + a8*b5_19 + a9*b4_19 h4 := a0*b4 + a1_2*b3 + a2*b2 + a3_2*b1 + a4*b0 + a5_2*b9_19 + a6*b8_19 + a7_2*b7_19 + a8*b6_19 + a9_2*b5_19 h5 := a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0 + a6*b9_19 + a7*b8_19 + a8*b7_19 + a9*b6_19 h6 := a0*b6 + a1_2*b5 + a2*b4 + a3_2*b3 + a4*b2 + a5_2*b1 + a6*b0 + a7_2*b9_19 + a8*b8_19 + a9_2*b7_19 h7 := a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0 + a8*b9_19 + a9*b8_19 h8 := a0*b8 + a1_2*b7 + a2*b6 + a3_2*b5 + a4*b4 + a5_2*b3 + a6*b2 + a7_2*b1 + a8*b0 + a9_2*b9_19 h9 := a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0 return fe.setReduced(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) } // Returns the unnormalized coefficients of fe^2. func (fe *FieldElement) square() (h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) { f0 := int64(fe[0]) f1 := int64(fe[1]) f2 := int64(fe[2]) f3 := int64(fe[3]) f4 := int64(fe[4]) f5 := int64(fe[5]) f6 := int64(fe[6]) f7 := int64(fe[7]) f8 := int64(fe[8]) f9 := int64(fe[9]) f0_2 := int64(2 * fe[0]) f1_2 := int64(2 * fe[1]) f2_2 := int64(2 * fe[2]) f3_2 := int64(2 * fe[3]) f4_2 := int64(2 * fe[4]) f5_2 := int64(2 * fe[5]) f6_2 := int64(2 * fe[6]) f7_2 := int64(2 * fe[7]) f5_38 := 38 * f5 f6_19 := 19 * f6 f7_38 := 38 * f7 f8_19 := 19 * f8 f9_38 := 38 * f9 h0 = f0*f0 + f1_2*f9_38 + f2_2*f8_19 + f3_2*f7_38 + f4_2*f6_19 + f5*f5_38 h1 = f0_2*f1 + f2*f9_38 + f3_2*f8_19 + f4*f7_38 + f5_2*f6_19 h2 = f0_2*f2 + f1_2*f1 + f3_2*f9_38 + f4_2*f8_19 + f5_2*f7_38 + f6*f6_19 h3 = f0_2*f3 + f1_2*f2 + f4*f9_38 + f5_2*f8_19 + f6*f7_38 h4 = f0_2*f4 + f1_2*f3_2 + f2*f2 + f5_2*f9_38 + f6_2*f8_19 + f7*f7_38 h5 = f0_2*f5 + f1_2*f4 + f2_2*f3 + f6*f9_38 + f7_2*f8_19 h6 = f0_2*f6 + f1_2*f5_2 + f2_2*f4 + f3_2*f3 + f7_2*f9_38 + f8*f8_19 h7 = f0_2*f7 + f1_2*f6 + f2_2*f5 + f3_2*f4 + f8*f9_38 h8 = f0_2*f8 + f1_2*f7_2 + f2_2*f6 + f3_2*f5_2 + f4*f4 + f9*f9_38 h9 = f0_2*f9 + f1_2*f8 + f2_2*f7 + f3_2*f6 + f4_2*f5 return } // Sets fe to a^2. Returns fe. func (fe *FieldElement) Square(a *FieldElement) *FieldElement { h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := a.square() return fe.setReduced(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) } // Sets fe to 2 * a^2. Returns fe. func (fe *FieldElement) DoubledSquare(a *FieldElement) *FieldElement { h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := a.square() h0 += h0 h1 += h1 h2 += h2 h3 += h3 h4 += h4 h5 += h5 h6 += h6 h7 += h7 h8 += h8 h9 += h9 return fe.setReduced(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) } go-ristretto-1.2.3/edwards25519/field_mul64.go000066400000000000000000000165521440464505300206750ustar00rootroot00000000000000//go:build go1.13 && !forcegeneric // +build go1.13,!forcegeneric package edwards25519 import ( "math/bits" ) // Sets fe to a * b. Returns fe. func (fe *FieldElement) Mul(a, b *FieldElement) *FieldElement { a0 := a[0] a1 := a[1] a2 := a[2] a3 := a[3] a4 := a[4] b0 := b[0] b1 := b[1] b2 := b[2] b3 := b[3] b4 := b[4] b1_19 := b1 * 19 b2_19 := b2 * 19 b3_19 := b3 * 19 b4_19 := b4 * 19 var carry, h, l uint64 // TODO make sure we only use bits.Add64 if it's constant-time c0h, c0l := bits.Mul64(b0, a0) h, l = bits.Mul64(b1_19, a4) c0l, carry = bits.Add64(c0l, l, 0) c0h, _ = bits.Add64(c0h, h, carry) h, l = bits.Mul64(b2_19, a3) c0l, carry = bits.Add64(c0l, l, 0) c0h, _ = bits.Add64(c0h, h, carry) h, l = bits.Mul64(b3_19, a2) c0l, carry = bits.Add64(c0l, l, 0) c0h, _ = bits.Add64(c0h, h, carry) h, l = bits.Mul64(b4_19, a1) c0l, carry = bits.Add64(c0l, l, 0) c0h, _ = bits.Add64(c0h, h, carry) c1h, c1l := bits.Mul64(b0, a1) h, l = bits.Mul64(b1, a0) c1l, carry = bits.Add64(c1l, l, 0) c1h, _ = bits.Add64(c1h, h, carry) h, l = bits.Mul64(b2_19, a4) c1l, carry = bits.Add64(c1l, l, 0) c1h, _ = bits.Add64(c1h, h, carry) h, l = bits.Mul64(b3_19, a3) c1l, carry = bits.Add64(c1l, l, 0) c1h, _ = bits.Add64(c1h, h, carry) h, l = bits.Mul64(b4_19, a2) c1l, carry = bits.Add64(c1l, l, 0) c1h, _ = bits.Add64(c1h, h, carry) c1l, carry = bits.Add64((c0l>>51)|(c0h<<13), c1l, 0) c1h, _ = bits.Add64(c1h, 0, carry) c0l &= 0x7ffffffffffff c2h, c2l := bits.Mul64(b0, a2) h, l = bits.Mul64(b1, a1) c2l, carry = bits.Add64(c2l, l, 0) c2h, _ = bits.Add64(c2h, h, carry) h, l = bits.Mul64(b2, a0) c2l, carry = bits.Add64(c2l, l, 0) c2h, _ = bits.Add64(c2h, h, carry) h, l = bits.Mul64(b3_19, a4) c2l, carry = bits.Add64(c2l, l, 0) c2h, _ = bits.Add64(c2h, h, carry) h, l = bits.Mul64(b4_19, a3) c2l, carry = bits.Add64(c2l, l, 0) c2h, _ = bits.Add64(c2h, h, carry) c2l, carry = bits.Add64((c1l>>51)|(c1h<<13), c2l, 0) c2h, _ = bits.Add64(c2h, 0, carry) c1l &= 0x7ffffffffffff c3h, c3l := bits.Mul64(b0, a3) h, l = bits.Mul64(b1, a2) c3l, carry = bits.Add64(c3l, l, 0) c3h, _ = bits.Add64(c3h, h, carry) h, l = bits.Mul64(b2, a1) c3l, carry = bits.Add64(c3l, l, 0) c3h, _ = bits.Add64(c3h, h, carry) h, l = bits.Mul64(b3, a0) c3l, carry = bits.Add64(c3l, l, 0) c3h, _ = bits.Add64(c3h, h, carry) h, l = bits.Mul64(b4_19, a4) c3l, carry = bits.Add64(c3l, l, 0) c3h, _ = bits.Add64(c3h, h, carry) c3l, carry = bits.Add64((c2l>>51)|(c2h<<13), c3l, 0) c3h, _ = bits.Add64(c3h, 0, carry) c2l &= 0x7ffffffffffff c4h, c4l := bits.Mul64(b0, a4) h, l = bits.Mul64(b1, a3) c4l, carry = bits.Add64(c4l, l, 0) c4h, _ = bits.Add64(c4h, h, carry) h, l = bits.Mul64(b2, a2) c4l, carry = bits.Add64(c4l, l, 0) c4h, _ = bits.Add64(c4h, h, carry) h, l = bits.Mul64(b3, a1) c4l, carry = bits.Add64(c4l, l, 0) c4h, _ = bits.Add64(c4h, h, carry) h, l = bits.Mul64(b4, a0) c4l, carry = bits.Add64(c4l, l, 0) c4h, _ = bits.Add64(c4h, h, carry) c4l, carry = bits.Add64((c3l>>51)|(c3h<<13), c4l, 0) c4h, _ = bits.Add64(c4h, 0, carry) c3l &= 0x7ffffffffffff carry = ((c4l >> 51) | (c4h << 13)) c4l &= 0x7ffffffffffff c0l += carry * 19 c1l += c0l >> 51 c0l &= 0x7ffffffffffff fe[0] = c0l fe[1] = c1l fe[2] = c2l fe[3] = c3l fe[4] = c4l return fe } // Sets fe to a^2. Returns fe. func (fe *FieldElement) Square(a *FieldElement) *FieldElement { a0 := a[0] a1 := a[1] a2 := a[2] a3 := a[3] a4 := a[4] a4_38 := a4 * 38 var carry, h, l uint64 c0h, c0l := bits.Mul64(a0, a0) h, l = bits.Mul64(a4*38, a1) c0l, carry = bits.Add64(c0l, l, 0) c0h, _ = bits.Add64(c0h, h, carry) h, l = bits.Mul64(a2*38, a3) c0l, carry = bits.Add64(c0l, l, 0) c0h, _ = bits.Add64(c0h, h, carry) c1h, c1l := bits.Mul64(2*a0, a1) h, l = bits.Mul64(a2, a4_38) c1l, carry = bits.Add64(c1l, l, 0) c1h, _ = bits.Add64(c1h, h, carry) h, l = bits.Mul64(a3*19, a3) c1l, carry = bits.Add64(c1l, l, 0) c1h, _ = bits.Add64(c1h, h, carry) c1l, carry = bits.Add64((c0l>>51)|(c0h<<13), c1l, 0) c1h, _ = bits.Add64(c1h, 0, carry) c0l &= 0x7ffffffffffff c2h, c2l := bits.Mul64(a0, 2*a2) h, l = bits.Mul64(a1, a1) c2l, carry = bits.Add64(c2l, l, 0) c2h, _ = bits.Add64(c2h, h, carry) h, l = bits.Mul64(a4_38, a3) c2l, carry = bits.Add64(c2l, l, 0) c2h, _ = bits.Add64(c2h, h, carry) c2l, carry = bits.Add64((c1l>>51)|(c1h<<13), c2l, 0) c2h, _ = bits.Add64(c2h, 0, carry) c1l &= 0x7ffffffffffff c3h, c3l := bits.Mul64(a0, 2*a3) h, l = bits.Mul64(2*a1, a2) c3l, carry = bits.Add64(c3l, l, 0) c3h, _ = bits.Add64(c3h, h, carry) h, l = bits.Mul64(a4*19, a4) c3l, carry = bits.Add64(c3l, l, 0) c3h, _ = bits.Add64(c3h, h, carry) c3l, carry = bits.Add64((c2l>>51)|(c2h<<13), c3l, 0) c3h, _ = bits.Add64(c3h, 0, carry) c2l &= 0x7ffffffffffff c4h, c4l := bits.Mul64(a0, 2*a4) h, l = bits.Mul64(a2, a2) c4l, carry = bits.Add64(c4l, l, 0) c4h, _ = bits.Add64(c4h, h, carry) h, l = bits.Mul64(a3, 2*a1) c4l, carry = bits.Add64(c4l, l, 0) c4h, _ = bits.Add64(c4h, h, carry) c4l, carry = bits.Add64((c3l>>51)|(c3h<<13), c4l, 0) c4h, _ = bits.Add64(c4h, 0, carry) c3l &= 0x7ffffffffffff carry = ((c4l >> 51) | (c4h << 13)) c0l += carry * 19 c4l &= 0x7ffffffffffff c1l += c0l >> 51 c0l &= 0x7ffffffffffff fe[0] = c0l fe[1] = c1l fe[2] = c2l fe[3] = c3l fe[4] = c4l return fe } // Sets fe to 2 * a^2. Returns fe. func (fe *FieldElement) DoubledSquare(a *FieldElement) *FieldElement { a0 := a[0] a1 := a[1] a2 := a[2] a3 := a[3] a4 := a[4] a0_2 := a0 * 2 a1_2 := a1 * 2 a2_2 := a2 * 2 a3_38 := a3 * 38 a4_38 := a4 * 38 var carry, h, l uint64 c0h, c0l := bits.Mul64(a0, a0_2) h, l = bits.Mul64(a4_38, a1_2) c0l, carry = bits.Add64(c0l, l, 0) c0h, _ = bits.Add64(c0h, h, carry) h, l = bits.Mul64(a2_2, a3_38) c0l, carry = bits.Add64(c0l, l, 0) c0h, _ = bits.Add64(c0h, h, carry) c1h, c1l := bits.Mul64(a0_2, a1_2) h, l = bits.Mul64(a2_2, a4_38) c1l, carry = bits.Add64(c1l, l, 0) c1h, _ = bits.Add64(c1h, h, carry) h, l = bits.Mul64(a3_38, a3) c1l, carry = bits.Add64(c1l, l, 0) c1h, _ = bits.Add64(c1h, h, carry) c1l, carry = bits.Add64((c0l>>51)|(c0h<<13), c1l, 0) c1h, _ = bits.Add64(c1h, 0, carry) c0l &= 0x7ffffffffffff c2h, c2l := bits.Mul64(a0_2, a2_2) h, l = bits.Mul64(a1_2, a1) c2l, carry = bits.Add64(c2l, l, 0) c2h, _ = bits.Add64(c2h, h, carry) h, l = bits.Mul64(a4_38, a3*2) c2l, carry = bits.Add64(c2l, l, 0) c2h, _ = bits.Add64(c2h, h, carry) c2l, carry = bits.Add64((c1l>>51)|(c1h<<13), c2l, 0) c2h, _ = bits.Add64(c2h, 0, carry) c1l &= 0x7ffffffffffff c3h, c3l := bits.Mul64(a0_2, 2*a3) h, l = bits.Mul64(a1_2, a2_2) c3l, carry = bits.Add64(c3l, l, 0) c3h, _ = bits.Add64(c3h, h, carry) h, l = bits.Mul64(a4_38, a4) c3l, carry = bits.Add64(c3l, l, 0) c3h, _ = bits.Add64(c3h, h, carry) c3l, carry = bits.Add64((c2l>>51)|(c2h<<13), c3l, 0) c3h, _ = bits.Add64(c3h, 0, carry) c2l &= 0x7ffffffffffff c4h, c4l := bits.Mul64(a0_2, 2*a4) h, l = bits.Mul64(a2_2, a2) c4l, carry = bits.Add64(c4l, l, 0) c4h, _ = bits.Add64(c4h, h, carry) h, l = bits.Mul64(2*a3, a1_2) c4l, carry = bits.Add64(c4l, l, 0) c4h, _ = bits.Add64(c4h, h, carry) c4l, carry = bits.Add64((c3l>>51)|(c3h<<13), c4l, 0) c4h, _ = bits.Add64(c4h, 0, carry) c3l &= 0x7ffffffffffff carry = ((c4l >> 51) | (c4h << 13)) c0l += carry * 19 c4l &= 0x7ffffffffffff c1l += c0l >> 51 c0l &= 0x7ffffffffffff fe[0] = c0l fe[1] = c1l fe[2] = c2l fe[3] = c3l fe[4] = c4l return fe } go-ristretto-1.2.3/edwards25519/field_radix51.go000066400000000000000000000172141440464505300211770ustar00rootroot00000000000000//go:build (amd64 && !forcegeneric) || (go1.13 && !forcegeneric) // +build amd64,!forcegeneric go1.13,!forcegeneric package edwards25519 // Element of the field GF(2^255 - 19) over which the elliptic // curve Edwards25519 is defined. type FieldElement [5]uint64 var ( feZero FieldElement feOne = FieldElement{1, 0, 0, 0, 0} feMinusOne = FieldElement{2251799813685228, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247} // sqrt(-1) feI = FieldElement{ 1718705420411056, 234908883556509, 2233514472574048, 2117202627021982, 765476049583133, } // -sqrt(-1) feMinusI = FieldElement{ 533094393274173, 2016890930128738, 18285341111199, 134597186663265, 1486323764102114, } // parameter d of Edwards25519 feD = FieldElement{ 929955233495203, 466365720129213, 1662059464998953, 2033849074728123, 1442794654840575, } // double feD fe2D = FieldElement{ 1859910466990425, 932731440258426, 1072319116312658, 1815898335770999, 633789495995903, } // 1 / sqrt(-1-d) feInvSqrtMinusDMinusOne = FieldElement{ 1972891073822467, 1430154612583622, 2243686579258279, 473840635492096, 133279003116800, } // 2 / sqrt(-1-d) feDoubleInvSqrtMinusDMinusOne = FieldElement{ 1693982333959686, 608509411481997, 2235573344831311, 947681270984193, 266558006233600, } // 2i / sqrt(-1-d) feDoubleIInvSqrtMinusDMinusOne = FieldElement{ 1608655899704280, 1999971613377227, 49908634785720, 1873700692181652, 353702208628067, } // (d-1)^2 feDMinusOneSquared = FieldElement{ 1507062230895904, 1572317787530805, 683053064812840, 317374165784489, 1572899562415810, } // 1 - d^2 feOneMinusDSquared = FieldElement{ 1136626929484150, 1998550399581263, 496427632559748, 118527312129759, 45110755273534, } // (d+1)/(d-1) feDp1OverDm1 = FieldElement{ 2159851467815724, 1752228607624431, 1825604053920671, 1212587319275468, 253422448836237, } // sqrt(i*d) feSqrtID = FieldElement{ 2298852427963285, 3837146560810661, 4413131899466403, 3883177008057528, 2352084440532925, } // 1/sqrt(d+1) feInvSqrt1pD = FieldElement{ 321571956990465, 1251814006996634, 2226845496292387, 189049560751797, 2074948709371214, } epZero = ExtendedPoint{feZero, feOne, feOne, feZero} epBase = ExtendedPoint{ FieldElement{2678275328304575, 4315672520525287, 2266428086574206, 2359477563015859, 2540138899492839}, FieldElement{1934594822876571, 2049809580636559, 1991994783322914, 1758681962032007, 380046701118659}, feOne, FieldElement{410445769351754, 2235400917701188, 1495825632738689, 1351628537510093, 430502003771208}, } ) // Neg sets fe to -a. Returns fe. func (fe *FieldElement) Neg(a *FieldElement) *FieldElement { var t FieldElement t = *a t[1] += t[0] >> 51 t[0] = t[0] & 0x7ffffffffffff t[2] += t[1] >> 51 t[1] = t[1] & 0x7ffffffffffff t[3] += t[2] >> 51 t[2] = t[2] & 0x7ffffffffffff t[4] += t[3] >> 51 t[3] = t[3] & 0x7ffffffffffff t[0] += (t[4] >> 51) * 19 t[4] = t[4] & 0x7ffffffffffff fe[0] = 0xfffffffffffda - t[0] fe[1] = 0xffffffffffffe - t[1] fe[2] = 0xffffffffffffe - t[2] fe[3] = 0xffffffffffffe - t[3] fe[4] = 0xffffffffffffe - t[4] return fe } // Sets fe to a-b. Returns fe. func (fe *FieldElement) sub(a, b *FieldElement) *FieldElement { var t FieldElement t = *b t[1] += t[0] >> 51 t[0] = t[0] & 0x7ffffffffffff t[2] += t[1] >> 51 t[1] = t[1] & 0x7ffffffffffff t[3] += t[2] >> 51 t[2] = t[2] & 0x7ffffffffffff t[4] += t[3] >> 51 t[3] = t[3] & 0x7ffffffffffff t[0] += (t[4] >> 51) * 19 t[4] = t[4] & 0x7ffffffffffff fe[0] = (a[0] + 0xfffffffffffda) - t[0] fe[1] = (a[1] + 0xffffffffffffe) - t[1] fe[2] = (a[2] + 0xffffffffffffe) - t[2] fe[3] = (a[3] + 0xffffffffffffe) - t[3] fe[4] = (a[4] + 0xffffffffffffe) - t[4] return fe } // Sets fe to a + b without normalizing. Returns fe. func (fe *FieldElement) add(a, b *FieldElement) *FieldElement { fe[0] = a[0] + b[0] fe[1] = a[1] + b[1] fe[2] = a[2] + b[2] fe[3] = a[3] + b[3] fe[4] = a[4] + b[4] return fe } // Reduce the even coefficients. Returns fe. func (fe *FieldElement) normalize() *FieldElement { return fe.setReduced(fe) } // Set fe to a reduced version of a. Returns fe. func (fe *FieldElement) setReduced(a *FieldElement) *FieldElement { *fe = *a fe[1] += fe[0] >> 51 fe[0] = fe[0] & 0x7ffffffffffff fe[2] += fe[1] >> 51 fe[1] = fe[1] & 0x7ffffffffffff fe[3] += fe[2] >> 51 fe[2] = fe[2] & 0x7ffffffffffff fe[4] += fe[3] >> 51 fe[3] = fe[3] & 0x7ffffffffffff fe[0] += (fe[4] >> 51) * 19 fe[4] = fe[4] & 0x7ffffffffffff c := (fe[0] + 19) >> 51 c = (fe[1] + c) >> 51 c = (fe[2] + c) >> 51 c = (fe[3] + c) >> 51 c = (fe[4] + c) >> 51 fe[0] += 19 * c fe[1] += fe[0] >> 51 fe[0] = fe[0] & 0x7ffffffffffff fe[2] += fe[1] >> 51 fe[1] = fe[1] & 0x7ffffffffffff fe[3] += fe[2] >> 51 fe[2] = fe[2] & 0x7ffffffffffff fe[4] += fe[3] >> 51 fe[3] = fe[3] & 0x7ffffffffffff fe[4] = fe[4] & 0x7ffffffffffff return fe } // Set fe to a if b == 1. Requires b to be either 0 or 1. func (fe *FieldElement) ConditionalSet(a *FieldElement, b int32) { b2 := uint64(1-b) - 1 fe[0] ^= b2 & (fe[0] ^ a[0]) fe[1] ^= b2 & (fe[1] ^ a[1]) fe[2] ^= b2 & (fe[2] ^ a[2]) fe[3] ^= b2 & (fe[3] ^ a[3]) fe[4] ^= b2 & (fe[4] ^ a[4]) } // Write fe to s in little endian. Returns fe. func (fe *FieldElement) BytesInto(s *[32]byte) *FieldElement { var t FieldElement t.setReduced(fe) s[0] = byte(t[0] & 0xff) s[1] = byte((t[0] >> 8) & 0xff) s[2] = byte((t[0] >> 16) & 0xff) s[3] = byte((t[0] >> 24) & 0xff) s[4] = byte((t[0] >> 32) & 0xff) s[5] = byte((t[0] >> 40) & 0xff) s[6] = byte((t[0] >> 48)) s[6] ^= byte((t[1] << 3) & 0xf8) s[7] = byte((t[1] >> 5) & 0xff) s[8] = byte((t[1] >> 13) & 0xff) s[9] = byte((t[1] >> 21) & 0xff) s[10] = byte((t[1] >> 29) & 0xff) s[11] = byte((t[1] >> 37) & 0xff) s[12] = byte((t[1] >> 45)) s[12] ^= byte((t[2] << 6) & 0xc0) s[13] = byte((t[2] >> 2) & 0xff) s[14] = byte((t[2] >> 10) & 0xff) s[15] = byte((t[2] >> 18) & 0xff) s[16] = byte((t[2] >> 26) & 0xff) s[17] = byte((t[2] >> 34) & 0xff) s[18] = byte((t[2] >> 42) & 0xff) s[19] = byte((t[2] >> 50)) s[19] ^= byte((t[3] << 1) & 0xfe) s[20] = byte((t[3] >> 7) & 0xff) s[21] = byte((t[3] >> 15) & 0xff) s[22] = byte((t[3] >> 23) & 0xff) s[23] = byte((t[3] >> 31) & 0xff) s[24] = byte((t[3] >> 39) & 0xff) s[25] = byte((t[3] >> 47)) s[25] ^= byte((t[4] << 4) & 0xf0) s[26] = byte((t[4] >> 4) & 0xff) s[27] = byte((t[4] >> 12) & 0xff) s[28] = byte((t[4] >> 20) & 0xff) s[29] = byte((t[4] >> 28) & 0xff) s[30] = byte((t[4] >> 36) & 0xff) s[31] = byte((t[4] >> 44)) return fe } // Sets fe to the little endian number encoded in buf modulo 2^255-19. // Ignores the highest bit in buf. Returns fe. func (fe *FieldElement) SetBytes(buf *[32]byte) *FieldElement { fe[0] = (uint64(buf[0]) | (uint64(buf[1]) << 8) | (uint64(buf[2]) << 16) | (uint64(buf[3]) << 24) | (uint64(buf[4]) << 32) | (uint64(buf[5]) << 40) | (uint64(buf[6]&7) << 48)) fe[1] = ((uint64(buf[6]) >> 3) | (uint64(buf[7]) << 5) | (uint64(buf[8]) << 13) | (uint64(buf[9]) << 21) | (uint64(buf[10]) << 29) | (uint64(buf[11]) << 37) | (uint64(buf[12]&63) << 45)) fe[2] = ((uint64(buf[12]) >> 6) | (uint64(buf[13]) << 2) | (uint64(buf[14]) << 10) | (uint64(buf[15]) << 18) | (uint64(buf[16]) << 26) | (uint64(buf[17]) << 34) | (uint64(buf[18]) << 42) | (uint64(buf[19]&1) << 50)) fe[3] = ((uint64(buf[19]) >> 1) | (uint64(buf[20]) << 7) | (uint64(buf[21]) << 15) | (uint64(buf[22]) << 23) | (uint64(buf[23]) << 31) | (uint64(buf[24]) << 39) | (uint64(buf[25]&15) << 47)) fe[4] = ((uint64(buf[25]) >> 4) | (uint64(buf[26]) << 4) | (uint64(buf[27]) << 12) | (uint64(buf[28]) << 20) | (uint64(buf[29]) << 28) | (uint64(buf[30]) << 36) | (uint64(buf[31]&127) << 44)) return fe } go-ristretto-1.2.3/edwards25519/field_test.go000066400000000000000000000121201440464505300206700ustar00rootroot00000000000000package edwards25519_test import ( "math/big" "math/rand" "os" "testing" "github.com/bwesterb/go-ristretto/edwards25519" ) var bi25519 big.Int var biL big.Int var rnd *rand.Rand func TestFeBigIntPacking(t *testing.T) { var bi big.Int var fe edwards25519.FieldElement for i := 0; i < 100; i++ { bi.Rand(rnd, &bi25519) fe.SetBigInt(&bi) if fe.BigInt().Cmp(&bi) != 0 { t.Fatalf("BigInt o SetBigInt != id (%v != %v)", &bi, fe.BigInt()) } } } func TestFePacking(t *testing.T) { var bi big.Int var fe1, fe2 edwards25519.FieldElement for i := 0; i < 100; i++ { bi.Rand(rnd, &bi25519) fe1.SetBigInt(&bi) buf := fe1.Bytes() fe2.SetBytes(&buf) if !fe1.Equals(&fe2) { t.Fatalf("SetBytes o Bytes != id (%v != %v)", &fe1, &fe2) } } } // TODO test unnormalized field elements func TestFeMul(t *testing.T) { var bi1, bi2, bi3 big.Int var fe1, fe2, fe3 edwards25519.FieldElement for i := 0; i < 100; i++ { bi1.Rand(rnd, &bi25519) bi2.Rand(rnd, &bi25519) bi3.Mul(&bi1, &bi2) bi3.Mod(&bi3, &bi25519) fe1.SetBigInt(&bi1) fe2.SetBigInt(&bi2) if fe3.Mul(&fe1, &fe2).BigInt().Cmp(&bi3) != 0 { t.Fatalf("%v * %v = %v != %v", &bi1, &bi2, &bi3, &fe3) } } } func TestFeSquare(t *testing.T) { var bi1, bi2 big.Int var fe1, fe2 edwards25519.FieldElement for i := 0; i < 100; i++ { bi1.Rand(rnd, &bi25519) bi2.Mul(&bi1, &bi1) bi2.Mod(&bi2, &bi25519) fe1.SetBigInt(&bi1) if fe2.Square(&fe1).BigInt().Cmp(&bi2) != 0 { t.Fatalf("%v^2 = %v != %v", &bi1, &bi2, &fe2) } } } func TestFeSub(t *testing.T) { var bi1, bi2, bi3 big.Int var fe1, fe2, fe3 edwards25519.FieldElement for i := 0; i < 100; i++ { bi1.Rand(rnd, &bi25519) bi2.Rand(rnd, &bi25519) bi3.Sub(&bi1, &bi2) bi3.Mod(&bi3, &bi25519) fe1.SetBigInt(&bi1) fe2.SetBigInt(&bi2) if fe3.Sub(&fe1, &fe2).BigInt().Cmp(&bi3) != 0 { t.Fatalf("%v - %v = %v != %v", &bi1, &bi2, &bi3, &fe3) } } } func TestFeAdd(t *testing.T) { var bi1, bi2, bi3 big.Int var fe1, fe2, fe3 edwards25519.FieldElement for i := 0; i < 100; i++ { bi1.Rand(rnd, &bi25519) bi2.Rand(rnd, &bi25519) bi3.Add(&bi1, &bi2) bi3.Mod(&bi3, &bi25519) fe1.SetBigInt(&bi1) fe2.SetBigInt(&bi2) if fe3.Add(&fe1, &fe2).BigInt().Cmp(&bi3) != 0 { t.Fatalf("%v + %v = %v != %v", &bi1, &bi2, &bi3, &fe3) } } } func TestFeInverse(t *testing.T) { var bi1, bi2 big.Int var fe1, fe2 edwards25519.FieldElement for i := 0; i < 100; i++ { bi1.Rand(rnd, &bi25519) bi2.ModInverse(&bi1, &bi25519) fe1.SetBigInt(&bi1) if fe2.Inverse(&fe1).BigInt().Cmp(&bi2) != 0 { t.Fatalf("1/%v = %v != %v", &bi1, &bi2, &fe2) } } } func TestFeInvSqrtI(t *testing.T) { var bi big.Int var fe1, fe2, feI edwards25519.FieldElement feI.SetI() for i := 0; i < 100; i++ { bi.Rand(rnd, &bi25519) fe1.SetBigInt(&bi) sq := fe2.InvSqrtI(&fe1) if sq == 0 { fe1.Mul(&fe1, &feI) } fe2.Mul(&fe2, &fe1) fe2.Square(&fe2) if !fe1.Equals(&fe2) { t.Fatalf("InvSqrtI(%v) incorrect", &bi) } } } func TestFeSqrt(t *testing.T) { var bi big.Int var fe1, fe2 edwards25519.FieldElement for i := 0; i < 100; i++ { bi.Rand(rnd, &bi25519) bi.Mul(&bi, &bi) bi.Mod(&bi, &bi25519) fe1.SetBigInt(&bi) fe2.Sqrt(&fe1) if fe2.IsNegativeI() == 1 { t.Fatalf("Sqrt(%v) is negative", &bi) } fe2.Square(&fe2) if !fe1.Equals(&fe2) { t.Fatalf("Sqrt(%v) incorrect", &bi) } } } func BenchmarkFeInverse(b *testing.B) { var fe edwards25519.FieldElement var bi big.Int bi.Rand(rnd, &bi25519) fe.SetBigInt(&bi) b.ResetTimer() for n := 0; n < b.N; n++ { fe.Inverse(&fe) } } func BenchmarkFeSquare(b *testing.B) { var fe edwards25519.FieldElement var bi big.Int bi.Rand(rnd, &bi25519) fe.SetBigInt(&bi) b.ResetTimer() for n := 0; n < b.N; n++ { fe.Square(&fe) } } func BenchmarkFeDoubledSquare(b *testing.B) { var fe edwards25519.FieldElement var bi big.Int bi.Rand(rnd, &bi25519) fe.SetBigInt(&bi) b.ResetTimer() for n := 0; n < b.N; n++ { fe.DoubledSquare(&fe) } } func BenchmarkFeMul(b *testing.B) { var fe edwards25519.FieldElement var bi big.Int bi.Rand(rnd, &bi25519) fe.SetBigInt(&bi) b.ResetTimer() for n := 0; n < b.N; n++ { fe.Mul(&fe, &fe) } } func BenchmarkFeIsNonZero(b *testing.B) { var fe edwards25519.FieldElement var bi big.Int bi.Rand(rnd, &bi25519) fe.SetBigInt(&bi) b.ResetTimer() for n := 0; n < b.N; n++ { fe.IsNonZeroI() } } func BenchmarkFePack(b *testing.B) { var fe edwards25519.FieldElement var buf [32]byte b.ResetTimer() for n := 0; n < b.N; n++ { fe.BytesInto(&buf) } } func BenchmarkFeUnpack(b *testing.B) { var fe edwards25519.FieldElement var buf [32]byte b.ResetTimer() for n := 0; n < b.N; n++ { fe.SetBytes(&buf) } } func BenchmarkFeInvSqrtI(b *testing.B) { var fe edwards25519.FieldElement var bi big.Int bi.Rand(rnd, &bi25519) fe.SetBigInt(&bi) b.ResetTimer() for n := 0; n < b.N; n++ { fe.InvSqrtI(&fe) } } func TestMain(m *testing.M) { bi25519.SetString( "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", 16) biL.SetString( "1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", 16) rnd = rand.New(rand.NewSource(37)) os.Exit(m.Run()) } go-ristretto-1.2.3/edwards25519/table.go000066400000000000000000000113501440464505300176410ustar00rootroot00000000000000package edwards25519 type NielsPoint struct { YPlusX, YMinusX, XY2D FieldElement } // Precomputed scalar multiplication table type ScalarMultTable [32][8]NielsPoint // Set p to zero, the neutral element. Return p. func (p *NielsPoint) SetZero() *NielsPoint { p.YMinusX.SetOne() p.YPlusX.SetOne() p.XY2D.SetZero() return p } // Set p to q. Returns p. func (p *NielsPoint) Set(q *NielsPoint) *NielsPoint { p.YPlusX.Set(&q.YPlusX) p.YMinusX.Set(&q.YMinusX) p.XY2D.Set(&q.XY2D) return p } // Set p to q if b == 1. Assumes b is 0 or 1. Returns p. func (p *NielsPoint) ConditionalSet(q *NielsPoint, b int32) *NielsPoint { p.YPlusX.ConditionalSet(&q.YPlusX, b) p.YMinusX.ConditionalSet(&q.YMinusX, b) p.XY2D.ConditionalSet(&q.XY2D, b) return p } // Set p to -q. Returns p. func (p *NielsPoint) Neg(q *NielsPoint) *NielsPoint { p.YMinusX.Set(&q.YPlusX) p.YPlusX.Set(&q.YMinusX) p.XY2D.Neg(&q.XY2D) return p } // Sets p to q+r. Returns p. func (p *CompletedPoint) AddExtendedNiels(q *ExtendedPoint, r *NielsPoint) *CompletedPoint { var t0 FieldElement p.X.add(&q.Y, &q.X) p.Y.sub(&q.Y, &q.X) p.Z.Mul(&p.X, &r.YPlusX) p.Y.Mul(&p.Y, &r.YMinusX) p.T.Mul(&r.XY2D, &q.T) t0.add(&q.Z, &q.Z) p.X.sub(&p.Z, &p.Y) p.Y.add(&p.Z, &p.Y) p.Z.add(&t0, &p.T) p.T.sub(&t0, &p.T) return p } // Set p to q-r. Returns p. func (p *CompletedPoint) SubExtendedNiels(q *ExtendedPoint, r *NielsPoint) *CompletedPoint { var t0 FieldElement p.X.add(&q.Y, &q.X) p.Y.sub(&q.Y, &q.X) p.Z.Mul(&p.X, &r.YMinusX) p.Y.Mul(&p.Y, &r.YPlusX) p.T.Mul(&r.XY2D, &q.T) t0.add(&q.Z, &q.Z) p.X.sub(&p.Z, &p.Y) p.Y.add(&p.Z, &p.Y) p.Z.sub(&t0, &p.T) p.T.add(&t0, &p.T) return p } // Sets p to q. Returns p. func (p *NielsPoint) SetExtended(q *ExtendedPoint) *NielsPoint { var x, y, zInv FieldElement zInv.Inverse(&q.Z) x.Mul(&q.X, &zInv) y.Mul(&q.Y, &zInv) p.YPlusX.Add(&y, &x) p.YMinusX.Sub(&y, &x) p.XY2D.Mul(&x, &y) p.XY2D.Add(&p.XY2D, &p.XY2D) p.XY2D.Mul(&p.XY2D, &feD) return p } // Fill the table t with data for the point p. func (t *ScalarMultTable) Compute(p *ExtendedPoint) { var c, cp ExtendedPoint var c_pp ProjectivePoint var c_cp CompletedPoint cp.Set(p) for i := 0; i < 32; i++ { c.SetZero() for v := 0; v < 8; v++ { c.Add(&c, &cp) t[i][v].SetExtended(&c) } c_cp.DoubleExtended(&c) c_pp.SetCompleted(&c_cp) c_cp.DoubleProjective(&c_pp) c_pp.SetCompleted(&c_cp) c_cp.DoubleProjective(&c_pp) c_pp.SetCompleted(&c_cp) c_cp.DoubleProjective(&c_pp) c_pp.SetCompleted(&c_cp) c_cp.DoubleProjective(&c_pp) cp.SetCompleted(&c_cp) } } // Compute 4-bit signed window for the scalar s func computeScalarWindow4(s *[32]byte, w *[64]int8) { for i := 0; i < 32; i++ { w[2*i] = int8(s[i] & 15) w[2*i+1] = int8((s[i] >> 4) & 15) } carry := int8(0) for i := 0; i < 63; i++ { w[i] += carry carry = (w[i] + 8) >> 4 w[i] -= carry << 4 } w[63] += carry } // Set p to s * q, where t was computed for q using t.Compute(q). func (t *ScalarMultTable) ScalarMult(p *ExtendedPoint, s *[32]byte) { var w [64]int8 computeScalarWindow4(s, &w) p.SetZero() var np NielsPoint var cp CompletedPoint var pp ProjectivePoint for i := int32(0); i < 32; i++ { t.selectPoint(&np, i, int32(w[2*i+1])) cp.AddExtendedNiels(p, &np) p.SetCompleted(&cp) } cp.DoubleExtended(p) pp.SetCompleted(&cp) cp.DoubleProjective(&pp) pp.SetCompleted(&cp) cp.DoubleProjective(&pp) pp.SetCompleted(&cp) cp.DoubleProjective(&pp) p.SetCompleted(&cp) for i := int32(0); i < 32; i++ { t.selectPoint(&np, i, int32(w[2*i])) cp.AddExtendedNiels(p, &np) p.SetCompleted(&cp) } } func (t *ScalarMultTable) VarTimeScalarMult(p *ExtendedPoint, s *[32]byte) { var w [64]int8 computeScalarWindow4(s, &w) p.SetZero() var np NielsPoint var cp CompletedPoint var pp ProjectivePoint for i := int32(0); i < 32; i++ { if t.varTimeSelectPoint(&np, i, int32(w[2*i+1])) { cp.AddExtendedNiels(p, &np) p.SetCompleted(&cp) } } cp.DoubleExtended(p) pp.SetCompleted(&cp) cp.DoubleProjective(&pp) pp.SetCompleted(&cp) cp.DoubleProjective(&pp) pp.SetCompleted(&cp) cp.DoubleProjective(&pp) p.SetCompleted(&cp) for i := int32(0); i < 32; i++ { if t.varTimeSelectPoint(&np, i, int32(w[2*i])) { cp.AddExtendedNiels(p, &np) p.SetCompleted(&cp) } } } func (t *ScalarMultTable) selectPoint(p *NielsPoint, pos int32, b int32) { bNegative := negative(b) bAbs := b - (((-bNegative) & b) << 1) p.SetZero() for i := int32(0); i < 8; i++ { p.ConditionalSet(&t[pos][i], equal30(bAbs, i+1)) } var negP NielsPoint negP.Neg(p) p.ConditionalSet(&negP, bNegative) } func (t *ScalarMultTable) varTimeSelectPoint(p *NielsPoint, pos int32, b int32) bool { if b == 0 { return false } if b < 0 { p.Neg(&t[pos][-b-1]) } else { p.Set(&t[pos][b-1]) } return true } go-ristretto-1.2.3/edwards25519/table_generic.go000066400000000000000000003072131440464505300213430ustar00rootroot00000000000000//go:build (!amd64 && !go1.13) || forcegeneric // +build !amd64,!go1.13 forcegeneric package edwards25519 var BaseScalarMultTable = ScalarMultTable{[8]NielsPoint{NielsPoint{YPlusX: FieldElement{-20868243, 1628258, -8994952, -5810221, -25776221, -3653418, -6394308, -5743505, 23532716, 9959724}, YMinusX: FieldElement{-5912631, -11081703, 6009768, -209557, 7468707, -4089375, -6362924, -8952552, -2788132, 1366550}, XY2D: FieldElement{8738181, -4489570, -9688441, 14785194, -10184609, 12363380, -29287919, -11864899, 24514362, 4438546}}, NielsPoint{YPlusX: FieldElement{12815894, 12976347, 21581243, -11784320, 25355658, 2750717, 11717903, 3814571, 358445, 10211303}, YMinusX: FieldElement{21703237, -6903825, -27185491, -6451973, 29577724, 9554005, 15616551, -11189268, 26829678, 5319081}, XY2D: FieldElement{26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697}}, NielsPoint{YPlusX: FieldElement{-33386987, -12413499, -23610196, 3649136, 2210761, -15537909, 26511630, 2078608, 26886373, -15609059}, YMinusX: FieldElement{24545969, -3506838, -5277728, -12534841, 13008707, -2927197, 6206343, -3258065, -16397082, 7100930}, XY2D: FieldElement{-30464156, 5976125, 11779434, 15670865, -23220365, -15915852, -7512774, -10017326, 17749093, 9920357}}, NielsPoint{YPlusX: FieldElement{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540}, YMinusX: FieldElement{23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397}, XY2D: FieldElement{7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325}}, NielsPoint{YPlusX: FieldElement{-11928380, -3963360, 27070730, -6703809, -6270217, 9853481, -7538109, -279533, 19121671, 6982365}, YMinusX: FieldElement{-31493446, 7202222, 6295441, 7646477, 12700127, 6760065, -16332637, -5336593, 28935082, -12691219}, XY2D: FieldElement{-19563160, -16186464, 29386857, -4097519, -10237984, 4348115, -28542350, -13850243, 23678021, 15815942}}, NielsPoint{YPlusX: FieldElement{15371964, 12862754, -32573250, -4720197, 26436522, -5875511, 19188627, 15224819, 9818940, 12085777}, YMinusX: FieldElement{8549212, -109983, -15149363, -2178705, -22900618, -4543417, -3044240, 15689887, -1762328, -14866737}, XY2D: FieldElement{-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652}}, NielsPoint{YPlusX: FieldElement{-32121264, -6939727, -11004492, -14675536, 8474162, 2468373, -12281005, 1725003, -26737328, -9116199}, YMinusX: FieldElement{403439, -2794281, -28670699, -6746546, -20782317, -5907090, 19183506, -3732089, -20017639, 240133}, XY2D: FieldElement{-28881845, -14381568, -9657904, -3680757, 20181635, -7843316, 31400660, -1370708, -29794553, 1409300}}, NielsPoint{YPlusX: FieldElement{14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726}, YMinusX: FieldElement{-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955}, XY2D: FieldElement{27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171}, YMinusX: FieldElement{27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510}, XY2D: FieldElement{17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660}}, NielsPoint{YPlusX: FieldElement{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639}, YMinusX: FieldElement{29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963}, XY2D: FieldElement{5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950}}, NielsPoint{YPlusX: FieldElement{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568}, YMinusX: FieldElement{12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335}, XY2D: FieldElement{25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628}}, NielsPoint{YPlusX: FieldElement{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007}, YMinusX: FieldElement{-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772}, XY2D: FieldElement{-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653}}, NielsPoint{YPlusX: FieldElement{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567}, YMinusX: FieldElement{13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686}, XY2D: FieldElement{21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372}}, NielsPoint{YPlusX: FieldElement{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887}, YMinusX: FieldElement{-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954}, XY2D: FieldElement{-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953}}, NielsPoint{YPlusX: FieldElement{24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833}, YMinusX: FieldElement{-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532}, XY2D: FieldElement{-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876}}, NielsPoint{YPlusX: FieldElement{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268}, YMinusX: FieldElement{33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214}, XY2D: FieldElement{1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800}, YMinusX: FieldElement{4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645}, XY2D: FieldElement{-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664}}, NielsPoint{YPlusX: FieldElement{1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933}, YMinusX: FieldElement{-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182}, XY2D: FieldElement{-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222}}, NielsPoint{YPlusX: FieldElement{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991}, YMinusX: FieldElement{20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880}, XY2D: FieldElement{9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092}}, NielsPoint{YPlusX: FieldElement{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295}, YMinusX: FieldElement{19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788}, XY2D: FieldElement{8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553}}, NielsPoint{YPlusX: FieldElement{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026}, YMinusX: FieldElement{11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347}, XY2D: FieldElement{-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033}}, NielsPoint{YPlusX: FieldElement{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395}, YMinusX: FieldElement{-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278}, XY2D: FieldElement{1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890}}, NielsPoint{YPlusX: FieldElement{32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995}, YMinusX: FieldElement{-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596}, XY2D: FieldElement{-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891}}, NielsPoint{YPlusX: FieldElement{31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060}, YMinusX: FieldElement{11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608}, XY2D: FieldElement{-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389}, YMinusX: FieldElement{-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016}, XY2D: FieldElement{-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341}}, NielsPoint{YPlusX: FieldElement{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505}, YMinusX: FieldElement{14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553}, XY2D: FieldElement{-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655}}, NielsPoint{YPlusX: FieldElement{15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220}, YMinusX: FieldElement{12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631}, XY2D: FieldElement{-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099}}, NielsPoint{YPlusX: FieldElement{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556}, YMinusX: FieldElement{14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749}, XY2D: FieldElement{236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930}}, NielsPoint{YPlusX: FieldElement{1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391}, YMinusX: FieldElement{5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253}, XY2D: FieldElement{20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066}}, NielsPoint{YPlusX: FieldElement{24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958}, YMinusX: FieldElement{-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082}, XY2D: FieldElement{-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383}}, NielsPoint{YPlusX: FieldElement{-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521}, YMinusX: FieldElement{-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807}, XY2D: FieldElement{23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948}}, NielsPoint{YPlusX: FieldElement{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134}, YMinusX: FieldElement{-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455}, XY2D: FieldElement{27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069}, YMinusX: FieldElement{-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746}, XY2D: FieldElement{24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919}}, NielsPoint{YPlusX: FieldElement{11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837}, YMinusX: FieldElement{8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906}, XY2D: FieldElement{-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771}}, NielsPoint{YPlusX: FieldElement{-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817}, YMinusX: FieldElement{10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098}, XY2D: FieldElement{10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409}}, NielsPoint{YPlusX: FieldElement{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504}, YMinusX: FieldElement{-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727}, XY2D: FieldElement{28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420}}, NielsPoint{YPlusX: FieldElement{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003}, YMinusX: FieldElement{-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605}, XY2D: FieldElement{-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384}}, NielsPoint{YPlusX: FieldElement{-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701}, YMinusX: FieldElement{-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683}, XY2D: FieldElement{29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708}}, NielsPoint{YPlusX: FieldElement{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563}, YMinusX: FieldElement{-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260}, XY2D: FieldElement{-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387}}, NielsPoint{YPlusX: FieldElement{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672}, YMinusX: FieldElement{23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686}, XY2D: FieldElement{-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182}, YMinusX: FieldElement{-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277}, XY2D: FieldElement{14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628}}, NielsPoint{YPlusX: FieldElement{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474}, YMinusX: FieldElement{-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539}, XY2D: FieldElement{-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822}}, NielsPoint{YPlusX: FieldElement{-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970}, YMinusX: FieldElement{19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756}, XY2D: FieldElement{-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508}}, NielsPoint{YPlusX: FieldElement{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683}, YMinusX: FieldElement{-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655}, XY2D: FieldElement{-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158}}, NielsPoint{YPlusX: FieldElement{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125}, YMinusX: FieldElement{-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839}, XY2D: FieldElement{-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664}}, NielsPoint{YPlusX: FieldElement{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294}, YMinusX: FieldElement{-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899}, XY2D: FieldElement{-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070}}, NielsPoint{YPlusX: FieldElement{3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294}, YMinusX: FieldElement{-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949}, XY2D: FieldElement{-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083}}, NielsPoint{YPlusX: FieldElement{31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420}, YMinusX: FieldElement{-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940}, XY2D: FieldElement{29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567}, YMinusX: FieldElement{20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127}, XY2D: FieldElement{-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294}}, NielsPoint{YPlusX: FieldElement{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887}, YMinusX: FieldElement{22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964}, XY2D: FieldElement{16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195}}, NielsPoint{YPlusX: FieldElement{9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244}, YMinusX: FieldElement{24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999}, XY2D: FieldElement{-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762}}, NielsPoint{YPlusX: FieldElement{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274}, YMinusX: FieldElement{-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236}, XY2D: FieldElement{-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605}}, NielsPoint{YPlusX: FieldElement{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761}, YMinusX: FieldElement{-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884}, XY2D: FieldElement{-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482}}, NielsPoint{YPlusX: FieldElement{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638}, YMinusX: FieldElement{-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490}, XY2D: FieldElement{-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170}}, NielsPoint{YPlusX: FieldElement{5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736}, YMinusX: FieldElement{10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124}, XY2D: FieldElement{-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392}}, NielsPoint{YPlusX: FieldElement{8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029}, YMinusX: FieldElement{6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048}, XY2D: FieldElement{28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593}, YMinusX: FieldElement{26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071}, XY2D: FieldElement{-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692}}, NielsPoint{YPlusX: FieldElement{11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687}, YMinusX: FieldElement{-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441}, XY2D: FieldElement{-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001}}, NielsPoint{YPlusX: FieldElement{-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460}, YMinusX: FieldElement{-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007}, XY2D: FieldElement{-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762}}, NielsPoint{YPlusX: FieldElement{15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005}, YMinusX: FieldElement{-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674}, XY2D: FieldElement{4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035}}, NielsPoint{YPlusX: FieldElement{7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590}, YMinusX: FieldElement{-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957}, XY2D: FieldElement{-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812}}, NielsPoint{YPlusX: FieldElement{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740}, YMinusX: FieldElement{-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122}, XY2D: FieldElement{-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158}}, NielsPoint{YPlusX: FieldElement{8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885}, YMinusX: FieldElement{26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140}, XY2D: FieldElement{19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857}}, NielsPoint{YPlusX: FieldElement{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155}, YMinusX: FieldElement{19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260}, XY2D: FieldElement{19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677}, YMinusX: FieldElement{32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815}, XY2D: FieldElement{22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751}}, NielsPoint{YPlusX: FieldElement{-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203}, YMinusX: FieldElement{-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208}, XY2D: FieldElement{1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230}}, NielsPoint{YPlusX: FieldElement{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850}, YMinusX: FieldElement{-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389}, XY2D: FieldElement{-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968}}, NielsPoint{YPlusX: FieldElement{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689}, YMinusX: FieldElement{14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880}, XY2D: FieldElement{5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304}}, NielsPoint{YPlusX: FieldElement{30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632}, YMinusX: FieldElement{-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412}, XY2D: FieldElement{20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566}}, NielsPoint{YPlusX: FieldElement{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038}, YMinusX: FieldElement{-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232}, XY2D: FieldElement{-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943}}, NielsPoint{YPlusX: FieldElement{17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856}, YMinusX: FieldElement{23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738}, XY2D: FieldElement{15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971}}, NielsPoint{YPlusX: FieldElement{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718}, YMinusX: FieldElement{-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697}, XY2D: FieldElement{-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912}, YMinusX: FieldElement{-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358}, XY2D: FieldElement{3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849}}, NielsPoint{YPlusX: FieldElement{29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307}, YMinusX: FieldElement{-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977}, XY2D: FieldElement{-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335}}, NielsPoint{YPlusX: FieldElement{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644}, YMinusX: FieldElement{-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616}, XY2D: FieldElement{-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735}}, NielsPoint{YPlusX: FieldElement{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099}, YMinusX: FieldElement{29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341}, XY2D: FieldElement{-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336}}, NielsPoint{YPlusX: FieldElement{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646}, YMinusX: FieldElement{31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425}, XY2D: FieldElement{-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388}}, NielsPoint{YPlusX: FieldElement{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743}, YMinusX: FieldElement{-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822}, XY2D: FieldElement{-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462}}, NielsPoint{YPlusX: FieldElement{18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985}, YMinusX: FieldElement{9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702}, XY2D: FieldElement{-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797}}, NielsPoint{YPlusX: FieldElement{21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293}, YMinusX: FieldElement{27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100}, XY2D: FieldElement{19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186}, YMinusX: FieldElement{2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610}, XY2D: FieldElement{-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707}}, NielsPoint{YPlusX: FieldElement{7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220}, YMinusX: FieldElement{915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025}, XY2D: FieldElement{32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044}}, NielsPoint{YPlusX: FieldElement{32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992}, YMinusX: FieldElement{-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027}, XY2D: FieldElement{21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197}}, NielsPoint{YPlusX: FieldElement{8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901}, YMinusX: FieldElement{31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952}, XY2D: FieldElement{19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878}}, NielsPoint{YPlusX: FieldElement{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390}, YMinusX: FieldElement{32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730}, XY2D: FieldElement{2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730}}, NielsPoint{YPlusX: FieldElement{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180}, YMinusX: FieldElement{-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272}, XY2D: FieldElement{-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715}}, NielsPoint{YPlusX: FieldElement{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970}, YMinusX: FieldElement{-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772}, XY2D: FieldElement{-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865}}, NielsPoint{YPlusX: FieldElement{15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750}, YMinusX: FieldElement{20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373}, XY2D: FieldElement{32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144}, YMinusX: FieldElement{-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195}, XY2D: FieldElement{5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086}}, NielsPoint{YPlusX: FieldElement{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684}, YMinusX: FieldElement{-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518}, XY2D: FieldElement{-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233}}, NielsPoint{YPlusX: FieldElement{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793}, YMinusX: FieldElement{-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794}, XY2D: FieldElement{580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435}}, NielsPoint{YPlusX: FieldElement{23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921}, YMinusX: FieldElement{13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518}, XY2D: FieldElement{2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563}}, NielsPoint{YPlusX: FieldElement{14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278}, YMinusX: FieldElement{-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024}, XY2D: FieldElement{4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030}}, NielsPoint{YPlusX: FieldElement{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783}, YMinusX: FieldElement{27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717}, XY2D: FieldElement{6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844}}, NielsPoint{YPlusX: FieldElement{14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333}, YMinusX: FieldElement{16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048}, XY2D: FieldElement{22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760}}, NielsPoint{YPlusX: FieldElement{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760}, YMinusX: FieldElement{-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757}, XY2D: FieldElement{-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468}, YMinusX: FieldElement{3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184}, XY2D: FieldElement{10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289}}, NielsPoint{YPlusX: FieldElement{15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066}, YMinusX: FieldElement{24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882}, XY2D: FieldElement{13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226}}, NielsPoint{YPlusX: FieldElement{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101}, YMinusX: FieldElement{29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279}, XY2D: FieldElement{-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811}}, NielsPoint{YPlusX: FieldElement{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709}, YMinusX: FieldElement{20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714}, XY2D: FieldElement{-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121}}, NielsPoint{YPlusX: FieldElement{9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464}, YMinusX: FieldElement{12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847}, XY2D: FieldElement{13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400}}, NielsPoint{YPlusX: FieldElement{4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414}, YMinusX: FieldElement{-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158}, XY2D: FieldElement{17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045}}, NielsPoint{YPlusX: FieldElement{-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415}, YMinusX: FieldElement{-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459}, XY2D: FieldElement{-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079}}, NielsPoint{YPlusX: FieldElement{21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412}, YMinusX: FieldElement{-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743}, XY2D: FieldElement{-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022}, YMinusX: FieldElement{18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429}, XY2D: FieldElement{-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065}}, NielsPoint{YPlusX: FieldElement{30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861}, YMinusX: FieldElement{10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000}, XY2D: FieldElement{-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101}}, NielsPoint{YPlusX: FieldElement{32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815}, YMinusX: FieldElement{29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642}, XY2D: FieldElement{10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966}}, NielsPoint{YPlusX: FieldElement{25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574}, YMinusX: FieldElement{-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742}, XY2D: FieldElement{-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689}}, NielsPoint{YPlusX: FieldElement{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020}, YMinusX: FieldElement{-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772}, XY2D: FieldElement{3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982}}, NielsPoint{YPlusX: FieldElement{-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953}, YMinusX: FieldElement{-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218}, XY2D: FieldElement{-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265}}, NielsPoint{YPlusX: FieldElement{29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073}, YMinusX: FieldElement{-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325}, XY2D: FieldElement{-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798}}, NielsPoint{YPlusX: FieldElement{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870}, YMinusX: FieldElement{-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863}, XY2D: FieldElement{-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267}, YMinusX: FieldElement{-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663}, XY2D: FieldElement{22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862}}, NielsPoint{YPlusX: FieldElement{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673}, YMinusX: FieldElement{15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943}, XY2D: FieldElement{15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020}}, NielsPoint{YPlusX: FieldElement{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238}, YMinusX: FieldElement{11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064}, XY2D: FieldElement{14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795}}, NielsPoint{YPlusX: FieldElement{15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052}, YMinusX: FieldElement{-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904}, XY2D: FieldElement{29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531}}, NielsPoint{YPlusX: FieldElement{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979}, YMinusX: FieldElement{-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841}, XY2D: FieldElement{10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431}}, NielsPoint{YPlusX: FieldElement{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324}, YMinusX: FieldElement{-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940}, XY2D: FieldElement{10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320}}, NielsPoint{YPlusX: FieldElement{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184}, YMinusX: FieldElement{14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114}, XY2D: FieldElement{30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878}}, NielsPoint{YPlusX: FieldElement{12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784}, YMinusX: FieldElement{-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091}, XY2D: FieldElement{-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208}, YMinusX: FieldElement{10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864}, XY2D: FieldElement{17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661}}, NielsPoint{YPlusX: FieldElement{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233}, YMinusX: FieldElement{26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212}, XY2D: FieldElement{-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525}}, NielsPoint{YPlusX: FieldElement{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068}, YMinusX: FieldElement{9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397}, XY2D: FieldElement{-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988}}, NielsPoint{YPlusX: FieldElement{5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889}, YMinusX: FieldElement{32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038}, XY2D: FieldElement{14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697}}, NielsPoint{YPlusX: FieldElement{20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875}, YMinusX: FieldElement{-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905}, XY2D: FieldElement{-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656}}, NielsPoint{YPlusX: FieldElement{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818}, YMinusX: FieldElement{27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714}, XY2D: FieldElement{10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203}}, NielsPoint{YPlusX: FieldElement{20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931}, YMinusX: FieldElement{-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024}, XY2D: FieldElement{-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084}}, NielsPoint{YPlusX: FieldElement{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204}, YMinusX: FieldElement{20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817}, XY2D: FieldElement{27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504}, YMinusX: FieldElement{-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768}, XY2D: FieldElement{-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255}}, NielsPoint{YPlusX: FieldElement{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790}, YMinusX: FieldElement{1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438}, XY2D: FieldElement{-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333}}, NielsPoint{YPlusX: FieldElement{17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971}, YMinusX: FieldElement{31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905}, XY2D: FieldElement{29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409}}, NielsPoint{YPlusX: FieldElement{12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409}, YMinusX: FieldElement{6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499}, XY2D: FieldElement{-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363}}, NielsPoint{YPlusX: FieldElement{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664}, YMinusX: FieldElement{-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324}, XY2D: FieldElement{-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940}}, NielsPoint{YPlusX: FieldElement{13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990}, YMinusX: FieldElement{-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914}, XY2D: FieldElement{-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290}}, NielsPoint{YPlusX: FieldElement{24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257}, YMinusX: FieldElement{-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433}, XY2D: FieldElement{-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236}}, NielsPoint{YPlusX: FieldElement{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045}, YMinusX: FieldElement{11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093}, XY2D: FieldElement{-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191}, YMinusX: FieldElement{-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507}, XY2D: FieldElement{-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906}}, NielsPoint{YPlusX: FieldElement{3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018}, YMinusX: FieldElement{-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109}, XY2D: FieldElement{-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926}}, NielsPoint{YPlusX: FieldElement{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528}, YMinusX: FieldElement{8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625}, XY2D: FieldElement{-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286}}, NielsPoint{YPlusX: FieldElement{2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033}, YMinusX: FieldElement{27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866}, XY2D: FieldElement{21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896}}, NielsPoint{YPlusX: FieldElement{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075}, YMinusX: FieldElement{26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347}, XY2D: FieldElement{-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437}}, NielsPoint{YPlusX: FieldElement{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165}, YMinusX: FieldElement{-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588}, XY2D: FieldElement{-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193}}, NielsPoint{YPlusX: FieldElement{-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017}, YMinusX: FieldElement{-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883}, XY2D: FieldElement{21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961}}, NielsPoint{YPlusX: FieldElement{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043}, YMinusX: FieldElement{29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663}, XY2D: FieldElement{-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860}, YMinusX: FieldElement{2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466}, XY2D: FieldElement{-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063}}, NielsPoint{YPlusX: FieldElement{-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997}, YMinusX: FieldElement{-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295}, XY2D: FieldElement{-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369}}, NielsPoint{YPlusX: FieldElement{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385}, YMinusX: FieldElement{18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109}, XY2D: FieldElement{2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906}}, NielsPoint{YPlusX: FieldElement{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424}, YMinusX: FieldElement{-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185}, XY2D: FieldElement{7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962}}, NielsPoint{YPlusX: FieldElement{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325}, YMinusX: FieldElement{10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593}, XY2D: FieldElement{696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404}}, NielsPoint{YPlusX: FieldElement{-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644}, YMinusX: FieldElement{17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801}, XY2D: FieldElement{26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804}}, NielsPoint{YPlusX: FieldElement{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884}, YMinusX: FieldElement{-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577}, XY2D: FieldElement{-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849}}, NielsPoint{YPlusX: FieldElement{32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473}, YMinusX: FieldElement{-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644}, XY2D: FieldElement{-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599}, YMinusX: FieldElement{-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768}, XY2D: FieldElement{-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084}}, NielsPoint{YPlusX: FieldElement{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328}, YMinusX: FieldElement{-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369}, XY2D: FieldElement{20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920}}, NielsPoint{YPlusX: FieldElement{12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815}, YMinusX: FieldElement{-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025}, XY2D: FieldElement{-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397}}, NielsPoint{YPlusX: FieldElement{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448}, YMinusX: FieldElement{6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981}, XY2D: FieldElement{30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165}}, NielsPoint{YPlusX: FieldElement{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501}, YMinusX: FieldElement{17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073}, XY2D: FieldElement{-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861}}, NielsPoint{YPlusX: FieldElement{14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845}, YMinusX: FieldElement{-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211}, XY2D: FieldElement{18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870}}, NielsPoint{YPlusX: FieldElement{10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096}, YMinusX: FieldElement{33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803}, XY2D: FieldElement{-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168}}, NielsPoint{YPlusX: FieldElement{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965}, YMinusX: FieldElement{-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505}, XY2D: FieldElement{18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782}, YMinusX: FieldElement{5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900}, XY2D: FieldElement{-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479}}, NielsPoint{YPlusX: FieldElement{-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208}, YMinusX: FieldElement{8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232}, XY2D: FieldElement{17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719}}, NielsPoint{YPlusX: FieldElement{16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271}, YMinusX: FieldElement{-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326}, XY2D: FieldElement{-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132}}, NielsPoint{YPlusX: FieldElement{14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300}, YMinusX: FieldElement{8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570}, XY2D: FieldElement{15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670}}, NielsPoint{YPlusX: FieldElement{-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994}, YMinusX: FieldElement{-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913}, XY2D: FieldElement{31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317}}, NielsPoint{YPlusX: FieldElement{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730}, YMinusX: FieldElement{842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096}, XY2D: FieldElement{-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078}}, NielsPoint{YPlusX: FieldElement{-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411}, YMinusX: FieldElement{-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905}, XY2D: FieldElement{-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654}}, NielsPoint{YPlusX: FieldElement{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870}, YMinusX: FieldElement{-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498}, XY2D: FieldElement{12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677}, YMinusX: FieldElement{10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647}, XY2D: FieldElement{-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743}}, NielsPoint{YPlusX: FieldElement{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468}, YMinusX: FieldElement{21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375}, XY2D: FieldElement{-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155}}, NielsPoint{YPlusX: FieldElement{6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725}, YMinusX: FieldElement{-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612}, XY2D: FieldElement{-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943}}, NielsPoint{YPlusX: FieldElement{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944}, YMinusX: FieldElement{30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928}, XY2D: FieldElement{9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406}}, NielsPoint{YPlusX: FieldElement{22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139}, YMinusX: FieldElement{-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963}, XY2D: FieldElement{-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693}}, NielsPoint{YPlusX: FieldElement{1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734}, YMinusX: FieldElement{-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680}, XY2D: FieldElement{-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410}}, NielsPoint{YPlusX: FieldElement{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931}, YMinusX: FieldElement{-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654}, XY2D: FieldElement{22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710}}, NielsPoint{YPlusX: FieldElement{29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180}, YMinusX: FieldElement{-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684}, XY2D: FieldElement{-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501}, YMinusX: FieldElement{-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413}, XY2D: FieldElement{6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880}}, NielsPoint{YPlusX: FieldElement{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874}, YMinusX: FieldElement{22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962}, XY2D: FieldElement{-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899}}, NielsPoint{YPlusX: FieldElement{21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152}, YMinusX: FieldElement{9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063}, XY2D: FieldElement{7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080}}, NielsPoint{YPlusX: FieldElement{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146}, YMinusX: FieldElement{-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183}, XY2D: FieldElement{-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133}}, NielsPoint{YPlusX: FieldElement{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421}, YMinusX: FieldElement{-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622}, XY2D: FieldElement{-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197}}, NielsPoint{YPlusX: FieldElement{2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663}, YMinusX: FieldElement{31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753}, XY2D: FieldElement{4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755}}, NielsPoint{YPlusX: FieldElement{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862}, YMinusX: FieldElement{-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118}, XY2D: FieldElement{26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171}}, NielsPoint{YPlusX: FieldElement{15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380}, YMinusX: FieldElement{16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824}, XY2D: FieldElement{28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438}, YMinusX: FieldElement{-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584}, XY2D: FieldElement{-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562}}, NielsPoint{YPlusX: FieldElement{30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471}, YMinusX: FieldElement{18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610}, XY2D: FieldElement{19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269}}, NielsPoint{YPlusX: FieldElement{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650}, YMinusX: FieldElement{14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369}, XY2D: FieldElement{19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461}}, NielsPoint{YPlusX: FieldElement{30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462}, YMinusX: FieldElement{-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793}, XY2D: FieldElement{-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218}}, NielsPoint{YPlusX: FieldElement{-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226}, YMinusX: FieldElement{18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019}, XY2D: FieldElement{-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037}}, NielsPoint{YPlusX: FieldElement{31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171}, YMinusX: FieldElement{-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132}, XY2D: FieldElement{-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841}}, NielsPoint{YPlusX: FieldElement{21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181}, YMinusX: FieldElement{-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210}, XY2D: FieldElement{-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040}}, NielsPoint{YPlusX: FieldElement{3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935}, YMinusX: FieldElement{24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105}, XY2D: FieldElement{-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852}, YMinusX: FieldElement{5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581}, XY2D: FieldElement{-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646}}, NielsPoint{YPlusX: FieldElement{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844}, YMinusX: FieldElement{10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025}, XY2D: FieldElement{27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453}}, NielsPoint{YPlusX: FieldElement{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068}, YMinusX: FieldElement{4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192}, XY2D: FieldElement{-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921}}, NielsPoint{YPlusX: FieldElement{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259}, YMinusX: FieldElement{-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426}, XY2D: FieldElement{-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072}}, NielsPoint{YPlusX: FieldElement{-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305}, YMinusX: FieldElement{13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832}, XY2D: FieldElement{28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943}}, NielsPoint{YPlusX: FieldElement{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011}, YMinusX: FieldElement{24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447}, XY2D: FieldElement{17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494}}, NielsPoint{YPlusX: FieldElement{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245}, YMinusX: FieldElement{-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859}, XY2D: FieldElement{28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915}}, NielsPoint{YPlusX: FieldElement{16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707}, YMinusX: FieldElement{10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848}, XY2D: FieldElement{-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391}, YMinusX: FieldElement{15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215}, XY2D: FieldElement{-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101}}, NielsPoint{YPlusX: FieldElement{23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713}, YMinusX: FieldElement{21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849}, XY2D: FieldElement{-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930}}, NielsPoint{YPlusX: FieldElement{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940}, YMinusX: FieldElement{-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031}, XY2D: FieldElement{-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404}}, NielsPoint{YPlusX: FieldElement{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243}, YMinusX: FieldElement{-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116}, XY2D: FieldElement{-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525}}, NielsPoint{YPlusX: FieldElement{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509}, YMinusX: FieldElement{-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883}, XY2D: FieldElement{15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865}}, NielsPoint{YPlusX: FieldElement{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660}, YMinusX: FieldElement{4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273}, XY2D: FieldElement{-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138}}, NielsPoint{YPlusX: FieldElement{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560}, YMinusX: FieldElement{-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135}, XY2D: FieldElement{2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941}}, NielsPoint{YPlusX: FieldElement{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739}, YMinusX: FieldElement{18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756}, XY2D: FieldElement{-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347}, YMinusX: FieldElement{-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028}, XY2D: FieldElement{21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075}}, NielsPoint{YPlusX: FieldElement{16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799}, YMinusX: FieldElement{-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609}, XY2D: FieldElement{-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817}}, NielsPoint{YPlusX: FieldElement{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989}, YMinusX: FieldElement{-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523}, XY2D: FieldElement{4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278}}, NielsPoint{YPlusX: FieldElement{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045}, YMinusX: FieldElement{19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377}, XY2D: FieldElement{24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480}}, NielsPoint{YPlusX: FieldElement{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016}, YMinusX: FieldElement{510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426}, XY2D: FieldElement{18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525}}, NielsPoint{YPlusX: FieldElement{13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396}, YMinusX: FieldElement{9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080}, XY2D: FieldElement{12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892}}, NielsPoint{YPlusX: FieldElement{15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275}, YMinusX: FieldElement{11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074}, XY2D: FieldElement{20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140}}, NielsPoint{YPlusX: FieldElement{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717}, YMinusX: FieldElement{-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101}, XY2D: FieldElement{24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632}, YMinusX: FieldElement{-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415}, XY2D: FieldElement{-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160}}, NielsPoint{YPlusX: FieldElement{31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876}, YMinusX: FieldElement{22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625}, XY2D: FieldElement{-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478}}, NielsPoint{YPlusX: FieldElement{27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164}, YMinusX: FieldElement{26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595}, XY2D: FieldElement{-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248}}, NielsPoint{YPlusX: FieldElement{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858}, YMinusX: FieldElement{15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193}, XY2D: FieldElement{8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184}}, NielsPoint{YPlusX: FieldElement{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942}, YMinusX: FieldElement{-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635}, XY2D: FieldElement{21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948}}, NielsPoint{YPlusX: FieldElement{11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935}, YMinusX: FieldElement{-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415}, XY2D: FieldElement{-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416}}, NielsPoint{YPlusX: FieldElement{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018}, YMinusX: FieldElement{4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778}, XY2D: FieldElement{366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659}}, NielsPoint{YPlusX: FieldElement{-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385}, YMinusX: FieldElement{18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503}, XY2D: FieldElement{476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056}, YMinusX: FieldElement{-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838}, XY2D: FieldElement{24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948}}, NielsPoint{YPlusX: FieldElement{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691}, YMinusX: FieldElement{-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118}, XY2D: FieldElement{-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517}}, NielsPoint{YPlusX: FieldElement{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269}, YMinusX: FieldElement{-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904}, XY2D: FieldElement{-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589}}, NielsPoint{YPlusX: FieldElement{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193}, YMinusX: FieldElement{-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910}, XY2D: FieldElement{-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930}}, NielsPoint{YPlusX: FieldElement{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667}, YMinusX: FieldElement{25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481}, XY2D: FieldElement{-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876}}, NielsPoint{YPlusX: FieldElement{22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640}, YMinusX: FieldElement{-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278}, XY2D: FieldElement{-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112}}, NielsPoint{YPlusX: FieldElement{26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272}, YMinusX: FieldElement{17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012}, XY2D: FieldElement{-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221}}, NielsPoint{YPlusX: FieldElement{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046}, YMinusX: FieldElement{13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345}, XY2D: FieldElement{-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937}, YMinusX: FieldElement{31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636}, XY2D: FieldElement{-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008}}, NielsPoint{YPlusX: FieldElement{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429}, YMinusX: FieldElement{-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576}, XY2D: FieldElement{31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066}}, NielsPoint{YPlusX: FieldElement{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490}, YMinusX: FieldElement{-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104}, XY2D: FieldElement{33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053}}, NielsPoint{YPlusX: FieldElement{31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275}, YMinusX: FieldElement{-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511}, XY2D: FieldElement{22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095}}, NielsPoint{YPlusX: FieldElement{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439}, YMinusX: FieldElement{23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939}, XY2D: FieldElement{-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424}}, NielsPoint{YPlusX: FieldElement{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310}, YMinusX: FieldElement{3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608}, XY2D: FieldElement{-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079}}, NielsPoint{YPlusX: FieldElement{-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101}, YMinusX: FieldElement{21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418}, XY2D: FieldElement{18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576}}, NielsPoint{YPlusX: FieldElement{30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356}, YMinusX: FieldElement{9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996}, XY2D: FieldElement{-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728}, YMinusX: FieldElement{-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658}, XY2D: FieldElement{-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242}}, NielsPoint{YPlusX: FieldElement{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001}, YMinusX: FieldElement{-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766}, XY2D: FieldElement{18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373}}, NielsPoint{YPlusX: FieldElement{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458}, YMinusX: FieldElement{-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628}, XY2D: FieldElement{-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657}}, NielsPoint{YPlusX: FieldElement{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062}, YMinusX: FieldElement{25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616}, XY2D: FieldElement{31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014}}, NielsPoint{YPlusX: FieldElement{24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383}, YMinusX: FieldElement{-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814}, XY2D: FieldElement{-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718}}, NielsPoint{YPlusX: FieldElement{30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417}, YMinusX: FieldElement{2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222}, XY2D: FieldElement{33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444}}, NielsPoint{YPlusX: FieldElement{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597}, YMinusX: FieldElement{23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970}, XY2D: FieldElement{1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799}}, NielsPoint{YPlusX: FieldElement{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647}, YMinusX: FieldElement{13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511}, XY2D: FieldElement{-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834}, YMinusX: FieldElement{-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461}, XY2D: FieldElement{29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062}}, NielsPoint{YPlusX: FieldElement{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516}, YMinusX: FieldElement{-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547}, XY2D: FieldElement{-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240}}, NielsPoint{YPlusX: FieldElement{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038}, YMinusX: FieldElement{-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741}, XY2D: FieldElement{16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103}}, NielsPoint{YPlusX: FieldElement{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747}, YMinusX: FieldElement{-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323}, XY2D: FieldElement{31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016}}, NielsPoint{YPlusX: FieldElement{-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373}, YMinusX: FieldElement{15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228}, XY2D: FieldElement{-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141}}, NielsPoint{YPlusX: FieldElement{16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399}, YMinusX: FieldElement{11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831}, XY2D: FieldElement{-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376}}, NielsPoint{YPlusX: FieldElement{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313}, YMinusX: FieldElement{-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958}, XY2D: FieldElement{-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577}}, NielsPoint{YPlusX: FieldElement{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743}, YMinusX: FieldElement{29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684}, XY2D: FieldElement{-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476}}}} go-ristretto-1.2.3/edwards25519/table_radix51.go000066400000000000000000002572221440464505300212100ustar00rootroot00000000000000//go:build (amd64 && !forcegeneric) || (go1.13 && !forcegeneric) // +build amd64,!forcegeneric go1.13,!forcegeneric package edwards25519 var BaseScalarMultTable = ScalarMultTable{[8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x636186c1936d, 0x69d5f4b76bf78, 0x721035676afa2, 0x6a171bb9e6e3b, 0x25fe4b16714ab}, YMinusX: FieldElement{0x55ba063a5c7c9, 0x7f335ac5bb3a7, 0x706678471f6a2, 0x5dd945f9ee8d3, 0x536857d574db}, XY2D: FieldElement{0x6edfa78855585, 0x3866aa76c2a86, 0x2f299cf64985f, 0x52bd2f2411a11, 0x10ee849760f39}}, NielsPoint{YPlusX: FieldElement{0x318036cc38e16, 0x530be01494dbb, 0xa7e3f582e589, 0xe8d2acb2cd0f, 0x26f3f9c05782d}, YMinusX: FieldElement{0x65a9fbd4b2a45, 0x67633ea612eac, 0x2472155c351fb, 0x5550fb0ee4a27, 0x144a6a599636d}, XY2D: FieldElement{0x2a8b3a59b7a5f, 0x3abb359ef087f, 0x4f5a8c4db05af, 0x5b9a807d04205, 0x701af5b13ea50}}, NielsPoint{YPlusX: FieldElement{0x50a5712028e02, 0xdeb9be97bcab, 0x44ba42c21bbc9, 0x7ede4194890d, 0x4474c759a40e5}, YMinusX: FieldElement{0x729f5a9768ab1, 0x502ef1baf77df, 0x74d568cc67f42, 0x73924bc5eb386, 0x1b1680705cce5}, XY2D: FieldElement{0x16cc0f22f2764, 0x3bc7944b3bd6a, 0x43492ce9daf73, 0x59c97478d5d39, 0x25d7d950ed464}}, NielsPoint{YPlusX: FieldElement{0x351b98efc099f, 0x68fbfa4a7050e, 0x42a49959d971b, 0x393e51a469efd, 0x680e910321e58}, YMinusX: FieldElement{0x6050a056818bf, 0x62acc1f5532bf, 0x28141ccc9fa25, 0x24d61f471e683, 0x27933f4c7445a}, XY2D: FieldElement{0x3fbe9c476ff09, 0xaf6b982e4b42, 0xad1251ba78e5, 0x715aeedee7c88, 0x7f9d0cbf63553}}, NielsPoint{YPlusX: FieldElement{0x70e187f49fcc4, 0x666d4fd9d1109, 0x25968a3a052f6, 0x7eef04b8cfa43, 0x1aa2b7523c606}, YMinusX: FieldElement{0x1b796b61f72a7, 0x1d2b434600f91, 0x19c9a04c1c9df, 0x6ba47bb06c8a3, 0x4f963b5b983a9}, XY2D: FieldElement{0x4240e7ed57d68, 0x705e845c06868, 0x109634b63c7df, 0x4b2a5f24c7a72, 0x3c55419694c44}}, NielsPoint{YPlusX: FieldElement{0x3111488ea8ebc, 0x6dfe6ea0ef8be, 0x69963259363a9, 0x3a13fcd24cb92, 0x2e1a84495d33c}, YMinusX: FieldElement{0x7f94984827349, 0x77b05bb18d6cc, 0x6eab11aa29075, 0x3bda27bd18c6f, 0x4749b3be51be8}, XY2D: FieldElement{0x4326702ea4b71, 0x6834376030b5, 0xef0512f9c380, 0xf1a9f2512584, 0x10b8e91a9f0d6}}, NielsPoint{YPlusX: FieldElement{0x6586ec215de3d, 0x48046bf5815b3, 0x96a854814e31, 0x69492b449b53, 0x5d39762680550}, YMinusX: FieldElement{0x755735c0627ef, 0x66439364a8514, 0x69775b6c2e312, 0x71c361d24b791, 0xea812ce8e18}, XY2D: FieldElement{0x49237fe474c4b, 0x71f582b6ca1cf, 0x621483133f282, 0x7ac56b1df22d3, 0x56044e395f06}}, NielsPoint{YPlusX: FieldElement{0x7596604dd3e8f, 0x6fc510e058b36, 0x3670c8db2cc0d, 0x297d899ce332f, 0x915e76061bce}, YMinusX: FieldElement{0x75dedf39234d9, 0x1c36ab1f3c54, 0xf08fee58f5da, 0xe19613a0d637, 0x3a9024a1320e0}, XY2D: FieldElement{0x1f5d9c9a2911a, 0x7117994fafcf8, 0x2d8a8cae28dc5, 0x74ab1b2090c87, 0x26907c5c2ecc4}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x4dd0e632f9c1d, 0x2ced12622a5d9, 0x18de9614742da, 0x79ca96fdbb5d4, 0x6dd37d49a00ee}, YMinusX: FieldElement{0x3635449aa515e, 0x3e178d0475dab, 0x50b4712a19712, 0x2dcc2860ff4ad, 0x30d76d6f03d31}, XY2D: FieldElement{0x444172106e4c7, 0x1251afed2d88, 0x534fc9bed4f5a, 0x5d85a39cf5234, 0x10c697112e864}}, NielsPoint{YPlusX: FieldElement{0x62aa08358c805, 0x46f440848e194, 0x447b771a8f52b, 0x377ba3269d31d, 0x3bf9baf55080}, YMinusX: FieldElement{0x3c4277dbe5fde, 0x5a335afd44c92, 0xc1164099753e, 0x70487006fe423, 0x25e61cabed66f}, XY2D: FieldElement{0x3e128cc586604, 0x5968b2e8fc7e2, 0x49a3d5bd61cf, 0x116505b1ef6e6, 0x566d78634586e}}, NielsPoint{YPlusX: FieldElement{0x54285c65a2fd0, 0x55e62ccf87420, 0x46bb961b19044, 0x1153405712039, 0x14fba5f34793b}, YMinusX: FieldElement{0x7a49f9cc10834, 0x2b513788a22c6, 0x5ff4b6ef2395b, 0x2ec8e5af607bf, 0x33975bca5ecc3}, XY2D: FieldElement{0x746166985f7d4, 0x9939000ae79a, 0x5844c7964f97a, 0x13617e1f95b3d, 0x14829cea83fc5}}, NielsPoint{YPlusX: FieldElement{0x70b2f4e71ecb8, 0x728148efc643c, 0x753e03995b76, 0x5bf5fb2ab6767, 0x5fc3bc4535d7}, YMinusX: FieldElement{0x37b8497dd95c2, 0x61549d6b4ffe8, 0x217a22db1d138, 0xb9cf062eb09e, 0x2fd9c71e5f758}, XY2D: FieldElement{0xb3ae52afdedd, 0x19da76619e497, 0x6fa0654d2558e, 0x78219d25e41d4, 0x373767475c651}}, NielsPoint{YPlusX: FieldElement{0x95cb14246590, 0x2d82aa6ac68, 0x442f183bc4851, 0x6464f1c0a0644, 0x6bf5905730907}, YMinusX: FieldElement{0x299fd40d1add9, 0x5f2de9a04e5f7, 0x7c0eebacc1c59, 0x4cca1b1f8290a, 0x1fbea56c3b18f}, XY2D: FieldElement{0x778f1e1415b8a, 0x6f75874efc1f4, 0x28a694019027f, 0x52b37a96bdc4d, 0x2521cf67a635}}, NielsPoint{YPlusX: FieldElement{0x46720772f5ee4, 0x632c0f359d622, 0x2b2092ba3e252, 0x662257c112680, 0x1753d9f7cd6}, YMinusX: FieldElement{0x7ee0b0a9d5294, 0x381fbeb4cca27, 0x7841f3a3e639d, 0x676ea30c3445f, 0x3fa00a7e71382}, XY2D: FieldElement{0x1232d963ddb34, 0x35692e70b078d, 0x247ca14777a1f, 0x6db556be8fcd0, 0x12b5fe2fa048e}}, NielsPoint{YPlusX: FieldElement{0x37c26ad6f1e92, 0x46a0971227be5, 0x4722f0d2d9b4c, 0x3dc46204ee03a, 0x6f7e93c20796c}, YMinusX: FieldElement{0xfbc496fce34d, 0x575be6b7dae3e, 0x4a31585cee609, 0x37e9023930ff, 0x749b76f96fb12}, XY2D: FieldElement{0x2f604aea6ae05, 0x637dc939323eb, 0x3fdad9b048d47, 0xa8b0d4045af7, 0xfcec10f01e02}}, NielsPoint{YPlusX: FieldElement{0x2d29dc4244e45, 0x6927b1bc147be, 0x308534ac0839, 0x4853664033f41, 0x413779166feab}, YMinusX: FieldElement{0x558a649fe1e44, 0x44635aeefcc89, 0x1ff434887f2ba, 0xf981220e2d44, 0x4901aa7183c51}, XY2D: FieldElement{0x1b7548c1af8f0, 0x7848c53368116, 0x1b64e7383de9, 0x109fbb0587c8f, 0x41bb887b726d1}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x34c597c6691ae, 0x7a150b6990fc4, 0x52beb9d922274, 0x70eed7164861a, 0xa871e070c6a9}, YMinusX: FieldElement{0x7d44744346be, 0x282b6a564a81d, 0x4ed80f875236b, 0x6fbbe1d450c50, 0x4eb728c12fcdb}, XY2D: FieldElement{0x1b5994bbc8989, 0x74b7ba84c0660, 0x75678f1cdaeb8, 0x23206b0d6f10c, 0x3ee7300f2685d}}, NielsPoint{YPlusX: FieldElement{0x27947841e7518, 0x32c7388dae87f, 0x414add3971be9, 0x1850832f0ef1, 0x7d47c6a2cfb89}, YMinusX: FieldElement{0x255e49e7dd6b7, 0x38c2163d59eba, 0x3861f2a005845, 0x2e11e4ccbaec9, 0x1381576297912}, XY2D: FieldElement{0x2d0148ef0d6e0, 0x3522a8de787fb, 0x2ee055e74f9d2, 0x64038f6310813, 0x148cf58d34c9e}}, NielsPoint{YPlusX: FieldElement{0x72f7d9ae4756d, 0x7711e690ffc4a, 0x582a2355b0d16, 0xdccfe885b6b4, 0x278febad4eaea}, YMinusX: FieldElement{0x492f67934f027, 0x7ded0815528d4, 0x58461511a6612, 0x5ea2e50de1544, 0x3ff2fa1ebd5db}, XY2D: FieldElement{0x2681f8c933966, 0x3840521931635, 0x674f14a308652, 0x3bd9c88a94890, 0x4104dd02fe9c6}}, NielsPoint{YPlusX: FieldElement{0x14e06db096ab8, 0x1219c89e6b024, 0x278abd486a2db, 0x240b292609520, 0x165b5a48efca}, YMinusX: FieldElement{0x2bf5e1124422a, 0x673146756ae56, 0x14ad99a87e830, 0x1eaca65b080fd, 0x2c863b00afaf5}, XY2D: FieldElement{0xa474a0846a76, 0x99a5ef981e32, 0x2a8ae3c4bbfe6, 0x45c34af14832c, 0x591b67d9bffec}}, NielsPoint{YPlusX: FieldElement{0x1b3719f18b55d, 0x754318c83d337, 0x27c17b7919797, 0x145b084089b61, 0x489b4f8670301}, YMinusX: FieldElement{0x70d1c80b49bfa, 0x3d57e7d914625, 0x3c0722165e545, 0x5e5b93819e04f, 0x3de02ec7ca8f7}, XY2D: FieldElement{0x2102d3aeb92ef, 0x68c22d50c3a46, 0x42ea89385894e, 0x75f9ebf55f38c, 0x49f5fbba496cb}}, NielsPoint{YPlusX: FieldElement{0x5628c1e9c572e, 0x598b108e822ab, 0x55d8fae29361a, 0xadc8d1a97b28, 0x6a1a6c288675}, YMinusX: FieldElement{0x49a108a5bcfd4, 0x6178c8e7d6612, 0x1f03473710375, 0x73a49614a6098, 0x5604a86dcbfa6}, XY2D: FieldElement{0xd1d47c1764b6, 0x1c08316a2e51, 0x2b3db45c95045, 0x1634f818d300c, 0x20989e89fe274}}, NielsPoint{YPlusX: FieldElement{0x4278b85eaec2e, 0xef59657be2ce, 0x72fd169588770, 0x2e9b205260b30, 0x730b9950f7059}, YMinusX: FieldElement{0x777fd3a2dcc7f, 0x594a9fb124932, 0x1f8e80ca15f0, 0x714d13cec3269, 0x403ed1d0ca67}, XY2D: FieldElement{0x32d35874ec552, 0x1f3048df1b929, 0x300d73b179b23, 0x6e67be5a37d0b, 0x5bd7454308303}}, NielsPoint{YPlusX: FieldElement{0x4932115e7792a, 0x457b9bbb930b8, 0x68f5d8b193226, 0x4164e8f1ed456, 0x5bb7db123067f}, YMinusX: FieldElement{0x2d19528b24cc2, 0x4ac66b8302ff3, 0x701c8d9fdad51, 0x6c1b35c5b3727, 0x133a78007380a}, XY2D: FieldElement{0x1f467c6ca62be, 0x2c4232a5dc12c, 0x7551dc013b087, 0x690c11b03bcd, 0x740dca6d58f0e}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x28c570478433c, 0x1d8502873a463, 0x7641e7eded49c, 0x1ecedd54cf571, 0x2c03f5256c2b0}, YMinusX: FieldElement{0xee0752cfce4e, 0x660dd8116fbe9, 0x55167130fffeb, 0x1c682b885955c, 0x161d25fa963ea}, XY2D: FieldElement{0x718757b53a47d, 0x619e18b0f2f21, 0x5fbdfe4c1ec04, 0x5d798c81ebb92, 0x699468bdbd96b}}, NielsPoint{YPlusX: FieldElement{0x53de66aa91948, 0x45f81a599b1b, 0x3f7a8bd214193, 0x71d4da412331a, 0x293e1c4e6c4a2}, YMinusX: FieldElement{0x72f46f4dafecf, 0x2948ffadef7a3, 0x11ecdfdf3bc04, 0x3c2e98ffeed25, 0x525219a473905}, XY2D: FieldElement{0x6134b925112e1, 0x6bb942bb406ed, 0x70c445c0dde2, 0x411d822c4d7a3, 0x5b605c447f032}}, NielsPoint{YPlusX: FieldElement{0x1fec6f0e7f04c, 0x3cebc692c477d, 0x77986a19a95e, 0x6eaaaa1778b0f, 0x2f12fef4cc5ab}, YMinusX: FieldElement{0x5805920c47c89, 0x1924771f9972c, 0x38bbddf9fc040, 0x1f7000092b281, 0x24a76dcea8aeb}, XY2D: FieldElement{0x522b2dfc0c740, 0x7e8193480e148, 0x33fd9a04341b9, 0x3c863678a20bc, 0x5e607b2518a43}}, NielsPoint{YPlusX: FieldElement{0x4431ca596cf14, 0x15da7c801405, 0x3c9b6f8f10b5, 0x346922934017, 0x201f33139e457}, YMinusX: FieldElement{0x31d8f6cdf1818, 0x1f86c4b144b16, 0x39875b8d73e9d, 0x2fbf0d9ffa7b3, 0x5067acab6ccdd}, XY2D: FieldElement{0x27f6b08039d51, 0x4802f8000dfaa, 0x9692a062c525, 0x1baea91075817, 0x397cba8862460}}, NielsPoint{YPlusX: FieldElement{0x5c3fbc81379e7, 0x41bbc255e2f02, 0x6a3f756998650, 0x1297fd4e07c42, 0x771b4022c1e1c}, YMinusX: FieldElement{0x13093f05959b2, 0x1bd352f2ec618, 0x75789b88ea86, 0x61d1117ea48b9, 0x2339d320766e6}, XY2D: FieldElement{0x5d986513a2fa7, 0x63f3a99e11b0f, 0x28a0ecfd6b26d, 0x53b6835e18d8f, 0x331a189219971}}, NielsPoint{YPlusX: FieldElement{0x12f3a9d7572af, 0x10d00e953c4ca, 0x603df116f2f8a, 0x33dc276e0e088, 0x1ac9619ff649a}, YMinusX: FieldElement{0x66f45fb4f80c6, 0x3cc38eeb9fea2, 0x107647270db1f, 0x710f1ea740dc8, 0x31167c6b83bdf}, XY2D: FieldElement{0x33842524b1068, 0x77dd39d30fe45, 0x189432141a0d0, 0x88fe4eb8c225, 0x612436341f08b}}, NielsPoint{YPlusX: FieldElement{0x349e31a2d2638, 0x137a7fa6b16c, 0x681ae92777edc, 0x222bfc5f8dc51, 0x1522aa3178d90}, YMinusX: FieldElement{0x541db874e898d, 0x62d80fb841b33, 0x3e6ef027fa97, 0x7a03c9e9633e8, 0x46ebe2309e5ef}, XY2D: FieldElement{0x2f5369614938, 0x356e5ada20587, 0x11bc89f6bf902, 0x36746419c8db, 0x45fe70f505243}}, NielsPoint{YPlusX: FieldElement{0x24920c8951491, 0x107ec61944c5e, 0x72752e017c01f, 0x122b7dda2e97a, 0x16619f6db57a2}, YMinusX: FieldElement{0x75a6960c0b8c, 0x6dde1c5e41b49, 0x42e3f516da341, 0x16a03fda8e79e, 0x428d1623a0e39}, XY2D: FieldElement{0x74a4401a308fd, 0x6ed4b9558109, 0x746f1f6a08867, 0x4636f5c6f2321, 0x1d81592d60bd3}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x5b69f7b85c5e8, 0x17a2d175650ec, 0x4cc3e6dbfc19e, 0x73e1d3873be0e, 0x3a5f6d51b0af8}, YMinusX: FieldElement{0x68756a60dac5f, 0x55d757b8aec26, 0x3383df45f80bd, 0x6783f8c9f96a6, 0x20234a7789ecd}, XY2D: FieldElement{0x20db67178b252, 0x73aa3da2c0eda, 0x79045c01c70d3, 0x1b37b15251059, 0x7cd682353cffe}}, NielsPoint{YPlusX: FieldElement{0x5cd6068acf4f3, 0x3079afc7a74cc, 0x58097650b64b4, 0x47fabac9c4e99, 0x3ef0253b2b2cd}, YMinusX: FieldElement{0x1a45bd887fab6, 0x65748076dc17c, 0x5b98000aa11a8, 0x4a1ecc9080974, 0x2838c8863bdc0}, XY2D: FieldElement{0x3b0cf4a465030, 0x22b8aef57a2d, 0x2ad0677e925ad, 0x4094167d7457a, 0x21dcb8a606a82}}, NielsPoint{YPlusX: FieldElement{0x500fabe7731ba, 0x7cc53c3113351, 0x7cf65fe080d81, 0x3c5d966011ba1, 0x5d840dbf6c6f6}, YMinusX: FieldElement{0x4468c9d9fc8, 0x5da8554796b8c, 0x3b8be70950025, 0x6d5892da6a609, 0xbc3d08194a31}, XY2D: FieldElement{0x6380d309fe18b, 0x4d73c2cb8ee0d, 0x6b882adbac0b6, 0x36eabdddd4cbe, 0x3a4276232ac19}}, NielsPoint{YPlusX: FieldElement{0xc172db447ecb, 0x3f8c505b7a77f, 0x6a857f97f3f10, 0x4fcc0567fe03a, 0x770c9e824e1a}, YMinusX: FieldElement{0x2432c8a7084fa, 0x47bf73ca8a968, 0x1639176262867, 0x5e8df4f8010ce, 0x1ff177cea16de}, XY2D: FieldElement{0x1d99a45b5b5fd, 0x523674f2499ec, 0xf8fa26182613, 0x58f7398048c98, 0x39f264fd41500}}, NielsPoint{YPlusX: FieldElement{0x34aabfe097be1, 0x43bfc03253a33, 0x29bc7fe91b7f3, 0xa761e4844a16, 0x65c621272c35f}, YMinusX: FieldElement{0x53417dbe7e29c, 0x54573827394f5, 0x565eea6f650dd, 0x42050748dc749, 0x1712d73468889}, XY2D: FieldElement{0x389f8ce3193dd, 0x2d424b8177ce5, 0x73fa0d3440cd, 0x139020cd49e97, 0x22f9800ab19ce}}, NielsPoint{YPlusX: FieldElement{0x29fdd9a6efdac, 0x7c694a9282840, 0x6f7cdeee44b3a, 0x55a3207b25cc3, 0x4171a4d38598c}, YMinusX: FieldElement{0x2368a3e9ef8cb, 0x454aa08e2ac0b, 0x490923f8fa700, 0x372aa9ea4582f, 0x13f416cd64762}, XY2D: FieldElement{0x758aa99c94c8c, 0x5f6001700ff44, 0x7694e488c01bd, 0xd5fde948eed6, 0x508214fa574bd}}, NielsPoint{YPlusX: FieldElement{0x215bb53d003d6, 0x1179e792ca8c3, 0x1a0e96ac840a2, 0x22393e2bb3ab6, 0x3a7758a4c86cb}, YMinusX: FieldElement{0x269153ed6fe4b, 0x72a23aef89840, 0x52be5299699c, 0x3a5e5ef132316, 0x22f960ec6faba}, XY2D: FieldElement{0x111f693ae5076, 0x3e3bfaa94ca90, 0x445799476b887, 0x24a0912464879, 0x5d9fd15f8de7f}}, NielsPoint{YPlusX: FieldElement{0x44d2aeed7521e, 0x50865d2c2a7e4, 0x2705b5238ea40, 0x46c70b25d3b97, 0x3bc187fa47eb9}, YMinusX: FieldElement{0x408d36d63727f, 0x5faf8f6a66062, 0x2bb892da8de6b, 0x769d4f0c7e2e6, 0x332f35914f8fb}, XY2D: FieldElement{0x70115ea86c20c, 0x16d88da24ada8, 0x1980622662adf, 0x501ebbc195a9d, 0x450d81ce906fb}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x4d8961cae743f, 0x6bdc38c7dba0e, 0x7d3b4a7e1b463, 0x844bdee2adf3, 0x4cbad279663ab}, YMinusX: FieldElement{0x3b6a1a6205275, 0x2e82791d06dcf, 0x23d72caa93c87, 0x5f0b7ab68aaf4, 0x2de25d4ba6345}, XY2D: FieldElement{0x19024a0d71fcd, 0x15f65115f101a, 0x4e99067149708, 0x119d8d1cba5af, 0x7d7fbcefe2007}}, NielsPoint{YPlusX: FieldElement{0x45dc5f3c29094, 0x3455220b579af, 0x70c1631e068a, 0x26bc0630e9b21, 0x4f9cd196dcd8d}, YMinusX: FieldElement{0x71e6a266b2801, 0x9aae73e2df5d, 0x40dd8b219b1a3, 0x546fb4517de0d, 0x5975435e87b75}, XY2D: FieldElement{0x297d86a7b3768, 0x4835a2f4c6332, 0x70305f434160, 0x183dd014e56ae, 0x7ccdd084387a0}}, NielsPoint{YPlusX: FieldElement{0x484186760cc93, 0x7435665533361, 0x2f686336b801, 0x5225446f64331, 0x3593ca848190c}, YMinusX: FieldElement{0x6422c6d260417, 0x212904817bb94, 0x5a319deb854f5, 0x7a9d4e060da7d, 0x428bd0ed61d0c}, XY2D: FieldElement{0x3189a5e849aa7, 0x6acbb1f59b242, 0x7f6ef4753630c, 0x1f346292a2da9, 0x27398308da2d6}}, NielsPoint{YPlusX: FieldElement{0x10e4c0a702453, 0x4daafa37bd734, 0x49f6bdc3e8961, 0x1feffdcecdae6, 0x572c2945492c3}, YMinusX: FieldElement{0x38d28435ed413, 0x4064f19992858, 0x7680fbef543cd, 0x1aadd83d58d3c, 0x269597aebe8c3}, XY2D: FieldElement{0x7c745d6cd30be, 0x27c7755df78ef, 0x1776833937fa3, 0x5405116441855, 0x7f985498c05bc}}, NielsPoint{YPlusX: FieldElement{0x615520fbf6363, 0xb9e9bf74da6a, 0x4fe8308201169, 0x173f76127de43, 0x30f2653cd69b1}, YMinusX: FieldElement{0x1ce889f0be117, 0x36f6a94510709, 0x7f248720016b4, 0x1821ed1e1cf91, 0x76c2ec470a31f}, XY2D: FieldElement{0xc938aac10c85, 0x41b64ed797141, 0x1beb1c1185e6d, 0x1ed5490600f07, 0x2f1273f159647}}, NielsPoint{YPlusX: FieldElement{0x8bd755a70bc0, 0x49e3a885ce609, 0x16585881b5ad6, 0x3c27568d34f5e, 0x38ac1997edc5f}, YMinusX: FieldElement{0x1fc7c8ae01e11, 0x2094d5573e8e7, 0x5ca3cbbf549d2, 0x4f920ecc54143, 0x5d9e572ad85b6}, XY2D: FieldElement{0x6b517a751b13b, 0xcfd370b180cc, 0x5377925d1f41a, 0x34e56566008a2, 0x22dfcd9cbfe9e}}, NielsPoint{YPlusX: FieldElement{0x459b4103be0a1, 0x59a4b3f2d2add, 0x7d734c8bb8eeb, 0x2393cbe594a09, 0xfe9877824cde}, YMinusX: FieldElement{0x3d2e0c30d0cd9, 0x3f597686671bb, 0xaa587eb63999, 0xe3c7b592c619, 0x6b2916c05448c}, XY2D: FieldElement{0x334d10aba913b, 0x45cdb581cfdb, 0x5e3e0553a8f36, 0x50bb3041effb2, 0x4c303f307ff00}}, NielsPoint{YPlusX: FieldElement{0x403580dd94500, 0x48df77d92653f, 0x38a9fe3b349ea, 0xea89850aafe1, 0x416b151ab706a}, YMinusX: FieldElement{0x23bd617b28c85, 0x6e72ee77d5a61, 0x1a972ff174dde, 0x3e2636373c60f, 0xd61b8f78b2ab}, XY2D: FieldElement{0xd7efe9c136b0, 0x1ab1c89640ad5, 0x55f82aef41f97, 0x46957f317ed0d, 0x191a2af74277e}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x62b434f460efb, 0x294c6c0fad3fc, 0x68368937b4c0f, 0x5c9f82910875b, 0x237e7dbe00545}, YMinusX: FieldElement{0x6f74bc53c1431, 0x1c40e5dbbd9c2, 0x6c8fb9cae5c97, 0x4845c5ce1b7da, 0x7e2e0e450b5cc}, XY2D: FieldElement{0x575ed6701b430, 0x4d3e17fa20026, 0x791fc888c4253, 0x2f1ba99078ac1, 0x71afa699b1115}}, NielsPoint{YPlusX: FieldElement{0x23c1c473b50d6, 0x3e7671de21d48, 0x326fa5547a1e8, 0x50e4dc25fafd9, 0x731fbc78f89}, YMinusX: FieldElement{0x66f9b3953b61d, 0x555f4283cccb9, 0x7dd67fb1960e7, 0x14707a1affed4, 0x21142e9c2b1c}, XY2D: FieldElement{0xc71848f81880, 0x44bd9d8233c86, 0x6e8578efe5830, 0x4045b6d7041b5, 0x4c4d6f3347e15}}, NielsPoint{YPlusX: FieldElement{0x4ddfc988f1970, 0x4f6173ea365e1, 0x645daf9ae4588, 0x7d43763db623b, 0x38bf9500a88f9}, YMinusX: FieldElement{0x7eccfc17d1fc9, 0x4ca280782831e, 0x7b8337db1d7d6, 0x5116def3895fb, 0x193fddaaa7e47}, XY2D: FieldElement{0x2c93c37e8876f, 0x3431a28c583fa, 0x49049da8bd879, 0x4b4a8407ac11c, 0x6a6fb99ebf0d4}}, NielsPoint{YPlusX: FieldElement{0x122b5b6e423c6, 0x21e50dff1ddd6, 0x73d76324e75c0, 0x588485495418e, 0x136fda9f42c5e}, YMinusX: FieldElement{0x6c1bb560855eb, 0x71f127e13ad48, 0x5c6b304905aec, 0x3756b8e889bc7, 0x75f76914a3189}, XY2D: FieldElement{0x4dfb1a305bdd1, 0x3b3ff05811f29, 0x6ed62283cd92e, 0x65d1543ec52e1, 0x22183510be8d}}, NielsPoint{YPlusX: FieldElement{0x2710143307a7f, 0x3d88fb48bf3ab, 0x249eb4ec18f7a, 0x136115dff295f, 0x1387c441fd404}, YMinusX: FieldElement{0x766385ead2d14, 0x194f8b06095e, 0x8478f6823b62, 0x6018689d37308, 0x6a071ce17b806}, XY2D: FieldElement{0x3c3d187978af8, 0x7afe1c88276ba, 0x51df281c8ad68, 0x64906bda4245d, 0x3171b26aaf1ed}}, NielsPoint{YPlusX: FieldElement{0x5b7d8b28a47d1, 0x2c2ee149e34c1, 0x776f5629afc53, 0x1f4ea50fc49a9, 0x6c514a6334424}, YMinusX: FieldElement{0x7319097564ca8, 0x1844ebc233525, 0x21d4543fdeee1, 0x1ad27aaff1bd2, 0x221fd4873cf08}, XY2D: FieldElement{0x2204f3a156341, 0x537414065a464, 0x43c0c3bedcf83, 0x5557e706ea620, 0x48daa596fb924}}, NielsPoint{YPlusX: FieldElement{0x61d5dc84c9793, 0x47de83040c29e, 0x189deb26507e7, 0x4d4e6fadc479a, 0x58c837fa0e8a7}, YMinusX: FieldElement{0x28e665ca59cc7, 0x165c715940dd9, 0x785f3aa11c95, 0x57b98d7e38469, 0x676dd6fccad84}, XY2D: FieldElement{0x1688596fc9058, 0x66f6ad403619f, 0x4d759a87772ef, 0x7856e6173bea4, 0x1c4f73f2c6a57}}, NielsPoint{YPlusX: FieldElement{0x6706efc7c3484, 0x6987839ec366d, 0x731f95cf7f26, 0x3ae758ebce4bc, 0x70459adb7daf6}, YMinusX: FieldElement{0x24fbd305fa0bb, 0x40a98cc75a1cf, 0x78ce1220a7533, 0x6217a10e1c197, 0x795ac80d1bf64}, XY2D: FieldElement{0x1db4991b42bb3, 0x469605b994372, 0x631e3715c9a58, 0x7e9cfefcf728f, 0x5fe162848ce21}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x1852d5d7cb208, 0x60d0fbe5ce50f, 0x5a1e246e37b75, 0x51aee05ffd590, 0x2b44c043677da}, YMinusX: FieldElement{0x1214fe194961a, 0xe1ae39a9e9cb, 0x543c8b526f9f7, 0x119498067e91d, 0x4789d446fc917}, XY2D: FieldElement{0x487ab074eb78e, 0x1d33b5e8ce343, 0x13e419feb1b46, 0x2721f565de6a4, 0x60c52eef2bb9a}}, NielsPoint{YPlusX: FieldElement{0x3c5c27cae6d11, 0x36a9491956e05, 0x124bac9131da6, 0x3b6f7de202b5d, 0x70d77248d9b66}, YMinusX: FieldElement{0x589bc3bfd8bf1, 0x6f93e6aa3416b, 0x4c0a3d6c1ae48, 0x55587260b586a, 0x10bc9c312ccfc}, XY2D: FieldElement{0x2e84b3ec2a05b, 0x69da2f03c1551, 0x23a174661a67b, 0x209bca289f238, 0x63755bd3a976f}}, NielsPoint{YPlusX: FieldElement{0x7101897f1acb7, 0x3d82cb77b07b8, 0x684083d7769f5, 0x52b28472dce07, 0x2763751737c52}, YMinusX: FieldElement{0x7a03e2ad10853, 0x213dcc6ad36ab, 0x1a6e240d5bdd6, 0x7c24ffcf8fedf, 0xd8cc1c48bc16}, XY2D: FieldElement{0x402d36eb419a9, 0x7cef68c14a052, 0xf1255bc2d139, 0x373e7d431186a, 0x70c2dd8a7ad16}}, NielsPoint{YPlusX: FieldElement{0x4967db8ed7e13, 0x15aeed02f523a, 0x6149591d094bc, 0x672f204c17006, 0x32b8613816a53}, YMinusX: FieldElement{0x194509f6fec0e, 0x528d8ca31acac, 0x7826d73b8b9fa, 0x24acb99e0f9b3, 0x2e0fac6363948}, XY2D: FieldElement{0x7f7bee448cd64, 0x4e10f10da0f3c, 0x3936cb9ab20e9, 0x7a0fc4fea6cd0, 0x4179215c735a4}}, NielsPoint{YPlusX: FieldElement{0x633b9286bcd34, 0x6cab3badb9c95, 0x74e387edfbdfa, 0x14313c58a0fd9, 0x31fa85662241c}, YMinusX: FieldElement{0x94e7d7dced2a, 0x68fa738e118e, 0x41b640a5fee2b, 0x6bb709df019d4, 0x700344a30cd99}, XY2D: FieldElement{0x26c422e3622f4, 0xf3066a05b5f0, 0x4e2448f0480a6, 0x244cde0dbf095, 0x24bb2312a9952}}, NielsPoint{YPlusX: FieldElement{0xc2af5f85c6b, 0x609f4cf2883f, 0x6e86eb5a1ca13, 0x68b44a2efccd1, 0xd1d2af9ffeb5}, YMinusX: FieldElement{0xed1732de67c3, 0x308c369291635, 0x33ef348f2d250, 0x4475ea1a1bb, 0xfee3e871e188}, XY2D: FieldElement{0x28aa132621edf, 0x42b244caf353b, 0x66b064cc2e08a, 0x6bb20020cbdd3, 0x16acd79718531}}, NielsPoint{YPlusX: FieldElement{0x1c6c57887b6ad, 0x5abf21fd7592b, 0x50bd41253867a, 0x3800b71273151, 0x164ed34b18161}, YMinusX: FieldElement{0x772af2d9b1d3d, 0x6d486448b4e5b, 0x2ce58dd8d18a8, 0x1849f67503c8b, 0x123e0ef6b9302}, XY2D: FieldElement{0x6d94c192fe69a, 0x5475222a2690f, 0x693789d86b8b3, 0x1f5c3bdfb69dc, 0x78da0fc61073f}}, NielsPoint{YPlusX: FieldElement{0x780f1680c3a94, 0x2a35d3cfcd453, 0x5e5cdc7ddf8, 0x6ee888078ac24, 0x54aa4b316b38}, YMinusX: FieldElement{0x15d28e52bc66a, 0x30e1e0351cb7e, 0x30a2f74b11f8c, 0x39d120cd7de03, 0x2d25deeb256b1}, XY2D: FieldElement{0x468d19267cb8, 0x38cdca9b5fbf9, 0x1bbb05c2ca1e2, 0x3b015758e9533, 0x134610a6ab7da}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x265e777d1f515, 0xf1f54c1e39a5, 0x2f01b95522646, 0x4fdd8db9dde6d, 0x654878cba97cc}, YMinusX: FieldElement{0x38ec78df6b0fe, 0x13caebea36a22, 0x5ebc6e54e5f6a, 0x32804903d0eb8, 0x2102fdba2b20d}, XY2D: FieldElement{0x6e405055ce6a1, 0x5024a35a532d3, 0x1f69054daf29d, 0x15d1d0d7a8bd5, 0xad725db29ecb}}, NielsPoint{YPlusX: FieldElement{0x7bc0c9b056f85, 0x51cfebffaffd8, 0x44abbe94df549, 0x7ecbbd7e33121, 0x4f675f5302399}, YMinusX: FieldElement{0x267b1834e2457, 0x6ae19c378bb88, 0x7457b5ed9d512, 0x3280d783d05fb, 0x4aefcffb71a03}, XY2D: FieldElement{0x536360415171e, 0x2313309077865, 0x251444334afbc, 0x2b0c3853756e8, 0xbccbb72a2a86}}, NielsPoint{YPlusX: FieldElement{0x55e4c50fe1296, 0x5fdd13efc30d, 0x1c0c6c380e5ee, 0x3e11de3fb62a8, 0x6678fd69108f3}, YMinusX: FieldElement{0x6962feab1a9c8, 0x6aca28fb9a30b, 0x56db7ca1b9f98, 0x39f58497018dd, 0x4024f0ab59d6b}, XY2D: FieldElement{0x6fa31636863c2, 0x10ae5a67e42b0, 0x27abbf01fda31, 0x380a7b9e64fbc, 0x2d42e2108ead4}}, NielsPoint{YPlusX: FieldElement{0x17b0d0f537593, 0x16263c0c9842e, 0x4ab827e4539a4, 0x6370ddb43d73a, 0x420bf3a79b423}, YMinusX: FieldElement{0x5131594dfd29b, 0x3a627e98d52fe, 0x1154041855661, 0x19175d09f8384, 0x676b2608b8d2d}, XY2D: FieldElement{0xba651c5b2b47, 0x5862363701027, 0xc4d6c219c6db, 0xf03dff8658de, 0x745d2ffa9c0cf}}, NielsPoint{YPlusX: FieldElement{0x6df5721d34e6a, 0x4f32f767a0c06, 0x1d5abeac76e20, 0x41ce9e104e1e4, 0x6e15be54c1dc}, YMinusX: FieldElement{0x25a1e2bc9c8bd, 0x104c8f3b037ea, 0x405576fa96c98, 0x2e86a88e3876f, 0x1ae23ceb960cf}, XY2D: FieldElement{0x25d871932994a, 0x6b9d63b560b6e, 0x2df2814c8d472, 0xfbbee20aa4ed, 0x58ded861278ec}}, NielsPoint{YPlusX: FieldElement{0x35ba8b6c2c9a8, 0x1dea58b3185bf, 0x4b455cd23bbbe, 0x5ec19c04883f8, 0x8ba696b531d5}, YMinusX: FieldElement{0x73793f266c55c, 0xb988a9c93b02, 0x9b0ea32325db, 0x37cae71c17c5e, 0x2ff39de85485f}, XY2D: FieldElement{0x53eeec3efc57a, 0x2fa9fe9022efd, 0x699c72c138154, 0x72a751ebd1ff8, 0x120633b4947cf}}, NielsPoint{YPlusX: FieldElement{0x531474912100a, 0x5afcdf7c0d057, 0x7a9e71b788ded, 0x5ef708f3b0c88, 0x7433be3cb393}, YMinusX: FieldElement{0x4987891610042, 0x79d9d7f5d0172, 0x3c293013b9ec4, 0xc2b85f39caca, 0x35d30a99b4d59}, XY2D: FieldElement{0x144c05ce997f4, 0x4960b8a347fef, 0x1da11f15d74f7, 0x54fac19c0fead, 0x2d873ede7af6d}}, NielsPoint{YPlusX: FieldElement{0x202e14e5df981, 0x2ea02bc3eb54c, 0x38875b2883564, 0x1298c513ae9dd, 0x543618a01600}, YMinusX: FieldElement{0x2316443373409, 0x5de95503b22af, 0x699201beae2df, 0x3db5849ff737a, 0x2e773654707fa}, XY2D: FieldElement{0x2bdf4974c23c1, 0x4b3b9c8d261bd, 0x26ae8b2a9bc28, 0x3068210165c51, 0x4b1443362d079}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x454e91c529ccb, 0x24c98c6bf72cf, 0x486594c3d89a, 0x7ae13a3d7fa3c, 0x17038418eaf66}, YMinusX: FieldElement{0x4b7c7b66e1f7a, 0x4bea185efd998, 0x4fabc711055f8, 0x1fb9f7836fe38, 0x582f446752da6}, XY2D: FieldElement{0x17bd320324ce4, 0x51489117898c6, 0x1684d92a0410b, 0x6e4d90f78c5a7, 0xc2a1c4bcda28}}, NielsPoint{YPlusX: FieldElement{0x4814869bd6945, 0x7b7c391a45db8, 0x57316ac35b641, 0x641e31de9096a, 0x5a6a9b30a314d}, YMinusX: FieldElement{0x5c7d06f1f0447, 0x7db70f80b3a49, 0x6cb4a3ec89a78, 0x43be8ad81397d, 0x7c558bd1c6f64}, XY2D: FieldElement{0x41524d396463d, 0x1586b449e1a1d, 0x2f17e904aed8a, 0x7e1d2861d3c8e, 0x404a5ca0afba}}, NielsPoint{YPlusX: FieldElement{0x49e1b2a416fd1, 0x51c6a0b316c57, 0x575a59ed71bdc, 0x74c021a1fec1e, 0x39527516e7f8e}, YMinusX: FieldElement{0x740070aa743d6, 0x16b64cbdd1183, 0x23f4b7b32eb43, 0x319aba58235b3, 0x46395bfdcadd9}, XY2D: FieldElement{0x7db2d1a5d9a9c, 0x79a200b85422f, 0x355bfaa71dd16, 0xb77ea5f78aa, 0x76579a29e822d}}, NielsPoint{YPlusX: FieldElement{0x4b51352b434f2, 0x1327bd01c2667, 0x434d73b60c8a1, 0x3e0daa89443ba, 0x2c514bb2a277}, YMinusX: FieldElement{0x68e7e49c02a17, 0x45795346fe8b6, 0x89306c8f3546, 0x6d89f6b2f88f6, 0x43a384dc9e05b}, XY2D: FieldElement{0x3d5da8bf1b645, 0x7ded6a96a6d09, 0x6c3494fee2f4d, 0x2c989c8b6bd4, 0x1160920961548}}, NielsPoint{YPlusX: FieldElement{0x5616369b4dcd, 0x4ecab86ac6f47, 0x3c60085d700b2, 0x213ee10dfcea, 0x2f637d7491e6e}, YMinusX: FieldElement{0x5166929dacfaa, 0x190826b31f689, 0x4f55567694a7d, 0x705f4f7b1e522, 0x351e125bc5698}, XY2D: FieldElement{0x49b461af67bbe, 0x75915712c3a96, 0x69a67ef580c0d, 0x54d38ef70cffc, 0x7f182d06e7ce2}}, NielsPoint{YPlusX: FieldElement{0x54b728e217522, 0x69a90971b0128, 0x51a40f2a963a3, 0x10be9ac12a6bf, 0x44acc043241c5}, YMinusX: FieldElement{0x48e64ab0168ec, 0x2a2bdb8a86f4f, 0x7343b6b2d6929, 0x1d804aa8ce9a3, 0x67d4ac8c343e9}, XY2D: FieldElement{0x56bbb4f7a5777, 0x29230627c238f, 0x5ad1a122cd7fb, 0xdea56e50e364, 0x556d1c8312ad7}}, NielsPoint{YPlusX: FieldElement{0x6756b11be821, 0x462147e7bb03e, 0x26519743ebfe0, 0x782fc59682ab5, 0x97abe38cc8c7}, YMinusX: FieldElement{0x740e30c8d3982, 0x7c2b47f4682fd, 0x5cd91b8c7dc1c, 0x77fa790f9e583, 0x746c6c6d1d824}, XY2D: FieldElement{0x1c9877ea52da4, 0x2b37b83a86189, 0x733af49310da5, 0x25e81161c04fb, 0x577e14a34bee8}}, NielsPoint{YPlusX: FieldElement{0x6cebebd4dd72b, 0x340c1e442329f, 0x32347ffd1a93f, 0x14a89252cbbe0, 0x705304b8fb009}, YMinusX: FieldElement{0x268ac61a73b0a, 0x206f234bebe1c, 0x5b403a7cbebe8, 0x7a160f09f4135, 0x60fa7ee96fd78}, XY2D: FieldElement{0x51d354d296ec6, 0x7cbf5a63b16c7, 0x2f50bb3cf0c14, 0x1feb385cac65a, 0x21398e0ca1635}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0xaaf9b4b75601, 0x26b91b5ae44f3, 0x6de808d7ab1c8, 0x6a769675530b0, 0x1bbfb284e98f7}, YMinusX: FieldElement{0x5058a382b33f3, 0x175a91816913e, 0x4f6cdb96b8ae8, 0x17347c9da81d2, 0x5aa3ed9d95a23}, XY2D: FieldElement{0x777e9c7d96561, 0x28e58f006ccac, 0x541bbbb2cac49, 0x3e63282994cec, 0x4a07e14e5e895}}, NielsPoint{YPlusX: FieldElement{0x358cdc477a49b, 0x3cc88fe02e481, 0x721aab7f4e36b, 0x408cc9469953, 0x50af7aed84afa}, YMinusX: FieldElement{0x412cb980df999, 0x5e78dd8ee29dc, 0x171dff68c575d, 0x2015dd2f6ef49, 0x3f0bac391d313}, XY2D: FieldElement{0x7de0115f65be5, 0x4242c21364dc9, 0x6b75b64a66098, 0x33c0102c085, 0x1921a316baebd}}, NielsPoint{YPlusX: FieldElement{0x2ad9ad9f3c18b, 0x5ec1638339aeb, 0x5703b6559a83b, 0x3fa9f4d05d612, 0x7b049deca062c}, YMinusX: FieldElement{0x22f7edfb870fc, 0x569eed677b128, 0x30937dcb0a5af, 0x758039c78ea1b, 0x6458df41e273a}, XY2D: FieldElement{0x3e37a35444483, 0x661fdb7d27b99, 0x317761dd621e4, 0x7323c30026189, 0x6093dccbc2950}}, NielsPoint{YPlusX: FieldElement{0x6eebe6084034b, 0x6cf01f70a8d7b, 0xb41a54c6670a, 0x6c84b99bb55db, 0x6e3180c98b647}, YMinusX: FieldElement{0x39a8585e0706d, 0x3167ce72663fe, 0x63d14ecdb4297, 0x4be21dcf970b8, 0x57d1ea084827a}, XY2D: FieldElement{0x2b6e7a128b071, 0x5b27511755dcf, 0x8584c2930565, 0x68c7bda6f4159, 0x363e999ddd97b}}, NielsPoint{YPlusX: FieldElement{0x48dce24baec6, 0x2b75795ec05e3, 0x3bfa4c5da6dc9, 0x1aac8659e371e, 0x231f979bc6f9b}, YMinusX: FieldElement{0x43c135ee1fc4, 0x2a11c9919f2d5, 0x6334cc25dbacd, 0x295da17b400da, 0x48ee9b78693a0}, XY2D: FieldElement{0x1de4bcc2af3c6, 0x61fc411a3eb86, 0x53ed19ac12ec0, 0x209dbc6b804e0, 0x79bfa9b08792}}, NielsPoint{YPlusX: FieldElement{0x1ed80a2d54245, 0x70efec72a5e79, 0x42151d42a822d, 0x1b5ebb6d631e8, 0x1ef4fb1594706}, YMinusX: FieldElement{0x3a51da300df4, 0x467b52b561c72, 0x4d5920210e590, 0xca769e789685, 0x38c77f684817}, XY2D: FieldElement{0x65ee65b167bec, 0x52da19b850a9, 0x408665656429, 0x7ab39596f9a4c, 0x575ee92a4a0bf}}, NielsPoint{YPlusX: FieldElement{0x6bc450aa4d801, 0x4f4a6773b0ba8, 0x6241b0b0ebc48, 0x40d9c4f1d9315, 0x200a1e7e382f5}, YMinusX: FieldElement{0x80908a182fcf, 0x532913b7ba98, 0x3dccf78c385c3, 0x68002dd5eaba9, 0x43d4e7112cd3f}, XY2D: FieldElement{0x5b967eaf93ac5, 0x360acca580a31, 0x1c65fd5c6f262, 0x71c7f15c2ecab, 0x50eca52651e4}}, NielsPoint{YPlusX: FieldElement{0x4397660e668ea, 0x7c2a75692f2f5, 0x3b29e7e6c66ef, 0x72ba658bcda9a, 0x6151c09fa131a}, YMinusX: FieldElement{0x31ade453f0c9c, 0x3dfee07737868, 0x611ecf7a7d411, 0x2637e6cbd64f6, 0x4b0ee6c21c58f}, XY2D: FieldElement{0x55c0dfdf05d96, 0x405569dcf475e, 0x5c5c277498bb, 0x18588d95dc389, 0x1fef24fa800f0}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x2aff530976b86, 0xd85a48c0845a, 0x796eb963642e0, 0x60bee50c4b626, 0x28005fe6c8340}, YMinusX: FieldElement{0x653fb1aa73196, 0x607faec8306fa, 0x4e85ec83e5254, 0x9f56900584fd, 0x544d49292fc86}, XY2D: FieldElement{0x7ba9f34528688, 0x284a20fb42d5d, 0x3652cd9706ffe, 0x6fd7baddde6b3, 0x72e472930f316}}, NielsPoint{YPlusX: FieldElement{0x3f635d32a7627, 0xcbecacde00fe, 0x3411141eaa936, 0x21c1e42f3cb94, 0x1fee7f000fe06}, YMinusX: FieldElement{0x5208c9781084f, 0x16468a1dc24d2, 0x7bf780ac540a8, 0x1a67eced75301, 0x5a9d2e8c2733a}, XY2D: FieldElement{0x305da03dbf7e5, 0x1228699b7aeca, 0x12a23b2936bc9, 0x2a1bda56ae6e9, 0xf94051ee040}}, NielsPoint{YPlusX: FieldElement{0x793bb07af9753, 0x1e7b6ecd4fafd, 0x2c7b1560fb43, 0x2296734cc5fb7, 0x47b7ffd25dd40}, YMinusX: FieldElement{0x56b23c3d330b2, 0x37608e360d1a6, 0x10ae0f3c8722e, 0x86d9b618b637, 0x7d79c7e8beab}, XY2D: FieldElement{0x3fb9cbc08dd12, 0x75c3dd85370ff, 0x47f06fe2819ac, 0x5db06ab9215ed, 0x1c3520a35ea64}}, NielsPoint{YPlusX: FieldElement{0x6f40216bc059, 0x3a2579b0fd9b5, 0x71c26407eec8c, 0x72ada4ab54f0b, 0x38750c3b66d12}, YMinusX: FieldElement{0x253a6bccba34a, 0x427070433701a, 0x20b8e58f9870e, 0x337c861db00cc, 0x1c3d05775d0ee}, XY2D: FieldElement{0x6f1409422e51a, 0x7856bbece2d25, 0x13380a72f031c, 0x43e1080a7f3ba, 0x621e2c7d3304}}, NielsPoint{YPlusX: FieldElement{0x61796b0dbf0f3, 0x73c2f9c32d6f5, 0x6aa8ed1537ebe, 0x74e92c91838f4, 0x5d8e589ca1002}, YMinusX: FieldElement{0x60cc8259838d, 0x38d3f35b95f3, 0x56078c243a923, 0x2de3293241bb2, 0x7d6097bd3a}, XY2D: FieldElement{0x71d950842a94b, 0x46b11e5c7d817, 0x5478bbecb4f0d, 0x7c3054b0a1c5d, 0x1583d7783c1cb}}, NielsPoint{YPlusX: FieldElement{0x34704cc9d28c7, 0x3dee598b1f200, 0x16e1c98746d9e, 0x4050b7095afdf, 0x4958064e83c55}, YMinusX: FieldElement{0x6a2ef5da27ae1, 0x28aace02e9d9d, 0x2459e965f0e8, 0x7b864d3150933, 0x252a5f2e81ed8}, XY2D: FieldElement{0x94265066e80d, 0xa60f918d61a5, 0x444bf7f30fde, 0x1c40da9ed3c06, 0x79c170bd843b}}, NielsPoint{YPlusX: FieldElement{0x6cd50c0d5d056, 0x5b7606ae779ba, 0x70fbd226bdda1, 0x5661e53391ff9, 0x6768c0d7317b8}, YMinusX: FieldElement{0x6ece464fa6fff, 0x3cc40bca460a0, 0x6e3a90afb8d0c, 0x5801abca11228, 0x6dec05e34ac9f}, XY2D: FieldElement{0x625e5f155c1b3, 0x4f32f6f723296, 0x5ac980105efce, 0x17a61165eee36, 0x51445e14ddcd5}}, NielsPoint{YPlusX: FieldElement{0x147ab2bbea455, 0x1f240f2253126, 0xc3de9e314e89, 0x21ea5a4fca45f, 0x12e990086e4fd}, YMinusX: FieldElement{0x2b4b3b144951, 0x5688977966aea, 0x18e176e399ffd, 0x2e45c5eb4938b, 0x13186f31e3929}, XY2D: FieldElement{0x496b37fdfbb2e, 0x3c2439d5f3e21, 0x16e60fe7e6a4d, 0x4d7ef889b621d, 0x77b2e3f05d3e9}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x639c12ddb0a4, 0x6180490cd7ab3, 0x3f3918297467c, 0x74568be1781ac, 0x7a195152e095}, YMinusX: FieldElement{0x7a9c59c2ec4de, 0x7e9f09e79652d, 0x6a3e422f22d86, 0x2ae8e3b836c8b, 0x63b795fc7ad32}, XY2D: FieldElement{0x68f02389e5fc8, 0x59f1bc877506, 0x504990e410cec, 0x9bd7d0feaee2, 0x3e8fe83d032f0}}, NielsPoint{YPlusX: FieldElement{0x4c8de8efd13c, 0x1c67c06e6210e, 0x183378f7f146a, 0x64352ceaed289, 0x22d60899a6258}, YMinusX: FieldElement{0x315b90570a294, 0x60ce108a925f1, 0x6eff61253c909, 0x3ef0e2d70b0, 0x75ba3b797fac4}, XY2D: FieldElement{0x1dbc070cdd196, 0x16d8fb1534c47, 0x500498183fa2a, 0x72f59c423de75, 0x904d07b87779}}, NielsPoint{YPlusX: FieldElement{0x22d6648f940b9, 0x197a5a1873e86, 0x207e4c41a54bc, 0x5360b3b4bd6d0, 0x6240aacebaf72}, YMinusX: FieldElement{0x61fd4ddba919c, 0x7d8e991b55699, 0x61b31473cc76c, 0x7039631e631d6, 0x43e2143fbc1dd}, XY2D: FieldElement{0x4749c5ba295a0, 0x37946fa4b5f06, 0x724c5ab5a51f1, 0x65633789dd3f3, 0x56bdaf238db40}}, NielsPoint{YPlusX: FieldElement{0xd36cc19d3bb2, 0x6ec4470d72262, 0x6853d7018a9ae, 0x3aa3e4dc2c8eb, 0x3aa31507e1e5}, YMinusX: FieldElement{0x2b9e3f53533eb, 0x2add727a806c5, 0x56955c8ce15a3, 0x18c4f070a290e, 0x1d24a86d83741}, XY2D: FieldElement{0x47648ffd4ce1f, 0x60a9591839e9d, 0x424d5f38117ab, 0x42cc46912c10e, 0x43b261dc9aeb4}}, NielsPoint{YPlusX: FieldElement{0x13d8b6c951364, 0x4c0017e8f632a, 0x53e559e53f9c4, 0x4b20146886eea, 0x2b4d5e242940}, YMinusX: FieldElement{0x31e1988bb79bb, 0x7b82f46b3bcab, 0xf7a8ce827b41, 0x5e15816177130, 0x326055cf5b276}, XY2D: FieldElement{0x155cb28d18df2, 0xc30d9ca11694, 0x2090e27ab3119, 0x208624e7a49b6, 0x27a6c809ae5d3}}, NielsPoint{YPlusX: FieldElement{0x4270ac43d6954, 0x2ed4cd95659a5, 0x75c0db37528f9, 0x2ccbcfd2c9234, 0x221503603d8c2}, YMinusX: FieldElement{0x6ebcd1f0db188, 0x74ceb4b7d1174, 0x7d56168df4f5c, 0xbf79176fd18a, 0x2cb67174ff60a}, XY2D: FieldElement{0x6cdf9390be1d0, 0x8e519c7e2b3d, 0x253c3d2a50881, 0x21b41448e333d, 0x7b1df4b73890f}}, NielsPoint{YPlusX: FieldElement{0x6221807f8f58c, 0x3fa92813a8be5, 0x6da98c38d5572, 0x1ed95554468f, 0x68698245d352e}, YMinusX: FieldElement{0x2f2e0b3b2a224, 0xc56aa22c1c92, 0x5fdec39f1b278, 0x4c90af5c7f106, 0x61fcef2658fc5}, XY2D: FieldElement{0x15d852a18187a, 0x270dbb59afb76, 0x7db120bcf92ab, 0xe7a25d714087, 0x46cf4c473daf0}}, NielsPoint{YPlusX: FieldElement{0x46ea7f1498140, 0x70725690a8427, 0xa73ae9f079fb, 0x2dd924461c62b, 0x1065aae50d8cc}, YMinusX: FieldElement{0x525ed9ec4e5f9, 0x22d20660684c, 0x7972b70397b68, 0x7a03958d3f965, 0x29387bcd14eb5}, XY2D: FieldElement{0x44525df200d57, 0x2d7f94ce94385, 0x60d00c170ecb7, 0x38b0503f3d8f0, 0x69a198e64f1ce}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x14434dcc5caed, 0x2c7909f667c20, 0x61a839d1fb576, 0x4f23800cabb76, 0x25b2697bd267f}, YMinusX: FieldElement{0x2b2e0d91a78bc, 0x3990a12ccf20c, 0x141c2e11f2622, 0xdfcefaa53320, 0x7369e6a92493a}, XY2D: FieldElement{0x73ffb13986864, 0x3282bb8f713ac, 0x49ced78f297ef, 0x6697027661def, 0x1420683db54e4}}, NielsPoint{YPlusX: FieldElement{0x6bb6fc1cc5ad0, 0x532c8d591669d, 0x1af794da86c33, 0xe0e9d86d24d3, 0x31e83b4161d08}, YMinusX: FieldElement{0xbd1e249dd197, 0xbcb1820568f, 0x2eab1718830d4, 0x396fd816997e6, 0x60b63bebf508a}, XY2D: FieldElement{0xc7129e062b4f, 0x1e526415b12fd, 0x461a0fd27923d, 0x18badf670a5b7, 0x55cf1eb62d550}}, NielsPoint{YPlusX: FieldElement{0x6b5e37df58c52, 0x3bcf33986c60e, 0x44fb8835ceae7, 0x99dec18e71a4, 0x1a56fbaa62ba0}, YMinusX: FieldElement{0x1101065c23d58, 0x5aa1290338b0f, 0x3157e9e2e7421, 0xea712017d489, 0x669a656457089}, XY2D: FieldElement{0x66b505c9dc9ec, 0x774ef86e35287, 0x4d1d944c0955e, 0x52e4c39d72b20, 0x13c4836799c58}}, NielsPoint{YPlusX: FieldElement{0x4fb6a5d8bd080, 0x58ae34908589b, 0x3954d977baf13, 0x413ea597441dc, 0x50bdc87dc8e5b}, YMinusX: FieldElement{0x25d465ab3e1b9, 0xf8fe27ec2847, 0x2d6e6dbf04f06, 0x3038cfc1b3276, 0x66f80c93a637b}, XY2D: FieldElement{0x537836edfe111, 0x2be02357b2c0d, 0x6dcee58c8d4f8, 0x2d732581d6192, 0x1dd56444725fd}}, NielsPoint{YPlusX: FieldElement{0x7e60008bac89a, 0x23d5c387c1852, 0x79e5df1f533a8, 0x2e6f9f1c5f0cf, 0x3a3a450f63a30}, YMinusX: FieldElement{0x47ff83362127d, 0x8e39af82b1f4, 0x488322ef27dab, 0x1973738a2a1a4, 0xe645912219f7}, XY2D: FieldElement{0x72f31d8394627, 0x7bd294a200f1, 0x665be00e274c6, 0x43de8f1b6368b, 0x318c8d9393a9a}}, NielsPoint{YPlusX: FieldElement{0x69e29ab1dd398, 0x30685b3c76bac, 0x565cf37f24859, 0x57b2ac28efef9, 0x509a41c325950}, YMinusX: FieldElement{0x45d032afffe19, 0x12fe49b6cde4e, 0x21663bc327cf1, 0x18a5e4c69f1dd, 0x224c7c679a1d5}, XY2D: FieldElement{0x6edca6f925e9, 0x68c8363e677b8, 0x60cfa25e4fbcf, 0x1c4c17609404e, 0x5bff02328a11}}, NielsPoint{YPlusX: FieldElement{0x1a0dd0dc512e4, 0x10894bf5fcd10, 0x52949013f9c37, 0x1f50fba4735c7, 0x576277cdee01a}, YMinusX: FieldElement{0x2137023cae00b, 0x15a3599eb26c6, 0x687221512b3c, 0x253cb3a0824e9, 0x780b8cc3fa2a4}, XY2D: FieldElement{0x38abc234f305f, 0x7a280bbc103de, 0x398a836695dfe, 0x3d0af41528a1a, 0x5ff418726271b}}, NielsPoint{YPlusX: FieldElement{0x347e813b69540, 0x76864c21c3cbb, 0x1e049dbcd74a8, 0x5b4d60f93749c, 0x29d4db8ca0a0c}, YMinusX: FieldElement{0x6080c1789db9d, 0x4be7cef1ea731, 0x2f40d769d8080, 0x35f7d4c44a603, 0x106a03dc25a96}, XY2D: FieldElement{0x50aaf333353d0, 0x4b59a613cbb35, 0x223dfc0e19a76, 0x77d1e2bb2c564, 0x4ab38a51052cb}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x7d1ef5fddc09c, 0x7beeaebb9dad9, 0x58d30ba0acfb, 0x5cd92eab5ae90, 0x3041c6bb04ed2}, YMinusX: FieldElement{0x42b256768d593, 0x2e88459427b4f, 0x2b3876630701, 0x34878d405eae5, 0x29cdd1adc088a}, XY2D: FieldElement{0x2f2f9d956e148, 0x6b3e6ad65c1fe, 0x5b00972b79e5d, 0x53d8d234c5daf, 0x104bbd6814049}}, NielsPoint{YPlusX: FieldElement{0x59a5fd67ff163, 0x3a998ead0352b, 0x83c95fa4af9a, 0x6fadbfc01266f, 0x204f2a20fb072}, YMinusX: FieldElement{0xfd3168f1ed67, 0x1bb0de7784a3e, 0x34bcb78b20477, 0xa4a26e2e2182, 0x5be8cc57092a7}, XY2D: FieldElement{0x43b3d30ebb079, 0x357aca5c61902, 0x5b570c5d62455, 0x30fb29e1e18c7, 0x2570fb17c2791}}, NielsPoint{YPlusX: FieldElement{0x6a9550bb8245a, 0x511f20a1a2325, 0x29324d7239bee, 0x3343cc37516c4, 0x241c5f91de018}, YMinusX: FieldElement{0x2367f2cb61575, 0x6c39ac04d87df, 0x6d4958bd7e5bd, 0x566f4638a1532, 0x3dcb65ea53030}, XY2D: FieldElement{0x172940de6caa, 0x6045b2e67451b, 0x56c07463efcb3, 0x728b6bfe6e91, 0x8420edd5fcdf}}, NielsPoint{YPlusX: FieldElement{0xc34e04f410ce, 0x344edc0d0a06b, 0x6e45486d84d6d, 0x44e2ecb3863f5, 0x4d654f321db8}, YMinusX: FieldElement{0x720ab8362fa4a, 0x29c4347cdd9bf, 0xe798ad5f8463, 0x4fef18bcb0bfe, 0xd9a53efbc176}, XY2D: FieldElement{0x5c116ddbdb5d5, 0x6d1b4bba5abcf, 0x4d28a48a5537a, 0x56b8e5b040b99, 0x4a7a4f2618991}}, NielsPoint{YPlusX: FieldElement{0x3b291af372a4b, 0x60e3028fe4498, 0x2267bca4f6a09, 0x719eec242b243, 0x4a96314223e0e}, YMinusX: FieldElement{0x718025fb15f95, 0x68d6b8371fe94, 0x3804448f7d97c, 0x42466fe784280, 0x11b50c4cddd31}, XY2D: FieldElement{0x274408a4ffd6, 0x7d382aedb34dd, 0x40acfc9ce385d, 0x628bb99a45b1e, 0x4f4bce4dce6bc}}, NielsPoint{YPlusX: FieldElement{0x2616ec49d0b6f, 0x1f95d8462e61c, 0x1ad3e9b9159c6, 0x79ba475a04df9, 0x3042cee561595}, YMinusX: FieldElement{0x7ce5ae2242584, 0x2d25eb153d4e3, 0x3a8f3d09ba9c9, 0xf3690d04eb8e, 0x73fcdd14b71c0}, XY2D: FieldElement{0x67079449bac41, 0x5b79c4621484f, 0x61069f2156b8d, 0xeb26573b10af, 0x389e740c9a9ce}}, NielsPoint{YPlusX: FieldElement{0x578f6570eac28, 0x644f2339c3937, 0x66e47b7956c2c, 0x34832fe1f55d0, 0x25c425e5d6263}, YMinusX: FieldElement{0x4b3ae34dcb9ce, 0x47c691a15ac9f, 0x318e06e5d400c, 0x3c422d9f83eb1, 0x61545379465a6}, XY2D: FieldElement{0x606a6f1d7de6e, 0x4f1c0c46107e7, 0x229b1dcfbe5d8, 0x3acc60a7b1327, 0x6539a08915484}}, NielsPoint{YPlusX: FieldElement{0x4dbd414bb4a19, 0x7930849f1dbb8, 0x329c5a466caf0, 0x6c824544feb9b, 0xf65320ef019b}, YMinusX: FieldElement{0x21f74c3d2f773, 0x24b88d08bd3a, 0x6e678cf054151, 0x43631272e747c, 0x11c5e4aac5cd1}, XY2D: FieldElement{0x6d1b1cafde0c6, 0x462c76a303a90, 0x3ca4e693cff9b, 0x3952cd45786fd, 0x4cabc7bdec330}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x7788f3f78d289, 0x5942809b3f811, 0x5973277f8c29c, 0x10f93bc5fe67, 0x7ee498165acb2}, YMinusX: FieldElement{0x69624089c0a2e, 0x75fc8e70473, 0x13e84ab1d2313, 0x2c10bedf6953b, 0x639b93f0321c8}, XY2D: FieldElement{0x508e39111a1c3, 0x290120e912f7a, 0x1cbf464acae43, 0x15373e9576157, 0xedf493c85b60}}, NielsPoint{YPlusX: FieldElement{0x7c4d284764113, 0x7fefebf06acec, 0x39afb7a824100, 0x1b48e47e7fd65, 0x4c00c54d1dfa}, YMinusX: FieldElement{0x48158599b5a68, 0x1fd75bc41d5d9, 0x2d9fc1fa95d3c, 0x7da27f20eba11, 0x403b92e3019d4}, XY2D: FieldElement{0x22f818b465cf8, 0x342901dff09b8, 0x31f595dc683cd, 0x37a57745fd682, 0x355bb12ab2617}}, NielsPoint{YPlusX: FieldElement{0x1dac75a8c7318, 0x3b679d5423460, 0x6b8fcb7b6400e, 0x6c73783be5f9d, 0x7518eaf8e052a}, YMinusX: FieldElement{0x664cc7493bbf4, 0x33d94761874e3, 0x179e1796f613, 0x1890535e2867d, 0xf9b8132182ec}, XY2D: FieldElement{0x59c41b7f6c32, 0x79e8706531491, 0x6c747643cb582, 0x2e20c0ad494e4, 0x47c3871bbb175}}, NielsPoint{YPlusX: FieldElement{0x65d50c85066b0, 0x6167453361f7c, 0x6ba3818bb312, 0x6aff29baa7522, 0x8fea02ce8d48}, YMinusX: FieldElement{0x4539771ec4f48, 0x7b9318badca28, 0x70f19afe016c5, 0x4ee7bb1608d23, 0xb89b8576469}, XY2D: FieldElement{0x5dd7668deead0, 0x4096d0ba47049, 0x6275997219114, 0x29bda8a67e6ae, 0x473829a74f75d}}, NielsPoint{YPlusX: FieldElement{0x1533aad3902c9, 0x1dde06b11e47b, 0x784bed1930b77, 0x1c80a92b9c867, 0x6c668b4d44e4d}, YMinusX: FieldElement{0x2da754679c418, 0x3164c31be105a, 0x11fac2b98ef5f, 0x35a1aaf779256, 0x2078684c4833c}, XY2D: FieldElement{0xcf217a78820c, 0x65024e7d2e769, 0x23bb5efdda82a, 0x19fd4b632d3c6, 0x7411a6054f8a4}}, NielsPoint{YPlusX: FieldElement{0x2e53d18b175b4, 0x33e7254204af3, 0x3bcd7d5a1c4c5, 0x4c7c22af65d0f, 0x1ec9a872458c3}, YMinusX: FieldElement{0x59d32b99dc86d, 0x6ac075e22a9ac, 0x30b9220113371, 0x27fd9a638966e, 0x7c136574fb813}, XY2D: FieldElement{0x6a4d400a2509b, 0x41791056971c, 0x655d5866e075c, 0x2302bf3e64df8, 0x3add88a5c7cd6}}, NielsPoint{YPlusX: FieldElement{0x298d459393046, 0x30bfecb3d90b8, 0x3d9b8ea3df8d6, 0x3900e96511579, 0x61ba1131a406a}, YMinusX: FieldElement{0x15770b635dcf2, 0x59ecd83f79571, 0x2db461c0b7fbd, 0x73a42a981345f, 0x249929fccc879}, XY2D: FieldElement{0xa0f116959029, 0x5974fd7b1347a, 0x1e0cc1c08edad, 0x673bdf8ad1f13, 0x5620310cbbd8e}}, NielsPoint{YPlusX: FieldElement{0x6b5f477e285d6, 0x4ed91ec326cc8, 0x6d6537503a3fd, 0x626d3763988d5, 0x7ec846f3658ce}, YMinusX: FieldElement{0x193434934d643, 0xd4a2445eaa51, 0x7d0708ae76fe0, 0x39847b6c3c7e1, 0x37676a2a4d9d9}, XY2D: FieldElement{0x68f3f1da22ec7, 0x6ed8039a2736b, 0x2627ee04c3c75, 0x6ea90a647e7d1, 0x6daaf723399b9}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x304bfacad8ea2, 0x502917d108b07, 0x43176ca6dd0f, 0x5d5158f2c1d84, 0x2b5449e58eb3b}, YMinusX: FieldElement{0x27562eb3dbe47, 0x291d7b4170be7, 0x5d1ca67dfa8e1, 0x2a88061f298a2, 0x1304e9e71627d}, XY2D: FieldElement{0x14d26adc9cfe, 0x7f1691ba16f13, 0x5e71828f06eac, 0x349ed07f0fffc, 0x4468de2d7c2dd}}, NielsPoint{YPlusX: FieldElement{0x2d8c6f86307ce, 0x6286ba1850973, 0x5e9dcb08444d4, 0x1a96a543362b2, 0x5da6427e63247}, YMinusX: FieldElement{0x3355e9419469e, 0x1847bb8ea8a37, 0x1fe6588cf9b71, 0x6b1c9d2db6b22, 0x6cce7c6ffb44b}, XY2D: FieldElement{0x4c688deac22ca, 0x6f775c3ff0352, 0x565603ee419bb, 0x6544456c61c46, 0x58f29abfe79f2}}, NielsPoint{YPlusX: FieldElement{0x264bf710ecdf6, 0x708c58527896b, 0x42ceae6c53394, 0x4381b21e82b6a, 0x6af93724185b4}, YMinusX: FieldElement{0x6cfab8de73e68, 0x3e6efced4bd21, 0x56609500dbe, 0x71b7824ad85df, 0x577629c4a7f41}, XY2D: FieldElement{0x24509c6a888, 0x2696ab12e6644, 0xcca27f4b80d8, 0xc7c1f11b119e, 0x701f25bb0caec}}, NielsPoint{YPlusX: FieldElement{0xf6d97cbec113, 0x4ce97fb7c93a3, 0x139835a11281b, 0x728907ada9156, 0x720a5bc050955}, YMinusX: FieldElement{0xb0f8e4616ced, 0x1d3c4b50fb875, 0x2f29673dc0198, 0x5f4b0f1830ffa, 0x2e0c92bfbdc40}, XY2D: FieldElement{0x709439b805a35, 0x6ec48557f8187, 0x8a4d1ba13a2c, 0x76348a0bf9ae, 0xe9b9cbb144ef}}, NielsPoint{YPlusX: FieldElement{0x69bd55db1beee, 0x6e14e47f731bd, 0x1a35e47270eac, 0x66f225478df8e, 0x366d44191cfd3}, YMinusX: FieldElement{0x2d48ffb5720ad, 0x57b7f21a1df77, 0x5550effba0645, 0x5ec6a4098a931, 0x221104eb3f337}, XY2D: FieldElement{0x41743f2bc8c14, 0x796b0ad8773c7, 0x29fee5cbb689b, 0x122665c178734, 0x4167a4e6bc593}}, NielsPoint{YPlusX: FieldElement{0x62665f8ce8fee, 0x29d101ac59857, 0x4d93bbba59ffc, 0x17b7897373f17, 0x34b33370cb7ed}, YMinusX: FieldElement{0x39d2876f62700, 0x1cecd1d6c87, 0x7f01a11747675, 0x2350da5a18190, 0x7938bb7e22552}, XY2D: FieldElement{0x591ee8681d6cc, 0x39db0b4ea79b8, 0x202220f380842, 0x2f276ba42e0ac, 0x1176fc6e2dfe6}}, NielsPoint{YPlusX: FieldElement{0xe28949770eb8, 0x5559e88147b72, 0x35e1e6e63ef30, 0x35b109aa7ff6f, 0x1f6a3e54f2690}, YMinusX: FieldElement{0x76cd05b9c619b, 0x69654b0901695, 0x7a53710b77f27, 0x79a1ea7d28175, 0x8fc3a4c677d5}, XY2D: FieldElement{0x4c199d30734ea, 0x6c622cb9acc14, 0x5660a55030216, 0x68f1199f11fb, 0x4f2fad0116b90}}, NielsPoint{YPlusX: FieldElement{0x4d91db73bb638, 0x55f82538112c5, 0x6d85a279815de, 0x740b7b0cd9cf9, 0x3451995f2944e}, YMinusX: FieldElement{0x6b24194ae4e54, 0x2230afded8897, 0x23412617d5071, 0x3d5d30f35969b, 0x445484a4972ef}, XY2D: FieldElement{0x2fcd09fea7d7c, 0x296126b9ed22a, 0x4a171012a05b2, 0x1db92c74d5523, 0x10b89ca604289}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x141be5a45f06e, 0x5adb38becaea7, 0x3fd46db41f2bb, 0x6d488bbb5ce39, 0x17d2d1d9ef0d4}, YMinusX: FieldElement{0x147499718289c, 0xa48a67e4c7ab, 0x30fbc544bafe3, 0xc701315fe58a, 0x20b878d577b75}, XY2D: FieldElement{0x2af18073f3e6a, 0x33aea420d24fe, 0x298008bf4ff94, 0x3539171db961e, 0x72214f63cc65c}}, NielsPoint{YPlusX: FieldElement{0x5b7b9f43b29c9, 0x149ea31eea3b3, 0x4be7713581609, 0x2d87960395e98, 0x1f24ac855a154}, YMinusX: FieldElement{0x37f405307a693, 0x2e5e66cf2b69c, 0x5d84266ae9c53, 0x5e4eb7de853b9, 0x5fdf48c58171c}, XY2D: FieldElement{0x608328e9505aa, 0x22182841dc49a, 0x3ec96891d2307, 0x2f363fff22e03, 0xba739e2ae39}}, NielsPoint{YPlusX: FieldElement{0x426f5ea88bb26, 0x33092e77f75c8, 0x1a53940d819e7, 0x1132e4f818613, 0x72297de7d518d}, YMinusX: FieldElement{0x698de5c8790d6, 0x268b8545beb25, 0x6d2648b96fedf, 0x47988ad1db07c, 0x3283a3e67ad7}, XY2D: FieldElement{0x41dc7be0cb939, 0x1b16c66100904, 0xa24c20cbc66d, 0x4a2e9efe48681, 0x5e1296846271}}, NielsPoint{YPlusX: FieldElement{0x7bbc8242c4550, 0x59a06103b35b7, 0x7237e4af32033, 0x726421ab3537a, 0x78cf25d38258c}, YMinusX: FieldElement{0x2eeb32d9c495a, 0x79e25772f9750, 0x6d747833bbf23, 0x6cdd816d5d749, 0x39c00c9c13698}, XY2D: FieldElement{0x66b8e31489d68, 0x573857e10e2b5, 0x13be816aa1472, 0x41964d3ad4bf8, 0x6b52076b3ff}}, NielsPoint{YPlusX: FieldElement{0x37e16b9ce082d, 0x1882f57853eb9, 0x7d29eacd01fc5, 0x2e76a59b5e715, 0x7de2e9561a9f7}, YMinusX: FieldElement{0xcfe19d95781c, 0x312cc621c453c, 0x145ace6da077c, 0x912bef9ce9b8, 0x4d57e3443bc76}, XY2D: FieldElement{0xd4f4b6a55ecb, 0x7ebb0bb733bce, 0x7ba6a05200549, 0x4f6ede4e22069, 0x6b2a90af1a602}}, NielsPoint{YPlusX: FieldElement{0x3f3245bb2d80a, 0xe5f720f36efd, 0x3b9cccf60c06d, 0x84e323f37926, 0x465812c8276c2}, YMinusX: FieldElement{0x3f4fc9ae61e97, 0x3bc07ebfa2d24, 0x3b744b55cd4a0, 0x72553b25721f3, 0x5fd8f4e9d12d3}, XY2D: FieldElement{0x3beb22a1062d9, 0x6a7063b82c9a8, 0xa5a35dc197ed, 0x3c80c06a53def, 0x5b32c2b1cb16}}, NielsPoint{YPlusX: FieldElement{0x4a42c7ad58195, 0x5c8667e799eff, 0x2e5e74c850a1, 0x3f0db614e869a, 0x31771a4856730}, YMinusX: FieldElement{0x5eccd24da8fd, 0x580bbfdf07918, 0x7e73586873c6a, 0x74ceddf77f93e, 0x3b5556a37b471}, XY2D: FieldElement{0xc524e14dd482, 0x283457496c656, 0xad6bcfb6cd45, 0x375d1e8b02414, 0x4fc079d27a733}}, NielsPoint{YPlusX: FieldElement{0x48b440c86c50d, 0x139929cca3b86, 0xf8f2e44cdf2f, 0x68432117ba6b2, 0x241170c2bae3c}, YMinusX: FieldElement{0x138b089bf2f7f, 0x4a05bfd34ea39, 0x203914c925ef5, 0x7497fffe04e3c, 0x124567cecaf98}, XY2D: FieldElement{0x1ab860ac473b4, 0x5c0227c86a7ff, 0x71b12bfc24477, 0x6a573a83075, 0x3f8612966c870}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0xfcfa36048d13, 0x66e7133bbb383, 0x64b42a8a45676, 0x4ea6e4f9a85cf, 0x26f57eee878a1}, YMinusX: FieldElement{0x20cc9782a0dde, 0x65d4e3070aab3, 0x7bc8e31547736, 0x9ebfb1432d98, 0x504aa77679736}, XY2D: FieldElement{0x32cd55687efb1, 0x4448f5e2f6195, 0x568919d460345, 0x34c2e0ad1a27, 0x4041943d9dba3}}, NielsPoint{YPlusX: FieldElement{0x17743a26caadd, 0x48c9156f9c964, 0x7ef278d1e9ad0, 0xce58ea7bd01, 0x12d931429800d}, YMinusX: FieldElement{0xeeba43ebcc96, 0x384dd5395f878, 0x1df331a35d272, 0x207ecfd4af70e, 0x1420a1d976843}, XY2D: FieldElement{0x67799d337594f, 0x1647548f6018, 0x57fce5578f145, 0x9220c142a71, 0x1b4f92314359a}}, NielsPoint{YPlusX: FieldElement{0x73030a49866b1, 0x2442be90b2679, 0x77bd3d8947dcf, 0x1fb55c1552028, 0x5ff191d56f9a2}, YMinusX: FieldElement{0x4109d89150951, 0x225bd2d2d47cb, 0x57cc080e73bea, 0x6d71075721fcb, 0x239b572a7f132}, XY2D: FieldElement{0x6d433ac2d9068, 0x72bf930a47033, 0x64facf4a20ead, 0x365f7a2b9402a, 0x20c526a758f3}}, NielsPoint{YPlusX: FieldElement{0x1ef59f042cc89, 0x3b1c24976dd26, 0x31d665cb16272, 0x28656e470c557, 0x452cfe0a5602c}, YMinusX: FieldElement{0x34f89ed8dbbc, 0x73b8f948d8ef3, 0x786c1d323caab, 0x43bd4a9266e51, 0x2aacc4615313}, XY2D: FieldElement{0xf7a0647877df, 0x4e1cc0f93f0d4, 0x7ec4726ef1190, 0x3bdd58bf512f8, 0x4cfb7d7b304b8}}, NielsPoint{YPlusX: FieldElement{0x699c29789ef12, 0x63beae321bc50, 0x325c340adbb35, 0x562e1a1e42bf6, 0x5b1d4cbc434d3}, YMinusX: FieldElement{0x43d6cb89b75fe, 0x3338d5b900e56, 0x38d327d531a53, 0x1b25c61d51b9f, 0x14b4622b39075}, XY2D: FieldElement{0x32615cc0a9f26, 0x57711b99cb6df, 0x5a69c14e93c38, 0x6e88980a4c599, 0x2f98f71258592}}, NielsPoint{YPlusX: FieldElement{0x2ae444f54a701, 0x615397afbc5c2, 0x60d7783f3f8fb, 0x2aa675fc486ba, 0x1d8062e9e7614}, YMinusX: FieldElement{0x4a74cb50f9e56, 0x531d1c2640192, 0xc03d9d6c7fd2, 0x57ccd156610c1, 0x3a6ae249d806a}, XY2D: FieldElement{0x2da85a9907c5a, 0x6b23721ec4caf, 0x4d2d3a4683aa2, 0x7f9c6870efdef, 0x298b8ce8aef25}}, NielsPoint{YPlusX: FieldElement{0x272ea0a2165de, 0x68179ef3ed06f, 0x4e2b9c0feac1e, 0x3ee290b1b63bb, 0x6ba6271803a7d}, YMinusX: FieldElement{0x27953eff70cb2, 0x54f22ae0ec552, 0x29f3da92e2724, 0x242ca0c22bd18, 0x34b8a8404d5ce}, XY2D: FieldElement{0x6ecb583693335, 0x3ec76bfdfb84d, 0x2c895cf56a04f, 0x6355149d54d52, 0x71d62bdd465e1}}, NielsPoint{YPlusX: FieldElement{0x5b5dab1f75ef5, 0x1e2d60cbeb9a5, 0x527c2175dfe57, 0x59e8a2b8ff51f, 0x1c333621262b2}, YMinusX: FieldElement{0x3cc28d378df80, 0x72141f4968ca6, 0x407696bdb6d0d, 0x5d271b22ffcfb, 0x74d5f317f3172}, XY2D: FieldElement{0x7e55467d9ca81, 0x6a5653186f50d, 0x6b188ece62df1, 0x4c66d36844971, 0x4aebcc4547e9d}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x8d9e7354b610, 0x26b750b6dc168, 0x162881e01acc9, 0x7966df31d01a5, 0x173bd9ddc9a1d}, YMinusX: FieldElement{0x71b276d01c9, 0xb0d8918e025e, 0x75beea79ee2eb, 0x3c92984094db8, 0x5d88fbf95a3db}, XY2D: FieldElement{0xf1efe5872df, 0x5da872318256a, 0x59ceb81635960, 0x18cf37693c764, 0x6e1cd13b19ea}}, NielsPoint{YPlusX: FieldElement{0x3af629e5b0353, 0x204f1a088e8e5, 0x10efc9ceea82e, 0x589863c2fa34b, 0x7f3a6a1a8d837}, YMinusX: FieldElement{0xad516f166f23, 0x263f56d57c81a, 0x13422384638ca, 0x1331ff1af0a50, 0x3080603526e16}, XY2D: FieldElement{0x644395d3d800b, 0x2b9203dbedefc, 0x4b18ce656a355, 0x3f3466bc182c, 0x30d0fded2e513}}, NielsPoint{YPlusX: FieldElement{0x4971e68b84750, 0x52ccc9779f396, 0x3e904ae8255c8, 0x4ecae46f39339, 0x4615084351c58}, YMinusX: FieldElement{0x14d1af21233b3, 0x1de1989b39c0b, 0x52669dc6f6f9e, 0x43434b28c3fc7, 0xa9214202c099}, XY2D: FieldElement{0x19c0aeb9a02e, 0x1a2c06995d792, 0x664cbb1571c44, 0x6ff0736fa80b2, 0x3bca0d2895ca5}}, NielsPoint{YPlusX: FieldElement{0x8eb69ecc01bf, 0x5b4c8912df38d, 0x5ea7f8bc2f20e, 0x120e516caafaf, 0x4ea8b4038df28}, YMinusX: FieldElement{0x31bc3c5d62a4, 0x7d9fe0f4c081e, 0x43ed51467f22c, 0x1e6cc0c1ed109, 0x5631deddae8f1}, XY2D: FieldElement{0x5460af1cad202, 0xb4919dd0655d, 0x7c4697d18c14c, 0x231c890bba2a4, 0x24ce0930542ca}}, NielsPoint{YPlusX: FieldElement{0x7a155fdf30b85, 0x1c6c6e5d487f9, 0x24be1134bdc5a, 0x1405970326f32, 0x549928a7324f4}, YMinusX: FieldElement{0x90f5fd06c106, 0x6abb1021e43fd, 0x232bcfad711a0, 0x3a5c13c047f37, 0x41d4e3c28a06d}, XY2D: FieldElement{0x632a763ee1a2e, 0x6fa4bffbd5e4d, 0x5fd35a6ba4792, 0x7b55e1de99de8, 0x491b66dec0dcf}}, NielsPoint{YPlusX: FieldElement{0x4a8ed0da64a1, 0x5ecfc45096ebe, 0x5edee93b488b2, 0x5b3c11a51bc8f, 0x4cf6b8b0b7018}, YMinusX: FieldElement{0x5b13dc7ea32a7, 0x18fc2db73131e, 0x7e3651f8f57e3, 0x25656055fa965, 0x8f338d0c85ee}, XY2D: FieldElement{0x3a821991a73bd, 0x3be6418f5870, 0x1ddc18eac9ef0, 0x54ce09e998dc2, 0x530d4a82eb078}}, NielsPoint{YPlusX: FieldElement{0x173456c9abf9e, 0x7892015100dad, 0x33ee14095fecb, 0x6ad95d67a0964, 0xdb3e7e00cbfb}, YMinusX: FieldElement{0x43630e1f94825, 0x4d1956a6b4009, 0x213fe2df8b5e0, 0x5ce3a41191e6, 0x65ea753f10177}, XY2D: FieldElement{0x6fc3ee2096363, 0x7ec36b96d67ac, 0x510ec6a0758b1, 0xed87df022109, 0x2a4ec1921e1a}}, NielsPoint{YPlusX: FieldElement{0x6162f1cf795f, 0x324ddcafe5eb9, 0x18d5e0463218, 0x7e78b9092428e, 0x36d12b5dec067}, YMinusX: FieldElement{0x6259a3b24b8a2, 0x188b5f4170b9c, 0x681c0dee15deb, 0x4dfe665f37445, 0x3d143c5112780}, XY2D: FieldElement{0x5279179154557, 0x39f8f0741424d, 0x45e6eb357923d, 0x42c9b5edb746f, 0x2ef517885ba82}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x6bffb305b2f51, 0x5b112b2d712dd, 0x35774974fe4e2, 0x4af87a96e3a3, 0x57968290bb3a0}, YMinusX: FieldElement{0x7974e8c58aedc, 0x7757e083488c6, 0x601c62ae7bc8b, 0x45370c2ecab74, 0x2f1b78fab143a}, XY2D: FieldElement{0x2b8430a20e101, 0x1a49e1d88fee3, 0x38bbb47ce4d96, 0x1f0e7ba84d437, 0x7dc43e35dc2aa}}, NielsPoint{YPlusX: FieldElement{0x2a5c273e9718, 0x32bc9dfb28b4f, 0x48df4f8d5db1a, 0x54c87976c028f, 0x44fb81d82d50}, YMinusX: FieldElement{0x66665887dd9c3, 0x629760a6ab0b2, 0x481e6c7243e6c, 0x97e37046fc77, 0x7ef72016758cc}, XY2D: FieldElement{0x718c5a907e3d9, 0x3b9c98c6b383b, 0x6ed255eccdc, 0x6976538229a59, 0x7f79823f9c30d}}, NielsPoint{YPlusX: FieldElement{0x41ff068f587ba, 0x1c00a191bcd53, 0x7b56f9c209e25, 0x3781e5fccaabe, 0x64a9b0431c06d}, YMinusX: FieldElement{0x4d239a3b513e8, 0x29723f51b1066, 0x642f4cf04d9c3, 0x4da095aa09b7a, 0xa4e0373d784d}, XY2D: FieldElement{0x3d6a15b7d2919, 0x41aa75046a5d6, 0x691751ec2d3da, 0x23638ab6721c4, 0x71a7d0ace183}}, NielsPoint{YPlusX: FieldElement{0x4355220e14431, 0xe1362a283981, 0x2757cd8359654, 0x2e9cd7ab10d90, 0x7c69bcf761775}, YMinusX: FieldElement{0x72daac887ba0b, 0xb7f4ac5dda60, 0x3bdda2c0498a4, 0x74e67aa180160, 0x2c3bcc7146ea7}, XY2D: FieldElement{0xd7eb04e8295f, 0x4a5ea1e6fa0fe, 0x45e635c436c60, 0x28ef4a8d4d18b, 0x6f5a9a7322aca}}, NielsPoint{YPlusX: FieldElement{0x1d4eba3d944be, 0x100f15f3dce5, 0x61a700e367825, 0x5922292ab3d23, 0x2ab9680ee8d3}, YMinusX: FieldElement{0x1000c2f41c6c5, 0x219fdf737174, 0x314727f127de7, 0x7e5277d23b81e, 0x494e21a2e147a}, XY2D: FieldElement{0x48a85dde50d9a, 0x1c1f734493df4, 0x47bdb64866889, 0x59a7d048f8eec, 0x6b5d76cbea46b}}, NielsPoint{YPlusX: FieldElement{0x141171e782522, 0x6806d26da7c1f, 0x3f31d1bc79ab9, 0x9f20459f5168, 0x16fb869c03dd3}, YMinusX: FieldElement{0x7556cec0cd994, 0x5eb9a03b7510a, 0x50ad1dd91cb71, 0x1aa5780b48a47, 0xae333f685277}, XY2D: FieldElement{0x6199733b60962, 0x69b157c266511, 0x64740f893f1ca, 0x3aa408fbf684, 0x3f81e38b8f70d}}, NielsPoint{YPlusX: FieldElement{0x37f355f17c824, 0x7ae85334815b, 0x7e3abddd2e48f, 0x61eeabe1f45e5, 0xad3e2d34cded}, YMinusX: FieldElement{0x10fcc7ed9affe, 0x4248cb0e96ff2, 0x4311c115172e2, 0x4c9d41cbf6925, 0x50510fc104f50}, XY2D: FieldElement{0x40fc5336e249d, 0x3386639fb2de1, 0x7bbf871d17b78, 0x75f796b7e8004, 0x127c158bf0fa1}}, NielsPoint{YPlusX: FieldElement{0x28fc4ae51b974, 0x26e89bfd2dbd4, 0x4e122a07665cf, 0x7cab1203405c3, 0x4ed82479d167d}, YMinusX: FieldElement{0x17c422e9879a2, 0x28a5946c8fec3, 0x53ab32e912b77, 0x7b44da09fe0a5, 0x354ef87d07ef4}, XY2D: FieldElement{0x3b52260c5d975, 0x79d6836171fdc, 0x7d994f140d4bb, 0x1b6c404561854, 0x302d92d205392}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x46fb6e4e0f177, 0x53497ad5265b7, 0x1ebdba01386fc, 0x302f0cb36a3c, 0xedc5f5eb426d}, YMinusX: FieldElement{0x3c1a2bca4283d, 0x23430c7bb2f02, 0x1a3ea1bb58bc2, 0x7265763de5c61, 0x10e5d3b76f1ca}, XY2D: FieldElement{0x3bfd653da8e67, 0x584953ec82a8a, 0x55e288fa7707b, 0x5395fc3931d81, 0x45b46c51361cb}}, NielsPoint{YPlusX: FieldElement{0x54ddd8a7fe3e4, 0x2cecc41c619d3, 0x43a6562ac4d91, 0x4efa5aca7bdd9, 0x5c1c0aef32122}, YMinusX: FieldElement{0x2abf314f7fa1, 0x391d19e8a1528, 0x6a2fa13895fc7, 0x9d8eddeaa591, 0x2177bfa36dcb7}, XY2D: FieldElement{0x1bbcfa79db8f, 0x3d84beb3666e1, 0x20c921d812204, 0x2dd843d3b32ce, 0x4ae619387d8ab}}, NielsPoint{YPlusX: FieldElement{0x17e44985bfb83, 0x54e32c626cc22, 0x96412ff38118, 0x6b241d61a246a, 0x75685abe5ba43}, YMinusX: FieldElement{0x3f6aa5344a32e, 0x69683680f11bb, 0x4c3581f623aa, 0x701af5875cba5, 0x1a00d91b17bf3}, XY2D: FieldElement{0x60933eb61f2b2, 0x5193fe92a4dd2, 0x3d995a550f43e, 0x3556fb93a883d, 0x135529b623b0e}}, NielsPoint{YPlusX: FieldElement{0x716bce22e83fe, 0x33d0130b83eb8, 0x952abad0afac, 0x309f64ed31b8a, 0x5972ea051590a}, YMinusX: FieldElement{0xdbd7add1d518, 0x119f823e2231e, 0x451d66e5e7de2, 0x500c39970f838, 0x79b5b81a65ca3}, XY2D: FieldElement{0x4ac20dc8f7811, 0x29589a9f501fa, 0x4d810d26a6b4a, 0x5ede00d96b259, 0x4f7e9c95905f3}}, NielsPoint{YPlusX: FieldElement{0x443d355299fe, 0x39b7d7d5aee39, 0x692519a2f34ec, 0x6e4404924cf78, 0x1942eec4a144a}, YMinusX: FieldElement{0x74bbc5781302e, 0x73135bb81ec4c, 0x7ef671b61483c, 0x7264614ccd729, 0x31993ad92e638}, XY2D: FieldElement{0x45319ae234992, 0x2219d47d24fb5, 0x4f04488b06cf6, 0x53aaa9e724a12, 0x2a0a65314ef9c}}, NielsPoint{YPlusX: FieldElement{0x61acd3c1c793a, 0x58b46b78779e6, 0x3369aacbe7af2, 0x509b0743074d4, 0x55dc39b6dea1}, YMinusX: FieldElement{0x7937ff7f927c2, 0xc2fa14c6a5b6, 0x556bddb6dd07c, 0x6f6acc179d108, 0x4cf6e218647c2}, XY2D: FieldElement{0x1227cc28d5bb6, 0x78ee9bff57623, 0x28cb2241f893a, 0x25b541e3c6772, 0x121a307710aa2}}, NielsPoint{YPlusX: FieldElement{0x1713ec77483c9, 0x6f70572d5facb, 0x25ef34e22ff81, 0x54d944f141188, 0x527bb94a6ced3}, YMinusX: FieldElement{0x35d5e9f034a97, 0x126069785bc9b, 0x5474ec7854ff0, 0x296a302a348ca, 0x333fc76c7a40e}, XY2D: FieldElement{0x5992a995b482e, 0x78dc707002ac7, 0x5936394d01741, 0x4fba4281aef17, 0x6b89069b20a7a}}, NielsPoint{YPlusX: FieldElement{0x2fa8cb5c7db77, 0x718e6982aa810, 0x39e95f81a1a1b, 0x5e794f3646cfb, 0x473d308a7639}, YMinusX: FieldElement{0x2a0416270220d, 0x75f248b69d025, 0x1cbbc16656a27, 0x5b9ffd6e26728, 0x23bc2103aa73e}, XY2D: FieldElement{0x6792603589e05, 0x248db9892595d, 0x6a53cad2d08, 0x20d0150f7ba73, 0x102f73bfde043}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x4dae0b5511c9a, 0x5257fffe0d456, 0x54108d1eb2180, 0x96cc0f9baefa, 0x3f6bd725da4ea}, YMinusX: FieldElement{0xb9ab7f5745c6, 0x5caf0f8d21d63, 0x7debea408ea2b, 0x9edb93896d16, 0x36597d25ea5c0}, XY2D: FieldElement{0x58d7b106058ac, 0x3cdf8d20bee69, 0xa4cb765015e, 0x36832337c7cc9, 0x7b7ecc19da60d}}, NielsPoint{YPlusX: FieldElement{0x64a51a77cfa9b, 0x29cf470ca0db5, 0x4b60b6e0898d9, 0x55d04ddffe6c7, 0x3bedc661bf5c}, YMinusX: FieldElement{0x2373c695c690d, 0x4c0c8520dcf18, 0x384af4b7494b9, 0x4ab4a8ea22225, 0x4235ad7601743}, XY2D: FieldElement{0xcb0d078975f5, 0x292313e530c4b, 0x38dbb9124a509, 0x350d0655a11f1, 0xe7ce2b0cdf06}}, NielsPoint{YPlusX: FieldElement{0x6fedfd94b70f9, 0x2383f9745bfd4, 0x4beae27c4c301, 0x75aa4416a3f3f, 0x615256138aece}, YMinusX: FieldElement{0x4643ac48c85a3, 0x6878c2735b892, 0x3a53523f4d877, 0x3a504ed8bee9d, 0x666e0a5d8fb46}, XY2D: FieldElement{0x3f64e4870cb0d, 0x61548b16d6557, 0x7a261773596f3, 0x7724d5f275d3a, 0x7f0bc810d514d}}, NielsPoint{YPlusX: FieldElement{0x49dad737213a0, 0x745dee5d31075, 0x7b1a55e7fdbe2, 0x5ba988f176ea1, 0x1d3a907ddec5a}, YMinusX: FieldElement{0x6ba426f4136f, 0x3cafc0606b720, 0x518f0a2359cda, 0x5fae5e46feca7, 0xd1f8dbcf8eed}, XY2D: FieldElement{0x693313ed081dc, 0x5b0a366901742, 0x40c872ca4ca7e, 0x6f18094009e01, 0x11b44a31bf}}, NielsPoint{YPlusX: FieldElement{0x61f696a0aa75c, 0x38b0a57ad42ca, 0x1e59ab706fdc9, 0x1308d46ebfcd, 0x63d988a2d2851}, YMinusX: FieldElement{0x7a06c3fc66c0c, 0x1c9bac1ba47fb, 0x23935c575038e, 0x3f0bd71c59c13, 0x3ac48d916e835}, XY2D: FieldElement{0x20753afbd232e, 0x71fbb1ed06002, 0x39cae47a4af3a, 0x337c0b34d9c2, 0x33fad52b2368a}}, NielsPoint{YPlusX: FieldElement{0x4c8d0c422cfe8, 0x760b4275971a5, 0x3da95bc1cad3d, 0xf151ff5b7376, 0x3cc355ccb90a7}, YMinusX: FieldElement{0x649c6c5e41e16, 0x60667eee6aa80, 0x4179d182be190, 0x653d9567e6979, 0x16c0f429a256d}, XY2D: FieldElement{0x69443903e9131, 0x16f4ac6f9dd36, 0x2ea4912e29253, 0x2b4643e68d25d, 0x631eaf426bae7}}, NielsPoint{YPlusX: FieldElement{0x175b9a3700de8, 0x77c5f00aa48fb, 0x3917785ca0317, 0x5aa9b2c79399, 0x431f2c7f665f8}, YMinusX: FieldElement{0x10410da66fe9f, 0x24d82dcb4d67d, 0x3e6fe0e17752d, 0x4dade1ecbb08f, 0x5599648b1ea91}, XY2D: FieldElement{0x26344858f7b19, 0x5f43d4a295ac0, 0x242a75c52acd4, 0x5934480220d10, 0x7b04715f91253}}, NielsPoint{YPlusX: FieldElement{0x6c280c4e6bac6, 0x3ada3b361766e, 0x42fe5125c3b4f, 0x111d84d4aac22, 0x48d0acfa57cde}, YMinusX: FieldElement{0x5bd28acf6ae43, 0x16fab8f56907d, 0x7acb11218d5f2, 0x41fe02023b4db, 0x59b37bf5c2f65}, XY2D: FieldElement{0x726e47dabe671, 0x2ec45e746f6c1, 0x6580e53c74686, 0x5eda104673f74, 0x16234191336d3}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x19cd61ff38640, 0x60c6c4b41ba9, 0x75cf70ca7366f, 0x118a8f16c011e, 0x4a25707a203b9}, YMinusX: FieldElement{0x499def6267ff6, 0x76e858108773c, 0x693cac5ddcb29, 0x311d00a9ff4, 0x2cdfdfecd5d05}, XY2D: FieldElement{0x7668a53f6ed6a, 0x303ba2e142556, 0x3880584c10909, 0x4fe20000a261d, 0x5721896d248e4}}, NielsPoint{YPlusX: FieldElement{0x55091a1d0da4e, 0x4f6bfc7c1050b, 0x64e4ecd2ea9be, 0x7eb1f28bbe70, 0x3c935afc4b03}, YMinusX: FieldElement{0x65517fd181bae, 0x3e5772c76816d, 0x19189640898a, 0x1ed2a84de7499, 0x578edd74f63c1}, XY2D: FieldElement{0x276c6492b0c3d, 0x9bfc40bf932e, 0x588e8f11f330b, 0x3d16e694dc26e, 0x3ec2ab590288c}}, NielsPoint{YPlusX: FieldElement{0x13a09ae32d1cb, 0x3e81eb85ab4e4, 0x7aaca43cae1f, 0x62f05d7526374, 0xe1bf66c6adba}, YMinusX: FieldElement{0xd27be4d87bb9, 0x56c27235db434, 0x72e6e0ea62d37, 0x5674cd06ee839, 0x2dd5c25a200fc}, XY2D: FieldElement{0x3d5e9792c887e, 0x319724dabbc55, 0x2b97c78680800, 0x7afdfdd34e6dd, 0x730548b35ae88}}, NielsPoint{YPlusX: FieldElement{0x3094ba1d6e334, 0x6e126a7e3300b, 0x89c0aefcfbc5, 0x2eea11f836583, 0x585a2277d8784}, YMinusX: FieldElement{0x551a3cba8b8ee, 0x3b6422be2d886, 0x630e1419689bc, 0x4653b07a7a955, 0x3043443b411db}, XY2D: FieldElement{0x25f8233d48962, 0x6bd8f04aff431, 0x4f907fd9a6312, 0x40fd3c737d29b, 0x7656278950ef9}}, NielsPoint{YPlusX: FieldElement{0x73a3ea86cf9d, 0x6e0e2abfb9c2e, 0x60e2a38ea33ee, 0x30b2429f3fe18, 0x28bbf484b613f}, YMinusX: FieldElement{0x3cf59d51fc8c0, 0x7a0a0d6de4718, 0x55c3a3e6fb74b, 0x353135f884fd5, 0x3f4160a8c1b84}, XY2D: FieldElement{0x12f5c6f136c7c, 0xfedba237de4c, 0x779bccebfab44, 0x3aea93f4d6909, 0x1e79cb358188f}}, NielsPoint{YPlusX: FieldElement{0x153d8f5e08181, 0x8533bbdb2efd, 0x1149796129431, 0x17a6e36168643, 0x478ab52d39d1f}, YMinusX: FieldElement{0x436c3eef7e3f1, 0x7ffd3c21f0026, 0x3e77bf20a2da9, 0x418bffc8472de, 0x65d7951b3a3b3}, XY2D: FieldElement{0x6a4d39252d159, 0x790e35900ecd4, 0x30725bf977786, 0x10a5c1635a053, 0x16d87a411a212}}, NielsPoint{YPlusX: FieldElement{0x4d5e2d54e0583, 0x2e5d7b33f5f74, 0x3a5de3f887ebf, 0x6ef24bd6139b7, 0x1f990b577a5a6}, YMinusX: FieldElement{0x57e5a42066215, 0x1a18b44983677, 0x3e652de1e6f8f, 0x6532be02ed8eb, 0x28f87c8165f38}, XY2D: FieldElement{0x44ead1be8f7d6, 0x5759d4f31f466, 0x378149f47943, 0x69f3be32b4f29, 0x45882fe1534d6}}, NielsPoint{YPlusX: FieldElement{0x49929943c6fe4, 0x4347072545b15, 0x3226bced7e7c5, 0x3a134ced89df, 0x7dcf843ce405f}, YMinusX: FieldElement{0x1345d757983d6, 0x222f54234cccd, 0x1784a3d8adbb4, 0x36ebeee8c2bcc, 0x688fe5b8f626f}, XY2D: FieldElement{0xd6484a4732c0, 0x7b94ac6532d92, 0x5771b8754850f, 0x48dd9df1461c8, 0x6739687e73271}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x5cc9dc80c1ac0, 0x683671486d4cd, 0x76f5f1a5e8173, 0x6d5d3f5f9df4a, 0x7da0b8f68d7e7}, YMinusX: FieldElement{0x2014385675a6, 0x6155fb53d1def, 0x37ea32e89927c, 0x59a668f5a82e, 0x46115aba1d4dc}, XY2D: FieldElement{0x71953c3b5da76, 0x6642233d37a81, 0x2c9658076b1bd, 0x5a581e63010ff, 0x5a5f887e83674}}, NielsPoint{YPlusX: FieldElement{0x628d3a0a643b9, 0x1cd8640c93d2, 0xb7b0cad70f2c, 0x3864da98144be, 0x43e37ae2d5d1c}, YMinusX: FieldElement{0x301cf70a13d11, 0x2a6a1ba1891ec, 0x2f291fb3f3ae0, 0x21a7b814bea52, 0x3669b656e44d1}, XY2D: FieldElement{0x63f06eda6e133, 0x233342758070f, 0x98e0459cc075, 0x4df5ead6c7c1b, 0x6a21e6cd4fd5e}}, NielsPoint{YPlusX: FieldElement{0x129126699b2e3, 0xee11a2603de8, 0x60ac2f5c74c21, 0x59b192a196808, 0x45371b07001e8}, YMinusX: FieldElement{0x6170a3046e65f, 0x5401a46a49e38, 0x20add5561c4a8, 0x7abb4edde9e46, 0x586bf9f1a195f}, XY2D: FieldElement{0x3088d5ef8790b, 0x38c2126fcb4db, 0x685bae149e3c3, 0xbcd601a4e930, 0xeafb03790e52}}, NielsPoint{YPlusX: FieldElement{0x805e0f75ae1d, 0x464cc59860a28, 0x248e5b7b00bef, 0x5d99675ef8f75, 0x44ae3344c5435}, YMinusX: FieldElement{0x555c13748042f, 0x4d041754232c0, 0x521b430866907, 0x3308e40fb9c39, 0x309acc675a02c}, XY2D: FieldElement{0x289b9bba543ee, 0x3ab592e28539e, 0x64d82abcdd83a, 0x3c78ec172e327, 0x62d5221b7f946}}, NielsPoint{YPlusX: FieldElement{0x5d4263af77a3c, 0x23fdd2289aeb0, 0x7dc64f77eb9ec, 0x1bd28338402c, 0x14f29a5383922}, YMinusX: FieldElement{0x4299c18d0936d, 0x5914183418a49, 0x52a18c721aed5, 0x2b151ba82976d, 0x5c0efde4bc754}, XY2D: FieldElement{0x17edc25b2d7f5, 0x37336a6081bee, 0x7b5318887e5c3, 0x49f6d491a5be1, 0x5e72365c7bee0}}, NielsPoint{YPlusX: FieldElement{0x339062f08b33e, 0x4bbf3e657cfb2, 0x67af7f56e5967, 0x4dbd67f9ed68f, 0x70b20555cb734}, YMinusX: FieldElement{0x3fc074571217f, 0x3a0d29b2b6aeb, 0x6478ccdde59d, 0x55e4d051bddfa, 0x77f1104c47b4e}, XY2D: FieldElement{0x113c555112c4c, 0x7535103f9b7ca, 0x140ed1d9a2108, 0x2522333bc2af, 0xe34398f4a064}}, NielsPoint{YPlusX: FieldElement{0x30b093e4b1928, 0x1ce7e7ec80312, 0x4e575bdf78f84, 0x61f7a190bed39, 0x6f8aded6ca379}, YMinusX: FieldElement{0x522d93ecebde8, 0x24f045e0f6cf, 0x16db63426cfa1, 0x1b93a1fd30fd8, 0x5e5405368a362}, XY2D: FieldElement{0x123dfdb7b29a, 0x4344356523c68, 0x79a527921ee5f, 0x74bfccb3e817e, 0x780de72ec8d3d}}, NielsPoint{YPlusX: FieldElement{0x7eaf300f42772, 0x5455188354ce3, 0x4dcca4a3dcbac, 0x3d314d0bfebcb, 0x1defc6ad32b58}, YMinusX: FieldElement{0x28545089ae7bc, 0x1e38fe9a0c15c, 0x12046e0e2377b, 0x6721c560aa885, 0xeb28bf671928}, XY2D: FieldElement{0x3be1aef5195a7, 0x6f22f62bdb5eb, 0x39768b8523049, 0x43394c8fbfdbd, 0x467d201bf8dd2}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x6f4bd567ae7a9, 0x65ac89317b783, 0x7d3b20fd8932, 0xf208326916, 0x2ef9c5a5ba384}, YMinusX: FieldElement{0x6919a74ef4fad, 0x59ed4611452bf, 0x691ec04ea09ef, 0x3cbcb2700e984, 0x71c43c4f5ba3c}, XY2D: FieldElement{0x56df6fa9e74cd, 0x79c95e4cf56df, 0x7be643bc609e2, 0x149c12ad9e878, 0x5a758ca390c5f}}, NielsPoint{YPlusX: FieldElement{0x918b1d61dc94, 0xd350260cd19c, 0x7a2ab4e37b4d9, 0x21fea735414d7, 0xa738027f639d}, YMinusX: FieldElement{0x72710d9462495, 0x25aafaa007456, 0x2d21f28eaa31b, 0x17671ea005fd0, 0x2dbae244b3eb7}, XY2D: FieldElement{0x74a2f57ffe1cc, 0x1bc3073087301, 0x7ec57f4019c34, 0x34e082e1fa524, 0x2698ca635126a}}, NielsPoint{YPlusX: FieldElement{0x5702f5e3dd90e, 0x31c9a4a70c5c7, 0x136a5aa78fc24, 0x1992f3b9f7b01, 0x3c004b0c4afa3}, YMinusX: FieldElement{0x5318832b0ba78, 0x6f24b9ff17cec, 0xa47f30e060c7, 0x58384540dc8d0, 0x1fb43dcc49cae}, XY2D: FieldElement{0x146ac06f4b82b, 0x4b500d89e7355, 0x3351e1c728a12, 0x10b9f69932fe3, 0x6b43fd01cd1fd}}, NielsPoint{YPlusX: FieldElement{0x742583e760ef3, 0x73dc1573216b8, 0x4ae48fdd7714a, 0x4f85f8a13e103, 0x73420b2d6ff0d}, YMinusX: FieldElement{0x75d4b4697c544, 0x11be1fff7f8f4, 0x119e16857f7e1, 0x38a14345cf5d5, 0x5a68d7105b52f}, XY2D: FieldElement{0x4f6cb9e851e06, 0x278c4471895e5, 0x7efcdce3d64e4, 0x64f6d455c4b4c, 0x3db5632fea34b}}, NielsPoint{YPlusX: FieldElement{0x190b1829825d5, 0xe7d3513225c9, 0x1c12be3b7abae, 0x58777781e9ca6, 0x59197ea495df2}, YMinusX: FieldElement{0x6ee2bf75dd9d8, 0x6c72ceb34be8d, 0x679c9cc345ec7, 0x7898df96898a4, 0x4321adf49d75}, XY2D: FieldElement{0x16019e4e55aae, 0x74fc5f25d209c, 0x4566a939ded0d, 0x66063e716e0b7, 0x45eafdc1f4d70}}, NielsPoint{YPlusX: FieldElement{0x64624cfccb1ed, 0x257ab8072b6c1, 0x120725676f0a, 0x4a018d04e8eee, 0x3f73ceea5d56d}, YMinusX: FieldElement{0x401858045d72b, 0x459e5e0ca2d30, 0x488b719308bea, 0x56f4a0d1b32b5, 0x5a5eebc80362d}, XY2D: FieldElement{0x7bfd10a4e8dc6, 0x7c899366736f4, 0x55ebbeaf95c01, 0x46db060903f8a, 0x2605889126621}}, NielsPoint{YPlusX: FieldElement{0x18e3cc676e542, 0x26079d995a990, 0x4a7c217908b2, 0x1dc7603e6655a, 0xdedfa10b2444}, YMinusX: FieldElement{0x704a68360ff04, 0x3cecc3cde8b3e, 0x21cd5470f64ff, 0x6abc18d953989, 0x54ad0c2e4e615}, XY2D: FieldElement{0x367d5b82b522a, 0xd3f4b83d7dc7, 0x3067f4cdbc58d, 0x20452da697937, 0x62ecb2baa77a9}}, NielsPoint{YPlusX: FieldElement{0x72836afb62874, 0xaf3c2094b240, 0xc285297f357a, 0x7cc2d5680d6e3, 0x61913d5075663}, YMinusX: FieldElement{0x5795261152b3d, 0x7a1dbbafa3cbd, 0x5ad31c52588d5, 0x45f3a4164685c, 0x2e59f919a966d}, XY2D: FieldElement{0x62d361a3231da, 0x65284004e01b8, 0x656533be91d60, 0x6ae016c00a89f, 0x3ddbc2a131c05}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x257a22796bb14, 0x6f360fb443e75, 0x680e47220eaea, 0x2fcf2a5f10c18, 0x5ee7fb38d8320}, YMinusX: FieldElement{0x40ff9ce5ec54b, 0x57185e261b35b, 0x3e254540e70a9, 0x1b5814003e3f8, 0x78968314ac04b}, XY2D: FieldElement{0x5fdcb41446a8e, 0x5286926ff2a71, 0xf231e296b3f6, 0x684a357c84693, 0x61d0633c9bca0}}, NielsPoint{YPlusX: FieldElement{0x328bcf8fc73df, 0x3b4de06ff95b4, 0x30aa427ba11a5, 0x5ee31bfda6d9c, 0x5b23ac2df8067}, YMinusX: FieldElement{0x44935ffdb2566, 0x12f016d176c6e, 0x4fbb00f16f5ae, 0x3fab78d99402a, 0x6e965fd847aed}, XY2D: FieldElement{0x2b953ee80527b, 0x55f5bcdb1b35a, 0x43a0b3fa23c66, 0x76e07388b820a, 0x79b9bbb9dd95d}}, NielsPoint{YPlusX: FieldElement{0x17dae8e9f7374, 0x719f76102da33, 0x5117c2a80ca8b, 0x41a66b65d0936, 0x1ba811460accb}, YMinusX: FieldElement{0x355406a3126c2, 0x50d1918727d76, 0x6e5ea0b498e0e, 0xa3b6063214f2, 0x5065f158c9fd2}, XY2D: FieldElement{0x169fb0c429954, 0x59aedd9ecee10, 0x39916eb851802, 0x57917555cc538, 0x3981f39e58a4f}}, NielsPoint{YPlusX: FieldElement{0x5dfa56de66fde, 0x58809075908, 0x6d3d8cb854a94, 0x5b2f4e970b1e3, 0x30f4452edcbc1}, YMinusX: FieldElement{0x38a7559230a93, 0x52c1cde8ba31f, 0x2a4f2d4745a3d, 0x7e9d42d4a28a, 0x38dc083705acd}, XY2D: FieldElement{0x52782c5759740, 0x53f3397d990ad, 0x3a939c7e84d15, 0x234c4227e39e0, 0x632d9a1a593f2}}, NielsPoint{YPlusX: FieldElement{0x1fd11ed0c84a7, 0x21b3ed2757e1, 0x73e1de58fc1c6, 0x5d110c84616ab, 0x3a5a7df28af64}, YMinusX: FieldElement{0x36b15b807cba6, 0x3f78a9e1afed7, 0xa59c2c608f1f, 0x52bdd8ecb81b7, 0xb24f48847ed4}, XY2D: FieldElement{0x2d4be511beac7, 0x6bda4d99e5b9b, 0x17e6996914e01, 0x7b1f0ce7fcf80, 0x34fcf74475481}}, NielsPoint{YPlusX: FieldElement{0x31dab78cfaa98, 0x4e3216e5e54b7, 0x249823973b689, 0x2584984e48885, 0x119a3042fb37}, YMinusX: FieldElement{0x7e04c789767ca, 0x1671b28cfb832, 0x7e57ea2e1c537, 0x1fbaaef444141, 0x3d3bdc164dfa6}, XY2D: FieldElement{0x2d89ce8c2177d, 0x6cd12ba182cf4, 0x20a8ac19a7697, 0x539fab2cc72d9, 0x56c088f1ede20}}, NielsPoint{YPlusX: FieldElement{0x35fac24f38f02, 0x7d75c6197ab03, 0x33e4bc2a42fa7, 0x1c7cd10b48145, 0x38b7ea483590}, YMinusX: FieldElement{0x53d1110a86e17, 0x6416eb65f466d, 0x41ca6235fce20, 0x5c3fc8a99bb12, 0x9674c6b99108}, XY2D: FieldElement{0x6f82199316ff8, 0x5d54f1a9f3e9, 0x3bcc5d0bd274a, 0x5b284b8d2d5ad, 0x6e5e31025969e}}, NielsPoint{YPlusX: FieldElement{0x4fb0e63066222, 0x130f59747e660, 0x41868fecd41a, 0x3105e8c923bc6, 0x3058ad43d1838}, YMinusX: FieldElement{0x462f587e593fb, 0x3d94ba7ce362d, 0x330f9b52667b7, 0x5d45a48e0f00a, 0x8f5114789a8d}, XY2D: FieldElement{0x40ffde57663d0, 0x71445d4c20647, 0x2653e68170f7c, 0x64cdee3c55ed6, 0x26549fa4efe3d}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x68549af3f666e, 0x9e2941d4bb68, 0x2e8311f5dff3c, 0x6429ef91ffbd2, 0x3a10dfe132ce3}, YMinusX: FieldElement{0x55a461e6bf9d6, 0x78eeef4b02e83, 0x1d34f648c16cf, 0x7fea2aba5132, 0x1926e1dc6401e}, XY2D: FieldElement{0x74e8aea17cea0, 0xc743f83fbc0f, 0x7cb03c4bf5455, 0x68a8ba9917e98, 0x1fa1d01d861e5}}, NielsPoint{YPlusX: FieldElement{0x4ac00d1df94ab, 0x3ba2101bd271b, 0x7578988b9c4af, 0xf2bf89f49f7e, 0x73fced18ee9a0}, YMinusX: FieldElement{0x55947d599832, 0x346fe2aa41990, 0x164c8079195b, 0x799ccfb7bba27, 0x773563bc6a75c}, XY2D: FieldElement{0x1e90863139cb3, 0x4f8b407d9a0d6, 0x58e24ca924f69, 0x7a246bbe76456, 0x1f426b701b864}}, NielsPoint{YPlusX: FieldElement{0x635c891a12552, 0x26aebd38ede2f, 0x66dc8faddae05, 0x21c7d41a03786, 0xb76bb1b3fa7e}, YMinusX: FieldElement{0x1264c41911c01, 0x702f44584bdf9, 0x43c511fc68ede, 0x482c3aed35f9, 0x4e1af5271d31b}, XY2D: FieldElement{0xc1f97f92939b, 0x17a88956dc117, 0x6ee005ef99dc7, 0x4aa9172b231cc, 0x7b6dd61eb772a}}, NielsPoint{YPlusX: FieldElement{0xabf9ab01d2c7, 0x3880287630ae6, 0x32eca045beddb, 0x57f43365f32d0, 0x53fa9b659bff6}, YMinusX: FieldElement{0x5c1e850f33d92, 0x1ec119ab9f6f5, 0x7f16f6de663e9, 0x7a7d6cb16dec6, 0x703e9bceaf1d2}, XY2D: FieldElement{0x4c8e994885455, 0x4ccb5da9cad82, 0x3596bc610e975, 0x7a80c0ddb9f5e, 0x398d93e5c4c61}}, NielsPoint{YPlusX: FieldElement{0x77c60d2e7e3f2, 0x4061051763870, 0x67bc4e0ecd2aa, 0x2bb941f1373b9, 0x699c9c9002c30}, YMinusX: FieldElement{0x3d16733e248f3, 0xe2b7e14be389, 0x42c0ddaf6784a, 0x589ea1fc67850, 0x53b09b5ddf191}, XY2D: FieldElement{0x6a7235946f1cc, 0x6b99cbb2fbe60, 0x6d3a5d6485c62, 0x4839466e923c0, 0x51caf30c6fcdd}}, NielsPoint{YPlusX: FieldElement{0x2f99a18ac54c7, 0x398a39661ee6f, 0x384331e40cde3, 0x4cd15c4de19a6, 0x12ae29c189f8e}, YMinusX: FieldElement{0x3a7427674e00a, 0x6142f4f7e74c1, 0x4cc93318c3a15, 0x6d51bac2b1ee7, 0x5504aa292383f}, XY2D: FieldElement{0x6c0cb1f0d01cf, 0x187469ef5d533, 0x27138883747bf, 0x2f52ae53a90e8, 0x5fd14fe958eba}}, NielsPoint{YPlusX: FieldElement{0x2fe5ebf93cb8e, 0x226da8acbe788, 0x10883a2fb7ea1, 0x94707842cf44, 0x7dd73f960725d}, YMinusX: FieldElement{0x42ddf2845ab2c, 0x6214ffd3276bb, 0xb8d181a5246, 0x268a6d579eb20, 0x93ff26e58647}, XY2D: FieldElement{0x524fe68059829, 0x65b75e47cb621, 0x15eb0a5d5cc19, 0x5209b3929d5a, 0x2f59bcbc86b47}}, NielsPoint{YPlusX: FieldElement{0x1d560b691c301, 0x7f5bafce3ce08, 0x4cd561614806c, 0x4588b6170b188, 0x2aa55e3d01082}, YMinusX: FieldElement{0x47d429917135f, 0x3eacfa07af070, 0x1deab46b46e44, 0x7a53f3ba46cdf, 0x5458b42e2e51a}, XY2D: FieldElement{0x192e60c07444f, 0x5ae8843a21daa, 0x6d721910b1538, 0x3321a95a6417e, 0x13e9004a8a768}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x600c9193b877f, 0x21c1b8a0d7765, 0x379927fb38ea2, 0x70d7679dbe01b, 0x5f46040898de9}, YMinusX: FieldElement{0x58845832fcedb, 0x135cd7f0c6e73, 0x53ffbdfe8e35b, 0x22f195e06e55b, 0x73937e8814bce}, XY2D: FieldElement{0x37116297bf48d, 0x45a9e0d069720, 0x25af71aa744ec, 0x41af0cb8aaba3, 0x2cf8a4e891d5e}}, NielsPoint{YPlusX: FieldElement{0x5487e17d06ba2, 0x3872a032d6596, 0x65e28c09348e0, 0x27b6bb2ce40c2, 0x7a6f7f2891d6a}, YMinusX: FieldElement{0x3fd8707110f67, 0x26f8716a92db2, 0x1cdaa1b753027, 0x504be58b52661, 0x2049bd6e58252}, XY2D: FieldElement{0x1fd8d6a9aef49, 0x7cb67b7216fa1, 0x67aff53c3b982, 0x20ea610da9628, 0x6011aadfc5459}}, NielsPoint{YPlusX: FieldElement{0x6d0c802cbf890, 0x141bfed554c7b, 0x6dbb667ef4263, 0x58f3126857edc, 0x69ce18b779340}, YMinusX: FieldElement{0x7926dcf95f83c, 0x42e25120e2bec, 0x63de96df1fa15, 0x4f06b50f3f9cc, 0x6fc5cc1b0b62f}, XY2D: FieldElement{0x75528b29879cb, 0x79a8fd2125a3d, 0x27c8d4b746ab8, 0xf8893f02210c, 0x15596b3ae5710}}, NielsPoint{YPlusX: FieldElement{0x731167e5124ca, 0x17b38e8bbe13f, 0x3d55b942f9056, 0x9c1495be913f, 0x3aa4e241afb6d}, YMinusX: FieldElement{0x739d23f9179a2, 0x632fadbb9e8c4, 0x7c8522bfe0c48, 0x6ed0983ef5aa9, 0xd2237687b5f4}, XY2D: FieldElement{0x138bf2a3305f5, 0x1f45d24d86598, 0x5274bad2160fe, 0x1b6041d58d12a, 0x32fcaa6e4687a}}, NielsPoint{YPlusX: FieldElement{0x7a4732787ccdf, 0x11e427c7f0640, 0x3659385f8c64, 0x5f4ead9766bfb, 0x746f6336c2600}, YMinusX: FieldElement{0x56e8dc57d9af5, 0x5b3be17be4f78, 0x3bf928cf82f4b, 0x52e55600a6f11, 0x4627e9cefebd6}, XY2D: FieldElement{0x2f345ab6c971c, 0x653286e63e7e9, 0x51061b78a23ad, 0x14999acb54501, 0x7b4917007ed66}}, NielsPoint{YPlusX: FieldElement{0x41b28dd53a2dd, 0x37be85f87ea86, 0x74be3d2a85e41, 0x1be87fac96ca6, 0x1d03620fe08cd}, YMinusX: FieldElement{0x5fb5cab84b064, 0x2513e778285b0, 0x457383125e043, 0x6bda3b56e223d, 0x122ba376f844f}, XY2D: FieldElement{0x232cda2b4e554, 0x422ba30ff840, 0x751e7667b43f5, 0x6261755da5f3e, 0x2c70bf52b68e}}, NielsPoint{YPlusX: FieldElement{0x532bf458d72e1, 0x40f96e796b59c, 0x22ef79d6f9da3, 0x501ab67beca77, 0x6b0697e3feb43}, YMinusX: FieldElement{0x7ec4b5d0b2fbb, 0x200e910595450, 0x742057105715e, 0x2f07022530f60, 0x26334f0a409ef}, XY2D: FieldElement{0xf04adf62a3c0, 0x5e0edb48bb6d9, 0x7c34aa4fbc003, 0x7d74e4e5cac24, 0x1cc37f43441b2}}, NielsPoint{YPlusX: FieldElement{0x656f1c9ceaeb9, 0x7031cacad5aec, 0x1308cd0716c57, 0x41c1373941942, 0x3a346f772f196}, YMinusX: FieldElement{0x7565a5cc7324f, 0x1ca0d5244a11, 0x116b067418713, 0xa57d8c55edae, 0x6c6809c103803}, XY2D: FieldElement{0x55112e2da6ac8, 0x6363d0a3dba5a, 0x319c98ba6f40c, 0x2e84b03a36ec7, 0x5911b9f6ef7c}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x1acf3512eeaef, 0x2639839692a69, 0x669a234830507, 0x68b920c0603d4, 0x555ef9d1c64b2}, YMinusX: FieldElement{0x39983f5df0ebb, 0x1ea2589959826, 0x6ce638703cdd6, 0x6311678898505, 0x6b3cecf9aa270}, XY2D: FieldElement{0x770ba3b73bd08, 0x11475f7e186d4, 0x251bc9892bbc, 0x24eab9bffcc5a, 0x675f4de133817}}, NielsPoint{YPlusX: FieldElement{0x7f6d93bdab31d, 0x1f3aca5bfd425, 0x2fa521c1c9760, 0x62180ce27f9cd, 0x60f450b882cd3}, YMinusX: FieldElement{0x452036b1782fc, 0x2d95b07681c5, 0x5901cf99205b2, 0x290686e5eecb4, 0x13d99df70164c}, XY2D: FieldElement{0x35ec321e5c0ca, 0x13ae337f44029, 0x4008e813f2da7, 0x640272f8e0c3a, 0x1c06de9e55eda}}, NielsPoint{YPlusX: FieldElement{0x52b40ff6d69aa, 0x31b8809377ffa, 0x536625cd14c2c, 0x516af252e17d1, 0x78096f8e7d32b}, YMinusX: FieldElement{0x77ad6a33ec4e2, 0x717c5dc11d321, 0x4a114559823e4, 0x306ce50a1e2b1, 0x4cf38a1fec2db}, XY2D: FieldElement{0x2aa650dfa5ce7, 0x54916a8f19415, 0xdc96fe71278, 0x55f2784e63eb8, 0x373cad3a26091}}, NielsPoint{YPlusX: FieldElement{0x6a8fb89ddbbad, 0x78c35d5d97e37, 0x66e3674ef2cb2, 0x34347ac53dd8f, 0x21547eda5112a}, YMinusX: FieldElement{0x4634d82c9f57c, 0x4249268a6d652, 0x6336d687f2ff7, 0x4fe4f4e26d9a0, 0x40f3d945441}, XY2D: FieldElement{0x5e939fd5986d3, 0x12a2147019bdf, 0x4c466e7d09cb2, 0x6fa5b95d203dd, 0x63550a334a254}}, NielsPoint{YPlusX: FieldElement{0x2584572547b49, 0x75c58811c1377, 0x4d3c637cc171b, 0x33d30747d34e3, 0x39a92bafaa7d7}, YMinusX: FieldElement{0x7d6edb569cf37, 0x60194a5dc2ca0, 0x5af59745e10a6, 0x7a8f53e004875, 0x3eea62c7daf78}, XY2D: FieldElement{0x4c713e693274e, 0x6ed1b7a6eb3a4, 0x62ace697d8e15, 0x266b8292ab075, 0x68436a0665c9c}}, NielsPoint{YPlusX: FieldElement{0x6d317e820107c, 0x90815d2ca3ca, 0x3ff1eb1499a1, 0x23960f050e319, 0x5373669c91611}, YMinusX: FieldElement{0x235e8202f3f27, 0x44c9f2eb61780, 0x630905b1d7003, 0x4fcc8d274ead1, 0x17b6e7f68ab78}, XY2D: FieldElement{0x14ab9a0e5257, 0x9939567f8ba5, 0x4b47b2a423c82, 0x688d7e57ac42d, 0x1cb4b5a678f87}}, NielsPoint{YPlusX: FieldElement{0x4aa62a2a007e7, 0x61e0e38f62d6e, 0x2f888fcc4782, 0x7562b83f21c00, 0x2dc0fd2d82ef6}, YMinusX: FieldElement{0x4c06b394afc6c, 0x4931b4bf636cc, 0x72b60d0322378, 0x25127c6818b25, 0x330bca78de743}, XY2D: FieldElement{0x6ff841119744e, 0x2c560e8e49305, 0x7254fefe5a57a, 0x67ae2c560a7df, 0x3c31be1b369f1}}, NielsPoint{YPlusX: FieldElement{0xbc93f9cb4272, 0x3f8f9db73182d, 0x2b235eabae1c4, 0x2ddbf8729551a, 0x41cec1097e7d5}, YMinusX: FieldElement{0x4864d08948aee, 0x5d237438df61e, 0x2b285601f7067, 0x25dbcbae6d753, 0x330b61134262d}, XY2D: FieldElement{0x619d7a26d808a, 0x3c3b3c2adbef2, 0x6877c9eec7f52, 0x3beb9ebe1b66d, 0x26b44cd91f287}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x7f29362730383, 0x7fd7951459c36, 0x7504c512d49e7, 0x87ed7e3bc55f, 0x7deb10149c726}, YMinusX: FieldElement{0x48478f387475, 0x69397d9678a3e, 0x67c8156c976f3, 0x2eb4d5589226c, 0x2c709e6c1c10a}, XY2D: FieldElement{0x2af6a8766ee7a, 0x8aaa79a1d96c, 0x42f92d59b2fb0, 0x1752c40009c07, 0x8e68e9ff62ce}}, NielsPoint{YPlusX: FieldElement{0x509d50ab8f2f9, 0x1b8ab247be5e5, 0x5d9b2e6b2e486, 0x4faa5479a1339, 0x4cb13bd738f71}, YMinusX: FieldElement{0x5500a4bc130ad, 0x127a17a938695, 0x2a26fa34e36d, 0x584d12e1ecc28, 0x2f1f3f87eeba3}, XY2D: FieldElement{0x48c75e515b64a, 0x75b6952071ef0, 0x5d46d42965406, 0x7746106989f9f, 0x19a1e353c0ae2}}, NielsPoint{YPlusX: FieldElement{0x172cdd596bdbd, 0x731ddf881684, 0x10426d64f8115, 0x71a4fd8a9a3da, 0x736bd3990266a}, YMinusX: FieldElement{0x47560bafa05c3, 0x418dcabcc2fa3, 0x35991cecf8682, 0x24371a94b8c60, 0x41546b11c20c3}, XY2D: FieldElement{0x32d509334b3b4, 0x16c102cae70aa, 0x1720dd51bf445, 0x5ae662faf9821, 0x412295a2b87fa}}, NielsPoint{YPlusX: FieldElement{0x55261e293eac6, 0x6426759b65cc, 0x40265ae116a48, 0x6c02304bae5bc, 0x760bb8d195ad}, YMinusX: FieldElement{0x19b88f57ed6e9, 0x4cdbf1904a339, 0x42b49cd4e4f2c, 0x71a2e771909d9, 0x14e153ebb52d2}, XY2D: FieldElement{0x61a17cde6818a, 0x53dad34108827, 0x32b32c55c55b6, 0x2f9165f9347a3, 0x6b34be9bc33ac}}, NielsPoint{YPlusX: FieldElement{0x469656571f2d3, 0xaa61ce6f423f, 0x3f940d71b27a1, 0x185f19d73d16a, 0x1b9c7b62e6dd}, YMinusX: FieldElement{0x72f643a78c0b2, 0x3de45c04f9e7b, 0x706d68d30fa5c, 0x696f63e8e2f24, 0x2012c18f0922d}, XY2D: FieldElement{0x355e55ac89d29, 0x3e8b414ec7101, 0x39db07c520c90, 0x6f41e9b77efe1, 0x8af5b784e4ba}}, NielsPoint{YPlusX: FieldElement{0x314d289cc2c4b, 0x23450e2f1bc4e, 0xcd93392f92f4, 0x1370c6a946b7d, 0x6423c1d5afd98}, YMinusX: FieldElement{0x499dc881f2533, 0x34ef26476c506, 0x4d107d2741497, 0x346c4bd6efdb3, 0x32b79d71163a1}, XY2D: FieldElement{0x5f8d9edfcb36a, 0x1e6e8dcbf3990, 0x7974f348af30a, 0x6e6724ef19c7c, 0x480a5efbc13e2}}, NielsPoint{YPlusX: FieldElement{0x14ce442ce221f, 0x18980a72516cc, 0x72f80db86677, 0x703331fda526e, 0x24b31d47691c8}, YMinusX: FieldElement{0x1e70b01622071, 0x1f163b5f8a16a, 0x56aaf341ad417, 0x7989635d830f7, 0x47aa27600cb7b}, XY2D: FieldElement{0x41eedc015f8c3, 0x7cf8d27ef854a, 0x289e3584693f9, 0x4a7857b309a7, 0x545b585d14dda}}, NielsPoint{YPlusX: FieldElement{0x4e4d0e3b321e1, 0x7451fe3d2ac40, 0x666f678eea98d, 0x38858667fead, 0x4d22dc3e64c8d}, YMinusX: FieldElement{0x7275ea0d43a0f, 0x681137dd7ccf7, 0x1e79cbab79a38, 0x22a214489a66a, 0xf62f9c332ba5}, XY2D: FieldElement{0x46589d63b5f39, 0x7eaf979ec3f96, 0x4ebe81572b9a8, 0x21b7f5d61694a, 0x1c0fa01a36371}}}, [8]NielsPoint{NielsPoint{YPlusX: FieldElement{0x2b0e8c936a50, 0x6b83b58b6cd21, 0x37ed8d3e72680, 0xa037db9f2a62, 0x4005419b1d2bc}, YMinusX: FieldElement{0x604b622943dff, 0x1c899f6741a58, 0x60219e2f232fb, 0x35fae92a7f9cb, 0xfa3614f3b1ca}, XY2D: FieldElement{0x3febdb9be82f0, 0x5e74895921400, 0x553ea38822706, 0x5a17c24cfc88c, 0x1fba218aef40a}}, NielsPoint{YPlusX: FieldElement{0x657043e7b0194, 0x5c11b55efe9e7, 0x7737bc6a074fb, 0xeae41ce355cc, 0x6c535d13ff776}, YMinusX: FieldElement{0x49448fac8f53e, 0x34f74c6e8356a, 0xad780607dba2, 0x7213a7eb63eb6, 0x392e3acaa8c86}, XY2D: FieldElement{0x534e93e8a35af, 0x8b10fd02c997, 0x26ac2acb81e05, 0x9d8c98ce3b79, 0x25e17fe4d50ac}}, NielsPoint{YPlusX: FieldElement{0x77ff576f121a7, 0x4e5f9b0fc722b, 0x46f949b0d28c8, 0x4cde65d17ef26, 0x6bba828f89698}, YMinusX: FieldElement{0x9bd71e04f676, 0x25ac841f2a145, 0x1a47eac823871, 0x1a8a8c36c581a, 0x255751442a9fb}, XY2D: FieldElement{0x1bc6690fe3901, 0x314132f5abc5a, 0x611835132d528, 0x5f24b8eb48a57, 0x559d504f7f6b7}}, NielsPoint{YPlusX: FieldElement{0x91e7f6d266fd, 0x36060ef037389, 0x18788ec1d1286, 0x287441c478eb0, 0x123ea6a3354bd}, YMinusX: FieldElement{0x38378b3eb54d5, 0x4d4aaa78f94ee, 0x4a002e875a74d, 0x10b851367b17c, 0x1ab12d5807e3}, XY2D: FieldElement{0x5189041e32d96, 0x5b062b090231, 0xc91766e7b78f, 0xaa0f55a138ec, 0x4a3961e2c918a}}, NielsPoint{YPlusX: FieldElement{0x7d644f3233f1e, 0x1c69f9e02c064, 0x36ae5e5266898, 0x8fc1dad38b79, 0x68aceead9bd41}, YMinusX: FieldElement{0x43be0f8e6bba0, 0x68fdffc614e3b, 0x4e91dab5b3be0, 0x3b1d4c9212ff0, 0x2cd6bce3fb1db}, XY2D: FieldElement{0x4c90ef3d7c210, 0x496f5a0818716, 0x79cf88cc239b8, 0x2cb9c306cf8db, 0x595760d5b508f}}, NielsPoint{YPlusX: FieldElement{0x2cbebfd022790, 0xb8822aec1105, 0x4d1cfd226bccc, 0x515b2fa4971be, 0x2cb2c5df54515}, YMinusX: FieldElement{0x1bfe104aa6397, 0x11494ff996c25, 0x64251623e5800, 0xd49fc5e044be, 0x709fa43edcb29}, XY2D: FieldElement{0x25d8c63fd2aca, 0x4c5cd29dffd61, 0x32ec0eb48af05, 0x18f9391f9b77c, 0x70f029ecf0c81}}, NielsPoint{YPlusX: FieldElement{0x2afaa5e10b0b9, 0x61de08355254d, 0xeb587de3c28d, 0x4f0bb9f7dbbd5, 0x44eca5a2a74bd}, YMinusX: FieldElement{0x307b32eed3e33, 0x6748ab03ce8c2, 0x57c0d9ab810bc, 0x42c64a224e98c, 0xb7d5d8a6c314}, XY2D: FieldElement{0x448327b95d543, 0x146681e3a4ba, 0x38714adc34e0c, 0x4f26f0e298e30, 0x272224512c7de}}, NielsPoint{YPlusX: FieldElement{0x3bb8a42a975fc, 0x6f2d5b46b17ef, 0x7b6a9223170e5, 0x53713fe3b7e6, 0x19735fd7f6bc2}, YMinusX: FieldElement{0x492af49c5342e, 0x2365cdf5a0357, 0x32138a7ffbb60, 0x2a1f7d14646fe, 0x11b5df18a44cc}, XY2D: FieldElement{0x390d042c84266, 0x1efe32a8fdc75, 0x6925ee7ae1238, 0x4af9281d0e832, 0xfef911191df8}}}} go-ristretto-1.2.3/edwards25519/table_test.go000066400000000000000000000076511440464505300207110ustar00rootroot00000000000000package edwards25519_test import ( "math/big" "testing" "github.com/bwesterb/go-ristretto/edwards25519" ) func TestAddExtendedNiels(t *testing.T) { var buf1, buf2 [32]byte var cp1, cp2, cp3 edwards25519.CompletedPoint var np2 edwards25519.NielsPoint var fe1, fe2 edwards25519.FieldElement var ep1, ep2, ep3a, ep3b edwards25519.ExtendedPoint for i := 0; i < 1000; i++ { rnd.Read(buf1[:]) rnd.Read(buf2[:]) fe1.SetBytes(&buf1) fe2.SetBytes(&buf2) cp1.SetRistrettoElligator2(&fe1) cp2.SetRistrettoElligator2(&fe2) ep1.SetCompleted(&cp1) ep2.SetCompleted(&cp2) ep3a.Add(&ep1, &ep2) np2.SetExtended(&ep2) cp3.AddExtendedNiels(&ep1, &np2) ep3b.SetCompleted(&cp3) if ep3a.RistrettoEqualsI(&ep3b) != 1 { t.Fatalf("%v + %v = %v != %v", ep1, ep2, ep3a, ep3b) } } } func TestSubExtendedNiels(t *testing.T) { var buf1, buf2 [32]byte var cp1, cp2, cp3 edwards25519.CompletedPoint var np2 edwards25519.NielsPoint var fe1, fe2 edwards25519.FieldElement var ep1, ep2, ep3a, ep3b edwards25519.ExtendedPoint for i := 0; i < 1000; i++ { rnd.Read(buf1[:]) rnd.Read(buf2[:]) fe1.SetBytes(&buf1) fe2.SetBytes(&buf2) cp1.SetRistrettoElligator2(&fe1) cp2.SetRistrettoElligator2(&fe2) ep1.SetCompleted(&cp1) ep2.SetCompleted(&cp2) ep3a.Sub(&ep1, &ep2) np2.SetExtended(&ep2) cp3.SubExtendedNiels(&ep1, &np2) ep3b.SetCompleted(&cp3) if ep3a.RistrettoEqualsI(&ep3b) != 1 { t.Fatalf("%v - %v = %v != %v", ep1, ep2, ep3a, ep3b) } } } func TestTableVarTimeBaseScalarMult(t *testing.T) { var table edwards25519.ScalarMultTable var B, p1, p2 edwards25519.ExtendedPoint B.SetBase() table.Compute(&B) var s [32]byte for i := 0; i < 1000; i++ { rnd.Read(s[:]) s[31] &= 31 table.ScalarMult(&p1, &s) table.VarTimeScalarMult(&p2, &s) if p1.RistrettoEqualsI(&p2) != 1 { t.Fatalf("[%v]B = %v != %v", s, p2, p1) } } } func TestTableBaseScalarMult(t *testing.T) { var table edwards25519.ScalarMultTable var B, p1, p2 edwards25519.ExtendedPoint B.SetBase() table.Compute(&B) var s [32]byte for i := 0; i < 1000; i++ { rnd.Read(s[:]) s[31] &= 31 table.ScalarMult(&p1, &s) p2.ScalarMult(&B, &s) if p1.RistrettoEqualsI(&p2) != 1 { t.Fatalf("[%v]B = %v != %v", s, p2, p1) } } } func TestBaseScalarMultTable(t *testing.T) { var table edwards25519.ScalarMultTable var B edwards25519.ExtendedPoint B.SetBase() table.Compute(&B) if edwards25519.BaseScalarMultTable != table { t.Fatalf("BaseScalarMultTable has incorrect values") } } func BenchmarkScalarMultTableCompute(b *testing.B) { var buf [32]byte var fe edwards25519.FieldElement var cp edwards25519.CompletedPoint var ep edwards25519.ExtendedPoint var table edwards25519.ScalarMultTable rnd.Read(buf[:]) fe.SetBytes(&buf) cp.SetRistrettoElligator2(&fe) ep.SetCompleted(&cp) b.ResetTimer() for n := 0; n < b.N; n++ { table.Compute(&ep) } } func BenchmarkScalarMultTableScalarMult(b *testing.B) { var buf, sBuf [32]byte var biS big.Int var cp edwards25519.CompletedPoint var ep edwards25519.ExtendedPoint var fe edwards25519.FieldElement var table edwards25519.ScalarMultTable biS.Rand(rnd, &biL) srBuf := biS.Bytes() for j := 0; j < len(srBuf); j++ { sBuf[j] = srBuf[len(srBuf)-j-1] } rnd.Read(buf[:]) fe.SetBytes(&buf) cp.SetRistrettoElligator2(&fe) ep.SetCompleted(&cp) table.Compute(&ep) b.ResetTimer() for n := 0; n < b.N; n++ { table.ScalarMult(&ep, &sBuf) } } func BenchmarkScalarMultTableVarTimeScalarMult(b *testing.B) { var buf, sBuf [32]byte var biS big.Int var cp edwards25519.CompletedPoint var ep edwards25519.ExtendedPoint var fe edwards25519.FieldElement var table edwards25519.ScalarMultTable biS.Rand(rnd, &biL) srBuf := biS.Bytes() for j := 0; j < len(srBuf); j++ { sBuf[j] = srBuf[len(srBuf)-j-1] } rnd.Read(buf[:]) fe.SetBytes(&buf) cp.SetRistrettoElligator2(&fe) ep.SetCompleted(&cp) table.Compute(&ep) b.ResetTimer() for n := 0; n < b.N; n++ { table.VarTimeScalarMult(&ep, &sBuf) } } go-ristretto-1.2.3/edwards25519/vartime.go000066400000000000000000000037761440464505300202360ustar00rootroot00000000000000package edwards25519 func load8u(in []byte) uint64 { var r uint64 r = uint64(in[0]) r |= uint64(in[1]) << 8 r |= uint64(in[2]) << 16 r |= uint64(in[3]) << 24 r |= uint64(in[4]) << 32 r |= uint64(in[5]) << 40 r |= uint64(in[6]) << 48 r |= uint64(in[7]) << 56 return r } // Computes the w=5 w-NAF of s and store it into naf. // naf is assumed to be zero-initialized and the highest three bits of s // have to be cleared. func computeScalar5NAF(s *[32]byte, naf *[256]int8) { var x [5]uint64 for i := 0; i < 4; i++ { x[i] = load8u(s[i*8 : (i+1)*8]) } pos := uint16(0) carry := uint64(0) for pos < 256 { idx := pos / 64 bit_idx := pos % 64 var bit_buf uint64 if bit_idx < 59 { bit_buf = x[idx] >> bit_idx } else { bit_buf = (x[idx] >> bit_idx) | (x[1+idx] << (64 - bit_idx)) } window := carry + (bit_buf & 31) if window&1 == 0 { pos += 1 continue } if window < 16 { carry = 0 naf[pos] = int8(window) } else { carry = 1 naf[pos] = int8(window) - int8(32) } pos += 5 } } func (p *ExtendedPoint) VarTimeScalarMult(q *ExtendedPoint, s *[32]byte) *ExtendedPoint { var lut [8]ExtendedPoint // Precomputations var dblQ ExtendedPoint dblQ.Double(q) lut[0].Set(q) for i := 1; i < 8; i++ { lut[i].Add(&lut[i-1], &dblQ) } // Compute non-adjacent form of s var naf [256]int8 computeScalar5NAF(s, &naf) // Skip the trailing zeroes i := 255 for ; i >= 0; i-- { if naf[i] != 0 { break } } // Corner-case: s is zero. p.SetZero() if i == -1 { return p } var pp ProjectivePoint var cp CompletedPoint for { if naf[i] > 0 { cp.AddExtended(p, &lut[(naf[i]+1)/2-1]) } else { cp.SubExtended(p, &lut[(1-naf[i])/2-1]) } if i == 0 { p.SetCompleted(&cp) break } i -= 1 pp.SetCompleted(&cp) cp.DoubleProjective(&pp) // Find next non-zero digit for { if i == 0 || naf[i] != 0 { break } i -= 1 pp.SetCompleted(&cp) cp.DoubleProjective(&pp) } p.SetCompleted(&cp) if naf[i] == 0 { break } } return p } go-ristretto-1.2.3/edwards25519/vartime_test.go000066400000000000000000000030311440464505300212550ustar00rootroot00000000000000package edwards25519 import ( "math/big" "math/rand" "testing" ) func TestComputeScalar5NAF(t *testing.T) { rnd := rand.New(rand.NewSource(37)) var rs, s [32]byte var sbi, wbi big.Int for i := 0; i < 1000; i++ { rnd.Read(s[0:32]) s[31] &= 31 var w [256]int8 computeScalar5NAF(&s, &w) for j := 0; j < 32; j++ { rs[j] = s[31-j] } sbi.SetBytes(rs[:]) var power, summand big.Int power.SetUint64(1) wbi.SetUint64(0) for j := 0; j < 255; j++ { summand.SetInt64(int64(w[j])) summand.Mul(&summand, &power) wbi.Add(&wbi, &summand) power.Add(&power, &power) } if wbi.Cmp(&sbi) != 0 { t.Fatalf("5NAF(%v) = %v %v != %v", s, w, &sbi, &wbi) } } } func TestVarTimeScalarMult(t *testing.T) { rnd := rand.New(rand.NewSource(37)) var fe FieldElement var cp CompletedPoint var q, p1, p2 ExtendedPoint var s [32]byte for i := 0; i < 1000; i++ { var buf [32]byte rnd.Read(buf[:]) fe.SetBytes(&buf) cp.SetRistrettoElligator2(&fe) q.SetCompleted(&cp) rnd.Read(s[0:32]) s[31] &= 31 p1.ScalarMult(&q, &s) p2.VarTimeScalarMult(&q, &s) if p1.RistrettoEqualsI(&p2) != 1 { t.Fatalf("[%v]%v = %v != %v", s, q, p1, p2) } } } func BenchmarkVarTimeScalarMult(b *testing.B) { rnd := rand.New(rand.NewSource(37)) var buf, s [32]byte var cp CompletedPoint var ep ExtendedPoint var fe FieldElement rnd.Read(s[0:32]) s[31] &= 31 rnd.Read(buf[:]) fe.SetBytes(&buf) cp.SetRistrettoElligator2(&fe) ep.SetCompleted(&cp) b.ResetTimer() for n := 0; n < b.N; n++ { ep.VarTimeScalarMult(&ep, &s) } } go-ristretto-1.2.3/elgamal_test.go000066400000000000000000000014431440464505300171560ustar00rootroot00000000000000package ristretto_test import ( "bytes" "fmt" "github.com/bwesterb/go-ristretto" ) func Example() { // Generate an El'Gamal keypair var secretKey ristretto.Scalar var publicKey ristretto.Point secretKey.Rand() // generate a new secret key publicKey.ScalarMultBase(&secretKey) // compute public key // El'Gamal encrypt a random curve point p into a ciphertext-pair (c1,c2) var p ristretto.Point var r ristretto.Scalar var c1 ristretto.Point var c2 ristretto.Point p.Rand() r.Rand() c2.ScalarMultBase(&r) c1.PublicScalarMult(&publicKey, &r) c1.Add(&c1, &p) // Decrypt (c1,c2) back to p var blinding, p2 ristretto.Point blinding.ScalarMult(&c2, &secretKey) p2.Sub(&c1, &blinding) fmt.Printf("%v", bytes.Equal(p.Bytes(), p2.Bytes())) // Output: // true } go-ristretto-1.2.3/go.mod000066400000000000000000000000611440464505300152670ustar00rootroot00000000000000module github.com/bwesterb/go-ristretto go 1.13 go-ristretto-1.2.3/ristretto.go000066400000000000000000000272371440464505300165650ustar00rootroot00000000000000// Pure Go implementation of the Ristretto prime-order group built from // the Edwards curve Edwards25519. // // Many cryptographic schemes need a group of prime order. Popular and // efficient elliptic curves like (Edwards25519 of `ed25519` fame) are // rarely of prime order. There is, however, a convenient method // to construct a prime order group from such curves, using a method // called Ristretto proposed by Mike Hamburg. // // This package implements the Ristretto group constructed from Edwards25519. // The Point type represents a group element. The API mimics that of the // math/big package. For instance, to set c to a+b, one writes // // var c ristretto.Point // c.Add(&a, &b) // sets c to a + b // // Warning: contrary to math.Big's interface, an uninitialized Point is not // the same thing as the zero (neutral element) of the group: // // var c ristretto.Point // c is uninitialized now --- not zero! // c.SetZero() // c is zero now; ready to use! // // Most methods return the receiver, so that function can be chained: // // s.Add(&a, &b).Add(&s, &c) // sets s to a + b + c // // The order of the Ristretto group is l = // 2^252 + 27742317777372353535851937790883648493 = // 7237005577332262213973186563042994240857116359379907606001950938285454250989. // The Scalar type implement the numbers modulo l and also has an API similar // to math/big. package ristretto import ( "crypto/rand" "crypto/sha256" "crypto/sha512" "crypto/subtle" "encoding/base64" "encoding/hex" "errors" "fmt" "github.com/bwesterb/go-ristretto/edwards25519" ) // Represents an element of the Ristretto group over Edwards25519. // // Warning: an uninitialized Point is not the same thing as a zero. Use // the SetZero() method to set an (uninitialized) Point to zero. type Point edwards25519.ExtendedPoint // A table to speed up scalar multiplication of a fixed point type ScalarMultTable edwards25519.ScalarMultTable // Sets p to zero (the neutral element). Returns p. func (p *Point) SetZero() *Point { p.e().SetZero() return p } // Sets p to the Edwards25519 basepoint. Returns p func (p *Point) SetBase() *Point { p.e().SetBase() return p } // Sets p to q. Returns p func (p *Point) Set(q *Point) *Point { p.e().Set(q.e()) return p } // Sets p to q + r. Returns p. func (p *Point) Add(q, r *Point) *Point { p.e().Add(q.e(), r.e()) return p } // Sets p to q + q. Returns p. func (p *Point) Double(q *Point) *Point { p.e().Double(q.e()) return p } // Sets p to q - r. Returns p. func (p *Point) Sub(q, r *Point) *Point { p.e().Sub(q.e(), r.e()) return p } // Sets p to -q. Returns p. func (p *Point) Neg(q *Point) *Point { p.e().Neg(q.e()) return p } // Packs p into the given buffer. Returns p. func (p *Point) BytesInto(buf *[32]byte) *Point { p.e().RistrettoInto(buf) return p } // Returns a packed version of p. func (p *Point) Bytes() []byte { return p.e().Ristretto() } // Sets p to the point encoded in buf using Bytes(). // Not every input encodes a point. Returns whether the buffer encoded a point. func (p *Point) SetBytes(buf *[32]byte) bool { return p.e().SetRistretto(buf) } // Sets p to the point corresponding to buf using the Elligator2 encoding. // // In contrast to SetBytes() (1) Every input buffer will decode to a point // and (2) SetElligator() is not injective: for every point there are // approximately four buffers that will encode to it. func (p *Point) SetElligator(buf *[32]byte) *Point { var fe edwards25519.FieldElement var cp edwards25519.CompletedPoint fe.SetBytes(buf) cp.SetRistrettoElligator2(&fe) p.e().SetCompleted(&cp) return p } // Sets p to s * q, where q is the point for which the table t was // computed. Returns p. func (p *Point) ScalarMultTable(t *ScalarMultTable, s *Scalar) *Point { var buf [32]byte s.BytesInto(&buf) t.t().ScalarMult(p.e(), &buf) return p } // Sets p to s * q, where q is the point for which the table t was // computed. Returns p. // // Warning: this method uses a non-constant time implementation and thus leaks // information about s. Use this function only if s is public knowledge. func (p *Point) PublicScalarMultTable(t *ScalarMultTable, s *Scalar) *Point { var buf [32]byte s.BytesInto(&buf) t.t().VarTimeScalarMult(p.e(), &buf) return p } // Sets p to s * q. Returns p. func (p *Point) ScalarMult(q *Point, s *Scalar) *Point { var buf [32]byte s.BytesInto(&buf) p.e().ScalarMult(q.e(), &buf) return p } // Sets p to s * q assuming s is *not* secret. Returns p. // // Warning: this method uses a non-constant time implementation and thus leaks // information about s. Use this function only if s is public knowledge. func (p *Point) PublicScalarMult(q *Point, s *Scalar) *Point { var buf [32]byte s.BytesInto(&buf) p.e().VarTimeScalarMult(q.e(), &buf) return p } // Sets p to s * B, where B is the edwards25519 basepoint. Returns p. // // Warning: this method uses a non-constant time implementation and thus leaks // information about s. Use this function only if s is public knowledge. func (p *Point) PublicScalarMultBase(s *Scalar) *Point { var buf [32]byte s.BytesInto(&buf) edwards25519.BaseScalarMultTable.VarTimeScalarMult(p.e(), &buf) return p } // Sets p to s * B, where B is the edwards25519 basepoint. Returns p. func (p *Point) ScalarMultBase(s *Scalar) *Point { var buf [32]byte s.BytesInto(&buf) edwards25519.BaseScalarMultTable.ScalarMult(p.e(), &buf) return p } // Sets p to a random point. Returns p. func (p *Point) Rand() *Point { var buf [32]byte if _, err := rand.Read(buf[:]); err != nil { panic(err) } return p.SetElligator(&buf) } // Sets p to the point derived from the buffer using SHA512 and Elligator2. // Returns p. // // NOTE curve25519-dalek uses a different (more conservative) method to derive // a point from raw data with a hash. This is implemented in // Point.DeriveDalek(). func (p *Point) Derive(buf []byte) *Point { var ptBuf [32]byte h := sha512.Sum512(buf) copy(ptBuf[:], h[:32]) return p.SetElligator(&ptBuf) } // Encode 16 bytes into a point using the Lizard method. // // Use Lizard() or LizardInto() to decode the bytes from a Point. // // Notes on usage: // // - If you want to create a Point from random data, you should rather // create a random Point with Point.Rand() and then use (a hash of) // Point.Bytes() as the random data. // // - If you want to derive a Point from data, but you do not care about // decoding the data back from the point, you should use // the Point.Derive() method instead. // // - There are some (and with high probability at most 80) inputs to // SetLizard() which cannot be decoded. The chance that you hit such // an input is around 1 in 2^122. // // In Lizard there are 256 - 128 - 3 = 125 check bits to pick out the // right preimage among at most eight. Conservatively assuming there are // seven other preimages, the chance that one of them passes the check as // well is given by: // // 1 - (1 - 2^-125)^7 = 7*2^-125 + 21*2^-250 - ... // =~ 2^(-125 - 2log(7)) // = 2^-122.192... // // Presuming a random hash function, the number of "bad" inputs is binomially // distributed with n=2^128 and p=2^-122.192... For such large n, the Poisson // distribution with lambda=n*p=56 is a very good approximation. In fact: // the cumulative distribution function (CDF) of the Poission distribution // is larger than that of the binomial distribution for k > lambda.[1] The value // of the former on k=80 is larger than 0.999 and so with a probability of 99.9%, // there are fewer than 80 bad inputs. // // [1] See "Some Inequalities Among Binomial and Poisson Probabilities" // by Anderson and Samuels in Proc. Fifth Berkeley Symp. on // Math. Statist. and Prob., Vol. 1 (Univ. of Calif. Press, 1967). func (p *Point) SetLizard(data *[16]byte) *Point { var fe edwards25519.FieldElement var cp edwards25519.CompletedPoint buf := sha256.Sum256(data[:]) copy(buf[8:], data[:]) buf[0] &= 254 // clear lowest bit to make the FieldElement positive buf[31] &= 63 // clear highest two bits to ensure below 2^255-19. fe.SetBytes(&buf) cp.SetRistrettoElligator2(&fe) p.e().SetCompleted(&cp) return p } // Decodes 16 bytes encoded into this point using SetLizard(). // // Returns nil if this point does not contain data encoded using Lizard. // // See SetLizard() for notes on usage. func (p *Point) Lizard() []byte { var ret [16]byte if p.LizardInto(&ret) != nil { return nil } return ret[:] } // Decodes 16 bytes into the given buffer encoded into this point // using SetLizard(). // // See SetLizard() for notes on usage. func (p *Point) LizardInto(buf *[16]byte) error { var fes [8]edwards25519.FieldElement var buf2 [32]byte var nFound uint8 mask := p.e().RistrettoElligator2Inverse(&fes) for j := 0; j < 8; j++ { ok := (mask >> uint(j)) & 1 fes[j].BytesInto(&buf2) h := sha256.Sum256(buf2[8:24]) copy(h[8:], buf2[8:24]) h[0] &= 254 h[31] &= 63 ok &= uint8(subtle.ConstantTimeCompare(h[:], buf2[:])) subtle.ConstantTimeCopy(int(ok), buf[:], buf2[8:24]) nFound += ok } if nFound == 1 { return nil } if nFound == 0 { return errors.New("No Lizard preimage") } return errors.New("Multiple Lizard preimages") } // Returns 1 if p == q and 0 otherwise. func (p *Point) EqualsI(q *Point) int32 { return p.e().RistrettoEqualsI(q.e()) } // Returns whether p == q func (p *Point) Equals(q *Point) bool { return p.EqualsI(q) == 1 } // Set p to q if b=1 in constant-time. b must be either 0 or 1. func (p *Point) ConditionalSet(q *Point, b int32) { p.e().ConditionalSet(q.e(), b) } // Sets p to the point derived from the buffer using SHA512 and Elligator2 // in the fashion of curve25519-dalek. // // NOTE See also Derive(), which is a different method which is twice as fast, // but which might not be as secure as this method. func (p *Point) DeriveDalek(data []byte) *Point { hash := sha512.Sum512(data) var p2 Point var buf [32]byte copy(buf[:], hash[:32]) p.SetElligator(&buf) copy(buf[:], hash[32:]) p2.SetElligator(&buf) p.Add(p, &p2) return p } // Implements encoding/BinaryUnmarshaler. Use SetBytes, if convenient, instead. func (p *Point) UnmarshalBinary(data []byte) error { if len(data) != 32 { return fmt.Errorf("ristretto.Point should be 32 bytes; not %d", len(data)) } var buf [32]byte copy(buf[:], data) if !p.SetBytes(&buf) { return errors.New("Buffer does not encode a ristretto.Point") } return nil } // Implements encoding/BinaryMarshaler. Use BytesInto, if convenient, instead. func (p *Point) MarshalBinary() ([]byte, error) { var buf [32]byte p.BytesInto(&buf) return buf[:], nil } func (p *Point) MarshalText() ([]byte, error) { enc := base64.RawURLEncoding var buf [32]byte p.BytesInto(&buf) ret := make([]byte, enc.EncodedLen(32)) enc.Encode(ret, buf[:]) return ret, nil } func textToBuf(dst, src []byte) error { var n int var err error if len(src) == 64 { n, err = hex.Decode(dst, src) if n == 32 && err == nil { return nil } } enc := base64.RawURLEncoding n, err = enc.Decode(dst, src) if err != nil { return err } if n != 32 { return fmt.Errorf("ristretto.Point should be 32 bytes; not %d", n) } return nil } func (p *Point) UnmarshalText(txt []byte) error { var buf [32]byte err := textToBuf(buf[:], txt) if err != nil { return err } if !p.SetBytes(&buf) { return errors.New("Buffer does not encode a ristretto.Point") } return nil } func (p Point) String() string { text, _ := p.MarshalText() return string(text) } func (p *Point) e() *edwards25519.ExtendedPoint { return (*edwards25519.ExtendedPoint)(p) } func (t *ScalarMultTable) t() *edwards25519.ScalarMultTable { return (*edwards25519.ScalarMultTable)(t) } // Fills the table for point p. func (t *ScalarMultTable) Compute(p *Point) { t.t().Compute(p.e()) } go-ristretto-1.2.3/ristretto_test.go000066400000000000000000000173031440464505300176150ustar00rootroot00000000000000package ristretto_test import ( "bytes" "encoding/hex" "testing" "github.com/bwesterb/go-ristretto" ) func TestPointDerive(t *testing.T) { testVectors := []struct{ in, out string }{ {"test", "b01d60504aa5f4c5bd9a7541c457661f9a789d18cb4e136e91d3c953488bd208"}, {"pep", "3286c8d171dec02e70549c280d62524430408a781efc07e4428d1735671d195b"}, {"ristretto", "c2f6bb4c4dab8feab66eab09e77e79b36095c86b3cd1145b9a2703205858d712"}, {"elligator", "784c727b1e8099eb94e5a8edbd260363567fdbd35106a7a29c8b809cd108b322"}, } for _, v := range testVectors { var p ristretto.Point p.Derive([]byte(v.in)) out2 := hex.EncodeToString(p.Bytes()) if out2 != v.out { t.Fatalf("Derive(%v) = %v != %v", v.in, v.out, out2) } } } // Test vectors from https://ristretto.group/test_vectors/ristretto255.html func TestRistretto255TestVectors(t *testing.T) { smallMultiples := []string{ "0000000000000000000000000000000000000000000000000000000000000000", "e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76", "6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919", "94741f5d5d52755ece4f23f044ee27d5d1ea1e2bd196b462166b16152a9d0259", "da80862773358b466ffadfe0b3293ab3d9fd53c5ea6c955358f568322daf6a57", "e882b131016b52c1d3337080187cf768423efccbb517bb495ab812c4160ff44e", "f64746d3c92b13050ed8d80236a7f0007c3b3f962f5ba793d19a601ebb1df403", "44f53520926ec81fbd5a387845beb7df85a96a24ece18738bdcfa6a7822a176d", "903293d8f2287ebe10e2374dc1a53e0bc887e592699f02d077d5263cdd55601c", "02622ace8f7303a31cafc63f8fc48fdc16e1c8c8d234b2f0d6685282a9076031", "20706fd788b2720a1ed2a5dad4952b01f413bcf0e7564de8cdc816689e2db95f", "bce83f8ba5dd2fa572864c24ba1810f9522bc6004afe95877ac73241cafdab42", "e4549ee16b9aa03099ca208c67adafcafa4c3f3e4e5303de6026e3ca8ff84460", "aa52e000df2e16f55fb1032fc33bc42742dad6bd5a8fc0be0167436c5948501f", "46376b80f409b29dc2b5f6f0c52591990896e5716f41477cd30085ab7f10301e", "e0c418f7c8d9c4cdd7395b93ea124f3ad99021bb681dfc3302a9d99a2e53e64e", } var B, pt ristretto.Point B.SetBase() pt.SetZero() for i, pt2 := range smallMultiples { if hex.EncodeToString(pt.Bytes()) != pt2 { t.Fatalf("%d * B = %s != %v", i, pt2, hex.EncodeToString(pt.Bytes())) } pt.Add(&B, &pt) } badEncodings := []string{ // Non-canonical field encodings. "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", "f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", // Negative field elements. "0100000000000000000000000000000000000000000000000000000000000000", "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", "ed57ffd8c914fb201471d1c3d245ce3c746fcbe63a3679d51b6a516ebebe0e20", "c34c4e1826e5d403b78e246e88aa051c36ccf0aafebffe137d148a2bf9104562", "c940e5a4404157cfb1628b108db051a8d439e1a421394ec4ebccb9ec92a8ac78", "47cfc5497c53dc8e61c91d17fd626ffb1c49e2bca94eed052281b510b1117a24", "f1c6165d33367351b0da8f6e4511010c68174a03b6581212c71c0e1d026c3c72", "87260f7a2f12495118360f02c26a470f450dadf34a413d21042b43b9d93e1309", // Non-square x^2. "26948d35ca62e643e26a83177332e6b6afeb9d08e4268b650f1f5bbd8d81d371", "4eac077a713c57b4f4397629a4145982c661f48044dd3f96427d40b147d9742f", "de6a7b00deadc788eb6b6c8d20c0ae96c2f2019078fa604fee5b87d6e989ad7b", "bcab477be20861e01e4a0e295284146a510150d9817763caf1a6f4b422d67042", "2a292df7e32cababbd9de088d1d1abec9fc0440f637ed2fba145094dc14bea08", "f4a9e534fc0d216c44b218fa0c42d99635a0127ee2e53c712f70609649fdff22", "8268436f8c4126196cf64b3c7ddbda90746a378625f9813dd9b8457077256731", "2810e5cbc2cc4d4eece54f61c6f69758e289aa7ab440b3cbeaa21995c2f4232b", // Negative xy value. "3eb858e78f5a7254d8c9731174a94f76755fd3941c0ac93735c07ba14579630e", "a45fdc55c76448c049a1ab33f17023edfb2be3581e9c7aade8a6125215e04220", "d483fe813c6ba647ebbfd3ec41adca1c6130c2beeee9d9bf065c8d151c5f396e", "8a2e1d30050198c65a54483123960ccc38aef6848e1ec8f5f780e8523769ba32", "32888462f8b486c68ad7dd9610be5192bbeaf3b443951ac1a8118419d9fa097b", "227142501b9d4355ccba290404bde41575b037693cef1f438c47f8fbf35d1165", "5c37cc491da847cfeb9281d407efc41e15144c876e0170b499a96a22ed31e01e", "445425117cb8c90edcbc7c1cc0e74f747f2c1efa5630a967c64f287792a48a4b", // s = -1, which causes y = 0. "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", } for _, ptHex := range badEncodings { var pt ristretto.Point var buf [32]byte tmp, _ := hex.DecodeString(ptHex) copy(buf[:], tmp) if pt.SetBytes(&buf) { t.Fatalf("%v should not decode", ptHex) } } encodedHashToPoints := []struct{ label, encoding string }{ {"Ristretto is traditionally a short shot of espresso coffee", "3066f82a1a747d45120d1740f14358531a8f04bbffe6a819f86dfe50f44a0a46"}, {"made with the normal amount of ground coffee but extracted with", "f26e5b6f7d362d2d2a94c5d0e7602cb4773c95a2e5c31a64f133189fa76ed61b"}, {"about half the amount of water in the same amount of time", "006ccd2a9e6867e6a2c5cea83d3302cc9de128dd2a9a57dd8ee7b9d7ffe02826"}, {"by using a finer grind.", "f8f0c87cf237953c5890aec3998169005dae3eca1fbb04548c635953c817f92a"}, {"This produces a concentrated shot of coffee per volume.", "ae81e7dedf20a497e10c304a765c1767a42d6e06029758d2d7e8ef7cc4c41179"}, {"Just pulling a normal shot short will produce a weaker shot", "e2705652ff9f5e44d3e841bf1c251cf7dddb77d140870d1ab2ed64f1a9ce8628"}, {"and is not a Ristretto as some believe.", "80bd07262511cdde4863f8a7434cef696750681cb9510eea557088f76d9e5065"}, } for _, tp := range encodedHashToPoints { var p ristretto.Point p.DeriveDalek([]byte(tp.label)) res := hex.EncodeToString(p.Bytes()) if res != tp.encoding { t.Fatalf("Test string %v produced %s instead of %s", tp.label, res, tp.encoding) } } } // Test base point multiplication func TestBasePointMultiples(t *testing.T) { var s ristretto.Scalar var p1, p2, B ristretto.Point B.SetBase() for i := 0; i < 1000; i++ { s.Rand() p1.ScalarMultBase(&s) p2.ScalarMult(&B, &s) if !p1.Equals(&p2) { t.Fatalf("[%v]B = %v != %v", s, p2, p1) } } } func TestConditionalSet(t *testing.T) { var p1, p2 ristretto.Point for i := 0; i < 1000; i++ { p1.Rand() p2.Rand() p1.ConditionalSet(&p2, 0) if p1.Equals(&p2) { t.Fatal() } p1.ConditionalSet(&p2, 1) if !p1.Equals(&p2) { t.Fatal() } } } func testLizardVector(t *testing.T, in, out string) { var p ristretto.Point var inBuf [16]byte var outBuf [32]byte hex.Decode(inBuf[:], []byte(in)) hex.Decode(outBuf[:], []byte(out)) p.SetLizard(&inBuf) if !bytes.Equal(p.Bytes(), outBuf[:]) { t.Fatalf("Lizard(%s) is wrong", in) } } func TestLizardVectors(t *testing.T) { testLizardVector(t, "00000000000000000000000000000000", "f0b7e34484f74cf00f15024b738539738646bbbe1e9bc7509a676815227e774f") testLizardVector(t, "01010101010101010101010101010101", "cc92e81f585afc5caac88660d8d17e9025a44489a363042123f6af0702156e65") } func TestLizardInjective(t *testing.T) { var buf1, buf2 [16]byte var buf [32]byte var p ristretto.Point for i := 0; i < 1000; i++ { rnd.Read(buf1[:]) p.SetLizard(&buf1) p.BytesInto(&buf) if !p.SetBytes(&buf) { t.Fatal() } err := p.LizardInto(&buf2) if err != nil { t.Fatalf("LizardInto: %v", err) } if !bytes.Equal(buf1[:], buf2[:]) { t.Fatalf("Lizard^-1 o Lizard != id: %v != %v", buf1, buf2) } } } func BenchmarkLizardDecode(b *testing.B) { buf := [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} var p ristretto.Point p.SetLizard(&buf) b.ResetTimer() for n := 0; n < b.N; n++ { p.Lizard() } } func BenchmarkLizardEncode(b *testing.B) { var buf [16]byte var p ristretto.Point for n := 0; n < b.N; n++ { rnd.Read(buf[:]) p.SetLizard(&buf) } } go-ristretto-1.2.3/scalar.go000066400000000000000000001054531440464505300157700ustar00rootroot00000000000000package ristretto import ( "crypto/rand" "crypto/sha512" "encoding/base64" "encoding/binary" "fmt" // Required for FieldElement.[Set]BigInt(). Obviously not used for actual // implementation, as operations on big.Ints are not constant-time. "math/big" ) // A number modulo the prime l, where l is the order of the Ristretto group // over Edwards25519. // // The scalar s is represented as an array s[0], ... s[7] with 0 <= s[i] < 2^32 // and s = s[0] + s[1] * 2^32 + s[2] * 2^64 + ... + s[7] * 2^224. type Scalar [8]uint32 var ( scZero Scalar scOne = Scalar{ 1, 0, 0, 0, 0, 0, 0, 0, } scL = Scalar{ 0x5cf5d3ed, 0x5812631a, 0xa2f79cd6, 0x14def9de, 0x00000000, 0x00000000, 0x00000000, 0x10000000, } ) // Encode s little endian into buf. Returns s. func (s *Scalar) BytesInto(buf *[32]byte) *Scalar { buf[0] = uint8(s[0]) buf[1] = uint8(s[0] >> 8) buf[2] = uint8(s[0] >> 16) buf[3] = uint8(s[0] >> 24) buf[4] = uint8(s[1]) buf[5] = uint8(s[1] >> 8) buf[6] = uint8(s[1] >> 16) buf[7] = uint8(s[1] >> 24) buf[8] = uint8(s[2]) buf[9] = uint8(s[2] >> 8) buf[10] = uint8(s[2] >> 16) buf[11] = uint8(s[2] >> 24) buf[12] = uint8(s[3]) buf[13] = uint8(s[3] >> 8) buf[14] = uint8(s[3] >> 16) buf[15] = uint8(s[3] >> 24) buf[16] = uint8(s[4]) buf[17] = uint8(s[4] >> 8) buf[18] = uint8(s[4] >> 16) buf[19] = uint8(s[4] >> 24) buf[20] = uint8(s[5]) buf[21] = uint8(s[5] >> 8) buf[22] = uint8(s[5] >> 16) buf[23] = uint8(s[5] >> 24) buf[24] = uint8(s[6]) buf[25] = uint8(s[6] >> 8) buf[26] = uint8(s[6] >> 16) buf[27] = uint8(s[6] >> 24) buf[28] = uint8(s[7]) buf[29] = uint8(s[7] >> 8) buf[30] = uint8(s[7] >> 16) buf[31] = uint8(s[7] >> 24) return s } // Bytes() returns a little-endian packed version of s. See also BytesInto(). func (s *Scalar) Bytes() []byte { var ret [32]byte s.BytesInto(&ret) return ret[:] } // Sets s to x mod l, where x is interpreted little endian and the // top 3 bits are ignored. Returns s. func (s *Scalar) SetBytes(x *[32]byte) *Scalar { s[0] = load4u32(x[0:]) s[1] = load4u32(x[4:]) s[2] = load4u32(x[8:]) s[3] = load4u32(x[12:]) s[4] = load4u32(x[16:]) s[5] = load4u32(x[20:]) s[6] = load4u32(x[24:]) s[7] = load4u32(x[28:]) & 0x1fffffff return s.Sub(s, &scL) } // Sets s to -a. Returns s. func (s *Scalar) Neg(a *Scalar) *Scalar { return s.Sub(&scZero, a) } // Sets s to a + b. Returns s. func (s *Scalar) Add(a, b *Scalar) *Scalar { carry := uint64(a[0]) + uint64(b[0]) s[0] = uint32(carry) carry = uint64(a[1]) + uint64(b[1]) + (carry >> 32) s[1] = uint32(carry) carry = uint64(a[2]) + uint64(b[2]) + (carry >> 32) s[2] = uint32(carry) carry = uint64(a[3]) + uint64(b[3]) + (carry >> 32) s[3] = uint32(carry) carry = uint64(a[4]) + uint64(b[4]) + (carry >> 32) s[4] = uint32(carry) carry = uint64(a[5]) + uint64(b[5]) + (carry >> 32) s[5] = uint32(carry) carry = uint64(a[6]) + uint64(b[6]) + (carry >> 32) s[6] = uint32(carry) carry = uint64(a[7]) + uint64(b[7]) + (carry >> 32) s[7] = uint32(carry) return s.Sub(s, &scL) } // Sets s to a - b. Returns s. func (s *Scalar) Sub(a, b *Scalar) *Scalar { borrow := uint64(a[0]) - uint64(b[0]) s0 := uint32(borrow) borrow = uint64(a[1]) - uint64(b[1]) - (borrow >> 63) s1 := uint32(borrow) borrow = uint64(a[2]) - uint64(b[2]) - (borrow >> 63) s2 := uint32(borrow) borrow = uint64(a[3]) - uint64(b[3]) - (borrow >> 63) s3 := uint32(borrow) borrow = uint64(a[4]) - uint64(b[4]) - (borrow >> 63) s4 := uint32(borrow) borrow = uint64(a[5]) - uint64(b[5]) - (borrow >> 63) s5 := uint32(borrow) borrow = uint64(a[6]) - uint64(b[6]) - (borrow >> 63) s6 := uint32(borrow) borrow = uint64(a[7]) - uint64(b[7]) - (borrow >> 63) s7 := uint32(borrow) // Add l if underflown ufMask := ((borrow >> 63) ^ 1) - 1 carry := uint64(s0) + (ufMask & uint64(0x5CF5D3ED)) s0 = uint32(carry) carry = uint64(s1) + (carry >> 32) + (ufMask & uint64(0x5812631A)) s1 = uint32(carry) carry = uint64(s2) + (carry >> 32) + (ufMask & uint64(0xA2F79CD6)) s2 = uint32(carry) carry = uint64(s3) + (carry >> 32) + (ufMask & uint64(0x14DEF9DE)) s3 = uint32(carry) carry = uint64(s4) + (carry >> 32) s4 = uint32(carry) carry = uint64(s5) + (carry >> 32) s5 = uint32(carry) carry = uint64(s6) + (carry >> 32) s6 = uint32(carry) carry = uint64(s7) + (carry >> 32) + (ufMask & 0x10000000) s7 = uint32(carry) s[0] = s0 s[1] = s1 s[2] = s2 s[3] = s3 s[4] = s4 s[5] = s5 s[6] = s6 s[7] = s7 return s } // Returns s as a big.Int. // // Warning: operations on big.Ints are not constant-time: do not use them // for cryptography unless you're sure this is not an issue. func (s *Scalar) BigInt() *big.Int { var ret big.Int var buf, rBuf [32]byte s.BytesInto(&buf) for i := 0; i < 32; i++ { rBuf[i] = buf[31-i] } return ret.SetBytes(rBuf[:]) } // Sets s to x modulo l. // // Warning: operations on big.Ints are not constant-time: do not use them // for cryptography unless you're sure this is not an issue. func (s *Scalar) SetBigInt(x *big.Int) *Scalar { var v, biL big.Int biL.SetString( "1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", 16) buf := v.Mod(x, &biL).Bytes() var rBuf [32]byte for i := 0; i < len(buf) && i < 32; i++ { rBuf[i] = buf[len(buf)-i-1] } return s.SetBytes(&rBuf) } // Sets s to x. func (s *Scalar) SetUint64(x uint64) *Scalar { var rBuf [32]byte binary.LittleEndian.PutUint64(rBuf[:], x) return s.SetBytes(&rBuf) } // Sets s to t. Returns s. func (s *Scalar) Set(t *Scalar) *Scalar { copy(s[:], t[:]) return s } // Sets s to 0. Returns s. func (s *Scalar) SetZero() *Scalar { return s.Set(&scZero) } // Sets s to 1. Returns s. func (s *Scalar) SetOne() *Scalar { return s.Set(&scOne) } // Sets s to a * b - c. Returns s. func (s *Scalar) MulSub(a, b, c *Scalar) *Scalar { a0 := int64(a[0] & 0x1fffff) a1 := int64(((a[0] >> 21) | (a[1] << 11)) & 0x1fffff) a2 := int64((a[1] >> 10) & 0x1fffff) a3 := int64(((a[1] >> 31) | (a[2] << 1)) & 0x1fffff) a4 := int64(((a[2] >> 20) | (a[3] << 12)) & 0x1fffff) a5 := int64((a[3] >> 9) & 0x1fffff) a6 := int64(((a[3] >> 30) | (a[4] << 2)) & 0x1fffff) a7 := int64(((a[4] >> 19) | (a[5] << 13)) & 0x1fffff) a8 := int64((a[5] >> 8) & 0x1fffff) a9 := int64(((a[5] >> 29) | (a[6] << 3)) & 0x1fffff) a10 := int64(((a[6] >> 18) | (a[7] << 14)) & 0x1fffff) a11 := int64((a[7] >> 7)) b0 := int64(b[0] & 0x1fffff) b1 := int64(((b[0] >> 21) | (b[1] << 11)) & 0x1fffff) b2 := int64((b[1] >> 10) & 0x1fffff) b3 := int64(((b[1] >> 31) | (b[2] << 1)) & 0x1fffff) b4 := int64(((b[2] >> 20) | (b[3] << 12)) & 0x1fffff) b5 := int64((b[3] >> 9) & 0x1fffff) b6 := int64(((b[3] >> 30) | (b[4] << 2)) & 0x1fffff) b7 := int64(((b[4] >> 19) | (b[5] << 13)) & 0x1fffff) b8 := int64((b[5] >> 8) & 0x1fffff) b9 := int64(((b[5] >> 29) | (b[6] << 3)) & 0x1fffff) b10 := int64(((b[6] >> 18) | (b[7] << 14)) & 0x1fffff) b11 := int64((b[7] >> 7)) c0 := int64(c[0] & 0x1fffff) c1 := int64(((c[0] >> 21) | (c[1] << 11)) & 0x1fffff) c2 := int64((c[1] >> 10) & 0x1fffff) c3 := int64(((c[1] >> 31) | (c[2] << 1)) & 0x1fffff) c4 := int64(((c[2] >> 20) | (c[3] << 12)) & 0x1fffff) c5 := int64((c[3] >> 9) & 0x1fffff) c6 := int64(((c[3] >> 30) | (c[4] << 2)) & 0x1fffff) c7 := int64(((c[4] >> 19) | (c[5] << 13)) & 0x1fffff) c8 := int64((c[5] >> 8) & 0x1fffff) c9 := int64(((c[5] >> 29) | (c[6] << 3)) & 0x1fffff) c10 := int64(((c[6] >> 18) | (c[7] << 14)) & 0x1fffff) c11 := int64((c[7] >> 7)) return s.reduceAfterMul( -c0+a0*b0, -c1+a0*b1+a1*b0, -c2+a0*b2+a1*b1+a2*b0, -c3+a0*b3+a1*b2+a2*b1+a3*b0, -c4+a0*b4+a1*b3+a2*b2+a3*b1+a4*b0, -c5+a0*b5+a1*b4+a2*b3+a3*b2+a4*b1+a5*b0, -c6+a0*b6+a1*b5+a2*b4+a3*b3+a4*b2+a5*b1+a6*b0, -c7+a0*b7+a1*b6+a2*b5+a3*b4+a4*b3+a5*b2+a6*b1+a7*b0, -c8+a0*b8+a1*b7+a2*b6+a3*b5+a4*b4+a5*b3+a6*b2+a7*b1+a8*b0, -c9+a0*b9+a1*b8+a2*b7+a3*b6+a4*b5+a5*b4+a6*b3+a7*b2+a8*b1+a9*b0, -c10+a0*b10+a1*b9+a2*b8+a3*b7+a4*b6+a5*b5+a6*b4+a7*b3+a8*b2+a9*b1+a10*b0, -c11+a0*b11+a1*b10+a2*b9+a3*b8+a4*b7+a5*b6+a6*b5+a7*b4+a8*b3+a9*b2+a10*b1+a11*b0, a1*b11+a2*b10+a3*b9+a4*b8+a5*b7+a6*b6+a7*b5+a8*b4+a9*b3+a10*b2+a11*b1, a2*b11+a3*b10+a4*b9+a5*b8+a6*b7+a7*b6+a8*b5+a9*b4+a10*b3+a11*b2, a3*b11+a4*b10+a5*b9+a6*b8+a7*b7+a8*b6+a9*b5+a10*b4+a11*b3, a4*b11+a5*b10+a6*b9+a7*b8+a8*b7+a9*b6+a10*b5+a11*b4, a5*b11+a6*b10+a7*b9+a8*b8+a9*b7+a10*b6+a11*b5, a6*b11+a7*b10+a8*b9+a9*b8+a10*b7+a11*b6, a7*b11+a8*b10+a9*b9+a10*b8+a11*b7, a8*b11+a9*b10+a10*b9+a11*b8, a9*b11+a10*b10+a11*b9, a10*b11+a11*b10, a11*b11) } // Sets s to a * b + c. Returns s. func (s *Scalar) MulAdd(a, b, c *Scalar) *Scalar { a0 := int64(a[0] & 0x1fffff) a1 := int64(((a[0] >> 21) | (a[1] << 11)) & 0x1fffff) a2 := int64((a[1] >> 10) & 0x1fffff) a3 := int64(((a[1] >> 31) | (a[2] << 1)) & 0x1fffff) a4 := int64(((a[2] >> 20) | (a[3] << 12)) & 0x1fffff) a5 := int64((a[3] >> 9) & 0x1fffff) a6 := int64(((a[3] >> 30) | (a[4] << 2)) & 0x1fffff) a7 := int64(((a[4] >> 19) | (a[5] << 13)) & 0x1fffff) a8 := int64((a[5] >> 8) & 0x1fffff) a9 := int64(((a[5] >> 29) | (a[6] << 3)) & 0x1fffff) a10 := int64(((a[6] >> 18) | (a[7] << 14)) & 0x1fffff) a11 := int64((a[7] >> 7)) b0 := int64(b[0] & 0x1fffff) b1 := int64(((b[0] >> 21) | (b[1] << 11)) & 0x1fffff) b2 := int64((b[1] >> 10) & 0x1fffff) b3 := int64(((b[1] >> 31) | (b[2] << 1)) & 0x1fffff) b4 := int64(((b[2] >> 20) | (b[3] << 12)) & 0x1fffff) b5 := int64((b[3] >> 9) & 0x1fffff) b6 := int64(((b[3] >> 30) | (b[4] << 2)) & 0x1fffff) b7 := int64(((b[4] >> 19) | (b[5] << 13)) & 0x1fffff) b8 := int64((b[5] >> 8) & 0x1fffff) b9 := int64(((b[5] >> 29) | (b[6] << 3)) & 0x1fffff) b10 := int64(((b[6] >> 18) | (b[7] << 14)) & 0x1fffff) b11 := int64((b[7] >> 7)) c0 := int64(c[0] & 0x1fffff) c1 := int64(((c[0] >> 21) | (c[1] << 11)) & 0x1fffff) c2 := int64((c[1] >> 10) & 0x1fffff) c3 := int64(((c[1] >> 31) | (c[2] << 1)) & 0x1fffff) c4 := int64(((c[2] >> 20) | (c[3] << 12)) & 0x1fffff) c5 := int64((c[3] >> 9) & 0x1fffff) c6 := int64(((c[3] >> 30) | (c[4] << 2)) & 0x1fffff) c7 := int64(((c[4] >> 19) | (c[5] << 13)) & 0x1fffff) c8 := int64((c[5] >> 8) & 0x1fffff) c9 := int64(((c[5] >> 29) | (c[6] << 3)) & 0x1fffff) c10 := int64(((c[6] >> 18) | (c[7] << 14)) & 0x1fffff) c11 := int64((c[7] >> 7)) return s.reduceAfterMul( c0+a0*b0, c1+a0*b1+a1*b0, c2+a0*b2+a1*b1+a2*b0, c3+a0*b3+a1*b2+a2*b1+a3*b0, c4+a0*b4+a1*b3+a2*b2+a3*b1+a4*b0, c5+a0*b5+a1*b4+a2*b3+a3*b2+a4*b1+a5*b0, c6+a0*b6+a1*b5+a2*b4+a3*b3+a4*b2+a5*b1+a6*b0, c7+a0*b7+a1*b6+a2*b5+a3*b4+a4*b3+a5*b2+a6*b1+a7*b0, c8+a0*b8+a1*b7+a2*b6+a3*b5+a4*b4+a5*b3+a6*b2+a7*b1+a8*b0, c9+a0*b9+a1*b8+a2*b7+a3*b6+a4*b5+a5*b4+a6*b3+a7*b2+a8*b1+a9*b0, c10+a0*b10+a1*b9+a2*b8+a3*b7+a4*b6+a5*b5+a6*b4+a7*b3+a8*b2+a9*b1+a10*b0, c11+a0*b11+a1*b10+a2*b9+a3*b8+a4*b7+a5*b6+a6*b5+a7*b4+a8*b3+a9*b2+a10*b1+a11*b0, a1*b11+a2*b10+a3*b9+a4*b8+a5*b7+a6*b6+a7*b5+a8*b4+a9*b3+a10*b2+a11*b1, a2*b11+a3*b10+a4*b9+a5*b8+a6*b7+a7*b6+a8*b5+a9*b4+a10*b3+a11*b2, a3*b11+a4*b10+a5*b9+a6*b8+a7*b7+a8*b6+a9*b5+a10*b4+a11*b3, a4*b11+a5*b10+a6*b9+a7*b8+a8*b7+a9*b6+a10*b5+a11*b4, a5*b11+a6*b10+a7*b9+a8*b8+a9*b7+a10*b6+a11*b5, a6*b11+a7*b10+a8*b9+a9*b8+a10*b7+a11*b6, a7*b11+a8*b10+a9*b9+a10*b8+a11*b7, a8*b11+a9*b10+a10*b9+a11*b8, a9*b11+a10*b10+a11*b9, a10*b11+a11*b10, a11*b11) } // Derive sets s to the half-length scalar derived from the given buffer // using SHA512. Returns s // // Warning: half-length scalars are insecure in almost every application. func (s *Scalar) DeriveShort(buf []byte) *Scalar { h := sha512.Sum512(buf) s[0] = load4u32(h[0:]) s[1] = load4u32(h[4:]) s[2] = load4u32(h[8:]) s[3] = load4u32(h[12:]) s[4] = 0 s[5] = 0 s[6] = 0 s[7] = 0 return s } // Derive sets s to the scalar derived from the given buffer using SHA512 and // Scalar.SetReduced() Returns s. func (s *Scalar) Derive(buf []byte) *Scalar { var sBuf [64]byte h := sha512.Sum512(buf) copy(sBuf[:], h[:]) return s.SetReduced(&sBuf) } // Sets s to t mod l, where t is interpreted little endian. Returns s. func (s *Scalar) SetReduced(t *[64]byte) *Scalar { t0 := 0x1FFFFF & load3(t[:]) t1 := 0x1FFFFF & (load4(t[2:]) >> 5) t2 := 0x1FFFFF & (load3(t[5:]) >> 2) t3 := 0x1FFFFF & (load4(t[7:]) >> 7) t4 := 0x1FFFFF & (load4(t[10:]) >> 4) t5 := 0x1FFFFF & (load3(t[13:]) >> 1) t6 := 0x1FFFFF & (load4(t[15:]) >> 6) t7 := 0x1FFFFF & (load3(t[18:]) >> 3) t8 := 0x1FFFFF & load3(t[21:]) t9 := 0x1FFFFF & (load4(t[23:]) >> 5) t10 := 0x1FFFFF & (load3(t[26:]) >> 2) t11 := 0x1FFFFF & (load4(t[28:]) >> 7) t12 := 0x1FFFFF & (load4(t[31:]) >> 4) t13 := 0x1FFFFF & (load3(t[34:]) >> 1) t14 := 0x1FFFFF & (load4(t[36:]) >> 6) t15 := 0x1FFFFF & (load3(t[39:]) >> 3) t16 := 0x1FFFFF & load3(t[42:]) t17 := 0x1FFFFF & (load4(t[44:]) >> 5) t18 := 0x1FFFFF & (load3(t[47:]) >> 2) t19 := 0x1FFFFF & (load4(t[49:]) >> 7) t20 := 0x1FFFFF & (load4(t[52:]) >> 4) t21 := 0x1FFFFF & (load3(t[55:]) >> 1) t22 := 0x1FFFFF & (load4(t[57:]) >> 6) t23 := (load4(t[60:]) >> 3) t11 += t23 * 666643 t12 += t23 * 470296 t13 += t23 * 654183 t14 -= t23 * 997805 t15 += t23 * 136657 t16 -= t23 * 683901 t23 = 0 t10 += t22 * 666643 t11 += t22 * 470296 t12 += t22 * 654183 t13 -= t22 * 997805 t14 += t22 * 136657 t15 -= t22 * 683901 t22 = 0 t9 += t21 * 666643 t10 += t21 * 470296 t11 += t21 * 654183 t12 -= t21 * 997805 t13 += t21 * 136657 t14 -= t21 * 683901 t21 = 0 t8 += t20 * 666643 t9 += t20 * 470296 t10 += t20 * 654183 t11 -= t20 * 997805 t12 += t20 * 136657 t13 -= t20 * 683901 t20 = 0 t7 += t19 * 666643 t8 += t19 * 470296 t9 += t19 * 654183 t10 -= t19 * 997805 t11 += t19 * 136657 t12 -= t19 * 683901 t19 = 0 t6 += t18 * 666643 t7 += t18 * 470296 t8 += t18 * 654183 t9 -= t18 * 997805 t10 += t18 * 136657 t11 -= t18 * 683901 t18 = 0 var carry [17]int64 carry[6] = (t6 + (1 << 20)) >> 21 t7 += carry[6] t6 -= carry[6] << 21 carry[8] = (t8 + (1 << 20)) >> 21 t9 += carry[8] t8 -= carry[8] << 21 carry[10] = (t10 + (1 << 20)) >> 21 t11 += carry[10] t10 -= carry[10] << 21 carry[12] = (t12 + (1 << 20)) >> 21 t13 += carry[12] t12 -= carry[12] << 21 carry[14] = (t14 + (1 << 20)) >> 21 t15 += carry[14] t14 -= carry[14] << 21 carry[16] = (t16 + (1 << 20)) >> 21 t17 += carry[16] t16 -= carry[16] << 21 carry[7] = (t7 + (1 << 20)) >> 21 t8 += carry[7] t7 -= carry[7] << 21 carry[9] = (t9 + (1 << 20)) >> 21 t10 += carry[9] t9 -= carry[9] << 21 carry[11] = (t11 + (1 << 20)) >> 21 t12 += carry[11] t11 -= carry[11] << 21 carry[13] = (t13 + (1 << 20)) >> 21 t14 += carry[13] t13 -= carry[13] << 21 carry[15] = (t15 + (1 << 20)) >> 21 t16 += carry[15] t15 -= carry[15] << 21 t5 += t17 * 666643 t6 += t17 * 470296 t7 += t17 * 654183 t8 -= t17 * 997805 t9 += t17 * 136657 t10 -= t17 * 683901 t17 = 0 t4 += t16 * 666643 t5 += t16 * 470296 t6 += t16 * 654183 t7 -= t16 * 997805 t8 += t16 * 136657 t9 -= t16 * 683901 t16 = 0 t3 += t15 * 666643 t4 += t15 * 470296 t5 += t15 * 654183 t6 -= t15 * 997805 t7 += t15 * 136657 t8 -= t15 * 683901 t15 = 0 t2 += t14 * 666643 t3 += t14 * 470296 t4 += t14 * 654183 t5 -= t14 * 997805 t6 += t14 * 136657 t7 -= t14 * 683901 t14 = 0 t1 += t13 * 666643 t2 += t13 * 470296 t3 += t13 * 654183 t4 -= t13 * 997805 t5 += t13 * 136657 t6 -= t13 * 683901 t13 = 0 t0 += t12 * 666643 t1 += t12 * 470296 t2 += t12 * 654183 t3 -= t12 * 997805 t4 += t12 * 136657 t5 -= t12 * 683901 t12 = 0 carry[0] = (t0 + (1 << 20)) >> 21 t1 += carry[0] t0 -= carry[0] << 21 carry[2] = (t2 + (1 << 20)) >> 21 t3 += carry[2] t2 -= carry[2] << 21 carry[4] = (t4 + (1 << 20)) >> 21 t5 += carry[4] t4 -= carry[4] << 21 carry[6] = (t6 + (1 << 20)) >> 21 t7 += carry[6] t6 -= carry[6] << 21 carry[8] = (t8 + (1 << 20)) >> 21 t9 += carry[8] t8 -= carry[8] << 21 carry[10] = (t10 + (1 << 20)) >> 21 t11 += carry[10] t10 -= carry[10] << 21 carry[1] = (t1 + (1 << 20)) >> 21 t2 += carry[1] t1 -= carry[1] << 21 carry[3] = (t3 + (1 << 20)) >> 21 t4 += carry[3] t3 -= carry[3] << 21 carry[5] = (t5 + (1 << 20)) >> 21 t6 += carry[5] t5 -= carry[5] << 21 carry[7] = (t7 + (1 << 20)) >> 21 t8 += carry[7] t7 -= carry[7] << 21 carry[9] = (t9 + (1 << 20)) >> 21 t10 += carry[9] t9 -= carry[9] << 21 carry[11] = (t11 + (1 << 20)) >> 21 t12 += carry[11] t11 -= carry[11] << 21 t0 += t12 * 666643 t1 += t12 * 470296 t2 += t12 * 654183 t3 -= t12 * 997805 t4 += t12 * 136657 t5 -= t12 * 683901 t12 = 0 carry[0] = t0 >> 21 t1 += carry[0] t0 -= carry[0] << 21 carry[1] = t1 >> 21 t2 += carry[1] t1 -= carry[1] << 21 carry[2] = t2 >> 21 t3 += carry[2] t2 -= carry[2] << 21 carry[3] = t3 >> 21 t4 += carry[3] t3 -= carry[3] << 21 carry[4] = t4 >> 21 t5 += carry[4] t4 -= carry[4] << 21 carry[5] = t5 >> 21 t6 += carry[5] t5 -= carry[5] << 21 carry[6] = t6 >> 21 t7 += carry[6] t6 -= carry[6] << 21 carry[7] = t7 >> 21 t8 += carry[7] t7 -= carry[7] << 21 carry[8] = t8 >> 21 t9 += carry[8] t8 -= carry[8] << 21 carry[9] = t9 >> 21 t10 += carry[9] t9 -= carry[9] << 21 carry[10] = t10 >> 21 t11 += carry[10] t10 -= carry[10] << 21 carry[11] = t11 >> 21 t12 += carry[11] t11 -= carry[11] << 21 t0 += t12 * 666643 t1 += t12 * 470296 t2 += t12 * 654183 t3 -= t12 * 997805 t4 += t12 * 136657 t5 -= t12 * 683901 t12 = 0 carry[0] = t0 >> 21 t1 += carry[0] t0 -= carry[0] << 21 carry[1] = t1 >> 21 t2 += carry[1] t1 -= carry[1] << 21 carry[2] = t2 >> 21 t3 += carry[2] t2 -= carry[2] << 21 carry[3] = t3 >> 21 t4 += carry[3] t3 -= carry[3] << 21 carry[4] = t4 >> 21 t5 += carry[4] t4 -= carry[4] << 21 carry[5] = t5 >> 21 t6 += carry[5] t5 -= carry[5] << 21 carry[6] = t6 >> 21 t7 += carry[6] t6 -= carry[6] << 21 carry[7] = t7 >> 21 t8 += carry[7] t7 -= carry[7] << 21 carry[8] = t8 >> 21 t9 += carry[8] t8 -= carry[8] << 21 carry[9] = t9 >> 21 t10 += carry[9] t9 -= carry[9] << 21 carry[10] = t10 >> 21 t11 += carry[10] t10 -= carry[10] << 21 s[0] = uint32(t0) | uint32(t1<<21) s[1] = uint32(t1>>11) | uint32(t2<<10) | uint32(t3<<31) s[2] = uint32(t3>>1) | uint32(t4<<20) s[3] = uint32(t4>>12) | uint32(t5<<9) | uint32(t6<<30) s[4] = uint32(t6>>2) | uint32(t7<<19) s[5] = uint32(t7>>13) | uint32(t8<<8) | uint32(t9<<29) s[6] = uint32(t9>>3) | uint32(t10<<18) s[7] = uint32(t10>>14) | uint32(t11<<7) return s } // Sets s to a random scalar. Returns s. func (s *Scalar) Rand() *Scalar { var buf [64]byte if _, err := rand.Read(buf[:]); err != nil { panic(err) } return s.SetReduced(&buf) } // Sets s to a*a. Returns s. func (s *Scalar) Square(a *Scalar) *Scalar { a0 := int64(a[0] & 0x1fffff) a1 := int64(((a[0] >> 21) | (a[1] << 11)) & 0x1fffff) a2 := int64((a[1] >> 10) & 0x1fffff) a3 := int64(((a[1] >> 31) | (a[2] << 1)) & 0x1fffff) a4 := int64(((a[2] >> 20) | (a[3] << 12)) & 0x1fffff) a5 := int64((a[3] >> 9) & 0x1fffff) a6 := int64(((a[3] >> 30) | (a[4] << 2)) & 0x1fffff) a7 := int64(((a[4] >> 19) | (a[5] << 13)) & 0x1fffff) a8 := int64((a[5] >> 8) & 0x1fffff) a9 := int64(((a[5] >> 29) | (a[6] << 3)) & 0x1fffff) a10 := int64(((a[6] >> 18) | (a[7] << 14)) & 0x1fffff) a11 := int64((a[7] >> 7)) return s.reduceAfterMul( a0*a0, 2*a0*a1, 2*a0*a2+a1*a1, 2*(a0*a3+a1*a2), 2*(a0*a4+a1*a3)+a2*a2, 2*(a0*a5+a1*a4+a2*a3), 2*(a0*a6+a1*a5+a2*a4)+a3*a3, 2*(a0*a7+a1*a6+a2*a5+a3*a4), 2*(a0*a8+a1*a7+a2*a6+a3*a5)+a4*a4, 2*(a0*a9+a1*a8+a2*a7+a3*a6+a4*a5), 2*(a0*a10+a1*a9+a2*a8+a3*a7+a4*a6)+a5*a5, 2*(a0*a11+a1*a10+a2*a9+a3*a8+a4*a7+a5*a6), 2*(a1*a11+a2*a10+a3*a9+a4*a8+a5*a7)+a6*a6, 2*(a2*a11+a3*a10+a4*a9+a5*a8+a6*a7), 2*(a3*a11+a4*a10+a5*a9+a6*a8)+a7*a7, 2*(a4*a11+a5*a10+a6*a9+a7*a8), 2*(a5*a11+a6*a10+a7*a9)+a8*a8, 2*(a6*a11+a7*a10+a8*a9), 2*(a7*a11+a8*a10)+a9*a9, 2*(a8*a11+a9*a10), 2*a9*a11+a10*a10, 2*a10*a11, a11*a11) } // Sets s to a * b. Returns s. func (s *Scalar) Mul(a, b *Scalar) *Scalar { a0 := int64(a[0] & 0x1fffff) a1 := int64(((a[0] >> 21) | (a[1] << 11)) & 0x1fffff) a2 := int64((a[1] >> 10) & 0x1fffff) a3 := int64(((a[1] >> 31) | (a[2] << 1)) & 0x1fffff) a4 := int64(((a[2] >> 20) | (a[3] << 12)) & 0x1fffff) a5 := int64((a[3] >> 9) & 0x1fffff) a6 := int64(((a[3] >> 30) | (a[4] << 2)) & 0x1fffff) a7 := int64(((a[4] >> 19) | (a[5] << 13)) & 0x1fffff) a8 := int64((a[5] >> 8) & 0x1fffff) a9 := int64(((a[5] >> 29) | (a[6] << 3)) & 0x1fffff) a10 := int64(((a[6] >> 18) | (a[7] << 14)) & 0x1fffff) a11 := int64((a[7] >> 7)) b0 := int64(b[0] & 0x1fffff) b1 := int64(((b[0] >> 21) | (b[1] << 11)) & 0x1fffff) b2 := int64((b[1] >> 10) & 0x1fffff) b3 := int64(((b[1] >> 31) | (b[2] << 1)) & 0x1fffff) b4 := int64(((b[2] >> 20) | (b[3] << 12)) & 0x1fffff) b5 := int64((b[3] >> 9) & 0x1fffff) b6 := int64(((b[3] >> 30) | (b[4] << 2)) & 0x1fffff) b7 := int64(((b[4] >> 19) | (b[5] << 13)) & 0x1fffff) b8 := int64((b[5] >> 8) & 0x1fffff) b9 := int64(((b[5] >> 29) | (b[6] << 3)) & 0x1fffff) b10 := int64(((b[6] >> 18) | (b[7] << 14)) & 0x1fffff) b11 := int64((b[7] >> 7)) return s.reduceAfterMul( a0*b0, a0*b1+a1*b0, a0*b2+a1*b1+a2*b0, a0*b3+a1*b2+a2*b1+a3*b0, a0*b4+a1*b3+a2*b2+a3*b1+a4*b0, a0*b5+a1*b4+a2*b3+a3*b2+a4*b1+a5*b0, a0*b6+a1*b5+a2*b4+a3*b3+a4*b2+a5*b1+a6*b0, a0*b7+a1*b6+a2*b5+a3*b4+a4*b3+a5*b2+a6*b1+a7*b0, a0*b8+a1*b7+a2*b6+a3*b5+a4*b4+a5*b3+a6*b2+a7*b1+a8*b0, a0*b9+a1*b8+a2*b7+a3*b6+a4*b5+a5*b4+a6*b3+a7*b2+a8*b1+a9*b0, a0*b10+a1*b9+a2*b8+a3*b7+a4*b6+a5*b5+a6*b4+a7*b3+a8*b2+a9*b1+a10*b0, a0*b11+a1*b10+a2*b9+a3*b8+a4*b7+a5*b6+a6*b5+a7*b4+a8*b3+a9*b2+a10*b1+a11*b0, a1*b11+a2*b10+a3*b9+a4*b8+a5*b7+a6*b6+a7*b5+a8*b4+a9*b3+a10*b2+a11*b1, a2*b11+a3*b10+a4*b9+a5*b8+a6*b7+a7*b6+a8*b5+a9*b4+a10*b3+a11*b2, a3*b11+a4*b10+a5*b9+a6*b8+a7*b7+a8*b6+a9*b5+a10*b4+a11*b3, a4*b11+a5*b10+a6*b9+a7*b8+a8*b7+a9*b6+a10*b5+a11*b4, a5*b11+a6*b10+a7*b9+a8*b8+a9*b7+a10*b6+a11*b5, a6*b11+a7*b10+a8*b9+a9*b8+a10*b7+a11*b6, a7*b11+a8*b10+a9*b9+a10*b8+a11*b7, a8*b11+a9*b10+a10*b9+a11*b8, a9*b11+a10*b10+a11*b9, a10*b11+a11*b10, a11*b11) } // Sets s to 1/t. Returns s. func (s *Scalar) Inverse(t *Scalar) *Scalar { var t0, t1, t2, t3, t4, t5 Scalar t1.Square(t) t2.Mul(t, &t1) t0.Mul(&t1, &t2) t1.Square(&t0) t3.Square(&t1) t1.Mul(&t2, &t3) t2.Square(&t1) t3.Mul(&t0, &t2) t0.Square(&t3) t2.Mul(&t1, &t0) t0.Square(&t2) t1.Mul(&t2, &t0) t0.Square(&t1) t1.Mul(&t3, &t0) t0.Square(&t1) t3.Square(&t0) t0.Mul(&t1, &t3) t3.Mul(&t2, &t0) t0.Square(&t3) t2.Mul(&t1, &t0) t0.Square(&t2) t1.Mul(&t3, &t0) t0.Square(&t1) t3.Mul(&t1, &t0) t0.Mul(&t2, &t3) t2.Mul(&t1, &t0) t1.Square(&t2) t3.Square(&t1) t4.Square(&t3) t3.Mul(&t1, &t4) t1.Mul(&t0, &t3) t0.Mul(&t2, &t1) t2.Mul(&t1, &t0) t1.Square(&t2) t3.Square(&t1) t1.Mul(&t0, &t3) t0.Square(&t1) t3.Square(&t0) t0.Mul(&t1, &t3) t3.Mul(&t2, &t0) t0.Square(&t3) t2.Mul(&t1, &t0) t0.Square(&t2) t1.Square(&t0) t0.Mul(&t2, &t1) t1.Mul(&t3, &t0) t0.Square(&t1) t3.Square(&t0) t0.Square(&t3) t3.Square(&t0) t0.Square(&t3) t3.Square(&t0) t0.Mul(&t1, &t3) t3.Mul(&t2, &t0) t0.Square(&t3) t2.Mul(&t1, &t0) t0.Square(&t2) t1.Mul(&t2, &t0) t0.Square(&t1) t4.Mul(&t2, &t0) t0.Square(&t4) t4.Square(&t0) t0.Mul(&t1, &t4) t1.Mul(&t3, &t0) t0.Square(&t1) t3.Mul(&t1, &t0) t0.Square(&t3) t4.Square(&t0) t0.Mul(&t3, &t4) t3.Mul(&t2, &t0) t0.Square(&t3) t2.Square(&t0) t0.Square(&t2) t2.Mul(&t1, &t0) t0.Square(&t2) t1.Mul(&t3, &t0) t0.Mul(&t2, &t1) t2.Mul(&t1, &t0) t1.Square(&t2) t3.Square(&t1) t1.Mul(&t0, &t3) t0.Square(&t1) t3.Mul(&t2, &t0) t0.Mul(&t1, &t3) t1.Square(&t0) t2.Square(&t1) t1.Mul(&t0, &t2) t2.Mul(&t3, &t1) t1.Mul(&t0, &t2) t0.Mul(&t2, &t1) t2.Square(&t0) t3.Mul(&t0, &t2) t2.Square(&t3) t3.Mul(&t1, &t2) t1.Mul(&t0, &t3) t0.Square(&t1) t2.Mul(&t1, &t0) t0.Square(&t2) t4.Mul(&t2, &t0) t0.Square(&t4) t4.Square(&t0) t5.Square(&t4) t4.Square(&t5) t5.Square(&t4) t4.Square(&t5) t5.Mul(&t0, &t4) t0.Mul(&t2, &t5) t2.Mul(&t3, &t0) t0.Mul(&t1, &t2) t1.Square(&t0) t3.Mul(&t0, &t1) t1.Square(&t3) t4.Mul(&t0, &t1) t1.Square(&t4) t4.Square(&t1) t1.Square(&t4) t4.Mul(&t3, &t1) t1.Mul(&t2, &t4) t2.Square(&t1) t3.Square(&t2) t4.Square(&t3) t3.Mul(&t2, &t4) t2.Mul(&t1, &t3) t3.Mul(&t0, &t2) t0.Square(&t3) t2.Square(&t0) t0.Square(&t2) t2.Mul(&t1, &t0) t0.Mul(&t3, &t2) t1.Square(&t0) t3.Square(&t1) t4.Mul(&t1, &t3) t3.Square(&t4) t4.Square(&t3) t3.Mul(&t1, &t4) t1.Mul(&t2, &t3) t2.Square(&t1) t3.Square(&t2) t2.Mul(&t0, &t3) t0.Square(&t2) t3.Mul(&t1, &t0) t0.Square(&t3) t1.Mul(&t2, &t0) t0.Mul(&t3, &t1) t2.Square(&t0) t3.Square(&t2) t2.Square(&t3) t3.Square(&t2) t2.Mul(&t1, &t3) t1.Mul(&t0, &t2) t0.Square(&t1) t3.Square(&t0) t4.Square(&t3) t3.Mul(&t0, &t4) t0.Mul(&t1, &t3) t3.Mul(&t2, &t0) t0.Square(&t3) t2.Square(&t0) t0.Mul(&t1, &t2) t1.Square(&t0) t2.Mul(&t3, &t1) t1.Mul(&t0, &t2) t0.Square(&t1) t3.Mul(&t2, &t0) t0.Square(&t3) t2.Square(&t0) t0.Mul(&t1, &t2) t1.Mul(&t3, &t0) t2.Square(&t1) t3.Mul(&t0, &t2) t0.Mul(&t1, &t3) t1.Square(&t0) t2.Square(&t1) t4.Square(&t2) t2.Mul(&t1, &t4) t4.Square(&t2) t2.Square(&t4) t4.Square(&t2) t2.Mul(&t1, &t4) t1.Mul(&t3, &t2) t2.Square(&t1) t3.Square(&t2) t2.Mul(&t1, &t3) t3.Square(&t2) t2.Square(&t3) t3.Mul(&t1, &t2) t2.Mul(&t0, &t3) t0.Square(&t2) t3.Mul(&t2, &t0) t0.Square(&t3) t4.Square(&t0) t0.Mul(&t3, &t4) t3.Mul(&t1, &t0) t0.Square(&t3) t1.Mul(&t3, &t0) t0.Mul(&t2, &t1) for i := 0; i < 126; i++ { t0.Square(&t0) } s.Mul(&t3, &t0) return s } // IsNonZeroI returns 1 if s is non-zero and 0 otherwise. func (s *Scalar) IsNonZeroI() int32 { ret := s[0] | s[1] | s[2] | s[3] | s[4] | s[5] | s[6] | s[7] ret |= ret >> 16 ret |= ret >> 8 ret |= ret >> 4 ret |= ret >> 2 ret |= ret >> 1 return int32(ret & 1) } // EqualsI returns 1 if s is equal to a, otherwise 0. func (s *Scalar) EqualsI(a *Scalar) int32 { var b Scalar return 1 - b.Sub(s, a).IsNonZeroI() } // Equals returns whether s is equal to a. func (s *Scalar) Equals(a *Scalar) bool { var b Scalar return b.Sub(s, a).IsNonZeroI() == 0 } // Implements encoding/BinaryUnmarshaler. Use SetBytes, if convenient, instead. func (s *Scalar) UnmarshalBinary(data []byte) error { if len(data) != 32 { return fmt.Errorf("ristretto.Scalar should be 32 bytes; not %d", len(data)) } var buf [32]byte copy(buf[:], data) s.SetBytes(&buf) return nil } // Implements encoding/BinaryMarshaler. Use BytesInto, if convenient, instead. func (s *Scalar) MarshalBinary() ([]byte, error) { var buf [32]byte s.BytesInto(&buf) return buf[:], nil } func (s *Scalar) MarshalText() ([]byte, error) { enc := base64.RawURLEncoding var buf [32]byte s.BytesInto(&buf) ret := make([]byte, enc.EncodedLen(32)) enc.Encode(ret, buf[:]) return ret, nil } func (s *Scalar) UnmarshalText(txt []byte) error { enc := base64.RawURLEncoding var buf [32]byte n, err := enc.Decode(buf[:], txt) if err != nil { return err } if n != 32 { return fmt.Errorf("ristretto.Scalar should be 32 bytes; not %d", n) } s.SetBytes(&buf) return nil } func (s Scalar) String() string { text, _ := s.MarshalText() return string(text) } // Interprets a 3-byte unsigned little endian byte-slice as int64 func load3(in []byte) int64 { var r int64 r = int64(in[0]) r |= int64(in[1]) << 8 r |= int64(in[2]) << 16 return r } // Interprets a 4-byte unsigned little endian byte-slice as int64 func load4(in []byte) int64 { var r int64 r = int64(in[0]) r |= int64(in[1]) << 8 r |= int64(in[2]) << 16 r |= int64(in[3]) << 24 return r } // Interprets a 4-byte unsigned little endian byte-slice as uint32 func load4u32(in []byte) uint32 { return (uint32(in[0]) | (uint32(in[1]) << 8) | (uint32(in[2]) << 16) | (uint32(in[3]) << 24)) } // Sets s to s0 + s1 * 2^21 + s2 * 2^(21*2) + ... + s22 * s^(21*22) modulo l. // Requires |s_i| to be sufficiently small (< ~2^42). Used in Mul, Square, etc. func (s *Scalar) reduceAfterMul(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22 int64) *Scalar { var s23 int64 = 0 var carry [23]int64 carry[0] = (s0 + (1 << 20)) >> 21 s1 += carry[0] s0 -= carry[0] << 21 carry[2] = (s2 + (1 << 20)) >> 21 s3 += carry[2] s2 -= carry[2] << 21 carry[4] = (s4 + (1 << 20)) >> 21 s5 += carry[4] s4 -= carry[4] << 21 carry[6] = (s6 + (1 << 20)) >> 21 s7 += carry[6] s6 -= carry[6] << 21 carry[8] = (s8 + (1 << 20)) >> 21 s9 += carry[8] s8 -= carry[8] << 21 carry[10] = (s10 + (1 << 20)) >> 21 s11 += carry[10] s10 -= carry[10] << 21 carry[12] = (s12 + (1 << 20)) >> 21 s13 += carry[12] s12 -= carry[12] << 21 carry[14] = (s14 + (1 << 20)) >> 21 s15 += carry[14] s14 -= carry[14] << 21 carry[16] = (s16 + (1 << 20)) >> 21 s17 += carry[16] s16 -= carry[16] << 21 carry[18] = (s18 + (1 << 20)) >> 21 s19 += carry[18] s18 -= carry[18] << 21 carry[20] = (s20 + (1 << 20)) >> 21 s21 += carry[20] s20 -= carry[20] << 21 carry[22] = (s22 + (1 << 20)) >> 21 s23 += carry[22] s22 -= carry[22] << 21 carry[1] = (s1 + (1 << 20)) >> 21 s2 += carry[1] s1 -= carry[1] << 21 carry[3] = (s3 + (1 << 20)) >> 21 s4 += carry[3] s3 -= carry[3] << 21 carry[5] = (s5 + (1 << 20)) >> 21 s6 += carry[5] s5 -= carry[5] << 21 carry[7] = (s7 + (1 << 20)) >> 21 s8 += carry[7] s7 -= carry[7] << 21 carry[9] = (s9 + (1 << 20)) >> 21 s10 += carry[9] s9 -= carry[9] << 21 carry[11] = (s11 + (1 << 20)) >> 21 s12 += carry[11] s11 -= carry[11] << 21 carry[13] = (s13 + (1 << 20)) >> 21 s14 += carry[13] s13 -= carry[13] << 21 carry[15] = (s15 + (1 << 20)) >> 21 s16 += carry[15] s15 -= carry[15] << 21 carry[17] = (s17 + (1 << 20)) >> 21 s18 += carry[17] s17 -= carry[17] << 21 carry[19] = (s19 + (1 << 20)) >> 21 s20 += carry[19] s19 -= carry[19] << 21 carry[21] = (s21 + (1 << 20)) >> 21 s22 += carry[21] s21 -= carry[21] << 21 s11 += s23 * 666643 s12 += s23 * 470296 s13 += s23 * 654183 s14 -= s23 * 997805 s15 += s23 * 136657 s16 -= s23 * 683901 s23 = 0 s10 += s22 * 666643 s11 += s22 * 470296 s12 += s22 * 654183 s13 -= s22 * 997805 s14 += s22 * 136657 s15 -= s22 * 683901 s22 = 0 s9 += s21 * 666643 s10 += s21 * 470296 s11 += s21 * 654183 s12 -= s21 * 997805 s13 += s21 * 136657 s14 -= s21 * 683901 s21 = 0 s8 += s20 * 666643 s9 += s20 * 470296 s10 += s20 * 654183 s11 -= s20 * 997805 s12 += s20 * 136657 s13 -= s20 * 683901 s20 = 0 s7 += s19 * 666643 s8 += s19 * 470296 s9 += s19 * 654183 s10 -= s19 * 997805 s11 += s19 * 136657 s12 -= s19 * 683901 s19 = 0 s6 += s18 * 666643 s7 += s18 * 470296 s8 += s18 * 654183 s9 -= s18 * 997805 s10 += s18 * 136657 s11 -= s18 * 683901 s18 = 0 carry[6] = (s6 + (1 << 20)) >> 21 s7 += carry[6] s6 -= carry[6] << 21 carry[8] = (s8 + (1 << 20)) >> 21 s9 += carry[8] s8 -= carry[8] << 21 carry[10] = (s10 + (1 << 20)) >> 21 s11 += carry[10] s10 -= carry[10] << 21 carry[12] = (s12 + (1 << 20)) >> 21 s13 += carry[12] s12 -= carry[12] << 21 carry[14] = (s14 + (1 << 20)) >> 21 s15 += carry[14] s14 -= carry[14] << 21 carry[16] = (s16 + (1 << 20)) >> 21 s17 += carry[16] s16 -= carry[16] << 21 carry[7] = (s7 + (1 << 20)) >> 21 s8 += carry[7] s7 -= carry[7] << 21 carry[9] = (s9 + (1 << 20)) >> 21 s10 += carry[9] s9 -= carry[9] << 21 carry[11] = (s11 + (1 << 20)) >> 21 s12 += carry[11] s11 -= carry[11] << 21 carry[13] = (s13 + (1 << 20)) >> 21 s14 += carry[13] s13 -= carry[13] << 21 carry[15] = (s15 + (1 << 20)) >> 21 s16 += carry[15] s15 -= carry[15] << 21 s5 += s17 * 666643 s6 += s17 * 470296 s7 += s17 * 654183 s8 -= s17 * 997805 s9 += s17 * 136657 s10 -= s17 * 683901 s17 = 0 s4 += s16 * 666643 s5 += s16 * 470296 s6 += s16 * 654183 s7 -= s16 * 997805 s8 += s16 * 136657 s9 -= s16 * 683901 s16 = 0 s3 += s15 * 666643 s4 += s15 * 470296 s5 += s15 * 654183 s6 -= s15 * 997805 s7 += s15 * 136657 s8 -= s15 * 683901 s15 = 0 s2 += s14 * 666643 s3 += s14 * 470296 s4 += s14 * 654183 s5 -= s14 * 997805 s6 += s14 * 136657 s7 -= s14 * 683901 s14 = 0 s1 += s13 * 666643 s2 += s13 * 470296 s3 += s13 * 654183 s4 -= s13 * 997805 s5 += s13 * 136657 s6 -= s13 * 683901 s13 = 0 s0 += s12 * 666643 s1 += s12 * 470296 s2 += s12 * 654183 s3 -= s12 * 997805 s4 += s12 * 136657 s5 -= s12 * 683901 s12 = 0 carry[0] = (s0 + (1 << 20)) >> 21 s1 += carry[0] s0 -= carry[0] << 21 carry[2] = (s2 + (1 << 20)) >> 21 s3 += carry[2] s2 -= carry[2] << 21 carry[4] = (s4 + (1 << 20)) >> 21 s5 += carry[4] s4 -= carry[4] << 21 carry[6] = (s6 + (1 << 20)) >> 21 s7 += carry[6] s6 -= carry[6] << 21 carry[8] = (s8 + (1 << 20)) >> 21 s9 += carry[8] s8 -= carry[8] << 21 carry[10] = (s10 + (1 << 20)) >> 21 s11 += carry[10] s10 -= carry[10] << 21 carry[1] = (s1 + (1 << 20)) >> 21 s2 += carry[1] s1 -= carry[1] << 21 carry[3] = (s3 + (1 << 20)) >> 21 s4 += carry[3] s3 -= carry[3] << 21 carry[5] = (s5 + (1 << 20)) >> 21 s6 += carry[5] s5 -= carry[5] << 21 carry[7] = (s7 + (1 << 20)) >> 21 s8 += carry[7] s7 -= carry[7] << 21 carry[9] = (s9 + (1 << 20)) >> 21 s10 += carry[9] s9 -= carry[9] << 21 carry[11] = (s11 + (1 << 20)) >> 21 s12 += carry[11] s11 -= carry[11] << 21 s0 += s12 * 666643 s1 += s12 * 470296 s2 += s12 * 654183 s3 -= s12 * 997805 s4 += s12 * 136657 s5 -= s12 * 683901 s12 = 0 carry[0] = s0 >> 21 s1 += carry[0] s0 -= carry[0] << 21 carry[1] = s1 >> 21 s2 += carry[1] s1 -= carry[1] << 21 carry[2] = s2 >> 21 s3 += carry[2] s2 -= carry[2] << 21 carry[3] = s3 >> 21 s4 += carry[3] s3 -= carry[3] << 21 carry[4] = s4 >> 21 s5 += carry[4] s4 -= carry[4] << 21 carry[5] = s5 >> 21 s6 += carry[5] s5 -= carry[5] << 21 carry[6] = s6 >> 21 s7 += carry[6] s6 -= carry[6] << 21 carry[7] = s7 >> 21 s8 += carry[7] s7 -= carry[7] << 21 carry[8] = s8 >> 21 s9 += carry[8] s8 -= carry[8] << 21 carry[9] = s9 >> 21 s10 += carry[9] s9 -= carry[9] << 21 carry[10] = s10 >> 21 s11 += carry[10] s10 -= carry[10] << 21 carry[11] = s11 >> 21 s12 += carry[11] s11 -= carry[11] << 21 s0 += s12 * 666643 s1 += s12 * 470296 s2 += s12 * 654183 s3 -= s12 * 997805 s4 += s12 * 136657 s5 -= s12 * 683901 s12 = 0 carry[0] = s0 >> 21 s1 += carry[0] s0 -= carry[0] << 21 carry[1] = s1 >> 21 s2 += carry[1] s1 -= carry[1] << 21 carry[2] = s2 >> 21 s3 += carry[2] s2 -= carry[2] << 21 carry[3] = s3 >> 21 s4 += carry[3] s3 -= carry[3] << 21 carry[4] = s4 >> 21 s5 += carry[4] s4 -= carry[4] << 21 carry[5] = s5 >> 21 s6 += carry[5] s5 -= carry[5] << 21 carry[6] = s6 >> 21 s7 += carry[6] s6 -= carry[6] << 21 carry[7] = s7 >> 21 s8 += carry[7] s7 -= carry[7] << 21 carry[8] = s8 >> 21 s9 += carry[8] s8 -= carry[8] << 21 carry[9] = s9 >> 21 s10 += carry[9] s9 -= carry[9] << 21 carry[10] = s10 >> 21 s11 += carry[10] s10 -= carry[10] << 21 s[0] = uint32(s0) | uint32(s1<<21) s[1] = uint32(s1>>11) | uint32(s2<<10) | uint32(s3<<31) s[2] = uint32(s3>>1) | uint32(s4<<20) s[3] = uint32(s4>>12) | uint32(s5<<9) | uint32(s6<<30) s[4] = uint32(s6>>2) | uint32(s7<<19) s[5] = uint32(s7>>13) | uint32(s8<<8) | uint32(s9<<29) s[6] = uint32(s9>>3) | uint32(s10<<18) s[7] = uint32(s10>>14) | uint32(s11<<7) return s } // Set s to t if b=1 in constant-time. b must be either 0 or 1. func (s *Scalar) ConditionalSet(t *Scalar, b int32) { m := uint32(-b) s[0] ^= m & (s[0] ^ t[0]) s[1] ^= m & (s[1] ^ t[1]) s[2] ^= m & (s[2] ^ t[2]) s[3] ^= m & (s[3] ^ t[3]) s[4] ^= m & (s[4] ^ t[4]) s[5] ^= m & (s[5] ^ t[5]) s[6] ^= m & (s[6] ^ t[6]) s[7] ^= m & (s[7] ^ t[7]) } go-ristretto-1.2.3/scalar_test.go000066400000000000000000000170161440464505300170240ustar00rootroot00000000000000package ristretto_test import ( "encoding/base64" "encoding/hex" "math/big" "math/rand" "os" "testing" "github.com/bwesterb/go-ristretto" ) var biL big.Int var rnd *rand.Rand func TestScPacking(t *testing.T) { var bi big.Int var s, s2 ristretto.Scalar var buf [32]byte for i := 0; i < 100; i++ { bi.Rand(rnd, &biL) s.SetBigInt(&bi) s.BytesInto(&buf) s2.SetBytes(&buf) if s.BigInt().Cmp(s2.BigInt()) != 0 { t.Fatalf("Unpack o Pack != id (%v != %v)", &bi, s2.BigInt()) } } } func TestScBigIntPacking(t *testing.T) { var bi big.Int var s ristretto.Scalar for i := 0; i < 100; i++ { bi.Rand(rnd, &biL) s.SetBigInt(&bi) if s.BigInt().Cmp(&bi) != 0 { t.Fatalf("BigInt o SetBigInt != id (%v != %v)", &bi, s.BigInt()) } } } func TestScSub(t *testing.T) { var bi1, bi2, bi3 big.Int var s1, s2, s3 ristretto.Scalar for i := 0; i < 1000; i++ { bi1.Rand(rnd, &biL) bi2.Rand(rnd, &biL) bi3.Sub(&bi1, &bi2) bi3.Mod(&bi3, &biL) s1.SetBigInt(&bi1) s2.SetBigInt(&bi2) if s3.Sub(&s1, &s2).BigInt().Cmp(&bi3) != 0 { t.Fatalf("%v - %v = %v != %v", &bi1, &bi2, &bi3, s3.BigInt()) } } } func TestScAdd(t *testing.T) { var bi1, bi2, bi3 big.Int var s1, s2, s3 ristretto.Scalar for i := 0; i < 1000; i++ { bi1.Rand(rnd, &biL) bi2.Rand(rnd, &biL) bi3.Add(&bi1, &bi2) bi3.Mod(&bi3, &biL) s1.SetBigInt(&bi1) s2.SetBigInt(&bi2) if s3.Add(&s1, &s2).BigInt().Cmp(&bi3) != 0 { t.Fatalf("%v + %v = %v != %v", &bi1, &bi2, &bi3, s3.BigInt()) } } } func TestScMul(t *testing.T) { var bi1, bi2, bi3 big.Int var s1, s2, s3 ristretto.Scalar for i := 0; i < 1000; i++ { bi1.Rand(rnd, &biL) bi2.Rand(rnd, &biL) bi3.Mul(&bi1, &bi2) bi3.Mod(&bi3, &biL) s1.SetBigInt(&bi1) s2.SetBigInt(&bi2) if s3.Mul(&s1, &s2).BigInt().Cmp(&bi3) != 0 { t.Fatalf("%v * %v = %v != %v", &bi1, &bi2, &bi3, s3.BigInt()) } } } func TestScSquare(t *testing.T) { var bi1, bi2 big.Int var s1, s2 ristretto.Scalar for i := 0; i < 1000; i++ { bi1.Rand(rnd, &biL) bi2.Mul(&bi1, &bi1) bi2.Mod(&bi2, &biL) s1.SetBigInt(&bi1) if s2.Square(&s1).BigInt().Cmp(&bi2) != 0 { t.Fatalf("%v^2 = %v != %v", &bi1, &bi2, s2.BigInt()) } } } func TestScMulSub(t *testing.T) { var bi1, bi2, bi3, bi4 big.Int var s1, s2, s3, s4 ristretto.Scalar for i := 0; i < 1000; i++ { bi1.Rand(rnd, &biL) bi2.Rand(rnd, &biL) bi3.Rand(rnd, &biL) bi4.Mul(&bi1, &bi2) bi4.Sub(&bi4, &bi3) bi4.Mod(&bi4, &biL) s1.SetBigInt(&bi1) s2.SetBigInt(&bi2) s3.SetBigInt(&bi3) if s4.MulSub(&s1, &s2, &s3).BigInt().Cmp(&bi4) != 0 { t.Fatalf("%v * %v - %v = %v != %v", &bi1, &bi2, &bi3, &bi4, s4.BigInt()) } } } func TestScMulAdd(t *testing.T) { var bi1, bi2, bi3, bi4 big.Int var s1, s2, s3, s4 ristretto.Scalar for i := 0; i < 1000; i++ { bi1.Rand(rnd, &biL) bi2.Rand(rnd, &biL) bi3.Rand(rnd, &biL) bi4.Mul(&bi1, &bi2) bi4.Add(&bi4, &bi3) bi4.Mod(&bi4, &biL) s1.SetBigInt(&bi1) s2.SetBigInt(&bi2) s3.SetBigInt(&bi3) if s4.MulAdd(&s1, &s2, &s3).BigInt().Cmp(&bi4) != 0 { t.Fatalf("%v * %v + %v = %v != %v", &bi1, &bi2, &bi3, &bi4, s4.BigInt()) } } } func TestScInverse(t *testing.T) { var bi1, bi2 big.Int var s1, s2 ristretto.Scalar for i := 0; i < 100; i++ { bi1.Rand(rnd, &biL) bi2.ModInverse(&bi1, &biL) s1.SetBigInt(&bi1) if s2.Inverse(&s1).BigInt().Cmp(&bi2) != 0 { t.Fatalf("1/%v = %v != %v", &bi1, &bi2, &s2) } } } func TestScNeg(t *testing.T) { var bi1, bi2 big.Int var s1, s2 ristretto.Scalar for i := 0; i < 1000; i++ { bi1.Rand(rnd, &biL) bi2.Neg(&bi1) bi2.Mod(&bi2, &biL) s1.SetBigInt(&bi1) if s2.Neg(&s1).BigInt().Cmp(&bi2) != 0 { t.Fatalf("-%v = %v != %v", &bi1, &bi2, &s2) } } } func TestScReduced(t *testing.T) { var bi1, bi2, bi512 big.Int var s ristretto.Scalar bi512.SetInt64(1).Lsh(&bi512, 512) for i := 0; i < 100; i++ { var rBuf [64]byte bi1.Rand(rnd, &bi512) bi2.Mod(&bi1, &biL) buf := bi1.Bytes() for j := 0; j < len(buf) && j < 64; j++ { rBuf[len(buf)-j-1] = buf[j] } s.SetReduced(&rBuf) if s.BigInt().Cmp(&bi2) != 0 { t.Fatalf("SetReduced(%v) = %v != %v %v", &bi1, &bi2, s.BigInt(), rBuf) } } } func TestScTextMarshaling(t *testing.T) { var s, s2 ristretto.Scalar for i := 0; i < 100; i++ { s.Rand() text, _ := s.MarshalText() err := s2.UnmarshalText(text) if err != nil { t.Fatalf("%v: UnmarshalText o MarshalText: %v", s, err) } if s.BigInt().Cmp(s2.BigInt()) != 0 { t.Fatalf("%v: UnmarshalText o MarshalText != id", s) } } } func TestScDeriveShort(t *testing.T) { var s ristretto.Scalar for k, v := range map[string]string{ "test1": "b16ed7d24b3ecbd4164dcdad374e08c000000000000000000000000000000000", "ristretto": "27bf1d7100b6a72bd2b2f43babb948b500000000000000000000000000000000", "decaf": "39e5d267455abfce52284ac648d4b97100000000000000000000000000000000", } { v2 := hex.EncodeToString(s.DeriveShort([]byte(k)).Bytes()) if v != v2 { t.Fatalf("DeriveShort(%s) = %s != %s", k, v, v2) } } } func TestScDerive(t *testing.T) { var s ristretto.Scalar for k, v := range map[string]string{ "test1": "f4f2ba0eccc056c32241b5e7f648ffe6bf870773e09104f0fd2c28fbd7fc5402", "ristretto": "a17454b11da0ee4f9aed08190c61781c326a0c59bb449133bacc0c75308db805", "decaf": "8107e19264d3e54e9869de056c90dc245dbc097529c4a5ef0dae42e1f3cd7700", } { v2 := hex.EncodeToString(s.Derive([]byte(k)).Bytes()) if v != v2 { t.Fatalf("Derive(%s) = %s != %s", k, v, v2) } } } func TestScSetUint64(t *testing.T) { var s1, s2 ristretto.Scalar var bi big.Int v := uint64(0x0102030405060708) bi.SetUint64(v) s1.SetUint64(v) s2.SetBigInt(&bi) if !s1.Equals(&s2) { t.Fatal() } } func TestScConditionalSet(t *testing.T) { var s1, s2 ristretto.Scalar for i := 0; i < 1000; i++ { s1.Rand() s2.Rand() s1.ConditionalSet(&s2, 0) if s1.Equals(&s2) { t.Fatal() } s1.ConditionalSet(&s2, 1) if !s1.Equals(&s2) { t.Fatal() } } } func TestIssue14(t *testing.T) { var buf [32]byte var s ristretto.Scalar var p1, p2 ristretto.Point tmp, _ := base64.StdEncoding.DecodeString( "QekHbzmOtwUfRnheuyj1qyt8HN1WPjW4Jy199/2fQQ8=") copy(buf[:], tmp) s.SetBytes(&buf) tmp, _ = base64.StdEncoding.DecodeString( "SqbtfZl5+A1RtHVfzN8HJCLUcC0Bz2kdThR7wRCUbCQ=") copy(buf[:], tmp) if !p1.SetBytes(&buf) { t.Fatal() } p2.ScalarMultBase(&s) if !p1.Equals(&p2) { t.Fatalf("%v*B = %v != %v", s, p2, p1) } } func BenchmarkScDerive(b *testing.B) { var s ristretto.Scalar for n := 0; n < b.N; n++ { s.Derive([]byte("test")) } } func BenchmarkScRand(b *testing.B) { var s ristretto.Scalar for n := 0; n < b.N; n++ { s.Rand() } } func BenchmarkScMul(b *testing.B) { var s, t ristretto.Scalar for n := 0; n < b.N; n++ { s.Mul(&s, &t) } } func BenchmarkScSquare(b *testing.B) { var s ristretto.Scalar for n := 0; n < b.N; n++ { s.Square(&s) } } func BenchmarkScInverse(b *testing.B) { var s ristretto.Scalar for n := 0; n < b.N; n++ { s.Inverse(&s) } } func BenchmarkScMullAdd(b *testing.B) { var s, t, u ristretto.Scalar for n := 0; n < b.N; n++ { s.MulAdd(&s, &t, &u) } } func BenchmarkScMullSub(b *testing.B) { var s, t, u ristretto.Scalar for n := 0; n < b.N; n++ { s.MulSub(&s, &t, &u) } } func BenchmarkScAdd(b *testing.B) { var s, t ristretto.Scalar for n := 0; n < b.N; n++ { s.Add(&s, &t) } } func BenchmarkScSub(b *testing.B) { var s, t ristretto.Scalar for n := 0; n < b.N; n++ { s.Sub(&s, &t) } } func TestMain(m *testing.M) { biL.SetString( "1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", 16) rnd = rand.New(rand.NewSource(37)) os.Exit(m.Run()) }