1package org.bouncycastle.cert; 2 3import java.io.IOException; 4import java.io.OutputStream; 5import java.math.BigInteger; 6import java.util.Date; 7import java.util.List; 8import java.util.Set; 9 10import org.bouncycastle.asn1.ASN1ObjectIdentifier; 11import org.bouncycastle.asn1.ASN1Primitive; 12import org.bouncycastle.asn1.DEROutputStream; 13import org.bouncycastle.asn1.x500.X500Name; 14import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 15import org.bouncycastle.asn1.x509.Certificate; 16import org.bouncycastle.asn1.x509.Extension; 17import org.bouncycastle.asn1.x509.Extensions; 18import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 19import org.bouncycastle.asn1.x509.TBSCertificate; 20import org.bouncycastle.operator.ContentVerifier; 21import org.bouncycastle.operator.ContentVerifierProvider; 22import org.bouncycastle.util.Encodable; 23 24/** 25 * Holding class for an X.509 Certificate structure. 26 */ 27public class X509CertificateHolder 28 implements Encodable 29{ 30 private Certificate x509Certificate; 31 private Extensions extensions; 32 33 private static Certificate parseBytes(byte[] certEncoding) 34 throws IOException 35 { 36 try 37 { 38 return Certificate.getInstance(ASN1Primitive.fromByteArray(certEncoding)); 39 } 40 catch (ClassCastException e) 41 { 42 throw new CertIOException("malformed data: " + e.getMessage(), e); 43 } 44 catch (IllegalArgumentException e) 45 { 46 throw new CertIOException("malformed data: " + e.getMessage(), e); 47 } 48 } 49 50 /** 51 * Create a X509CertificateHolder from the passed in bytes. 52 * 53 * @param certEncoding BER/DER encoding of the certificate. 54 * @throws IOException in the event of corrupted data, or an incorrect structure. 55 */ 56 public X509CertificateHolder(byte[] certEncoding) 57 throws IOException 58 { 59 this(parseBytes(certEncoding)); 60 } 61 62 /** 63 * Create a X509CertificateHolder from the passed in ASN.1 structure. 64 * 65 * @param x509Certificate an ASN.1 Certificate structure. 66 */ 67 public X509CertificateHolder(Certificate x509Certificate) 68 { 69 this.x509Certificate = x509Certificate; 70 this.extensions = x509Certificate.getTBSCertificate().getExtensions(); 71 } 72 73 public int getVersionNumber() 74 { 75 return x509Certificate.getVersionNumber(); 76 } 77 78 /** 79 * @deprecated use getVersionNumber 80 */ 81 public int getVersion() 82 { 83 return x509Certificate.getVersionNumber(); 84 } 85 86 /** 87 * Return whether or not the holder's certificate contains extensions. 88 * 89 * @return true if extension are present, false otherwise. 90 */ 91 public boolean hasExtensions() 92 { 93 return extensions != null; 94 } 95 96 /** 97 * Look up the extension associated with the passed in OID. 98 * 99 * @param oid the OID of the extension of interest. 100 * 101 * @return the extension if present, null otherwise. 102 */ 103 public Extension getExtension(ASN1ObjectIdentifier oid) 104 { 105 if (extensions != null) 106 { 107 return extensions.getExtension(oid); 108 } 109 110 return null; 111 } 112 113 /** 114 * Return the extensions block associated with this certificate if there is one. 115 * 116 * @return the extensions block, null otherwise. 117 */ 118 public Extensions getExtensions() 119 { 120 return extensions; 121 } 122 123 /** 124 * Returns a list of ASN1ObjectIdentifier objects representing the OIDs of the 125 * extensions contained in this holder's certificate. 126 * 127 * @return a list of extension OIDs. 128 */ 129 public List getExtensionOIDs() 130 { 131 return CertUtils.getExtensionOIDs(extensions); 132 } 133 134 /** 135 * Returns a set of ASN1ObjectIdentifier objects representing the OIDs of the 136 * critical extensions contained in this holder's certificate. 137 * 138 * @return a set of critical extension OIDs. 139 */ 140 public Set getCriticalExtensionOIDs() 141 { 142 return CertUtils.getCriticalExtensionOIDs(extensions); 143 } 144 145 /** 146 * Returns a set of ASN1ObjectIdentifier objects representing the OIDs of the 147 * non-critical extensions contained in this holder's certificate. 148 * 149 * @return a set of non-critical extension OIDs. 150 */ 151 public Set getNonCriticalExtensionOIDs() 152 { 153 return CertUtils.getNonCriticalExtensionOIDs(extensions); 154 } 155 156 /** 157 * Return the serial number of this attribute certificate. 158 * 159 * @return the serial number. 160 */ 161 public BigInteger getSerialNumber() 162 { 163 return x509Certificate.getSerialNumber().getValue(); 164 } 165 166 /** 167 * Return the issuer of this certificate. 168 * 169 * @return the certificate issuer. 170 */ 171 public X500Name getIssuer() 172 { 173 return X500Name.getInstance(x509Certificate.getIssuer()); 174 } 175 176 /** 177 * Return the subject this certificate is for. 178 * 179 * @return the subject for the certificate. 180 */ 181 public X500Name getSubject() 182 { 183 return X500Name.getInstance(x509Certificate.getSubject()); 184 } 185 186 /** 187 * Return the date before which this certificate is not valid. 188 * 189 * @return the start time for the certificate's validity period. 190 */ 191 public Date getNotBefore() 192 { 193 return x509Certificate.getStartDate().getDate(); 194 } 195 196 /** 197 * Return the date after which this certificate is not valid. 198 * 199 * @return the final time for the certificate's validity period. 200 */ 201 public Date getNotAfter() 202 { 203 return x509Certificate.getEndDate().getDate(); 204 } 205 206 /** 207 * Return the SubjectPublicKeyInfo describing the public key this certificate is carrying. 208 * 209 * @return the public key ASN.1 structure contained in the certificate. 210 */ 211 public SubjectPublicKeyInfo getSubjectPublicKeyInfo() 212 { 213 return x509Certificate.getSubjectPublicKeyInfo(); 214 } 215 216 /** 217 * Return the underlying ASN.1 structure for the certificate in this holder. 218 * 219 * @return a Certificate object. 220 */ 221 public Certificate toASN1Structure() 222 { 223 return x509Certificate; 224 } 225 226 /** 227 * Return the details of the signature algorithm used to create this attribute certificate. 228 * 229 * @return the AlgorithmIdentifier describing the signature algorithm used to create this attribute certificate. 230 */ 231 public AlgorithmIdentifier getSignatureAlgorithm() 232 { 233 return x509Certificate.getSignatureAlgorithm(); 234 } 235 236 /** 237 * Return the bytes making up the signature associated with this attribute certificate. 238 * 239 * @return the attribute certificate signature bytes. 240 */ 241 public byte[] getSignature() 242 { 243 return x509Certificate.getSignature().getOctets(); 244 } 245 246 /** 247 * Return whether or not this certificate is valid on a particular date. 248 * 249 * @param date the date of interest. 250 * @return true if the certificate is valid, false otherwise. 251 */ 252 public boolean isValidOn(Date date) 253 { 254 return !date.before(x509Certificate.getStartDate().getDate()) && !date.after(x509Certificate.getEndDate().getDate()); 255 } 256 257 /** 258 * Validate the signature on the certificate in this holder. 259 * 260 * @param verifierProvider a ContentVerifierProvider that can generate a verifier for the signature. 261 * @return true if the signature is valid, false otherwise. 262 * @throws CertException if the signature cannot be processed or is inappropriate. 263 */ 264 public boolean isSignatureValid(ContentVerifierProvider verifierProvider) 265 throws CertException 266 { 267 TBSCertificate tbsCert = x509Certificate.getTBSCertificate(); 268 269 if (!CertUtils.isAlgIdEqual(tbsCert.getSignature(), x509Certificate.getSignatureAlgorithm())) 270 { 271 throw new CertException("signature invalid - algorithm identifier mismatch"); 272 } 273 274 ContentVerifier verifier; 275 276 try 277 { 278 verifier = verifierProvider.get((tbsCert.getSignature())); 279 280 OutputStream sOut = verifier.getOutputStream(); 281 DEROutputStream dOut = new DEROutputStream(sOut); 282 283 dOut.writeObject(tbsCert); 284 285 sOut.close(); 286 } 287 catch (Exception e) 288 { 289 throw new CertException("unable to process signature: " + e.getMessage(), e); 290 } 291 292 return verifier.verify(this.getSignature()); 293 } 294 295 public boolean equals( 296 Object o) 297 { 298 if (o == this) 299 { 300 return true; 301 } 302 303 if (!(o instanceof X509CertificateHolder)) 304 { 305 return false; 306 } 307 308 X509CertificateHolder other = (X509CertificateHolder)o; 309 310 return this.x509Certificate.equals(other.x509Certificate); 311 } 312 313 public int hashCode() 314 { 315 return this.x509Certificate.hashCode(); 316 } 317 318 /** 319 * Return the ASN.1 encoding of this holder's certificate. 320 * 321 * @return a DER encoded byte array. 322 * @throws IOException if an encoding cannot be generated. 323 */ 324 public byte[] getEncoded() 325 throws IOException 326 { 327 return x509Certificate.getEncoded(); 328 } 329} 330