1 package org.bouncycastle.math.ec; 2 3 import java.math.BigInteger; 4 import java.util.Random; 5 6 import org.bouncycastle.math.raw.Mod; 7 import org.bouncycastle.math.raw.Nat; 8 import org.bouncycastle.util.Arrays; 9 import org.bouncycastle.util.BigIntegers; 10 11 public abstract class ECFieldElement 12 implements ECConstants 13 { toBigInteger()14 public abstract BigInteger toBigInteger(); getFieldName()15 public abstract String getFieldName(); getFieldSize()16 public abstract int getFieldSize(); add(ECFieldElement b)17 public abstract ECFieldElement add(ECFieldElement b); addOne()18 public abstract ECFieldElement addOne(); subtract(ECFieldElement b)19 public abstract ECFieldElement subtract(ECFieldElement b); multiply(ECFieldElement b)20 public abstract ECFieldElement multiply(ECFieldElement b); divide(ECFieldElement b)21 public abstract ECFieldElement divide(ECFieldElement b); negate()22 public abstract ECFieldElement negate(); square()23 public abstract ECFieldElement square(); invert()24 public abstract ECFieldElement invert(); sqrt()25 public abstract ECFieldElement sqrt(); 26 bitLength()27 public int bitLength() 28 { 29 return toBigInteger().bitLength(); 30 } 31 isOne()32 public boolean isOne() 33 { 34 return bitLength() == 1; 35 } 36 isZero()37 public boolean isZero() 38 { 39 return 0 == toBigInteger().signum(); 40 } 41 multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)42 public ECFieldElement multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) 43 { 44 return multiply(b).subtract(x.multiply(y)); 45 } 46 multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)47 public ECFieldElement multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) 48 { 49 return multiply(b).add(x.multiply(y)); 50 } 51 squareMinusProduct(ECFieldElement x, ECFieldElement y)52 public ECFieldElement squareMinusProduct(ECFieldElement x, ECFieldElement y) 53 { 54 return square().subtract(x.multiply(y)); 55 } 56 squarePlusProduct(ECFieldElement x, ECFieldElement y)57 public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y) 58 { 59 return square().add(x.multiply(y)); 60 } 61 squarePow(int pow)62 public ECFieldElement squarePow(int pow) 63 { 64 ECFieldElement r = this; 65 for (int i = 0; i < pow; ++i) 66 { 67 r = r.square(); 68 } 69 return r; 70 } 71 testBitZero()72 public boolean testBitZero() 73 { 74 return toBigInteger().testBit(0); 75 } 76 toString()77 public String toString() 78 { 79 return this.toBigInteger().toString(16); 80 } 81 getEncoded()82 public byte[] getEncoded() 83 { 84 return BigIntegers.asUnsignedByteArray((getFieldSize() + 7) / 8, toBigInteger()); 85 } 86 87 public static class Fp extends ECFieldElement 88 { 89 BigInteger q, r, x; 90 calculateResidue(BigInteger p)91 static BigInteger calculateResidue(BigInteger p) 92 { 93 int bitLength = p.bitLength(); 94 if (bitLength >= 96) 95 { 96 BigInteger firstWord = p.shiftRight(bitLength - 64); 97 if (firstWord.longValue() == -1L) 98 { 99 return ONE.shiftLeft(bitLength).subtract(p); 100 } 101 } 102 return null; 103 } 104 105 /** 106 * @deprecated Use ECCurve.fromBigInteger to construct field elements 107 */ Fp(BigInteger q, BigInteger x)108 public Fp(BigInteger q, BigInteger x) 109 { 110 this(q, calculateResidue(q), x); 111 } 112 Fp(BigInteger q, BigInteger r, BigInteger x)113 Fp(BigInteger q, BigInteger r, BigInteger x) 114 { 115 if (x == null || x.signum() < 0 || x.compareTo(q) >= 0) 116 { 117 throw new IllegalArgumentException("x value invalid in Fp field element"); 118 } 119 120 this.q = q; 121 this.r = r; 122 this.x = x; 123 } 124 toBigInteger()125 public BigInteger toBigInteger() 126 { 127 return x; 128 } 129 130 /** 131 * return the field name for this field. 132 * 133 * @return the string "Fp". 134 */ getFieldName()135 public String getFieldName() 136 { 137 return "Fp"; 138 } 139 getFieldSize()140 public int getFieldSize() 141 { 142 return q.bitLength(); 143 } 144 getQ()145 public BigInteger getQ() 146 { 147 return q; 148 } 149 add(ECFieldElement b)150 public ECFieldElement add(ECFieldElement b) 151 { 152 return new Fp(q, r, modAdd(x, b.toBigInteger())); 153 } 154 addOne()155 public ECFieldElement addOne() 156 { 157 BigInteger x2 = x.add(ECConstants.ONE); 158 if (x2.compareTo(q) == 0) 159 { 160 x2 = ECConstants.ZERO; 161 } 162 return new Fp(q, r, x2); 163 } 164 subtract(ECFieldElement b)165 public ECFieldElement subtract(ECFieldElement b) 166 { 167 return new Fp(q, r, modSubtract(x, b.toBigInteger())); 168 } 169 multiply(ECFieldElement b)170 public ECFieldElement multiply(ECFieldElement b) 171 { 172 return new Fp(q, r, modMult(x, b.toBigInteger())); 173 } 174 multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)175 public ECFieldElement multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) 176 { 177 BigInteger ax = this.x, bx = b.toBigInteger(), xx = x.toBigInteger(), yx = y.toBigInteger(); 178 BigInteger ab = ax.multiply(bx); 179 BigInteger xy = xx.multiply(yx); 180 return new Fp(q, r, modReduce(ab.subtract(xy))); 181 } 182 multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)183 public ECFieldElement multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) 184 { 185 BigInteger ax = this.x, bx = b.toBigInteger(), xx = x.toBigInteger(), yx = y.toBigInteger(); 186 BigInteger ab = ax.multiply(bx); 187 BigInteger xy = xx.multiply(yx); 188 return new Fp(q, r, modReduce(ab.add(xy))); 189 } 190 divide(ECFieldElement b)191 public ECFieldElement divide(ECFieldElement b) 192 { 193 return new Fp(q, r, modMult(x, modInverse(b.toBigInteger()))); 194 } 195 negate()196 public ECFieldElement negate() 197 { 198 return x.signum() == 0 ? this : new Fp(q, r, q.subtract(x)); 199 } 200 square()201 public ECFieldElement square() 202 { 203 return new Fp(q, r, modMult(x, x)); 204 } 205 squareMinusProduct(ECFieldElement x, ECFieldElement y)206 public ECFieldElement squareMinusProduct(ECFieldElement x, ECFieldElement y) 207 { 208 BigInteger ax = this.x, xx = x.toBigInteger(), yx = y.toBigInteger(); 209 BigInteger aa = ax.multiply(ax); 210 BigInteger xy = xx.multiply(yx); 211 return new Fp(q, r, modReduce(aa.subtract(xy))); 212 } 213 squarePlusProduct(ECFieldElement x, ECFieldElement y)214 public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y) 215 { 216 BigInteger ax = this.x, xx = x.toBigInteger(), yx = y.toBigInteger(); 217 BigInteger aa = ax.multiply(ax); 218 BigInteger xy = xx.multiply(yx); 219 return new Fp(q, r, modReduce(aa.add(xy))); 220 } 221 invert()222 public ECFieldElement invert() 223 { 224 // TODO Modular inversion can be faster for a (Generalized) Mersenne Prime. 225 return new Fp(q, r, modInverse(x)); 226 } 227 228 // D.1.4 91 229 /** 230 * return a sqrt root - the routine verifies that the calculation 231 * returns the right value - if none exists it returns null. 232 */ sqrt()233 public ECFieldElement sqrt() 234 { 235 if (this.isZero() || this.isOne()) // earlier JDK compatibility 236 { 237 return this; 238 } 239 240 if (!q.testBit(0)) 241 { 242 throw new RuntimeException("not done yet"); 243 } 244 245 // note: even though this class implements ECConstants don't be tempted to 246 // remove the explicit declaration, some J2ME environments don't cope. 247 248 if (q.testBit(1)) // q == 4m + 3 249 { 250 BigInteger e = q.shiftRight(2).add(ECConstants.ONE); 251 return checkSqrt(new Fp(q, r, x.modPow(e, q))); 252 } 253 254 if (q.testBit(2)) // q == 8m + 5 255 { 256 BigInteger t1 = x.modPow(q.shiftRight(3), q); 257 BigInteger t2 = modMult(t1, x); 258 BigInteger t3 = modMult(t2, t1); 259 260 if (t3.equals(ECConstants.ONE)) 261 { 262 return checkSqrt(new Fp(q, r, t2)); 263 } 264 265 // TODO This is constant and could be precomputed 266 BigInteger t4 = ECConstants.TWO.modPow(q.shiftRight(2), q); 267 268 BigInteger y = modMult(t2, t4); 269 270 return checkSqrt(new Fp(q, r, y)); 271 } 272 273 // q == 8m + 1 274 275 BigInteger legendreExponent = q.shiftRight(1); 276 if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE))) 277 { 278 return null; 279 } 280 281 BigInteger X = this.x; 282 BigInteger fourX = modDouble(modDouble(X)); 283 284 BigInteger k = legendreExponent.add(ECConstants.ONE), qMinusOne = q.subtract(ECConstants.ONE); 285 286 BigInteger U, V; 287 Random rand = new Random(); 288 do 289 { 290 BigInteger P; 291 do 292 { 293 P = new BigInteger(q.bitLength(), rand); 294 } 295 while (P.compareTo(q) >= 0 296 || !modReduce(P.multiply(P).subtract(fourX)).modPow(legendreExponent, q).equals(qMinusOne)); 297 298 BigInteger[] result = lucasSequence(P, X, k); 299 U = result[0]; 300 V = result[1]; 301 302 if (modMult(V, V).equals(fourX)) 303 { 304 return new ECFieldElement.Fp(q, r, modHalfAbs(V)); 305 } 306 } 307 while (U.equals(ECConstants.ONE) || U.equals(qMinusOne)); 308 309 return null; 310 } 311 checkSqrt(ECFieldElement z)312 private ECFieldElement checkSqrt(ECFieldElement z) 313 { 314 return z.square().equals(this) ? z : null; 315 } 316 lucasSequence( BigInteger P, BigInteger Q, BigInteger k)317 private BigInteger[] lucasSequence( 318 BigInteger P, 319 BigInteger Q, 320 BigInteger k) 321 { 322 // TODO Research and apply "common-multiplicand multiplication here" 323 324 int n = k.bitLength(); 325 int s = k.getLowestSetBit(); 326 327 // assert k.testBit(s); 328 329 BigInteger Uh = ECConstants.ONE; 330 BigInteger Vl = ECConstants.TWO; 331 BigInteger Vh = P; 332 BigInteger Ql = ECConstants.ONE; 333 BigInteger Qh = ECConstants.ONE; 334 335 for (int j = n - 1; j >= s + 1; --j) 336 { 337 Ql = modMult(Ql, Qh); 338 339 if (k.testBit(j)) 340 { 341 Qh = modMult(Ql, Q); 342 Uh = modMult(Uh, Vh); 343 Vl = modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql))); 344 Vh = modReduce(Vh.multiply(Vh).subtract(Qh.shiftLeft(1))); 345 } 346 else 347 { 348 Qh = Ql; 349 Uh = modReduce(Uh.multiply(Vl).subtract(Ql)); 350 Vh = modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql))); 351 Vl = modReduce(Vl.multiply(Vl).subtract(Ql.shiftLeft(1))); 352 } 353 } 354 355 Ql = modMult(Ql, Qh); 356 Qh = modMult(Ql, Q); 357 Uh = modReduce(Uh.multiply(Vl).subtract(Ql)); 358 Vl = modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql))); 359 Ql = modMult(Ql, Qh); 360 361 for (int j = 1; j <= s; ++j) 362 { 363 Uh = modMult(Uh, Vl); 364 Vl = modReduce(Vl.multiply(Vl).subtract(Ql.shiftLeft(1))); 365 Ql = modMult(Ql, Ql); 366 } 367 368 return new BigInteger[]{ Uh, Vl }; 369 } 370 modAdd(BigInteger x1, BigInteger x2)371 protected BigInteger modAdd(BigInteger x1, BigInteger x2) 372 { 373 BigInteger x3 = x1.add(x2); 374 if (x3.compareTo(q) >= 0) 375 { 376 x3 = x3.subtract(q); 377 } 378 return x3; 379 } 380 modDouble(BigInteger x)381 protected BigInteger modDouble(BigInteger x) 382 { 383 BigInteger _2x = x.shiftLeft(1); 384 if (_2x.compareTo(q) >= 0) 385 { 386 _2x = _2x.subtract(q); 387 } 388 return _2x; 389 } 390 modHalf(BigInteger x)391 protected BigInteger modHalf(BigInteger x) 392 { 393 if (x.testBit(0)) 394 { 395 x = q.add(x); 396 } 397 return x.shiftRight(1); 398 } 399 modHalfAbs(BigInteger x)400 protected BigInteger modHalfAbs(BigInteger x) 401 { 402 if (x.testBit(0)) 403 { 404 x = q.subtract(x); 405 } 406 return x.shiftRight(1); 407 } 408 modInverse(BigInteger x)409 protected BigInteger modInverse(BigInteger x) 410 { 411 int bits = getFieldSize(); 412 int len = (bits + 31) >> 5; 413 int[] p = Nat.fromBigInteger(bits, q); 414 int[] n = Nat.fromBigInteger(bits, x); 415 int[] z = Nat.create(len); 416 Mod.invert(p, n, z); 417 return Nat.toBigInteger(len, z); 418 } 419 modMult(BigInteger x1, BigInteger x2)420 protected BigInteger modMult(BigInteger x1, BigInteger x2) 421 { 422 return modReduce(x1.multiply(x2)); 423 } 424 modReduce(BigInteger x)425 protected BigInteger modReduce(BigInteger x) 426 { 427 if (r != null) 428 { 429 boolean negative = x.signum() < 0; 430 if (negative) 431 { 432 x = x.abs(); 433 } 434 int qLen = q.bitLength(); 435 boolean rIsOne = r.equals(ECConstants.ONE); 436 while (x.bitLength() > (qLen + 1)) 437 { 438 BigInteger u = x.shiftRight(qLen); 439 BigInteger v = x.subtract(u.shiftLeft(qLen)); 440 if (!rIsOne) 441 { 442 u = u.multiply(r); 443 } 444 x = u.add(v); 445 } 446 while (x.compareTo(q) >= 0) 447 { 448 x = x.subtract(q); 449 } 450 if (negative && x.signum() != 0) 451 { 452 x = q.subtract(x); 453 } 454 } 455 else 456 { 457 x = x.mod(q); 458 } 459 return x; 460 } 461 modSubtract(BigInteger x1, BigInteger x2)462 protected BigInteger modSubtract(BigInteger x1, BigInteger x2) 463 { 464 BigInteger x3 = x1.subtract(x2); 465 if (x3.signum() < 0) 466 { 467 x3 = x3.add(q); 468 } 469 return x3; 470 } 471 equals(Object other)472 public boolean equals(Object other) 473 { 474 if (other == this) 475 { 476 return true; 477 } 478 479 if (!(other instanceof ECFieldElement.Fp)) 480 { 481 return false; 482 } 483 484 ECFieldElement.Fp o = (ECFieldElement.Fp)other; 485 return q.equals(o.q) && x.equals(o.x); 486 } 487 hashCode()488 public int hashCode() 489 { 490 return q.hashCode() ^ x.hashCode(); 491 } 492 } 493 494 /** 495 * Class representing the Elements of the finite field 496 * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB) 497 * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial 498 * basis representations are supported. Gaussian normal basis (GNB) 499 * representation is not supported. 500 */ 501 public static class F2m extends ECFieldElement 502 { 503 /** 504 * Indicates gaussian normal basis representation (GNB). Number chosen 505 * according to X9.62. GNB is not implemented at present. 506 */ 507 public static final int GNB = 1; 508 509 /** 510 * Indicates trinomial basis representation (TPB). Number chosen 511 * according to X9.62. 512 */ 513 public static final int TPB = 2; 514 515 /** 516 * Indicates pentanomial basis representation (PPB). Number chosen 517 * according to X9.62. 518 */ 519 public static final int PPB = 3; 520 521 /** 522 * TPB or PPB. 523 */ 524 private int representation; 525 526 /** 527 * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>. 528 */ 529 private int m; 530 531 private int[] ks; 532 533 /** 534 * The <code>LongArray</code> holding the bits. 535 */ 536 private LongArray x; 537 538 /** 539 * Constructor for PPB. 540 * @param m The exponent <code>m</code> of 541 * <code>F<sub>2<sup>m</sup></sub></code>. 542 * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> + 543 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 544 * represents the reduction polynomial <code>f(z)</code>. 545 * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> + 546 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 547 * represents the reduction polynomial <code>f(z)</code>. 548 * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> + 549 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 550 * represents the reduction polynomial <code>f(z)</code>. 551 * @param x The BigInteger representing the value of the field element. 552 * @deprecated Use ECCurve.fromBigInteger to construct field elements 553 */ F2m( int m, int k1, int k2, int k3, BigInteger x)554 public F2m( 555 int m, 556 int k1, 557 int k2, 558 int k3, 559 BigInteger x) 560 { 561 if (x == null || x.signum() < 0 || x.bitLength() > m) 562 { 563 throw new IllegalArgumentException("x value invalid in F2m field element"); 564 } 565 566 if ((k2 == 0) && (k3 == 0)) 567 { 568 this.representation = TPB; 569 this.ks = new int[]{ k1 }; 570 } 571 else 572 { 573 if (k2 >= k3) 574 { 575 throw new IllegalArgumentException( 576 "k2 must be smaller than k3"); 577 } 578 if (k2 <= 0) 579 { 580 throw new IllegalArgumentException( 581 "k2 must be larger than 0"); 582 } 583 this.representation = PPB; 584 this.ks = new int[]{ k1, k2, k3 }; 585 } 586 587 this.m = m; 588 this.x = new LongArray(x); 589 } 590 591 /** 592 * Constructor for TPB. 593 * @param m The exponent <code>m</code> of 594 * <code>F<sub>2<sup>m</sup></sub></code>. 595 * @param k The integer <code>k</code> where <code>x<sup>m</sup> + 596 * x<sup>k</sup> + 1</code> represents the reduction 597 * polynomial <code>f(z)</code>. 598 * @param x The BigInteger representing the value of the field element. 599 * @deprecated Use ECCurve.fromBigInteger to construct field elements 600 */ F2m(int m, int k, BigInteger x)601 public F2m(int m, int k, BigInteger x) 602 { 603 // Set k1 to k, and set k2 and k3 to 0 604 this(m, k, 0, 0, x); 605 } 606 F2m(int m, int[] ks, LongArray x)607 private F2m(int m, int[] ks, LongArray x) 608 { 609 this.m = m; 610 this.representation = (ks.length == 1) ? TPB : PPB; 611 this.ks = ks; 612 this.x = x; 613 } 614 bitLength()615 public int bitLength() 616 { 617 return x.degree(); 618 } 619 isOne()620 public boolean isOne() 621 { 622 return x.isOne(); 623 } 624 isZero()625 public boolean isZero() 626 { 627 return x.isZero(); 628 } 629 testBitZero()630 public boolean testBitZero() 631 { 632 return x.testBitZero(); 633 } 634 toBigInteger()635 public BigInteger toBigInteger() 636 { 637 return x.toBigInteger(); 638 } 639 getFieldName()640 public String getFieldName() 641 { 642 return "F2m"; 643 } 644 getFieldSize()645 public int getFieldSize() 646 { 647 return m; 648 } 649 650 /** 651 * Checks, if the ECFieldElements <code>a</code> and <code>b</code> 652 * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code> 653 * (having the same representation). 654 * @param a field element. 655 * @param b field element to be compared. 656 * @throws IllegalArgumentException if <code>a</code> and <code>b</code> 657 * are not elements of the same field 658 * <code>F<sub>2<sup>m</sup></sub></code> (having the same 659 * representation). 660 */ checkFieldElements( ECFieldElement a, ECFieldElement b)661 public static void checkFieldElements( 662 ECFieldElement a, 663 ECFieldElement b) 664 { 665 if ((!(a instanceof F2m)) || (!(b instanceof F2m))) 666 { 667 throw new IllegalArgumentException("Field elements are not " 668 + "both instances of ECFieldElement.F2m"); 669 } 670 671 ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a; 672 ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b; 673 674 if (aF2m.representation != bF2m.representation) 675 { 676 // Should never occur 677 throw new IllegalArgumentException("One of the F2m field elements has incorrect representation"); 678 } 679 680 if ((aF2m.m != bF2m.m) || !Arrays.areEqual(aF2m.ks, bF2m.ks)) 681 { 682 throw new IllegalArgumentException("Field elements are not elements of the same field F2m"); 683 } 684 } 685 add(final ECFieldElement b)686 public ECFieldElement add(final ECFieldElement b) 687 { 688 // No check performed here for performance reasons. Instead the 689 // elements involved are checked in ECPoint.F2m 690 // checkFieldElements(this, b); 691 LongArray iarrClone = (LongArray)this.x.clone(); 692 F2m bF2m = (F2m)b; 693 iarrClone.addShiftedByWords(bF2m.x, 0); 694 return new F2m(m, ks, iarrClone); 695 } 696 addOne()697 public ECFieldElement addOne() 698 { 699 return new F2m(m, ks, x.addOne()); 700 } 701 subtract(final ECFieldElement b)702 public ECFieldElement subtract(final ECFieldElement b) 703 { 704 // Addition and subtraction are the same in F2m 705 return add(b); 706 } 707 multiply(final ECFieldElement b)708 public ECFieldElement multiply(final ECFieldElement b) 709 { 710 // Right-to-left comb multiplication in the LongArray 711 // Input: Binary polynomials a(z) and b(z) of degree at most m-1 712 // Output: c(z) = a(z) * b(z) mod f(z) 713 714 // No check performed here for performance reasons. Instead the 715 // elements involved are checked in ECPoint.F2m 716 // checkFieldElements(this, b); 717 return new F2m(m, ks, x.modMultiply(((F2m)b).x, m, ks)); 718 } 719 multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)720 public ECFieldElement multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) 721 { 722 return multiplyPlusProduct(b, x, y); 723 } 724 multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)725 public ECFieldElement multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) 726 { 727 LongArray ax = this.x, bx = ((F2m)b).x, xx = ((F2m)x).x, yx = ((F2m)y).x; 728 729 LongArray ab = ax.multiply(bx, m, ks); 730 LongArray xy = xx.multiply(yx, m, ks); 731 732 if (ab == ax || ab == bx) 733 { 734 ab = (LongArray)ab.clone(); 735 } 736 737 ab.addShiftedByWords(xy, 0); 738 ab.reduce(m, ks); 739 740 return new F2m(m, ks, ab); 741 } 742 divide(final ECFieldElement b)743 public ECFieldElement divide(final ECFieldElement b) 744 { 745 // There may be more efficient implementations 746 ECFieldElement bInv = b.invert(); 747 return multiply(bInv); 748 } 749 negate()750 public ECFieldElement negate() 751 { 752 // -x == x holds for all x in F2m 753 return this; 754 } 755 square()756 public ECFieldElement square() 757 { 758 return new F2m(m, ks, x.modSquare(m, ks)); 759 } 760 squareMinusProduct(ECFieldElement x, ECFieldElement y)761 public ECFieldElement squareMinusProduct(ECFieldElement x, ECFieldElement y) 762 { 763 return squarePlusProduct(x, y); 764 } 765 squarePlusProduct(ECFieldElement x, ECFieldElement y)766 public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y) 767 { 768 LongArray ax = this.x, xx = ((F2m)x).x, yx = ((F2m)y).x; 769 770 LongArray aa = ax.square(m, ks); 771 LongArray xy = xx.multiply(yx, m, ks); 772 773 if (aa == ax) 774 { 775 aa = (LongArray)aa.clone(); 776 } 777 778 aa.addShiftedByWords(xy, 0); 779 aa.reduce(m, ks); 780 781 return new F2m(m, ks, aa); 782 } 783 squarePow(int pow)784 public ECFieldElement squarePow(int pow) 785 { 786 return pow < 1 ? this : new F2m(m, ks, x.modSquareN(pow, m, ks)); 787 } 788 invert()789 public ECFieldElement invert() 790 { 791 return new ECFieldElement.F2m(this.m, this.ks, this.x.modInverse(m, ks)); 792 } 793 sqrt()794 public ECFieldElement sqrt() 795 { 796 return (x.isZero() || x.isOne()) ? this : squarePow(m - 1); 797 } 798 799 /** 800 * @return the representation of the field 801 * <code>F<sub>2<sup>m</sup></sub></code>, either of 802 * TPB (trinomial 803 * basis representation) or 804 * PPB (pentanomial 805 * basis representation). 806 */ getRepresentation()807 public int getRepresentation() 808 { 809 return this.representation; 810 } 811 812 /** 813 * @return the degree <code>m</code> of the reduction polynomial 814 * <code>f(z)</code>. 815 */ getM()816 public int getM() 817 { 818 return this.m; 819 } 820 821 /** 822 * @return TPB: The integer <code>k</code> where <code>x<sup>m</sup> + 823 * x<sup>k</sup> + 1</code> represents the reduction polynomial 824 * <code>f(z)</code>.<br> 825 * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> + 826 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 827 * represents the reduction polynomial <code>f(z)</code>.<br> 828 */ getK1()829 public int getK1() 830 { 831 return this.ks[0]; 832 } 833 834 /** 835 * @return TPB: Always returns <code>0</code><br> 836 * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> + 837 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 838 * represents the reduction polynomial <code>f(z)</code>.<br> 839 */ getK2()840 public int getK2() 841 { 842 return this.ks.length >= 2 ? this.ks[1] : 0; 843 } 844 845 /** 846 * @return TPB: Always set to <code>0</code><br> 847 * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> + 848 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 849 * represents the reduction polynomial <code>f(z)</code>.<br> 850 */ getK3()851 public int getK3() 852 { 853 return this.ks.length >= 3 ? this.ks[2] : 0; 854 } 855 equals(Object anObject)856 public boolean equals(Object anObject) 857 { 858 if (anObject == this) 859 { 860 return true; 861 } 862 863 if (!(anObject instanceof ECFieldElement.F2m)) 864 { 865 return false; 866 } 867 868 ECFieldElement.F2m b = (ECFieldElement.F2m)anObject; 869 870 return ((this.m == b.m) 871 && (this.representation == b.representation) 872 && Arrays.areEqual(this.ks, b.ks) 873 && (this.x.equals(b.x))); 874 } 875 hashCode()876 public int hashCode() 877 { 878 return x.hashCode() ^ m ^ Arrays.hashCode(ks); 879 } 880 } 881 } 882