1. /*
  2. * @(#)ECFieldF2m.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 defines an elliptic curve (EC)
  12. * characteristic 2 finite field.
  13. *
  14. * @see ECField
  15. *
  16. * @author Valerie Peng
  17. * @version 1.3, 12/19/03
  18. *
  19. * @since 1.5
  20. */
  21. public class ECFieldF2m implements ECField {
  22. private int m;
  23. private int[] ks;
  24. private BigInteger rp;
  25. /**
  26. * Creates an elliptic curve characteristic 2 finite
  27. * field which has 2^<code>m</code> elements with normal basis.
  28. * @param m with 2^<code>m</code> being the number of elements.
  29. * @exception IllegalArgumentException if <code>m</code>
  30. * is not positive.
  31. */
  32. public ECFieldF2m(int m) {
  33. if (m <= 0) {
  34. throw new IllegalArgumentException("m is not positive");
  35. }
  36. this.m = m;
  37. this.ks = null;
  38. this.rp = null;
  39. }
  40. /**
  41. * Creates an elliptic curve characteristic 2 finite
  42. * field which has 2^<code>m</code> elements with
  43. * polynomial basis.
  44. * The reduction polynomial for this field is based
  45. * on <code>rp</code> whose i-th bit correspondes to
  46. * the i-th coefficient of the reduction polynomial.<p>
  47. * Note: A valid reduction polynomial is either a
  48. * trinomial (X^<code>m</code> + X^<code>k</code> + 1
  49. * with <code>m</code> > <code>k</code> >= 1) or a
  50. * pentanomial (X^<code>m</code> + X^<code>k3</code>
  51. * + X^<code>k2</code> + X^<code>k1</code> + 1 with
  52. * <code>m</code> > <code>k3</code> > <code>k2</code>
  53. * > <code>k1</code> >= 1).
  54. * @param m with 2^<code>m</code> being the number of elements.
  55. * @param rp the BigInteger whose i-th bit corresponds to
  56. * the i-th coefficient of the reduction polynomial.
  57. * @exception NullPointerException if <code>rp</code> is null.
  58. * @exception IllegalArgumentException if <code>m</code>
  59. * is not positive, or <code>rp</code> does not represent
  60. * a valid reduction polynomial.
  61. */
  62. public ECFieldF2m(int m, BigInteger rp) {
  63. // check m and rp
  64. this.m = m;
  65. this.rp = rp;
  66. if (m <= 0) {
  67. throw new IllegalArgumentException("m is not positive");
  68. }
  69. int bitCount = this.rp.bitCount();
  70. if (!this.rp.testBit(0) || !this.rp.testBit(m) ||
  71. ((bitCount != 3) && (bitCount != 5))) {
  72. throw new IllegalArgumentException
  73. ("rp does not represent a valid reduction polynomial");
  74. }
  75. // convert rp into ks
  76. BigInteger temp = this.rp.clearBit(0).clearBit(m);
  77. this.ks = new int[bitCount-2];
  78. for (int i = this.ks.length-1; i >= 0; i--) {
  79. int index = temp.getLowestSetBit();
  80. this.ks[i] = index;
  81. temp = temp.clearBit(index);
  82. }
  83. }
  84. /**
  85. * Creates an elliptic curve characteristic 2 finite
  86. * field which has 2^<code>m</code> elements with
  87. * polynomial basis. The reduction polynomial for this
  88. * field is based on <code>ks</code> whose content
  89. * contains the order of the middle term(s) of the
  90. * reduction polynomial.
  91. * Note: A valid reduction polynomial is either a
  92. * trinomial (X^<code>m</code> + X^<code>k</code> + 1
  93. * with <code>m</code> > <code>k</code> >= 1) or a
  94. * pentanomial (X^<code>m</code> + X^<code>k3</code>
  95. * + X^<code>k2</code> + X^<code>k1</code> + 1 with
  96. * <code>m</code> > <code>k3</code> > <code>k2</code>
  97. * > <code>k1</code> >= 1), so <code>ks</code> should
  98. * have length 1 or 3.
  99. * @param m with 2^<code>m</code> being the number of elements.
  100. * @param ks the order of the middle term(s) of the
  101. * reduction polynomial. Contents of this array are copied
  102. * to protect against subsequent modification.
  103. * @exception NullPointerException if <code>ks</code> is null.
  104. * @exception IllegalArgumentException if<code>m</code>
  105. * is not positive, or the length of <code>ks</code>
  106. * is neither 1 nor 3, or values in <code>ks</code>
  107. * are not between <code>m</code>-1 and 1 (inclusive)
  108. * and in descending order.
  109. */
  110. public ECFieldF2m(int m, int[] ks) {
  111. // check m and ks
  112. this.m = m;
  113. this.ks = (int[]) ks.clone();
  114. if (m <= 0) {
  115. throw new IllegalArgumentException("m is not positive");
  116. }
  117. if ((this.ks.length != 1) && (this.ks.length != 3)) {
  118. throw new IllegalArgumentException
  119. ("length of ks is neither 1 nor 3");
  120. }
  121. for (int i = 0; i < this.ks.length; i++) {
  122. if ((this.ks[i] < 1) || (this.ks[i] > m-1)) {
  123. throw new IllegalArgumentException
  124. ("ks["+ i + "] is out of range");
  125. }
  126. if ((i != 0) && (this.ks[i] >= this.ks[i-1])) {
  127. throw new IllegalArgumentException
  128. ("values in ks are not in descending order");
  129. }
  130. }
  131. // convert ks into rp
  132. this.rp = BigInteger.ONE;
  133. this.rp = rp.setBit(m);
  134. for (int j = 0; j < this.ks.length; j++) {
  135. rp = rp.setBit(this.ks[j]);
  136. }
  137. }
  138. /**
  139. * Returns the field size in bits which is <code>m</code>
  140. * for this characteristic 2 finite field.
  141. * @return the field size in bits.
  142. */
  143. public int getFieldSize() {
  144. return m;
  145. }
  146. /**
  147. * Returns the value <code>m</code> of this characteristic
  148. * 2 finite field.
  149. * @return <code>m</code> with 2^<code>m</code> being the
  150. * number of elements.
  151. */
  152. public int getM() {
  153. return m;
  154. }
  155. /**
  156. * Returns a BigInteger whose i-th bit corresponds to the
  157. * i-th coefficient of the reduction polynomial for polynomial
  158. * basis or null for normal basis.
  159. * @return a BigInteger whose i-th bit corresponds to the
  160. * i-th coefficient of the reduction polynomial for polynomial
  161. * basis or null for normal basis.
  162. */
  163. public BigInteger getReductionPolynomial() {
  164. return rp;
  165. }
  166. /**
  167. * Returns an integer array which contains the order of the
  168. * middle term(s) of the reduction polynomial for polynomial
  169. * basis or null for normal basis.
  170. * @return an integer array which contains the order of the
  171. * middle term(s) of the reduction polynomial for polynomial
  172. * basis or null for normal basis. A new array is returned
  173. * each time this method is called.
  174. */
  175. public int[] getMidTermsOfReductionPolynomial() {
  176. if (ks == null) {
  177. return null;
  178. } else {
  179. return (int[]) ks.clone();
  180. }
  181. }
  182. /**
  183. * Compares this finite field for equality with the
  184. * specified object.
  185. * @param obj the object to be compared.
  186. * @return true if <code>obj</code> is an instance
  187. * of ECFieldF2m and both <code>m</code> and the reduction
  188. * polynomial match, false otherwise.
  189. */
  190. public boolean equals(Object obj) {
  191. if (this == obj) return true;
  192. if (obj instanceof ECFieldF2m) {
  193. // no need to compare rp here since ks and rp
  194. // should be equivalent
  195. return ((m == ((ECFieldF2m)obj).m) &&
  196. (Arrays.equals(ks, ((ECFieldF2m) obj).ks)));
  197. }
  198. return false;
  199. }
  200. /**
  201. * Returns a hash code value for this characteristic 2
  202. * finite field.
  203. * @return a hash code value.
  204. */
  205. public int hashCode() {
  206. int value = m << 5;
  207. value += (rp==null? 0:rp.hashCode());
  208. // no need to involve ks here since ks and rp
  209. // should be equivalent.
  210. return value;
  211. }
  212. }