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