2002/03/21 01:19:32
[org.ibex.core.git] / src / org / bouncycastle / asn1 / x509 / X509Name.java
1 package org.bouncycastle.asn1.x509;
2
3 import java.io.*;
4 import java.util.*;
5
6 import org.bouncycastle.asn1.*;
7
8 public class X509Name
9     implements DEREncodable
10 {
11     /**
12      * country code - StringType(SIZE(2))
13      */
14     public static final DERObjectIdentifier C = new DERObjectIdentifier("2.5.4.6");
15
16     /**
17      * organization - StringType(SIZE(1..64))
18      */
19     public static final DERObjectIdentifier O = new DERObjectIdentifier("2.5.4.10");
20
21     /**
22      * organizational unit name - StringType(SIZE(1..64))
23      */
24     public static final DERObjectIdentifier OU = new DERObjectIdentifier("2.5.4.11");
25
26     /**
27      * common name - StringType(SIZE(1..64))
28      */
29     public static final DERObjectIdentifier CN = new DERObjectIdentifier("2.5.4.3");
30
31     /**
32      * device serial number name - StringType(SIZE(1..64))
33      */
34     public static final DERObjectIdentifier SN = new DERObjectIdentifier("2.5.4.5");
35
36     /**
37      * locality name - StringType(SIZE(1..64))
38      */
39     public static final DERObjectIdentifier L = new DERObjectIdentifier("2.5.4.7");
40
41     /**
42      * state, or province name - StringType(SIZE(1..64))
43      */
44     public static final DERObjectIdentifier ST = new DERObjectIdentifier("2.5.4.8");
45
46     /**
47      * email address (RSA PKCS#9 extension) - IA5String
48      * <p>
49      * note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
50      */
51     public static final DERObjectIdentifier EmailAddress = new DERObjectIdentifier("1.2.840.113549.1.9.1");
52
53     /**
54      * look up table translating OID values into their common symbols.
55      */
56     public static Hashtable OIDLookUp = new Hashtable();
57
58     /**
59      * look up table translating common symbols into their OIDS.
60      */
61     public static Hashtable SymbolLookUp = new Hashtable();
62
63     static
64     {
65         OIDLookUp.put(C, "C");
66         OIDLookUp.put(O, "O");
67         OIDLookUp.put(OU, "OU");
68         OIDLookUp.put(CN, "CN");
69         OIDLookUp.put(L, "L");
70         OIDLookUp.put(ST, "ST");
71         OIDLookUp.put(SN, "SN");
72         OIDLookUp.put(EmailAddress, "EmailAddress");
73
74         SymbolLookUp.put("C", C);
75         SymbolLookUp.put("O", O);
76         SymbolLookUp.put("OU", OU);
77         SymbolLookUp.put("CN", CN);
78         SymbolLookUp.put("L", L);
79         SymbolLookUp.put("ST", ST);
80         SymbolLookUp.put("SN", SN);
81         SymbolLookUp.put("EmailAddress", EmailAddress);
82     }
83
84     private Vector                  ordering = new Vector();
85     private Hashtable               attributes = new Hashtable();
86     private DERConstructedSequence  seq = null;
87
88     /**
89      * Constructor from DERConstructedSequence.
90      *
91      * the principal will be a list of constructed sets, each containing an (OID, String) pair.
92      */
93     public X509Name(
94         DERConstructedSequence  seq)
95     {
96         this.seq = seq; 
97
98         Enumeration e = seq.getObjects();
99
100         while (e.hasMoreElements())
101         {
102             DERSet  set = (DERSet)e.nextElement();
103             DERConstructedSequence  s = (DERConstructedSequence)set.getSequence();
104
105             ordering.addElement(s.getObjectAt(0));
106             attributes.put(s.getObjectAt(0), ((DERString)s.getObjectAt(1)).getString());
107         }
108     }
109
110     /**
111      * constructor from a table of attributes.
112      * <p>
113      * it's is assumed the table contains OID/String pairs, and the contents
114      * of the table are copied into an internal table as part of the 
115      * construction process.
116      * <p>
117      * <b>Note:</b> if the name you are trying to generate should be
118      * following a specific ordering, you should use the constructor
119      * with the ordering specified below.
120      */
121     public X509Name(
122         Hashtable  attributes)
123     {
124         this(null, attributes);
125     }
126
127     /**
128      * constructor from a table of attributes with ordering.
129      * <p>
130      * it's is assumed the table contains OID/String pairs, and the contents
131      * of the table are copied into an internal table as part of the 
132      * construction process. The ordering vector should contain the OIDs
133      * in the order they are meant to be encoded or printed in toString.
134      */
135     public X509Name(
136         Vector      ordering,
137         Hashtable   attributes)
138     {
139         if (ordering != null)
140         {
141             for (int i = 0; i != ordering.size(); i++)
142             {
143                 this.ordering.addElement(ordering.elementAt(i));
144             }
145         }
146         else
147         {
148             Enumeration     e = attributes.keys();
149
150             while (e.hasMoreElements())
151             {
152                 this.ordering.addElement(e.nextElement());
153             }
154         }
155
156         for (int i = 0; i != this.ordering.size(); i++)
157         {
158             DERObjectIdentifier     oid = (DERObjectIdentifier)this.ordering.elementAt(i);
159
160             if (OIDLookUp.get(oid) == null)
161             {
162                 throw new IllegalArgumentException("Unknown object id - " + oid.getId() + " - passed to distinguished name");
163             }
164
165             if (attributes.get(oid) == null)
166             {
167                 throw new IllegalArgumentException("No attribute for object id - " + oid.getId() + " - passed to distinguished name");
168             }
169
170             this.attributes.put(oid, attributes.get(oid)); // copy the hash table
171         }
172     }
173
174     /**
175      * takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
176      * some such, converting it into an ordered set of name attributes.
177      */
178     public X509Name(
179         String  dirName)
180     {
181         X509NameTokenizer   nTok = new X509NameTokenizer(dirName);
182
183         while (nTok.hasMoreTokens())
184         {
185             String  token = nTok.nextToken();
186             int     index = token.indexOf('=');
187
188             if (index == -1)
189             {
190                 throw new IllegalArgumentException("badly formated directory string");
191             }
192
193             String  name = token.substring(0, index);
194             String  value = token.substring(index + 1);
195
196             DERObjectIdentifier oid = (DERObjectIdentifier)SymbolLookUp.get(name);
197             if (oid == null)
198             {
199                 throw new IllegalArgumentException("Unknown object id - " + oid.getId() + " - passed to distinguished name");
200             }
201
202             this.ordering.addElement(oid);
203             this.attributes.put(oid, value);
204         }
205     }
206
207     public DERObject getDERObject()
208     {
209         if (seq == null)
210         {
211             seq = new DERConstructedSequence();
212
213             for (int i = 0; i != ordering.size(); i++)
214             {
215                 DERConstructedSequence  s = new DERConstructedSequence();
216                 DERObjectIdentifier     oid = (DERObjectIdentifier)ordering.elementAt(i);
217
218                 s.addObject(oid);
219                 if (oid.equals(EmailAddress))
220                 {
221                     s.addObject(new DERIA5String((String)attributes.get(oid)));
222                 }
223                 else
224                 {
225                     s.addObject(new DERPrintableString((String)attributes.get(oid)));
226                 }
227
228                 seq.addObject(new DERSet(s));
229             }
230         }
231
232         return seq;
233     }
234
235     public int hashCode()
236     {
237         Enumeration     e = attributes.keys();
238         int             hashCode = 0;
239
240         while (e.hasMoreElements())
241         {
242             Object  o = e.nextElement();
243
244             hashCode ^= o.hashCode();
245             hashCode ^= attributes.get(o).hashCode();
246         }
247
248         for (int i = 0; i != ordering.size(); i++)
249         {
250             hashCode ^= ordering.elementAt(i).hashCode();
251         }
252
253         return hashCode;
254     }
255
256     public boolean equals(
257         Object o)
258     {
259         if (o == null || !(o instanceof X509Name))
260         {
261             return false;
262         }
263
264         X509Name        other = (X509Name)o;
265
266         if (ordering.size() != other.ordering.size())
267         {
268             return false;
269         }
270
271         for (int i = 0; i != ordering.size(); i++)
272         {
273             if (!ordering.elementAt(i).equals(other.ordering.elementAt(i)))
274             {
275                 return false;
276             }
277         }
278
279         Enumeration     e1 = attributes.keys();
280         Enumeration     e2 = other.attributes.keys();
281
282         while (e1.hasMoreElements() && e2.hasMoreElements())
283         {
284             Object  o1 = e1.nextElement();
285             Object  o2 = e2.nextElement();
286             
287             if (!o1.equals(o2))
288             {
289                 return false;
290             }
291         }
292
293         if (e1.hasMoreElements() || e2.hasMoreElements())
294         {
295             return false;
296         }
297
298         return true;
299     }
300
301     public String toString()
302     {
303         StringBuffer    buf = new StringBuffer();
304         boolean         first = true;
305
306         for (int i = 0; i != ordering.size(); i++)
307         {
308             Object  oid = ordering.elementAt(i);
309             String  sym = (String)OIDLookUp.get(oid);
310             
311             if (first)
312             {
313                 first = false;
314             }
315             else
316             {
317                 buf.append(", ");
318             }
319
320             if (sym != null)
321             {
322                 buf.append(sym);
323                 buf.append("=");
324                 buf.append((String)attributes.get(oid));
325             }
326             else
327             {
328                 buf.append(((DERObjectIdentifier)oid).getId());
329                 buf.append("=");
330                 buf.append((String)attributes.get(oid));
331             }
332         }
333
334         return buf.toString();
335     }
336 }