1. /*
  2. * @(#)EllipticCurve.java 1.3 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.security.spec;
  8. import java.math.BigInteger;
  9. import java.util.Arrays;
  10. /**
  11. * This immutable class holds the necessary values needed to represent
  12. * an elliptic curve.
  13. *
  14. * @see ECField
  15. * @see ECFieldFp
  16. * @see ECFieldF2m
  17. *
  18. * @author Valerie Peng
  19. * @version 1.3, 12/19/03
  20. *
  21. * @since 1.5
  22. */
  23. public class EllipticCurve {
  24. private final ECField field;
  25. private final BigInteger a;
  26. private final BigInteger b;
  27. private final byte[] seed;
  28. // Check coefficient c is a valid element in ECField field.
  29. private static void checkValidity(ECField field, BigInteger c,
  30. String cName) {
  31. // can only perform check if field is ECFieldFp or ECFieldF2m.
  32. if (field instanceof ECFieldFp) {
  33. BigInteger p = ((ECFieldFp)field).getP();
  34. if (p.compareTo(c) != 1) {
  35. throw new IllegalArgumentException(cName + " is too large");
  36. } else if (c.signum() != 1) {
  37. throw new IllegalArgumentException(cName + " is negative");
  38. }
  39. } else if (field instanceof ECFieldF2m) {
  40. int m = ((ECFieldF2m)field).getM();
  41. if (c.bitLength() > m) {
  42. throw new IllegalArgumentException(cName + " is too large");
  43. }
  44. }
  45. }
  46. /**
  47. * Creates an elliptic curve with the specified elliptic field
  48. * <code>field</code> and the coefficients <code>a</code> and
  49. * <code>b</code>.
  50. * @param field the finite field that this elliptic curve is over.
  51. * @param a the first coefficient of this elliptic curve.
  52. * @param b the second coefficient of this elliptic curve.
  53. * @exception NullPointerException if <code>field</code>,
  54. * <code>a</code>, or <code>b</code> is null.
  55. * @exception IllegalArgumentException if <code>a</code>
  56. * or <code>b</code> is not null and not in <code>field</code>.
  57. */
  58. public EllipticCurve(ECField field, BigInteger a,
  59. BigInteger b) {
  60. this(field, a, b, null);
  61. }
  62. /**
  63. * Creates an elliptic curve with the specified elliptic field
  64. * <code>field</code>, the coefficients <code>a</code> and
  65. * <code>b</code>, and the <code>seed</code> used for curve generation.
  66. * @param field the finite field that this elliptic curve is over.
  67. * @param a the first coefficient of this elliptic curve.
  68. * @param b the second coefficient of this elliptic curve.
  69. * @param seed the bytes used during curve generation for later
  70. * validation. Contents of this array are copied to protect against
  71. * subsequent modification.
  72. * @exception NullPointerException if <code>field</code>,
  73. * <code>a</code>, or <code>b</code> is null.
  74. * @exception IllegalArgumentException if <code>a</code>
  75. * or <code>b</code> is not null and not in <code>field</code>.
  76. */
  77. public EllipticCurve(ECField field, BigInteger a,
  78. BigInteger b, byte[] seed) {
  79. if (field == null) {
  80. throw new NullPointerException("field is null");
  81. }
  82. if (a == null) {
  83. throw new NullPointerException("first coefficient is null");
  84. }
  85. if (b == null) {
  86. throw new NullPointerException("second coefficient is null");
  87. }
  88. checkValidity(field, a, "first coefficient");
  89. checkValidity(field, b, "second coefficient");
  90. this.field = field;
  91. this.a = a;
  92. this.b = b;
  93. if (seed != null) {
  94. this.seed = (byte[]) seed.clone();
  95. } else {
  96. this.seed = null;
  97. }
  98. }
  99. /**
  100. * Returns the finite field <code>field</code> that this
  101. * elliptic curve is over.
  102. * @return the field <code>field</code> that this curve
  103. * is over.
  104. */
  105. public ECField getField() {
  106. return field;
  107. }
  108. /**
  109. * Returns the first coefficient <code>a</code> of the
  110. * elliptic curve.
  111. * @return the first coefficient <code>a</code>.
  112. */
  113. public BigInteger getA() {
  114. return a;
  115. }
  116. /**
  117. * Returns the second coefficient <code>b</code> of the
  118. * elliptic curve.
  119. * @return the second coefficient <code>b</code>.
  120. */
  121. public BigInteger getB() {
  122. return b;
  123. }
  124. /**
  125. * Returns the seeding bytes <code>seed</code> used
  126. * during curve generation. May be null if not specified.
  127. * @return the seeding bytes <code>seed</code>. A new
  128. * array is returned each time this method is called.
  129. */
  130. public byte[] getSeed() {
  131. if (seed == null) return null;
  132. else return (byte[]) seed.clone();
  133. }
  134. /**
  135. * Compares this elliptic curve for equality with the
  136. * specified object.
  137. * @param obj the object to be compared.
  138. * @return true if <code>obj</code> is an instance of
  139. * EllipticCurve and the field, A, B, and seeding bytes
  140. * match, false otherwise.
  141. */
  142. public boolean equals(Object obj) {
  143. if (this == obj) return true;
  144. if (obj instanceof EllipticCurve) {
  145. EllipticCurve curve = (EllipticCurve) obj;
  146. if ((field.equals(curve.field)) &&
  147. (a.equals(curve.a)) &&
  148. (b.equals(curve.b)) &&
  149. (Arrays.equals(seed, curve.seed))) {
  150. return true;
  151. }
  152. }
  153. return false;
  154. }
  155. /**
  156. * Returns a hash code value for this elliptic curve.
  157. * @return a hash code value.
  158. */
  159. public int hashCode() {
  160. return (field.hashCode() << 6 +
  161. (a.hashCode() << 4) +
  162. (b.hashCode() << 2) +
  163. (seed==null? 0:seed.length));
  164. }
  165. }