View Javadoc
1   /*
2    * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package sun.security.x509;
27  
28  import java.lang.reflect.*;
29  import java.io.IOException;
30  import java.security.PrivilegedExceptionAction;
31  import java.security.AccessController;
32  import java.security.Principal;
33  import java.util.*;
34  
35  import sun.security.util.*;
36  import javax.security.auth.x500.X500Principal;
37  
38  /**
39   * Note:  As of 1.4, the public class,
40   * javax.security.auth.x500.X500Principal,
41   * should be used when parsing, generating, and comparing X.500 DNs.
42   * This class contains other useful methods for checking name constraints
43   * and retrieving DNs by keyword.
44   *
45   * <p> X.500 names are used to identify entities, such as those which are
46   * identified by X.509 certificates.  They are world-wide, hierarchical,
47   * and descriptive.  Entities can be identified by attributes, and in
48   * some systems can be searched for according to those attributes.
49   * <p>
50   * The ASN.1 for this is:
51   * <pre>
52   * GeneralName ::= CHOICE {
53   * ....
54   *     directoryName                   [4]     Name,
55   * ....
56   * Name ::= CHOICE {
57   *   RDNSequence }
58   *
59   * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
60   *
61   * RelativeDistinguishedName ::=
62   *   SET OF AttributeTypeAndValue
63   *
64   * AttributeTypeAndValue ::= SEQUENCE {
65   *   type     AttributeType,
66   *   value    AttributeValue }
67   *
68   * AttributeType ::= OBJECT IDENTIFIER
69   *
70   * AttributeValue ::= ANY DEFINED BY AttributeType
71   * ....
72   * DirectoryString ::= CHOICE {
73   *       teletexString           TeletexString (SIZE (1..MAX)),
74   *       printableString         PrintableString (SIZE (1..MAX)),
75   *       universalString         UniversalString (SIZE (1..MAX)),
76   *       utf8String              UTF8String (SIZE (1.. MAX)),
77   *       bmpString               BMPString (SIZE (1..MAX)) }
78   * </pre>
79   * <p>
80   * This specification requires only a subset of the name comparison
81   * functionality specified in the X.500 series of specifications.  The
82   * requirements for conforming implementations are as follows:
83   * <ol TYPE=a>
84   * <li>attribute values encoded in different types (e.g.,
85   *    PrintableString and BMPString) may be assumed to represent
86   *    different strings;
87   * <p>
88   * <li>attribute values in types other than PrintableString are case
89   *    sensitive (this permits matching of attribute values as binary
90   *    objects);
91   * <p>
92   * <li>attribute values in PrintableString are not case sensitive
93   *    (e.g., "Marianne Swanson" is the same as "MARIANNE SWANSON"); and
94   * <p>
95   * <li>attribute values in PrintableString are compared after
96   *    removing leading and trailing white space and converting internal
97   *    substrings of one or more consecutive white space characters to a
98   *    single space.
99   * </ol>
100  * <p>
101  * These name comparison rules permit a certificate user to validate
102  * certificates issued using languages or encodings unfamiliar to the
103  * certificate user.
104  * <p>
105  * In addition, implementations of this specification MAY use these
106  * comparison rules to process unfamiliar attribute types for name
107  * chaining. This allows implementations to process certificates with
108  * unfamiliar attributes in the issuer name.
109  * <p>
110  * Note that the comparison rules defined in the X.500 series of
111  * specifications indicate that the character sets used to encode data
112  * in distinguished names are irrelevant.  The characters themselves are
113  * compared without regard to encoding. Implementations of the profile
114  * are permitted to use the comparison algorithm defined in the X.500
115  * series.  Such an implementation will recognize a superset of name
116  * matches recognized by the algorithm specified above.
117  * <p>
118  * Note that instances of this class are immutable.
119  *
120  * @author David Brownell
121  * @author Amit Kapoor
122  * @author Hemma Prafullchandra
123  * @see GeneralName
124  * @see GeneralNames
125  * @see GeneralNameInterface
126  */
127 
128 public class X500Name implements GeneralNameInterface, Principal {
129 
130     private String dn; // roughly RFC 1779 DN, or null
131     private String rfc1779Dn; // RFC 1779 compliant DN, or null
132     private String rfc2253Dn; // RFC 2253 DN, or null
133     private String canonicalDn; // canonical RFC 2253 DN or null
134     private RDN[] names;        // RDNs (never null)
135     private X500Principal x500Principal;
136     private byte[] encoded;
137 
138     // cached immutable list of the RDNs and all the AVAs
139     private volatile List<RDN> rdnList;
140     private volatile List<AVA> allAvaList;
141 
142     /**
143      * Constructs a name from a conventionally formatted string, such
144      * as "CN=Dave, OU=JavaSoft, O=Sun Microsystems, C=US".
145      * (RFC 1779, 2253, or 4514 style).
146      *
147      * @param dname the X.500 Distinguished Name
148      */
149     public X500Name(String dname) throws IOException {
150         this(dname, Collections.<String, String>emptyMap());
151     }
152 
153     /**
154      * Constructs a name from a conventionally formatted string, such
155      * as "CN=Dave, OU=JavaSoft, O=Sun Microsystems, C=US".
156      * (RFC 1779, 2253, or 4514 style).
157      *
158      * @param dname the X.500 Distinguished Name
159      * @param keywordMap an additional keyword/OID map
160      */
161     public X500Name(String dname, Map<String, String> keywordMap)
162         throws IOException {
163         parseDN(dname, keywordMap);
164     }
165 
166     /**
167      * Constructs a name from a string formatted according to format.
168      * Currently, the formats DEFAULT and RFC2253 are supported.
169      * DEFAULT is the default format used by the X500Name(String)
170      * constructor. RFC2253 is the format strictly according to RFC2253
171      * without extensions.
172      *
173      * @param dname the X.500 Distinguished Name
174      * @param format the specified format of the String DN
175      */
176     public X500Name(String dname, String format) throws IOException {
177         if (dname == null) {
178             throw new NullPointerException("Name must not be null");
179         }
180         if (format.equalsIgnoreCase("RFC2253")) {
181             parseRFC2253DN(dname);
182         } else if (format.equalsIgnoreCase("DEFAULT")) {
183             parseDN(dname, Collections.<String, String>emptyMap());
184         } else {
185             throw new IOException("Unsupported format " + format);
186         }
187     }
188 
189     /**
190      * Constructs a name from fields common in enterprise application
191      * environments.
192      *
193      * <P><EM><STRONG>NOTE:</STRONG>  The behaviour when any of
194      * these strings contain characters outside the ASCII range
195      * is unspecified in currently relevant standards.</EM>
196      *
197      * @param commonName common name of a person, e.g. "Vivette Davis"
198      * @param organizationUnit small organization name, e.g. "Purchasing"
199      * @param organizationName large organization name, e.g. "Onizuka, Inc."
200      * @param country two letter country code, e.g. "CH"
201      */
202     public X500Name(String commonName, String organizationUnit,
203                      String organizationName, String country)
204     throws IOException {
205         names = new RDN[4];
206         /*
207          * NOTE:  it's only on output that little-endian
208          * ordering is used.
209          */
210         names[3] = new RDN(1);
211         names[3].assertion[0] = new AVA(commonName_oid,
212                 new DerValue(commonName));
213         names[2] = new RDN(1);
214         names[2].assertion[0] = new AVA(orgUnitName_oid,
215                 new DerValue(organizationUnit));
216         names[1] = new RDN(1);
217         names[1].assertion[0] = new AVA(orgName_oid,
218                 new DerValue(organizationName));
219         names[0] = new RDN(1);
220         names[0].assertion[0] = new AVA(countryName_oid,
221                 new DerValue(country));
222     }
223 
224     /**
225      * Constructs a name from fields common in Internet application
226      * environments.
227      *
228      * <P><EM><STRONG>NOTE:</STRONG>  The behaviour when any of
229      * these strings contain characters outside the ASCII range
230      * is unspecified in currently relevant standards.</EM>
231      *
232      * @param commonName common name of a person, e.g. "Vivette Davis"
233      * @param organizationUnit small organization name, e.g. "Purchasing"
234      * @param organizationName large organization name, e.g. "Onizuka, Inc."
235      * @param localityName locality (city) name, e.g. "Palo Alto"
236      * @param stateName state name, e.g. "California"
237      * @param country two letter country code, e.g. "CH"
238      */
239     public X500Name(String commonName, String organizationUnit,
240                     String organizationName, String localityName,
241                     String stateName, String country)
242     throws IOException {
243         names = new RDN[6];
244         /*
245          * NOTE:  it's only on output that little-endian
246          * ordering is used.
247          */
248         names[5] = new RDN(1);
249         names[5].assertion[0] = new AVA(commonName_oid,
250                 new DerValue(commonName));
251         names[4] = new RDN(1);
252         names[4].assertion[0] = new AVA(orgUnitName_oid,
253                 new DerValue(organizationUnit));
254         names[3] = new RDN(1);
255         names[3].assertion[0] = new AVA(orgName_oid,
256                 new DerValue(organizationName));
257         names[2] = new RDN(1);
258         names[2].assertion[0] = new AVA(localityName_oid,
259                 new DerValue(localityName));
260         names[1] = new RDN(1);
261         names[1].assertion[0] = new AVA(stateName_oid,
262                 new DerValue(stateName));
263         names[0] = new RDN(1);
264         names[0].assertion[0] = new AVA(countryName_oid,
265                 new DerValue(country));
266     }
267 
268     /**
269      * Constructs a name from an array of relative distinguished names
270      *
271      * @param rdnArray array of relative distinguished names
272      * @throws IOException on error
273      */
274     public X500Name(RDN[] rdnArray) throws IOException {
275         if (rdnArray == null) {
276             names = new RDN[0];
277         } else {
278             names = rdnArray.clone();
279             for (int i = 0; i < names.length; i++) {
280                 if (names[i] == null) {
281                     throw new IOException("Cannot create an X500Name");
282                 }
283             }
284         }
285     }
286 
287     /**
288      * Constructs a name from an ASN.1 encoded value.  The encoding
289      * of the name in the stream uses DER (a BER/1 subset).
290      *
291      * @param value a DER-encoded value holding an X.500 name.
292      */
293     public X500Name(DerValue value) throws IOException {
294         //Note that toDerInputStream uses only the buffer (data) and not
295         //the tag, so an empty SEQUENCE (OF) will yield an empty DerInputStream
296         this(value.toDerInputStream());
297     }
298 
299     /**
300      * Constructs a name from an ASN.1 encoded input stream.  The encoding
301      * of the name in the stream uses DER (a BER/1 subset).
302      *
303      * @param in DER-encoded data holding an X.500 name.
304      */
305     public X500Name(DerInputStream in) throws IOException {
306         parseDER(in);
307     }
308 
309     /**
310      *  Constructs a name from an ASN.1 encoded byte array.
311      *
312      * @param name DER-encoded byte array holding an X.500 name.
313      */
314     public X500Name(byte[] name) throws IOException {
315         DerInputStream in = new DerInputStream(name);
316         parseDER(in);
317     }
318 
319     /**
320      * Return an immutable List of all RDNs in this X500Name.
321      */
322     public List<RDN> rdns() {
323         List<RDN> list = rdnList;
324         if (list == null) {
325             list = Collections.unmodifiableList(Arrays.asList(names));
326             rdnList = list;
327         }
328         return list;
329     }
330 
331     /**
332      * Return the number of RDNs in this X500Name.
333      */
334     public int size() {
335         return names.length;
336     }
337 
338     /**
339      * Return an immutable List of the the AVAs contained in all the
340      * RDNs of this X500Name.
341      */
342     public List<AVA> allAvas() {
343         List<AVA> list = allAvaList;
344         if (list == null) {
345             list = new ArrayList<AVA>();
346             for (int i = 0; i < names.length; i++) {
347                 list.addAll(names[i].avas());
348             }
349         }
350         return list;
351     }
352 
353     /**
354      * Return the total number of AVAs contained in all the RDNs of
355      * this X500Name.
356      */
357     public int avaSize() {
358         return allAvas().size();
359     }
360 
361     /**
362      * Return whether this X500Name is empty. An X500Name is not empty
363      * if it has at least one RDN containing at least one AVA.
364      */
365     public boolean isEmpty() {
366         int n = names.length;
367         if (n == 0) {
368             return true;
369         }
370         for (int i = 0; i < n; i++) {
371             if (names[i].assertion.length != 0) {
372                 return false;
373             }
374         }
375         return true;
376     }
377 
378     /**
379      * Calculates a hash code value for the object.  Objects
380      * which are equal will also have the same hashcode.
381      */
382     public int hashCode() {
383         return getRFC2253CanonicalName().hashCode();
384     }
385 
386     /**
387      * Compares this name with another, for equality.
388      *
389      * @return true iff the names are identical.
390      */
391     public boolean equals(Object obj) {
392         if (this == obj) {
393             return true;
394         }
395         if (obj instanceof X500Name == false) {
396             return false;
397         }
398         X500Name other = (X500Name)obj;
399         // if we already have the canonical forms, compare now
400         if ((this.canonicalDn != null) && (other.canonicalDn != null)) {
401             return this.canonicalDn.equals(other.canonicalDn);
402         }
403         // quick check that number of RDNs and AVAs match before canonicalizing
404         int n = this.names.length;
405         if (n != other.names.length) {
406             return false;
407         }
408         for (int i = 0; i < n; i++) {
409             RDN r1 = this.names[i];
410             RDN r2 = other.names[i];
411             if (r1.assertion.length != r2.assertion.length) {
412                 return false;
413             }
414         }
415         // definite check via canonical form
416         String thisCanonical = this.getRFC2253CanonicalName();
417         String otherCanonical = other.getRFC2253CanonicalName();
418         return thisCanonical.equals(otherCanonical);
419     }
420 
421     /*
422      * Returns the name component as a Java string, regardless of its
423      * encoding restrictions.
424      */
425     private String getString(DerValue attribute) throws IOException {
426         if (attribute == null)
427             return null;
428         String  value = attribute.getAsString();
429 
430         if (value == null)
431             throw new IOException("not a DER string encoding, "
432                     + attribute.tag);
433         else
434             return value;
435     }
436 
437     /**
438      * Return type of GeneralName.
439      */
440     public int getType() {
441         return (GeneralNameInterface.NAME_DIRECTORY);
442     }
443 
444     /**
445      * Returns a "Country" name component.  If more than one
446      * such attribute exists, the topmost one is returned.
447      *
448      * @return "C=" component of the name, if any.
449      */
450     public String getCountry() throws IOException {
451         DerValue attr = findAttribute(countryName_oid);
452 
453         return getString(attr);
454     }
455 
456 
457     /**
458      * Returns an "Organization" name component.  If more than
459      * one such attribute exists, the topmost one is returned.
460      *
461      * @return "O=" component of the name, if any.
462      */
463     public String getOrganization() throws IOException {
464         DerValue attr = findAttribute(orgName_oid);
465 
466         return getString(attr);
467     }
468 
469 
470     /**
471      * Returns an "Organizational Unit" name component.  If more
472      * than one such attribute exists, the topmost one is returned.
473      *
474      * @return "OU=" component of the name, if any.
475      */
476     public String getOrganizationalUnit() throws IOException {
477         DerValue attr = findAttribute(orgUnitName_oid);
478 
479         return getString(attr);
480     }
481 
482 
483     /**
484      * Returns a "Common Name" component.  If more than one such
485      * attribute exists, the topmost one is returned.
486      *
487      * @return "CN=" component of the name, if any.
488      */
489     public String getCommonName() throws IOException {
490         DerValue attr = findAttribute(commonName_oid);
491 
492         return getString(attr);
493     }
494 
495 
496     /**
497      * Returns a "Locality" name component.  If more than one
498      * such component exists, the topmost one is returned.
499      *
500      * @return "L=" component of the name, if any.
501      */
502     public String getLocality() throws IOException {
503         DerValue attr = findAttribute(localityName_oid);
504 
505         return getString(attr);
506     }
507 
508     /**
509      * Returns a "State" name component.  If more than one
510      * such component exists, the topmost one is returned.
511      *
512      * @return "S=" component of the name, if any.
513      */
514     public String getState() throws IOException {
515       DerValue attr = findAttribute(stateName_oid);
516 
517         return getString(attr);
518     }
519 
520     /**
521      * Returns a "Domain" name component.  If more than one
522      * such component exists, the topmost one is returned.
523      *
524      * @return "DC=" component of the name, if any.
525      */
526     public String getDomain() throws IOException {
527         DerValue attr = findAttribute(DOMAIN_COMPONENT_OID);
528 
529         return getString(attr);
530     }
531 
532     /**
533      * Returns a "DN Qualifier" name component.  If more than one
534      * such component exists, the topmost one is returned.
535      *
536      * @return "DNQ=" component of the name, if any.
537      */
538     public String getDNQualifier() throws IOException {
539         DerValue attr = findAttribute(DNQUALIFIER_OID);
540 
541         return getString(attr);
542     }
543 
544     /**
545      * Returns a "Surname" name component.  If more than one
546      * such component exists, the topmost one is returned.
547      *
548      * @return "SURNAME=" component of the name, if any.
549      */
550     public String getSurname() throws IOException {
551         DerValue attr = findAttribute(SURNAME_OID);
552 
553         return getString(attr);
554     }
555 
556     /**
557      * Returns a "Given Name" name component.  If more than one
558      * such component exists, the topmost one is returned.
559      *
560      * @return "GIVENNAME=" component of the name, if any.
561      */
562     public String getGivenName() throws IOException {
563        DerValue attr = findAttribute(GIVENNAME_OID);
564 
565        return getString(attr);
566     }
567 
568     /**
569      * Returns an "Initials" name component.  If more than one
570      * such component exists, the topmost one is returned.
571      *
572      * @return "INITIALS=" component of the name, if any.
573      */
574     public String getInitials() throws IOException {
575         DerValue attr = findAttribute(INITIALS_OID);
576 
577         return getString(attr);
578      }
579 
580      /**
581       * Returns a "Generation Qualifier" name component.  If more than one
582       * such component exists, the topmost one is returned.
583       *
584       * @return "GENERATION=" component of the name, if any.
585       */
586     public String getGeneration() throws IOException {
587         DerValue attr = findAttribute(GENERATIONQUALIFIER_OID);
588 
589         return getString(attr);
590     }
591 
592     /**
593      * Returns an "IP address" name component.  If more than one
594      * such component exists, the topmost one is returned.
595      *
596      * @return "IP=" component of the name, if any.
597      */
598     public String getIP() throws IOException {
599         DerValue attr = findAttribute(ipAddress_oid);
600 
601         return getString(attr);
602     }
603 
604     /**
605      * Returns a string form of the X.500 distinguished name.
606      * The format of the string is from RFC 1779. The returned string
607      * may contain non-standardised keywords for more readability
608      * (keywords from RFCs 1779, 2253, and 3280).
609      */
610     public String toString() {
611         if (dn == null) {
612             generateDN();
613         }
614         return dn;
615     }
616 
617     /**
618      * Returns a string form of the X.500 distinguished name
619      * using the algorithm defined in RFC 1779. Only standard attribute type
620      * keywords defined in RFC 1779 are emitted.
621      */
622     public String getRFC1779Name() {
623         return getRFC1779Name(Collections.<String, String>emptyMap());
624     }
625 
626     /**
627      * Returns a string form of the X.500 distinguished name
628      * using the algorithm defined in RFC 1779. Attribute type
629      * keywords defined in RFC 1779 are emitted, as well as additional
630      * keywords contained in the OID/keyword map.
631      */
632     public String getRFC1779Name(Map<String, String> oidMap)
633         throws IllegalArgumentException {
634         if (oidMap.isEmpty()) {
635             // return cached result
636             if (rfc1779Dn != null) {
637                 return rfc1779Dn;
638             } else {
639                 rfc1779Dn = generateRFC1779DN(oidMap);
640                 return rfc1779Dn;
641             }
642         }
643         return generateRFC1779DN(oidMap);
644     }
645 
646     /**
647      * Returns a string form of the X.500 distinguished name
648      * using the algorithm defined in RFC 2253. Only standard attribute type
649      * keywords defined in RFC 2253 are emitted.
650      */
651     public String getRFC2253Name() {
652         return getRFC2253Name(Collections.<String, String>emptyMap());
653     }
654 
655     /**
656      * Returns a string form of the X.500 distinguished name
657      * using the algorithm defined in RFC 2253. Attribute type
658      * keywords defined in RFC 2253 are emitted, as well as additional
659      * keywords contained in the OID/keyword map.
660      */
661     public String getRFC2253Name(Map<String, String> oidMap) {
662         /* check for and return cached name */
663         if (oidMap.isEmpty()) {
664             if (rfc2253Dn != null) {
665                 return rfc2253Dn;
666             } else {
667                 rfc2253Dn = generateRFC2253DN(oidMap);
668                 return rfc2253Dn;
669             }
670         }
671         return generateRFC2253DN(oidMap);
672     }
673 
674     private String generateRFC2253DN(Map<String, String> oidMap) {
675         /*
676          * Section 2.1 : if the RDNSequence is an empty sequence
677          * the result is the empty or zero length string.
678          */
679         if (names.length == 0) {
680             return "";
681         }
682 
683         /*
684          * 2.1 (continued) : Otherwise, the output consists of the string
685          * encodings of each RelativeDistinguishedName in the RDNSequence
686          * (according to 2.2), starting with the last element of the sequence
687          * and moving backwards toward the first.
688          *
689          * The encodings of adjoining RelativeDistinguishedNames are separated
690          * by a comma character (',' ASCII 44).
691          */
692         StringBuilder fullname = new StringBuilder(48);
693         for (int i = names.length - 1; i >= 0; i--) {
694             if (i < names.length - 1) {
695                 fullname.append(',');
696             }
697             fullname.append(names[i].toRFC2253String(oidMap));
698         }
699         return fullname.toString();
700     }
701 
702     public String getRFC2253CanonicalName() {
703         /* check for and return cached name */
704         if (canonicalDn != null) {
705             return canonicalDn;
706         }
707         /*
708          * Section 2.1 : if the RDNSequence is an empty sequence
709          * the result is the empty or zero length string.
710          */
711         if (names.length == 0) {
712             canonicalDn = "";
713             return canonicalDn;
714         }
715 
716         /*
717          * 2.1 (continued) : Otherwise, the output consists of the string
718          * encodings of each RelativeDistinguishedName in the RDNSequence
719          * (according to 2.2), starting with the last element of the sequence
720          * and moving backwards toward the first.
721          *
722          * The encodings of adjoining RelativeDistinguishedNames are separated
723          * by a comma character (',' ASCII 44).
724          */
725         StringBuilder fullname = new StringBuilder(48);
726         for (int i = names.length - 1; i >= 0; i--) {
727             if (i < names.length - 1) {
728                 fullname.append(',');
729             }
730             fullname.append(names[i].toRFC2253String(true));
731         }
732         canonicalDn = fullname.toString();
733         return canonicalDn;
734     }
735 
736     /**
737      * Returns the value of toString().  This call is needed to
738      * implement the java.security.Principal interface.
739      */
740     public String getName() { return toString(); }
741 
742     /**
743      * Find the first instance of this attribute in a "top down"
744      * search of all the attributes in the name.
745      */
746     private DerValue findAttribute(ObjectIdentifier attribute) {
747         if (names != null) {
748             for (int i = 0; i < names.length; i++) {
749                 DerValue value = names[i].findAttribute(attribute);
750                 if (value != null) {
751                     return value;
752                 }
753             }
754         }
755         return null;
756     }
757 
758     /**
759      * Find the most specific ("last") attribute of the given
760      * type.
761      */
762     public DerValue findMostSpecificAttribute(ObjectIdentifier attribute) {
763         if (names != null) {
764             for (int i = names.length - 1; i >= 0; i--) {
765                 DerValue value = names[i].findAttribute(attribute);
766                 if (value != null) {
767                     return value;
768                 }
769             }
770         }
771         return null;
772     }
773 
774     /****************************************************************/
775 
776     private void parseDER(DerInputStream in) throws IOException {
777         //
778         // X.500 names are a "SEQUENCE OF" RDNs, which means zero or
779         // more and order matters.  We scan them in order, which
780         // conventionally is big-endian.
781         //
782         DerValue[] nameseq = null;
783         byte[] derBytes = in.toByteArray();
784 
785         try {
786             nameseq = in.getSequence(5);
787         } catch (IOException ioe) {
788             if (derBytes == null) {
789                 nameseq = null;
790             } else {
791                 DerValue derVal = new DerValue(DerValue.tag_Sequence,
792                                            derBytes);
793                 derBytes = derVal.toByteArray();
794                 nameseq = new DerInputStream(derBytes).getSequence(5);
795             }
796         }
797 
798         if (nameseq == null) {
799             names = new RDN[0];
800         } else {
801             names = new RDN[nameseq.length];
802             for (int i = 0; i < nameseq.length; i++) {
803                 names[i] = new RDN(nameseq[i]);
804             }
805         }
806     }
807 
808     /**
809      * Encodes the name in DER-encoded form.
810      *
811      * @deprecated Use encode() instead
812      * @param out where to put the DER-encoded X.500 name
813      */
814     @Deprecated
815     public void emit(DerOutputStream out) throws IOException {
816         encode(out);
817     }
818 
819     /**
820      * Encodes the name in DER-encoded form.
821      *
822      * @param out where to put the DER-encoded X.500 name
823      */
824     public void encode(DerOutputStream out) throws IOException {
825         DerOutputStream tmp = new DerOutputStream();
826         for (int i = 0; i < names.length; i++) {
827             names[i].encode(tmp);
828         }
829         out.write(DerValue.tag_Sequence, tmp);
830     }
831 
832     /**
833      * Returned the encoding as an uncloned byte array. Callers must
834      * guarantee that they neither modify it not expose it to untrusted
835      * code.
836      */
837     public byte[] getEncodedInternal() throws IOException {
838         if (encoded == null) {
839             DerOutputStream     out = new DerOutputStream();
840             DerOutputStream     tmp = new DerOutputStream();
841             for (int i = 0; i < names.length; i++) {
842                 names[i].encode(tmp);
843             }
844             out.write(DerValue.tag_Sequence, tmp);
845             encoded = out.toByteArray();
846         }
847         return encoded;
848     }
849 
850     /**
851      * Gets the name in DER-encoded form.
852      *
853      * @return the DER encoded byte array of this name.
854      */
855     public byte[] getEncoded() throws IOException {
856         return getEncodedInternal().clone();
857     }
858 
859     /*
860      * Parses a Distinguished Name (DN) in printable representation.
861      *
862      * According to RFC 1779, RDNs in a DN are separated by comma.
863      * The following examples show both methods of quoting a comma, so that it
864      * is not considered a separator:
865      *
866      *     O="Sue, Grabbit and Runn" or
867      *     O=Sue\, Grabbit and Runn
868      *
869      * This method can parse RFC 1779, 2253 or 4514 DNs and non-standard 3280
870      * keywords. Additional keywords can be specified in the keyword/OID map.
871      */
872     private void parseDN(String input, Map<String, String> keywordMap)
873         throws IOException {
874         if (input == null || input.length() == 0) {
875             names = new RDN[0];
876             return;
877         }
878 
879         List<RDN> dnVector = new ArrayList<>();
880         int dnOffset = 0;
881         int rdnEnd;
882         String rdnString;
883         int quoteCount = 0;
884 
885         String dnString = input;
886 
887         int searchOffset = 0;
888         int nextComma = dnString.indexOf(',');
889         int nextSemiColon = dnString.indexOf(';');
890         while (nextComma >=0 || nextSemiColon >=0) {
891 
892             if (nextSemiColon < 0) {
893                 rdnEnd = nextComma;
894             } else if (nextComma < 0) {
895                 rdnEnd = nextSemiColon;
896             } else {
897                 rdnEnd = Math.min(nextComma, nextSemiColon);
898             }
899             quoteCount += countQuotes(dnString, searchOffset, rdnEnd);
900 
901             /*
902              * We have encountered an RDN delimiter (comma or a semicolon).
903              * If the comma or semicolon in the RDN under consideration is
904              * preceded by a backslash (escape), or by a double quote, it
905              * is part of the RDN. Otherwise, it is used as a separator, to
906              * delimit the RDN under consideration from any subsequent RDNs.
907              */
908             if (rdnEnd >= 0 && quoteCount != 1 &&
909                 !escaped(rdnEnd, searchOffset, dnString)) {
910 
911                 /*
912                  * Comma/semicolon is a separator
913                  */
914                 rdnString = dnString.substring(dnOffset, rdnEnd);
915 
916                 // Parse RDN, and store it in vector
917                 RDN rdn = new RDN(rdnString, keywordMap);
918                 dnVector.add(rdn);
919 
920                 // Increase the offset
921                 dnOffset = rdnEnd + 1;
922 
923                 // Set quote counter back to zero
924                 quoteCount = 0;
925             }
926 
927             searchOffset = rdnEnd + 1;
928             nextComma = dnString.indexOf(',', searchOffset);
929             nextSemiColon = dnString.indexOf(';', searchOffset);
930         }
931 
932         // Parse last or only RDN, and store it in vector
933         rdnString = dnString.substring(dnOffset);
934         RDN rdn = new RDN(rdnString, keywordMap);
935         dnVector.add(rdn);
936 
937         /*
938          * Store the vector elements as an array of RDNs
939          * NOTE: It's only on output that little-endian ordering is used.
940          */
941         Collections.reverse(dnVector);
942         names = dnVector.toArray(new RDN[dnVector.size()]);
943     }
944 
945     private void parseRFC2253DN(String dnString) throws IOException {
946         if (dnString.length() == 0) {
947             names = new RDN[0];
948             return;
949          }
950 
951          List<RDN> dnVector = new ArrayList<>();
952          int dnOffset = 0;
953          String rdnString;
954          int searchOffset = 0;
955          int rdnEnd = dnString.indexOf(',');
956          while (rdnEnd >=0) {
957              /*
958               * We have encountered an RDN delimiter (comma).
959               * If the comma in the RDN under consideration is
960               * preceded by a backslash (escape), it
961               * is part of the RDN. Otherwise, it is used as a separator, to
962               * delimit the RDN under consideration from any subsequent RDNs.
963               */
964              if (rdnEnd > 0 && !escaped(rdnEnd, searchOffset, dnString)) {
965 
966                  /*
967                   * Comma is a separator
968                   */
969                  rdnString = dnString.substring(dnOffset, rdnEnd);
970 
971                  // Parse RDN, and store it in vector
972                  RDN rdn = new RDN(rdnString, "RFC2253");
973                  dnVector.add(rdn);
974 
975                  // Increase the offset
976                  dnOffset = rdnEnd + 1;
977              }
978 
979              searchOffset = rdnEnd + 1;
980              rdnEnd = dnString.indexOf(',', searchOffset);
981          }
982 
983          // Parse last or only RDN, and store it in vector
984          rdnString = dnString.substring(dnOffset);
985          RDN rdn = new RDN(rdnString, "RFC2253");
986          dnVector.add(rdn);
987 
988          /*
989           * Store the vector elements as an array of RDNs
990           * NOTE: It's only on output that little-endian ordering is used.
991           */
992          Collections.reverse(dnVector);
993          names = dnVector.toArray(new RDN[dnVector.size()]);
994     }
995 
996     /*
997      * Counts double quotes in string.
998      * Escaped quotes are ignored.
999      */
1000     static int countQuotes(String string, int from, int to) {
1001         int count = 0;
1002 
1003         for (int i = from; i < to; i++) {
1004             if ((string.charAt(i) == '"' && i == from) ||
1005                 (string.charAt(i) == '"' && string.charAt(i-1) != '\\')) {
1006                 count++;
1007             }
1008         }
1009 
1010         return count;
1011     }
1012 
1013     private static boolean escaped
1014                 (int rdnEnd, int searchOffset, String dnString) {
1015 
1016         if (rdnEnd == 1 && dnString.charAt(rdnEnd - 1) == '\\') {
1017 
1018             //  case 1:
1019             //  \,
1020 
1021             return true;
1022 
1023         } else if (rdnEnd > 1 && dnString.charAt(rdnEnd - 1) == '\\' &&
1024                 dnString.charAt(rdnEnd - 2) != '\\') {
1025 
1026             //  case 2:
1027             //  foo\,
1028 
1029             return true;
1030 
1031         } else if (rdnEnd > 1 && dnString.charAt(rdnEnd - 1) == '\\' &&
1032                 dnString.charAt(rdnEnd - 2) == '\\') {
1033 
1034             //  case 3:
1035             //  foo\\\\\,
1036 
1037             int count = 0;
1038             rdnEnd--;   // back up to last backSlash
1039             while (rdnEnd >= searchOffset) {
1040                 if (dnString.charAt(rdnEnd) == '\\') {
1041                     count++;    // count consecutive backslashes
1042                 }
1043                 rdnEnd--;
1044             }
1045 
1046             // if count is odd, then rdnEnd is escaped
1047             return (count % 2) != 0 ? true : false;
1048 
1049         } else {
1050             return false;
1051         }
1052     }
1053 
1054     /*
1055      * Dump the printable form of a distinguished name.  Each relative
1056      * name is separated from the next by a ",", and assertions in the
1057      * relative names have "label=value" syntax.
1058      *
1059      * Uses RFC 1779 syntax (i.e. little-endian, comma separators)
1060      */
1061     private void generateDN() {
1062         if (names.length == 1) {
1063             dn = names[0].toString();
1064             return;
1065         }
1066 
1067         StringBuilder sb = new StringBuilder(48);
1068         if (names != null) {
1069             for (int i = names.length - 1; i >= 0; i--) {
1070                 if (i != names.length - 1) {
1071                     sb.append(", ");
1072                 }
1073                 sb.append(names[i].toString());
1074             }
1075         }
1076         dn = sb.toString();
1077     }
1078 
1079     /*
1080      * Dump the printable form of a distinguished name.  Each relative
1081      * name is separated from the next by a ",", and assertions in the
1082      * relative names have "label=value" syntax.
1083      *
1084      * Uses RFC 1779 syntax (i.e. little-endian, comma separators)
1085      * Valid keywords from RFC 1779 are used. Additional keywords can be
1086      * specified in the OID/keyword map.
1087      */
1088     private String generateRFC1779DN(Map<String, String> oidMap) {
1089         if (names.length == 1) {
1090             return names[0].toRFC1779String(oidMap);
1091         }
1092 
1093         StringBuilder sb = new StringBuilder(48);
1094         if (names != null) {
1095             for (int i = names.length - 1; i >= 0; i--) {
1096                 if (i != names.length - 1) {
1097                     sb.append(", ");
1098                 }
1099                 sb.append(names[i].toRFC1779String(oidMap));
1100             }
1101         }
1102         return sb.toString();
1103     }
1104 
1105     /****************************************************************/
1106 
1107     /*
1108      * Maybe return a preallocated OID, to reduce storage costs
1109      * and speed recognition of common X.500 attributes.
1110      */
1111     static ObjectIdentifier intern(ObjectIdentifier oid) {
1112         ObjectIdentifier interned = internedOIDs.get(oid);
1113         if (interned != null) {
1114             return interned;
1115         }
1116         internedOIDs.put(oid, oid);
1117         return oid;
1118     }
1119 
1120     private static final Map<ObjectIdentifier,ObjectIdentifier> internedOIDs
1121                         = new HashMap<ObjectIdentifier,ObjectIdentifier>();
1122 
1123     /*
1124      * Selected OIDs from X.520
1125      * Includes all those specified in RFC 3280 as MUST or SHOULD
1126      * be recognized
1127      */
1128     private static final int commonName_data[] = { 2, 5, 4, 3 };
1129     private static final int SURNAME_DATA[] = { 2, 5, 4, 4 };
1130     private static final int SERIALNUMBER_DATA[] = { 2, 5, 4, 5 };
1131     private static final int countryName_data[] = { 2, 5, 4, 6 };
1132     private static final int localityName_data[] = { 2, 5, 4, 7 };
1133     private static final int stateName_data[] = { 2, 5, 4, 8 };
1134     private static final int streetAddress_data[] = { 2, 5, 4, 9 };
1135     private static final int orgName_data[] = { 2, 5, 4, 10 };
1136     private static final int orgUnitName_data[] = { 2, 5, 4, 11 };
1137     private static final int title_data[] = { 2, 5, 4, 12 };
1138     private static final int GIVENNAME_DATA[] = { 2, 5, 4, 42 };
1139     private static final int INITIALS_DATA[] = { 2, 5, 4, 43 };
1140     private static final int GENERATIONQUALIFIER_DATA[] = { 2, 5, 4, 44 };
1141     private static final int DNQUALIFIER_DATA[] = { 2, 5, 4, 46 };
1142 
1143     private static final int ipAddress_data[] = { 1, 3, 6, 1, 4, 1, 42, 2, 11, 2, 1 };
1144     private static final int DOMAIN_COMPONENT_DATA[] =
1145         { 0, 9, 2342, 19200300, 100, 1, 25 };
1146     private static final int userid_data[] =
1147         { 0, 9, 2342, 19200300, 100, 1, 1 };
1148 
1149 
1150     public static final ObjectIdentifier commonName_oid;
1151     public static final ObjectIdentifier countryName_oid;
1152     public static final ObjectIdentifier localityName_oid;
1153     public static final ObjectIdentifier orgName_oid;
1154     public static final ObjectIdentifier orgUnitName_oid;
1155     public static final ObjectIdentifier stateName_oid;
1156     public static final ObjectIdentifier streetAddress_oid;
1157     public static final ObjectIdentifier title_oid;
1158     public static final ObjectIdentifier DNQUALIFIER_OID;
1159     public static final ObjectIdentifier SURNAME_OID;
1160     public static final ObjectIdentifier GIVENNAME_OID;
1161     public static final ObjectIdentifier INITIALS_OID;
1162     public static final ObjectIdentifier GENERATIONQUALIFIER_OID;
1163     public static final ObjectIdentifier ipAddress_oid;
1164     public static final ObjectIdentifier DOMAIN_COMPONENT_OID;
1165     public static final ObjectIdentifier userid_oid;
1166     public static final ObjectIdentifier SERIALNUMBER_OID;
1167 
1168     static {
1169     /** OID for the "CN=" attribute, denoting a person's common name. */
1170         commonName_oid = intern(ObjectIdentifier.newInternal(commonName_data));
1171 
1172     /** OID for the "SERIALNUMBER=" attribute, denoting a serial number for.
1173         a name. Do not confuse with PKCS#9 issuerAndSerialNumber or the
1174         certificate serial number. */
1175         SERIALNUMBER_OID = intern(ObjectIdentifier.newInternal(SERIALNUMBER_DATA));
1176 
1177     /** OID for the "C=" attribute, denoting a country. */
1178         countryName_oid = intern(ObjectIdentifier.newInternal(countryName_data));
1179 
1180     /** OID for the "L=" attribute, denoting a locality (such as a city) */
1181         localityName_oid = intern(ObjectIdentifier.newInternal(localityName_data));
1182 
1183     /** OID for the "O=" attribute, denoting an organization name */
1184         orgName_oid = intern(ObjectIdentifier.newInternal(orgName_data));
1185 
1186     /** OID for the "OU=" attribute, denoting an organizational unit name */
1187         orgUnitName_oid = intern(ObjectIdentifier.newInternal(orgUnitName_data));
1188 
1189     /** OID for the "S=" attribute, denoting a state (such as Delaware) */
1190         stateName_oid = intern(ObjectIdentifier.newInternal(stateName_data));
1191 
1192     /** OID for the "STREET=" attribute, denoting a street address. */
1193         streetAddress_oid = intern(ObjectIdentifier.newInternal(streetAddress_data));
1194 
1195     /** OID for the "T=" attribute, denoting a person's title. */
1196         title_oid = intern(ObjectIdentifier.newInternal(title_data));
1197 
1198     /** OID for the "DNQUALIFIER=" or "DNQ=" attribute, denoting DN
1199         disambiguating information.*/
1200         DNQUALIFIER_OID = intern(ObjectIdentifier.newInternal(DNQUALIFIER_DATA));
1201 
1202     /** OID for the "SURNAME=" attribute, denoting a person's surname.*/
1203         SURNAME_OID = intern(ObjectIdentifier.newInternal(SURNAME_DATA));
1204 
1205     /** OID for the "GIVENNAME=" attribute, denoting a person's given name.*/
1206         GIVENNAME_OID = intern(ObjectIdentifier.newInternal(GIVENNAME_DATA));
1207 
1208     /** OID for the "INITIALS=" attribute, denoting a person's initials.*/
1209         INITIALS_OID = intern(ObjectIdentifier.newInternal(INITIALS_DATA));
1210 
1211     /** OID for the "GENERATION=" attribute, denoting Jr., II, etc.*/
1212         GENERATIONQUALIFIER_OID =
1213             intern(ObjectIdentifier.newInternal(GENERATIONQUALIFIER_DATA));
1214 
1215     /*
1216      * OIDs from other sources which show up in X.500 names we
1217      * expect to deal with often
1218      */
1219     /** OID for "IP=" IP address attributes, used with SKIP. */
1220         ipAddress_oid = intern(ObjectIdentifier.newInternal(ipAddress_data));
1221 
1222     /*
1223      * Domain component OID from RFC 1274, RFC 2247, RFC 3280
1224      */
1225 
1226     /*
1227      * OID for "DC=" domain component attributes, used with DNS names in DN
1228      * format
1229      */
1230         DOMAIN_COMPONENT_OID =
1231             intern(ObjectIdentifier.newInternal(DOMAIN_COMPONENT_DATA));
1232 
1233     /** OID for "UID=" denoting a user id, defined in RFCs 1274 & 2798. */
1234         userid_oid = intern(ObjectIdentifier.newInternal(userid_data));
1235     }
1236 
1237     /**
1238      * Return constraint type:<ul>
1239      *   <li>NAME_DIFF_TYPE = -1: input name is different type from this name
1240      *       (i.e. does not constrain)
1241      *   <li>NAME_MATCH = 0: input name matches this name
1242      *   <li>NAME_NARROWS = 1: input name narrows this name
1243      *   <li>NAME_WIDENS = 2: input name widens this name
1244      *   <li>NAME_SAME_TYPE = 3: input name does not match or narrow this name,
1245      &       but is same type
1246      * </ul>.  These results are used in checking NameConstraints during
1247      * certification path verification.
1248      *
1249      * @param inputName to be checked for being constrained
1250      * @returns constraint type above
1251      * @throws UnsupportedOperationException if name is not exact match, but
1252      *         narrowing and widening are not supported for this name type.
1253      */
1254     public int constrains(GeneralNameInterface inputName)
1255             throws UnsupportedOperationException {
1256         int constraintType;
1257         if (inputName == null) {
1258             constraintType = NAME_DIFF_TYPE;
1259         } else if (inputName.getType() != NAME_DIRECTORY) {
1260             constraintType = NAME_DIFF_TYPE;
1261         } else { // type == NAME_DIRECTORY
1262             X500Name inputX500 = (X500Name)inputName;
1263             if (inputX500.equals(this)) {
1264                 constraintType = NAME_MATCH;
1265             } else if (inputX500.names.length == 0) {
1266                 constraintType = NAME_WIDENS;
1267             } else if (this.names.length == 0) {
1268                 constraintType = NAME_NARROWS;
1269             } else if (inputX500.isWithinSubtree(this)) {
1270                 constraintType = NAME_NARROWS;
1271             } else if (isWithinSubtree(inputX500)) {
1272                 constraintType = NAME_WIDENS;
1273             } else {
1274                 constraintType = NAME_SAME_TYPE;
1275             }
1276         }
1277         return constraintType;
1278     }
1279 
1280     /**
1281      * Compares this name with another and determines if
1282      * it is within the subtree of the other. Useful for
1283      * checking against the name constraints extension.
1284      *
1285      * @return true iff this name is within the subtree of other.
1286      */
1287     private boolean isWithinSubtree(X500Name other) {
1288         if (this == other) {
1289             return true;
1290         }
1291         if (other == null) {
1292             return false;
1293         }
1294         if (other.names.length == 0) {
1295             return true;
1296         }
1297         if (this.names.length == 0) {
1298             return false;
1299         }
1300         if (names.length < other.names.length) {
1301             return false;
1302         }
1303         for (int i = 0; i < other.names.length; i++) {
1304             if (!names[i].equals(other.names[i])) {
1305                 return false;
1306             }
1307         }
1308         return true;
1309     }
1310 
1311     /**
1312      * Return subtree depth of this name for purposes of determining
1313      * NameConstraints minimum and maximum bounds and for calculating
1314      * path lengths in name subtrees.
1315      *
1316      * @returns distance of name from root
1317      * @throws UnsupportedOperationException if not supported for this name type
1318      */
1319     public int subtreeDepth() throws UnsupportedOperationException {
1320         return names.length;
1321     }
1322 
1323     /**
1324      * Return lowest common ancestor of this name and other name
1325      *
1326      * @param other another X500Name
1327      * @return X500Name of lowest common ancestor; null if none
1328      */
1329     public X500Name commonAncestor(X500Name other) {
1330 
1331         if (other == null) {
1332             return null;
1333         }
1334         int otherLen = other.names.length;
1335         int thisLen = this.names.length;
1336         if (thisLen == 0 || otherLen == 0) {
1337             return null;
1338         }
1339         int minLen = (thisLen < otherLen) ? thisLen: otherLen;
1340 
1341         //Compare names from highest RDN down the naming tree
1342         //Note that these are stored in RDN[0]...
1343         int i=0;
1344         for (; i < minLen; i++) {
1345             if (!names[i].equals(other.names[i])) {
1346                 if (i == 0) {
1347                     return null;
1348                 } else {
1349                     break;
1350                 }
1351             }
1352         }
1353 
1354         //Copy matching RDNs into new RDN array
1355         RDN[] ancestor = new RDN[i];
1356         for (int j=0; j < i; j++) {
1357             ancestor[j] = names[j];
1358         }
1359 
1360         X500Name commonAncestor = null;
1361         try {
1362             commonAncestor = new X500Name(ancestor);
1363         } catch (IOException ioe) {
1364             return null;
1365         }
1366         return commonAncestor;
1367     }
1368 
1369     /**
1370      * Constructor object for use by asX500Principal().
1371      */
1372     private static final Constructor<X500Principal> principalConstructor;
1373 
1374     /**
1375      * Field object for use by asX500Name().
1376      */
1377     private static final Field principalField;
1378 
1379     /**
1380      * Retrieve the Constructor and Field we need for reflective access
1381      * and make them accessible.
1382      */
1383     static {
1384         PrivilegedExceptionAction<Object[]> pa =
1385                 new PrivilegedExceptionAction<Object[]>() {
1386             public Object[] run() throws Exception {
1387                 Class<X500Principal> pClass = X500Principal.class;
1388                 Class<?>[] args = new Class<?>[] { X500Name.class };
1389                 Constructor<X500Principal> cons = pClass.getDeclaredConstructor(args);
1390                 cons.setAccessible(true);
1391                 Field field = pClass.getDeclaredField("thisX500Name");
1392                 field.setAccessible(true);
1393                 return new Object[] {cons, field};
1394             }
1395         };
1396         try {
1397             Object[] result = AccessController.doPrivileged(pa);
1398             @SuppressWarnings("unchecked")
1399             Constructor<X500Principal> constr =
1400                     (Constructor<X500Principal>)result[0];
1401             principalConstructor = constr;
1402             principalField = (Field)result[1];
1403         } catch (Exception e) {
1404             throw new InternalError("Could not obtain X500Principal access", e);
1405         }
1406     }
1407 
1408     /**
1409      * Get an X500Principal backed by this X500Name.
1410      *
1411      * Note that we are using privileged reflection to access the hidden
1412      * package private constructor in X500Principal.
1413      */
1414     public X500Principal asX500Principal() {
1415         if (x500Principal == null) {
1416             try {
1417                 Object[] args = new Object[] {this};
1418                 x500Principal = principalConstructor.newInstance(args);
1419             } catch (Exception e) {
1420                 throw new RuntimeException("Unexpected exception", e);
1421             }
1422         }
1423         return x500Principal;
1424     }
1425 
1426     /**
1427      * Get the X500Name contained in the given X500Principal.
1428      *
1429      * Note that the X500Name is retrieved using reflection.
1430      */
1431     public static X500Name asX500Name(X500Principal p) {
1432         try {
1433             X500Name name = (X500Name)principalField.get(p);
1434             name.x500Principal = p;
1435             return name;
1436         } catch (Exception e) {
1437             throw new RuntimeException("Unexpected exception", e);
1438         }
1439     }
1440 
1441 }