X509CertificateObject.java revision e1142c149e244797ce73b0e7fad40816e447a817
1package org.bouncycastle.jce.provider; 2 3import java.io.ByteArrayOutputStream; 4import java.io.IOException; 5import java.math.BigInteger; 6import java.net.InetAddress; 7import java.net.UnknownHostException; 8import java.security.InvalidKeyException; 9import java.security.NoSuchAlgorithmException; 10import java.security.NoSuchProviderException; 11import java.security.Principal; 12import java.security.Provider; 13import java.security.PublicKey; 14import java.security.Security; 15import java.security.Signature; 16import java.security.SignatureException; 17import java.security.cert.Certificate; 18import java.security.cert.CertificateEncodingException; 19import java.security.cert.CertificateException; 20import java.security.cert.CertificateExpiredException; 21import java.security.cert.CertificateNotYetValidException; 22import java.security.cert.CertificateParsingException; 23import java.security.cert.X509Certificate; 24import java.util.ArrayList; 25import java.util.Collection; 26import java.util.Collections; 27import java.util.Date; 28import java.util.Enumeration; 29import java.util.HashSet; 30import java.util.List; 31import java.util.Set; 32 33import javax.security.auth.x500.X500Principal; 34 35import org.bouncycastle.asn1.ASN1Encodable; 36import org.bouncycastle.asn1.ASN1Encoding; 37import org.bouncycastle.asn1.ASN1InputStream; 38import org.bouncycastle.asn1.ASN1ObjectIdentifier; 39import org.bouncycastle.asn1.ASN1OutputStream; 40import org.bouncycastle.asn1.ASN1Primitive; 41import org.bouncycastle.asn1.ASN1Sequence; 42import org.bouncycastle.asn1.ASN1String; 43import org.bouncycastle.asn1.DERBitString; 44import org.bouncycastle.asn1.DERIA5String; 45import org.bouncycastle.asn1.DERNull; 46import org.bouncycastle.asn1.DEROctetString; 47import org.bouncycastle.asn1.misc.MiscObjectIdentifiers; 48import org.bouncycastle.asn1.misc.NetscapeCertType; 49import org.bouncycastle.asn1.misc.NetscapeRevocationURL; 50import org.bouncycastle.asn1.misc.VerisignCzagExtension; 51import org.bouncycastle.asn1.util.ASN1Dump; 52import org.bouncycastle.asn1.x500.X500Name; 53import org.bouncycastle.asn1.x500.style.RFC4519Style; 54import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 55import org.bouncycastle.asn1.x509.BasicConstraints; 56import org.bouncycastle.asn1.x509.Extension; 57import org.bouncycastle.asn1.x509.Extensions; 58import org.bouncycastle.asn1.x509.GeneralName; 59import org.bouncycastle.asn1.x509.KeyUsage; 60// BEGIN android-added 61import org.bouncycastle.asn1.x509.X509Name; 62// END android-added 63import org.bouncycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl; 64import org.bouncycastle.jce.X509Principal; 65import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier; 66import org.bouncycastle.util.Arrays; 67import org.bouncycastle.util.Integers; 68import org.bouncycastle.util.encoders.Hex; 69 70public class X509CertificateObject 71 extends X509Certificate 72 implements PKCS12BagAttributeCarrier 73{ 74 private org.bouncycastle.asn1.x509.Certificate c; 75 private BasicConstraints basicConstraints; 76 private boolean[] keyUsage; 77 private boolean hashValueSet; 78 private int hashValue; 79 80 private PKCS12BagAttributeCarrier attrCarrier = new PKCS12BagAttributeCarrierImpl(); 81 82 public X509CertificateObject( 83 org.bouncycastle.asn1.x509.Certificate c) 84 throws CertificateParsingException 85 { 86 this.c = c; 87 88 try 89 { 90 byte[] bytes = this.getExtensionBytes("2.5.29.19"); 91 92 if (bytes != null) 93 { 94 basicConstraints = BasicConstraints.getInstance(ASN1Primitive.fromByteArray(bytes)); 95 } 96 } 97 catch (Exception e) 98 { 99 throw new CertificateParsingException("cannot construct BasicConstraints: " + e); 100 } 101 102 try 103 { 104 byte[] bytes = this.getExtensionBytes("2.5.29.15"); 105 if (bytes != null) 106 { 107 DERBitString bits = DERBitString.getInstance(ASN1Primitive.fromByteArray(bytes)); 108 109 bytes = bits.getBytes(); 110 int length = (bytes.length * 8) - bits.getPadBits(); 111 112 keyUsage = new boolean[(length < 9) ? 9 : length]; 113 114 for (int i = 0; i != length; i++) 115 { 116 keyUsage[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; 117 } 118 } 119 else 120 { 121 keyUsage = null; 122 } 123 } 124 catch (Exception e) 125 { 126 throw new CertificateParsingException("cannot construct KeyUsage: " + e); 127 } 128 } 129 130 public void checkValidity() 131 throws CertificateExpiredException, CertificateNotYetValidException 132 { 133 this.checkValidity(new Date()); 134 } 135 136 public void checkValidity( 137 Date date) 138 throws CertificateExpiredException, CertificateNotYetValidException 139 { 140 if (date.getTime() > this.getNotAfter().getTime()) // for other VM compatibility 141 { 142 throw new CertificateExpiredException("certificate expired on " + c.getEndDate().getTime()); 143 } 144 145 if (date.getTime() < this.getNotBefore().getTime()) 146 { 147 throw new CertificateNotYetValidException("certificate not valid till " + c.getStartDate().getTime()); 148 } 149 } 150 151 public int getVersion() 152 { 153 return c.getVersionNumber(); 154 } 155 156 public BigInteger getSerialNumber() 157 { 158 return c.getSerialNumber().getValue(); 159 } 160 161 public Principal getIssuerDN() 162 { 163 try 164 { 165 return new X509Principal(X500Name.getInstance(c.getIssuer().getEncoded())); 166 } 167 catch (IOException e) 168 { 169 return null; 170 } 171 } 172 173 public X500Principal getIssuerX500Principal() 174 { 175 try 176 { 177 ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 178 ASN1OutputStream aOut = new ASN1OutputStream(bOut); 179 180 aOut.writeObject(c.getIssuer()); 181 182 return new X500Principal(bOut.toByteArray()); 183 } 184 catch (IOException e) 185 { 186 throw new IllegalStateException("can't encode issuer DN"); 187 } 188 } 189 190 public Principal getSubjectDN() 191 { 192 return new X509Principal(X500Name.getInstance(c.getSubject().toASN1Primitive())); 193 } 194 195 public X500Principal getSubjectX500Principal() 196 { 197 try 198 { 199 ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 200 ASN1OutputStream aOut = new ASN1OutputStream(bOut); 201 202 aOut.writeObject(c.getSubject()); 203 204 return new X500Principal(bOut.toByteArray()); 205 } 206 catch (IOException e) 207 { 208 throw new IllegalStateException("can't encode issuer DN"); 209 } 210 } 211 212 public Date getNotBefore() 213 { 214 return c.getStartDate().getDate(); 215 } 216 217 public Date getNotAfter() 218 { 219 return c.getEndDate().getDate(); 220 } 221 222 public byte[] getTBSCertificate() 223 throws CertificateEncodingException 224 { 225 try 226 { 227 return c.getTBSCertificate().getEncoded(ASN1Encoding.DER); 228 } 229 catch (IOException e) 230 { 231 throw new CertificateEncodingException(e.toString()); 232 } 233 } 234 235 public byte[] getSignature() 236 { 237 return c.getSignature().getBytes(); 238 } 239 240 /** 241 * return a more "meaningful" representation for the signature algorithm used in 242 * the certficate. 243 */ 244 public String getSigAlgName() 245 { 246 Provider prov = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME); 247 248 if (prov != null) 249 { 250 String algName = prov.getProperty("Alg.Alias.Signature." + this.getSigAlgOID()); 251 252 if (algName != null) 253 { 254 return algName; 255 } 256 } 257 258 Provider[] provs = Security.getProviders(); 259 260 // 261 // search every provider looking for a real algorithm 262 // 263 for (int i = 0; i != provs.length; i++) 264 { 265 String algName = provs[i].getProperty("Alg.Alias.Signature." + this.getSigAlgOID()); 266 if (algName != null) 267 { 268 return algName; 269 } 270 } 271 272 return this.getSigAlgOID(); 273 } 274 275 /** 276 * return the object identifier for the signature. 277 */ 278 public String getSigAlgOID() 279 { 280 return c.getSignatureAlgorithm().getAlgorithm().getId(); 281 } 282 283 /** 284 * return the signature parameters, or null if there aren't any. 285 */ 286 public byte[] getSigAlgParams() 287 { 288 if (c.getSignatureAlgorithm().getParameters() != null) 289 { 290 try 291 { 292 return c.getSignatureAlgorithm().getParameters().toASN1Primitive().getEncoded(ASN1Encoding.DER); 293 } 294 catch (IOException e) 295 { 296 return null; 297 } 298 } 299 else 300 { 301 return null; 302 } 303 } 304 305 public boolean[] getIssuerUniqueID() 306 { 307 DERBitString id = c.getTBSCertificate().getIssuerUniqueId(); 308 309 if (id != null) 310 { 311 byte[] bytes = id.getBytes(); 312 boolean[] boolId = new boolean[bytes.length * 8 - id.getPadBits()]; 313 314 for (int i = 0; i != boolId.length; i++) 315 { 316 boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; 317 } 318 319 return boolId; 320 } 321 322 return null; 323 } 324 325 public boolean[] getSubjectUniqueID() 326 { 327 DERBitString id = c.getTBSCertificate().getSubjectUniqueId(); 328 329 if (id != null) 330 { 331 byte[] bytes = id.getBytes(); 332 boolean[] boolId = new boolean[bytes.length * 8 - id.getPadBits()]; 333 334 for (int i = 0; i != boolId.length; i++) 335 { 336 boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; 337 } 338 339 return boolId; 340 } 341 342 return null; 343 } 344 345 public boolean[] getKeyUsage() 346 { 347 return keyUsage; 348 } 349 350 public List getExtendedKeyUsage() 351 throws CertificateParsingException 352 { 353 byte[] bytes = this.getExtensionBytes("2.5.29.37"); 354 355 if (bytes != null) 356 { 357 try 358 { 359 ASN1InputStream dIn = new ASN1InputStream(bytes); 360 ASN1Sequence seq = (ASN1Sequence)dIn.readObject(); 361 List list = new ArrayList(); 362 363 for (int i = 0; i != seq.size(); i++) 364 { 365 list.add(((ASN1ObjectIdentifier)seq.getObjectAt(i)).getId()); 366 } 367 368 return Collections.unmodifiableList(list); 369 } 370 catch (Exception e) 371 { 372 throw new CertificateParsingException("error processing extended key usage extension"); 373 } 374 } 375 376 return null; 377 } 378 379 public int getBasicConstraints() 380 { 381 if (basicConstraints != null) 382 { 383 if (basicConstraints.isCA()) 384 { 385 if (basicConstraints.getPathLenConstraint() == null) 386 { 387 return Integer.MAX_VALUE; 388 } 389 else 390 { 391 return basicConstraints.getPathLenConstraint().intValue(); 392 } 393 } 394 else 395 { 396 return -1; 397 } 398 } 399 400 return -1; 401 } 402 403 public Collection getSubjectAlternativeNames() 404 throws CertificateParsingException 405 { 406 return getAlternativeNames(getExtensionBytes(Extension.subjectAlternativeName.getId())); 407 } 408 409 public Collection getIssuerAlternativeNames() 410 throws CertificateParsingException 411 { 412 return getAlternativeNames(getExtensionBytes(Extension.issuerAlternativeName.getId())); 413 } 414 415 public Set getCriticalExtensionOIDs() 416 { 417 if (this.getVersion() == 3) 418 { 419 Set set = new HashSet(); 420 Extensions extensions = c.getTBSCertificate().getExtensions(); 421 422 if (extensions != null) 423 { 424 Enumeration e = extensions.oids(); 425 426 while (e.hasMoreElements()) 427 { 428 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); 429 Extension ext = extensions.getExtension(oid); 430 431 if (ext.isCritical()) 432 { 433 set.add(oid.getId()); 434 } 435 } 436 437 return set; 438 } 439 } 440 441 return null; 442 } 443 444 private byte[] getExtensionBytes(String oid) 445 { 446 Extensions exts = c.getTBSCertificate().getExtensions(); 447 448 if (exts != null) 449 { 450 Extension ext = exts.getExtension(new ASN1ObjectIdentifier(oid)); 451 if (ext != null) 452 { 453 return ext.getExtnValue().getOctets(); 454 } 455 } 456 457 return null; 458 } 459 460 public byte[] getExtensionValue(String oid) 461 { 462 Extensions exts = c.getTBSCertificate().getExtensions(); 463 464 if (exts != null) 465 { 466 Extension ext = exts.getExtension(new ASN1ObjectIdentifier(oid)); 467 468 if (ext != null) 469 { 470 try 471 { 472 return ext.getExtnValue().getEncoded(); 473 } 474 catch (Exception e) 475 { 476 throw new IllegalStateException("error parsing " + e.toString()); 477 } 478 } 479 } 480 481 return null; 482 } 483 484 public Set getNonCriticalExtensionOIDs() 485 { 486 if (this.getVersion() == 3) 487 { 488 Set set = new HashSet(); 489 Extensions extensions = c.getTBSCertificate().getExtensions(); 490 491 if (extensions != null) 492 { 493 Enumeration e = extensions.oids(); 494 495 while (e.hasMoreElements()) 496 { 497 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); 498 Extension ext = extensions.getExtension(oid); 499 500 if (!ext.isCritical()) 501 { 502 set.add(oid.getId()); 503 } 504 } 505 506 return set; 507 } 508 } 509 510 return null; 511 } 512 513 public boolean hasUnsupportedCriticalExtension() 514 { 515 if (this.getVersion() == 3) 516 { 517 Extensions extensions = c.getTBSCertificate().getExtensions(); 518 519 if (extensions != null) 520 { 521 Enumeration e = extensions.oids(); 522 523 while (e.hasMoreElements()) 524 { 525 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); 526 String oidId = oid.getId(); 527 528 if (oidId.equals(RFC3280CertPathUtilities.KEY_USAGE) 529 || oidId.equals(RFC3280CertPathUtilities.CERTIFICATE_POLICIES) 530 || oidId.equals(RFC3280CertPathUtilities.POLICY_MAPPINGS) 531 || oidId.equals(RFC3280CertPathUtilities.INHIBIT_ANY_POLICY) 532 || oidId.equals(RFC3280CertPathUtilities.CRL_DISTRIBUTION_POINTS) 533 || oidId.equals(RFC3280CertPathUtilities.ISSUING_DISTRIBUTION_POINT) 534 || oidId.equals(RFC3280CertPathUtilities.DELTA_CRL_INDICATOR) 535 || oidId.equals(RFC3280CertPathUtilities.POLICY_CONSTRAINTS) 536 || oidId.equals(RFC3280CertPathUtilities.BASIC_CONSTRAINTS) 537 || oidId.equals(RFC3280CertPathUtilities.SUBJECT_ALTERNATIVE_NAME) 538 || oidId.equals(RFC3280CertPathUtilities.NAME_CONSTRAINTS)) 539 { 540 continue; 541 } 542 543 Extension ext = extensions.getExtension(oid); 544 545 if (ext.isCritical()) 546 { 547 return true; 548 } 549 } 550 } 551 } 552 553 return false; 554 } 555 556 public PublicKey getPublicKey() 557 { 558 try 559 { 560 return BouncyCastleProvider.getPublicKey(c.getSubjectPublicKeyInfo()); 561 } 562 catch (IOException e) 563 { 564 return null; // should never happen... 565 } 566 } 567 568 // BEGIN android-changed 569 private byte[] encoded; 570 // END android-changed 571 public byte[] getEncoded() 572 throws CertificateEncodingException 573 { 574 try 575 { 576 // BEGIN android-changed 577 if (encoded == null) { 578 encoded = c.getEncoded(ASN1Encoding.DER); 579 } 580 return encoded; 581 // END android-changed 582 } 583 catch (IOException e) 584 { 585 throw new CertificateEncodingException(e.toString()); 586 } 587 } 588 589 public boolean equals( 590 Object o) 591 { 592 if (o == this) 593 { 594 return true; 595 } 596 597 if (!(o instanceof Certificate)) 598 { 599 return false; 600 } 601 602 Certificate other = (Certificate)o; 603 604 try 605 { 606 byte[] b1 = this.getEncoded(); 607 byte[] b2 = other.getEncoded(); 608 609 return Arrays.areEqual(b1, b2); 610 } 611 catch (CertificateEncodingException e) 612 { 613 return false; 614 } 615 } 616 617 public synchronized int hashCode() 618 { 619 if (!hashValueSet) 620 { 621 hashValue = calculateHashCode(); 622 hashValueSet = true; 623 } 624 625 return hashValue; 626 } 627 628 private int calculateHashCode() 629 { 630 try 631 { 632 int hashCode = 0; 633 byte[] certData = this.getEncoded(); 634 for (int i = 1; i < certData.length; i++) 635 { 636 hashCode += certData[i] * i; 637 } 638 return hashCode; 639 } 640 catch (CertificateEncodingException e) 641 { 642 return 0; 643 } 644 } 645 646 public void setBagAttribute( 647 ASN1ObjectIdentifier oid, 648 ASN1Encodable attribute) 649 { 650 attrCarrier.setBagAttribute(oid, attribute); 651 } 652 653 public ASN1Encodable getBagAttribute( 654 ASN1ObjectIdentifier oid) 655 { 656 return attrCarrier.getBagAttribute(oid); 657 } 658 659 public Enumeration getBagAttributeKeys() 660 { 661 return attrCarrier.getBagAttributeKeys(); 662 } 663 664 public String toString() 665 { 666 StringBuffer buf = new StringBuffer(); 667 String nl = System.getProperty("line.separator"); 668 669 buf.append(" [0] Version: ").append(this.getVersion()).append(nl); 670 buf.append(" SerialNumber: ").append(this.getSerialNumber()).append(nl); 671 buf.append(" IssuerDN: ").append(this.getIssuerDN()).append(nl); 672 buf.append(" Start Date: ").append(this.getNotBefore()).append(nl); 673 buf.append(" Final Date: ").append(this.getNotAfter()).append(nl); 674 buf.append(" SubjectDN: ").append(this.getSubjectDN()).append(nl); 675 buf.append(" Public Key: ").append(this.getPublicKey()).append(nl); 676 buf.append(" Signature Algorithm: ").append(this.getSigAlgName()).append(nl); 677 678 byte[] sig = this.getSignature(); 679 680 buf.append(" Signature: ").append(new String(Hex.encode(sig, 0, 20))).append(nl); 681 for (int i = 20; i < sig.length; i += 20) 682 { 683 if (i < sig.length - 20) 684 { 685 buf.append(" ").append(new String(Hex.encode(sig, i, 20))).append(nl); 686 } 687 else 688 { 689 buf.append(" ").append(new String(Hex.encode(sig, i, sig.length - i))).append(nl); 690 } 691 } 692 693 Extensions extensions = c.getTBSCertificate().getExtensions(); 694 695 if (extensions != null) 696 { 697 Enumeration e = extensions.oids(); 698 699 if (e.hasMoreElements()) 700 { 701 buf.append(" Extensions: \n"); 702 } 703 704 while (e.hasMoreElements()) 705 { 706 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); 707 Extension ext = extensions.getExtension(oid); 708 709 if (ext.getExtnValue() != null) 710 { 711 byte[] octs = ext.getExtnValue().getOctets(); 712 ASN1InputStream dIn = new ASN1InputStream(octs); 713 buf.append(" critical(").append(ext.isCritical()).append(") "); 714 try 715 { 716 if (oid.equals(Extension.basicConstraints)) 717 { 718 buf.append(BasicConstraints.getInstance(dIn.readObject())).append(nl); 719 } 720 else if (oid.equals(Extension.keyUsage)) 721 { 722 buf.append(KeyUsage.getInstance(dIn.readObject())).append(nl); 723 } 724 else if (oid.equals(MiscObjectIdentifiers.netscapeCertType)) 725 { 726 buf.append(new NetscapeCertType((DERBitString)dIn.readObject())).append(nl); 727 } 728 else if (oid.equals(MiscObjectIdentifiers.netscapeRevocationURL)) 729 { 730 buf.append(new NetscapeRevocationURL((DERIA5String)dIn.readObject())).append(nl); 731 } 732 else if (oid.equals(MiscObjectIdentifiers.verisignCzagExtension)) 733 { 734 buf.append(new VerisignCzagExtension((DERIA5String)dIn.readObject())).append(nl); 735 } 736 else 737 { 738 buf.append(oid.getId()); 739 buf.append(" value = ").append(ASN1Dump.dumpAsString(dIn.readObject())).append(nl); 740 //buf.append(" value = ").append("*****").append(nl); 741 } 742 } 743 catch (Exception ex) 744 { 745 buf.append(oid.getId()); 746 // buf.append(" value = ").append(new String(Hex.encode(ext.getExtnValue().getOctets()))).append(nl); 747 buf.append(" value = ").append("*****").append(nl); 748 } 749 } 750 else 751 { 752 buf.append(nl); 753 } 754 } 755 } 756 757 return buf.toString(); 758 } 759 760 public final void verify( 761 PublicKey key) 762 throws CertificateException, NoSuchAlgorithmException, 763 InvalidKeyException, NoSuchProviderException, SignatureException 764 { 765 Signature signature; 766 String sigName = X509SignatureUtil.getSignatureName(c.getSignatureAlgorithm()); 767 768 try 769 { 770 signature = Signature.getInstance(sigName, BouncyCastleProvider.PROVIDER_NAME); 771 } 772 catch (Exception e) 773 { 774 signature = Signature.getInstance(sigName); 775 } 776 777 checkSignature(key, signature); 778 } 779 780 public final void verify( 781 PublicKey key, 782 String sigProvider) 783 throws CertificateException, NoSuchAlgorithmException, 784 InvalidKeyException, NoSuchProviderException, SignatureException 785 { 786 String sigName = X509SignatureUtil.getSignatureName(c.getSignatureAlgorithm()); 787 Signature signature = Signature.getInstance(sigName, sigProvider); 788 789 checkSignature(key, signature); 790 } 791 792 private void checkSignature( 793 PublicKey key, 794 Signature signature) 795 throws CertificateException, NoSuchAlgorithmException, 796 SignatureException, InvalidKeyException 797 { 798 if (!isAlgIdEqual(c.getSignatureAlgorithm(), c.getTBSCertificate().getSignature())) 799 { 800 throw new CertificateException("signature algorithm in TBS cert not same as outer cert"); 801 } 802 803 ASN1Encodable params = c.getSignatureAlgorithm().getParameters(); 804 805 // TODO This should go after the initVerify? 806 X509SignatureUtil.setSignatureParameters(signature, params); 807 808 signature.initVerify(key); 809 810 signature.update(this.getTBSCertificate()); 811 812 if (!signature.verify(this.getSignature())) 813 { 814 throw new SignatureException("certificate does not verify with supplied key"); 815 } 816 } 817 818 private boolean isAlgIdEqual(AlgorithmIdentifier id1, AlgorithmIdentifier id2) 819 { 820 if (!id1.getAlgorithm().equals(id2.getAlgorithm())) 821 { 822 return false; 823 } 824 825 if (id1.getParameters() == null) 826 { 827 if (id2.getParameters() != null && !id2.getParameters().equals(DERNull.INSTANCE)) 828 { 829 return false; 830 } 831 832 return true; 833 } 834 835 if (id2.getParameters() == null) 836 { 837 if (id1.getParameters() != null && !id1.getParameters().equals(DERNull.INSTANCE)) 838 { 839 return false; 840 } 841 842 return true; 843 } 844 845 return id1.getParameters().equals(id2.getParameters()); 846 } 847 848 private static Collection getAlternativeNames(byte[] extVal) 849 throws CertificateParsingException 850 { 851 if (extVal == null) 852 { 853 return null; 854 } 855 try 856 { 857 Collection temp = new ArrayList(); 858 Enumeration it = ASN1Sequence.getInstance(extVal).getObjects(); 859 while (it.hasMoreElements()) 860 { 861 GeneralName genName = GeneralName.getInstance(it.nextElement()); 862 List list = new ArrayList(); 863 list.add(Integers.valueOf(genName.getTagNo())); 864 switch (genName.getTagNo()) 865 { 866 case GeneralName.ediPartyName: 867 case GeneralName.x400Address: 868 case GeneralName.otherName: 869 list.add(genName.getEncoded()); 870 break; 871 case GeneralName.directoryName: 872 // BEGIN android-changed 873 list.add(X509Name.getInstance(genName.getName()).toString(true, X509Name.DefaultSymbols)); 874 // END android-changed 875 break; 876 case GeneralName.dNSName: 877 case GeneralName.rfc822Name: 878 case GeneralName.uniformResourceIdentifier: 879 list.add(((ASN1String)genName.getName()).getString()); 880 break; 881 case GeneralName.registeredID: 882 list.add(ASN1ObjectIdentifier.getInstance(genName.getName()).getId()); 883 break; 884 case GeneralName.iPAddress: 885 byte[] addrBytes = DEROctetString.getInstance(genName.getName()).getOctets(); 886 final String addr; 887 try 888 { 889 addr = InetAddress.getByAddress(addrBytes).getHostAddress(); 890 } 891 catch (UnknownHostException e) 892 { 893 continue; 894 } 895 list.add(addr); 896 break; 897 default: 898 throw new IOException("Bad tag number: " + genName.getTagNo()); 899 } 900 901 temp.add(Collections.unmodifiableList(list)); 902 } 903 if (temp.size() == 0) 904 { 905 return null; 906 } 907 return Collections.unmodifiableCollection(temp); 908 } 909 catch (Exception e) 910 { 911 throw new CertificateParsingException(e.getMessage()); 912 } 913 } 914} 915