IETFUtils.java revision e6bf3e8dfa2804891a82075cb469b736321b4827
1package org.bouncycastle.asn1.x500.style; 2 3import java.io.IOException; 4import java.util.Hashtable; 5import java.util.Vector; 6 7import org.bouncycastle.asn1.ASN1Encodable; 8import org.bouncycastle.asn1.ASN1Encoding; 9import org.bouncycastle.asn1.ASN1ObjectIdentifier; 10import org.bouncycastle.asn1.ASN1Primitive; 11import org.bouncycastle.asn1.ASN1String; 12import org.bouncycastle.asn1.DERUniversalString; 13import org.bouncycastle.asn1.x500.AttributeTypeAndValue; 14import org.bouncycastle.asn1.x500.RDN; 15import org.bouncycastle.asn1.x500.X500NameBuilder; 16import org.bouncycastle.asn1.x500.X500NameStyle; 17import org.bouncycastle.util.Strings; 18import org.bouncycastle.util.encoders.Hex; 19 20public class IETFUtils 21{ 22 public static RDN[] rDNsFromString(String name, X500NameStyle x500Style) 23 { 24 X500NameTokenizer nTok = new X500NameTokenizer(name); 25 X500NameBuilder builder = new X500NameBuilder(x500Style); 26 27 while (nTok.hasMoreTokens()) 28 { 29 String token = nTok.nextToken(); 30 int index = token.indexOf('='); 31 32 if (index == -1) 33 { 34 throw new IllegalArgumentException("badly formated directory string"); 35 } 36 37 String attr = token.substring(0, index); 38 String value = token.substring(index + 1); 39 ASN1ObjectIdentifier oid = x500Style.attrNameToOID(attr); 40 41 if (value.indexOf('+') > 0) 42 { 43 X500NameTokenizer vTok = new X500NameTokenizer(value, '+'); 44 String v = vTok.nextToken(); 45 46 Vector oids = new Vector(); 47 Vector values = new Vector(); 48 49 oids.addElement(oid); 50 values.addElement(v); 51 52 while (vTok.hasMoreTokens()) 53 { 54 String sv = vTok.nextToken(); 55 int ndx = sv.indexOf('='); 56 57 String nm = sv.substring(0, ndx); 58 String vl = sv.substring(ndx + 1); 59 60 oids.addElement(x500Style.attrNameToOID(nm)); 61 values.addElement(vl); 62 } 63 64 builder.addMultiValuedRDN(toOIDArray(oids), toValueArray(values)); 65 } 66 else 67 { 68 builder.addRDN(oid, value); 69 } 70 } 71 72 return builder.build().getRDNs(); 73 } 74 75 private static String[] toValueArray(Vector values) 76 { 77 String[] tmp = new String[values.size()]; 78 79 for (int i = 0; i != tmp.length; i++) 80 { 81 tmp[i] = (String)values.elementAt(i); 82 } 83 84 return tmp; 85 } 86 87 private static ASN1ObjectIdentifier[] toOIDArray(Vector oids) 88 { 89 ASN1ObjectIdentifier[] tmp = new ASN1ObjectIdentifier[oids.size()]; 90 91 for (int i = 0; i != tmp.length; i++) 92 { 93 tmp[i] = (ASN1ObjectIdentifier)oids.elementAt(i); 94 } 95 96 return tmp; 97 } 98 99 public static ASN1ObjectIdentifier decodeAttrName( 100 String name, 101 Hashtable lookUp) 102 { 103 if (Strings.toUpperCase(name).startsWith("OID.")) 104 { 105 return new ASN1ObjectIdentifier(name.substring(4)); 106 } 107 else if (name.charAt(0) >= '0' && name.charAt(0) <= '9') 108 { 109 return new ASN1ObjectIdentifier(name); 110 } 111 112 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)lookUp.get(Strings.toLowerCase(name)); 113 if (oid == null) 114 { 115 throw new IllegalArgumentException("Unknown object id - " + name + " - passed to distinguished name"); 116 } 117 118 return oid; 119 } 120 121 public static ASN1Encodable valueFromHexString( 122 String str, 123 int off) 124 throws IOException 125 { 126 str = Strings.toLowerCase(str); 127 byte[] data = new byte[(str.length() - off) / 2]; 128 for (int index = 0; index != data.length; index++) 129 { 130 char left = str.charAt((index * 2) + off); 131 char right = str.charAt((index * 2) + off + 1); 132 133 if (left < 'a') 134 { 135 data[index] = (byte)((left - '0') << 4); 136 } 137 else 138 { 139 data[index] = (byte)((left - 'a' + 10) << 4); 140 } 141 if (right < 'a') 142 { 143 data[index] |= (byte)(right - '0'); 144 } 145 else 146 { 147 data[index] |= (byte)(right - 'a' + 10); 148 } 149 } 150 151 return ASN1Primitive.fromByteArray(data); 152 } 153 154 public static void appendTypeAndValue( 155 StringBuffer buf, 156 AttributeTypeAndValue typeAndValue, 157 Hashtable oidSymbols) 158 { 159 String sym = (String)oidSymbols.get(typeAndValue.getType()); 160 161 if (sym != null) 162 { 163 buf.append(sym); 164 } 165 else 166 { 167 buf.append(typeAndValue.getType().getId()); 168 } 169 170 buf.append('='); 171 172 buf.append(valueToString(typeAndValue.getValue())); 173 } 174 175 public static String valueToString(ASN1Encodable value) 176 { 177 StringBuffer vBuf = new StringBuffer(); 178 179 if (value instanceof ASN1String && !(value instanceof DERUniversalString)) 180 { 181 String v = ((ASN1String)value).getString(); 182 if (v.length() > 0 && v.charAt(0) == '#') 183 { 184 vBuf.append("\\" + v); 185 } 186 else 187 { 188 vBuf.append(v); 189 } 190 } 191 else 192 { 193 try 194 { 195 vBuf.append("#" + bytesToString(Hex.encode(value.toASN1Primitive().getEncoded(ASN1Encoding.DER)))); 196 } 197 catch (IOException e) 198 { 199 throw new IllegalArgumentException("Other value has no encoded form"); 200 } 201 } 202 203 int end = vBuf.length(); 204 int index = 0; 205 206 if (vBuf.length() >= 2 && vBuf.charAt(0) == '\\' && vBuf.charAt(1) == '#') 207 { 208 index += 2; 209 } 210 211 while (index != end) 212 { 213 if ((vBuf.charAt(index) == ',') 214 || (vBuf.charAt(index) == '"') 215 || (vBuf.charAt(index) == '\\') 216 || (vBuf.charAt(index) == '+') 217 || (vBuf.charAt(index) == '=') 218 || (vBuf.charAt(index) == '<') 219 || (vBuf.charAt(index) == '>') 220 || (vBuf.charAt(index) == ';')) 221 { 222 vBuf.insert(index, "\\"); 223 index++; 224 end++; 225 } 226 227 index++; 228 } 229 230 return vBuf.toString(); 231 } 232 233 private static String bytesToString( 234 byte[] data) 235 { 236 char[] cs = new char[data.length]; 237 238 for (int i = 0; i != cs.length; i++) 239 { 240 cs[i] = (char)(data[i] & 0xff); 241 } 242 243 return new String(cs); 244 } 245 246 public static String canonicalize(String s) 247 { 248 String value = Strings.toLowerCase(s.trim()); 249 250 if (value.length() > 0 && value.charAt(0) == '#') 251 { 252 ASN1Primitive obj = decodeObject(value); 253 254 if (obj instanceof ASN1String) 255 { 256 value = Strings.toLowerCase(((ASN1String)obj).getString().trim()); 257 } 258 } 259 260 value = stripInternalSpaces(value); 261 262 return value; 263 } 264 265 private static ASN1Primitive decodeObject(String oValue) 266 { 267 try 268 { 269 return ASN1Primitive.fromByteArray(Hex.decode(oValue.substring(1))); 270 } 271 catch (IOException e) 272 { 273 throw new IllegalStateException("unknown encoding in name: " + e); 274 } 275 } 276 277 public static String stripInternalSpaces( 278 String str) 279 { 280 StringBuffer res = new StringBuffer(); 281 282 if (str.length() != 0) 283 { 284 char c1 = str.charAt(0); 285 286 res.append(c1); 287 288 for (int k = 1; k < str.length(); k++) 289 { 290 char c2 = str.charAt(k); 291 if (!(c1 == ' ' && c2 == ' ')) 292 { 293 res.append(c2); 294 } 295 c1 = c2; 296 } 297 } 298 299 return res.toString(); 300 } 301} 302