PkixCertPath.cs :  » PDF » iTextSharp » Org » BouncyCastle » Pkix » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » PDF » iTextSharp 
iTextSharp » Org » BouncyCastle » Pkix » PkixCertPath.cs
using System;
using System.Collections;
using System.IO;
using System.Text;

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Cms;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;

namespace Org.BouncyCastle.Pkix{
  /**
   * An immutable sequence of certificates (a certification path).<br />
   * <br />
   * This is an abstract class that defines the methods common to all CertPaths.
   * Subclasses can handle different kinds of certificates (X.509, PGP, etc.).<br />
   * <br />
   * All CertPath objects have a type, a list of Certificates, and one or more
   * supported encodings. Because the CertPath class is immutable, a CertPath
   * cannot change in any externally visible way after being constructed. This
   * stipulation applies to all public fields and methods of this class and any
   * added or overridden by subclasses.<br />
   * <br />
   * The type is a string that identifies the type of Certificates in the
   * certification path. For each certificate cert in a certification path
   * certPath, cert.getType().equals(certPath.getType()) must be true.<br />
   * <br />
   * The list of Certificates is an ordered List of zero or more Certificates.
   * This List and all of the Certificates contained in it must be immutable.<br />
   * <br />
   * Each CertPath object must support one or more encodings so that the object
   * can be translated into a byte array for storage or transmission to other
   * parties. Preferably, these encodings should be well-documented standards
   * (such as PKCS#7). One of the encodings supported by a CertPath is considered
   * the default encoding. This encoding is used if no encoding is explicitly
   * requested (for the {@link #getEncoded()} method, for instance).<br />
   * <br />
   * All CertPath objects are also Serializable. CertPath objects are resolved
   * into an alternate {@link CertPathRep} object during serialization. This
   * allows a CertPath object to be serialized into an equivalent representation
   * regardless of its underlying implementation.<br />
   * <br />
   * CertPath objects can be created with a CertificateFactory or they can be
   * returned by other classes, such as a CertPathBuilder.<br />
   * <br />
   * By convention, X.509 CertPaths (consisting of X509Certificates), are ordered
   * starting with the target certificate and ending with a certificate issued by
   * the trust anchor. That is, the issuer of one certificate is the subject of
   * the following one. The certificate representing the
   * {@link TrustAnchor TrustAnchor} should not be included in the certification
   * path. Unvalidated X.509 CertPaths may not follow these conventions. PKIX
   * CertPathValidators will detect any departure from these conventions that
   * cause the certification path to be invalid and throw a
   * CertPathValidatorException.<br />
   * <br />
   * <strong>Concurrent Access</strong><br />
   * <br />
   * All CertPath objects must be thread-safe. That is, multiple threads may
   * concurrently invoke the methods defined in this class on a single CertPath
   * object (or more than one) with no ill effects. This is also true for the List
   * returned by CertPath.getCertificates.<br />
   * <br />
   * Requiring CertPath objects to be immutable and thread-safe allows them to be
   * passed around to various pieces of code without worrying about coordinating
   * access. Providing this thread-safety is generally not difficult, since the
   * CertPath and List objects in question are immutable.
   * 
   * @see CertificateFactory
   * @see CertPathBuilder
   */
  /// <summary>
  /// CertPath implementation for X.509 certificates.
  /// </summary>
  public class PkixCertPath
//    : CertPath
  {
    internal static readonly IList certPathEncodings;

        static PkixCertPath()
        {
            ArrayList encodings = new ArrayList();
            encodings.Add("PkiPath");
            encodings.Add("PEM");
            encodings.Add("PKCS7");
            certPathEncodings = encodings;
        }

    private IList certificates = new ArrayList();

    /**
     * @param certs
     */
    private static IList SortCerts(
      IList certs)
    {
      if (certs.Count < 2)
        return certs;

      X509Name issuer = ((X509Certificate)certs[0]).IssuerDN;
      bool okay = true;

      for (int i = 1; i != certs.Count; i++) 
      {
        X509Certificate cert = (X509Certificate)certs[i];

        if (issuer.Equivalent(cert.SubjectDN, true))
        {
          issuer = ((X509Certificate)certs[i]).IssuerDN;
        }
        else
        {
          okay = false;
          break;
        }
      }

      if (okay)
        return certs;

      // find end-entity cert
      IList retList = new ArrayList(certs.Count);
      IList orig = new ArrayList(certs);

      for (int i = 0; i < certs.Count; i++)
      {
        X509Certificate cert = (X509Certificate)certs[i];
        bool           found = false;

        X509Name subject = cert.SubjectDN;
        foreach (X509Certificate c in certs)
        {
          if (c.IssuerDN.Equivalent(subject, true))
          {
            found = true;
            break;
          }
        }

        if (!found)
        {
          retList.Add(cert);
          certs.RemoveAt(i);
        }
      }

      // can only have one end entity cert - something's wrong, give up.
      if (retList.Count > 1)
        return orig;

      for (int i = 0; i != retList.Count; i++)
      {
        issuer = ((X509Certificate)retList[i]).IssuerDN;

        for (int j = 0; j < certs.Count; j++)
        {
          X509Certificate c = (X509Certificate)certs[j];
          if (issuer.Equivalent(c.SubjectDN, true))
          {
            retList.Add(c);
            certs.RemoveAt(j);
            break;
          }
        }
      }

      // make sure all certificates are accounted for.
      if (certs.Count > 0)
        return orig;

      return retList;
    }

    /**
     * Creates a CertPath of the specified type.
     * This constructor is protected because most users should use
     * a CertificateFactory to create CertPaths.
     * @param type the standard name of the type of Certificatesin this path
     **/
    public PkixCertPath(
      ICollection certificates)
//      : base("X.509")
    {
      this.certificates = SortCerts(new ArrayList(certificates));
    }

    public PkixCertPath(
      Stream inStream)
      : this(inStream, "PkiPath")
    {
    }

    /**
     * Creates a CertPath of the specified type.
     * This constructor is protected because most users should use
     * a CertificateFactory to create CertPaths.
     *
     * @param type the standard name of the type of Certificatesin this path
     **/
    public PkixCertPath(
      Stream  inStream,
      String  encoding)
//      : base("X.509")
    {
      try
      {
        if (encoding.ToUpper().Equals("PkiPath".ToUpper()))
        {
          Asn1InputStream derInStream = new Asn1InputStream(inStream);
          Asn1Object derObject = derInStream.ReadObject();
          if (!(derObject is Asn1Sequence))
          {
            throw new CertificateException(
              "input stream does not contain a ASN1 SEQUENCE while reading PkiPath encoded data to load CertPath");
          }
          IEnumerator e = ((Asn1Sequence)derObject).GetEnumerator();
          Stream certInStream;
          MemoryStream outStream;
          DerOutputStream derOutStream;
          certificates = new ArrayList();

          while (e.MoveNext())
          {
            outStream = new MemoryStream();
            derOutStream = new DerOutputStream(outStream);

            derOutStream.WriteObject((Asn1Encodable)e.Current);
            derOutStream.Close();

            certInStream = new MemoryStream(outStream.ToArray(), false);
            certificates.Insert(0, new X509CertificateParser().ReadCertificate(certInStream));
          }
        }
        else if (encoding.ToUpper().Equals("PKCS7")
          || encoding.ToUpper().Equals("PEM"))
        {
          certificates = new ArrayList();

          X509CertificateParser certParser = new X509CertificateParser();
          X509Certificate cert = null;

          while ((cert = certParser.ReadCertificate(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());
      }

      this.certificates = SortCerts(certificates);
    }
    
    /**
     * 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)
     **/
    public virtual IEnumerable Encodings
    {
            get { return new EnumerableProxy(certPathEncodings); }
    }

    /**
    * Compares this certification path for equality with the specified object.
    * Two CertPaths are equal if and only if their types are equal and their
    * certificate Lists (and by implication the Certificates in those Lists)
    * are equal. A CertPath is never equal to an object that is not a CertPath.<br />
    * <br />
    * This algorithm is implemented by this method. If it is overridden, the
    * behavior specified here must be maintained.
    * 
    * @param other
    *            the object to test for equality with this certification path
    * 
    * @return true if the specified object is equal to this certification path,
    *         false otherwise
    * 
    * @see Object#hashCode() Object.hashCode()
    */
    public override bool Equals(
      object obj)
    {
      if (this == obj)
        return true;

      PkixCertPath other = obj as PkixCertPath;
      if (other == null)
        return false;

//      if (!this.Type.Equals(other.Type))
//        return false;

      //return this.Certificates.Equals(other.Certificates);

      // TODO Extract this to a utility class
      IList thisCerts = this.Certificates;
      IList otherCerts = other.Certificates;

      if (thisCerts.Count != otherCerts.Count)
        return false;

      IEnumerator e1 = thisCerts.GetEnumerator();
      IEnumerator e2 = thisCerts.GetEnumerator();

      while (e1.MoveNext())
      {
        e2.MoveNext();

        if (!Platform.Equals(e1.Current, e2.Current))
          return false;
      }

      return true;
    }

    public override int GetHashCode()
    {
      // FIXME?
      return this.Certificates.GetHashCode();
    }

    /**
     * Returns the encoded form of this certification path, using
     * the default encoding.
     *
     * @return the encoded bytes
     * @exception CertificateEncodingException if an encoding error occurs
     **/
    public virtual byte[] GetEncoded()
    {
      foreach (object enc in Encodings)
      {
        if (enc is string)
        {
          return GetEncoded((string)enc);
        }
      }
      return null;
    }

    /**
     * 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
     *
     */
    public virtual byte[] GetEncoded(
      string encoding)
    {
            if (String.Compare(encoding, "PkiPath", true) == 0)
      {
        Asn1EncodableVector v = new Asn1EncodableVector();

        for (int i = certificates.Count - 1; i >= 0; i--) 
        {
          v.Add(ToAsn1Object((X509Certificate) certificates[i]));
        }

        return ToDerEncoded(new DerSequence(v));
      }
      else if (String.Compare(encoding, "PKCS7", true) == 0)
      {
        Asn1.Pkcs.ContentInfo encInfo = new Asn1.Pkcs.ContentInfo(
          PkcsObjectIdentifiers.Data, null);

        Asn1EncodableVector v = new Asn1EncodableVector();
        for (int i = 0; i != certificates.Count; i++)
        {
          v.Add(ToAsn1Object((X509Certificate)certificates[i]));
        }

        Asn1.Pkcs.SignedData sd = new Asn1.Pkcs.SignedData(
          new DerInteger(1),
          new DerSet(),
          encInfo,
          new DerSet(v),
          null,
          new DerSet());

        return ToDerEncoded(new Asn1.Pkcs.ContentInfo(PkcsObjectIdentifiers.SignedData, sd));
      }
      else if (String.Compare(encoding, "PEM", true) == 0)
      {
        MemoryStream bOut = new MemoryStream();
        PemWriter pWrt = new PemWriter(new StreamWriter(bOut));

        try
        {
          for (int i = 0; i != certificates.Count; i++)
          {
            pWrt.WriteObject(certificates[i]);
          }

          pWrt.Writer.Close();
        }
        catch (Exception)
        {
          throw new CertificateEncodingException("can't encode certificate for PEM encoded path");
        }

        return bOut.ToArray();
      }
      else
      {
        throw new CertificateEncodingException("unsupported encoding: " + encoding);
      }
    }

    /// <summary>
    /// Returns the list of certificates in this certification
    /// path.
    /// </summary>
    public virtual IList Certificates
    {
      get { return new ArrayList(certificates); }    
    }

    /**
     * Return a DERObject containing the encoded certificate.
     *
     * @param cert the X509Certificate object to be encoded
     *
     * @return the DERObject
     **/
    private Asn1Object ToAsn1Object(
      X509Certificate cert)
    {
      try
      {
        return Asn1Object.FromByteArray(cert.GetEncoded());
      }
      catch (Exception e)
      {
        throw new CertificateEncodingException("Exception while encoding certificate", e);
      }
    }

    private byte[] ToDerEncoded(Asn1Encodable obj) 
    {
      try
      {
        return obj.GetEncoded(Asn1Encodable.Der);
      }
      catch (IOException e)
      {
        throw new CertificateEncodingException("Exception thrown", e);
      }
    }
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.