1 package org.bouncycastle.math.ec; 2 3 import java.math.BigInteger; 4 import java.util.Random; 5 6 import org.bouncycastle.util.Arrays; 7 import org.bouncycastle.util.BigIntegers; 8 9 public abstract class ECFieldElement 10 implements ECConstants 11 { toBigInteger()12 public abstract BigInteger toBigInteger(); getFieldName()13 public abstract String getFieldName(); getFieldSize()14 public abstract int getFieldSize(); add(ECFieldElement b)15 public abstract ECFieldElement add(ECFieldElement b); addOne()16 public abstract ECFieldElement addOne(); subtract(ECFieldElement b)17 public abstract ECFieldElement subtract(ECFieldElement b); multiply(ECFieldElement b)18 public abstract ECFieldElement multiply(ECFieldElement b); divide(ECFieldElement b)19 public abstract ECFieldElement divide(ECFieldElement b); negate()20 public abstract ECFieldElement negate(); square()21 public abstract ECFieldElement square(); invert()22 public abstract ECFieldElement invert(); sqrt()23 public abstract ECFieldElement sqrt(); 24 bitLength()25 public int bitLength() 26 { 27 return toBigInteger().bitLength(); 28 } 29 isZero()30 public boolean isZero() 31 { 32 return 0 == toBigInteger().signum(); 33 } 34 testBitZero()35 public boolean testBitZero() 36 { 37 return toBigInteger().testBit(0); 38 } 39 toString()40 public String toString() 41 { 42 return this.toBigInteger().toString(16); 43 } 44 getEncoded()45 public byte[] getEncoded() 46 { 47 return BigIntegers.asUnsignedByteArray((getFieldSize() + 7) / 8, toBigInteger()); 48 } 49 50 public static class Fp extends ECFieldElement 51 { 52 BigInteger q, r, x; 53 54 // static int[] calculateNaf(BigInteger p) 55 // { 56 // int[] naf = WNafUtil.generateCompactNaf(p); 57 // 58 // int bit = 0; 59 // for (int i = 0; i < naf.length; ++i) 60 // { 61 // int ni = naf[i]; 62 // int digit = ni >> 16, zeroes = ni & 0xFFFF; 63 // 64 // bit += zeroes; 65 // naf[i] = digit < 0 ? ~bit : bit; 66 // ++bit; 67 // } 68 // 69 // int last = naf.length - 1; 70 // if (last > 0 && last <= 16) 71 // { 72 // int top = naf[last], top2 = naf[last - 1]; 73 // if (top2 < 0) 74 // { 75 // top2 = ~top2; 76 // } 77 // if (top - top2 >= 64) 78 // { 79 // return naf; 80 // } 81 // } 82 // 83 // return null; 84 // } 85 calculateResidue(BigInteger p)86 static BigInteger calculateResidue(BigInteger p) 87 { 88 int bitLength = p.bitLength(); 89 if (bitLength > 128) 90 { 91 BigInteger firstWord = p.shiftRight(bitLength - 64); 92 if (firstWord.longValue() == -1L) 93 { 94 return ONE.shiftLeft(bitLength).subtract(p); 95 } 96 } 97 return null; 98 } 99 100 /** 101 * @deprecated Use ECCurve.fromBigInteger to construct field elements 102 */ Fp(BigInteger q, BigInteger x)103 public Fp(BigInteger q, BigInteger x) 104 { 105 this(q, calculateResidue(q), x); 106 } 107 Fp(BigInteger q, BigInteger r, BigInteger x)108 Fp(BigInteger q, BigInteger r, BigInteger x) 109 { 110 if (x == null || x.signum() < 0 || x.compareTo(q) >= 0) 111 { 112 throw new IllegalArgumentException("x value invalid in Fp field element"); 113 } 114 115 this.q = q; 116 this.r = r; 117 this.x = x; 118 } 119 toBigInteger()120 public BigInteger toBigInteger() 121 { 122 return x; 123 } 124 125 /** 126 * return the field name for this field. 127 * 128 * @return the string "Fp". 129 */ getFieldName()130 public String getFieldName() 131 { 132 return "Fp"; 133 } 134 getFieldSize()135 public int getFieldSize() 136 { 137 return q.bitLength(); 138 } 139 getQ()140 public BigInteger getQ() 141 { 142 return q; 143 } 144 add(ECFieldElement b)145 public ECFieldElement add(ECFieldElement b) 146 { 147 return new Fp(q, r, modAdd(x, b.toBigInteger())); 148 } 149 addOne()150 public ECFieldElement addOne() 151 { 152 BigInteger x2 = x.add(ECConstants.ONE); 153 if (x2.compareTo(q) == 0) 154 { 155 x2 = ECConstants.ZERO; 156 } 157 return new Fp(q, r, x2); 158 } 159 subtract(ECFieldElement b)160 public ECFieldElement subtract(ECFieldElement b) 161 { 162 BigInteger x2 = b.toBigInteger(); 163 BigInteger x3 = x.subtract(x2); 164 if (x3.signum() < 0) 165 { 166 x3 = x3.add(q); 167 } 168 return new Fp(q, r, x3); 169 } 170 multiply(ECFieldElement b)171 public ECFieldElement multiply(ECFieldElement b) 172 { 173 return new Fp(q, r, modMult(x, b.toBigInteger())); 174 } 175 divide(ECFieldElement b)176 public ECFieldElement divide(ECFieldElement b) 177 { 178 return new Fp(q, modMult(x, b.toBigInteger().modInverse(q))); 179 } 180 negate()181 public ECFieldElement negate() 182 { 183 BigInteger x2; 184 if (x.signum() == 0) 185 { 186 x2 = x; 187 } 188 else if (ONE.equals(r)) 189 { 190 x2 = q.xor(x); 191 } 192 else 193 { 194 x2 = q.subtract(x); 195 } 196 return new Fp(q, r, x2); 197 } 198 square()199 public ECFieldElement square() 200 { 201 return new Fp(q, r, modMult(x, x)); 202 } 203 invert()204 public ECFieldElement invert() 205 { 206 // TODO Modular inversion can be faster for a (Generalized) Mersenne Prime. 207 return new Fp(q, r, x.modInverse(q)); 208 } 209 210 // D.1.4 91 211 /** 212 * return a sqrt root - the routine verifies that the calculation 213 * returns the right value - if none exists it returns null. 214 */ sqrt()215 public ECFieldElement sqrt() 216 { 217 if (!q.testBit(0)) 218 { 219 throw new RuntimeException("not done yet"); 220 } 221 222 // note: even though this class implements ECConstants don't be tempted to 223 // remove the explicit declaration, some J2ME environments don't cope. 224 // p mod 4 == 3 225 if (q.testBit(1)) 226 { 227 // z = g^(u+1) + p, p = 4u + 3 228 ECFieldElement z = new Fp(q, r, x.modPow(q.shiftRight(2).add(ECConstants.ONE), q)); 229 230 return z.square().equals(this) ? z : null; 231 } 232 233 // p mod 4 == 1 234 BigInteger qMinusOne = q.subtract(ECConstants.ONE); 235 236 BigInteger legendreExponent = qMinusOne.shiftRight(1); 237 if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE))) 238 { 239 return null; 240 } 241 242 BigInteger u = qMinusOne.shiftRight(2); 243 BigInteger k = u.shiftLeft(1).add(ECConstants.ONE); 244 245 BigInteger Q = this.x; 246 BigInteger fourQ = modDouble(modDouble(Q)); 247 248 BigInteger U, V; 249 Random rand = new Random(); 250 do 251 { 252 BigInteger P; 253 do 254 { 255 P = new BigInteger(q.bitLength(), rand); 256 } 257 while (P.compareTo(q) >= 0 258 || !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, q).equals(qMinusOne))); 259 260 BigInteger[] result = lucasSequence(P, Q, k); 261 U = result[0]; 262 V = result[1]; 263 264 if (modMult(V, V).equals(fourQ)) 265 { 266 // Integer division by 2, mod q 267 if (V.testBit(0)) 268 { 269 V = V.add(q); 270 } 271 272 V = V.shiftRight(1); 273 274 //assert V.multiply(V).mod(q).equals(x); 275 276 return new ECFieldElement.Fp(q, r, V); 277 } 278 } 279 while (U.equals(ECConstants.ONE) || U.equals(qMinusOne)); 280 281 return null; 282 283 // BigInteger qMinusOne = q.subtract(ECConstants.ONE); 284 // BigInteger legendreExponent = qMinusOne.shiftRight(1); //divide(ECConstants.TWO); 285 // if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE))) 286 // { 287 // return null; 288 // } 289 // 290 // Random rand = new Random(); 291 // BigInteger fourX = x.shiftLeft(2); 292 // 293 // BigInteger r; 294 // do 295 // { 296 // r = new BigInteger(q.bitLength(), rand); 297 // } 298 // while (r.compareTo(q) >= 0 299 // || !(r.multiply(r).subtract(fourX).modPow(legendreExponent, q).equals(qMinusOne))); 300 // 301 // BigInteger n1 = qMinusOne.shiftRight(2); //.divide(ECConstants.FOUR); 302 // BigInteger n2 = n1.add(ECConstants.ONE); //q.add(ECConstants.THREE).divide(ECConstants.FOUR); 303 // 304 // BigInteger wOne = WOne(r, x, q); 305 // BigInteger wSum = W(n1, wOne, q).add(W(n2, wOne, q)).mod(q); 306 // BigInteger twoR = r.shiftLeft(1); //ECConstants.TWO.multiply(r); 307 // 308 // BigInteger root = twoR.modPow(q.subtract(ECConstants.TWO), q) 309 // .multiply(x).mod(q) 310 // .multiply(wSum).mod(q); 311 // 312 // return new Fp(q, root); 313 } 314 315 // private static BigInteger W(BigInteger n, BigInteger wOne, BigInteger p) 316 // { 317 // if (n.equals(ECConstants.ONE)) 318 // { 319 // return wOne; 320 // } 321 // boolean isEven = !n.testBit(0); 322 // n = n.shiftRight(1);//divide(ECConstants.TWO); 323 // if (isEven) 324 // { 325 // BigInteger w = W(n, wOne, p); 326 // return w.multiply(w).subtract(ECConstants.TWO).mod(p); 327 // } 328 // BigInteger w1 = W(n.add(ECConstants.ONE), wOne, p); 329 // BigInteger w2 = W(n, wOne, p); 330 // return w1.multiply(w2).subtract(wOne).mod(p); 331 // } 332 // 333 // private BigInteger WOne(BigInteger r, BigInteger x, BigInteger p) 334 // { 335 // return r.multiply(r).multiply(x.modPow(q.subtract(ECConstants.TWO), q)).subtract(ECConstants.TWO).mod(p); 336 // } 337 lucasSequence( BigInteger P, BigInteger Q, BigInteger k)338 private BigInteger[] lucasSequence( 339 BigInteger P, 340 BigInteger Q, 341 BigInteger k) 342 { 343 int n = k.bitLength(); 344 int s = k.getLowestSetBit(); 345 346 BigInteger Uh = ECConstants.ONE; 347 BigInteger Vl = ECConstants.TWO; 348 BigInteger Vh = P; 349 BigInteger Ql = ECConstants.ONE; 350 BigInteger Qh = ECConstants.ONE; 351 352 for (int j = n - 1; j >= s + 1; --j) 353 { 354 Ql = modMult(Ql, Qh); 355 356 if (k.testBit(j)) 357 { 358 Qh = modMult(Ql, Q); 359 Uh = modMult(Uh, Vh); 360 Vl = modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql))); 361 Vh = modReduce(Vh.multiply(Vh).subtract(Qh.shiftLeft(1))); 362 } 363 else 364 { 365 Qh = Ql; 366 Uh = modReduce(Uh.multiply(Vl).subtract(Ql)); 367 Vh = modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql))); 368 Vl = modReduce(Vl.multiply(Vl).subtract(Ql.shiftLeft(1))); 369 } 370 } 371 372 Ql = modMult(Ql, Qh); 373 Qh = modMult(Ql, Q); 374 Uh = modReduce(Uh.multiply(Vl).subtract(Ql)); 375 Vl = modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql))); 376 Ql = modMult(Ql, Qh); 377 378 for (int j = 1; j <= s; ++j) 379 { 380 Uh = modMult(Uh, Vl); 381 Vl = modReduce(Vl.multiply(Vl).subtract(Ql.shiftLeft(1))); 382 Ql = modMult(Ql, Ql); 383 } 384 385 return new BigInteger[]{ Uh, Vl }; 386 } 387 modAdd(BigInteger x1, BigInteger x2)388 protected BigInteger modAdd(BigInteger x1, BigInteger x2) 389 { 390 BigInteger x3 = x1.add(x2); 391 if (x3.compareTo(q) >= 0) 392 { 393 x3 = x3.subtract(q); 394 } 395 return x3; 396 } 397 modDouble(BigInteger x)398 protected BigInteger modDouble(BigInteger x) 399 { 400 BigInteger _2x = x.shiftLeft(1); 401 if (_2x.compareTo(q) >= 0) 402 { 403 _2x = _2x.subtract(q); 404 } 405 return _2x; 406 } 407 modMult(BigInteger x1, BigInteger x2)408 protected BigInteger modMult(BigInteger x1, BigInteger x2) 409 { 410 return modReduce(x1.multiply(x2)); 411 } 412 modReduce(BigInteger x)413 protected BigInteger modReduce(BigInteger x) 414 { 415 // if (naf != null) 416 // { 417 // int last = naf.length - 1; 418 // int bits = naf[last]; 419 // while (x.bitLength() > (bits + 1)) 420 // { 421 // BigInteger u = x.shiftRight(bits); 422 // BigInteger v = x.subtract(u.shiftLeft(bits)); 423 // 424 // x = v; 425 // 426 // for (int i = 0; i < last; ++i) 427 // { 428 // int ni = naf[i]; 429 // if (ni < 0) 430 // { 431 // x = x.add(u.shiftLeft(~ni)); 432 // } 433 // else 434 // { 435 // x = x.subtract(u.shiftLeft(ni)); 436 // } 437 // } 438 // } 439 // while (x.compareTo(q) >= 0) 440 // { 441 // x = x.subtract(q); 442 // } 443 // } 444 // else 445 if (r != null) 446 { 447 int qLen = q.bitLength(); 448 while (x.bitLength() > (qLen + 1)) 449 { 450 BigInteger u = x.shiftRight(qLen); 451 BigInteger v = x.subtract(u.shiftLeft(qLen)); 452 if (!r.equals(ONE)) 453 { 454 u = u.multiply(r); 455 } 456 x = u.add(v); 457 } 458 while (x.compareTo(q) >= 0) 459 { 460 x = x.subtract(q); 461 } 462 } 463 else 464 { 465 x = x.mod(q); 466 } 467 return x; 468 } 469 equals(Object other)470 public boolean equals(Object other) 471 { 472 if (other == this) 473 { 474 return true; 475 } 476 477 if (!(other instanceof ECFieldElement.Fp)) 478 { 479 return false; 480 } 481 482 ECFieldElement.Fp o = (ECFieldElement.Fp)other; 483 return q.equals(o.q) && x.equals(o.x); 484 } 485 hashCode()486 public int hashCode() 487 { 488 return q.hashCode() ^ x.hashCode(); 489 } 490 } 491 492 // /** 493 // * Class representing the Elements of the finite field 494 // * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB) 495 // * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial 496 // * basis representations are supported. Gaussian normal basis (GNB) 497 // * representation is not supported. 498 // */ 499 // public static class F2m extends ECFieldElement 500 // { 501 // BigInteger x; 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 // /** 532 // * TPB: The integer <code>k</code> where <code>x<sup>m</sup> + 533 // * x<sup>k</sup> + 1</code> represents the reduction polynomial 534 // * <code>f(z)</code>.<br> 535 // * PPB: The integer <code>k1</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>.<br> 538 // */ 539 // private int k1; 540 // 541 // /** 542 // * TPB: Always set to <code>0</code><br> 543 // * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> + 544 // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 545 // * represents the reduction polynomial <code>f(z)</code>.<br> 546 // */ 547 // private int k2; 548 // 549 // /** 550 // * TPB: Always set to <code>0</code><br> 551 // * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> + 552 // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 553 // * represents the reduction polynomial <code>f(z)</code>.<br> 554 // */ 555 // private int k3; 556 // 557 // /** 558 // * Constructor for PPB. 559 // * @param m The exponent <code>m</code> of 560 // * <code>F<sub>2<sup>m</sup></sub></code>. 561 // * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> + 562 // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 563 // * represents the reduction polynomial <code>f(z)</code>. 564 // * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> + 565 // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 566 // * represents the reduction polynomial <code>f(z)</code>. 567 // * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> + 568 // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 569 // * represents the reduction polynomial <code>f(z)</code>. 570 // * @param x The BigInteger representing the value of the field element. 571 // */ 572 // public F2m( 573 // int m, 574 // int k1, 575 // int k2, 576 // int k3, 577 // BigInteger x) 578 // { 579 //// super(x); 580 // this.x = x; 581 // 582 // if ((k2 == 0) && (k3 == 0)) 583 // { 584 // this.representation = TPB; 585 // } 586 // else 587 // { 588 // if (k2 >= k3) 589 // { 590 // throw new IllegalArgumentException( 591 // "k2 must be smaller than k3"); 592 // } 593 // if (k2 <= 0) 594 // { 595 // throw new IllegalArgumentException( 596 // "k2 must be larger than 0"); 597 // } 598 // this.representation = PPB; 599 // } 600 // 601 // if (x.signum() < 0) 602 // { 603 // throw new IllegalArgumentException("x value cannot be negative"); 604 // } 605 // 606 // this.m = m; 607 // this.k1 = k1; 608 // this.k2 = k2; 609 // this.k3 = k3; 610 // } 611 // 612 // /** 613 // * Constructor for TPB. 614 // * @param m The exponent <code>m</code> of 615 // * <code>F<sub>2<sup>m</sup></sub></code>. 616 // * @param k The integer <code>k</code> where <code>x<sup>m</sup> + 617 // * x<sup>k</sup> + 1</code> represents the reduction 618 // * polynomial <code>f(z)</code>. 619 // * @param x The BigInteger representing the value of the field element. 620 // */ 621 // public F2m(int m, int k, BigInteger x) 622 // { 623 // // Set k1 to k, and set k2 and k3 to 0 624 // this(m, k, 0, 0, x); 625 // } 626 // 627 // public BigInteger toBigInteger() 628 // { 629 // return x; 630 // } 631 // 632 // public String getFieldName() 633 // { 634 // return "F2m"; 635 // } 636 // 637 // public int getFieldSize() 638 // { 639 // return m; 640 // } 641 // 642 // /** 643 // * Checks, if the ECFieldElements <code>a</code> and <code>b</code> 644 // * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code> 645 // * (having the same representation). 646 // * @param a field element. 647 // * @param b field element to be compared. 648 // * @throws IllegalArgumentException if <code>a</code> and <code>b</code> 649 // * are not elements of the same field 650 // * <code>F<sub>2<sup>m</sup></sub></code> (having the same 651 // * representation). 652 // */ 653 // public static void checkFieldElements( 654 // ECFieldElement a, 655 // ECFieldElement b) 656 // { 657 // if ((!(a instanceof F2m)) || (!(b instanceof F2m))) 658 // { 659 // throw new IllegalArgumentException("Field elements are not " 660 // + "both instances of ECFieldElement.F2m"); 661 // } 662 // 663 // if ((a.toBigInteger().signum() < 0) || (b.toBigInteger().signum() < 0)) 664 // { 665 // throw new IllegalArgumentException( 666 // "x value may not be negative"); 667 // } 668 // 669 // ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a; 670 // ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b; 671 // 672 // if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1) 673 // || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3)) 674 // { 675 // throw new IllegalArgumentException("Field elements are not " 676 // + "elements of the same field F2m"); 677 // } 678 // 679 // if (aF2m.representation != bF2m.representation) 680 // { 681 // // Should never occur 682 // throw new IllegalArgumentException( 683 // "One of the field " 684 // + "elements are not elements has incorrect representation"); 685 // } 686 // } 687 // 688 // /** 689 // * Computes <code>z * a(z) mod f(z)</code>, where <code>f(z)</code> is 690 // * the reduction polynomial of <code>this</code>. 691 // * @param a The polynomial <code>a(z)</code> to be multiplied by 692 // * <code>z mod f(z)</code>. 693 // * @return <code>z * a(z) mod f(z)</code> 694 // */ 695 // private BigInteger multZModF(final BigInteger a) 696 // { 697 // // Left-shift of a(z) 698 // BigInteger az = a.shiftLeft(1); 699 // if (az.testBit(this.m)) 700 // { 701 // // If the coefficient of z^m in a(z) equals 1, reduction 702 // // modulo f(z) is performed: Add f(z) to to a(z): 703 // // Step 1: Unset mth coeffient of a(z) 704 // az = az.clearBit(this.m); 705 // 706 // // Step 2: Add r(z) to a(z), where r(z) is defined as 707 // // f(z) = z^m + r(z), and k1, k2, k3 are the positions of 708 // // the non-zero coefficients in r(z) 709 // az = az.flipBit(0); 710 // az = az.flipBit(this.k1); 711 // if (this.representation == PPB) 712 // { 713 // az = az.flipBit(this.k2); 714 // az = az.flipBit(this.k3); 715 // } 716 // } 717 // return az; 718 // } 719 // 720 // public ECFieldElement add(final ECFieldElement b) 721 // { 722 // // No check performed here for performance reasons. Instead the 723 // // elements involved are checked in ECPoint.F2m 724 // // checkFieldElements(this, b); 725 // if (b.toBigInteger().signum() == 0) 726 // { 727 // return this; 728 // } 729 // 730 // return new F2m(this.m, this.k1, this.k2, this.k3, this.x.xor(b.toBigInteger())); 731 // } 732 // 733 // public ECFieldElement subtract(final ECFieldElement b) 734 // { 735 // // Addition and subtraction are the same in F2m 736 // return add(b); 737 // } 738 // 739 // 740 // public ECFieldElement multiply(final ECFieldElement b) 741 // { 742 // // Left-to-right shift-and-add field multiplication in F2m 743 // // Input: Binary polynomials a(z) and b(z) of degree at most m-1 744 // // Output: c(z) = a(z) * b(z) mod f(z) 745 // 746 // // No check performed here for performance reasons. Instead the 747 // // elements involved are checked in ECPoint.F2m 748 // // checkFieldElements(this, b); 749 // final BigInteger az = this.x; 750 // BigInteger bz = b.toBigInteger(); 751 // BigInteger cz; 752 // 753 // // Compute c(z) = a(z) * b(z) mod f(z) 754 // if (az.testBit(0)) 755 // { 756 // cz = bz; 757 // } 758 // else 759 // { 760 // cz = ECConstants.ZERO; 761 // } 762 // 763 // for (int i = 1; i < this.m; i++) 764 // { 765 // // b(z) := z * b(z) mod f(z) 766 // bz = multZModF(bz); 767 // 768 // if (az.testBit(i)) 769 // { 770 // // If the coefficient of x^i in a(z) equals 1, b(z) is added 771 // // to c(z) 772 // cz = cz.xor(bz); 773 // } 774 // } 775 // return new ECFieldElement.F2m(m, this.k1, this.k2, this.k3, cz); 776 // } 777 // 778 // 779 // public ECFieldElement divide(final ECFieldElement b) 780 // { 781 // // There may be more efficient implementations 782 // ECFieldElement bInv = b.invert(); 783 // return multiply(bInv); 784 // } 785 // 786 // public ECFieldElement negate() 787 // { 788 // // -x == x holds for all x in F2m 789 // return this; 790 // } 791 // 792 // public ECFieldElement square() 793 // { 794 // // Naive implementation, can probably be speeded up using modular 795 // // reduction 796 // return multiply(this); 797 // } 798 // 799 // public ECFieldElement invert() 800 // { 801 // // Inversion in F2m using the extended Euclidean algorithm 802 // // Input: A nonzero polynomial a(z) of degree at most m-1 803 // // Output: a(z)^(-1) mod f(z) 804 // 805 // // u(z) := a(z) 806 // BigInteger uz = this.x; 807 // if (uz.signum() <= 0) 808 // { 809 // throw new ArithmeticException("x is zero or negative, " + 810 // "inversion is impossible"); 811 // } 812 // 813 // // v(z) := f(z) 814 // BigInteger vz = ECConstants.ZERO.setBit(m); 815 // vz = vz.setBit(0); 816 // vz = vz.setBit(this.k1); 817 // if (this.representation == PPB) 818 // { 819 // vz = vz.setBit(this.k2); 820 // vz = vz.setBit(this.k3); 821 // } 822 // 823 // // g1(z) := 1, g2(z) := 0 824 // BigInteger g1z = ECConstants.ONE; 825 // BigInteger g2z = ECConstants.ZERO; 826 // 827 // // while u != 1 828 // while (!(uz.equals(ECConstants.ZERO))) 829 // { 830 // // j := deg(u(z)) - deg(v(z)) 831 // int j = uz.bitLength() - vz.bitLength(); 832 // 833 // // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j 834 // if (j < 0) 835 // { 836 // final BigInteger uzCopy = uz; 837 // uz = vz; 838 // vz = uzCopy; 839 // 840 // final BigInteger g1zCopy = g1z; 841 // g1z = g2z; 842 // g2z = g1zCopy; 843 // 844 // j = -j; 845 // } 846 // 847 // // u(z) := u(z) + z^j * v(z) 848 // // Note, that no reduction modulo f(z) is required, because 849 // // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z))) 850 // // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z)) 851 // // = deg(u(z)) 852 // uz = uz.xor(vz.shiftLeft(j)); 853 // 854 // // g1(z) := g1(z) + z^j * g2(z) 855 // g1z = g1z.xor(g2z.shiftLeft(j)); 856 //// if (g1z.bitLength() > this.m) { 857 //// throw new ArithmeticException( 858 //// "deg(g1z) >= m, g1z = " + g1z.toString(16)); 859 //// } 860 // } 861 // return new ECFieldElement.F2m( 862 // this.m, this.k1, this.k2, this.k3, g2z); 863 // } 864 // 865 // public ECFieldElement sqrt() 866 // { 867 // throw new RuntimeException("Not implemented"); 868 // } 869 // 870 // /** 871 // * @return the representation of the field 872 // * <code>F<sub>2<sup>m</sup></sub></code>, either of 873 // * TPB (trinomial 874 // * basis representation) or 875 // * PPB (pentanomial 876 // * basis representation). 877 // */ 878 // public int getRepresentation() 879 // { 880 // return this.representation; 881 // } 882 // 883 // /** 884 // * @return the degree <code>m</code> of the reduction polynomial 885 // * <code>f(z)</code>. 886 // */ 887 // public int getM() 888 // { 889 // return this.m; 890 // } 891 // 892 // /** 893 // * @return TPB: The integer <code>k</code> where <code>x<sup>m</sup> + 894 // * x<sup>k</sup> + 1</code> represents the reduction polynomial 895 // * <code>f(z)</code>.<br> 896 // * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> + 897 // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 898 // * represents the reduction polynomial <code>f(z)</code>.<br> 899 // */ 900 // public int getK1() 901 // { 902 // return this.k1; 903 // } 904 // 905 // /** 906 // * @return TPB: Always returns <code>0</code><br> 907 // * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> + 908 // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 909 // * represents the reduction polynomial <code>f(z)</code>.<br> 910 // */ 911 // public int getK2() 912 // { 913 // return this.k2; 914 // } 915 // 916 // /** 917 // * @return TPB: Always set to <code>0</code><br> 918 // * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> + 919 // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 920 // * represents the reduction polynomial <code>f(z)</code>.<br> 921 // */ 922 // public int getK3() 923 // { 924 // return this.k3; 925 // } 926 // 927 // public boolean equals(Object anObject) 928 // { 929 // if (anObject == this) 930 // { 931 // return true; 932 // } 933 // 934 // if (!(anObject instanceof ECFieldElement.F2m)) 935 // { 936 // return false; 937 // } 938 // 939 // ECFieldElement.F2m b = (ECFieldElement.F2m)anObject; 940 // 941 // return ((this.m == b.m) && (this.k1 == b.k1) && (this.k2 == b.k2) 942 // && (this.k3 == b.k3) 943 // && (this.representation == b.representation) 944 // && (this.x.equals(b.x))); 945 // } 946 // 947 // public int hashCode() 948 // { 949 // return x.hashCode() ^ m ^ k1 ^ k2 ^ k3; 950 // } 951 // } 952 953 /** 954 * Class representing the Elements of the finite field 955 * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB) 956 * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial 957 * basis representations are supported. Gaussian normal basis (GNB) 958 * representation is not supported. 959 */ 960 public static class F2m extends ECFieldElement 961 { 962 /** 963 * Indicates gaussian normal basis representation (GNB). Number chosen 964 * according to X9.62. GNB is not implemented at present. 965 */ 966 public static final int GNB = 1; 967 968 /** 969 * Indicates trinomial basis representation (TPB). Number chosen 970 * according to X9.62. 971 */ 972 public static final int TPB = 2; 973 974 /** 975 * Indicates pentanomial basis representation (PPB). Number chosen 976 * according to X9.62. 977 */ 978 public static final int PPB = 3; 979 980 /** 981 * TPB or PPB. 982 */ 983 private int representation; 984 985 /** 986 * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>. 987 */ 988 private int m; 989 990 // /** 991 // * TPB: The integer <code>k</code> where <code>x<sup>m</sup> + 992 // * x<sup>k</sup> + 1</code> represents the reduction polynomial 993 // * <code>f(z)</code>.<br> 994 // * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> + 995 // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 996 // * represents the reduction polynomial <code>f(z)</code>.<br> 997 // */ 998 // private int k1; 999 // 1000 // /** 1001 // * TPB: Always set to <code>0</code><br> 1002 // * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> + 1003 // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 1004 // * represents the reduction polynomial <code>f(z)</code>.<br> 1005 // */ 1006 // private int k2; 1007 // 1008 // /** 1009 // * TPB: Always set to <code>0</code><br> 1010 // * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> + 1011 // * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 1012 // * represents the reduction polynomial <code>f(z)</code>.<br> 1013 // */ 1014 // private int k3; 1015 1016 private int[] ks; 1017 1018 /** 1019 * The <code>LongArray</code> holding the bits. 1020 */ 1021 private LongArray x; 1022 1023 /** 1024 * Constructor for PPB. 1025 * @param m The exponent <code>m</code> of 1026 * <code>F<sub>2<sup>m</sup></sub></code>. 1027 * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> + 1028 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 1029 * represents the reduction polynomial <code>f(z)</code>. 1030 * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> + 1031 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 1032 * represents the reduction polynomial <code>f(z)</code>. 1033 * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> + 1034 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 1035 * represents the reduction polynomial <code>f(z)</code>. 1036 * @param x The BigInteger representing the value of the field element. 1037 * @deprecated Use ECCurve.fromBigInteger to construct field elements 1038 */ F2m( int m, int k1, int k2, int k3, BigInteger x)1039 public F2m( 1040 int m, 1041 int k1, 1042 int k2, 1043 int k3, 1044 BigInteger x) 1045 { 1046 if ((k2 == 0) && (k3 == 0)) 1047 { 1048 this.representation = TPB; 1049 this.ks = new int[]{ k1 }; 1050 } 1051 else 1052 { 1053 if (k2 >= k3) 1054 { 1055 throw new IllegalArgumentException( 1056 "k2 must be smaller than k3"); 1057 } 1058 if (k2 <= 0) 1059 { 1060 throw new IllegalArgumentException( 1061 "k2 must be larger than 0"); 1062 } 1063 this.representation = PPB; 1064 this.ks = new int[]{ k1, k2, k3 }; 1065 } 1066 1067 this.m = m; 1068 this.x = new LongArray(x); 1069 } 1070 1071 /** 1072 * Constructor for TPB. 1073 * @param m The exponent <code>m</code> of 1074 * <code>F<sub>2<sup>m</sup></sub></code>. 1075 * @param k The integer <code>k</code> where <code>x<sup>m</sup> + 1076 * x<sup>k</sup> + 1</code> represents the reduction 1077 * polynomial <code>f(z)</code>. 1078 * @param x The BigInteger representing the value of the field element. 1079 * @deprecated Use ECCurve.fromBigInteger to construct field elements 1080 */ F2m(int m, int k, BigInteger x)1081 public F2m(int m, int k, BigInteger x) 1082 { 1083 // Set k1 to k, and set k2 and k3 to 0 1084 this(m, k, 0, 0, x); 1085 } 1086 F2m(int m, int[] ks, LongArray x)1087 private F2m(int m, int[] ks, LongArray x) 1088 { 1089 this.m = m; 1090 this.representation = (ks.length == 1) ? TPB : PPB; 1091 this.ks = ks; 1092 this.x = x; 1093 } 1094 bitLength()1095 public int bitLength() 1096 { 1097 return x.degree(); 1098 } 1099 isZero()1100 public boolean isZero() 1101 { 1102 return x.isZero(); 1103 } 1104 testBitZero()1105 public boolean testBitZero() 1106 { 1107 return x.testBitZero(); 1108 } 1109 toBigInteger()1110 public BigInteger toBigInteger() 1111 { 1112 return x.toBigInteger(); 1113 } 1114 getFieldName()1115 public String getFieldName() 1116 { 1117 return "F2m"; 1118 } 1119 getFieldSize()1120 public int getFieldSize() 1121 { 1122 return m; 1123 } 1124 1125 /** 1126 * Checks, if the ECFieldElements <code>a</code> and <code>b</code> 1127 * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code> 1128 * (having the same representation). 1129 * @param a field element. 1130 * @param b field element to be compared. 1131 * @throws IllegalArgumentException if <code>a</code> and <code>b</code> 1132 * are not elements of the same field 1133 * <code>F<sub>2<sup>m</sup></sub></code> (having the same 1134 * representation). 1135 */ checkFieldElements( ECFieldElement a, ECFieldElement b)1136 public static void checkFieldElements( 1137 ECFieldElement a, 1138 ECFieldElement b) 1139 { 1140 if ((!(a instanceof F2m)) || (!(b instanceof F2m))) 1141 { 1142 throw new IllegalArgumentException("Field elements are not " 1143 + "both instances of ECFieldElement.F2m"); 1144 } 1145 1146 ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a; 1147 ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b; 1148 1149 if (aF2m.representation != bF2m.representation) 1150 { 1151 // Should never occur 1152 throw new IllegalArgumentException("One of the F2m field elements has incorrect representation"); 1153 } 1154 1155 if ((aF2m.m != bF2m.m) || !Arrays.areEqual(aF2m.ks, bF2m.ks)) 1156 { 1157 throw new IllegalArgumentException("Field elements are not elements of the same field F2m"); 1158 } 1159 } 1160 add(final ECFieldElement b)1161 public ECFieldElement add(final ECFieldElement b) 1162 { 1163 // No check performed here for performance reasons. Instead the 1164 // elements involved are checked in ECPoint.F2m 1165 // checkFieldElements(this, b); 1166 LongArray iarrClone = (LongArray)this.x.clone(); 1167 F2m bF2m = (F2m)b; 1168 iarrClone.addShiftedByWords(bF2m.x, 0); 1169 return new F2m(m, ks, iarrClone); 1170 } 1171 addOne()1172 public ECFieldElement addOne() 1173 { 1174 return new F2m(m, ks, x.addOne()); 1175 } 1176 subtract(final ECFieldElement b)1177 public ECFieldElement subtract(final ECFieldElement b) 1178 { 1179 // Addition and subtraction are the same in F2m 1180 return add(b); 1181 } 1182 multiply(final ECFieldElement b)1183 public ECFieldElement multiply(final ECFieldElement b) 1184 { 1185 // Right-to-left comb multiplication in the LongArray 1186 // Input: Binary polynomials a(z) and b(z) of degree at most m-1 1187 // Output: c(z) = a(z) * b(z) mod f(z) 1188 1189 // No check performed here for performance reasons. Instead the 1190 // elements involved are checked in ECPoint.F2m 1191 // checkFieldElements(this, b); 1192 return new F2m(m, ks, x.modMultiply(((F2m)b).x, m, ks)); 1193 } 1194 divide(final ECFieldElement b)1195 public ECFieldElement divide(final ECFieldElement b) 1196 { 1197 // There may be more efficient implementations 1198 ECFieldElement bInv = b.invert(); 1199 return multiply(bInv); 1200 } 1201 negate()1202 public ECFieldElement negate() 1203 { 1204 // -x == x holds for all x in F2m 1205 return this; 1206 } 1207 square()1208 public ECFieldElement square() 1209 { 1210 return new F2m(m, ks, x.modSquare(m, ks)); 1211 } 1212 invert()1213 public ECFieldElement invert() 1214 { 1215 return new ECFieldElement.F2m(this.m, this.ks, this.x.modInverse(m, ks)); 1216 } 1217 sqrt()1218 public ECFieldElement sqrt() 1219 { 1220 throw new RuntimeException("Not implemented"); 1221 } 1222 1223 /** 1224 * @return the representation of the field 1225 * <code>F<sub>2<sup>m</sup></sub></code>, either of 1226 * TPB (trinomial 1227 * basis representation) or 1228 * PPB (pentanomial 1229 * basis representation). 1230 */ getRepresentation()1231 public int getRepresentation() 1232 { 1233 return this.representation; 1234 } 1235 1236 /** 1237 * @return the degree <code>m</code> of the reduction polynomial 1238 * <code>f(z)</code>. 1239 */ getM()1240 public int getM() 1241 { 1242 return this.m; 1243 } 1244 1245 /** 1246 * @return TPB: The integer <code>k</code> where <code>x<sup>m</sup> + 1247 * x<sup>k</sup> + 1</code> represents the reduction polynomial 1248 * <code>f(z)</code>.<br> 1249 * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> + 1250 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 1251 * represents the reduction polynomial <code>f(z)</code>.<br> 1252 */ getK1()1253 public int getK1() 1254 { 1255 return this.ks[0]; 1256 } 1257 1258 /** 1259 * @return TPB: Always returns <code>0</code><br> 1260 * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> + 1261 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 1262 * represents the reduction polynomial <code>f(z)</code>.<br> 1263 */ getK2()1264 public int getK2() 1265 { 1266 return this.ks.length >= 2 ? this.ks[1] : 0; 1267 } 1268 1269 /** 1270 * @return TPB: Always set to <code>0</code><br> 1271 * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> + 1272 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 1273 * represents the reduction polynomial <code>f(z)</code>.<br> 1274 */ getK3()1275 public int getK3() 1276 { 1277 return this.ks.length >= 3 ? this.ks[2] : 0; 1278 } 1279 equals(Object anObject)1280 public boolean equals(Object anObject) 1281 { 1282 if (anObject == this) 1283 { 1284 return true; 1285 } 1286 1287 if (!(anObject instanceof ECFieldElement.F2m)) 1288 { 1289 return false; 1290 } 1291 1292 ECFieldElement.F2m b = (ECFieldElement.F2m)anObject; 1293 1294 return ((this.m == b.m) 1295 && (this.representation == b.representation) 1296 && Arrays.areEqual(this.ks, b.ks) 1297 && (this.x.equals(b.x))); 1298 } 1299 hashCode()1300 public int hashCode() 1301 { 1302 return x.hashCode() ^ m ^ Arrays.hashCode(ks); 1303 } 1304 } 1305 } 1306