• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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