FileDocCategorySizeDatePackage
PKIXCertPath.javaAPI DocAndroid 1.5 API12595Wed May 06 22:41:06 BST 2009org.bouncycastle.jce.provider

PKIXCertPath

public class PKIXCertPath extends CertPath
CertPath implementation for X.509 certificates.

Fields Summary
static final List
certPathEncodings
private List
certificates
Constructors Summary
PKIXCertPath(List certificates)

        super("X.509");
        this.certificates = sortCerts(new ArrayList(certificates));
    
PKIXCertPath(InputStream inStream, String encoding)
Creates a CertPath of the specified type. This constructor is protected because most users should use a CertificateFactory to create CertPaths.

        super("X.509");
        try
        {
            if (encoding.equalsIgnoreCase("PkiPath"))
            {
                ASN1InputStream derInStream = new ASN1InputStream(inStream);
                DERObject derObject = derInStream.readObject();
                if (!(derObject instanceof ASN1Sequence))
                {
                    throw new CertificateException("input stream does not contain a ASN1 SEQUENCE while reading PkiPath encoded data to load CertPath");
                }
                Enumeration e = ((ASN1Sequence)derObject).getObjects();
                InputStream certInStream;
                ByteArrayOutputStream outStream;
                DEROutputStream derOutStream;
                certificates = new ArrayList();
                CertificateFactory certFactory= CertificateFactory.getInstance("X.509", "BC");
                while (e.hasMoreElements())
                {
                    outStream = new ByteArrayOutputStream();
                    derOutStream = new DEROutputStream(outStream);
        
                    derOutStream.writeObject(e.nextElement());
                    derOutStream.close();
    
                    certInStream = new ByteArrayInputStream(outStream.toByteArray());
                    certificates.add(0,certFactory.generateCertificate(certInStream));
                }
            }
            else if (encoding.equalsIgnoreCase("PKCS7") || encoding.equalsIgnoreCase("PEM"))
            {
                // BEGIN android-modified
                inStream = new BufferedInputStream(inStream, 8192);
                // END android-modified
                certificates = new ArrayList();
                CertificateFactory certFactory= CertificateFactory.getInstance("X.509", "BC");
                Certificate cert;
                while ((cert = certFactory.generateCertificate(inStream)) != null)
                {
                    certificates.add(cert);
                }
            }
            else
            {
                throw new CertificateException("unsupported encoding: " + encoding);
            }
        }
        catch (IOException ex) 
        {
            throw new CertificateException("IOException throw while decoding CertPath:\n" + ex.toString()); 
        }
        catch (NoSuchProviderException ex) 
        {
            throw new CertificateException("BouncyCastle provider not found while trying to get a CertificateFactory:\n" + ex.toString()); 
        }
        
        this.certificates = sortCerts(certificates);
    
Methods Summary
public java.util.ListgetCertificates()
Returns the list of certificates in this certification path. The List returned must be immutable and thread-safe.

return
an immutable List of Certificates (may be empty, but not null)

        return Collections.unmodifiableList(new ArrayList(certificates));
    
public byte[]getEncoded()
Returns the encoded form of this certification path, using the default encoding.

return
the encoded bytes
exception
CertificateEncodingException if an encoding error occurs

        Iterator iter = getEncodings();
        if (iter.hasNext())
        {
            Object enc = iter.next();
            if (enc instanceof String)
            {
            return getEncoded((String)enc);
            }
        }
        return null;
    
public byte[]getEncoded(java.lang.String encoding)
Returns the encoded form of this certification path, using the specified encoding.

param
encoding the name of the encoding to use
return
the encoded bytes
exception
CertificateEncodingException if an encoding error occurs or the encoding requested is not supported

        if (encoding.equalsIgnoreCase("PkiPath"))
        {
            ASN1EncodableVector v = new ASN1EncodableVector();

            ListIterator iter = certificates.listIterator(certificates.size());
            while (iter.hasPrevious())
            {
                v.add(toASN1Object((X509Certificate)iter.previous()));
            }

            return toDEREncoded(new DERSequence(v));
        }
        else if (encoding.equalsIgnoreCase("PKCS7"))
        {
            ContentInfo encInfo = new ContentInfo(PKCSObjectIdentifiers.data, null);

            ASN1EncodableVector v = new ASN1EncodableVector();
            for (int i = 0; i != certificates.size(); i++)
            {
                v.add(toASN1Object((X509Certificate)certificates.get(i)));
            }
            
            SignedData  sd = new SignedData(
                                     new DERInteger(1),
                                     new DERSet(),
                                     encInfo, 
                                     new DERSet(v), 
                                     null, 
                                     new DERSet());

            return toDEREncoded(new ContentInfo(
                    PKCSObjectIdentifiers.signedData, sd));
        }
        // BEGIN android-removed
        // else if (encoding.equalsIgnoreCase("PEM"))
        // {
        //     ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        //     PEMWriter             pWrt = new PEMWriter(new OutputStreamWriter(bOut));
        //
        //     try
        //     {
        //         for (int i = 0; i != certificates.size(); i++)
        //         {
        //             pWrt.writeObject(certificates.get(i));
        //         }
        //     
        //         pWrt.close();
        //     }
        //     catch (Exception e)
        //     {
        //         throw new CertificateEncodingException("can't encode certificate for PEM encoded path");
        //     }
        //
        //     return bOut.toByteArray();
        // }
        // END android-removed
        else
        {
            throw new CertificateEncodingException("unsupported encoding: " + encoding);
        }
    
public java.util.IteratorgetEncodings()
Returns an iteration of the encodings supported by this certification path, with the default encoding first. Attempts to modify the returned Iterator via its remove method result in an UnsupportedOperationException.

return
an Iterator over the names of the supported encodings (as Strings)

        return certPathEncodings.iterator();
    
private java.util.ListsortCerts(java.util.List certs)

param
certs

        if (certs.size() < 2)
        {
            return certs;
        }
        
        X500Principal   issuer = ((X509Certificate)certs.get(0)).getIssuerX500Principal();
        boolean         okay = true;
        
        for (int i = 1; i != certs.size(); i++) 
        {
            X509Certificate cert = (X509Certificate)certs.get(i);
            
            if (issuer.equals(cert.getSubjectX500Principal()))
            {
                issuer = ((X509Certificate)certs.get(i)).getIssuerX500Principal();
            }
            else
            {
                okay = false;
                break;
            }
        }
        
        if (okay)
        {
            return certs;
        }
        
        // find end-entity cert
        List       retList = new ArrayList(certs.size());
        
        for (int i = 0; i < certs.size(); i++)
        {
            X509Certificate cert = (X509Certificate)certs.get(i);
            boolean         found = false;
            
            X500Principal   subject = cert.getSubjectX500Principal();
            
            for (int j = 0; j != certs.size(); j++)
            {
                X509Certificate c = (X509Certificate)certs.get(j);
                if (c.getIssuerX500Principal().equals(subject))
                {
                    found = true;
                    break;
                }
            }
            
            if (!found)
            {
                retList.add(cert);
                certs.remove(i);
            }
        }
        
        // can only have one end entity cert - something's wrong, give up.
        if (retList.size() > 1)
        {
            for (int i = 0; i != certs.size(); i++)
            {
                retList.add(certs.get(i));
            }
            
            return retList;
        }

        for (int i = 0; i != retList.size(); i++)
        {
            issuer = ((X509Certificate)retList.get(i)).getIssuerX500Principal();
            
            for (int j = 0; j < certs.size(); j++)
            {
                X509Certificate c = (X509Certificate)certs.get(j);
                if (issuer.equals(c.getSubjectX500Principal()))
                {
                    retList.add(c);
                    certs.remove(j);
                    break;
                }
            }
        }
        
        // make sure all certificates are accounted for.
        for (int i = 0; i != certs.size(); i++)
        {
            retList.add(certs.get(i));
        }
        
        return retList;
    
private org.bouncycastle.asn1.DERObjecttoASN1Object(java.security.cert.X509Certificate cert)
Return a DERObject containing the encoded certificate.

param
cert the X509Certificate object to be encoded
return
the DERObject

        try
        {
            return new ASN1InputStream(cert.getEncoded()).readObject();
        }
        catch (Exception e)
        {
            throw new CertificateEncodingException("Exception while encoding certificate: " + e.toString());
        }
    
private byte[]toDEREncoded(org.bouncycastle.asn1.ASN1Encodable obj)

        try
        {
            ByteArrayOutputStream bOut = new ByteArrayOutputStream();
            DEROutputStream       dOut = new DEROutputStream(bOut);
            
            dOut.writeObject(obj);
            dOut.close();
            
            return bOut.toByteArray();
        }
        catch (IOException e)
        {
            throw new CertificateEncodingException("Exeption thrown: " + e);
        }