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