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