1 package org.bouncycastle.math.ec; 2 3 import java.math.BigInteger; 4 import java.util.Random; 5 6 import org.bouncycastle.util.BigIntegers; 7 8 /** 9 * base class for an elliptic curve 10 */ 11 public 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 getAllCoordinateSystems()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 Config(int coord, ECMultiplier multiplier)33 Config(int coord, ECMultiplier multiplier) 34 { 35 this.coord = coord; 36 this.multiplier = multiplier; 37 } 38 setCoordinateSystem(int coord)39 public Config setCoordinateSystem(int coord) 40 { 41 this.coord = coord; 42 return this; 43 } 44 setMultiplier(ECMultiplier multiplier)45 public Config setMultiplier(ECMultiplier multiplier) 46 { 47 this.multiplier = multiplier; 48 return this; 49 } 50 create()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 getFieldSize()75 public abstract int getFieldSize(); 76 fromBigInteger(BigInteger x)77 public abstract ECFieldElement fromBigInteger(BigInteger x); 78 configure()79 public Config configure() 80 { 81 return new Config(this.coord, this.multiplier); 82 } 83 createPoint(BigInteger x, BigInteger y)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 */ createPoint(BigInteger x, BigInteger y, boolean withCompression)93 public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression) 94 { 95 return createRawPoint(fromBigInteger(x), fromBigInteger(y), withCompression); 96 } 97 cloneCurve()98 protected abstract ECCurve cloneCurve(); 99 createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)100 protected abstract ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression); 101 createDefaultMultiplier()102 protected ECMultiplier createDefaultMultiplier() 103 { 104 return new WNafL2RMultiplier(); 105 } 106 supportsCoordinateSystem(int coord)107 public boolean supportsCoordinateSystem(int coord) 108 { 109 return coord == COORD_AFFINE; 110 } 111 getPreCompInfo(ECPoint p)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 */ setPreCompInfo(ECPoint point, PreCompInfo preCompInfo)128 public void setPreCompInfo(ECPoint point, PreCompInfo preCompInfo) 129 { 130 checkPoint(point); 131 point.preCompInfo = preCompInfo; 132 } 133 importPoint(ECPoint p)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 */ normalizeAll(ECPoint[] points)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 getInfinity()200 public abstract ECPoint getInfinity(); 201 getA()202 public ECFieldElement getA() 203 { 204 return a; 205 } 206 getB()207 public ECFieldElement getB() 208 { 209 return b; 210 } 211 getCoordinateSystem()212 public int getCoordinateSystem() 213 { 214 return coord; 215 } 216 decompressPoint(int yTilde, BigInteger X1)217 protected abstract ECPoint decompressPoint(int yTilde, BigInteger X1); 218 219 /** 220 * Sets the default <code>ECMultiplier</code>, unless already set. 221 */ getMultiplier()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 */ decodePoint(byte[] encoded)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 checkPoint(ECPoint point)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 checkPoints(ECPoint[] points)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 Fp(BigInteger q, BigInteger a, BigInteger b)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 Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b)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 cloneCurve()347 protected ECCurve cloneCurve() 348 { 349 return new Fp(q, r, a, b); 350 } 351 supportsCoordinateSystem(int coord)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 getQ()366 public BigInteger getQ() 367 { 368 return q; 369 } 370 getFieldSize()371 public int getFieldSize() 372 { 373 return q.bitLength(); 374 } 375 fromBigInteger(BigInteger x)376 public ECFieldElement fromBigInteger(BigInteger x) 377 { 378 return new ECFieldElement.Fp(this.q, this.r, x); 379 } 380 createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)381 protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) 382 { 383 return new ECPoint.Fp(this, x, y, withCompression); 384 } 385 importPoint(ECPoint p)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 decompressPoint(int yTilde, BigInteger X1)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 getInfinity()433 public ECPoint getInfinity() 434 { 435 return infinity; 436 } 437 equals( Object anObject)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 hashCode()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 */ F2m( int m, int k, BigInteger a, BigInteger b)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 */ F2m( int m, int k, BigInteger a, BigInteger b, BigInteger n, BigInteger h)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 */ F2m( int m, int k1, int k2, int k3, BigInteger a, BigInteger b)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 */ F2m( int m, int k1, int k2, int k3, BigInteger a, BigInteger b, BigInteger n, BigInteger h)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 F2m(int m, int k1, int k2, int k3, ECFieldElement a, ECFieldElement b, BigInteger n, BigInteger h)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 cloneCurve()698 protected ECCurve cloneCurve() 699 { 700 return new F2m(m, k1, k2, k3, a, b, n, h); 701 } 702 supportsCoordinateSystem(int coord)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 createDefaultMultiplier()716 protected ECMultiplier createDefaultMultiplier() 717 { 718 if (isKoblitz()) 719 { 720 return new WTauNafMultiplier(); 721 } 722 723 return super.createDefaultMultiplier(); 724 } 725 getFieldSize()726 public int getFieldSize() 727 { 728 return m; 729 } 730 fromBigInteger(BigInteger x)731 public ECFieldElement fromBigInteger(BigInteger x) 732 { 733 return new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, x); 734 } 735 createPoint(BigInteger x, BigInteger y, boolean withCompression)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 createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)761 protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) 762 { 763 return new ECPoint.F2m(this, x, y, withCompression); 764 } 765 getInfinity()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 */ isKoblitz()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 */ getMu()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 */ getSi()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 */ decompressPoint(int yTilde, BigInteger X1)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 */ solveQuadraticEquation(ECFieldElement beta)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 equals( Object anObject)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 hashCode()927 public int hashCode() 928 { 929 return this.a.hashCode() ^ this.b.hashCode() ^ m ^ k1 ^ k2 ^ k3; 930 } 931 getM()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 */ isTrinomial()942 public boolean isTrinomial() 943 { 944 return k2 == 0 && k3 == 0; 945 } 946 getK1()947 public int getK1() 948 { 949 return k1; 950 } 951 getK2()952 public int getK2() 953 { 954 return k2; 955 } 956 getK3()957 public int getK3() 958 { 959 return k3; 960 } 961 getN()962 public BigInteger getN() 963 { 964 return n; 965 } 966 getH()967 public BigInteger getH() 968 { 969 return h; 970 } 971 } 972 } 973