1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 package com.android.org.bouncycastle.asn1.x509; 3 4 import java.io.IOException; 5 import java.util.Enumeration; 6 import java.util.Hashtable; 7 import java.util.Vector; 8 9 import com.android.org.bouncycastle.asn1.ASN1Encodable; 10 import com.android.org.bouncycastle.asn1.ASN1EncodableVector; 11 import com.android.org.bouncycastle.asn1.ASN1Encoding; 12 import com.android.org.bouncycastle.asn1.ASN1Object; 13 import com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier; 14 import com.android.org.bouncycastle.asn1.ASN1Primitive; 15 import com.android.org.bouncycastle.asn1.ASN1Sequence; 16 import com.android.org.bouncycastle.asn1.ASN1Set; 17 import com.android.org.bouncycastle.asn1.ASN1String; 18 import com.android.org.bouncycastle.asn1.ASN1TaggedObject; 19 import com.android.org.bouncycastle.asn1.DERSequence; 20 import com.android.org.bouncycastle.asn1.DERSet; 21 import com.android.org.bouncycastle.asn1.DERUniversalString; 22 import com.android.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 23 import com.android.org.bouncycastle.asn1.x500.X500Name; 24 import com.android.org.bouncycastle.util.Strings; 25 import com.android.org.bouncycastle.util.encoders.Hex; 26 27 /** 28 * <pre> 29 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 30 * 31 * RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue 32 * 33 * AttributeTypeAndValue ::= SEQUENCE { 34 * type OBJECT IDENTIFIER, 35 * value ANY } 36 * </pre> 37 * @deprecated use org.bouncycastle.asn1.x500.X500Name. 38 * @hide This class is not part of the Android public SDK API 39 */ 40 @libcore.api.CorePlatformApi 41 public class X509Name 42 extends ASN1Object 43 { 44 /** 45 * country code - StringType(SIZE(2)) 46 * @deprecated use a X500NameStyle 47 */ 48 public static final ASN1ObjectIdentifier C = new ASN1ObjectIdentifier("2.5.4.6"); 49 50 /** 51 * organization - StringType(SIZE(1..64)) 52 * @deprecated use a X500NameStyle 53 */ 54 @libcore.api.CorePlatformApi 55 public static final ASN1ObjectIdentifier O = new ASN1ObjectIdentifier("2.5.4.10"); 56 57 /** 58 * organizational unit name - StringType(SIZE(1..64)) 59 * @deprecated use a X500NameStyle 60 */ 61 @libcore.api.CorePlatformApi 62 public static final ASN1ObjectIdentifier OU = new ASN1ObjectIdentifier("2.5.4.11"); 63 64 /** 65 * Title 66 * @deprecated use a X500NameStyle 67 */ 68 public static final ASN1ObjectIdentifier T = new ASN1ObjectIdentifier("2.5.4.12"); 69 70 /** 71 * common name - StringType(SIZE(1..64)) 72 * @deprecated use a X500NameStyle 73 */ 74 @dalvik.annotation.compat.UnsupportedAppUsage 75 @libcore.api.CorePlatformApi 76 public static final ASN1ObjectIdentifier CN = new ASN1ObjectIdentifier("2.5.4.3"); 77 78 /** 79 * device serial number name - StringType(SIZE(1..64)) 80 */ 81 public static final ASN1ObjectIdentifier SN = new ASN1ObjectIdentifier("2.5.4.5"); 82 83 /** 84 * street - StringType(SIZE(1..64)) 85 */ 86 public static final ASN1ObjectIdentifier STREET = new ASN1ObjectIdentifier("2.5.4.9"); 87 88 /** 89 * device serial number name - StringType(SIZE(1..64)) 90 */ 91 public static final ASN1ObjectIdentifier SERIALNUMBER = SN; 92 93 /** 94 * locality name - StringType(SIZE(1..64)) 95 */ 96 public static final ASN1ObjectIdentifier L = new ASN1ObjectIdentifier("2.5.4.7"); 97 98 /** 99 * state, or province name - StringType(SIZE(1..64)) 100 */ 101 public static final ASN1ObjectIdentifier ST = new ASN1ObjectIdentifier("2.5.4.8"); 102 103 /** 104 * Naming attributes of type X520name 105 */ 106 public static final ASN1ObjectIdentifier SURNAME = new ASN1ObjectIdentifier("2.5.4.4"); 107 public static final ASN1ObjectIdentifier GIVENNAME = new ASN1ObjectIdentifier("2.5.4.42"); 108 public static final ASN1ObjectIdentifier INITIALS = new ASN1ObjectIdentifier("2.5.4.43"); 109 public static final ASN1ObjectIdentifier GENERATION = new ASN1ObjectIdentifier("2.5.4.44"); 110 public static final ASN1ObjectIdentifier UNIQUE_IDENTIFIER = new ASN1ObjectIdentifier("2.5.4.45"); 111 112 /** 113 * businessCategory - DirectoryString(SIZE(1..128) 114 */ 115 public static final ASN1ObjectIdentifier BUSINESS_CATEGORY = new ASN1ObjectIdentifier( 116 "2.5.4.15"); 117 118 /** 119 * postalCode - DirectoryString(SIZE(1..40) 120 */ 121 public static final ASN1ObjectIdentifier POSTAL_CODE = new ASN1ObjectIdentifier( 122 "2.5.4.17"); 123 124 /** 125 * dnQualifier - DirectoryString(SIZE(1..64) 126 */ 127 public static final ASN1ObjectIdentifier DN_QUALIFIER = new ASN1ObjectIdentifier( 128 "2.5.4.46"); 129 130 /** 131 * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64) 132 */ 133 public static final ASN1ObjectIdentifier PSEUDONYM = new ASN1ObjectIdentifier( 134 "2.5.4.65"); 135 136 137 /** 138 * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z 139 */ 140 public static final ASN1ObjectIdentifier DATE_OF_BIRTH = new ASN1ObjectIdentifier( 141 "1.3.6.1.5.5.7.9.1"); 142 143 /** 144 * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128) 145 */ 146 public static final ASN1ObjectIdentifier PLACE_OF_BIRTH = new ASN1ObjectIdentifier( 147 "1.3.6.1.5.5.7.9.2"); 148 149 /** 150 * RFC 3039 Gender - PrintableString (SIZE(1)) -- "M", "F", "m" or "f" 151 */ 152 public static final ASN1ObjectIdentifier GENDER = new ASN1ObjectIdentifier( 153 "1.3.6.1.5.5.7.9.3"); 154 155 /** 156 * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166 157 * codes only 158 */ 159 public static final ASN1ObjectIdentifier COUNTRY_OF_CITIZENSHIP = new ASN1ObjectIdentifier( 160 "1.3.6.1.5.5.7.9.4"); 161 162 /** 163 * RFC 3039 CountryOfResidence - PrintableString (SIZE (2)) -- ISO 3166 164 * codes only 165 */ 166 public static final ASN1ObjectIdentifier COUNTRY_OF_RESIDENCE = new ASN1ObjectIdentifier( 167 "1.3.6.1.5.5.7.9.5"); 168 169 170 /** 171 * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64) 172 */ 173 public static final ASN1ObjectIdentifier NAME_AT_BIRTH = new ASN1ObjectIdentifier("1.3.36.8.3.14"); 174 175 /** 176 * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF 177 * DirectoryString(SIZE(1..30)) 178 */ 179 public static final ASN1ObjectIdentifier POSTAL_ADDRESS = new ASN1ObjectIdentifier("2.5.4.16"); 180 181 /** 182 * RFC 2256 dmdName 183 */ 184 public static final ASN1ObjectIdentifier DMD_NAME = new ASN1ObjectIdentifier("2.5.4.54"); 185 186 /** 187 * id-at-telephoneNumber 188 */ 189 public static final ASN1ObjectIdentifier TELEPHONE_NUMBER = X509ObjectIdentifiers.id_at_telephoneNumber; 190 191 /** 192 * id-at-name 193 */ 194 public static final ASN1ObjectIdentifier NAME = X509ObjectIdentifiers.id_at_name; 195 196 /** 197 * Email address (RSA PKCS#9 extension) - IA5String. 198 * <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here. 199 * @deprecated use a X500NameStyle 200 */ 201 public static final ASN1ObjectIdentifier EmailAddress = PKCSObjectIdentifiers.pkcs_9_at_emailAddress; 202 203 /** 204 * more from PKCS#9 205 */ 206 public static final ASN1ObjectIdentifier UnstructuredName = PKCSObjectIdentifiers.pkcs_9_at_unstructuredName; 207 public static final ASN1ObjectIdentifier UnstructuredAddress = PKCSObjectIdentifiers.pkcs_9_at_unstructuredAddress; 208 209 /** 210 * email address in Verisign certificates 211 */ 212 public static final ASN1ObjectIdentifier E = EmailAddress; 213 214 /* 215 * others... 216 */ 217 public static final ASN1ObjectIdentifier DC = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25"); 218 219 /** 220 * LDAP User id. 221 */ 222 public static final ASN1ObjectIdentifier UID = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1"); 223 224 /** 225 * determines whether or not strings should be processed and printed 226 * from back to front. 227 */ 228 public static boolean DefaultReverse = false; 229 230 /** 231 * default look up table translating OID values into their common symbols following 232 * the convention in RFC 2253 with a few extras 233 */ 234 @libcore.api.CorePlatformApi 235 public static final Hashtable DefaultSymbols = new Hashtable(); 236 237 /** 238 * look up table translating OID values into their common symbols following the convention in RFC 2253 239 * 240 */ 241 public static final Hashtable RFC2253Symbols = new Hashtable(); 242 243 /** 244 * look up table translating OID values into their common symbols following the convention in RFC 1779 245 * 246 */ 247 public static final Hashtable RFC1779Symbols = new Hashtable(); 248 249 /** 250 * look up table translating common symbols into their OIDS. 251 */ 252 public static final Hashtable DefaultLookUp = new Hashtable(); 253 254 /** 255 * look up table translating OID values into their common symbols 256 * @deprecated use DefaultSymbols 257 */ 258 public static final Hashtable OIDLookUp = DefaultSymbols; 259 260 /** 261 * look up table translating string values into their OIDS - 262 * @deprecated use DefaultLookUp 263 */ 264 public static final Hashtable SymbolLookUp = DefaultLookUp; 265 266 // BEGIN Android-changed: Use Boolean class constants instead of Boolean constructor 267 private static final Boolean TRUE = Boolean.TRUE; 268 private static final Boolean FALSE = Boolean.FALSE; 269 // END Android-changed: Use Boolean class constants instead of Boolean constructor 270 271 static 272 { 273 DefaultSymbols.put(C, "C"); 274 DefaultSymbols.put(O, "O"); 275 DefaultSymbols.put(T, "T"); 276 DefaultSymbols.put(OU, "OU"); 277 DefaultSymbols.put(CN, "CN"); 278 DefaultSymbols.put(L, "L"); 279 DefaultSymbols.put(ST, "ST"); 280 DefaultSymbols.put(SN, "SERIALNUMBER"); 281 DefaultSymbols.put(EmailAddress, "E"); 282 DefaultSymbols.put(DC, "DC"); 283 DefaultSymbols.put(UID, "UID"); 284 DefaultSymbols.put(STREET, "STREET"); 285 DefaultSymbols.put(SURNAME, "SURNAME"); 286 DefaultSymbols.put(GIVENNAME, "GIVENNAME"); 287 DefaultSymbols.put(INITIALS, "INITIALS"); 288 DefaultSymbols.put(GENERATION, "GENERATION"); 289 DefaultSymbols.put(UnstructuredAddress, "unstructuredAddress"); 290 DefaultSymbols.put(UnstructuredName, "unstructuredName"); 291 DefaultSymbols.put(UNIQUE_IDENTIFIER, "UniqueIdentifier"); 292 DefaultSymbols.put(DN_QUALIFIER, "DN"); 293 DefaultSymbols.put(PSEUDONYM, "Pseudonym"); 294 DefaultSymbols.put(POSTAL_ADDRESS, "PostalAddress"); 295 DefaultSymbols.put(NAME_AT_BIRTH, "NameAtBirth"); 296 DefaultSymbols.put(COUNTRY_OF_CITIZENSHIP, "CountryOfCitizenship"); 297 DefaultSymbols.put(COUNTRY_OF_RESIDENCE, "CountryOfResidence"); 298 DefaultSymbols.put(GENDER, "Gender"); 299 DefaultSymbols.put(PLACE_OF_BIRTH, "PlaceOfBirth"); 300 DefaultSymbols.put(DATE_OF_BIRTH, "DateOfBirth"); 301 DefaultSymbols.put(POSTAL_CODE, "PostalCode"); 302 DefaultSymbols.put(BUSINESS_CATEGORY, "BusinessCategory"); 303 DefaultSymbols.put(TELEPHONE_NUMBER, "TelephoneNumber"); 304 DefaultSymbols.put(NAME, "Name"); 305 306 RFC2253Symbols.put(C, "C"); 307 RFC2253Symbols.put(O, "O"); 308 RFC2253Symbols.put(OU, "OU"); 309 RFC2253Symbols.put(CN, "CN"); 310 RFC2253Symbols.put(L, "L"); 311 RFC2253Symbols.put(ST, "ST"); 312 RFC2253Symbols.put(STREET, "STREET"); 313 RFC2253Symbols.put(DC, "DC"); 314 RFC2253Symbols.put(UID, "UID"); 315 316 RFC1779Symbols.put(C, "C"); 317 RFC1779Symbols.put(O, "O"); 318 RFC1779Symbols.put(OU, "OU"); 319 RFC1779Symbols.put(CN, "CN"); 320 RFC1779Symbols.put(L, "L"); 321 RFC1779Symbols.put(ST, "ST"); 322 RFC1779Symbols.put(STREET, "STREET"); 323 324 DefaultLookUp.put("c", C); 325 DefaultLookUp.put("o", O); 326 DefaultLookUp.put("t", T); 327 DefaultLookUp.put("ou", OU); 328 DefaultLookUp.put("cn", CN); 329 DefaultLookUp.put("l", L); 330 DefaultLookUp.put("st", ST); 331 DefaultLookUp.put("sn", SN); 332 DefaultLookUp.put("serialnumber", SN); 333 DefaultLookUp.put("street", STREET); 334 DefaultLookUp.put("emailaddress", E); 335 DefaultLookUp.put("dc", DC); 336 DefaultLookUp.put("e", E); 337 DefaultLookUp.put("uid", UID); 338 DefaultLookUp.put("surname", SURNAME); 339 DefaultLookUp.put("givenname", GIVENNAME); 340 DefaultLookUp.put("initials", INITIALS); 341 DefaultLookUp.put("generation", GENERATION); 342 DefaultLookUp.put("unstructuredaddress", UnstructuredAddress); 343 DefaultLookUp.put("unstructuredname", UnstructuredName); 344 DefaultLookUp.put("uniqueidentifier", UNIQUE_IDENTIFIER); 345 DefaultLookUp.put("dn", DN_QUALIFIER); 346 DefaultLookUp.put("pseudonym", PSEUDONYM); 347 DefaultLookUp.put("postaladdress", POSTAL_ADDRESS); 348 DefaultLookUp.put("nameofbirth", NAME_AT_BIRTH); 349 DefaultLookUp.put("countryofcitizenship", COUNTRY_OF_CITIZENSHIP); 350 DefaultLookUp.put("countryofresidence", COUNTRY_OF_RESIDENCE); 351 DefaultLookUp.put("gender", GENDER); 352 DefaultLookUp.put("placeofbirth", PLACE_OF_BIRTH); 353 DefaultLookUp.put("dateofbirth", DATE_OF_BIRTH); 354 DefaultLookUp.put("postalcode", POSTAL_CODE); 355 DefaultLookUp.put("businesscategory", BUSINESS_CATEGORY); 356 DefaultLookUp.put("telephonenumber", TELEPHONE_NUMBER); 357 DefaultLookUp.put("name", NAME); 358 } 359 360 private X509NameEntryConverter converter = null; 361 private Vector ordering = new Vector(); 362 private Vector values = new Vector(); 363 private Vector added = new Vector(); 364 365 private ASN1Sequence seq; 366 367 private boolean isHashCodeCalculated; 368 private int hashCodeValue; 369 370 /** 371 * Return a X509Name based on the passed in tagged object. 372 * 373 * @param obj tag object holding name. 374 * @param explicit true if explicitly tagged false otherwise. 375 * @return the X509Name 376 */ 377 public static X509Name getInstance( 378 ASN1TaggedObject obj, 379 boolean explicit) 380 { 381 return getInstance(ASN1Sequence.getInstance(obj, explicit)); 382 } 383 384 @libcore.api.CorePlatformApi 385 public static X509Name getInstance( 386 Object obj) 387 { 388 if (obj == null || obj instanceof X509Name) 389 { 390 return (X509Name)obj; 391 } 392 else if (obj instanceof X500Name) 393 { 394 return new X509Name(ASN1Sequence.getInstance(((X500Name)obj).toASN1Primitive())); 395 } 396 else if (obj != null) 397 { 398 return new X509Name(ASN1Sequence.getInstance(obj)); 399 } 400 401 return null; 402 } 403 404 protected X509Name() 405 { 406 // constructure use by new X500 Name class 407 } 408 /** 409 * Constructor from ASN1Sequence 410 * 411 * the principal will be a list of constructed sets, each containing an (OID, String) pair. 412 * @deprecated use X500Name.getInstance() 413 */ 414 @dalvik.annotation.compat.UnsupportedAppUsage 415 public X509Name( 416 ASN1Sequence seq) 417 { 418 this.seq = seq; 419 420 Enumeration e = seq.getObjects(); 421 422 while (e.hasMoreElements()) 423 { 424 ASN1Set set = ASN1Set.getInstance(((ASN1Encodable)e.nextElement()).toASN1Primitive()); 425 426 for (int i = 0; i < set.size(); i++) 427 { 428 ASN1Sequence s = ASN1Sequence.getInstance(set.getObjectAt(i).toASN1Primitive()); 429 430 if (s.size() != 2) 431 { 432 throw new IllegalArgumentException("badly sized pair"); 433 } 434 435 ordering.addElement(ASN1ObjectIdentifier.getInstance(s.getObjectAt(0))); 436 437 ASN1Encodable value = s.getObjectAt(1); 438 if (value instanceof ASN1String && !(value instanceof DERUniversalString)) 439 { 440 String v = ((ASN1String)value).getString(); 441 if (v.length() > 0 && v.charAt(0) == '#') 442 { 443 values.addElement("\\" + v); 444 } 445 else 446 { 447 values.addElement(v); 448 } 449 } 450 else 451 { 452 try 453 { 454 values.addElement("#" + bytesToString(Hex.encode(value.toASN1Primitive().getEncoded(ASN1Encoding.DER)))); 455 } 456 catch (IOException e1) 457 { 458 throw new IllegalArgumentException("cannot encode value"); 459 } 460 } 461 added.addElement((i != 0) ? TRUE : FALSE); // to allow earlier JDK compatibility 462 } 463 } 464 } 465 466 /** 467 * constructor from a table of attributes. 468 * <p> 469 * it's is assumed the table contains OID/String pairs, and the contents 470 * of the table are copied into an internal table as part of the 471 * construction process. 472 * <p> 473 * <b>Note:</b> if the name you are trying to generate should be 474 * following a specific ordering, you should use the constructor 475 * with the ordering specified below. 476 * @deprecated use an ordered constructor! The hashtable ordering is rarely correct 477 */ 478 public X509Name( 479 Hashtable attributes) 480 { 481 this(null, attributes); 482 } 483 484 /** 485 * Constructor from a table of attributes with ordering. 486 * <p> 487 * it's is assumed the table contains OID/String pairs, and the contents 488 * of the table are copied into an internal table as part of the 489 * construction process. The ordering vector should contain the OIDs 490 * in the order they are meant to be encoded or printed in toString. 491 */ 492 public X509Name( 493 Vector ordering, 494 Hashtable attributes) 495 { 496 this(ordering, attributes, new X509DefaultEntryConverter()); 497 } 498 499 /** 500 * Constructor from a table of attributes with ordering. 501 * <p> 502 * it's is assumed the table contains OID/String pairs, and the contents 503 * of the table are copied into an internal table as part of the 504 * construction process. The ordering vector should contain the OIDs 505 * in the order they are meant to be encoded or printed in toString. 506 * <p> 507 * The passed in converter will be used to convert the strings into their 508 * ASN.1 counterparts. 509 * @deprecated use X500Name, X500NameBuilder 510 */ 511 public X509Name( 512 Vector ordering, 513 Hashtable attributes, 514 X509NameEntryConverter converter) 515 { 516 this.converter = converter; 517 518 if (ordering != null) 519 { 520 for (int i = 0; i != ordering.size(); i++) 521 { 522 this.ordering.addElement(ordering.elementAt(i)); 523 this.added.addElement(FALSE); 524 } 525 } 526 else 527 { 528 Enumeration e = attributes.keys(); 529 530 while (e.hasMoreElements()) 531 { 532 this.ordering.addElement(e.nextElement()); 533 this.added.addElement(FALSE); 534 } 535 } 536 537 for (int i = 0; i != this.ordering.size(); i++) 538 { 539 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)this.ordering.elementAt(i); 540 541 if (attributes.get(oid) == null) 542 { 543 throw new IllegalArgumentException("No attribute for object id - " + oid.getId() + " - passed to distinguished name"); 544 } 545 546 this.values.addElement(attributes.get(oid)); // copy the hash table 547 } 548 } 549 550 /** 551 * Takes two vectors one of the oids and the other of the values. 552 * @deprecated use X500Name, X500NameBuilder 553 */ 554 public X509Name( 555 Vector oids, 556 Vector values) 557 { 558 this(oids, values, new X509DefaultEntryConverter()); 559 } 560 561 /** 562 * Takes two vectors one of the oids and the other of the values. 563 * <p> 564 * The passed in converter will be used to convert the strings into their 565 * ASN.1 counterparts. 566 * @deprecated use X500Name, X500NameBuilder 567 */ 568 public X509Name( 569 Vector oids, 570 Vector values, 571 X509NameEntryConverter converter) 572 { 573 this.converter = converter; 574 575 if (oids.size() != values.size()) 576 { 577 throw new IllegalArgumentException("oids vector must be same length as values."); 578 } 579 580 for (int i = 0; i < oids.size(); i++) 581 { 582 this.ordering.addElement(oids.elementAt(i)); 583 this.values.addElement(values.elementAt(i)); 584 this.added.addElement(FALSE); 585 } 586 } 587 588 // private Boolean isEncoded(String s) 589 // { 590 // if (s.charAt(0) == '#') 591 // { 592 // return TRUE; 593 // } 594 // 595 // return FALSE; 596 // } 597 598 /** 599 * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or 600 * some such, converting it into an ordered set of name attributes. 601 * @deprecated use X500Name, X500NameBuilder 602 */ 603 @dalvik.annotation.compat.UnsupportedAppUsage 604 @libcore.api.CorePlatformApi 605 public X509Name( 606 String dirName) 607 { 608 this(DefaultReverse, DefaultLookUp, dirName); 609 } 610 611 /** 612 * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or 613 * some such, converting it into an ordered set of name attributes with each 614 * string value being converted to its associated ASN.1 type using the passed 615 * in converter. 616 * @deprecated use X500Name, X500NameBuilder 617 */ 618 public X509Name( 619 String dirName, 620 X509NameEntryConverter converter) 621 { 622 this(DefaultReverse, DefaultLookUp, dirName, converter); 623 } 624 625 /** 626 * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or 627 * some such, converting it into an ordered set of name attributes. If reverse 628 * is true, create the encoded version of the sequence starting from the 629 * last element in the string. 630 * @deprecated use X500Name, X500NameBuilder 631 */ 632 public X509Name( 633 boolean reverse, 634 String dirName) 635 { 636 this(reverse, DefaultLookUp, dirName); 637 } 638 639 /** 640 * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or 641 * some such, converting it into an ordered set of name attributes with each 642 * string value being converted to its associated ASN.1 type using the passed 643 * in converter. If reverse is true the ASN.1 sequence representing the DN will 644 * be built by starting at the end of the string, rather than the start. 645 * @deprecated use X500Name, X500NameBuilder 646 */ 647 public X509Name( 648 boolean reverse, 649 String dirName, 650 X509NameEntryConverter converter) 651 { 652 this(reverse, DefaultLookUp, dirName, converter); 653 } 654 655 /** 656 * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or 657 * some such, converting it into an ordered set of name attributes. lookUp 658 * should provide a table of lookups, indexed by lowercase only strings and 659 * yielding a ASN1ObjectIdentifier, other than that OID. and numeric oids 660 * will be processed automatically. 661 * <br> 662 * If reverse is true, create the encoded version of the sequence 663 * starting from the last element in the string. 664 * @param reverse true if we should start scanning from the end (RFC 2553). 665 * @param lookUp table of names and their oids. 666 * @param dirName the X.500 string to be parsed. 667 * @deprecated use X500Name, X500NameBuilder 668 */ 669 public X509Name( 670 boolean reverse, 671 Hashtable lookUp, 672 String dirName) 673 { 674 this(reverse, lookUp, dirName, new X509DefaultEntryConverter()); 675 } 676 677 private ASN1ObjectIdentifier decodeOID( 678 String name, 679 Hashtable lookUp) 680 { 681 name = name.trim(); 682 if (Strings.toUpperCase(name).startsWith("OID.")) 683 { 684 return new ASN1ObjectIdentifier(name.substring(4)); 685 } 686 else if (name.charAt(0) >= '0' && name.charAt(0) <= '9') 687 { 688 return new ASN1ObjectIdentifier(name); 689 } 690 691 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)lookUp.get(Strings.toLowerCase(name)); 692 if (oid == null) 693 { 694 throw new IllegalArgumentException("Unknown object id - " + name + " - passed to distinguished name"); 695 } 696 697 return oid; 698 } 699 700 private String unescape(String elt) 701 { 702 if (elt.length() == 0 || (elt.indexOf('\\') < 0 && elt.indexOf('"') < 0)) 703 { 704 return elt.trim(); 705 } 706 707 char[] elts = elt.toCharArray(); 708 boolean escaped = false; 709 boolean quoted = false; 710 StringBuffer buf = new StringBuffer(elt.length()); 711 int start = 0; 712 713 // if it's an escaped hash string and not an actual encoding in string form 714 // we need to leave it escaped. 715 if (elts[0] == '\\') 716 { 717 if (elts[1] == '#') 718 { 719 start = 2; 720 buf.append("\\#"); 721 } 722 } 723 724 boolean nonWhiteSpaceEncountered = false; 725 int lastEscaped = 0; 726 727 for (int i = start; i != elts.length; i++) 728 { 729 char c = elts[i]; 730 731 if (c != ' ') 732 { 733 nonWhiteSpaceEncountered = true; 734 } 735 736 if (c == '"') 737 { 738 if (!escaped) 739 { 740 quoted = !quoted; 741 } 742 else 743 { 744 buf.append(c); 745 } 746 escaped = false; 747 } 748 else if (c == '\\' && !(escaped || quoted)) 749 { 750 escaped = true; 751 lastEscaped = buf.length(); 752 } 753 else 754 { 755 if (c == ' ' && !escaped && !nonWhiteSpaceEncountered) 756 { 757 continue; 758 } 759 buf.append(c); 760 escaped = false; 761 } 762 } 763 764 if (buf.length() > 0) 765 { 766 while (buf.charAt(buf.length() - 1) == ' ' && lastEscaped != (buf.length() - 1)) 767 { 768 buf.setLength(buf.length() - 1); 769 } 770 } 771 772 return buf.toString(); 773 } 774 775 /** 776 * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or 777 * some such, converting it into an ordered set of name attributes. lookUp 778 * should provide a table of lookups, indexed by lowercase only strings and 779 * yielding a ASN1ObjectIdentifier, other than that OID. and numeric oids 780 * will be processed automatically. The passed in converter is used to convert the 781 * string values to the right of each equals sign to their ASN.1 counterparts. 782 * <br> 783 * @param reverse true if we should start scanning from the end, false otherwise. 784 * @param lookUp table of names and oids. 785 * @param dirName the string dirName 786 * @param converter the converter to convert string values into their ASN.1 equivalents 787 */ 788 public X509Name( 789 boolean reverse, 790 Hashtable lookUp, 791 String dirName, 792 X509NameEntryConverter converter) 793 { 794 this.converter = converter; 795 X509NameTokenizer nTok = new X509NameTokenizer(dirName); 796 797 while (nTok.hasMoreTokens()) 798 { 799 String token = nTok.nextToken(); 800 801 if (token.indexOf('+') > 0) 802 { 803 X509NameTokenizer pTok = new X509NameTokenizer(token, '+'); 804 805 addEntry(lookUp, pTok.nextToken(), FALSE); 806 807 while (pTok.hasMoreTokens()) 808 { 809 addEntry(lookUp, pTok.nextToken(), TRUE); 810 } 811 } 812 else 813 { 814 addEntry(lookUp, token, FALSE); 815 } 816 } 817 818 if (reverse) 819 { 820 Vector o = new Vector(); 821 Vector v = new Vector(); 822 Vector a = new Vector(); 823 824 int count = 1; 825 826 for (int i = 0; i < this.ordering.size(); i++) 827 { 828 if (((Boolean)this.added.elementAt(i)).booleanValue()) 829 { 830 o.insertElementAt(this.ordering.elementAt(i), count); 831 v.insertElementAt(this.values.elementAt(i), count); 832 a.insertElementAt(this.added.elementAt(i), count); 833 count++; 834 } 835 else 836 { 837 o.insertElementAt(this.ordering.elementAt(i), 0); 838 v.insertElementAt(this.values.elementAt(i), 0); 839 a.insertElementAt(this.added.elementAt(i), 0); 840 count = 1; 841 } 842 } 843 844 this.ordering = o; 845 this.values = v; 846 this.added = a; 847 } 848 } 849 850 private void addEntry(Hashtable lookUp, String token, Boolean isAdded) 851 { 852 X509NameTokenizer vTok; 853 String name; 854 String value;ASN1ObjectIdentifier oid; 855 vTok = new X509NameTokenizer(token, '='); 856 857 name = vTok.nextToken(); 858 859 if (!vTok.hasMoreTokens()) 860 { 861 throw new IllegalArgumentException("badly formatted directory string"); 862 } 863 864 value = vTok.nextToken(); 865 866 oid = decodeOID(name, lookUp); 867 868 this.ordering.addElement(oid); 869 this.values.addElement(unescape(value)); 870 this.added.addElement(isAdded); 871 } 872 873 /** 874 * return a vector of the oids in the name, in the order they were found. 875 */ 876 @dalvik.annotation.compat.UnsupportedAppUsage 877 @libcore.api.CorePlatformApi 878 public Vector getOIDs() 879 { 880 Vector v = new Vector(); 881 882 for (int i = 0; i != ordering.size(); i++) 883 { 884 v.addElement(ordering.elementAt(i)); 885 } 886 887 return v; 888 } 889 890 /** 891 * return a vector of the values found in the name, in the order they 892 * were found. 893 */ 894 @dalvik.annotation.compat.UnsupportedAppUsage 895 @libcore.api.CorePlatformApi 896 public Vector getValues() 897 { 898 Vector v = new Vector(); 899 900 for (int i = 0; i != values.size(); i++) 901 { 902 v.addElement(values.elementAt(i)); 903 } 904 905 return v; 906 } 907 908 /** 909 * return a vector of the values found in the name, in the order they 910 * were found, with the DN label corresponding to passed in oid. 911 */ 912 public Vector getValues( 913 ASN1ObjectIdentifier oid) 914 { 915 Vector v = new Vector(); 916 917 for (int i = 0; i != values.size(); i++) 918 { 919 if (ordering.elementAt(i).equals(oid)) 920 { 921 String val = (String)values.elementAt(i); 922 923 if (val.length() > 2 && val.charAt(0) == '\\' && val.charAt(1) == '#') 924 { 925 v.addElement(val.substring(1)); 926 } 927 else 928 { 929 v.addElement(val); 930 } 931 } 932 } 933 934 return v; 935 } 936 937 public ASN1Primitive toASN1Primitive() 938 { 939 if (seq == null) 940 { 941 ASN1EncodableVector vec = new ASN1EncodableVector(); 942 ASN1EncodableVector sVec = new ASN1EncodableVector(); 943 ASN1ObjectIdentifier lstOid = null; 944 945 for (int i = 0; i != ordering.size(); i++) 946 { 947 ASN1EncodableVector v = new ASN1EncodableVector(); 948 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)ordering.elementAt(i); 949 950 v.add(oid); 951 952 String str = (String)values.elementAt(i); 953 954 v.add(converter.getConvertedValue(oid, str)); 955 956 if (lstOid == null 957 || ((Boolean)this.added.elementAt(i)).booleanValue()) 958 { 959 sVec.add(new DERSequence(v)); 960 } 961 else 962 { 963 vec.add(new DERSet(sVec)); 964 sVec = new ASN1EncodableVector(); 965 966 sVec.add(new DERSequence(v)); 967 } 968 969 lstOid = oid; 970 } 971 972 vec.add(new DERSet(sVec)); 973 974 seq = new DERSequence(vec); 975 } 976 977 return seq; 978 } 979 980 /** 981 * @param inOrder if true the order of both X509 names must be the same, 982 * as well as the values associated with each element. 983 */ 984 public boolean equals(Object obj, boolean inOrder) 985 { 986 if (!inOrder) 987 { 988 return this.equals(obj); 989 } 990 991 if (obj == this) 992 { 993 return true; 994 } 995 996 if (!(obj instanceof X509Name || obj instanceof ASN1Sequence)) 997 { 998 return false; 999 } 1000 1001 ASN1Primitive derO = ((ASN1Encodable)obj).toASN1Primitive(); 1002 1003 if (this.toASN1Primitive().equals(derO)) 1004 { 1005 return true; 1006 } 1007 1008 X509Name other; 1009 1010 try 1011 { 1012 other = X509Name.getInstance(obj); 1013 } 1014 catch (IllegalArgumentException e) 1015 { 1016 return false; 1017 } 1018 1019 int orderingSize = ordering.size(); 1020 1021 if (orderingSize != other.ordering.size()) 1022 { 1023 return false; 1024 } 1025 1026 for (int i = 0; i < orderingSize; i++) 1027 { 1028 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)ordering.elementAt(i); 1029 ASN1ObjectIdentifier oOid = (ASN1ObjectIdentifier)other.ordering.elementAt(i); 1030 1031 if (oid.equals(oOid)) 1032 { 1033 String value = (String)values.elementAt(i); 1034 String oValue = (String)other.values.elementAt(i); 1035 1036 if (!equivalentStrings(value, oValue)) 1037 { 1038 return false; 1039 } 1040 } 1041 else 1042 { 1043 return false; 1044 } 1045 } 1046 1047 return true; 1048 } 1049 1050 public int hashCode() 1051 { 1052 if (isHashCodeCalculated) 1053 { 1054 return hashCodeValue; 1055 } 1056 1057 isHashCodeCalculated = true; 1058 1059 // this needs to be order independent, like equals 1060 for (int i = 0; i != ordering.size(); i += 1) 1061 { 1062 String value = (String)values.elementAt(i); 1063 1064 value = canonicalize(value); 1065 value = stripInternalSpaces(value); 1066 1067 hashCodeValue ^= ordering.elementAt(i).hashCode(); 1068 hashCodeValue ^= value.hashCode(); 1069 } 1070 1071 return hashCodeValue; 1072 } 1073 1074 /** 1075 * test for equality - note: case is ignored. 1076 */ 1077 public boolean equals(Object obj) 1078 { 1079 if (obj == this) 1080 { 1081 return true; 1082 } 1083 1084 if (!(obj instanceof X509Name || obj instanceof ASN1Sequence)) 1085 { 1086 return false; 1087 } 1088 1089 ASN1Primitive derO = ((ASN1Encodable)obj).toASN1Primitive(); 1090 1091 if (this.toASN1Primitive().equals(derO)) 1092 { 1093 return true; 1094 } 1095 1096 X509Name other; 1097 1098 try 1099 { 1100 other = X509Name.getInstance(obj); 1101 } 1102 catch (IllegalArgumentException e) 1103 { 1104 return false; 1105 } 1106 1107 int orderingSize = ordering.size(); 1108 1109 if (orderingSize != other.ordering.size()) 1110 { 1111 return false; 1112 } 1113 1114 boolean[] indexes = new boolean[orderingSize]; 1115 int start, end, delta; 1116 1117 if (ordering.elementAt(0).equals(other.ordering.elementAt(0))) // guess forward 1118 { 1119 start = 0; 1120 end = orderingSize; 1121 delta = 1; 1122 } 1123 else // guess reversed - most common problem 1124 { 1125 start = orderingSize - 1; 1126 end = -1; 1127 delta = -1; 1128 } 1129 1130 for (int i = start; i != end; i += delta) 1131 { 1132 boolean found = false; 1133 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)ordering.elementAt(i); 1134 String value = (String)values.elementAt(i); 1135 1136 for (int j = 0; j < orderingSize; j++) 1137 { 1138 if (indexes[j]) 1139 { 1140 continue; 1141 } 1142 1143 ASN1ObjectIdentifier oOid = (ASN1ObjectIdentifier)other.ordering.elementAt(j); 1144 1145 if (oid.equals(oOid)) 1146 { 1147 String oValue = (String)other.values.elementAt(j); 1148 1149 if (equivalentStrings(value, oValue)) 1150 { 1151 indexes[j] = true; 1152 found = true; 1153 break; 1154 } 1155 } 1156 } 1157 1158 if (!found) 1159 { 1160 return false; 1161 } 1162 } 1163 1164 return true; 1165 } 1166 1167 private boolean equivalentStrings(String s1, String s2) 1168 { 1169 String value = canonicalize(s1); 1170 String oValue = canonicalize(s2); 1171 1172 if (!value.equals(oValue)) 1173 { 1174 value = stripInternalSpaces(value); 1175 oValue = stripInternalSpaces(oValue); 1176 1177 if (!value.equals(oValue)) 1178 { 1179 return false; 1180 } 1181 } 1182 1183 return true; 1184 } 1185 1186 private String canonicalize(String s) 1187 { 1188 String value = Strings.toLowerCase(s.trim()); 1189 1190 if (value.length() > 0 && value.charAt(0) == '#') 1191 { 1192 ASN1Primitive obj = decodeObject(value); 1193 1194 if (obj instanceof ASN1String) 1195 { 1196 value = Strings.toLowerCase(((ASN1String)obj).getString().trim()); 1197 } 1198 } 1199 1200 return value; 1201 } 1202 1203 private ASN1Primitive decodeObject(String oValue) 1204 { 1205 try 1206 { 1207 return ASN1Primitive.fromByteArray(Hex.decode(oValue.substring(1))); 1208 } 1209 catch (IOException e) 1210 { 1211 throw new IllegalStateException("unknown encoding in name: " + e); 1212 } 1213 } 1214 1215 private String stripInternalSpaces( 1216 String str) 1217 { 1218 StringBuffer res = new StringBuffer(); 1219 1220 if (str.length() != 0) 1221 { 1222 char c1 = str.charAt(0); 1223 1224 res.append(c1); 1225 1226 for (int k = 1; k < str.length(); k++) 1227 { 1228 char c2 = str.charAt(k); 1229 if (!(c1 == ' ' && c2 == ' ')) 1230 { 1231 res.append(c2); 1232 } 1233 c1 = c2; 1234 } 1235 } 1236 1237 return res.toString(); 1238 } 1239 1240 private void appendValue( 1241 StringBuffer buf, 1242 Hashtable oidSymbols, 1243 ASN1ObjectIdentifier oid, 1244 String value) 1245 { 1246 String sym = (String)oidSymbols.get(oid); 1247 1248 if (sym != null) 1249 { 1250 buf.append(sym); 1251 } 1252 else 1253 { 1254 buf.append(oid.getId()); 1255 } 1256 1257 buf.append('='); 1258 1259 int start = buf.length(); 1260 buf.append(value); 1261 int end = buf.length(); 1262 1263 if (value.length() >= 2 && value.charAt(0) == '\\' && value.charAt(1) == '#') 1264 { 1265 start += 2; 1266 } 1267 1268 while (start < end && buf.charAt(start) == ' ') 1269 { 1270 buf.insert(start, "\\"); 1271 start += 2; 1272 ++end; 1273 } 1274 1275 while (--end > start && buf.charAt(end) == ' ') 1276 { 1277 buf.insert(end, '\\'); 1278 } 1279 1280 while (start <= end) 1281 { 1282 switch (buf.charAt(start)) 1283 { 1284 case ',': 1285 case '"': 1286 case '\\': 1287 case '+': 1288 case '=': 1289 case '<': 1290 case '>': 1291 case ';': 1292 buf.insert(start, "\\"); 1293 start += 2; 1294 ++end; 1295 break; 1296 default: 1297 ++start; 1298 break; 1299 } 1300 } 1301 } 1302 1303 /** 1304 * convert the structure to a string - if reverse is true the 1305 * oids and values are listed out starting with the last element 1306 * in the sequence (ala RFC 2253), otherwise the string will begin 1307 * with the first element of the structure. If no string definition 1308 * for the oid is found in oidSymbols the string value of the oid is 1309 * added. Two standard symbol tables are provided DefaultSymbols, and 1310 * RFC2253Symbols as part of this class. 1311 * 1312 * @param reverse if true start at the end of the sequence and work back. 1313 * @param oidSymbols look up table strings for oids. 1314 */ 1315 @libcore.api.CorePlatformApi 1316 public String toString( 1317 boolean reverse, 1318 Hashtable oidSymbols) 1319 { 1320 StringBuffer buf = new StringBuffer(); 1321 Vector components = new Vector(); 1322 boolean first = true; 1323 1324 StringBuffer ava = null; 1325 1326 for (int i = 0; i < ordering.size(); i++) 1327 { 1328 if (((Boolean)added.elementAt(i)).booleanValue()) 1329 { 1330 ava.append('+'); 1331 appendValue(ava, oidSymbols, 1332 (ASN1ObjectIdentifier)ordering.elementAt(i), 1333 (String)values.elementAt(i)); 1334 } 1335 else 1336 { 1337 ava = new StringBuffer(); 1338 appendValue(ava, oidSymbols, 1339 (ASN1ObjectIdentifier)ordering.elementAt(i), 1340 (String)values.elementAt(i)); 1341 components.addElement(ava); 1342 } 1343 } 1344 1345 if (reverse) 1346 { 1347 for (int i = components.size() - 1; i >= 0; i--) 1348 { 1349 if (first) 1350 { 1351 first = false; 1352 } 1353 else 1354 { 1355 buf.append(','); 1356 } 1357 1358 buf.append(components.elementAt(i).toString()); 1359 } 1360 } 1361 else 1362 { 1363 for (int i = 0; i < components.size(); i++) 1364 { 1365 if (first) 1366 { 1367 first = false; 1368 } 1369 else 1370 { 1371 buf.append(','); 1372 } 1373 1374 buf.append(components.elementAt(i).toString()); 1375 } 1376 } 1377 1378 return buf.toString(); 1379 } 1380 1381 private String bytesToString( 1382 byte[] data) 1383 { 1384 char[] cs = new char[data.length]; 1385 1386 for (int i = 0; i != cs.length; i++) 1387 { 1388 cs[i] = (char)(data[i] & 0xff); 1389 } 1390 1391 return new String(cs); 1392 } 1393 1394 public String toString() 1395 { 1396 return toString(DefaultReverse, DefaultSymbols); 1397 } 1398 } 1399