2002/03/21 01:19:32
[org.ibex.core.git] / src / org / bouncycastle / asn1 / x509 / X509Name.java
diff --git a/src/org/bouncycastle/asn1/x509/X509Name.java b/src/org/bouncycastle/asn1/x509/X509Name.java
new file mode 100644 (file)
index 0000000..2f2a60f
--- /dev/null
@@ -0,0 +1,336 @@
+package org.bouncycastle.asn1.x509;
+
+import java.io.*;
+import java.util.*;
+
+import org.bouncycastle.asn1.*;
+
+public class X509Name
+    implements DEREncodable
+{
+    /**
+     * country code - StringType(SIZE(2))
+     */
+    public static final DERObjectIdentifier C = new DERObjectIdentifier("2.5.4.6");
+
+    /**
+     * organization - StringType(SIZE(1..64))
+     */
+    public static final DERObjectIdentifier O = new DERObjectIdentifier("2.5.4.10");
+
+    /**
+     * organizational unit name - StringType(SIZE(1..64))
+     */
+    public static final DERObjectIdentifier OU = new DERObjectIdentifier("2.5.4.11");
+
+    /**
+     * common name - StringType(SIZE(1..64))
+     */
+    public static final DERObjectIdentifier CN = new DERObjectIdentifier("2.5.4.3");
+
+    /**
+     * device serial number name - StringType(SIZE(1..64))
+     */
+    public static final DERObjectIdentifier SN = new DERObjectIdentifier("2.5.4.5");
+
+    /**
+     * locality name - StringType(SIZE(1..64))
+     */
+    public static final DERObjectIdentifier L = new DERObjectIdentifier("2.5.4.7");
+
+    /**
+     * state, or province name - StringType(SIZE(1..64))
+     */
+    public static final DERObjectIdentifier ST = new DERObjectIdentifier("2.5.4.8");
+
+    /**
+     * email address (RSA PKCS#9 extension) - IA5String
+     * <p>
+     * note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
+     */
+    public static final DERObjectIdentifier EmailAddress = new DERObjectIdentifier("1.2.840.113549.1.9.1");
+
+    /**
+     * look up table translating OID values into their common symbols.
+     */
+    public static Hashtable OIDLookUp = new Hashtable();
+
+    /**
+     * look up table translating common symbols into their OIDS.
+     */
+    public static Hashtable SymbolLookUp = new Hashtable();
+
+    static
+    {
+        OIDLookUp.put(C, "C");
+        OIDLookUp.put(O, "O");
+        OIDLookUp.put(OU, "OU");
+        OIDLookUp.put(CN, "CN");
+        OIDLookUp.put(L, "L");
+        OIDLookUp.put(ST, "ST");
+        OIDLookUp.put(SN, "SN");
+        OIDLookUp.put(EmailAddress, "EmailAddress");
+
+        SymbolLookUp.put("C", C);
+        SymbolLookUp.put("O", O);
+        SymbolLookUp.put("OU", OU);
+        SymbolLookUp.put("CN", CN);
+        SymbolLookUp.put("L", L);
+        SymbolLookUp.put("ST", ST);
+        SymbolLookUp.put("SN", SN);
+        SymbolLookUp.put("EmailAddress", EmailAddress);
+    }
+
+    private Vector                  ordering = new Vector();
+    private Hashtable               attributes = new Hashtable();
+    private DERConstructedSequence  seq = null;
+
+    /**
+     * Constructor from DERConstructedSequence.
+     *
+     * the principal will be a list of constructed sets, each containing an (OID, String) pair.
+     */
+    public X509Name(
+        DERConstructedSequence  seq)
+    {
+        this.seq = seq; 
+
+        Enumeration e = seq.getObjects();
+
+        while (e.hasMoreElements())
+        {
+            DERSet  set = (DERSet)e.nextElement();
+            DERConstructedSequence  s = (DERConstructedSequence)set.getSequence();
+
+            ordering.addElement(s.getObjectAt(0));
+            attributes.put(s.getObjectAt(0), ((DERString)s.getObjectAt(1)).getString());
+        }
+    }
+
+    /**
+     * constructor from a table of attributes.
+     * <p>
+     * it's is assumed the table contains OID/String pairs, and the contents
+     * of the table are copied into an internal table as part of the 
+     * construction process.
+     * <p>
+     * <b>Note:</b> if the name you are trying to generate should be
+     * following a specific ordering, you should use the constructor
+     * with the ordering specified below.
+     */
+    public X509Name(
+        Hashtable  attributes)
+    {
+        this(null, attributes);
+    }
+
+    /**
+     * constructor from a table of attributes with ordering.
+     * <p>
+     * it's is assumed the table contains OID/String pairs, and the contents
+     * of the table are copied into an internal table as part of the 
+     * construction process. The ordering vector should contain the OIDs
+     * in the order they are meant to be encoded or printed in toString.
+     */
+    public X509Name(
+        Vector      ordering,
+        Hashtable   attributes)
+    {
+        if (ordering != null)
+        {
+            for (int i = 0; i != ordering.size(); i++)
+            {
+                this.ordering.addElement(ordering.elementAt(i));
+            }
+        }
+        else
+        {
+            Enumeration     e = attributes.keys();
+
+            while (e.hasMoreElements())
+            {
+                this.ordering.addElement(e.nextElement());
+            }
+        }
+
+        for (int i = 0; i != this.ordering.size(); i++)
+        {
+            DERObjectIdentifier     oid = (DERObjectIdentifier)this.ordering.elementAt(i);
+
+            if (OIDLookUp.get(oid) == null)
+            {
+                throw new IllegalArgumentException("Unknown object id - " + oid.getId() + " - passed to distinguished name");
+            }
+
+            if (attributes.get(oid) == null)
+            {
+                throw new IllegalArgumentException("No attribute for object id - " + oid.getId() + " - passed to distinguished name");
+            }
+
+            this.attributes.put(oid, attributes.get(oid)); // copy the hash table
+        }
+    }
+
+    /**
+     * takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+     * some such, converting it into an ordered set of name attributes.
+     */
+    public X509Name(
+        String  dirName)
+    {
+        X509NameTokenizer   nTok = new X509NameTokenizer(dirName);
+
+        while (nTok.hasMoreTokens())
+        {
+            String  token = nTok.nextToken();
+            int     index = token.indexOf('=');
+
+            if (index == -1)
+            {
+                throw new IllegalArgumentException("badly formated directory string");
+            }
+
+            String  name = token.substring(0, index);
+            String  value = token.substring(index + 1);
+
+            DERObjectIdentifier oid = (DERObjectIdentifier)SymbolLookUp.get(name);
+            if (oid == null)
+            {
+                throw new IllegalArgumentException("Unknown object id - " + oid.getId() + " - passed to distinguished name");
+            }
+
+            this.ordering.addElement(oid);
+            this.attributes.put(oid, value);
+        }
+    }
+
+    public DERObject getDERObject()
+    {
+        if (seq == null)
+        {
+            seq = new DERConstructedSequence();
+
+            for (int i = 0; i != ordering.size(); i++)
+            {
+                DERConstructedSequence  s = new DERConstructedSequence();
+                DERObjectIdentifier     oid = (DERObjectIdentifier)ordering.elementAt(i);
+
+                s.addObject(oid);
+                if (oid.equals(EmailAddress))
+                {
+                    s.addObject(new DERIA5String((String)attributes.get(oid)));
+                }
+                else
+                {
+                    s.addObject(new DERPrintableString((String)attributes.get(oid)));
+                }
+
+                seq.addObject(new DERSet(s));
+            }
+        }
+
+        return seq;
+    }
+
+    public int hashCode()
+    {
+        Enumeration     e = attributes.keys();
+        int             hashCode = 0;
+
+        while (e.hasMoreElements())
+        {
+            Object  o = e.nextElement();
+
+            hashCode ^= o.hashCode();
+            hashCode ^= attributes.get(o).hashCode();
+        }
+
+        for (int i = 0; i != ordering.size(); i++)
+        {
+            hashCode ^= ordering.elementAt(i).hashCode();
+        }
+
+        return hashCode;
+    }
+
+    public boolean equals(
+        Object o)
+    {
+        if (o == null || !(o instanceof X509Name))
+        {
+            return false;
+        }
+
+        X509Name        other = (X509Name)o;
+
+        if (ordering.size() != other.ordering.size())
+        {
+            return false;
+        }
+
+        for (int i = 0; i != ordering.size(); i++)
+        {
+            if (!ordering.elementAt(i).equals(other.ordering.elementAt(i)))
+            {
+                return false;
+            }
+        }
+
+        Enumeration     e1 = attributes.keys();
+        Enumeration     e2 = other.attributes.keys();
+
+        while (e1.hasMoreElements() && e2.hasMoreElements())
+        {
+            Object  o1 = e1.nextElement();
+            Object  o2 = e2.nextElement();
+            
+            if (!o1.equals(o2))
+            {
+                return false;
+            }
+        }
+
+        if (e1.hasMoreElements() || e2.hasMoreElements())
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    public String toString()
+    {
+        StringBuffer    buf = new StringBuffer();
+        boolean         first = true;
+
+        for (int i = 0; i != ordering.size(); i++)
+        {
+            Object  oid = ordering.elementAt(i);
+            String  sym = (String)OIDLookUp.get(oid);
+            
+            if (first)
+            {
+                first = false;
+            }
+            else
+            {
+                buf.append(", ");
+            }
+
+            if (sym != null)
+            {
+                buf.append(sym);
+                buf.append("=");
+                buf.append((String)attributes.get(oid));
+            }
+            else
+            {
+                buf.append(((DERObjectIdentifier)oid).getId());
+                buf.append("=");
+                buf.append((String)attributes.get(oid));
+            }
+        }
+
+        return buf.toString();
+    }
+}