1package org.bouncycastle.math.ec; 2 3import java.math.BigInteger; 4import java.util.Random; 5 6import org.bouncycastle.util.Arrays; 7import org.bouncycastle.util.BigIntegers; 8 9public abstract class ECFieldElement 10 implements ECConstants 11{ 12 public abstract BigInteger toBigInteger(); 13 public abstract String getFieldName(); 14 public abstract int getFieldSize(); 15 public abstract ECFieldElement add(ECFieldElement b); 16 public abstract ECFieldElement addOne(); 17 public abstract ECFieldElement subtract(ECFieldElement b); 18 public abstract ECFieldElement multiply(ECFieldElement b); 19 public abstract ECFieldElement divide(ECFieldElement b); 20 public abstract ECFieldElement negate(); 21 public abstract ECFieldElement square(); 22 public abstract ECFieldElement invert(); 23 public abstract ECFieldElement sqrt(); 24 25 public int bitLength() 26 { 27 return toBigInteger().bitLength(); 28 } 29 30 public boolean isZero() 31 { 32 return 0 == toBigInteger().signum(); 33 } 34 35 public boolean testBitZero() 36 { 37 return toBigInteger().testBit(0); 38 } 39 40 public String toString() 41 { 42 return this.toBigInteger().toString(16); 43 } 44 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 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 */ 103 public Fp(BigInteger q, BigInteger x) 104 { 105 this(q, calculateResidue(q), x); 106 } 107 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 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 */ 130 public String getFieldName() 131 { 132 return "Fp"; 133 } 134 135 public int getFieldSize() 136 { 137 return q.bitLength(); 138 } 139 140 public BigInteger getQ() 141 { 142 return q; 143 } 144 145 public ECFieldElement add(ECFieldElement b) 146 { 147 return new Fp(q, r, modAdd(x, b.toBigInteger())); 148 } 149 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 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 171 public ECFieldElement multiply(ECFieldElement b) 172 { 173 return new Fp(q, r, modMult(x, b.toBigInteger())); 174 } 175 176 public ECFieldElement divide(ECFieldElement b) 177 { 178 return new Fp(q, modMult(x, b.toBigInteger().modInverse(q))); 179 } 180 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 199 public ECFieldElement square() 200 { 201 return new Fp(q, r, modMult(x, x)); 202 } 203 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 */ 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 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 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 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 408 protected BigInteger modMult(BigInteger x1, BigInteger x2) 409 { 410 return modReduce(x1.multiply(x2)); 411 } 412 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 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 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 */ 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 */ 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 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 1095 public int bitLength() 1096 { 1097 return x.degree(); 1098 } 1099 1100 public boolean isZero() 1101 { 1102 return x.isZero(); 1103 } 1104 1105 public boolean testBitZero() 1106 { 1107 return x.testBitZero(); 1108 } 1109 1110 public BigInteger toBigInteger() 1111 { 1112 return x.toBigInteger(); 1113 } 1114 1115 public String getFieldName() 1116 { 1117 return "F2m"; 1118 } 1119 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 */ 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 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 1172 public ECFieldElement addOne() 1173 { 1174 return new F2m(m, ks, x.addOne()); 1175 } 1176 1177 public ECFieldElement subtract(final ECFieldElement b) 1178 { 1179 // Addition and subtraction are the same in F2m 1180 return add(b); 1181 } 1182 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 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 1202 public ECFieldElement negate() 1203 { 1204 // -x == x holds for all x in F2m 1205 return this; 1206 } 1207 1208 public ECFieldElement square() 1209 { 1210 return new F2m(m, ks, x.modSquare(m, ks)); 1211 } 1212 1213 public ECFieldElement invert() 1214 { 1215 return new ECFieldElement.F2m(this.m, this.ks, this.x.modInverse(m, ks)); 1216 } 1217 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 */ 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 */ 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 */ 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 */ 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 */ 1275 public int getK3() 1276 { 1277 return this.ks.length >= 3 ? this.ks[2] : 0; 1278 } 1279 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 1300 public int hashCode() 1301 { 1302 return x.hashCode() ^ m ^ Arrays.hashCode(ks); 1303 } 1304 } 1305} 1306