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