001 /*
002 * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025 package java.security.spec;
026
027 import java.math.BigInteger;
028 import java.util.Arrays;
029
030 /**
031 * This immutable class defines an elliptic curve (EC)
032 * characteristic 2 finite field.
033 *
034 * @see ECField
035 *
036 * @author Valerie Peng
037 * @version 1.10, 05/05/07
038 *
039 * @since 1.5
040 */
041 public class ECFieldF2m implements ECField {
042
043 private int m;
044 private int[] ks;
045 private BigInteger rp;
046
047 /**
048 * Creates an elliptic curve characteristic 2 finite
049 * field which has 2^<code>m</code> elements with normal basis.
050 * @param m with 2^<code>m</code> being the number of elements.
051 * @exception IllegalArgumentException if <code>m</code>
052 * is not positive.
053 */
054 public ECFieldF2m(int m) {
055 if (m <= 0) {
056 throw new IllegalArgumentException("m is not positive");
057 }
058 this .m = m;
059 this .ks = null;
060 this .rp = null;
061 }
062
063 /**
064 * Creates an elliptic curve characteristic 2 finite
065 * field which has 2^<code>m</code> elements with
066 * polynomial basis.
067 * The reduction polynomial for this field is based
068 * on <code>rp</code> whose i-th bit correspondes to
069 * the i-th coefficient of the reduction polynomial.<p>
070 * Note: A valid reduction polynomial is either a
071 * trinomial (X^<code>m</code> + X^<code>k</code> + 1
072 * with <code>m</code> > <code>k</code> >= 1) or a
073 * pentanomial (X^<code>m</code> + X^<code>k3</code>
074 * + X^<code>k2</code> + X^<code>k1</code> + 1 with
075 * <code>m</code> > <code>k3</code> > <code>k2</code>
076 * > <code>k1</code> >= 1).
077 * @param m with 2^<code>m</code> being the number of elements.
078 * @param rp the BigInteger whose i-th bit corresponds to
079 * the i-th coefficient of the reduction polynomial.
080 * @exception NullPointerException if <code>rp</code> is null.
081 * @exception IllegalArgumentException if <code>m</code>
082 * is not positive, or <code>rp</code> does not represent
083 * a valid reduction polynomial.
084 */
085 public ECFieldF2m(int m, BigInteger rp) {
086 // check m and rp
087 this .m = m;
088 this .rp = rp;
089 if (m <= 0) {
090 throw new IllegalArgumentException("m is not positive");
091 }
092 int bitCount = this .rp.bitCount();
093 if (!this .rp.testBit(0) || !this .rp.testBit(m)
094 || ((bitCount != 3) && (bitCount != 5))) {
095 throw new IllegalArgumentException(
096 "rp does not represent a valid reduction polynomial");
097 }
098 // convert rp into ks
099 BigInteger temp = this .rp.clearBit(0).clearBit(m);
100 this .ks = new int[bitCount - 2];
101 for (int i = this .ks.length - 1; i >= 0; i--) {
102 int index = temp.getLowestSetBit();
103 this .ks[i] = index;
104 temp = temp.clearBit(index);
105 }
106 }
107
108 /**
109 * Creates an elliptic curve characteristic 2 finite
110 * field which has 2^<code>m</code> elements with
111 * polynomial basis. The reduction polynomial for this
112 * field is based on <code>ks</code> whose content
113 * contains the order of the middle term(s) of the
114 * reduction polynomial.
115 * Note: A valid reduction polynomial is either a
116 * trinomial (X^<code>m</code> + X^<code>k</code> + 1
117 * with <code>m</code> > <code>k</code> >= 1) or a
118 * pentanomial (X^<code>m</code> + X^<code>k3</code>
119 * + X^<code>k2</code> + X^<code>k1</code> + 1 with
120 * <code>m</code> > <code>k3</code> > <code>k2</code>
121 * > <code>k1</code> >= 1), so <code>ks</code> should
122 * have length 1 or 3.
123 * @param m with 2^<code>m</code> being the number of elements.
124 * @param ks the order of the middle term(s) of the
125 * reduction polynomial. Contents of this array are copied
126 * to protect against subsequent modification.
127 * @exception NullPointerException if <code>ks</code> is null.
128 * @exception IllegalArgumentException if<code>m</code>
129 * is not positive, or the length of <code>ks</code>
130 * is neither 1 nor 3, or values in <code>ks</code>
131 * are not between <code>m</code>-1 and 1 (inclusive)
132 * and in descending order.
133 */
134 public ECFieldF2m(int m, int[] ks) {
135 // check m and ks
136 this .m = m;
137 this .ks = (int[]) ks.clone();
138 if (m <= 0) {
139 throw new IllegalArgumentException("m is not positive");
140 }
141 if ((this .ks.length != 1) && (this .ks.length != 3)) {
142 throw new IllegalArgumentException(
143 "length of ks is neither 1 nor 3");
144 }
145 for (int i = 0; i < this .ks.length; i++) {
146 if ((this .ks[i] < 1) || (this .ks[i] > m - 1)) {
147 throw new IllegalArgumentException("ks[" + i
148 + "] is out of range");
149 }
150 if ((i != 0) && (this .ks[i] >= this .ks[i - 1])) {
151 throw new IllegalArgumentException(
152 "values in ks are not in descending order");
153 }
154 }
155 // convert ks into rp
156 this .rp = BigInteger.ONE;
157 this .rp = rp.setBit(m);
158 for (int j = 0; j < this .ks.length; j++) {
159 rp = rp.setBit(this .ks[j]);
160 }
161 }
162
163 /**
164 * Returns the field size in bits which is <code>m</code>
165 * for this characteristic 2 finite field.
166 * @return the field size in bits.
167 */
168 public int getFieldSize() {
169 return m;
170 }
171
172 /**
173 * Returns the value <code>m</code> of this characteristic
174 * 2 finite field.
175 * @return <code>m</code> with 2^<code>m</code> being the
176 * number of elements.
177 */
178 public int getM() {
179 return m;
180 }
181
182 /**
183 * Returns a BigInteger whose i-th bit corresponds to the
184 * i-th coefficient of the reduction polynomial for polynomial
185 * basis or null for normal basis.
186 * @return a BigInteger whose i-th bit corresponds to the
187 * i-th coefficient of the reduction polynomial for polynomial
188 * basis or null for normal basis.
189 */
190 public BigInteger getReductionPolynomial() {
191 return rp;
192 }
193
194 /**
195 * Returns an integer array which contains the order of the
196 * middle term(s) of the reduction polynomial for polynomial
197 * basis or null for normal basis.
198 * @return an integer array which contains the order of the
199 * middle term(s) of the reduction polynomial for polynomial
200 * basis or null for normal basis. A new array is returned
201 * each time this method is called.
202 */
203 public int[] getMidTermsOfReductionPolynomial() {
204 if (ks == null) {
205 return null;
206 } else {
207 return (int[]) ks.clone();
208 }
209 }
210
211 /**
212 * Compares this finite field for equality with the
213 * specified object.
214 * @param obj the object to be compared.
215 * @return true if <code>obj</code> is an instance
216 * of ECFieldF2m and both <code>m</code> and the reduction
217 * polynomial match, false otherwise.
218 */
219 public boolean equals(Object obj) {
220 if (this == obj)
221 return true;
222 if (obj instanceof ECFieldF2m) {
223 // no need to compare rp here since ks and rp
224 // should be equivalent
225 return ((m == ((ECFieldF2m) obj).m) && (Arrays.equals(ks,
226 ((ECFieldF2m) obj).ks)));
227 }
228 return false;
229 }
230
231 /**
232 * Returns a hash code value for this characteristic 2
233 * finite field.
234 * @return a hash code value.
235 */
236 public int hashCode() {
237 int value = m << 5;
238 value += (rp == null ? 0 : rp.hashCode());
239 // no need to involve ks here since ks and rp
240 // should be equivalent.
241 return value;
242 }
243 }
|