1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package java.security.cert;
19
20 import java.io.ByteArrayInputStream;
21 import java.io.NotSerializableException;
22 import java.io.ObjectStreamException;
23 import java.io.ObjectStreamField;
24 import java.io.Serializable;
25 import java.security.InvalidKeyException;
26 import java.security.NoSuchAlgorithmException;
27 import java.security.NoSuchProviderException;
28 import java.security.PublicKey;
29 import java.security.SignatureException;
30 import java.util.Arrays;
31
32 import org.apache.harmony.security.internal.nls.Messages;
33
34 /**
35 * Abstract class to represent identity certificates. It represents a way to
36 * verify the binding of a Principal and its public key. Examples are X.509,
37 * PGP, and SDSI.
38 */
39 public abstract class Certificate implements Serializable {
40
41 private static final long serialVersionUID = -3585440601605666277L;
42
43 // The standard name of the certificate type
44 private final String type;
45
46 /**
47 * Creates a new {@code Certificate} with the specified type.
48 *
49 * @param type
50 * the certificate type.
51 */
52 protected Certificate(String type) {
53 this.type = type;
54 }
55
56 /**
57 * Returns the certificate type.
58 *
59 * @return the certificate type.
60 */
61 public final String getType() {
62 return type;
63 }
64
65 /**
66 * Compares the argument to the certificate, and returns {@code true} if they
67 * represent the <em>same</em> object using a class specific comparison. The
68 * implementation in Object returns {@code true} only if the argument is the
69 * exact same object as the callee (==).
70 *
71 * @param other
72 * the object to compare with this object.
73 * @return {@code true} if the object is the same as this object, {@code
74 * false} if it is different from this object.
75 * @see #hashCode
76 */
77 public boolean equals(Object other) {
78 // obj equal to itself
79 if (this == other) {
80 return true;
81 }
82 if (other instanceof Certificate) {
83 try {
84 // check that encoded forms match
85 return Arrays.equals(this.getEncoded(),
86 ((Certificate)other).getEncoded());
87 } catch (CertificateEncodingException e) {
88 throw new RuntimeException(e);
89 }
90 }
91 return false;
92 }
93
94 /**
95 * Returns an integer hash code for the certificate. Any two objects which
96 * return {@code true} when passed to {@code equals} must return the same
97 * value for this method.
98 *
99 * @return the certificate's hash
100 * @see #equals
101 */
102 public int hashCode() {
103 try {
104 byte[] encoded = getEncoded();
105 int hash = 0;
106 for (int i=0; i<encoded.length; i++) {
107 hash += i*encoded[i];
108 }
109 return hash;
110 } catch (CertificateEncodingException e) {
111 throw new RuntimeException(e);
112 }
113 }
114
115 /**
116 * Returns the encoded representation for this certificate.
117 *
118 * @return the encoded representation for this certificate.
119 * @throws CertificateEncodingException
120 * if the encoding fails.
121 */
122 public abstract byte[] getEncoded() throws CertificateEncodingException;
123
124 /**
125 * Verifies that this certificate was signed with the given public key.
126 *
127 * @param key
128 * PublicKey public key for which verification should be
129 * performed.
130 * @throws CertificateException
131 * if encoding errors are detected.
132 * @throws NoSuchAlgorithmException
133 * if an unsupported algorithm is detected.
134 * @throws InvalidKeyException
135 * if an invalid key is detected.
136 * @throws NoSuchProviderException
137 * if there is no default provider.
138 * @throws SignatureException
139 * if signature errors are detected.
140 */
141 public abstract void verify(PublicKey key)
142 throws CertificateException,
143 NoSuchAlgorithmException,
144 InvalidKeyException,
145 NoSuchProviderException,
146 SignatureException;
147
148 /**
149 * Verifies that this certificate was signed with the given public key. It
150 * Uses the signature algorithm given by the provider.
151 *
152 * @param key
153 * PublicKey public key for which verification should be
154 * performed.
155 * @param sigProvider
156 * String the name of the signature provider.
157 * @exception CertificateException
158 * if encoding errors are detected.
159 * @exception NoSuchAlgorithmException
160 * if an unsupported algorithm is detected.
161 * @exception InvalidKeyException
162 * if an invalid key is detected.
163 * @exception NoSuchProviderException
164 * if the specified provider does not exists.
165 * @exception SignatureException
166 * if signature errors are detected.
167 */
168 public abstract void verify(PublicKey key, String sigProvider)
169 throws CertificateException,
170 NoSuchAlgorithmException,
171 InvalidKeyException,
172 NoSuchProviderException,
173 SignatureException;
174
175 /**
176 * Returns a string containing a concise, human-readable description of the
177 * certificate.
178 *
179 * @return a printable representation for the certificate.
180 */
181 public abstract String toString();
182
183 /**
184 * Returns the public key corresponding to this certificate.
185 *
186 * @return the public key corresponding to this certificate.
187 */
188 public abstract PublicKey getPublicKey();
189
190 /**
191 * Returns an alternate object to be serialized.
192 *
193 * @return the object to serialize.
194 * @throws ObjectStreamException
195 * if the creation of the alternate object fails.
196 */
197 protected Object writeReplace() throws ObjectStreamException {
198 try {
199 return new CertificateRep(getType(), getEncoded());
200 } catch (CertificateEncodingException e) {
201 throw new NotSerializableException (
202 Messages.getString("security.66", e)); //$NON-NLS-1$
203 }
204 }
205
206 /**
207 * The alternate {@code Serializable} class to be used for serialization and
208 * deserialization of {@code Certificate} objects.
209 */
210 protected static class CertificateRep implements Serializable {
211
212 private static final long serialVersionUID = -8563758940495660020L;
213 // The standard name of the certificate type
214 private final String type;
215 // The certificate data
216 private final byte[] data;
217
218 // Force default serialization to use writeUnshared/readUnshared
219 // for the certificate data
220 private static final ObjectStreamField[] serialPersistentFields = {
221 new ObjectStreamField("type", String.class), //$NON-NLS-1$
222 new ObjectStreamField("data", byte[].class, true) //$NON-NLS-1$
223 };
224
225 /**
226 * Creates a new {@code CertificateRep} instance with the specified
227 * certificate type and encoded data.
228 *
229 * @param type
230 * the certificate type.
231 * @param data
232 * the encoded data.
233 */
234 protected CertificateRep(String type, byte[] data) {
235 this.type = type;
236 this.data = data;
237 }
238
239 /**
240 * Deserializes a {@code Certificate} from a serialized {@code
241 * CertificateRep} object.
242 *
243 * @return the deserialized {@code Certificate}.
244 * @throws ObjectStreamException
245 * if deserialization fails.
246 */
247 protected Object readResolve() throws ObjectStreamException {
248 try {
249 CertificateFactory cf = CertificateFactory.getInstance(type);
250 return cf.generateCertificate(new ByteArrayInputStream(data));
251 } catch (Throwable t) {
252 throw new NotSerializableException(
253 Messages.getString("security.68", t)); //$NON-NLS-1$
254 }
255 }
256 }
257 }