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