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