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