1 /* 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.security.spec; 26 27 import java.math.BigInteger; 28 import java.util.Arrays; 29 30 /** 31 * This immutable class defines an elliptic curve (EC) 32 * characteristic 2 finite field. 33 * 34 * @see ECField 35 * 36 * @author Valerie Peng 37 * 38 * @since 1.5 39 */ 40 public class ECFieldF2m implements ECField { 41 42 private int m; 43 private int[] ks; 44 private BigInteger rp; 45 46 /** 47 * Creates an elliptic curve characteristic 2 finite 48 * field which has 2^{@code m} elements with normal basis. 49 * @param m with 2^{@code m} being the number of elements. 50 * @exception IllegalArgumentException if {@code m} 51 * is not positive. 52 */ ECFieldF2m(int m)53 public ECFieldF2m(int m) { 54 if (m <= 0) { 55 throw new IllegalArgumentException("m is not positive"); 56 } 57 this.m = m; 58 this.ks = null; 59 this.rp = null; 60 } 61 62 /** 63 * Creates an elliptic curve characteristic 2 finite 64 * field which has 2^{@code m} elements with 65 * polynomial basis. 66 * The reduction polynomial for this field is based 67 * on {@code rp} whose i-th bit corresponds to 68 * the i-th coefficient of the reduction polynomial.<p> 69 * Note: A valid reduction polynomial is either a 70 * trinomial (X^{@code m} + X^{@code k} + 1 71 * with {@code m} > {@code k} >= 1) or a 72 * pentanomial (X^{@code m} + X^{@code k3} 73 * + X^{@code k2} + X^{@code k1} + 1 with 74 * {@code m} > {@code k3} > {@code k2} 75 * > {@code k1} >= 1). 76 * @param m with 2^{@code m} being the number of elements. 77 * @param rp the BigInteger whose i-th bit corresponds to 78 * the i-th coefficient of the reduction polynomial. 79 * @exception NullPointerException if {@code rp} is null. 80 * @exception IllegalArgumentException if {@code m} 81 * is not positive, or {@code rp} does not represent 82 * a valid reduction polynomial. 83 */ ECFieldF2m(int m, BigInteger rp)84 public ECFieldF2m(int m, BigInteger rp) { 85 // check m and rp 86 this.m = m; 87 this.rp = rp; 88 if (m <= 0) { 89 throw new IllegalArgumentException("m is not positive"); 90 } 91 int bitCount = this.rp.bitCount(); 92 if (!this.rp.testBit(0) || !this.rp.testBit(m) || 93 ((bitCount != 3) && (bitCount != 5))) { 94 throw new IllegalArgumentException 95 ("rp does not represent a valid reduction polynomial"); 96 } 97 // convert rp into ks 98 BigInteger temp = this.rp.clearBit(0).clearBit(m); 99 this.ks = new int[bitCount-2]; 100 for (int i = this.ks.length-1; i >= 0; i--) { 101 int index = temp.getLowestSetBit(); 102 this.ks[i] = index; 103 temp = temp.clearBit(index); 104 } 105 } 106 107 /** 108 * Creates an elliptic curve characteristic 2 finite 109 * field which has 2^{@code m} elements with 110 * polynomial basis. The reduction polynomial for this 111 * field is based on {@code ks} whose content 112 * contains the order of the middle term(s) of the 113 * reduction polynomial. 114 * Note: A valid reduction polynomial is either a 115 * trinomial (X^{@code m} + X^{@code k} + 1 116 * with {@code m} > {@code k} >= 1) or a 117 * pentanomial (X^{@code m} + X^{@code k3} 118 * + X^{@code k2} + X^{@code k1} + 1 with 119 * {@code m} > {@code k3} > {@code k2} 120 * > {@code k1} >= 1), so {@code ks} should 121 * have length 1 or 3. 122 * @param m with 2^{@code m} being the number of elements. 123 * @param ks the order of the middle term(s) of the 124 * reduction polynomial. Contents of this array are copied 125 * to protect against subsequent modification. 126 * @exception NullPointerException if {@code ks} is null. 127 * @exception IllegalArgumentException if{@code m} 128 * is not positive, or the length of {@code ks} 129 * is neither 1 nor 3, or values in {@code ks} 130 * are not between {@code m}-1 and 1 (inclusive) 131 * and in descending order. 132 */ ECFieldF2m(int m, int[] ks)133 public ECFieldF2m(int m, int[] ks) { 134 // check m and ks 135 this.m = m; 136 this.ks = ks.clone(); 137 if (m <= 0) { 138 throw new IllegalArgumentException("m is not positive"); 139 } 140 if ((this.ks.length != 1) && (this.ks.length != 3)) { 141 throw new IllegalArgumentException 142 ("length of ks is neither 1 nor 3"); 143 } 144 for (int i = 0; i < this.ks.length; i++) { 145 if ((this.ks[i] < 1) || (this.ks[i] > m-1)) { 146 throw new IllegalArgumentException 147 ("ks["+ i + "] is out of range"); 148 } 149 if ((i != 0) && (this.ks[i] >= this.ks[i-1])) { 150 throw new IllegalArgumentException 151 ("values in ks are not in descending order"); 152 } 153 } 154 // convert ks into rp 155 this.rp = BigInteger.ONE; 156 this.rp = rp.setBit(m); 157 for (int j = 0; j < this.ks.length; j++) { 158 rp = rp.setBit(this.ks[j]); 159 } 160 } 161 162 /** 163 * Returns the field size in bits which is {@code m} 164 * for this characteristic 2 finite field. 165 * @return the field size in bits. 166 */ getFieldSize()167 public int getFieldSize() { 168 return m; 169 } 170 171 /** 172 * Returns the value {@code m} of this characteristic 173 * 2 finite field. 174 * @return {@code m} with 2^{@code m} being the 175 * number of elements. 176 */ getM()177 public int getM() { 178 return m; 179 } 180 181 /** 182 * Returns a BigInteger whose i-th bit corresponds to the 183 * i-th coefficient of the reduction polynomial for polynomial 184 * basis or null for normal basis. 185 * @return a BigInteger whose i-th bit corresponds to the 186 * i-th coefficient of the reduction polynomial for polynomial 187 * basis or null for normal basis. 188 */ getReductionPolynomial()189 public BigInteger getReductionPolynomial() { 190 return rp; 191 } 192 193 /** 194 * Returns an integer array which contains the order of the 195 * middle term(s) of the reduction polynomial for polynomial 196 * basis or null for normal basis. 197 * @return an integer array which contains the order of the 198 * middle term(s) of the reduction polynomial for polynomial 199 * basis or null for normal basis. A new array is returned 200 * each time this method is called. 201 */ getMidTermsOfReductionPolynomial()202 public int[] getMidTermsOfReductionPolynomial() { 203 if (ks == null) { 204 return null; 205 } else { 206 return ks.clone(); 207 } 208 } 209 210 /** 211 * Compares this finite field for equality with the 212 * specified object. 213 * @param obj the object to be compared. 214 * @return true if {@code obj} is an instance 215 * of ECFieldF2m and both {@code m} and the reduction 216 * polynomial match, false otherwise. 217 */ equals(Object obj)218 public boolean equals(Object obj) { 219 if (this == obj) return true; 220 if (obj instanceof ECFieldF2m) { 221 // no need to compare rp here since ks and rp 222 // should be equivalent 223 return ((m == ((ECFieldF2m)obj).m) && 224 (Arrays.equals(ks, ((ECFieldF2m) obj).ks))); 225 } 226 return false; 227 } 228 229 /** 230 * Returns a hash code value for this characteristic 2 231 * finite field. 232 * @return a hash code value. 233 */ hashCode()234 public int hashCode() { 235 int value = m << 5; 236 value += (rp==null? 0:rp.hashCode()); 237 // no need to involve ks here since ks and rp 238 // should be equivalent. 239 return value; 240 } 241 } 242