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