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