001    /* Certificate.java --- Certificate class
002       Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package java.security.cert;
040    
041    import java.io.ByteArrayInputStream;
042    import java.io.InvalidObjectException;
043    import java.io.ObjectStreamException;
044    import java.io.Serializable;
045    import java.security.InvalidKeyException;
046    import java.security.NoSuchAlgorithmException;
047    import java.security.NoSuchProviderException;
048    import java.security.PublicKey;
049    import java.security.SignatureException;
050    
051    /**
052     * The Certificate class is an abstract class used to manage
053     * identity certificates. An identity certificate is a
054     * combination of a principal and a public key which is
055     * certified by another principal. This is the puprose of
056     * Certificate Authorities (CA).
057     *
058     * <p>This class is used to manage different types of certificates
059     * but have important common puposes. Different types of
060     * certificates like X.509 and OpenPGP share general certificate
061     * functions (like encoding and verifying) and information like
062     * public keys.
063     *
064     * <p>X.509, OpenPGP, and SDSI can be implemented by subclassing this
065     * class even though they differ in storage methods and information
066     * stored.
067     *
068     * @see CertificateFactory
069     * @see X509Certificate
070     * @since JDK 1.2
071     * @author Mark Benvenuto
072     * @author Casey Marshall
073     */
074    public abstract class Certificate implements Serializable
075    {
076      private static final long serialVersionUID = -3585440601605666277L;
077    
078      private String type;
079    
080      /**
081         Constructs a new certificate of the specified type. An example
082         is "X.509".
083    
084         @param type a valid standard name for a certificate.
085      */
086      protected Certificate(String type)
087      {
088        this.type = type;
089      }
090    
091      /**
092         Returns the Certificate type.
093    
094         @return a string representing the Certificate type
095      */
096      public final String getType()
097      {
098        return type;
099      }
100    
101      /**
102         Compares this Certificate to other. It checks if the
103         object if instanceOf Certificate and then checks if
104         the encoded form matches.
105    
106         @param other An Object to test for equality
107    
108         @return true if equal, false otherwise
109      */
110      public boolean equals(Object other)
111      {
112        if( other instanceof Certificate ) {
113          try {
114            Certificate x = (Certificate) other;
115            if( getEncoded().length != x.getEncoded().length )
116              return false;
117    
118            byte[] b1 = getEncoded();
119            byte[] b2 = x.getEncoded();
120    
121            for( int i = 0; i < b1.length; i++ )
122              if( b1[i] != b2[i] )
123                return false;
124    
125          } catch( CertificateEncodingException cee ) {
126            return false;
127          }
128          return true;
129        }
130        return false;
131      }
132    
133      /**
134         Returns a hash code for this Certificate in its encoded
135         form.
136    
137         @return A hash code of this class
138      */
139      public int hashCode()
140      {
141        return super.hashCode();
142      }
143    
144      /**
145         Gets the DER ASN.1 encoded format for this Certificate.
146         It assumes each certificate has only one encoding format.
147         Ex: X.509 is encoded as ASN.1 DER
148    
149         @return byte array containg encoded form
150    
151         @throws CertificateEncodingException if an error occurs
152      */
153      public abstract byte[] getEncoded() throws CertificateEncodingException;
154    
155      /**
156         Verifies that this Certificate was properly signed with the
157         PublicKey that corresponds to its private key.
158    
159         @param key PublicKey to verify with
160    
161         @throws CertificateException encoding error
162         @throws NoSuchAlgorithmException unsupported algorithm
163         @throws InvalidKeyException incorrect key
164         @throws NoSuchProviderException no provider
165         @throws SignatureException signature error
166      */
167      public abstract void verify(PublicKey key)
168        throws CertificateException,
169        NoSuchAlgorithmException,
170        InvalidKeyException,
171        NoSuchProviderException,
172        SignatureException;
173    
174      /**
175         Verifies that this Certificate was properly signed with the
176         PublicKey that corresponds to its private key and uses
177         the signature engine provided by the provider.
178    
179         @param key PublicKey to verify with
180         @param sigProvider Provider to use for signature algorithm
181    
182         @throws CertificateException encoding error
183         @throws NoSuchAlgorithmException unsupported algorithm
184         @throws InvalidKeyException incorrect key
185         @throws NoSuchProviderException incorrect provider
186         @throws SignatureException signature error
187      */
188      public abstract void verify(PublicKey key,
189                                  String sigProvider)
190        throws CertificateException,
191        NoSuchAlgorithmException,
192        InvalidKeyException,
193        NoSuchProviderException,
194        SignatureException;
195    
196      /**
197         Returns a string representing the Certificate.
198    
199         @return a string representing the Certificate.
200      */
201      public abstract String toString();
202    
203    
204      /**
205         Returns the public key stored in the Certificate.
206    
207         @return The public key
208      */
209      public abstract PublicKey getPublicKey();
210    
211      // Protected methods.
212      // ------------------------------------------------------------------------
213    
214      /**
215       * Returns a replacement for this certificate to be serialized. This
216       * method returns the equivalent to the following for this class:
217       *
218       * <blockquote>
219       * <pre>new CertificateRep(getType(), getEncoded());</pre>
220       * </blockquote>
221       *
222       * <p>This thusly replaces the certificate with its name and its
223       * encoded form, which can be deserialized later with the {@link
224       * CertificateFactory} implementation for this certificate's type.
225       *
226       * @return The replacement object to be serialized.
227       * @throws ObjectStreamException If the replacement could not be
228       * created.
229       */
230      protected Object writeReplace() throws ObjectStreamException
231      {
232        try
233          {
234            return new CertificateRep(getType(), getEncoded());
235          }
236        catch (CertificateEncodingException cee)
237          {
238            throw new InvalidObjectException(cee.toString());
239          }
240      }
241    
242      // Inner class.
243      // ------------------------------------------------------------------------
244    
245      /**
246         Certificate.CertificateRep is an inner class used to provide an alternate
247         storage mechanism for serialized Certificates.
248      */
249      protected static class CertificateRep implements java.io.Serializable
250      {
251    
252        /** From JDK1.4. */
253        private static final long serialVersionUID = -8563758940495660020L;
254    
255        /** The certificate type, e.g. "X.509". */
256        private String type;
257    
258        /** The encoded certificate data. */
259        private byte[] data;
260    
261        /**
262         * Create an alternative representation of this certificate. The
263         * <code>(type, data)</code> pair is typically the certificate's
264         * type as returned by {@link Certificate#getType()} (i.e. the
265         * canonical name of the certificate type) and the encoded form as
266         * returned by {@link Certificate#getEncoded()}.
267         *
268         * <p>For example, X.509 certificates would create an instance of
269         * this class with the parameters "X.509" and the ASN.1
270         * representation of the certificate, encoded as DER bytes.
271         *
272         * @param type The certificate type.
273         * @param data The encoded certificate data.
274         */
275        protected CertificateRep(String type, byte[] data)
276        {
277          this.type = type;
278          this.data = data;
279        }
280    
281        /**
282         * Deserialize this certificate replacement into the appropriate
283         * certificate object. That is, this method attempts to create a
284         * {@link CertificateFactory} for this certificate's type, then
285         * attempts to parse the encoded data with that factory, returning
286         * the resulting certificate.
287         *
288         * @return The deserialized certificate.
289         * @throws ObjectStreamException If there is no appropriate
290         * certificate factory for the given type, or if the encoded form
291         * cannot be parsed.
292         */
293        protected Object readResolve() throws ObjectStreamException
294        {
295          try
296            {
297              CertificateFactory fact = CertificateFactory.getInstance(type);
298              return fact.generateCertificate(new ByteArrayInputStream(data));
299            }
300          catch (Exception e)
301            {
302              throw new InvalidObjectException(e.toString());
303            }
304        }
305      }
306    }