1 /*
2 * Copyright 2003-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package java.security.spec;
27
28 import java.math.BigInteger;
29 import java.util.Arrays;
30
31 /**
32 * This immutable class holds the necessary values needed to represent
33 * an elliptic curve.
34 *
35 * @see ECField
36 * @see ECFieldFp
37 * @see ECFieldF2m
38 *
39 * @author Valerie Peng
40 *
41 * @since 1.5
42 */
43 public class EllipticCurve {
44
45 private final ECField field;
46 private final BigInteger a;
47 private final BigInteger b;
48 private final byte[] seed;
49
50 // Check coefficient c is a valid element in ECField field.
51 private static void checkValidity(ECField field, BigInteger c,
52 String cName) {
53 // can only perform check if field is ECFieldFp or ECFieldF2m.
54 if (field instanceof ECFieldFp) {
55 BigInteger p = ((ECFieldFp)field).getP();
56 if (p.compareTo(c) != 1) {
57 throw new IllegalArgumentException(cName + " is too large");
58 } else if (c.signum() < 0) {
59 throw new IllegalArgumentException(cName + " is negative");
60 }
61 } else if (field instanceof ECFieldF2m) {
62 int m = ((ECFieldF2m)field).getM();
63 if (c.bitLength() > m) {
64 throw new IllegalArgumentException(cName + " is too large");
65 }
66 }
67 }
68
69 /**
70 * Creates an elliptic curve with the specified elliptic field
71 * <code>field</code> and the coefficients <code>a</code> and
72 * <code>b</code>.
73 * @param field the finite field that this elliptic curve is over.
74 * @param a the first coefficient of this elliptic curve.
75 * @param b the second coefficient of this elliptic curve.
76 * @exception NullPointerException if <code>field</code>,
77 * <code>a</code>, or <code>b</code> is null.
78 * @exception IllegalArgumentException if <code>a</code>
79 * or <code>b</code> is not null and not in <code>field</code>.
80 */
81 public EllipticCurve(ECField field, BigInteger a,
82 BigInteger b) {
83 this(field, a, b, null);
84 }
85
86 /**
87 * Creates an elliptic curve with the specified elliptic field
88 * <code>field</code>, the coefficients <code>a</code> and
89 * <code>b</code>, and the <code>seed</code> used for curve generation.
90 * @param field the finite field that this elliptic curve is over.
91 * @param a the first coefficient of this elliptic curve.
92 * @param b the second coefficient of this elliptic curve.
93 * @param seed the bytes used during curve generation for later
94 * validation. Contents of this array are copied to protect against
95 * subsequent modification.
96 * @exception NullPointerException if <code>field</code>,
97 * <code>a</code>, or <code>b</code> is null.
98 * @exception IllegalArgumentException if <code>a</code>
99 * or <code>b</code> is not null and not in <code>field</code>.
100 */
101 public EllipticCurve(ECField field, BigInteger a,
102 BigInteger b, byte[] seed) {
103 if (field == null) {
104 throw new NullPointerException("field is null");
105 }
106 if (a == null) {
107 throw new NullPointerException("first coefficient is null");
108 }
109 if (b == null) {
110 throw new NullPointerException("second coefficient is null");
111 }
112 checkValidity(field, a, "first coefficient");
113 checkValidity(field, b, "second coefficient");
114 this.field = field;
115 this.a = a;
116 this.b = b;
117 if (seed != null) {
118 this.seed = seed.clone();
119 } else {
120 this.seed = null;
121 }
122 }
123
124 /**
125 * Returns the finite field <code>field</code> that this
126 * elliptic curve is over.
127 * @return the field <code>field</code> that this curve
128 * is over.
129 */
130 public ECField getField() {
131 return field;
132 }
133
134 /**
135 * Returns the first coefficient <code>a</code> of the
136 * elliptic curve.
137 * @return the first coefficient <code>a</code>.
138 */
139 public BigInteger getA() {
140 return a;
141 }
142
143 /**
144 * Returns the second coefficient <code>b</code> of the
145 * elliptic curve.
146 * @return the second coefficient <code>b</code>.
147 */
148 public BigInteger getB() {
149 return b;
150 }
151
152 /**
153 * Returns the seeding bytes <code>seed</code> used
154 * during curve generation. May be null if not specified.
155 * @return the seeding bytes <code>seed</code>. A new
156 * array is returned each time this method is called.
157 */
158 public byte[] getSeed() {
159 if (seed == null) return null;
160 else return seed.clone();
161 }
162
163 /**
164 * Compares this elliptic curve for equality with the
165 * specified object.
166 * @param obj the object to be compared.
167 * @return true if <code>obj</code> is an instance of
168 * EllipticCurve and the field, A, B, and seeding bytes
169 * match, false otherwise.
170 */
171 public boolean equals(Object obj) {
172 if (this == obj) return true;
173 if (obj instanceof EllipticCurve) {
174 EllipticCurve curve = (EllipticCurve) obj;
175 if ((field.equals(curve.field)) &&
176 (a.equals(curve.a)) &&
177 (b.equals(curve.b)) &&
178 (Arrays.equals(seed, curve.seed))) {
179 return true;
180 }
181 }
182 return false;
183 }
184
185 /**
186 * Returns a hash code value for this elliptic curve.
187 * @return a hash code value.
188 */
189 public int hashCode() {
190 return (field.hashCode() << 6 +
191 (a.hashCode() << 4) +
192 (b.hashCode() << 2) +
193 (seed==null? 0:seed.length));
194 }
195 }