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 * Return the extensions block associated with this certificate if there is one. 113 * 114 * @return the extensions block, null otherwise. 115 */ 116 public Extensions getExtensions() 117 { 118 return extensions; 119 } 120 121 /** 122 * Returns a list of ASN1ObjectIdentifier objects representing the OIDs of the 123 * extensions contained in this holder's certificate. 124 * 125 * @return a list of extension OIDs. 126 */ 127 public List getExtensionOIDs() 128 { 129 return CertUtils.getExtensionOIDs(extensions); 130 } 131 132 /** 133 * Returns a set of ASN1ObjectIdentifier objects representing the OIDs of the 134 * critical extensions contained in this holder's certificate. 135 * 136 * @return a set of critical extension OIDs. 137 */ 138 public Set getCriticalExtensionOIDs() 139 { 140 return CertUtils.getCriticalExtensionOIDs(extensions); 141 } 142 143 /** 144 * Returns a set of ASN1ObjectIdentifier objects representing the OIDs of the 145 * non-critical extensions contained in this holder's certificate. 146 * 147 * @return a set of non-critical extension OIDs. 148 */ 149 public Set getNonCriticalExtensionOIDs() 150 { 151 return CertUtils.getNonCriticalExtensionOIDs(extensions); 152 } 153 154 /** 155 * Return the serial number of this attribute certificate. 156 * 157 * @return the serial number. 158 */ 159 public BigInteger getSerialNumber() 160 { 161 return x509Certificate.getSerialNumber().getValue(); 162 } 163 164 /** 165 * Return the issuer of this certificate. 166 * 167 * @return the certificate issuer. 168 */ 169 public X500Name getIssuer() 170 { 171 return X500Name.getInstance(x509Certificate.getIssuer()); 172 } 173 174 /** 175 * Return the subject this certificate is for. 176 * 177 * @return the subject for the certificate. 178 */ 179 public X500Name getSubject() 180 { 181 return X500Name.getInstance(x509Certificate.getSubject()); 182 } 183 184 /** 185 * Return the date before which this certificate is not valid. 186 * 187 * @return the start time for the certificate's validity period. 188 */ 189 public Date getNotBefore() 190 { 191 return x509Certificate.getStartDate().getDate(); 192 } 193 194 /** 195 * Return the date after which this certificate is not valid. 196 * 197 * @return the final time for the certificate's validity period. 198 */ 199 public Date getNotAfter() 200 { 201 return x509Certificate.getEndDate().getDate(); 202 } 203 204 /** 205 * Return the SubjectPublicKeyInfo describing the public key this certificate is carrying. 206 * 207 * @return the public key ASN.1 structure contained in the certificate. 208 */ 209 public SubjectPublicKeyInfo getSubjectPublicKeyInfo() 210 { 211 return x509Certificate.getSubjectPublicKeyInfo(); 212 } 213 214 /** 215 * Return the underlying ASN.1 structure for the certificate in this holder. 216 * 217 * @return a X509CertificateStructure object. 218 */ 219 public Certificate toASN1Structure() 220 { 221 return x509Certificate; 222 } 223 224 /** 225 * Return the details of the signature algorithm used to create this attribute certificate. 226 * 227 * @return the AlgorithmIdentifier describing the signature algorithm used to create this attribute certificate. 228 */ 229 public AlgorithmIdentifier getSignatureAlgorithm() 230 { 231 return x509Certificate.getSignatureAlgorithm(); 232 } 233 234 /** 235 * Return the bytes making up the signature associated with this attribute certificate. 236 * 237 * @return the attribute certificate signature bytes. 238 */ 239 public byte[] getSignature() 240 { 241 return x509Certificate.getSignature().getBytes(); 242 } 243 244 /** 245 * Return whether or not this certificate is valid on a particular date. 246 * 247 * @param date the date of interest. 248 * @return true if the certificate is valid, false otherwise. 249 */ 250 public boolean isValidOn(Date date) 251 { 252 return !date.before(x509Certificate.getStartDate().getDate()) && !date.after(x509Certificate.getEndDate().getDate()); 253 } 254 255 /** 256 * Validate the signature on the certificate in this holder. 257 * 258 * @param verifierProvider a ContentVerifierProvider that can generate a verifier for the signature. 259 * @return true if the signature is valid, false otherwise. 260 * @throws CertException if the signature cannot be processed or is inappropriate. 261 */ 262 public boolean isSignatureValid(ContentVerifierProvider verifierProvider) 263 throws CertException 264 { 265 TBSCertificate tbsCert = x509Certificate.getTBSCertificate(); 266 267 if (!CertUtils.isAlgIdEqual(tbsCert.getSignature(), x509Certificate.getSignatureAlgorithm())) 268 { 269 throw new CertException("signature invalid - algorithm identifier mismatch"); 270 } 271 272 ContentVerifier verifier; 273 274 try 275 { 276 verifier = verifierProvider.get((tbsCert.getSignature())); 277 278 OutputStream sOut = verifier.getOutputStream(); 279 DEROutputStream dOut = new DEROutputStream(sOut); 280 281 dOut.writeObject(tbsCert); 282 283 sOut.close(); 284 } 285 catch (Exception e) 286 { 287 throw new CertException("unable to process signature: " + e.getMessage(), e); 288 } 289 290 return verifier.verify(x509Certificate.getSignature().getBytes()); 291 } 292 293 public boolean equals( 294 Object o) 295 { 296 if (o == this) 297 { 298 return true; 299 } 300 301 if (!(o instanceof X509CertificateHolder)) 302 { 303 return false; 304 } 305 306 X509CertificateHolder other = (X509CertificateHolder)o; 307 308 return this.x509Certificate.equals(other.x509Certificate); 309 } 310 311 public int hashCode() 312 { 313 return this.x509Certificate.hashCode(); 314 } 315 316 /** 317 * Return the ASN.1 encoding of this holder's certificate. 318 * 319 * @return a DER encoded byte array. 320 * @throws IOException if an encoding cannot be generated. 321 */ 322 public byte[] getEncoded() 323 throws IOException 324 { 325 return x509Certificate.getEncoded(); 326 } 327} 328