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 
parseBytes(byte[] certEncoding)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      */
X509CertificateHolder(byte[] certEncoding)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      */
X509CertificateHolder(Certificate x509Certificate)67     public X509CertificateHolder(Certificate x509Certificate)
68     {
69         this.x509Certificate = x509Certificate;
70         this.extensions = x509Certificate.getTBSCertificate().getExtensions();
71     }
72 
getVersionNumber()73     public int getVersionNumber()
74     {
75         return x509Certificate.getVersionNumber();
76     }
77 
78     /**
79      * @deprecated use getVersionNumber
80      */
getVersion()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      */
hasExtensions()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      */
getExtension(ASN1ObjectIdentifier oid)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      */
getExtensions()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      */
getExtensionOIDs()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      */
getCriticalExtensionOIDs()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      */
getNonCriticalExtensionOIDs()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      */
getSerialNumber()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      */
getIssuer()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      */
getSubject()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      */
getNotBefore()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      */
getNotAfter()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      */
getSubjectPublicKeyInfo()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      */
toASN1Structure()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      */
getSignatureAlgorithm()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      */
getSignature()241     public byte[] getSignature()
242     {
243         return x509Certificate.getSignature().getBytes();
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      */
isValidOn(Date date)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      */
isSignatureValid(ContentVerifierProvider verifierProvider)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(x509Certificate.getSignature().getBytes());
293     }
294 
equals( Object o)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 
hashCode()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      */
getEncoded()324     public byte[] getEncoded()
325         throws IOException
326     {
327         return x509Certificate.getEncoded();
328     }
329 }
330