16e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrompackage org.bouncycastle.asn1.x500.style;
26e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
36e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.io.IOException;
4a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstromimport java.util.Enumeration;
56e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.util.Hashtable;
66e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.util.Vector;
76e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
86e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.asn1.ASN1Encodable;
94c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Encoding;
106e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.asn1.ASN1ObjectIdentifier;
114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Primitive;
126e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.asn1.ASN1String;
136e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.asn1.DERUniversalString;
146e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.asn1.x500.AttributeTypeAndValue;
156e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.asn1.x500.RDN;
166e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.asn1.x500.X500NameBuilder;
176e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.asn1.x500.X500NameStyle;
186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.util.Strings;
196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.util.encoders.Hex;
206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
216e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrompublic class IETFUtils
226e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom{
23a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private static String unescape(String elt)
24a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    {
25a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        if (elt.length() == 0 || (elt.indexOf('\\') < 0 && elt.indexOf('"') < 0))
26a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        {
27a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            return elt.trim();
28a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        }
29a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
30a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        char[] elts = elt.toCharArray();
31a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        boolean escaped = false;
32a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        boolean quoted = false;
33a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        StringBuffer buf = new StringBuffer(elt.length());
34a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        int start = 0;
35a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
36a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        // if it's an escaped hash string and not an actual encoding in string form
37a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        // we need to leave it escaped.
38a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        if (elts[0] == '\\')
39a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        {
40a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            if (elts[1] == '#')
41a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            {
42a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                start = 2;
43a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                buf.append("\\#");
44a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            }
45a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        }
46a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
47a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        boolean nonWhiteSpaceEncountered = false;
48a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        int     lastEscaped = 0;
49a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        char    hex1 = 0;
50a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
51a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        for (int i = start; i != elts.length; i++)
52a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        {
53a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            char c = elts[i];
54a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
55a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            if (c != ' ')
56a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            {
57a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                nonWhiteSpaceEncountered = true;
58a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            }
59a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
60a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            if (c == '"')
61a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            {
62a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                if (!escaped)
63a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                {
64a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    quoted = !quoted;
65a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                }
66a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                else
67a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                {
68a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    buf.append(c);
69a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                }
70a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                escaped = false;
71a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            }
72a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            else if (c == '\\' && !(escaped || quoted))
73a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            {
74a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                escaped = true;
75a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                lastEscaped = buf.length();
76a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            }
77a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            else
78a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            {
79a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                if (c == ' ' && !escaped && !nonWhiteSpaceEncountered)
80a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                {
81a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    continue;
82a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                }
83a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                if (escaped && isHexDigit(c))
84a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                {
85a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    if (hex1 != 0)
86a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    {
87a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                        buf.append((char)(convertHex(hex1) * 16 + convertHex(c)));
88a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                        escaped = false;
89a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                        hex1 = 0;
90a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                        continue;
91a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    }
92a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    hex1 = c;
93a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    continue;
94a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                }
95a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                buf.append(c);
96a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                escaped = false;
97a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            }
98a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        }
99a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
100a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        if (buf.length() > 0)
101a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        {
102a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            while (buf.charAt(buf.length() - 1) == ' ' && lastEscaped != (buf.length() - 1))
103a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            {
104a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                buf.setLength(buf.length() - 1);
105a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            }
106a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        }
107a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
108a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        return buf.toString();
109a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    }
110a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
111a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private static boolean isHexDigit(char c)
112a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    {
113a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F');
114a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    }
115a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
116a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private static int convertHex(char c)
117a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    {
118a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        if ('0' <= c && c <= '9')
119a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        {
120a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            return c - '0';
121a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        }
122a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        if ('a' <= c && c <= 'f')
123a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        {
124a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            return c - 'a' + 10;
125a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        }
126a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        return c - 'A' + 10;
127a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    }
128a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
1296e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    public static RDN[] rDNsFromString(String name, X500NameStyle x500Style)
1306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
1316e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        X500NameTokenizer nTok = new X500NameTokenizer(name);
1326e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        X500NameBuilder builder = new X500NameBuilder(x500Style);
1336e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1346e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        while (nTok.hasMoreTokens())
1356e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
1366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            String  token = nTok.nextToken();
1376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
138a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            if (token.indexOf('+') > 0)
1396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
140a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                X500NameTokenizer   pTok = new X500NameTokenizer(token, '+');
141a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                X500NameTokenizer   vTok = new X500NameTokenizer(pTok.nextToken(), '=');
1426e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
143a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                String              attr = vTok.nextToken();
1446e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
145a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                if (!vTok.hasMoreTokens())
146a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                {
147a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    throw new IllegalArgumentException("badly formatted directory string");
148a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                }
1496e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
150a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                String               value = vTok.nextToken();
151a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                ASN1ObjectIdentifier oid = x500Style.attrNameToOID(attr.trim());
1526e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
153a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                if (pTok.hasMoreTokens())
1546e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                {
155a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    Vector oids = new Vector();
156a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    Vector values = new Vector();
1576e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
158a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    oids.addElement(oid);
159a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    values.addElement(unescape(value));
1606e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
161a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    while (pTok.hasMoreTokens())
162a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    {
163a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                        vTok = new X500NameTokenizer(pTok.nextToken(), '=');
164a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
165a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                        attr = vTok.nextToken();
166a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
167a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                        if (!vTok.hasMoreTokens())
168a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                        {
169a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                            throw new IllegalArgumentException("badly formatted directory string");
170a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                        }
171a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
172a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                        value = vTok.nextToken();
173a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                        oid = x500Style.attrNameToOID(attr.trim());
1746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
175a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
176a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                        oids.addElement(oid);
177a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                        values.addElement(unescape(value));
178a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    }
179a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
180a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    builder.addMultiValuedRDN(toOIDArray(oids), toValueArray(values));
181a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                }
182a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                else
183a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                {
184a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    builder.addRDN(oid, unescape(value));
185a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                }
1866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
1876e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            else
1886e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
189a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                X500NameTokenizer   vTok = new X500NameTokenizer(token, '=');
190a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
191a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                String              attr = vTok.nextToken();
192a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
193a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                if (!vTok.hasMoreTokens())
194a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                {
195a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    throw new IllegalArgumentException("badly formatted directory string");
196a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                }
197a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
198a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                String               value = vTok.nextToken();
199a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                ASN1ObjectIdentifier oid = x500Style.attrNameToOID(attr.trim());
200a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
201a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                builder.addRDN(oid, unescape(value));
2026e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
2036e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
2046e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2056e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return builder.build().getRDNs();
2066e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
2076e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2086e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    private static String[] toValueArray(Vector values)
2096e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
2106e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        String[] tmp = new String[values.size()];
2116e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2126e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        for (int i = 0; i != tmp.length; i++)
2136e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
2146e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            tmp[i] = (String)values.elementAt(i);
2156e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
2166e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2176e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return tmp;
2186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
2196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    private static ASN1ObjectIdentifier[] toOIDArray(Vector oids)
2216e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
2226e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        ASN1ObjectIdentifier[] tmp = new ASN1ObjectIdentifier[oids.size()];
2236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        for (int i = 0; i != tmp.length; i++)
2256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
2266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            tmp[i] = (ASN1ObjectIdentifier)oids.elementAt(i);
2276e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
2286e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2296e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return tmp;
2306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
2316e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
232a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    public static String[] findAttrNamesForOID(
233a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        ASN1ObjectIdentifier oid,
234a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        Hashtable            lookup)
235a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    {
236a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        int count = 0;
237a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        for (Enumeration en = lookup.elements(); en.hasMoreElements();)
238a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        {
239a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            if (oid.equals(en.nextElement()))
240a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            {
241a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                count++;
242a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            }
243a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        }
244a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
245a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        String[] aliases = new String[count];
246a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        count = 0;
247a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
248a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        for (Enumeration en = lookup.keys(); en.hasMoreElements();)
249a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        {
250a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            String key = (String)en.nextElement();
251a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            if (oid.equals(lookup.get(key)))
252a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            {
253a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                aliases[count++] = key;
254a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            }
255a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        }
256a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
257a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        return aliases;
258a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    }
259a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
2606e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    public static ASN1ObjectIdentifier decodeAttrName(
2616e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        String      name,
2626e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        Hashtable   lookUp)
2636e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
2646e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (Strings.toUpperCase(name).startsWith("OID."))
2656e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
2666e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            return new ASN1ObjectIdentifier(name.substring(4));
2676e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
2686e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else if (name.charAt(0) >= '0' && name.charAt(0) <= '9')
2696e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
2706e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            return new ASN1ObjectIdentifier(name);
2716e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
2726e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2736e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)lookUp.get(Strings.toLowerCase(name));
2746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (oid == null)
2756e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
2766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            throw new IllegalArgumentException("Unknown object id - " + name + " - passed to distinguished name");
2776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
2786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return oid;
2806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
2816e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    public static ASN1Encodable valueFromHexString(
2836e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        String  str,
2846e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        int     off)
2856e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        throws IOException
2866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
2876e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        byte[] data = new byte[(str.length() - off) / 2];
2886e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        for (int index = 0; index != data.length; index++)
2896e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
2906e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            char left = str.charAt((index * 2) + off);
2916e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            char right = str.charAt((index * 2) + off + 1);
2926e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
293a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            data[index] = (byte)((convertHex(left) << 4) | convertHex(right));
2946e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
2956e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return ASN1Primitive.fromByteArray(data);
2976e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
2986e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
299e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom    public static void appendRDN(
300e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        StringBuffer          buf,
301e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        RDN                   rdn,
302e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        Hashtable             oidSymbols)
303e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom    {
304e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        if (rdn.isMultiValued())
305e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
306e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            AttributeTypeAndValue[] atv = rdn.getTypesAndValues();
307e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            boolean firstAtv = true;
308e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
309e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            for (int j = 0; j != atv.length; j++)
310e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            {
311e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                if (firstAtv)
312e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                {
313e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                    firstAtv = false;
314e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                }
315e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                else
316e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                {
317e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                    buf.append('+');
318e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                }
319e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
320e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                IETFUtils.appendTypeAndValue(buf, atv[j], oidSymbols);
321e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            }
322e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        }
323e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        else
324e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
325e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            IETFUtils.appendTypeAndValue(buf, rdn.getFirst(), oidSymbols);
326e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        }
327e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom    }
328e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
3296e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    public static void appendTypeAndValue(
3306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        StringBuffer          buf,
3316e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        AttributeTypeAndValue typeAndValue,
3326e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        Hashtable             oidSymbols)
3336e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
3346e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        String  sym = (String)oidSymbols.get(typeAndValue.getType());
3356e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
3366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (sym != null)
3376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
3386e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            buf.append(sym);
3396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
3406e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else
3416e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
3426e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            buf.append(typeAndValue.getType().getId());
3436e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
3446e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
3456e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        buf.append('=');
3466e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
3476e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        buf.append(valueToString(typeAndValue.getValue()));
3486e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
3496e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
3506e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    public static String valueToString(ASN1Encodable value)
3516e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
3526e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        StringBuffer vBuf = new StringBuffer();
3536e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
3546e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (value instanceof ASN1String && !(value instanceof DERUniversalString))
3556e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
3566e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            String v = ((ASN1String)value).getString();
3576e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            if (v.length() > 0 && v.charAt(0) == '#')
3586e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
3596e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                vBuf.append("\\" + v);
3606e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
3616e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            else
3626e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
3636e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                vBuf.append(v);
3646e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
3656e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
3666e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else
3676e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
3684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            try
3694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
3704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                vBuf.append("#" + bytesToString(Hex.encode(value.toASN1Primitive().getEncoded(ASN1Encoding.DER))));
3714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
3724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            catch (IOException e)
3734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
3744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new IllegalArgumentException("Other value has no encoded form");
3754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
3766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
3776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
3786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        int     end = vBuf.length();
3796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        int     index = 0;
3806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
3816e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (vBuf.length() >= 2 && vBuf.charAt(0) == '\\' && vBuf.charAt(1) == '#')
3826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
3836e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            index += 2;
3846e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
3856e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
3866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        while (index != end)
3876e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
3886e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            if ((vBuf.charAt(index) == ',')
3896e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom               || (vBuf.charAt(index) == '"')
3906e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom               || (vBuf.charAt(index) == '\\')
3916e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom               || (vBuf.charAt(index) == '+')
3926e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom               || (vBuf.charAt(index) == '=')
3936e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom               || (vBuf.charAt(index) == '<')
3946e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom               || (vBuf.charAt(index) == '>')
3956e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom               || (vBuf.charAt(index) == ';'))
3966e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
3976e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                vBuf.insert(index, "\\");
3986e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                index++;
3996e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                end++;
4006e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
4016e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
4026e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            index++;
4036e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
4046e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
405a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        int start = 0;
406a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        if (vBuf.length() > 0)
407a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        {
4085db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            while (vBuf.length() > start && vBuf.charAt(start) == ' ')
409a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            {
410a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                vBuf.insert(start, "\\");
411a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                start += 2;
412a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            }
413a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        }
414a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
415a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        int endBuf = vBuf.length() - 1;
416a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
417a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        while (endBuf >= 0 && vBuf.charAt(endBuf) == ' ')
418a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        {
419a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            vBuf.insert(endBuf, '\\');
420a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            endBuf--;
421a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        }
422a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
4236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return vBuf.toString();
4246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
4256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
4266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    private static String bytesToString(
4276e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        byte[] data)
4286e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
4296e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        char[]  cs = new char[data.length];
4306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
4316e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        for (int i = 0; i != cs.length; i++)
4326e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
4336e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            cs[i] = (char)(data[i] & 0xff);
4346e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
4356e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
4366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return new String(cs);
4376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
4386e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
4396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    public static String canonicalize(String s)
4406e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
4416e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        String value = Strings.toLowerCase(s.trim());
4426e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
4436e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (value.length() > 0 && value.charAt(0) == '#')
4446e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
4454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ASN1Primitive obj = decodeObject(value);
4466e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
4476e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            if (obj instanceof ASN1String)
4486e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
4496e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                value = Strings.toLowerCase(((ASN1String)obj).getString().trim());
4506e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
4516e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
4526e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
4536e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        value = stripInternalSpaces(value);
4546e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
4556e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return value;
4566e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
4576e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
4584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private static ASN1Primitive decodeObject(String oValue)
4596e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
4606e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        try
4616e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
4624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return ASN1Primitive.fromByteArray(Hex.decode(oValue.substring(1)));
4636e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
4646e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        catch (IOException e)
4656e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
4666e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            throw new IllegalStateException("unknown encoding in name: " + e);
4676e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
4686e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
4696e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
4706e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    public static String stripInternalSpaces(
4716e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        String str)
4726e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
4736e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        StringBuffer res = new StringBuffer();
4746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
4756e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (str.length() != 0)
4766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
4776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            char c1 = str.charAt(0);
4786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
4796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            res.append(c1);
4806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
4816e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            for (int k = 1; k < str.length(); k++)
4826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
4836e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                char c2 = str.charAt(k);
4846e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                if (!(c1 == ' ' && c2 == ' '))
4856e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                {
4866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    res.append(c2);
4876e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                }
4886e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                c1 = c2;
4896e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
4906e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
4916e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
4926e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return res.toString();
4936e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
494e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
495e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom    public static boolean rDNAreEqual(RDN rdn1, RDN rdn2)
496e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom    {
497e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        if (rdn1.isMultiValued())
498e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
499e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            if (rdn2.isMultiValued())
500e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            {
501e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                AttributeTypeAndValue[] atvs1 = rdn1.getTypesAndValues();
502e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                AttributeTypeAndValue[] atvs2 = rdn2.getTypesAndValues();
503e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
504e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                if (atvs1.length != atvs2.length)
505e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                {
506e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                    return false;
507e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                }
508e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
509e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                for (int i = 0; i != atvs1.length; i++)
510e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                {
511e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                    if (!atvAreEqual(atvs1[i], atvs2[i]))
512e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                    {
513e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                        return false;
514e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                    }
515e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                }
516e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            }
517e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            else
518e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            {
519e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                return false;
520e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            }
521e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        }
522e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        else
523e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
524e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            if (!rdn2.isMultiValued())
525e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            {
526e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                return atvAreEqual(rdn1.getFirst(), rdn2.getFirst());
527e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            }
528e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            else
529e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            {
530e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom                return false;
531e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            }
532e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        }
533e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
534e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        return true;
535e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom    }
536e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
537e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom    private static boolean atvAreEqual(AttributeTypeAndValue atv1, AttributeTypeAndValue atv2)
538e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom    {
539e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        if (atv1 == atv2)
540e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
541e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            return true;
542e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        }
543e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
544e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        if (atv1 == null)
545e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
546e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            return false;
547e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        }
548e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
549e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        if (atv2 == null)
550e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
551e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            return false;
552e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        }
553e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
554e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        ASN1ObjectIdentifier o1 = atv1.getType();
555e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        ASN1ObjectIdentifier o2 = atv2.getType();
556e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
557e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        if (!o1.equals(o2))
558e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
559e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            return false;
560e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        }
561e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
562e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        String v1 = IETFUtils.canonicalize(IETFUtils.valueToString(atv1.getValue()));
563e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        String v2 = IETFUtils.canonicalize(IETFUtils.valueToString(atv2.getValue()));
564e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
565e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        if (!v1.equals(v2))
566e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
567e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            return false;
568e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        }
569e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom
570e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        return true;
571e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom    }
5726e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom}
573