Home | History | Annotate | Download | only in cert
      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.ASN1Primitive;
     12 import org.bouncycastle.asn1.DEROutputStream;
     13 import org.bouncycastle.asn1.x500.X500Name;
     14 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
     15 import org.bouncycastle.asn1.x509.Certificate;
     16 import org.bouncycastle.asn1.x509.Extension;
     17 import org.bouncycastle.asn1.x509.Extensions;
     18 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
     19 import org.bouncycastle.asn1.x509.TBSCertificate;
     20 import org.bouncycastle.operator.ContentVerifier;
     21 import org.bouncycastle.operator.ContentVerifierProvider;
     22 import org.bouncycastle.util.Encodable;
     23 
     24 /**
     25  * Holding class for an X.509 Certificate structure.
     26  */
     27 public 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