package org.bouncycastle.asn1.x500.style; import java.io.IOException; import java.util.Hashtable; import java.util.Vector; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Object; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1String; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERUniversalString; import org.bouncycastle.asn1.x500.AttributeTypeAndValue; import org.bouncycastle.asn1.x500.RDN; import org.bouncycastle.asn1.x500.X500NameBuilder; import org.bouncycastle.asn1.x500.X500NameStyle; import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; public class IETFUtils { public static RDN[] rDNsFromString(String name, X500NameStyle x500Style) { X500NameTokenizer nTok = new X500NameTokenizer(name); X500NameBuilder builder = new X500NameBuilder(x500Style); while (nTok.hasMoreTokens()) { String token = nTok.nextToken(); int index = token.indexOf('='); if (index == -1) { throw new IllegalArgumentException("badly formated directory string"); } String attr = token.substring(0, index); String value = token.substring(index + 1); ASN1ObjectIdentifier oid = x500Style.attrNameToOID(attr); if (value.indexOf('+') > 0) { X500NameTokenizer vTok = new X500NameTokenizer(value, '+'); String v = vTok.nextToken(); Vector oids = new Vector(); Vector values = new Vector(); oids.addElement(oid); values.addElement(v); while (vTok.hasMoreTokens()) { String sv = vTok.nextToken(); int ndx = sv.indexOf('='); String nm = sv.substring(0, ndx); String vl = sv.substring(ndx + 1); oids.addElement(x500Style.attrNameToOID(nm)); values.addElement(vl); } builder.addMultiValuedRDN(toOIDArray(oids), toValueArray(values)); } else { builder.addRDN(oid, value); } } return builder.build().getRDNs(); } private static String[] toValueArray(Vector values) { String[] tmp = new String[values.size()]; for (int i = 0; i != tmp.length; i++) { tmp[i] = (String)values.elementAt(i); } return tmp; } private static ASN1ObjectIdentifier[] toOIDArray(Vector oids) { ASN1ObjectIdentifier[] tmp = new ASN1ObjectIdentifier[oids.size()]; for (int i = 0; i != tmp.length; i++) { tmp[i] = (ASN1ObjectIdentifier)oids.elementAt(i); } return tmp; } public static ASN1ObjectIdentifier decodeAttrName( String name, Hashtable lookUp) { if (Strings.toUpperCase(name).startsWith("OID.")) { return new ASN1ObjectIdentifier(name.substring(4)); } else if (name.charAt(0) >= '0' && name.charAt(0) <= '9') { return new ASN1ObjectIdentifier(name); } ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)lookUp.get(Strings.toLowerCase(name)); if (oid == null) { throw new IllegalArgumentException("Unknown object id - " + name + " - passed to distinguished name"); } return oid; } public static ASN1Encodable valueFromHexString( String str, int off) throws IOException { str = Strings.toLowerCase(str); byte[] data = new byte[(str.length() - off) / 2]; for (int index = 0; index != data.length; index++) { char left = str.charAt((index * 2) + off); char right = str.charAt((index * 2) + off + 1); if (left < 'a') { data[index] = (byte)((left - '0') << 4); } else { data[index] = (byte)((left - 'a' + 10) << 4); } if (right < 'a') { data[index] |= (byte)(right - '0'); } else { data[index] |= (byte)(right - 'a' + 10); } } return ASN1Object.fromByteArray(data); } public static void appendTypeAndValue( StringBuffer buf, AttributeTypeAndValue typeAndValue, Hashtable oidSymbols) { String sym = (String)oidSymbols.get(typeAndValue.getType()); if (sym != null) { buf.append(sym); } else { buf.append(typeAndValue.getType().getId()); } buf.append('='); buf.append(valueToString(typeAndValue.getValue())); } public static String valueToString(ASN1Encodable value) { StringBuffer vBuf = new StringBuffer(); if (value instanceof ASN1String && !(value instanceof DERUniversalString)) { String v = ((ASN1String)value).getString(); if (v.length() > 0 && v.charAt(0) == '#') { vBuf.append("\\" + v); } else { vBuf.append(v); } } else { vBuf.append("#" + bytesToString(Hex.encode(value.getDERObject().getDEREncoded()))); } int end = vBuf.length(); int index = 0; if (vBuf.length() >= 2 && vBuf.charAt(0) == '\\' && vBuf.charAt(1) == '#') { index += 2; } while (index != end) { if ((vBuf.charAt(index) == ',') || (vBuf.charAt(index) == '"') || (vBuf.charAt(index) == '\\') || (vBuf.charAt(index) == '+') || (vBuf.charAt(index) == '=') || (vBuf.charAt(index) == '<') || (vBuf.charAt(index) == '>') || (vBuf.charAt(index) == ';')) { vBuf.insert(index, "\\"); index++; end++; } index++; } return vBuf.toString(); } private static String bytesToString( byte[] data) { char[] cs = new char[data.length]; for (int i = 0; i != cs.length; i++) { cs[i] = (char)(data[i] & 0xff); } return new String(cs); } public static String canonicalize(String s) { String value = Strings.toLowerCase(s.trim()); if (value.length() > 0 && value.charAt(0) == '#') { DERObject obj = decodeObject(value); if (obj instanceof ASN1String) { value = Strings.toLowerCase(((ASN1String)obj).getString().trim()); } } value = stripInternalSpaces(value); return value; } private static ASN1Object decodeObject(String oValue) { try { return ASN1Object.fromByteArray(Hex.decode(oValue.substring(1))); } catch (IOException e) { throw new IllegalStateException("unknown encoding in name: " + e); } } public static String stripInternalSpaces( String str) { StringBuffer res = new StringBuffer(); if (str.length() != 0) { char c1 = str.charAt(0); res.append(c1); for (int k = 1; k < str.length(); k++) { char c2 = str.charAt(k); if (!(c1 == ' ' && c2 == ' ')) { res.append(c2); } c1 = c2; } } return res.toString(); } }