001/* Certificate.java --- Certificate class
002   Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.security.cert;
040
041import java.io.ByteArrayInputStream;
042import java.io.InvalidObjectException;
043import java.io.ObjectStreamException;
044import java.io.Serializable;
045import java.security.InvalidKeyException;
046import java.security.NoSuchAlgorithmException;
047import java.security.NoSuchProviderException;
048import java.security.PublicKey;
049import 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 */
074public 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}