1 19 20 package com.maverick.crypto.asn1.x509; 21 22 import java.io.ByteArrayInputStream ; 23 import java.io.IOException ; 24 import java.util.Enumeration ; 25 import java.util.Hashtable ; 26 import java.util.Vector ; 27 28 import com.maverick.crypto.asn1.*; 29 30 public class X509Name 31 implements DEREncodable 32 { 33 36 public static final DERObjectIdentifier C = new DERObjectIdentifier("2.5.4.6"); 37 38 41 public static final DERObjectIdentifier O = new DERObjectIdentifier("2.5.4.10"); 42 43 46 public static final DERObjectIdentifier OU = new DERObjectIdentifier("2.5.4.11"); 47 48 51 public static final DERObjectIdentifier T = new DERObjectIdentifier("2.5.4.12"); 52 53 56 public static final DERObjectIdentifier CN = new DERObjectIdentifier("2.5.4.3"); 57 58 61 public static final DERObjectIdentifier SN = new DERObjectIdentifier("2.5.4.5"); 62 63 66 public static final DERObjectIdentifier L = new DERObjectIdentifier("2.5.4.7"); 67 68 71 public static final DERObjectIdentifier ST = new DERObjectIdentifier("2.5.4.8"); 72 73 76 public static final DERObjectIdentifier SURNAME = new DERObjectIdentifier("2.5.4.4"); 77 public static final DERObjectIdentifier GIVENNAME = new DERObjectIdentifier("2.5.4.42"); 78 public static final DERObjectIdentifier INITIALS = new DERObjectIdentifier("2.5.4.43"); 79 public static final DERObjectIdentifier GENERATION = new DERObjectIdentifier("2.5.4.44"); 80 public static final DERObjectIdentifier UNIQUE_IDENTIFIER = new DERObjectIdentifier("2.5.4.45"); 81 82 86 public static final DERObjectIdentifier EmailAddress = new DERObjectIdentifier("1.2.840.113549.1.9.1"); 87 88 91 public static final DERObjectIdentifier E = EmailAddress; 92 93 96 public static final DERObjectIdentifier DC = new DERObjectIdentifier("0.9.2342.19200300.100.1.25"); 97 98 101 public static final DERObjectIdentifier UID = new DERObjectIdentifier("0.9.2342.19200300.100.1.1"); 102 103 106 public static Hashtable OIDLookUp = new Hashtable (); 107 108 112 public static boolean DefaultReverse = false; 113 114 118 public static Hashtable DefaultSymbols = OIDLookUp; 119 120 124 public static Hashtable RFC2253Symbols = new Hashtable (); 125 126 130 public static Hashtable SymbolLookUp = new Hashtable (); 131 132 135 public static Hashtable DefaultLookUp = SymbolLookUp; 136 137 static 138 { 139 DefaultSymbols.put(C, "C"); 140 DefaultSymbols.put(O, "O"); 141 DefaultSymbols.put(T, "T"); 142 DefaultSymbols.put(OU, "OU"); 143 DefaultSymbols.put(CN, "CN"); 144 DefaultSymbols.put(L, "L"); 145 DefaultSymbols.put(ST, "ST"); 146 DefaultSymbols.put(SN, "SN"); 147 DefaultSymbols.put(EmailAddress, "E"); 148 DefaultSymbols.put(DC, "DC"); 149 DefaultSymbols.put(UID, "UID"); 150 DefaultSymbols.put(SURNAME, "SURNAME"); 151 DefaultSymbols.put(GIVENNAME, "GIVENNAME"); 152 DefaultSymbols.put(INITIALS, "INITIALS"); 153 DefaultSymbols.put(GENERATION, "GENERATION"); 154 155 RFC2253Symbols.put(C, "C"); 156 RFC2253Symbols.put(O, "O"); 157 RFC2253Symbols.put(T, "T"); 158 RFC2253Symbols.put(OU, "OU"); 159 RFC2253Symbols.put(CN, "CN"); 160 RFC2253Symbols.put(L, "L"); 161 RFC2253Symbols.put(ST, "ST"); 162 RFC2253Symbols.put(SN, "SN"); 163 RFC2253Symbols.put(EmailAddress, "EMAILADDRESS"); 164 RFC2253Symbols.put(DC, "DC"); 165 RFC2253Symbols.put(UID, "UID"); 166 RFC2253Symbols.put(SURNAME, "SURNAME"); 167 RFC2253Symbols.put(GIVENNAME, "GIVENNAME"); 168 RFC2253Symbols.put(INITIALS, "INITIALS"); 169 RFC2253Symbols.put(GENERATION, "GENERATION"); 170 171 DefaultLookUp.put("c", C); 172 DefaultLookUp.put("o", O); 173 DefaultLookUp.put("t", T); 174 DefaultLookUp.put("ou", OU); 175 DefaultLookUp.put("cn", CN); 176 DefaultLookUp.put("l", L); 177 DefaultLookUp.put("st", ST); 178 DefaultLookUp.put("sn", SN); 179 DefaultLookUp.put("emailaddress", E); 180 DefaultLookUp.put("dc", DC); 181 DefaultLookUp.put("e", E); 182 DefaultLookUp.put("uid", UID); 183 DefaultLookUp.put("surname", SURNAME); 184 DefaultLookUp.put("givenname", GIVENNAME); 185 DefaultLookUp.put("initials", INITIALS); 186 DefaultLookUp.put("generation", GENERATION); 187 } 188 189 private Vector ordering = new Vector (); 190 private Vector values = new Vector (); 191 private Vector added = new Vector (); 192 193 private ASN1Sequence seq; 194 195 public static X509Name getInstance( 196 ASN1TaggedObject obj, 197 boolean explicit) 198 { 199 return getInstance(ASN1Sequence.getInstance(obj, explicit)); 200 } 201 202 public static X509Name getInstance( 203 Object obj) 204 { 205 if (obj == null || obj instanceof X509Name) 206 { 207 return (X509Name)obj; 208 } 209 else if (obj instanceof ASN1Sequence) 210 { 211 return new X509Name((ASN1Sequence)obj); 212 } 213 214 throw new IllegalArgumentException ("unknown object in factory"); 215 } 216 217 222 public X509Name( 223 ASN1Sequence seq) 224 { 225 this.seq = seq; 226 227 Enumeration e = seq.getObjects(); 228 229 while (e.hasMoreElements()) 230 { 231 ASN1Set set = (ASN1Set)e.nextElement(); 232 233 for (int i = 0; i < set.size(); i++) 234 { 235 ASN1Sequence s = (ASN1Sequence)set.getObjectAt(i); 236 237 ordering.addElement(s.getObjectAt(0)); 238 values.addElement(((DERString) s.getObjectAt(1)).getString()); 239 added.addElement((i != 0) ? new Boolean (true) : new Boolean (false)); 240 } 241 } 242 } 243 244 255 public X509Name( 256 Hashtable attributes) 257 { 258 this(null, attributes); 259 } 260 261 269 public X509Name( 270 Vector ordering, 271 Hashtable attributes) 272 { 273 if (ordering != null) 274 { 275 for (int i = 0; i != ordering.size(); i++) 276 { 277 this.ordering.addElement(ordering.elementAt(i)); 278 this.added.addElement(new Boolean (false)); 279 } 280 } 281 else 282 { 283 Enumeration e = attributes.keys(); 284 285 while (e.hasMoreElements()) 286 { 287 this.ordering.addElement(e.nextElement()); 288 this.added.addElement(new Boolean (false)); 289 } 290 } 291 292 for (int i = 0; i != this.ordering.size(); i++) 293 { 294 DERObjectIdentifier oid = (DERObjectIdentifier)this.ordering.elementAt(i); 295 296 if (attributes.get(oid) == null) 297 { 298 throw new IllegalArgumentException ("No attribute for object id - " + oid.getId() + " - passed to distinguished name"); 299 } 300 301 this.values.addElement(attributes.get(oid)); } 303 } 304 305 308 public X509Name( 309 Vector oids, 310 Vector values) 311 { 312 if (oids.size() != values.size()) 313 { 314 throw new IllegalArgumentException ("oids vector must be same length as values."); 315 } 316 317 for (int i = 0; i < oids.size(); i++) 318 { 319 this.ordering.addElement(oids.elementAt(i)); 320 this.values.addElement(values.elementAt(i)); 321 this.added.addElement(new Boolean (false)); 322 } 323 } 324 325 329 public X509Name( 330 String dirName) 331 { 332 this(DefaultReverse, DefaultLookUp, dirName); 333 } 334 335 341 public X509Name( 342 boolean reverse, 343 String dirName) 344 { 345 this(reverse, DefaultLookUp, dirName); 346 } 347 348 361 public X509Name( 362 boolean reverse, 363 Hashtable lookUp, 364 String dirName) 365 { 366 X509NameTokenizer nTok = new X509NameTokenizer(dirName); 367 368 while (nTok.hasMoreTokens()) 369 { 370 String token = nTok.nextToken(); 371 int index = token.indexOf('='); 372 373 if (index == -1) 374 { 375 throw new IllegalArgumentException ("badly formated directory string"); 376 } 377 378 String name = token.substring(0, index); 379 String value = token.substring(index + 1); 380 DERObjectIdentifier oid = null; 381 382 if (name.toUpperCase().startsWith("OID.")) 383 { 384 oid = new DERObjectIdentifier(name.substring(4)); 385 } 386 else if (name.charAt(0) >= '0' && name.charAt(0) <= '9') 387 { 388 oid = new DERObjectIdentifier(name); 389 } 390 else 391 { 392 oid = (DERObjectIdentifier)lookUp.get(name.toLowerCase()); 393 if (oid == null) 394 { 395 throw new IllegalArgumentException ("Unknown object id - " + name + " - passed to distinguished name"); 396 } 397 } 398 399 this.ordering.addElement(oid); 400 this.values.addElement(value); 401 this.added.addElement(new Boolean (false)); 402 } 403 404 if (reverse) 405 { 406 Vector o = new Vector (); 407 Vector v = new Vector (); 408 409 for (int i = this.ordering.size() - 1; i >= 0; i--) 410 { 411 o.addElement(this.ordering.elementAt(i)); 412 v.addElement(this.values.elementAt(i)); 413 this.added.addElement(new Boolean (false)); 414 } 415 416 this.ordering = o; 417 this.values = v; 418 } 419 } 420 421 424 public Vector getOIDs() 425 { 426 Vector v = new Vector (); 427 428 for (int i = 0; i != ordering.size(); i++) 429 { 430 v.addElement(ordering.elementAt(i)); 431 } 432 433 return v; 434 } 435 436 440 public Vector getValues() 441 { 442 Vector v = new Vector (); 443 444 for (int i = 0; i != values.size(); i++) 445 { 446 v.addElement(values.elementAt(i)); 447 } 448 449 return v; 450 } 451 452 456 private boolean canBePrintable( 457 String str) 458 { 459 for (int i = str.length() - 1; i >= 0; i--) 460 { 461 if (str.charAt(i) > 0x007f) 462 { 463 return false; 464 } 465 } 466 467 return true; 468 } 469 470 public DERObject getDERObject() 471 { 472 if (seq == null) 473 { 474 ASN1EncodableVector vec = new ASN1EncodableVector(); 475 476 for (int i = 0; i != ordering.size(); i++) 477 { 478 ASN1EncodableVector v = new ASN1EncodableVector(); 479 DERObjectIdentifier oid = (DERObjectIdentifier)ordering.elementAt(i); 480 481 v.add(oid); 482 483 String str = (String )values.elementAt(i); 484 485 if (str.charAt(0) == '#') 486 { 487 str = str.toLowerCase(); 488 byte[] data = new byte[str.length() / 2]; 489 for (int index = 0; index != data.length; index++) 490 { 491 char left = str.charAt((index * 2) + 1); 492 char right = str.charAt((index * 2) + 2); 493 494 if (left < 'a') 495 { 496 data[index] = (byte)((left - '0') << 4); 497 } 498 else 499 { 500 data[index] = (byte)((left - 'a' + 10) << 4); 501 } 502 if (right < 'a') 503 { 504 data[index] |= (byte)(right - '0'); 505 } 506 else 507 { 508 data[index] |= (byte)(right - 'a' + 10); 509 } 510 } 511 512 ASN1InputStream aIn = new ASN1InputStream( 513 new ByteArrayInputStream (data)); 514 515 try 516 { 517 v.add(aIn.readObject()); 518 } 519 catch (IOException e) 520 { 521 throw new RuntimeException ("bad object in '#' string"); 522 } 523 } 524 else 525 { 526 if (oid.equals(EmailAddress)) 527 { 528 v.add(new DERIA5String(str)); 529 } 530 else 531 { 532 if (canBePrintable(str)) 533 { 534 v.add(new DERPrintableString(str)); 535 } 536 else 537 { 538 v.add(new DERUTF8String(str)); 539 } 540 } 541 } 542 543 vec.add(new DERSet(new DERSequence(v))); 544 } 545 546 seq = new DERSequence(vec); 547 } 548 549 return seq; 550 } 551 552 556 public boolean equals(Object _obj, boolean inOrder) 557 { 558 if (_obj == this) 559 { 560 return true; 561 } 562 563 if (!inOrder) 564 { 565 return this.equals(_obj); 566 } 567 568 if (_obj == null || !(_obj instanceof X509Name)) 569 { 570 return false; 571 } 572 573 X509Name _oxn = (X509Name)_obj; 574 int _orderingSize = ordering.size(); 575 576 if (_orderingSize != _oxn.ordering.size()) 577 { 578 return false; 579 } 580 581 for(int i = 0; i < _orderingSize; i++) 582 { 583 String _oid = ((DERObjectIdentifier)ordering.elementAt(i)).getId(); 584 String _val = (String )values.elementAt(i); 585 586 String _oOID = ((DERObjectIdentifier)_oxn.ordering.elementAt(i)).getId(); 587 String _oVal = (String )_oxn.values.elementAt(i); 588 589 if (_oid.equals(_oOID)) 590 { 591 _val = _val.trim().toLowerCase(); 592 _oVal = _oVal.trim().toLowerCase(); 593 if (_val.equals(_oVal)) 594 { 595 continue; 596 } 597 else 598 { 599 StringBuffer v1 = new StringBuffer (); 600 StringBuffer v2 = new StringBuffer (); 601 602 if (_val.length() != 0) 603 { 604 char c1 = _val.charAt(0); 605 606 v1.append(c1); 607 608 for (int k = 1; k < _val.length(); k++) 609 { 610 char c2 = _val.charAt(k); 611 if (!(c1 == ' ' && c2 == ' ')) 612 { 613 v1.append(c2); 614 } 615 c1 = c2; 616 } 617 } 618 619 if (_oVal.length() != 0) 620 { 621 char c1 = _oVal.charAt(0); 622 623 v2.append(c1); 624 625 for (int k = 1; k < _oVal.length(); k++) 626 { 627 char c2 = _oVal.charAt(k); 628 if (!(c1 == ' ' && c2 == ' ')) 629 { 630 v2.append(c2); 631 } 632 c1 = c2; 633 } 634 } 635 636 if (!v1.toString().equals(v2.toString())) 637 { 638 return false; 639 } 640 } 641 } 642 } 643 644 return true; 645 } 646 647 650 public boolean equals(Object _obj) 651 { 652 if (_obj == this) 653 { 654 return true; 655 } 656 657 if (_obj == null || !(_obj instanceof X509Name)) 658 { 659 return false; 660 } 661 662 X509Name _oxn = (X509Name)_obj; 663 664 if (this.getDERObject().equals(_oxn.getDERObject())) 665 { 666 return true; 667 } 668 669 int _orderingSize = ordering.size(); 670 671 if (_orderingSize != _oxn.ordering.size()) 672 { 673 return false; 674 } 675 676 boolean[] _indexes = new boolean[_orderingSize]; 677 678 for(int i = 0; i < _orderingSize; i++) 679 { 680 boolean _found = false; 681 String _oid = ((DERObjectIdentifier)ordering.elementAt(i)).getId(); 682 String _val = (String )values.elementAt(i); 683 684 for(int j = 0; j < _orderingSize; j++) 685 { 686 if(_indexes[j] == true) 687 { 688 continue; 689 } 690 691 String _oOID = ((DERObjectIdentifier)_oxn.ordering.elementAt(j)).getId(); 692 String _oVal = (String )_oxn.values.elementAt(j); 693 694 if (_oid.equals(_oOID)) 695 { 696 _val = _val.trim().toLowerCase(); 697 _oVal = _oVal.trim().toLowerCase(); 698 if (_val.equals(_oVal)) 699 { 700 _indexes[j] = true; 701 _found = true; 702 break; 703 } 704 else 705 { 706 StringBuffer v1 = new StringBuffer (); 707 StringBuffer v2 = new StringBuffer (); 708 709 if (_val.length() != 0) 710 { 711 char c1 = _val.charAt(0); 712 713 v1.append(c1); 714 715 for (int k = 1; k < _val.length(); k++) 716 { 717 char c2 = _val.charAt(k); 718 if (!(c1 == ' ' && c2 == ' ')) 719 { 720 v1.append(c2); 721 } 722 c1 = c2; 723 } 724 } 725 726 if (_oVal.length() != 0) 727 { 728 char c1 = _oVal.charAt(0); 729 730 v2.append(c1); 731 732 for (int k = 1; k < _oVal.length(); k++) 733 { 734 char c2 = _oVal.charAt(k); 735 if (!(c1 == ' ' && c2 == ' ')) 736 { 737 v2.append(c2); 738 } 739 c1 = c2; 740 } 741 } 742 743 if (v1.toString().equals(v2.toString())) 744 { 745 _indexes[j] = true; 746 _found = true; 747 break; 748 } 749 } 750 } 751 } 752 753 if(!_found) 754 { 755 return false; 756 } 757 } 758 759 return true; 760 } 761 762 public int hashCode() 763 { 764 ASN1Sequence seq = (ASN1Sequence)this.getDERObject(); 765 Enumeration e = seq.getObjects(); 766 int hashCode = 0; 767 768 while (e.hasMoreElements()) 769 { 770 hashCode ^= e.nextElement().hashCode(); 771 } 772 773 return hashCode; 774 } 775 776 private void appendValue( 777 StringBuffer buf, 778 Hashtable oidSymbols, 779 DERObjectIdentifier oid, 780 String value) 781 { 782 String sym = (String )oidSymbols.get(oid); 783 784 if (sym != null) 785 { 786 buf.append(sym); 787 } 788 else 789 { 790 buf.append(oid.getId()); 791 } 792 793 buf.append("="); 794 795 int index = buf.length(); 796 797 buf.append(value); 798 799 int end = buf.length(); 800 801 while (index != end) 802 { 803 if ((buf.charAt(index) == ',') 804 || (buf.charAt(index) == '"') 805 || (buf.charAt(index) == '\\') 806 || (buf.charAt(index) == '+') 807 || (buf.charAt(index) == '<') 808 || (buf.charAt(index) == '>') 809 || (buf.charAt(index) == ';')) 810 { 811 buf.insert(index, "\\"); 812 index++; 813 end++; 814 } 815 816 index++; 817 } 818 } 819 820 832 public String toString( 833 boolean reverse, 834 Hashtable oidSymbols) 835 { 836 StringBuffer buf = new StringBuffer (); 837 boolean first = true; 838 839 if (reverse) 840 { 841 for (int i = ordering.size() - 1; i >= 0; i--) 842 { 843 if (first) 844 { 845 first = false; 846 } 847 else 848 { 849 if (((Boolean )added.elementAt(i + 1)).booleanValue()) 850 { 851 buf.append(" + "); 852 } 853 else 854 { 855 buf.append(","); 856 } 857 } 858 859 appendValue(buf, oidSymbols, 860 (DERObjectIdentifier)ordering.elementAt(i), 861 (String )values.elementAt(i)); 862 } 863 } 864 else 865 { 866 for (int i = 0; i < ordering.size(); i++) 867 { 868 if (first) 869 { 870 first = false; 871 } 872 else 873 { 874 if (((Boolean )added.elementAt(i)).booleanValue()) 875 { 876 buf.append(" + "); 877 } 878 else 879 { 880 buf.append(","); 881 } 882 } 883 884 appendValue(buf, oidSymbols, 885 (DERObjectIdentifier)ordering.elementAt(i), 886 (String )values.elementAt(i)); 887 } 888 } 889 890 return buf.toString(); 891 } 892 893 public String toString() 894 { 895 return toString(DefaultReverse, DefaultSymbols); 896 } 897 } 898 | Popular Tags |