1 package org.bouncycastle.asn1.x509;
5 import org.bouncycastle.asn1.*;
8 implements DEREncodable
11 * country code - StringType(SIZE(2))
13 public static final DERObjectIdentifier C = new DERObjectIdentifier("2.5.4.6");
16 * organization - StringType(SIZE(1..64))
18 public static final DERObjectIdentifier O = new DERObjectIdentifier("2.5.4.10");
21 * organizational unit name - StringType(SIZE(1..64))
23 public static final DERObjectIdentifier OU = new DERObjectIdentifier("2.5.4.11");
28 public static final DERObjectIdentifier T = new DERObjectIdentifier("2.5.4.12");
31 * common name - StringType(SIZE(1..64))
33 public static final DERObjectIdentifier CN = new DERObjectIdentifier("2.5.4.3");
36 * device serial number name - StringType(SIZE(1..64))
38 public static final DERObjectIdentifier SN = new DERObjectIdentifier("2.5.4.5");
41 * locality name - StringType(SIZE(1..64))
43 public static final DERObjectIdentifier L = new DERObjectIdentifier("2.5.4.7");
46 * state, or province name - StringType(SIZE(1..64))
48 public static final DERObjectIdentifier ST = new DERObjectIdentifier("2.5.4.8");
52 * email address (RSA PKCS#9 extension) - IA5String
54 * note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
56 public static final DERObjectIdentifier EmailAddress = new DERObjectIdentifier("1.2.840.113549.1.9.1");
59 * email address in Verisign certificates
61 public static final DERObjectIdentifier E = EmailAddress;
66 public static final DERObjectIdentifier DC = new DERObjectIdentifier("0.9.2342.19200300.100.1.25");
71 public static final DERObjectIdentifier UID = new DERObjectIdentifier("0.9.2342.19200300.100.1.1");
74 * look up table translating OID values into their common symbols.
76 public static Hashtable OIDLookUp = new Hashtable();
79 * look up table translating common symbols into their OIDS.
81 public static Hashtable SymbolLookUp = new Hashtable();
85 OIDLookUp.put(C, "C");
86 OIDLookUp.put(O, "O");
87 OIDLookUp.put(T, "T");
88 OIDLookUp.put(OU, "OU");
89 OIDLookUp.put(CN, "CN");
90 OIDLookUp.put(L, "L");
91 OIDLookUp.put(ST, "ST");
92 OIDLookUp.put(SN, "SN");
93 OIDLookUp.put(EmailAddress, "E");
94 OIDLookUp.put(DC, "DC");
95 OIDLookUp.put(UID, "UID");
97 SymbolLookUp.put("c", C);
98 SymbolLookUp.put("o", O);
99 SymbolLookUp.put("t", T);
100 SymbolLookUp.put("ou", OU);
101 SymbolLookUp.put("cn", CN);
102 SymbolLookUp.put("l", L);
103 SymbolLookUp.put("st", ST);
104 SymbolLookUp.put("sn", SN);
105 SymbolLookUp.put("emailaddress", E);
106 SymbolLookUp.put("dc", DC);
107 SymbolLookUp.put("e", E);
108 SymbolLookUp.put("uid", UID);
111 private Vector ordering = new Vector();
112 private Vector values = new Vector();
113 private ASN1Sequence seq;
115 public static X509Name getInstance(
116 ASN1TaggedObject obj,
119 return getInstance(ASN1Sequence.getInstance(obj, explicit));
122 public static X509Name getInstance(
125 if (obj == null || obj instanceof X509Name)
127 return (X509Name)obj;
129 else if (obj instanceof ASN1Sequence)
131 return new X509Name((ASN1Sequence)obj);
134 throw new IllegalArgumentException("unknown object in factory");
138 * Constructor from ASN1Sequence
140 * the principal will be a list of constructed sets, each containing an (OID, String) pair.
147 Enumeration e = seq.getObjects();
149 while (e.hasMoreElements())
151 ASN1Set set = (ASN1Set)e.nextElement();
152 ASN1Sequence s = (ASN1Sequence)set.getObjectAt(0);
154 ordering.addElement(s.getObjectAt(0));
155 values.addElement(((DERString)s.getObjectAt(1)).getString());
160 * constructor from a table of attributes.
162 * it's is assumed the table contains OID/String pairs, and the contents
163 * of the table are copied into an internal table as part of the
164 * construction process.
166 * <b>Note:</b> if the name you are trying to generate should be
167 * following a specific ordering, you should use the constructor
168 * with the ordering specified below.
171 Hashtable attributes)
173 this(null, attributes);
177 * constructor from a table of attributes with ordering.
179 * it's is assumed the table contains OID/String pairs, and the contents
180 * of the table are copied into an internal table as part of the
181 * construction process. The ordering vector should contain the OIDs
182 * in the order they are meant to be encoded or printed in toString.
186 Hashtable attributes)
188 if (ordering != null)
190 for (int i = 0; i != ordering.size(); i++)
192 this.ordering.addElement(ordering.elementAt(i));
197 Enumeration e = attributes.keys();
199 while (e.hasMoreElements())
201 this.ordering.addElement(e.nextElement());
205 for (int i = 0; i != this.ordering.size(); i++)
207 DERObjectIdentifier oid = (DERObjectIdentifier)this.ordering.elementAt(i);
209 if (OIDLookUp.get(oid) == null)
211 throw new IllegalArgumentException("Unknown object id - " + oid.getId() + " - passed to distinguished name");
214 if (attributes.get(oid) == null)
216 throw new IllegalArgumentException("No attribute for object id - " + oid.getId() + " - passed to distinguished name");
219 this.values.addElement(attributes.get(oid)); // copy the hash table
224 * takes two vectors one of the oids and the other of the values.
230 if (ordering.size() != values.size())
232 throw new IllegalArgumentException("ordering vector must be same length as values.");
235 for (int i = 0; i < ordering.size(); i++)
237 this.ordering.addElement(ordering.elementAt(i));
238 this.values.addElement(values.elementAt(i));
243 * takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
244 * some such, converting it into an ordered set of name attributes.
249 X509NameTokenizer nTok = new X509NameTokenizer(dirName);
251 while (nTok.hasMoreTokens())
253 String token = nTok.nextToken();
254 int index = token.indexOf('=');
258 throw new IllegalArgumentException("badly formated directory string");
261 String name = token.substring(0, index);
262 String value = token.substring(index + 1);
263 DERObjectIdentifier oid = null;
265 if (name.toUpperCase().startsWith("OID."))
267 oid = new DERObjectIdentifier(name.substring(4));
269 else if (name.charAt(0) >= '0' && name.charAt(0) <= '9')
271 oid = new DERObjectIdentifier(name);
275 oid = (DERObjectIdentifier)SymbolLookUp.get(name.toLowerCase());
278 throw new IllegalArgumentException("Unknown object id - " + name + " - passed to distinguished name");
282 this.ordering.addElement(oid);
283 this.values.addElement(value);
288 * return false if we have characters out of the range of a printable
289 * string, true otherwise.
291 private boolean canBePrintable(
294 for (int i = str.length() - 1; i >= 0; i--)
296 if (str.charAt(i) > 0x007f)
305 public DERObject getDERObject()
309 DEREncodableVector vec = new DEREncodableVector();
311 for (int i = 0; i != ordering.size(); i++)
313 DEREncodableVector v = new DEREncodableVector();
314 DERObjectIdentifier oid = (DERObjectIdentifier)ordering.elementAt(i);
318 String str = (String)values.elementAt(i);
320 if (oid.equals(EmailAddress))
322 v.add(new DERIA5String(str));
326 if (canBePrintable(str))
328 v.add(new DERPrintableString(str));
332 v.add(new DERUTF8String(str));
336 vec.add(new DERSet(new DERSequence(v)));
339 seq = new DERSequence(vec);
346 * test for equality - note: case is ignored.
348 public boolean equals(Object _obj)
355 if (_obj == null || !(_obj instanceof X509Name))
360 X509Name _oxn = (X509Name)_obj;
361 int _orderingSize = ordering.size();
363 if (_orderingSize != _oxn.ordering.size())
368 boolean[] _indexes = new boolean[_orderingSize];
370 for(int i = 0; i < _orderingSize; i++)
372 boolean _found = false;
373 String _oid = ((DERObjectIdentifier)ordering.elementAt(i)).getId();
374 String _val = (String)values.elementAt(i);
376 for(int j = 0; j < _orderingSize; j++)
378 if(_indexes[j] == true)
383 String _oOID = ((DERObjectIdentifier)_oxn.ordering.elementAt(j)).getId();
384 String _oVal = (String)_oxn.values.elementAt(j);
386 // was equalsIgnoreCase but MIDP doesn't like that.
387 if(_oid.equals(_oOID) && _val.toLowerCase().equals(_oVal.toLowerCase()))
405 public int hashCode()
407 ASN1Sequence seq = (ASN1Sequence)this.getDERObject();
408 Enumeration e = seq.getObjects();
411 while (e.hasMoreElements())
413 hashCode ^= e.nextElement().hashCode();
419 public String toString()
421 StringBuffer buf = new StringBuffer();
422 boolean first = true;
423 Enumeration e1 = ordering.elements();
424 Enumeration e2 = values.elements();
426 while (e1.hasMoreElements())
428 Object oid = e1.nextElement();
429 String sym = (String)OIDLookUp.get(oid);
446 buf.append(((DERObjectIdentifier)oid).getId());
451 int index = buf.length();
453 buf.append((String)e2.nextElement());
455 int end = buf.length();
459 if ((buf.charAt(index) == ',')
460 || (buf.charAt(index) == '"')
461 || (buf.charAt(index) == '\\')
462 || (buf.charAt(index) == '+')
463 || (buf.charAt(index) == '<')
464 || (buf.charAt(index) == '>')
465 || (buf.charAt(index) == ';'))
467 buf.insert(index, "\\");
476 return buf.toString();