1 /*
   2  * Copyright (c) 1997, 2010, 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.util.Arrays;
  29 
  30 import java.security.PublicKey;
  31 import java.security.NoSuchAlgorithmException;
  32 import java.security.NoSuchProviderException;
  33 import java.security.InvalidKeyException;
  34 import java.security.SignatureException;
  35 
  36 import sun.security.x509.X509CertImpl;
  37 
  38 /**
  39  * <p>Abstract class for managing a variety of identity certificates.
  40  * An identity certificate is a binding of a principal to a public key which
  41  * is vouched for by another principal.  (A principal represents
  42  * an entity such as an individual user, a group, or a corporation.)
  43  *<p>
  44  * This class is an abstraction for certificates that have different
  45  * formats but important common uses.  For example, different types of
  46  * certificates, such as X.509 and PGP, share general certificate
  47  * functionality (like encoding and verifying) and
  48  * some types of information (like a public key).
  49  * <p>
  50  * X.509, PGP, and SDSI certificates can all be implemented by
  51  * subclassing the Certificate class, even though they contain different
  52  * sets of information, and they store and retrieve the information in
  53  * different ways.
  54  *
  55  * @see X509Certificate
  56  * @see CertificateFactory
  57  *
  58  * @author Hemma Prafullchandra
  59  */
  60 
  61 public abstract class Certificate implements java.io.Serializable {
  62 
  63     private static final long serialVersionUID = -3585440601605666277L;
  64 
  65     // the certificate type
  66     private final String type;
  67 
  68     /**
  69      * Creates a certificate of the specified type.
  70      *
  71      * @param type the standard name of the certificate type.
  72      * See the CertificateFactory section in the <a href=
  73      * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertificateFactory">
  74      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
  75      * for information about standard certificate types.
  76      */
  77     protected Certificate(String type) {
  78         this.type = type;
  79     }
  80 
  81     /**
  82      * Returns the type of this certificate.
  83      *
  84      * @return the type of this certificate.
  85      */
  86     public final String getType() {
  87         return this.type;
  88     }
  89 
  90     /**
  91      * Compares this certificate for equality with the specified
  92      * object. If the <code>other</code> object is an
  93      * <code>instanceof</code> <code>Certificate</code>, then
  94      * its encoded form is retrieved and compared with the
  95      * encoded form of this certificate.
  96      *
  97      * @param other the object to test for equality with this certificate.
  98      * @return true iff the encoded forms of the two certificates
  99      * match, false otherwise.
 100      */
 101     public boolean equals(Object other) {
 102         if (this == other) {
 103             return true;
 104         }
 105         if (!(other instanceof Certificate)) {
 106             return false;
 107         }
 108         try {
 109             byte[] thisCert = X509CertImpl.getEncodedInternal(this);
 110             byte[] otherCert = X509CertImpl.getEncodedInternal((Certificate)other);
 111 
 112             return Arrays.equals(thisCert, otherCert);
 113         } catch (CertificateException e) {
 114             return false;
 115         }
 116     }
 117 
 118     /**
 119      * Returns a hashcode value for this certificate from its
 120      * encoded form.
 121      *
 122      * @return the hashcode value.
 123      */
 124     public int hashCode() {
 125         int retval = 0;
 126         try {
 127             byte[] certData = X509CertImpl.getEncodedInternal(this);
 128             for (int i = 1; i < certData.length; i++) {
 129                  retval += certData[i] * i;
 130             }
 131             return retval;
 132         } catch (CertificateException e) {
 133             return retval;
 134         }
 135     }
 136 
 137     /**
 138      * Returns the encoded form of this certificate. It is
 139      * assumed that each certificate type would have only a single
 140      * form of encoding; for example, X.509 certificates would
 141      * be encoded as ASN.1 DER.
 142      *
 143      * @return the encoded form of this certificate
 144      *
 145      * @exception CertificateEncodingException if an encoding error occurs.
 146      */
 147     public abstract byte[] getEncoded()
 148         throws CertificateEncodingException;
 149 
 150     /**
 151      * Verifies that this certificate was signed using the
 152      * private key that corresponds to the specified public key.
 153      *
 154      * @param key the PublicKey used to carry out the verification.
 155      *
 156      * @exception NoSuchAlgorithmException on unsupported signature
 157      * algorithms.
 158      * @exception InvalidKeyException on incorrect key.
 159      * @exception NoSuchProviderException if there's no default provider.
 160      * @exception SignatureException on signature errors.
 161      * @exception CertificateException on encoding errors.
 162      */
 163     public abstract void verify(PublicKey key)
 164         throws CertificateException, NoSuchAlgorithmException,
 165         InvalidKeyException, NoSuchProviderException,
 166         SignatureException;
 167 
 168     /**
 169      * Verifies that this certificate was signed using the
 170      * private key that corresponds to the specified public key.
 171      * This method uses the signature verification engine
 172      * supplied by the specified provider.
 173      *
 174      * @param key the PublicKey used to carry out the verification.
 175      * @param sigProvider the name of the signature provider.
 176      *
 177      * @exception NoSuchAlgorithmException on unsupported signature
 178      * algorithms.
 179      * @exception InvalidKeyException on incorrect key.
 180      * @exception NoSuchProviderException on incorrect provider.
 181      * @exception SignatureException on signature errors.
 182      * @exception CertificateException on encoding errors.
 183      */
 184     public abstract void verify(PublicKey key, String sigProvider)
 185         throws CertificateException, NoSuchAlgorithmException,
 186         InvalidKeyException, NoSuchProviderException,
 187         SignatureException;
 188 
 189     /**
 190      * Returns a string representation of this certificate.
 191      *
 192      * @return a string representation of this certificate.
 193      */
 194     public abstract String toString();
 195 
 196     /**
 197      * Gets the public key from this certificate.
 198      *
 199      * @return the public key.
 200      */
 201     public abstract PublicKey getPublicKey();
 202 
 203     /**
 204      * Alternate Certificate class for serialization.
 205      * @since 1.3
 206      */
 207     protected static class CertificateRep implements java.io.Serializable {
 208 
 209         private static final long serialVersionUID = -8563758940495660020L;
 210 
 211         private String type;
 212         private byte[] data;
 213 
 214         /**
 215          * Construct the alternate Certificate class with the Certificate
 216          * type and Certificate encoding bytes.
 217          *
 218          * <p>
 219          *
 220          * @param type the standard name of the Certificate type. <p>
 221          *
 222          * @param data the Certificate data.
 223          */
 224         protected CertificateRep(String type, byte[] data) {
 225             this.type = type;
 226             this.data = data;
 227         }
 228 
 229         /**
 230          * Resolve the Certificate Object.
 231          *
 232          * <p>
 233          *
 234          * @return the resolved Certificate Object
 235          *
 236          * @throws java.io.ObjectStreamException if the Certificate
 237          *      could not be resolved
 238          */
 239         protected Object readResolve() throws java.io.ObjectStreamException {
 240             try {
 241                 CertificateFactory cf = CertificateFactory.getInstance(type);
 242                 return cf.generateCertificate
 243                         (new java.io.ByteArrayInputStream(data));
 244             } catch (CertificateException e) {
 245                 throw new java.io.NotSerializableException
 246                                 ("java.security.cert.Certificate: " +
 247                                 type +
 248                                 ": " +
 249                                 e.getMessage());
 250             }
 251         }
 252     }
 253 
 254     /**
 255      * Replace the Certificate to be serialized.
 256      *
 257      * @return the alternate Certificate object to be serialized
 258      *
 259      * @throws java.io.ObjectStreamException if a new object representing
 260      * this Certificate could not be created
 261      * @since 1.3
 262      */
 263     protected Object writeReplace() throws java.io.ObjectStreamException {
 264         try {
 265             return new CertificateRep(type, getEncoded());
 266         } catch (CertificateException e) {
 267             throw new java.io.NotSerializableException
 268                                 ("java.security.cert.Certificate: " +
 269                                 type +
 270                                 ": " +
 271                                 e.getMessage());
 272         }
 273     }
 274 }