ECCurve.java revision 5db505e1f6a68c8d5dfdb0fed0b8607dea7bed96
1package org.bouncycastle.math.ec; 2 3import java.math.BigInteger; 4import java.util.Random; 5 6import org.bouncycastle.util.BigIntegers; 7 8/** 9 * base class for an elliptic curve 10 */ 11public abstract class ECCurve 12{ 13 public static final int COORD_AFFINE = 0; 14 public static final int COORD_HOMOGENEOUS = 1; 15 public static final int COORD_JACOBIAN = 2; 16 public static final int COORD_JACOBIAN_CHUDNOVSKY = 3; 17 public static final int COORD_JACOBIAN_MODIFIED = 4; 18 public static final int COORD_LAMBDA_AFFINE = 5; 19 public static final int COORD_LAMBDA_PROJECTIVE = 6; 20 public static final int COORD_SKEWED = 7; 21 22 public static int[] getAllCoordinateSystems() 23 { 24 return new int[]{ COORD_AFFINE, COORD_HOMOGENEOUS, COORD_JACOBIAN, COORD_JACOBIAN_CHUDNOVSKY, 25 COORD_JACOBIAN_MODIFIED, COORD_LAMBDA_AFFINE, COORD_LAMBDA_PROJECTIVE, COORD_SKEWED }; 26 } 27 28 public class Config 29 { 30 protected int coord; 31 protected ECMultiplier multiplier; 32 33 Config(int coord, ECMultiplier multiplier) 34 { 35 this.coord = coord; 36 this.multiplier = multiplier; 37 } 38 39 public Config setCoordinateSystem(int coord) 40 { 41 this.coord = coord; 42 return this; 43 } 44 45 public Config setMultiplier(ECMultiplier multiplier) 46 { 47 this.multiplier = multiplier; 48 return this; 49 } 50 51 public ECCurve create() 52 { 53 if (!supportsCoordinateSystem(coord)) 54 { 55 throw new IllegalStateException("unsupported coordinate system"); 56 } 57 58 ECCurve c = cloneCurve(); 59 if (c == ECCurve.this) 60 { 61 throw new IllegalStateException("implementation returned current curve"); 62 } 63 64 c.coord = coord; 65 c.multiplier = multiplier; 66 67 return c; 68 } 69 } 70 71 protected ECFieldElement a, b; 72 protected int coord = COORD_AFFINE; 73 protected ECMultiplier multiplier = null; 74 75 public abstract int getFieldSize(); 76 77 public abstract ECFieldElement fromBigInteger(BigInteger x); 78 79 public Config configure() 80 { 81 return new Config(this.coord, this.multiplier); 82 } 83 84 public ECPoint createPoint(BigInteger x, BigInteger y) 85 { 86 return createPoint(x, y, false); 87 } 88 89 /** 90 * @deprecated per-point compression property will be removed, use {@link #createPoint(BigInteger, BigInteger)} 91 * and refer {@link ECPoint#getEncoded(boolean)} 92 */ 93 public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression) 94 { 95 return createRawPoint(fromBigInteger(x), fromBigInteger(y), withCompression); 96 } 97 98 protected abstract ECCurve cloneCurve(); 99 100 protected abstract ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression); 101 102 protected ECMultiplier createDefaultMultiplier() 103 { 104 return new WNafL2RMultiplier(); 105 } 106 107 public boolean supportsCoordinateSystem(int coord) 108 { 109 return coord == COORD_AFFINE; 110 } 111 112 public PreCompInfo getPreCompInfo(ECPoint p) 113 { 114 checkPoint(p); 115 return p.preCompInfo; 116 } 117 118 /** 119 * Sets the <code>PreCompInfo</code> for a point on this curve. Used by 120 * <code>ECMultiplier</code>s to save the precomputation for this <code>ECPoint</code> for use 121 * by subsequent multiplication. 122 * 123 * @param point 124 * The <code>ECPoint</code> to store precomputations for. 125 * @param preCompInfo 126 * The values precomputed by the <code>ECMultiplier</code>. 127 */ 128 public void setPreCompInfo(ECPoint point, PreCompInfo preCompInfo) 129 { 130 checkPoint(point); 131 point.preCompInfo = preCompInfo; 132 } 133 134 public ECPoint importPoint(ECPoint p) 135 { 136 if (this == p.getCurve()) 137 { 138 return p; 139 } 140 if (p.isInfinity()) 141 { 142 return getInfinity(); 143 } 144 145 // TODO Default behaviour could be improved if the two curves have the same coordinate system by copying any Z coordinates. 146 p = p.normalize(); 147 148 return createPoint(p.getXCoord().toBigInteger(), p.getYCoord().toBigInteger(), p.withCompression); 149 } 150 151 /** 152 * Normalization ensures that any projective coordinate is 1, and therefore that the x, y 153 * coordinates reflect those of the equivalent point in an affine coordinate system. Where more 154 * than one point is to be normalized, this method will generally be more efficient than 155 * normalizing each point separately. 156 * 157 * @param points 158 * An array of points that will be updated in place with their normalized versions, 159 * where necessary 160 */ 161 public void normalizeAll(ECPoint[] points) 162 { 163 checkPoints(points); 164 165 if (this.getCoordinateSystem() == ECCurve.COORD_AFFINE) 166 { 167 return; 168 } 169 170 /* 171 * Figure out which of the points actually need to be normalized 172 */ 173 ECFieldElement[] zs = new ECFieldElement[points.length]; 174 int[] indices = new int[points.length]; 175 int count = 0; 176 for (int i = 0; i < points.length; ++i) 177 { 178 ECPoint p = points[i]; 179 if (null != p && !p.isNormalized()) 180 { 181 zs[count] = p.getZCoord(0); 182 indices[count++] = i; 183 } 184 } 185 186 if (count == 0) 187 { 188 return; 189 } 190 191 ECAlgorithms.implMontgomeryTrick(zs, 0, count); 192 193 for (int j = 0; j < count; ++j) 194 { 195 int index = indices[j]; 196 points[index] = points[index].normalize(zs[j]); 197 } 198 } 199 200 public abstract ECPoint getInfinity(); 201 202 public ECFieldElement getA() 203 { 204 return a; 205 } 206 207 public ECFieldElement getB() 208 { 209 return b; 210 } 211 212 public int getCoordinateSystem() 213 { 214 return coord; 215 } 216 217 protected abstract ECPoint decompressPoint(int yTilde, BigInteger X1); 218 219 /** 220 * Sets the default <code>ECMultiplier</code>, unless already set. 221 */ 222 public ECMultiplier getMultiplier() 223 { 224 if (this.multiplier == null) 225 { 226 this.multiplier = createDefaultMultiplier(); 227 } 228 return this.multiplier; 229 } 230 231 /** 232 * Decode a point on this curve from its ASN.1 encoding. The different 233 * encodings are taken account of, including point compression for 234 * <code>F<sub>p</sub></code> (X9.62 s 4.2.1 pg 17). 235 * @return The decoded point. 236 */ 237 public ECPoint decodePoint(byte[] encoded) 238 { 239 ECPoint p = null; 240 int expectedLength = (getFieldSize() + 7) / 8; 241 242 switch (encoded[0]) 243 { 244 case 0x00: // infinity 245 { 246 if (encoded.length != 1) 247 { 248 throw new IllegalArgumentException("Incorrect length for infinity encoding"); 249 } 250 251 p = getInfinity(); 252 break; 253 } 254 case 0x02: // compressed 255 case 0x03: // compressed 256 { 257 if (encoded.length != (expectedLength + 1)) 258 { 259 throw new IllegalArgumentException("Incorrect length for compressed encoding"); 260 } 261 262 int yTilde = encoded[0] & 1; 263 BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength); 264 265 p = decompressPoint(yTilde, X); 266 break; 267 } 268 case 0x04: // uncompressed 269 case 0x06: // hybrid 270 case 0x07: // hybrid 271 { 272 if (encoded.length != (2 * expectedLength + 1)) 273 { 274 throw new IllegalArgumentException("Incorrect length for uncompressed/hybrid encoding"); 275 } 276 277 BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength); 278 BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength); 279 280 p = createPoint(X, Y); 281 break; 282 } 283 default: 284 throw new IllegalArgumentException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16)); 285 } 286 287 return p; 288 } 289 290 protected void checkPoint(ECPoint point) 291 { 292 if (null == point || (this != point.getCurve())) 293 { 294 throw new IllegalArgumentException("'point' must be non-null and on this curve"); 295 } 296 } 297 298 protected void checkPoints(ECPoint[] points) 299 { 300 if (points == null) 301 { 302 throw new IllegalArgumentException("'points' cannot be null"); 303 } 304 305 for (int i = 0; i < points.length; ++i) 306 { 307 ECPoint point = points[i]; 308 if (null != point && this != point.getCurve()) 309 { 310 throw new IllegalArgumentException("'points' entries must be null or on this curve"); 311 } 312 } 313 } 314 315 /** 316 * Elliptic curve over Fp 317 */ 318 public static class Fp extends ECCurve 319 { 320 private static final int FP_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED; 321 322 BigInteger q, r; 323 ECPoint.Fp infinity; 324 325 public Fp(BigInteger q, BigInteger a, BigInteger b) 326 { 327 this.q = q; 328 this.r = ECFieldElement.Fp.calculateResidue(q); 329 this.infinity = new ECPoint.Fp(this, null, null); 330 331 this.a = fromBigInteger(a); 332 this.b = fromBigInteger(b); 333 this.coord = FP_DEFAULT_COORDS; 334 } 335 336 protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b) 337 { 338 this.q = q; 339 this.r = r; 340 this.infinity = new ECPoint.Fp(this, null, null); 341 342 this.a = a; 343 this.b = b; 344 this.coord = FP_DEFAULT_COORDS; 345 } 346 347 protected ECCurve cloneCurve() 348 { 349 return new Fp(q, r, a, b); 350 } 351 352 public boolean supportsCoordinateSystem(int coord) 353 { 354 switch (coord) 355 { 356 case COORD_AFFINE: 357 case COORD_HOMOGENEOUS: 358 case COORD_JACOBIAN: 359 case COORD_JACOBIAN_MODIFIED: 360 return true; 361 default: 362 return false; 363 } 364 } 365 366 public BigInteger getQ() 367 { 368 return q; 369 } 370 371 public int getFieldSize() 372 { 373 return q.bitLength(); 374 } 375 376 public ECFieldElement fromBigInteger(BigInteger x) 377 { 378 return new ECFieldElement.Fp(this.q, this.r, x); 379 } 380 381 protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) 382 { 383 return new ECPoint.Fp(this, x, y, withCompression); 384 } 385 386 public ECPoint importPoint(ECPoint p) 387 { 388 if (this != p.getCurve() && this.getCoordinateSystem() == COORD_JACOBIAN && !p.isInfinity()) 389 { 390 switch (p.getCurve().getCoordinateSystem()) 391 { 392 case COORD_JACOBIAN: 393 case COORD_JACOBIAN_CHUDNOVSKY: 394 case COORD_JACOBIAN_MODIFIED: 395 return new ECPoint.Fp(this, 396 fromBigInteger(p.x.toBigInteger()), 397 fromBigInteger(p.y.toBigInteger()), 398 new ECFieldElement[]{ fromBigInteger(p.zs[0].toBigInteger()) }, 399 p.withCompression); 400 default: 401 break; 402 } 403 } 404 405 return super.importPoint(p); 406 } 407 408 protected ECPoint decompressPoint(int yTilde, BigInteger X1) 409 { 410 ECFieldElement x = fromBigInteger(X1); 411 ECFieldElement alpha = x.multiply(x.square().add(a)).add(b); 412 ECFieldElement beta = alpha.sqrt(); 413 414 // 415 // if we can't find a sqrt we haven't got a point on the 416 // curve - run! 417 // 418 if (beta == null) 419 { 420 throw new RuntimeException("Invalid point compression"); 421 } 422 423 BigInteger betaValue = beta.toBigInteger(); 424 if (betaValue.testBit(0) != (yTilde == 1)) 425 { 426 // Use the other root 427 beta = fromBigInteger(q.subtract(betaValue)); 428 } 429 430 return new ECPoint.Fp(this, x, beta, true); 431 } 432 433 public ECPoint getInfinity() 434 { 435 return infinity; 436 } 437 438 public boolean equals( 439 Object anObject) 440 { 441 if (anObject == this) 442 { 443 return true; 444 } 445 446 if (!(anObject instanceof ECCurve.Fp)) 447 { 448 return false; 449 } 450 451 ECCurve.Fp other = (ECCurve.Fp) anObject; 452 453 return this.q.equals(other.q) 454 && a.equals(other.a) && b.equals(other.b); 455 } 456 457 public int hashCode() 458 { 459 return a.hashCode() ^ b.hashCode() ^ q.hashCode(); 460 } 461 } 462 463 /** 464 * Elliptic curves over F2m. The Weierstrass equation is given by 465 * <code>y<sup>2</sup> + xy = x<sup>3</sup> + ax<sup>2</sup> + b</code>. 466 */ 467 public static class F2m extends ECCurve 468 { 469 private static final int F2M_DEFAULT_COORDS = COORD_AFFINE; 470 471 /** 472 * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>. 473 */ 474 private int m; // can't be final - JDK 1.1 475 476 /** 477 * TPB: The integer <code>k</code> where <code>x<sup>m</sup> + 478 * x<sup>k</sup> + 1</code> represents the reduction polynomial 479 * <code>f(z)</code>.<br> 480 * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> + 481 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 482 * represents the reduction polynomial <code>f(z)</code>.<br> 483 */ 484 private int k1; // can't be final - JDK 1.1 485 486 /** 487 * TPB: Always set to <code>0</code><br> 488 * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> + 489 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 490 * represents the reduction polynomial <code>f(z)</code>.<br> 491 */ 492 private int k2; // can't be final - JDK 1.1 493 494 /** 495 * TPB: Always set to <code>0</code><br> 496 * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> + 497 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 498 * represents the reduction polynomial <code>f(z)</code>.<br> 499 */ 500 private int k3; // can't be final - JDK 1.1 501 502 /** 503 * The order of the base point of the curve. 504 */ 505 private BigInteger n; // can't be final - JDK 1.1 506 507 /** 508 * The cofactor of the curve. 509 */ 510 private BigInteger h; // can't be final - JDK 1.1 511 512 /** 513 * The point at infinity on this curve. 514 */ 515 private ECPoint.F2m infinity; // can't be final - JDK 1.1 516 517 /** 518 * The parameter <code>μ</code> of the elliptic curve if this is 519 * a Koblitz curve. 520 */ 521 private byte mu = 0; 522 523 /** 524 * The auxiliary values <code>s<sub>0</sub></code> and 525 * <code>s<sub>1</sub></code> used for partial modular reduction for 526 * Koblitz curves. 527 */ 528 private BigInteger[] si = null; 529 530 /** 531 * Constructor for Trinomial Polynomial Basis (TPB). 532 * @param m The exponent <code>m</code> of 533 * <code>F<sub>2<sup>m</sup></sub></code>. 534 * @param k The integer <code>k</code> where <code>x<sup>m</sup> + 535 * x<sup>k</sup> + 1</code> represents the reduction 536 * polynomial <code>f(z)</code>. 537 * @param a The coefficient <code>a</code> in the Weierstrass equation 538 * for non-supersingular elliptic curves over 539 * <code>F<sub>2<sup>m</sup></sub></code>. 540 * @param b The coefficient <code>b</code> in the Weierstrass equation 541 * for non-supersingular elliptic curves over 542 * <code>F<sub>2<sup>m</sup></sub></code>. 543 */ 544 public F2m( 545 int m, 546 int k, 547 BigInteger a, 548 BigInteger b) 549 { 550 this(m, k, 0, 0, a, b, null, null); 551 } 552 553 /** 554 * Constructor for Trinomial Polynomial Basis (TPB). 555 * @param m The exponent <code>m</code> of 556 * <code>F<sub>2<sup>m</sup></sub></code>. 557 * @param k The integer <code>k</code> where <code>x<sup>m</sup> + 558 * x<sup>k</sup> + 1</code> represents the reduction 559 * polynomial <code>f(z)</code>. 560 * @param a The coefficient <code>a</code> in the Weierstrass equation 561 * for non-supersingular elliptic curves over 562 * <code>F<sub>2<sup>m</sup></sub></code>. 563 * @param b The coefficient <code>b</code> in the Weierstrass equation 564 * for non-supersingular elliptic curves over 565 * <code>F<sub>2<sup>m</sup></sub></code>. 566 * @param n The order of the main subgroup of the elliptic curve. 567 * @param h The cofactor of the elliptic curve, i.e. 568 * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>. 569 */ 570 public F2m( 571 int m, 572 int k, 573 BigInteger a, 574 BigInteger b, 575 BigInteger n, 576 BigInteger h) 577 { 578 this(m, k, 0, 0, a, b, n, h); 579 } 580 581 /** 582 * Constructor for Pentanomial Polynomial Basis (PPB). 583 * @param m The exponent <code>m</code> of 584 * <code>F<sub>2<sup>m</sup></sub></code>. 585 * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> + 586 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 587 * represents the reduction polynomial <code>f(z)</code>. 588 * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> + 589 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 590 * represents the reduction polynomial <code>f(z)</code>. 591 * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> + 592 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 593 * represents the reduction polynomial <code>f(z)</code>. 594 * @param a The coefficient <code>a</code> in the Weierstrass equation 595 * for non-supersingular elliptic curves over 596 * <code>F<sub>2<sup>m</sup></sub></code>. 597 * @param b The coefficient <code>b</code> in the Weierstrass equation 598 * for non-supersingular elliptic curves over 599 * <code>F<sub>2<sup>m</sup></sub></code>. 600 */ 601 public F2m( 602 int m, 603 int k1, 604 int k2, 605 int k3, 606 BigInteger a, 607 BigInteger b) 608 { 609 this(m, k1, k2, k3, a, b, null, null); 610 } 611 612 /** 613 * Constructor for Pentanomial Polynomial Basis (PPB). 614 * @param m The exponent <code>m</code> of 615 * <code>F<sub>2<sup>m</sup></sub></code>. 616 * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> + 617 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 618 * represents the reduction polynomial <code>f(z)</code>. 619 * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> + 620 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 621 * represents the reduction polynomial <code>f(z)</code>. 622 * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> + 623 * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 624 * represents the reduction polynomial <code>f(z)</code>. 625 * @param a The coefficient <code>a</code> in the Weierstrass equation 626 * for non-supersingular elliptic curves over 627 * <code>F<sub>2<sup>m</sup></sub></code>. 628 * @param b The coefficient <code>b</code> in the Weierstrass equation 629 * for non-supersingular elliptic curves over 630 * <code>F<sub>2<sup>m</sup></sub></code>. 631 * @param n The order of the main subgroup of the elliptic curve. 632 * @param h The cofactor of the elliptic curve, i.e. 633 * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>. 634 */ 635 public F2m( 636 int m, 637 int k1, 638 int k2, 639 int k3, 640 BigInteger a, 641 BigInteger b, 642 BigInteger n, 643 BigInteger h) 644 { 645 this.m = m; 646 this.k1 = k1; 647 this.k2 = k2; 648 this.k3 = k3; 649 this.n = n; 650 this.h = h; 651 652 if (k1 == 0) 653 { 654 throw new IllegalArgumentException("k1 must be > 0"); 655 } 656 657 if (k2 == 0) 658 { 659 if (k3 != 0) 660 { 661 throw new IllegalArgumentException("k3 must be 0 if k2 == 0"); 662 } 663 } 664 else 665 { 666 if (k2 <= k1) 667 { 668 throw new IllegalArgumentException("k2 must be > k1"); 669 } 670 671 if (k3 <= k2) 672 { 673 throw new IllegalArgumentException("k3 must be > k2"); 674 } 675 } 676 677 this.infinity = new ECPoint.F2m(this, null, null); 678 this.a = fromBigInteger(a); 679 this.b = fromBigInteger(b); 680 this.coord = F2M_DEFAULT_COORDS; 681 } 682 683 protected F2m(int m, int k1, int k2, int k3, ECFieldElement a, ECFieldElement b, BigInteger n, BigInteger h) 684 { 685 this.m = m; 686 this.k1 = k1; 687 this.k2 = k2; 688 this.k3 = k3; 689 this.n = n; 690 this.h = h; 691 692 this.infinity = new ECPoint.F2m(this, null, null); 693 this.a = a; 694 this.b = b; 695 this.coord = F2M_DEFAULT_COORDS; 696 } 697 698 protected ECCurve cloneCurve() 699 { 700 return new F2m(m, k1, k2, k3, a, b, n, h); 701 } 702 703 public boolean supportsCoordinateSystem(int coord) 704 { 705 switch (coord) 706 { 707 case COORD_AFFINE: 708 case COORD_HOMOGENEOUS: 709 case COORD_LAMBDA_PROJECTIVE: 710 return true; 711 default: 712 return false; 713 } 714 } 715 716 protected ECMultiplier createDefaultMultiplier() 717 { 718 if (isKoblitz()) 719 { 720 return new WTauNafMultiplier(); 721 } 722 723 return super.createDefaultMultiplier(); 724 } 725 726 public int getFieldSize() 727 { 728 return m; 729 } 730 731 public ECFieldElement fromBigInteger(BigInteger x) 732 { 733 return new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, x); 734 } 735 736 public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression) 737 { 738 ECFieldElement X = fromBigInteger(x), Y = fromBigInteger(y); 739 740 switch (this.getCoordinateSystem()) 741 { 742 case COORD_LAMBDA_AFFINE: 743 case COORD_LAMBDA_PROJECTIVE: 744 { 745 if (!X.isZero()) 746 { 747 // Y becomes Lambda (X + Y/X) here 748 Y = Y.divide(X).add(X); 749 } 750 break; 751 } 752 default: 753 { 754 break; 755 } 756 } 757 758 return createRawPoint(X, Y, withCompression); 759 } 760 761 protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) 762 { 763 return new ECPoint.F2m(this, x, y, withCompression); 764 } 765 766 public ECPoint getInfinity() 767 { 768 return infinity; 769 } 770 771 /** 772 * Returns true if this is a Koblitz curve (ABC curve). 773 * @return true if this is a Koblitz curve (ABC curve), false otherwise 774 */ 775 public boolean isKoblitz() 776 { 777 return n != null && h != null && a.bitLength() <= 1 && b.bitLength() == 1; 778 } 779 780 /** 781 * Returns the parameter <code>μ</code> of the elliptic curve. 782 * @return <code>μ</code> of the elliptic curve. 783 * @throws IllegalArgumentException if the given ECCurve is not a 784 * Koblitz curve. 785 */ 786 synchronized byte getMu() 787 { 788 if (mu == 0) 789 { 790 mu = Tnaf.getMu(this); 791 } 792 return mu; 793 } 794 795 /** 796 * @return the auxiliary values <code>s<sub>0</sub></code> and 797 * <code>s<sub>1</sub></code> used for partial modular reduction for 798 * Koblitz curves. 799 */ 800 synchronized BigInteger[] getSi() 801 { 802 if (si == null) 803 { 804 si = Tnaf.getSi(this); 805 } 806 return si; 807 } 808 809 /** 810 * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). 811 * 812 * @param yTilde 813 * ~yp, an indication bit for the decompression of yp. 814 * @param X1 815 * The field element xp. 816 * @return the decompressed point. 817 */ 818 protected ECPoint decompressPoint(int yTilde, BigInteger X1) 819 { 820 ECFieldElement xp = fromBigInteger(X1); 821 ECFieldElement yp = null; 822 if (xp.isZero()) 823 { 824 yp = (ECFieldElement.F2m)b; 825 for (int i = 0; i < m - 1; i++) 826 { 827 yp = yp.square(); 828 } 829 } 830 else 831 { 832 ECFieldElement beta = xp.add(a).add(b.multiply(xp.square().invert())); 833 ECFieldElement z = solveQuadraticEquation(beta); 834 if (z == null) 835 { 836 throw new IllegalArgumentException("Invalid point compression"); 837 } 838 if (z.testBitZero() != (yTilde == 1)) 839 { 840 z = z.addOne(); 841 } 842 843 yp = xp.multiply(z); 844 845 switch (this.getCoordinateSystem()) 846 { 847 case COORD_LAMBDA_AFFINE: 848 case COORD_LAMBDA_PROJECTIVE: 849 { 850 yp = yp.divide(xp).add(xp); 851 break; 852 } 853 default: 854 { 855 break; 856 } 857 } 858 } 859 860 return new ECPoint.F2m(this, xp, yp, true); 861 } 862 863 /** 864 * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62 865 * D.1.6) The other solution is <code>z + 1</code>. 866 * 867 * @param beta 868 * The value to solve the quadratic equation for. 869 * @return the solution for <code>z<sup>2</sup> + z = beta</code> or 870 * <code>null</code> if no solution exists. 871 */ 872 private ECFieldElement solveQuadraticEquation(ECFieldElement beta) 873 { 874 if (beta.isZero()) 875 { 876 return beta; 877 } 878 879 ECFieldElement zeroElement = fromBigInteger(ECConstants.ZERO); 880 881 ECFieldElement z = null; 882 ECFieldElement gamma = null; 883 884 Random rand = new Random(); 885 do 886 { 887 ECFieldElement t = fromBigInteger(new BigInteger(m, rand)); 888 z = zeroElement; 889 ECFieldElement w = beta; 890 for (int i = 1; i <= m - 1; i++) 891 { 892 ECFieldElement w2 = w.square(); 893 z = z.square().add(w2.multiply(t)); 894 w = w2.add(beta); 895 } 896 if (!w.isZero()) 897 { 898 return null; 899 } 900 gamma = z.square().add(z); 901 } 902 while (gamma.isZero()); 903 904 return z; 905 } 906 907 public boolean equals( 908 Object anObject) 909 { 910 if (anObject == this) 911 { 912 return true; 913 } 914 915 if (!(anObject instanceof ECCurve.F2m)) 916 { 917 return false; 918 } 919 920 ECCurve.F2m other = (ECCurve.F2m)anObject; 921 922 return (this.m == other.m) && (this.k1 == other.k1) 923 && (this.k2 == other.k2) && (this.k3 == other.k3) 924 && a.equals(other.a) && b.equals(other.b); 925 } 926 927 public int hashCode() 928 { 929 return this.a.hashCode() ^ this.b.hashCode() ^ m ^ k1 ^ k2 ^ k3; 930 } 931 932 public int getM() 933 { 934 return m; 935 } 936 937 /** 938 * Return true if curve uses a Trinomial basis. 939 * 940 * @return true if curve Trinomial, false otherwise. 941 */ 942 public boolean isTrinomial() 943 { 944 return k2 == 0 && k3 == 0; 945 } 946 947 public int getK1() 948 { 949 return k1; 950 } 951 952 public int getK2() 953 { 954 return k2; 955 } 956 957 public int getK3() 958 { 959 return k3; 960 } 961 962 public BigInteger getN() 963 { 964 return n; 965 } 966 967 public BigInteger getH() 968 { 969 return h; 970 } 971 } 972} 973