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