KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > security > cert > X509CertSelector


1 /*
2  * @(#)X509CertSelector.java 1.20 04/06/08
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.security.cert;
9
10 import java.io.IOException JavaDoc;
11 import java.math.BigInteger JavaDoc;
12 import java.security.PublicKey JavaDoc;
13 import java.util.*;
14 import javax.security.auth.x500.X500Principal JavaDoc;
15
16 import sun.misc.HexDumpEncoder;
17 import sun.security.util.Debug;
18 import sun.security.util.DerInputStream;
19 import sun.security.util.DerValue;
20 import sun.security.util.ObjectIdentifier;
21 import sun.security.x509.*;
22
23 /**
24  * A <code>CertSelector</code> that selects <code>X509Certificates</code> that
25  * match all specified criteria. This class is particularly useful when
26  * selecting certificates from a <code>CertStore</code> to build a
27  * PKIX-compliant certification path.
28  * <p>
29  * When first constructed, an <code>X509CertSelector</code> has no criteria
30  * enabled and each of the <code>get</code> methods return a default value
31  * (<code>null</code>, or <code>-1</code> for the {@link #getBasicConstraints
32  * getBasicConstraints} method). Therefore, the {@link #match match}
33  * method would return <code>true</code> for any <code>X509Certificate</code>.
34  * Typically, several criteria are enabled (by calling
35  * {@link #setIssuer setIssuer} or
36  * {@link #setKeyUsage setKeyUsage}, for instance) and then the
37  * <code>X509CertSelector</code> is passed to
38  * {@link CertStore#getCertificates CertStore.getCertificates} or some similar
39  * method.
40  * <p>
41  * Several criteria can be enabled (by calling {@link #setIssuer setIssuer}
42  * and {@link #setSerialNumber setSerialNumber},
43  * for example) such that the <code>match</code> method
44  * usually uniquely matches a single <code>X509Certificate</code>. We say
45  * usually, since it is possible for two issuing CAs to have the same
46  * distinguished name and each issue a certificate with the same serial
47  * number. Other unique combinations include the issuer, subject,
48  * subjectKeyIdentifier and/or the subjectPublicKey criteria.
49  * <p>
50  * Please refer to RFC 2459 for definitions of the X.509 certificate
51  * extensions mentioned below.
52  * <p>
53  * <b>Concurrent Access</b>
54  * <p>
55  * Unless otherwise specified, the methods defined in this class are not
56  * thread-safe. Multiple threads that need to access a single
57  * object concurrently should synchronize amongst themselves and
58  * provide the necessary locking. Multiple threads each manipulating
59  * separate objects need not synchronize.
60  *
61  * @see CertSelector
62  * @see X509Certificate
63  *
64  * @version 1.20, 06/08/04
65  * @since 1.4
66  * @author Steve Hanna
67  */

68 public class X509CertSelector implements CertSelector JavaDoc {
69
70     private static final Debug debug = Debug.getInstance("certpath");
71     
72     private final static ObjectIdentifier ANY_EXTENDED_KEY_USAGE =
73     ObjectIdentifier.newInternal(new int[] {2, 5, 29, 37, 0});
74     
75     static {
76     CertPathHelperImpl.initialize();
77     }
78   
79     private BigInteger JavaDoc serialNumber;
80     private X500Principal JavaDoc issuer;
81     private X500Principal JavaDoc subject;
82     private byte[] subjectKeyID;
83     private byte[] authorityKeyID;
84     private Date certificateValid;
85     private Date privateKeyValid;
86     private ObjectIdentifier subjectPublicKeyAlgID;
87     private PublicKey JavaDoc subjectPublicKey;
88     private byte[] subjectPublicKeyBytes;
89     private boolean[] keyUsage;
90     private Set<String JavaDoc> keyPurposeSet;
91     private Set<ObjectIdentifier> keyPurposeOIDSet;
92     private Set<List<?>> subjectAlternativeNames;
93     private Set<GeneralNameInterface> subjectAlternativeGeneralNames;
94     private CertificatePolicySet policy;
95     private Set<String JavaDoc> policySet;
96     private Set<List<?>> pathToNames;
97     private Set<GeneralNameInterface> pathToGeneralNames;
98     private NameConstraintsExtension nc;
99     private byte[] ncBytes;
100     private int basicConstraints = -1;
101     private X509Certificate JavaDoc x509Cert;
102     private boolean matchAllSubjectAltNames = true;
103
104     private static final Boolean JavaDoc FALSE = Boolean.FALSE;
105
106     private static final int PRIVATE_KEY_USAGE_ID = 0;
107     private static final int SUBJECT_ALT_NAME_ID = 1;
108     private static final int NAME_CONSTRAINTS_ID = 2;
109     private static final int CERT_POLICIES_ID = 3;
110     private static final int EXTENDED_KEY_USAGE_ID = 4;
111     private static final int NUM_OF_EXTENSIONS = 5;
112     private static final String JavaDoc[] EXTENSION_OIDS = new String JavaDoc[NUM_OF_EXTENSIONS];
113     
114     static {
115     EXTENSION_OIDS[PRIVATE_KEY_USAGE_ID] = "2.5.29.16";
116     EXTENSION_OIDS[SUBJECT_ALT_NAME_ID] = "2.5.29.17";
117     EXTENSION_OIDS[NAME_CONSTRAINTS_ID] = "2.5.29.30";
118     EXTENSION_OIDS[CERT_POLICIES_ID] = "2.5.29.32";
119     EXTENSION_OIDS[EXTENDED_KEY_USAGE_ID] = "2.5.29.37";
120     };
121     
122     /* Constants representing the GeneralName types */
123     static final int NAME_ANY = 0;
124     static final int NAME_RFC822 = 1;
125     static final int NAME_DNS = 2;
126     static final int NAME_X400 = 3;
127     static final int NAME_DIRECTORY = 4;
128     static final int NAME_EDI = 5;
129     static final int NAME_URI = 6;
130     static final int NAME_IP = 7;
131     static final int NAME_OID = 8;
132
133     /**
134      * Creates an <code>X509CertSelector</code>. Initially, no criteria are set
135      * so any <code>X509Certificate</code> will match.
136      */

137     public X509CertSelector() {
138     // empty
139
}
140  
141     /**
142      * Sets the certificateEquals criterion. The specified
143      * <code>X509Certificate</code> must be equal to the
144      * <code>X509Certificate</code> passed to the <code>match</code> method.
145      * If <code>null</code>, then this check is not applied.
146      *
147      * <p>This method is particularly useful when it is necessary to
148      * match a single certificate. Although other criteria can be specified
149      * in conjunction with the certificateEquals criterion, it is usually not
150      * practical or necessary.
151      *
152      * @param cert the <code>X509Certificate</code> to match (or
153      * <code>null</code>)
154      * @see #getCertificate
155      */

156     public void setCertificate(X509Certificate JavaDoc cert) {
157     x509Cert = cert;
158     }
159
160     /**
161      * Sets the serialNumber criterion. The specified serial number
162      * must match the certificate serial number in the
163      * <code>X509Certificate</code>. If <code>null</code>, any certificate
164      * serial number will do.
165      *
166      * @param serial the certificate serial number to match
167      * (or <code>null</code>)
168      * @see #getSerialNumber
169      */

170     public void setSerialNumber(BigInteger JavaDoc serial) {
171     serialNumber = serial;
172     }
173   
174     /**
175      * Sets the issuer criterion. The specified distinguished name
176      * must match the issuer distinguished name in the
177      * <code>X509Certificate</code>. If <code>null</code>, any issuer
178      * distinguished name will do.
179      *
180      * @param issuer a distinguished name as X500Principal
181      * (or <code>null</code>)
182      * @since 1.5
183      */

184     public void setIssuer(X500Principal JavaDoc issuer) {
185     this.issuer = issuer;
186     }
187
188     /**
189      * <strong>Denigrated</strong>, use {@linkplain #setIssuer(X500Principal)}
190      * or {@linkplain #setIssuer(byte[])} instead. This method should not be
191      * relied on as it can fail to match some certificates because of a loss of
192      * encoding information in the RFC 2253 String form of some distinguished
193      * names.
194      * <p>
195      * Sets the issuer criterion. The specified distinguished name
196      * must match the issuer distinguished name in the
197      * <code>X509Certificate</code>. If <code>null</code>, any issuer
198      * distinguished name will do.
199      * <p>
200      * If <code>issuerDN</code> is not <code>null</code>, it should contain a
201      * distinguished name, in RFC 2253 format.
202      *
203      * @param issuerDN a distinguished name in RFC 2253 format
204      * (or <code>null</code>)
205      * @throws IOException if a parsing error occurs (incorrect form for DN)
206      */

207     public void setIssuer(String JavaDoc issuerDN) throws IOException JavaDoc {
208     if (issuerDN == null) {
209         issuer = null;
210     } else {
211         issuer = new X500Name(issuerDN).asX500Principal();
212     }
213     }
214
215     /**
216      * Sets the issuer criterion. The specified distinguished name
217      * must match the issuer distinguished name in the
218      * <code>X509Certificate</code>. If <code>null</code> is specified,
219      * the issuer criterion is disabled and any issuer distinguished name will
220      * do.
221      * <p>
222      * If <code>issuerDN</code> is not <code>null</code>, it should contain a
223      * single DER encoded distinguished name, as defined in X.501. The ASN.1
224      * notation for this structure is as follows.
225      * <pre><code>
226      * Name ::= CHOICE {
227      * RDNSequence }
228      *
229      * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
230      *
231      * RelativeDistinguishedName ::=
232      * SET SIZE (1 .. MAX) OF AttributeTypeAndValue
233      *
234      * AttributeTypeAndValue ::= SEQUENCE {
235      * type AttributeType,
236      * value AttributeValue }
237      *
238      * AttributeType ::= OBJECT IDENTIFIER
239      *
240      * AttributeValue ::= ANY DEFINED BY AttributeType
241      * ....
242      * DirectoryString ::= CHOICE {
243      * teletexString TeletexString (SIZE (1..MAX)),
244      * printableString PrintableString (SIZE (1..MAX)),
245      * universalString UniversalString (SIZE (1..MAX)),
246      * utf8String UTF8String (SIZE (1.. MAX)),
247      * bmpString BMPString (SIZE (1..MAX)) }
248      * </code></pre>
249      * <p>
250      * Note that the byte array specified here is cloned to protect against
251      * subsequent modifications.
252      *
253      * @param issuerDN a byte array containing the distinguished name
254      * in ASN.1 DER encoded form (or <code>null</code>)
255      * @throws IOException if an encoding error occurs (incorrect form for DN)
256      */

257     public void setIssuer(byte[] issuerDN) throws IOException JavaDoc {
258     try {
259         issuer = (issuerDN == null ? null : new X500Principal JavaDoc(issuerDN));
260     } catch (IllegalArgumentException JavaDoc e) {
261         throw (IOException JavaDoc)new IOException JavaDoc("Invalid name").initCause(e);
262     }
263     }
264   
265     /**
266      * Sets the subject criterion. The specified distinguished name
267      * must match the subject distinguished name in the
268      * <code>X509Certificate</code>. If <code>null</code>, any subject
269      * distinguished name will do.
270      *
271      * @param subject a distinguished name as X500Principal
272      * (or <code>null</code>)
273      * @since 1.5
274      */

275     public void setSubject(X500Principal JavaDoc subject) {
276     this.subject = subject;
277     }
278
279     /**
280      * <strong>Denigrated</strong>, use {@linkplain #setSubject(X500Principal)}
281      * or {@linkplain #setSubject(byte[])} instead. This method should not be
282      * relied on as it can fail to match some certificates because of a loss of
283      * encoding information in the RFC 2253 String form of some distinguished
284      * names.
285      * <p>
286      * Sets the subject criterion. The specified distinguished name
287      * must match the subject distinguished name in the
288      * <code>X509Certificate</code>. If <code>null</code>, any subject
289      * distinguished name will do.
290      * <p>
291      * If <code>subjectDN</code> is not <code>null</code>, it should contain a
292      * distinguished name, in RFC 2253 format.
293      *
294      * @param subjectDN a distinguished name in RFC 2253 format
295      * (or <code>null</code>)
296      * @throws IOException if a parsing error occurs (incorrect form for DN)
297      */

298     public void setSubject(String JavaDoc subjectDN) throws IOException JavaDoc {
299     if (subjectDN == null) {
300         subject = null;
301     } else {
302         subject = new X500Name(subjectDN).asX500Principal();
303     }
304     }
305
306     /**
307      * Sets the subject criterion. The specified distinguished name
308      * must match the subject distinguished name in the
309      * <code>X509Certificate</code>. If <code>null</code>, any subject
310      * distinguished name will do.
311      * <p>
312      * If <code>subjectDN</code> is not <code>null</code>, it should contain a
313      * single DER encoded distinguished name, as defined in X.501. For the ASN.1
314      * notation for this structure, see
315      * {@link #setIssuer(byte [] issuerDN) setIssuer(byte [] issuerDN)}.
316      *
317      * @param subjectDN a byte array containing the distinguished name in
318      * ASN.1 DER format (or <code>null</code>)
319      * @throws IOException if an encoding error occurs (incorrect form for DN)
320      */

321     public void setSubject(byte[] subjectDN) throws IOException JavaDoc {
322     try {
323         subject = (subjectDN == null ? null : new X500Principal JavaDoc(subjectDN));
324     } catch (IllegalArgumentException JavaDoc e) {
325         throw (IOException JavaDoc)new IOException JavaDoc("Invalid name").initCause(e);
326     }
327     }
328
329     /**
330      * Sets the subjectKeyIdentifier criterion. The
331      * <code>X509Certificate</code> must contain a SubjectKeyIdentifier
332      * extension for which the contents of the extension
333      * matches the specified criterion value.
334      * If the criterion value is <code>null</code>, no
335      * subjectKeyIdentifier check will be done.
336      * <p>
337      * If <code>subjectKeyID</code> is not <code>null</code>, it
338      * should contain a single DER encoded value corresponding to the contents
339      * of the extension value (not including the object identifier,
340      * criticality setting, and encapsulating OCTET STRING)
341      * for a SubjectKeyIdentifier extension.
342      * The ASN.1 notation for this structure follows.
343      * <p>
344      * <pre><code>
345      * SubjectKeyIdentifier ::= KeyIdentifier
346      *
347      * KeyIdentifier ::= OCTET STRING
348      * </code></pre>
349      * <p>
350      * Since the format of subject key identifiers is not mandated by
351      * any standard, subject key identifiers are not parsed by the
352      * <code>X509CertSelector</code>. Instead, the values are compared using
353      * a byte-by-byte comparison.
354      * <p>
355      * Note that the byte array supplied here is cloned to protect against
356      * subsequent modifications.
357      *
358      * @param subjectKeyID the subject key identifier (or <code>null</code>)
359      * @see #getSubjectKeyIdentifier
360      */

361     public void setSubjectKeyIdentifier(byte[] subjectKeyID) {
362     if (subjectKeyID == null) {
363         this.subjectKeyID = null;
364     } else {
365         this.subjectKeyID = (byte[])subjectKeyID.clone();
366     }
367     }
368
369     /**
370      * Sets the authorityKeyIdentifier criterion. The
371      * <code>X509Certificate</code> must contain an
372      * AuthorityKeyIdentifier extension for which the contents of the
373      * extension value matches the specified criterion value.
374      * If the criterion value is <code>null</code>, no
375      * authorityKeyIdentifier check will be done.
376      * <p>
377      * If <code>authorityKeyID</code> is not <code>null</code>, it
378      * should contain a single DER encoded value corresponding to the contents
379      * of the extension value (not including the object identifier,
380      * criticality setting, and encapsulating OCTET STRING)
381      * for an AuthorityKeyIdentifier extension.
382      * The ASN.1 notation for this structure follows.
383      * <p>
384      * <pre><code>
385      * AuthorityKeyIdentifier ::= SEQUENCE {
386      * keyIdentifier [0] KeyIdentifier OPTIONAL,
387      * authorityCertIssuer [1] GeneralNames OPTIONAL,
388      * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
389      *
390      * KeyIdentifier ::= OCTET STRING
391      * </code></pre>
392      * <p>
393      * Authority key identifiers are not parsed by the
394      * <code>X509CertSelector</code>. Instead, the values are
395      * compared using a byte-by-byte comparison.
396      * <p>
397      * When the <code>keyIdentifier</code> field of
398      * <code>AuthorityKeyIdentifier</code> is populated, the value is
399      * usually taken from the <code>SubjectKeyIdentifier</code> extension
400      * in the issuer's certificate. Note, however, that the result of
401      * <code>X509Certificate.getExtensionValue(&lt;SubjectKeyIdentifier Object
402      * Identifier&gt;)</code> on the issuer's certificate may NOT be used
403      * directly as the input to <code>setAuthorityKeyIdentifier</code>.
404      * This is because the SubjectKeyIdentifier contains
405      * only a KeyIdentifier OCTET STRING, and not a SEQUENCE of
406      * KeyIdentifier, GeneralNames, and CertificateSerialNumber.
407      * In order to use the extension value of the issuer certificate's
408      * <code>SubjectKeyIdentifier</code>
409      * extension, it will be necessary to extract the value of the embedded
410      * <code>KeyIdentifier</code> OCTET STRING, then DER encode this OCTET
411      * STRING inside a SEQUENCE.
412      * For more details on SubjectKeyIdentifier, see
413      * {@link #setSubjectKeyIdentifier(byte[] subjectKeyID)}.
414      * <p>
415      * Note also that the byte array supplied here is cloned to protect against
416      * subsequent modifications.
417      *
418      * @param authorityKeyID the authority key identifier
419      * (or <code>null</code>)
420      * @see #getAuthorityKeyIdentifier
421      */

422     public void setAuthorityKeyIdentifier(byte[] authorityKeyID) {
423     if (authorityKeyID == null) {
424         this.authorityKeyID = null;
425     } else {
426         this.authorityKeyID = (byte[])authorityKeyID.clone();
427     }
428     }
429
430     /**
431      * Sets the certificateValid criterion. The specified date must fall
432      * within the certificate validity period for the
433      * <code>X509Certificate</code>. If <code>null</code>, no certificateValid
434      * check will be done.
435      * <p>
436      * Note that the <code>Date</code> supplied here is cloned to protect
437      * against subsequent modifications.
438      *
439      * @param certValid the <code>Date</code> to check (or <code>null</code>)
440      * @see #getCertificateValid
441      */

442     public void setCertificateValid(Date certValid) {
443     if (certValid == null) {
444         certificateValid = null;
445     } else {
446         certificateValid = (Date)certValid.clone();
447     }
448     }
449
450     /**
451      * Sets the privateKeyValid criterion. The specified date must fall
452      * within the private key validity period for the
453      * <code>X509Certificate</code>. If <code>null</code>, no privateKeyValid
454      * check will be done.
455      * <p>
456      * Note that the <code>Date</code> supplied here is cloned to protect
457      * against subsequent modifications.
458      *
459      * @param privateKeyValid the <code>Date</code> to check (or
460      * <code>null</code>)
461      * @see #getPrivateKeyValid
462      */

463     public void setPrivateKeyValid(Date privateKeyValid) {
464     if (privateKeyValid == null) {
465         this.privateKeyValid = null;
466     } else {
467         this.privateKeyValid = (Date)privateKeyValid.clone();
468     }
469     }
470
471     /**
472      * Sets the subjectPublicKeyAlgID criterion. The
473      * <code>X509Certificate</code> must contain a subject public key
474      * with the specified algorithm. If <code>null</code>, no
475      * subjectPublicKeyAlgID check will be done.
476      *
477      * @param oid The object identifier (OID) of the algorithm to check
478      * for (or <code>null</code>). An OID is represented by a
479      * set of nonnegative integers separated by periods.
480      * @throws IOException if the OID is invalid, such as
481      * the first component being not 0, 1 or 2 or the second component
482      * being greater than 39.
483      *
484      * @see #getSubjectPublicKeyAlgID
485      */

486     public void setSubjectPublicKeyAlgID(String JavaDoc oid) throws IOException JavaDoc {
487     if (oid == null) {
488         subjectPublicKeyAlgID = null;
489     } else {
490         subjectPublicKeyAlgID = new ObjectIdentifier(oid);
491     }
492     }
493     
494     /**
495      * Sets the subjectPublicKey criterion. The
496      * <code>X509Certificate</code> must contain the specified subject public
497      * key. If <code>null</code>, no subjectPublicKey check will be done.
498      *
499      * @param key the subject public key to check for (or <code>null</code>)
500      * @see #getSubjectPublicKey
501      */

502     public void setSubjectPublicKey(PublicKey JavaDoc key) {
503     if (key == null) {
504         subjectPublicKey = null;
505         subjectPublicKeyBytes = null;
506     } else {
507         subjectPublicKey = key;
508         subjectPublicKeyBytes = key.getEncoded();
509     }
510     }
511
512     /**
513      * Sets the subjectPublicKey criterion. The <code>X509Certificate</code>
514      * must contain the specified subject public key. If <code>null</code>,
515      * no subjectPublicKey check will be done.
516      * <p>
517      * Because this method allows the public key to be specified as a byte
518      * array, it may be used for unknown key types.
519      * <p>
520      * If <code>key</code> is not <code>null</code>, it should contain a
521      * single DER encoded SubjectPublicKeyInfo structure, as defined in X.509.
522      * The ASN.1 notation for this structure is as follows.
523      * <pre><code>
524      * SubjectPublicKeyInfo ::= SEQUENCE {
525      * algorithm AlgorithmIdentifier,
526      * subjectPublicKey BIT STRING }
527      *
528      * AlgorithmIdentifier ::= SEQUENCE {
529      * algorithm OBJECT IDENTIFIER,
530      * parameters ANY DEFINED BY algorithm OPTIONAL }
531      * -- contains a value of the type
532      * -- registered for use with the
533      * -- algorithm object identifier value
534      * </code></pre>
535      * <p>
536      * Note that the byte array supplied here is cloned to protect against
537      * subsequent modifications.
538      *
539      * @param key a byte array containing the subject public key in ASN.1 DER
540      * form (or <code>null</code>)
541      * @throws IOException if an encoding error occurs (incorrect form for
542      * subject public key)
543      * @see #getSubjectPublicKey
544      */

545     public void setSubjectPublicKey(byte[] key) throws IOException JavaDoc {
546     if (key == null) {
547         subjectPublicKey = null;
548         subjectPublicKeyBytes = null;
549     } else {
550         subjectPublicKeyBytes = (byte[])key.clone();
551         subjectPublicKey = X509Key.parse(new DerValue(subjectPublicKeyBytes));
552     }
553     }
554
555     /**
556      * Sets the keyUsage criterion. The <code>X509Certificate</code>
557      * must allow the specified keyUsage values. If <code>null</code>, no
558      * keyUsage check will be done. Note that an <code>X509Certificate</code>
559      * that has no keyUsage extension implicitly allows all keyUsage values.
560      * <p>
561      * Note that the boolean array supplied here is cloned to protect against
562      * subsequent modifications.
563      *
564      * @param keyUsage a boolean array in the same format as the boolean
565      * array returned by
566      * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}.
567      * Or <code>null</code>.
568      * @see #getKeyUsage
569      */

570     public void setKeyUsage(boolean[] keyUsage) {
571     if (keyUsage == null) {
572         this.keyUsage = null;
573     } else {
574         this.keyUsage = (boolean[])keyUsage.clone();
575     }
576     }
577
578     /**
579      * Sets the extendedKeyUsage criterion. The <code>X509Certificate</code>
580      * must allow the specified key purposes in its extended key usage
581      * extension. If <code>keyPurposeSet</code> is empty or <code>null</code>,
582      * no extendedKeyUsage check will be done. Note that an
583      * <code>X509Certificate</code> that has no extendedKeyUsage extension
584      * implicitly allows all key purposes.
585      * <p>
586      * Note that the <code>Set</code> is cloned to protect against
587      * subsequent modifications.
588      *
589      * @param keyPurposeSet a <code>Set</code> of key purpose OIDs in string
590      * format (or <code>null</code>). Each OID is represented by a set of
591      * nonnegative integers separated by periods.
592      * @throws IOException if the OID is invalid, such as
593      * the first component being not 0, 1 or 2 or the second component
594      * being greater than 39.
595      * @see #getExtendedKeyUsage
596      */

597     public void setExtendedKeyUsage(Set<String JavaDoc> keyPurposeSet) throws IOException JavaDoc {
598     if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) {
599         this.keyPurposeSet = null;
600         keyPurposeOIDSet = null;
601     } else {
602         this.keyPurposeSet =
603         Collections.unmodifiableSet(new HashSet<String JavaDoc>(keyPurposeSet));
604         keyPurposeOIDSet = new HashSet<ObjectIdentifier>();
605         for (String JavaDoc s : this.keyPurposeSet) {
606         keyPurposeOIDSet.add(new ObjectIdentifier(s));
607         }
608     }
609     }
610
611     /**
612      * Enables/disables matching all of the subjectAlternativeNames
613      * specified in the {@link #setSubjectAlternativeNames
614      * setSubjectAlternativeNames} or {@link #addSubjectAlternativeName
615      * addSubjectAlternativeName} methods. If enabled,
616      * the <code>X509Certificate</code> must contain all of the
617      * specified subject alternative names. If disabled, the
618      * <code>X509Certificate</code> must contain at least one of the
619      * specified subject alternative names.
620      *
621      * <p>The matchAllNames flag is <code>true</code> by default.
622      *
623      * @param matchAllNames if <code>true</code>, the flag is enabled;
624      * if <code>false</code>, the flag is disabled.
625      * @see #getMatchAllSubjectAltNames
626      */

627     public void setMatchAllSubjectAltNames(boolean matchAllNames) {
628     this.matchAllSubjectAltNames = matchAllNames;
629     }
630
631     /**
632      * Sets the subjectAlternativeNames criterion. The
633      * <code>X509Certificate</code> must contain all or at least one of the
634      * specified subjectAlternativeNames, depending on the value of
635      * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
636      * setMatchAllSubjectAltNames}).
637      * <p>
638      * This method allows the caller to specify, with a single method call,
639      * the complete set of subject alternative names for the
640      * subjectAlternativeNames criterion. The specified value replaces
641      * the previous value for the subjectAlternativeNames criterion.
642      * <p>
643      * The <code>names</code> parameter (if not <code>null</code>) is a
644      * <code>Collection</code> with one
645      * entry for each name to be included in the subject alternative name
646      * criterion. Each entry is a <code>List</code> whose first entry is an
647      * <code>Integer</code> (the name type, 0-8) and whose second
648      * entry is a <code>String</code> or a byte array (the name, in
649      * string or ASN.1 DER encoded form, respectively).
650      * There can be multiple names of the same type. If <code>null</code>
651      * is supplied as the value for this argument, no
652      * subjectAlternativeNames check will be performed.
653      * <p>
654      * Each subject alternative name in the <code>Collection</code>
655      * may be specified either as a <code>String</code> or as an ASN.1 encoded
656      * byte array. For more details about the formats used, see
657      * {@link #addSubjectAlternativeName(int type, String name)
658      * addSubjectAlternativeName(int type, String name)} and
659      * {@link #addSubjectAlternativeName(int type, byte [] name)
660      * addSubjectAlternativeName(int type, byte [] name)}.
661      * <p>
662      * <strong>Note:</strong> for distinguished names, specify the byte
663      * array form instead of the String form. See the note in
664      * {@link #addSubjectAlternativeName(int, String)} for more information.
665      * <p>
666      * Note that the <code>names</code> parameter can contain duplicate
667      * names (same name and name type), but they may be removed from the
668      * <code>Collection</code> of names returned by the
669      * {@link #getSubjectAlternativeNames getSubjectAlternativeNames} method.
670      * <p>
671      * Note that a deep copy is performed on the <code>Collection</code> to
672      * protect against subsequent modifications.
673      *
674      * @param names a <code>Collection</code> of names (or <code>null</code>)
675      * @throws IOException if a parsing error occurs
676      * @see #getSubjectAlternativeNames
677      */

678     public void setSubjectAlternativeNames(Collection<List<?>> names)
679         throws IOException JavaDoc {
680     if (names == null) {
681         subjectAlternativeNames = null;
682         subjectAlternativeGeneralNames = null;
683     } else {
684         if (names.isEmpty()) {
685         subjectAlternativeNames = null;
686         subjectAlternativeGeneralNames = null;
687         return;
688         }
689         Set<List<?>> tempNames = cloneAndCheckNames(names);
690         // Ensure that we either set both of these or neither
691
subjectAlternativeGeneralNames = parseNames(tempNames);
692         subjectAlternativeNames = tempNames;
693     }
694     }
695
696     /**
697      * Adds a name to the subjectAlternativeNames criterion. The
698      * <code>X509Certificate</code> must contain all or at least one
699      * of the specified subjectAlternativeNames, depending on the value of
700      * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
701      * setMatchAllSubjectAltNames}).
702      * <p>
703      * This method allows the caller to add a name to the set of subject
704      * alternative names.
705      * The specified name is added to any previous value for the
706      * subjectAlternativeNames criterion. If the specified name is a
707      * duplicate, it may be ignored.
708      * <p>
709      * The name is provided in string format. RFC 822, DNS, and URI names
710      * use the well-established string formats for those types (subject to
711      * the restrictions included in RFC 2459). IPv4 address names are
712      * supplied using dotted quad notation. OID address names are represented
713      * as a series of nonnegative integers separated by periods. And
714      * directory names (distinguished names) are supplied in RFC 2253 format.
715      * No standard string format is defined for otherNames, X.400 names,
716      * EDI party names, IPv6 address names, or any other type of names. They
717      * should be specified using the
718      * {@link #addSubjectAlternativeName(int type, byte [] name)
719      * addSubjectAlternativeName(int type, byte [] name)}
720      * method.
721      * <p>
722      * <strong>Note:</strong> for distinguished names, use
723      * {@linkplain #addSubjectAlternativeName(int, byte[])} instead.
724      * This method should not be relied on as it can fail to match some
725      * certificates because of a loss of encoding information in the RFC 2253
726      * String form of some distinguished names.
727      *
728      * @param type the name type (0-8, as specified in
729      * RFC 2459, section 4.2.1.7)
730      * @param name the name in string form (not <code>null</code>)
731      * @throws IOException if a parsing error occurs
732      */

733     public void addSubjectAlternativeName(int type, String JavaDoc name)
734         throws IOException JavaDoc {
735     addSubjectAlternativeNameInternal(type, name);
736     }
737
738     /**
739      * Adds a name to the subjectAlternativeNames criterion. The
740      * <code>X509Certificate</code> must contain all or at least one
741      * of the specified subjectAlternativeNames, depending on the value of
742      * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
743      * setMatchAllSubjectAltNames}).
744      * <p>
745      * This method allows the caller to add a name to the set of subject
746      * alternative names.
747      * The specified name is added to any previous value for the
748      * subjectAlternativeNames criterion. If the specified name is a
749      * duplicate, it may be ignored.
750      * <p>
751      * The name is provided as a byte array. This byte array should contain
752      * the DER encoded name, as it would appear in the GeneralName structure
753      * defined in RFC 2459 and X.509. The encoded byte array should only contain
754      * the encoded value of the name, and should not include the tag associated
755      * with the name in the GeneralName structure. The ASN.1 definition of this
756      * structure appears below.
757      * <pre><code>
758      * GeneralName ::= CHOICE {
759      * otherName [0] OtherName,
760      * rfc822Name [1] IA5String,
761      * dNSName [2] IA5String,
762      * x400Address [3] ORAddress,
763      * directoryName [4] Name,
764      * ediPartyName [5] EDIPartyName,
765      * uniformResourceIdentifier [6] IA5String,
766      * iPAddress [7] OCTET STRING,
767      * registeredID [8] OBJECT IDENTIFIER}
768      * </code></pre>
769      * <p>
770      * Note that the byte array supplied here is cloned to protect against
771      * subsequent modifications.
772      *
773      * @param type the name type (0-8, as listed above)
774      * @param name a byte array containing the name in ASN.1 DER encoded form
775      * @throws IOException if a parsing error occurs
776      */

777     public void addSubjectAlternativeName(int type, byte[] name)
778         throws IOException JavaDoc {
779     // clone because byte arrays are modifiable
780
addSubjectAlternativeNameInternal(type, name.clone());
781     }
782
783     /**
784      * A private method that adds a name (String or byte array) to the
785      * subjectAlternativeNames criterion. The <code>X509Certificate</code>
786      * must contain the specified subjectAlternativeName.
787      *
788      * @param type the name type (0-8, as specified in
789      * RFC 2459, section 4.2.1.7)
790      * @param name the name in string or byte array form
791      * @throws IOException if a parsing error occurs
792      */

793     private void addSubjectAlternativeNameInternal(int type, Object JavaDoc name)
794         throws IOException JavaDoc {
795     // First, ensure that the name parses
796
GeneralNameInterface tempName = makeGeneralNameInterface(type, name);
797     if (subjectAlternativeNames == null) {
798         subjectAlternativeNames = new HashSet<List<?>>();
799     }
800     if (subjectAlternativeGeneralNames == null) {
801         subjectAlternativeGeneralNames = new HashSet<GeneralNameInterface>();
802     }
803     List<Object JavaDoc> list = new ArrayList<Object JavaDoc>(2);
804     list.add(Integer.valueOf(type));
805     list.add(name);
806     subjectAlternativeNames.add(list);
807     subjectAlternativeGeneralNames.add(tempName);
808     }
809
810     /**
811      * Parse an argument of the form passed to setSubjectAlternativeNames,
812      * returning a <code>Collection</code> of
813      * <code>GeneralNameInterface</code>s.
814      * Throw an IllegalArgumentException or a ClassCastException
815      * if the argument is malformed.
816      *
817      * @param names a Collection with one entry per name.
818      * Each entry is a <code>List</code> whose first entry
819      * is an Integer (the name type, 0-8) and whose second
820      * entry is a String or a byte array (the name, in
821      * string or ASN.1 DER encoded form, respectively).
822      * There can be multiple names of the same type. Null is
823      * not an acceptable value.
824      * @return a Set of <code>GeneralNameInterface</code>s
825      * @throws IOException if a parsing error occurs
826      */

827     private static Set<GeneralNameInterface> parseNames(Collection<List<?>> names) throws IOException JavaDoc {
828     Set<GeneralNameInterface> genNames = new HashSet<GeneralNameInterface>();
829     Iterator<List<?>> i = names.iterator();
830     while (i.hasNext()) {
831         Object JavaDoc o = i.next();
832         if (!(o instanceof List)) {
833         throw new IOException JavaDoc("expected List");
834         }
835         List<Object JavaDoc> nameList = (List<Object JavaDoc>)o;
836         if (nameList.size() != 2) {
837         throw new IOException JavaDoc("name list size not 2");
838         }
839         o = nameList.get(0);
840         if (!(o instanceof Integer JavaDoc)) {
841         throw new IOException JavaDoc("expected an Integer");
842         }
843         int nameType = ((Integer JavaDoc)o).intValue();
844         o = nameList.get(1);
845         genNames.add(makeGeneralNameInterface(nameType, o));
846     }
847     return genNames;
848     }
849   
850     /**
851      * Compare for equality two objects of the form passed to
852      * setSubjectAlternativeNames (or X509CRLSelector.setIssuerNames).
853      * Throw an <code>IllegalArgumentException</code> or a
854      * <code>ClassCastException</code> if one of the objects is malformed.
855      *
856      * @param object1 a Collection containing the first object to compare
857      * @param object2 a Collection containing the second object to compare
858      * @return true if the objects are equal, false otherwise
859      */

860     static boolean equalNames(Collection object1, Collection object2) {
861     if ((object1 == null) || (object2 == null)) {
862         return object1 == object2;
863     }
864     return object1.equals(object2);
865     }
866
867     /**
868      * Make a <code>GeneralNameInterface</code> out of a name type (0-8) and an
869      * Object that may be a byte array holding the ASN.1 DER encoded
870      * name or a String form of the name. Except for X.509
871      * Distinguished Names, the String form of the name must not be the
872      * result from calling toString on an existing GeneralNameInterface
873      * implementing class. The output of toString is not compatible
874      * with the String constructors for names other than Distinguished
875      * Names.
876      *
877      * @param type name type (0-8)
878      * @param name name as ASN.1 Der-encoded byte array or String
879      * @return a GeneralNameInterface name
880      * @throws IOException if a parsing error occurs
881      */

882     static GeneralNameInterface makeGeneralNameInterface(int type, Object JavaDoc name)
883         throws IOException JavaDoc {
884     GeneralNameInterface result;
885     if (debug != null) {
886         debug.println("X509CertSelector.makeGeneralNameInterface("
887             + type + ")...");
888     }
889   
890     if (name instanceof String JavaDoc) {
891         if (debug != null) {
892         debug.println("X509CertSelector.makeGeneralNameInterface() "
893             + "name is String: " + name);
894         }
895         switch (type) {
896         case NAME_RFC822:
897         result = new RFC822Name((String JavaDoc)name);
898         break;
899         case NAME_DNS:
900         result = new DNSName((String JavaDoc)name);
901         break;
902         case NAME_DIRECTORY:
903         result = new X500Name((String JavaDoc)name);
904         break;
905         case NAME_URI:
906         result = new URIName((String JavaDoc)name);
907         break;
908         case NAME_IP:
909         result = new IPAddressName((String JavaDoc)name);
910         break;
911         case NAME_OID:
912         result = new OIDName((String JavaDoc)name);
913         break;
914         default:
915         throw new IOException JavaDoc("unable to parse String names of type "
916                       + type);
917         }
918         if (debug != null) {
919         debug.println("X509CertSelector.makeGeneralNameInterface() "
920             + "result: " + result.toString());
921         }
922     } else if (name instanceof byte[]) {
923         DerValue val = new DerValue((byte[]) name);
924         if (debug != null) {
925         debug.println
926             ("X509CertSelector.makeGeneralNameInterface() is byte[]");
927         }
928     
929         switch (type) {
930         case NAME_ANY:
931         result = new OtherName(val);
932         break;
933         case NAME_RFC822:
934         result = new RFC822Name(val);
935