PkixCertPath
CertPath implementation for X.509 certificates.
            
                using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.X509;
using System;
using System.Collections.Generic;
using System.IO;
namespace Org.BouncyCastle.Pkix
{
    public class PkixCertPath
    {
        private static readonly List<string> EncodingNames = new List<string> {
            "PkiPath",
            "PEM",
            "PKCS7"
        };
        private readonly IList<X509Certificate> m_certificates;
        public virtual IEnumerable<string> Encodings => CollectionUtilities.Proxy(EncodingNames);
        public virtual IList<X509Certificate> Certificates => CollectionUtilities.ReadOnly(m_certificates);
        private static IList<X509Certificate> SortCerts(IList<X509Certificate> certs)
        {
            if (certs.Count < 2)
                return certs;
            X509Name issuerDN = certs[0].IssuerDN;
            bool flag = true;
            for (int i = 1; i != certs.Count; i++) {
                X509Certificate x509Certificate = certs[i];
                if (!issuerDN.Equivalent(x509Certificate.SubjectDN, true)) {
                    flag = false;
                    break;
                }
                issuerDN = x509Certificate.IssuerDN;
            }
            if (flag)
                return certs;
            List<X509Certificate> list = new List<X509Certificate>(certs.Count);
            List<X509Certificate> result = new List<X509Certificate>(certs);
            for (int j = 0; j < certs.Count; j++) {
                X509Certificate x509Certificate2 = certs[j];
                bool flag2 = false;
                X509Name subjectDN = x509Certificate2.SubjectDN;
                foreach (X509Certificate cert in certs) {
                    if (cert.IssuerDN.Equivalent(subjectDN, true)) {
                        flag2 = true;
                        break;
                    }
                }
                if (!flag2) {
                    list.Add(x509Certificate2);
                    certs.RemoveAt(j);
                }
            }
            if (list.Count > 1)
                return result;
            for (int k = 0; k != list.Count; k++) {
                issuerDN = list[k].IssuerDN;
                for (int l = 0; l < certs.Count; l++) {
                    X509Certificate x509Certificate3 = certs[l];
                    if (issuerDN.Equivalent(x509Certificate3.SubjectDN, true)) {
                        list.Add(x509Certificate3);
                        certs.RemoveAt(l);
                        break;
                    }
                }
            }
            if (certs.Count > 0)
                return result;
            return list;
        }
        public PkixCertPath(IList<X509Certificate> certificates)
        {
            m_certificates = SortCerts(new List<X509Certificate>(certificates));
        }
        public PkixCertPath(Stream inStream)
            : this(inStream, "PkiPath")
        {
        }
        public PkixCertPath(Stream inStream, string encoding)
        {
            IList<X509Certificate> certs = default(IList<X509Certificate>);
            try {
                if (Platform.EqualsIgnoreCase("PkiPath", encoding)) {
                    using (Asn1InputStream asn1InputStream = new Asn1InputStream(inStream, 2147483647, true)) {
                        Asn1Sequence obj = asn1InputStream.ReadObject() as Asn1Sequence;
                        if (obj == null)
                            throw new CertificateException("input stream does not contain a ASN1 SEQUENCE while reading PkiPath encoded data to load CertPath");
                        X509Certificate[] array = obj.MapElements((Asn1Encodable element) => new X509Certificate(X509CertificateStructure.GetInstance(element.ToAsn1Object())));
                        Array.Reverse((Array)array);
                        certs = new List<X509Certificate>(array);
                    }
                } else {
                    if (!Platform.EqualsIgnoreCase("PEM", encoding) && !Platform.EqualsIgnoreCase("PKCS7", encoding))
                        throw new CertificateException("unsupported encoding: " + encoding);
                    certs = new X509CertificateParser().ReadCertificates(inStream);
                }
            } catch (IOException ex) {
                throw new CertificateException("IOException throw while decoding CertPath:\n" + ex.ToString());
            }
            m_certificates = SortCerts(certs);
        }
        public override bool Equals(object obj)
        {
            if (this == obj)
                return true;
            PkixCertPath pkixCertPath = obj as PkixCertPath;
            if (pkixCertPath == null)
                return false;
            IList<X509Certificate> certificates = Certificates;
            IList<X509Certificate> certificates2 = pkixCertPath.Certificates;
            if (certificates.Count != certificates2.Count)
                return false;
            IEnumerator<X509Certificate> enumerator = certificates.GetEnumerator();
            IEnumerator<X509Certificate> enumerator2 = certificates2.GetEnumerator();
            while (enumerator.MoveNext()) {
                enumerator2.MoveNext();
                if (!object.Equals(enumerator.Current, enumerator2.Current))
                    return false;
            }
            return true;
        }
        public override int GetHashCode()
        {
            return m_certificates.GetHashCode();
        }
        public virtual byte[] GetEncoded()
        {
            return GetEncoded(EncodingNames[0]);
        }
        public virtual byte[] GetEncoded(string encoding)
        {
            if (Platform.EqualsIgnoreCase(encoding, "PkiPath")) {
                Asn1EncodableVector asn1EncodableVector = new Asn1EncodableVector(m_certificates.Count);
                for (int num = m_certificates.Count - 1; num >= 0; num--) {
                    asn1EncodableVector.Add(ToAsn1Object(m_certificates[num]));
                }
                return ToDerEncoded(new DerSequence(asn1EncodableVector));
            }
            if (Platform.EqualsIgnoreCase(encoding, "PKCS7")) {
                ContentInfo contentInfo = new ContentInfo(PkcsObjectIdentifiers.Data, null);
                Asn1EncodableVector asn1EncodableVector2 = new Asn1EncodableVector(m_certificates.Count);
                foreach (X509Certificate certificate in m_certificates) {
                    asn1EncodableVector2.Add(ToAsn1Object(certificate));
                }
                SignedData content = new SignedData(new DerInteger(1), new DerSet(), contentInfo, DerSet.FromVector(asn1EncodableVector2), null, new DerSet());
                return ToDerEncoded(new ContentInfo(PkcsObjectIdentifiers.SignedData, content));
            }
            if (Platform.EqualsIgnoreCase(encoding, "PEM")) {
                MemoryStream memoryStream = new MemoryStream();
                try {
                    using (PemWriter pemWriter = new PemWriter(new StreamWriter(memoryStream))) {
                        foreach (X509Certificate certificate2 in m_certificates) {
                            pemWriter.WriteObject(certificate2);
                        }
                    }
                } catch (Exception) {
                    throw new CertificateEncodingException("can't encode certificate for PEM encoded path");
                }
                return memoryStream.ToArray();
            }
            throw new CertificateEncodingException("unsupported encoding: " + encoding);
        }
        private Asn1Object ToAsn1Object(X509Certificate cert)
        {
            try {
                return cert.CertificateStructure.ToAsn1Object();
            } catch (Exception innerException) {
                throw new CertificateEncodingException("Exception while encoding certificate", innerException);
            }
        }
        private byte[] ToDerEncoded(Asn1Encodable obj)
        {
            try {
                return obj.GetEncoded("DER");
            } catch (IOException innerException) {
                throw new CertificateEncodingException("Exception thrown", innerException);
            }
        }
    }
}