github.com/consensys/gnark-crypto@v0.14.0/ecc/bls12-381/twistededwards/point.go (about) 1 // Copyright 2020 Consensys Software Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Code generated by consensys/gnark-crypto DO NOT EDIT 16 17 package twistededwards 18 19 import ( 20 "crypto/subtle" 21 "io" 22 "math/big" 23 "math/bits" 24 25 "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" 26 ) 27 28 // PointAffine point on a twisted Edwards curve 29 type PointAffine struct { 30 X, Y fr.Element 31 } 32 33 // PointProj point in projective coordinates 34 type PointProj struct { 35 X, Y, Z fr.Element 36 } 37 38 // PointExtended point in extended coordinates 39 type PointExtended struct { 40 X, Y, Z, T fr.Element 41 } 42 43 const ( 44 //following https://tools.ietf.org/html/rfc8032#section-3.1, 45 // an fr element x is negative if its binary encoding is 46 // lexicographically larger than -x. 47 mCompressedNegative = 0x80 48 mCompressedPositive = 0x00 49 mUnmask = 0x7f 50 51 // size in byte of a compressed point (point.Y --> fr.Element) 52 sizePointCompressed = fr.Bytes 53 ) 54 55 // Bytes returns the compressed point as a byte array 56 // Follows https://tools.ietf.org/html/rfc8032#section-3.1, 57 // as the twisted Edwards implementation is primarily used 58 // for eddsa. 59 func (p *PointAffine) Bytes() [sizePointCompressed]byte { 60 61 var res [sizePointCompressed]byte 62 var mask uint 63 64 y := p.Y.Bytes() 65 66 if p.X.LexicographicallyLargest() { 67 mask = mCompressedNegative 68 } else { 69 mask = mCompressedPositive 70 } 71 // p.Y must be in little endian 72 y[0] |= byte(mask) // msb of y 73 for i, j := 0, sizePointCompressed-1; i < j; i, j = i+1, j-1 { 74 y[i], y[j] = y[j], y[i] 75 } 76 subtle.ConstantTimeCopy(1, res[:], y[:]) 77 return res 78 } 79 80 // Marshal converts p to a byte slice 81 func (p *PointAffine) Marshal() []byte { 82 b := p.Bytes() 83 return b[:] 84 } 85 86 func computeX(y *fr.Element) (x fr.Element) { 87 initOnce.Do(initCurveParams) 88 89 var one, num, den fr.Element 90 one.SetOne() 91 num.Square(y) 92 den.Mul(&num, &curveParams.D) 93 num.Sub(&one, &num) 94 den.Sub(&curveParams.A, &den) 95 x.Div(&num, &den) 96 x.Sqrt(&x) 97 return 98 } 99 100 // SetBytes sets p from buf 101 // len(buf) >= sizePointCompressed 102 // buf contains the Y coordinate masked with a parity bit to recompute the X coordinate 103 // from the curve equation. See Bytes() and https://tools.ietf.org/html/rfc8032#section-3.1 104 // Returns the number of read bytes and an error if the buffer is too short. 105 func (p *PointAffine) SetBytes(buf []byte) (int, error) { 106 107 if len(buf) < sizePointCompressed { 108 return 0, io.ErrShortBuffer 109 } 110 bufCopy := make([]byte, sizePointCompressed) 111 subtle.ConstantTimeCopy(1, bufCopy, buf[:sizePointCompressed]) 112 for i, j := 0, sizePointCompressed-1; i < j; i, j = i+1, j-1 { 113 bufCopy[i], bufCopy[j] = bufCopy[j], bufCopy[i] 114 } 115 isLexicographicallyLargest := (mCompressedNegative&bufCopy[0])>>7 == 1 116 bufCopy[0] &= mUnmask 117 p.Y.SetBytes(bufCopy) 118 p.X = computeX(&p.Y) 119 if isLexicographicallyLargest { 120 if !p.X.LexicographicallyLargest() { 121 p.X.Neg(&p.X) 122 } 123 } else { 124 if p.X.LexicographicallyLargest() { 125 p.X.Neg(&p.X) 126 } 127 } 128 129 return sizePointCompressed, nil 130 } 131 132 // Unmarshal alias to SetBytes() 133 func (p *PointAffine) Unmarshal(b []byte) error { 134 _, err := p.SetBytes(b) 135 return err 136 } 137 138 // Set sets p to p1 and return it 139 func (p *PointAffine) Set(p1 *PointAffine) *PointAffine { 140 p.X.Set(&p1.X) 141 p.Y.Set(&p1.Y) 142 return p 143 } 144 145 // Equal returns true if p=p1 false otherwise 146 func (p *PointAffine) Equal(p1 *PointAffine) bool { 147 return p.X.Equal(&p1.X) && p.Y.Equal(&p1.Y) 148 } 149 150 // IsZero returns true if p=0 false otherwise 151 func (p *PointAffine) IsZero() bool { 152 var one fr.Element 153 one.SetOne() 154 return p.X.IsZero() && p.Y.Equal(&one) 155 } 156 157 // NewPointAffine creates a new instance of PointAffine 158 func NewPointAffine(x, y fr.Element) PointAffine { 159 return PointAffine{x, y} 160 } 161 162 // IsOnCurve checks if a point is on the twisted Edwards curve 163 func (p *PointAffine) IsOnCurve() bool { 164 initOnce.Do(initCurveParams) 165 166 var lhs, rhs, tmp fr.Element 167 168 tmp.Mul(&p.Y, &p.Y) 169 lhs.Mul(&p.X, &p.X) 170 mulByA(&lhs) 171 lhs.Add(&lhs, &tmp) 172 173 tmp.Mul(&p.X, &p.X). 174 Mul(&tmp, &p.Y). 175 Mul(&tmp, &p.Y). 176 Mul(&tmp, &curveParams.D) 177 rhs.SetOne().Add(&rhs, &tmp) 178 179 return lhs.Equal(&rhs) 180 } 181 182 // Neg sets p to -p1 and returns it 183 func (p *PointAffine) Neg(p1 *PointAffine) *PointAffine { 184 p.X.Neg(&p1.X) 185 p.Y = p1.Y 186 return p 187 } 188 189 // Add adds two points (x,y), (u,v) on a twisted Edwards curve with parameters a, d 190 // modifies p 191 func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine { 192 initOnce.Do(initCurveParams) 193 194 var xu, yv, xv, yu, dxyuv, one, denx, deny fr.Element 195 pRes := new(PointAffine) 196 xv.Mul(&p1.X, &p2.Y) 197 yu.Mul(&p1.Y, &p2.X) 198 pRes.X.Add(&xv, &yu) 199 200 xu.Mul(&p1.X, &p2.X) 201 mulByA(&xu) 202 yv.Mul(&p1.Y, &p2.Y) 203 pRes.Y.Sub(&yv, &xu) 204 205 dxyuv.Mul(&xv, &yu).Mul(&dxyuv, &curveParams.D) 206 one.SetOne() 207 denx.Add(&one, &dxyuv) 208 deny.Sub(&one, &dxyuv) 209 210 p.X.Div(&pRes.X, &denx) 211 p.Y.Div(&pRes.Y, &deny) 212 213 return p 214 } 215 216 // Double doubles point (x,y) on a twisted Edwards curve with parameters a, d 217 // modifies p 218 func (p *PointAffine) Double(p1 *PointAffine) *PointAffine { 219 220 p.Set(p1) 221 var xx, yy, xy, denum, two fr.Element 222 223 xx.Square(&p.X) 224 yy.Square(&p.Y) 225 xy.Mul(&p.X, &p.Y) 226 mulByA(&xx) 227 denum.Add(&xx, &yy) 228 229 p.X.Double(&xy).Div(&p.X, &denum) 230 231 two.SetOne().Double(&two) 232 denum.Neg(&denum).Add(&denum, &two) 233 234 p.Y.Sub(&yy, &xx).Div(&p.Y, &denum) 235 236 return p 237 } 238 239 // FromProj sets p in affine from p in projective 240 func (p *PointAffine) FromProj(p1 *PointProj) *PointAffine { 241 var I fr.Element 242 I.Inverse(&p1.Z) 243 p.X.Mul(&p1.X, &I) 244 p.Y.Mul(&p1.Y, &I) 245 return p 246 } 247 248 // FromExtended sets p in affine from p in extended coordinates 249 func (p *PointAffine) FromExtended(p1 *PointExtended) *PointAffine { 250 var I fr.Element 251 I.Inverse(&p1.Z) 252 p.X.Mul(&p1.X, &I) 253 p.Y.Mul(&p1.Y, &I) 254 return p 255 } 256 257 // ScalarMultiplication scalar multiplication of a point 258 // p1 in affine coordinates with a scalar in big.Int 259 func (p *PointAffine) ScalarMultiplication(p1 *PointAffine, scalar *big.Int) *PointAffine { 260 261 var p1Extended, resExtended PointExtended 262 p1Extended.FromAffine(p1) 263 resExtended.ScalarMultiplication(&p1Extended, scalar) 264 p.FromExtended(&resExtended) 265 266 return p 267 } 268 269 // setInfinity sets p to O (0:1) 270 func (p *PointAffine) setInfinity() *PointAffine { 271 p.X.SetZero() 272 p.Y.SetOne() 273 return p 274 } 275 276 //-------- Projective coordinates 277 278 // Set sets p to p1 and return it 279 func (p *PointProj) Set(p1 *PointProj) *PointProj { 280 p.X.Set(&p1.X) 281 p.Y.Set(&p1.Y) 282 p.Z.Set(&p1.Z) 283 return p 284 } 285 286 // setInfinity sets p to O (0:1:1) 287 func (p *PointProj) setInfinity() *PointProj { 288 p.X.SetZero() 289 p.Y.SetOne() 290 p.Z.SetOne() 291 return p 292 } 293 294 // Equal returns true if p=p1 false otherwise 295 // If one point is on the affine chart Z=0 it returns false 296 func (p *PointProj) Equal(p1 *PointProj) bool { 297 // If one point is infinity, the other must also be infinity. 298 if p.Z.IsZero() { 299 return p1.Z.IsZero() 300 } 301 // If the other point is infinity, return false since we can't 302 // the following checks would be incorrect. 303 if p1.Z.IsZero() { 304 return false 305 } 306 307 var lhs, rhs fr.Element 308 lhs.Mul(&p.X, &p1.Z) 309 rhs.Mul(&p1.X, &p.Z) 310 if !lhs.Equal(&rhs) { 311 return false 312 } 313 lhs.Mul(&p.Y, &p1.Z) 314 rhs.Mul(&p1.Y, &p.Z) 315 316 return lhs.Equal(&rhs) 317 } 318 319 // IsZero returns true if p=0 false otherwise 320 func (p *PointProj) IsZero() bool { 321 return p.X.IsZero() && p.Y.Equal(&p.Z) 322 } 323 324 // Neg negates point (x,y) on a twisted Edwards curve with parameters a, d 325 // modifies p 326 func (p *PointProj) Neg(p1 *PointProj) *PointProj { 327 p.X.Neg(&p1.X) 328 p.Y = p1.Y 329 p.Z = p1.Z 330 return p 331 } 332 333 // FromAffine sets p in projective from p in affine 334 func (p *PointProj) FromAffine(p1 *PointAffine) *PointProj { 335 p.X.Set(&p1.X) 336 p.Y.Set(&p1.Y) 337 p.Z.SetOne() 338 return p 339 } 340 341 // MixedAdd adds a point in projective to a point in affine coordinates 342 // cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp 343 func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj { 344 initOnce.Do(initCurveParams) 345 346 var B, C, D, E, F, G, H, I fr.Element 347 B.Square(&p1.Z) 348 C.Mul(&p1.X, &p2.X) 349 D.Mul(&p1.Y, &p2.Y) 350 E.Mul(&curveParams.D, &C).Mul(&E, &D) 351 F.Sub(&B, &E) 352 G.Add(&B, &E) 353 H.Add(&p1.X, &p1.Y) 354 I.Add(&p2.X, &p2.Y) 355 p.X.Mul(&H, &I). 356 Sub(&p.X, &C). 357 Sub(&p.X, &D). 358 Mul(&p.X, &p1.Z). 359 Mul(&p.X, &F) 360 mulByA(&C) 361 p.Y.Sub(&D, &C). 362 Mul(&p.Y, &p1.Z). 363 Mul(&p.Y, &G) 364 p.Z.Mul(&F, &G) 365 366 return p 367 } 368 369 // Double adds points in projective coordinates 370 // cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp 371 func (p *PointProj) Double(p1 *PointProj) *PointProj { 372 373 var B, C, D, E, F, H, J fr.Element 374 375 B.Add(&p1.X, &p1.Y).Square(&B) 376 C.Square(&p1.X) 377 D.Square(&p1.Y) 378 E.Set(&C) 379 mulByA(&E) 380 F.Add(&E, &D) 381 H.Square(&p1.Z) 382 J.Sub(&F, &H).Sub(&J, &H) 383 p.X.Sub(&B, &C). 384 Sub(&p.X, &D). 385 Mul(&p.X, &J) 386 p.Y.Sub(&E, &D).Mul(&p.Y, &F) 387 p.Z.Mul(&F, &J) 388 389 return p 390 } 391 392 // Add adds points in projective coordinates 393 // cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp 394 func (p *PointProj) Add(p1, p2 *PointProj) *PointProj { 395 initOnce.Do(initCurveParams) 396 397 var A, B, C, D, E, F, G, H, I fr.Element 398 A.Mul(&p1.Z, &p2.Z) 399 B.Square(&A) 400 C.Mul(&p1.X, &p2.X) 401 D.Mul(&p1.Y, &p2.Y) 402 E.Mul(&curveParams.D, &C).Mul(&E, &D) 403 F.Sub(&B, &E) 404 G.Add(&B, &E) 405 H.Add(&p1.X, &p1.Y) 406 I.Add(&p2.X, &p2.Y) 407 p.X.Mul(&H, &I). 408 Sub(&p.X, &C). 409 Sub(&p.X, &D). 410 Mul(&p.X, &A). 411 Mul(&p.X, &F) 412 mulByA(&C) 413 C.Neg(&C) 414 p.Y.Add(&D, &C). 415 Mul(&p.Y, &A). 416 Mul(&p.Y, &G) 417 p.Z.Mul(&F, &G) 418 419 return p 420 } 421 422 // scalarMulWindowed scalar multiplication of a point 423 // p1 in projective coordinates with a scalar in big.Int 424 // using the windowed double-and-add method. 425 func (p *PointProj) scalarMulWindowed(p1 *PointProj, scalar *big.Int) *PointProj { 426 var _scalar big.Int 427 _scalar.Set(scalar) 428 p.Set(p1) 429 if _scalar.Sign() == -1 { 430 _scalar.Neg(&_scalar) 431 p.Neg(p) 432 } 433 var resProj PointProj 434 resProj.setInfinity() 435 const wordSize = bits.UintSize 436 sWords := _scalar.Bits() 437 438 for i := len(sWords) - 1; i >= 0; i-- { 439 ithWord := sWords[i] 440 for k := 0; k < wordSize; k++ { 441 resProj.Double(&resProj) 442 kthBit := (ithWord >> (wordSize - 1 - k)) & 1 443 if kthBit == 1 { 444 resProj.Add(&resProj, p) 445 } 446 } 447 } 448 449 p.Set(&resProj) 450 return p 451 } 452 453 // ScalarMultiplication scalar multiplication of a point 454 // p1 in projective coordinates with a scalar in big.Int 455 func (p *PointProj) ScalarMultiplication(p1 *PointProj, scalar *big.Int) *PointProj { 456 return p.scalarMulWindowed(p1, scalar) 457 } 458 459 // ------- Extended coordinates 460 461 // Set sets p to p1 and return it 462 func (p *PointExtended) Set(p1 *PointExtended) *PointExtended { 463 p.X.Set(&p1.X) 464 p.Y.Set(&p1.Y) 465 p.T.Set(&p1.T) 466 p.Z.Set(&p1.Z) 467 return p 468 } 469 470 // IsZero returns true if p=0 false otherwise 471 func (p *PointExtended) IsZero() bool { 472 return p.X.IsZero() && p.Y.Equal(&p.Z) && p.T.IsZero() 473 } 474 475 // Equal returns true if p=p1 false otherwise 476 // If one point is on the affine chart Z=0 it returns false 477 func (p *PointExtended) Equal(p1 *PointExtended) bool { 478 if p.Z.IsZero() || p1.Z.IsZero() { 479 return false 480 } 481 var pAffine, p1Affine PointAffine 482 pAffine.FromExtended(p) 483 p1Affine.FromExtended(p1) 484 return pAffine.Equal(&p1Affine) 485 } 486 487 // Neg negates point (x,y) on a twisted Edwards curve with parameters a, d 488 // modifies p 489 func (p *PointExtended) Neg(p1 *PointExtended) *PointExtended { 490 p.X.Neg(&p1.X) 491 p.Y = p1.Y 492 p.Z = p1.Z 493 p.T.Neg(&p1.T) 494 return p 495 } 496 497 // FromAffine sets p in projective from p in affine 498 func (p *PointExtended) FromAffine(p1 *PointAffine) *PointExtended { 499 p.X.Set(&p1.X) 500 p.Y.Set(&p1.Y) 501 p.Z.SetOne() 502 p.T.Mul(&p1.X, &p1.Y) 503 return p 504 } 505 506 // Add adds points in extended coordinates 507 // See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd 508 func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended { 509 var A, B, C, D, E, F, G, H, tmp fr.Element 510 A.Mul(&p1.X, &p2.X) 511 B.Mul(&p1.Y, &p2.Y) 512 C.Mul(&p1.T, &p2.T).Mul(&C, &curveParams.D) 513 D.Mul(&p1.Z, &p2.Z) 514 tmp.Add(&p1.X, &p1.Y) 515 E.Add(&p2.X, &p2.Y). 516 Mul(&E, &tmp). 517 Sub(&E, &A). 518 Sub(&E, &B) 519 F.Sub(&D, &C) 520 G.Add(&D, &C) 521 H.Set(&A) 522 mulByA(&H) 523 H.Sub(&B, &H) 524 525 p.X.Mul(&E, &F) 526 p.Y.Mul(&G, &H) 527 p.T.Mul(&E, &H) 528 p.Z.Mul(&F, &G) 529 530 return p 531 } 532 533 // MixedAdd adds a point in extended coordinates to a point in affine coordinates 534 // See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd-2 535 func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended { 536 var A, B, C, D, E, F, G, H, tmp fr.Element 537 538 A.Mul(&p2.X, &p1.Z) 539 B.Mul(&p2.Y, &p1.Z) 540 541 if p1.X.Equal(&A) && p1.Y.Equal(&B) { 542 p.MixedDouble(p1) 543 return p 544 } 545 546 A.Mul(&p1.X, &p2.X) 547 B.Mul(&p1.Y, &p2.Y) 548 C.Mul(&p1.Z, &p2.X). 549 Mul(&C, &p2.Y) 550 D.Set(&p1.T) 551 E.Add(&D, &C) 552 tmp.Sub(&p1.X, &p1.Y) 553 F.Add(&p2.X, &p2.Y). 554 Mul(&F, &tmp). 555 Add(&F, &B). 556 Sub(&F, &A) 557 G.Set(&A) 558 mulByA(&G) 559 G.Add(&G, &B) 560 H.Sub(&D, &C) 561 562 p.X.Mul(&E, &F) 563 p.Y.Mul(&G, &H) 564 p.T.Mul(&E, &H) 565 p.Z.Mul(&F, &G) 566 567 return p 568 } 569 570 // Double adds points in extended coordinates 571 // Dedicated doubling 572 // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd 573 func (p *PointExtended) Double(p1 *PointExtended) *PointExtended { 574 575 var A, B, C, D, E, F, G, H fr.Element 576 577 A.Square(&p1.X) 578 B.Square(&p1.Y) 579 C.Square(&p1.Z). 580 Double(&C) 581 D.Set(&A) 582 mulByA(&D) 583 E.Add(&p1.X, &p1.Y). 584 Square(&E). 585 Sub(&E, &A). 586 Sub(&E, &B) 587 G.Add(&D, &B) 588 F.Sub(&G, &C) 589 H.Sub(&D, &B) 590 591 p.X.Mul(&E, &F) 592 p.Y.Mul(&G, &H) 593 p.T.Mul(&H, &E) 594 p.Z.Mul(&F, &G) 595 596 return p 597 } 598 599 // MixedDouble adds points in extended coordinates 600 // Dedicated mixed doubling 601 // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-mdbl-2008-hwcd 602 func (p *PointExtended) MixedDouble(p1 *PointExtended) *PointExtended { 603 604 var A, B, D, E, G, H, two fr.Element 605 two.SetUint64(2) 606 607 A.Square(&p1.X) 608 B.Square(&p1.Y) 609 D.Set(&A) 610 mulByA(&D) 611 E.Add(&p1.X, &p1.Y). 612 Square(&E). 613 Sub(&E, &A). 614 Sub(&E, &B) 615 G.Add(&D, &B) 616 H.Sub(&D, &B) 617 618 p.X.Sub(&G, &two). 619 Mul(&p.X, &E) 620 p.Y.Mul(&G, &H) 621 p.T.Mul(&H, &E) 622 p.Z.Square(&G). 623 Sub(&p.Z, &G). 624 Sub(&p.Z, &G) 625 626 return p 627 } 628 629 // setInfinity sets p to O (0:1:1:0) 630 func (p *PointExtended) setInfinity() *PointExtended { 631 p.X.SetZero() 632 p.Y.SetOne() 633 p.Z.SetOne() 634 p.T.SetZero() 635 return p 636 } 637 638 // scalarMulWindowed scalar multiplication of a point 639 // p1 in extended coordinates with a scalar in big.Int 640 // using the windowed double-and-add method. 641 func (p *PointExtended) scalarMulWindowed(p1 *PointExtended, scalar *big.Int) *PointExtended { 642 var _scalar big.Int 643 _scalar.Set(scalar) 644 p.Set(p1) 645 if _scalar.Sign() == -1 { 646 _scalar.Neg(&_scalar) 647 p.Neg(p) 648 } 649 var resExtended PointExtended 650 resExtended.setInfinity() 651 const wordSize = bits.UintSize 652 sWords := _scalar.Bits() 653 654 for i := len(sWords) - 1; i >= 0; i-- { 655 ithWord := sWords[i] 656 for k := 0; k < wordSize; k++ { 657 resExtended.Double(&resExtended) 658 kthBit := (ithWord >> (wordSize - 1 - k)) & 1 659 if kthBit == 1 { 660 resExtended.Add(&resExtended, p) 661 } 662 } 663 } 664 665 p.Set(&resExtended) 666 return p 667 } 668 669 // ScalarMultiplication scalar multiplication of a point 670 // p1 in extended coordinates with a scalar in big.Int 671 func (p *PointExtended) ScalarMultiplication(p1 *PointExtended, scalar *big.Int) *PointExtended { 672 return p.scalarMulWindowed(p1, scalar) 673 }