• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2000, 2011, 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 
26 package java.security.cert;
27 
28 import java.io.ByteArrayInputStream;
29 import java.io.NotSerializableException;
30 import java.io.ObjectStreamException;
31 import java.io.Serializable;
32 import java.util.Iterator;
33 import java.util.List;
34 
35 /**
36  * An immutable sequence of certificates (a certification path).
37  * <p>
38  * This is an abstract class that defines the methods common to all
39  * <code>CertPath</code>s. Subclasses can handle different kinds of
40  * certificates (X.509, PGP, etc.).
41  * <p>
42  * All <code>CertPath</code> objects have a type, a list of
43  * <code>Certificate</code>s, and one or more supported encodings. Because the
44  * <code>CertPath</code> class is immutable, a <code>CertPath</code> cannot
45  * change in any externally visible way after being constructed. This
46  * stipulation applies to all public fields and methods of this class and any
47  * added or overridden by subclasses.
48  * <p>
49  * The type is a <code>String</code> that identifies the type of
50  * <code>Certificate</code>s in the certification path. For each
51  * certificate <code>cert</code> in a certification path <code>certPath</code>,
52  * <code>cert.getType().equals(certPath.getType())</code> must be
53  * <code>true</code>.
54  * <p>
55  * The list of <code>Certificate</code>s is an ordered <code>List</code> of
56  * zero or more <code>Certificate</code>s. This <code>List</code> and all
57  * of the <code>Certificate</code>s contained in it must be immutable.
58  * <p>
59  * Each <code>CertPath</code> object must support one or more encodings
60  * so that the object can be translated into a byte array for storage or
61  * transmission to other parties. Preferably, these encodings should be
62  * well-documented standards (such as PKCS#7). One of the encodings supported
63  * by a <code>CertPath</code> is considered the default encoding. This
64  * encoding is used if no encoding is explicitly requested (for the
65  * {@link #getEncoded() getEncoded()} method, for instance).
66  * <p>
67  * All <code>CertPath</code> objects are also <code>Serializable</code>.
68  * <code>CertPath</code> objects are resolved into an alternate
69  * {@link CertPathRep CertPathRep} object during serialization. This allows
70  * a <code>CertPath</code> object to be serialized into an equivalent
71  * representation regardless of its underlying implementation.
72  * <p>
73  * <code>CertPath</code> objects can be created with a
74  * <code>CertificateFactory</code> or they can be returned by other classes,
75  * such as a <code>CertPathBuilder</code>.
76  * <p>
77  * By convention, X.509 <code>CertPath</code>s (consisting of
78  * <code>X509Certificate</code>s), are ordered starting with the target
79  * certificate and ending with a certificate issued by the trust anchor. That
80  * is, the issuer of one certificate is the subject of the following one. The
81  * certificate representing the {@link TrustAnchor TrustAnchor} should not be
82  * included in the certification path. Unvalidated X.509 <code>CertPath</code>s
83  * may not follow these conventions. PKIX <code>CertPathValidator</code>s will
84  * detect any departure from these conventions that cause the certification
85  * path to be invalid and throw a <code>CertPathValidatorException</code>.
86  *
87  * <p> Every implementation of the Java platform is required to support the
88  * following standard <code>CertPath</code> encodings:
89  * <ul>
90  * <li><tt>PKCS7</tt></li>
91  * <li><tt>PkiPath</tt></li>
92  * </ul>
93  * These encodings are described in the <a href=
94  * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathEncodings">
95  * CertPath Encodings section</a> of the
96  * Java Cryptography Architecture Standard Algorithm Name Documentation.
97  * Consult the release documentation for your implementation to see if any
98  * other encodings are supported.
99  * <p>
100  * <b>Concurrent Access</b>
101  * <p>
102  * All <code>CertPath</code> objects must be thread-safe. That is, multiple
103  * threads may concurrently invoke the methods defined in this class on a
104  * single <code>CertPath</code> object (or more than one) with no
105  * ill effects. This is also true for the <code>List</code> returned by
106  * <code>CertPath.getCertificates</code>.
107  * <p>
108  * Requiring <code>CertPath</code> objects to be immutable and thread-safe
109  * allows them to be passed around to various pieces of code without worrying
110  * about coordinating access.  Providing this thread-safety is
111  * generally not difficult, since the <code>CertPath</code> and
112  * <code>List</code> objects in question are immutable.
113  *
114  * @see CertificateFactory
115  * @see CertPathBuilder
116  *
117  * @author      Yassir Elley
118  * @since       1.4
119  */
120 public abstract class CertPath implements Serializable {
121 
122     private static final long serialVersionUID = 6068470306649138683L;
123 
124     private String type;        // the type of certificates in this chain
125 
126     /**
127      * Creates a <code>CertPath</code> of the specified type.
128      * <p>
129      * This constructor is protected because most users should use a
130      * <code>CertificateFactory</code> to create <code>CertPath</code>s.
131      *
132      * @param type the standard name of the type of
133      * <code>Certificate</code>s in this path
134      */
CertPath(String type)135     protected CertPath(String type) {
136         this.type = type;
137     }
138 
139     /**
140      * Returns the type of <code>Certificate</code>s in this certification
141      * path. This is the same string that would be returned by
142      * {@link java.security.cert.Certificate#getType() cert.getType()}
143      * for all <code>Certificate</code>s in the certification path.
144      *
145      * @return the type of <code>Certificate</code>s in this certification
146      * path (never null)
147      */
getType()148     public String getType() {
149         return type;
150     }
151 
152     /**
153      * Returns an iteration of the encodings supported by this certification
154      * path, with the default encoding first. Attempts to modify the returned
155      * <code>Iterator</code> via its <code>remove</code> method result in an
156      * <code>UnsupportedOperationException</code>.
157      *
158      * @return an <code>Iterator</code> over the names of the supported
159      *         encodings (as Strings)
160      */
getEncodings()161     public abstract Iterator<String> getEncodings();
162 
163     /**
164      * Compares this certification path for equality with the specified
165      * object. Two <code>CertPath</code>s are equal if and only if their
166      * types are equal and their certificate <code>List</code>s (and by
167      * implication the <code>Certificate</code>s in those <code>List</code>s)
168      * are equal. A <code>CertPath</code> is never equal to an object that is
169      * not a <code>CertPath</code>.
170      * <p>
171      * This algorithm is implemented by this method. If it is overridden,
172      * the behavior specified here must be maintained.
173      *
174      * @param other the object to test for equality with this certification path
175      * @return true if the specified object is equal to this certification path,
176      * false otherwise
177      */
equals(Object other)178     public boolean equals(Object other) {
179         if (this == other)
180             return true;
181 
182         if (! (other instanceof CertPath))
183             return false;
184 
185         CertPath otherCP = (CertPath) other;
186         if (! otherCP.getType().equals(type))
187             return false;
188 
189         List<? extends Certificate> thisCertList = this.getCertificates();
190         List<? extends Certificate> otherCertList = otherCP.getCertificates();
191         return(thisCertList.equals(otherCertList));
192     }
193 
194     /**
195      * Returns the hashcode for this certification path. The hash code of
196      * a certification path is defined to be the result of the following
197      * calculation:
198      * <pre><code>
199      *  hashCode = path.getType().hashCode();
200      *  hashCode = 31*hashCode + path.getCertificates().hashCode();
201      * </code></pre>
202      * This ensures that <code>path1.equals(path2)</code> implies that
203      * <code>path1.hashCode()==path2.hashCode()</code> for any two certification
204      * paths, <code>path1</code> and <code>path2</code>, as required by the
205      * general contract of <code>Object.hashCode</code>.
206      *
207      * @return the hashcode value for this certification path
208      */
hashCode()209     public int hashCode() {
210         int hashCode = type.hashCode();
211         hashCode = 31*hashCode + getCertificates().hashCode();
212         return hashCode;
213     }
214 
215     /**
216      * Returns a string representation of this certification path.
217      * This calls the <code>toString</code> method on each of the
218      * <code>Certificate</code>s in the path.
219      *
220      * @return a string representation of this certification path
221      */
toString()222     public String toString() {
223         StringBuffer sb = new StringBuffer();
224         Iterator<? extends Certificate> stringIterator =
225                                         getCertificates().iterator();
226 
227         sb.append("\n" + type + " Cert Path: length = "
228             + getCertificates().size() + ".\n");
229         sb.append("[\n");
230         int i = 1;
231         while (stringIterator.hasNext()) {
232             sb.append("=========================================="
233                 + "===============Certificate " + i + " start.\n");
234             Certificate stringCert = stringIterator.next();
235             sb.append(stringCert.toString());
236             sb.append("\n========================================"
237                 + "=================Certificate " + i + " end.\n\n\n");
238             i++;
239         }
240 
241         sb.append("\n]");
242         return sb.toString();
243     }
244 
245     /**
246      * Returns the encoded form of this certification path, using the default
247      * encoding.
248      *
249      * @return the encoded bytes
250      * @exception CertificateEncodingException if an encoding error occurs
251      */
getEncoded()252     public abstract byte[] getEncoded()
253         throws CertificateEncodingException;
254 
255     /**
256      * Returns the encoded form of this certification path, using the
257      * specified encoding.
258      *
259      * @param encoding the name of the encoding to use
260      * @return the encoded bytes
261      * @exception CertificateEncodingException if an encoding error occurs or
262      *   the encoding requested is not supported
263      */
getEncoded(String encoding)264     public abstract byte[] getEncoded(String encoding)
265         throws CertificateEncodingException;
266 
267     /**
268      * Returns the list of certificates in this certification path.
269      * The <code>List</code> returned must be immutable and thread-safe.
270      *
271      * @return an immutable <code>List</code> of <code>Certificate</code>s
272      *         (may be empty, but not null)
273      */
getCertificates()274     public abstract List<? extends Certificate> getCertificates();
275 
276     /**
277      * Replaces the <code>CertPath</code> to be serialized with a
278      * <code>CertPathRep</code> object.
279      *
280      * @return the <code>CertPathRep</code> to be serialized
281      *
282      * @throws ObjectStreamException if a <code>CertPathRep</code> object
283      * representing this certification path could not be created
284      */
writeReplace()285     protected Object writeReplace() throws ObjectStreamException {
286         try {
287             return new CertPathRep(type, getEncoded());
288         } catch (CertificateException ce) {
289             NotSerializableException nse =
290                 new NotSerializableException
291                     ("java.security.cert.CertPath: " + type);
292             nse.initCause(ce);
293             throw nse;
294         }
295     }
296 
297     /**
298      * Alternate <code>CertPath</code> class for serialization.
299      * @since 1.4
300      */
301     protected static class CertPathRep implements Serializable {
302 
303         private static final long serialVersionUID = 3015633072427920915L;
304 
305         /** The Certificate type */
306         private String type;
307         /** The encoded form of the cert path */
308         private byte[] data;
309 
310         /**
311          * Creates a <code>CertPathRep</code> with the specified
312          * type and encoded form of a certification path.
313          *
314          * @param type the standard name of a <code>CertPath</code> type
315          * @param data the encoded form of the certification path
316          */
CertPathRep(String type, byte[] data)317         protected CertPathRep(String type, byte[] data) {
318             this.type = type;
319             this.data = data;
320         }
321 
322         /**
323          * Returns a <code>CertPath</code> constructed from the type and data.
324          *
325          * @return the resolved <code>CertPath</code> object
326          *
327          * @throws ObjectStreamException if a <code>CertPath</code> could not
328          * be constructed
329          */
readResolve()330         protected Object readResolve() throws ObjectStreamException {
331             try {
332                 CertificateFactory cf = CertificateFactory.getInstance(type);
333                 return cf.generateCertPath(new ByteArrayInputStream(data));
334             } catch (CertificateException ce) {
335                 NotSerializableException nse =
336                     new NotSerializableException
337                         ("java.security.cert.CertPath: " + type);
338                 nse.initCause(ce);
339                 throw nse;
340             }
341         }
342     }
343 }
344