PEMReader.cs :  » PDF » iTextSharp » Org » BouncyCastle » OpenSsl » 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 » OpenSsl » PEMReader.cs
using System;
using System.Collections;
using System.IO;
using System.Text;

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Nist;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.TeleTrust;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.X509;

namespace Org.BouncyCastle.OpenSsl{
  /**
  * Class for reading OpenSSL PEM encoded streams containing 
  * X509 certificates, PKCS8 encoded keys and PKCS7 objects.
  * <p>
  * In the case of PKCS7 objects the reader will return a CMS ContentInfo object. Keys and
  * Certificates will be returned using the appropriate java.security type.</p>
  */
  public class PemReader
  {
    private readonly TextReader reader;
    private readonly IPasswordFinder pFinder;

    public TextReader Reader
    {
      get { return reader; }
    }

    /**
    * Create a new PemReader
    *
    * @param reader the Reader
    */
    public PemReader(
      TextReader reader)
      : this(reader, null)
    {
    }

    /**
    * Create a new PemReader with a password finder
    *
    * @param reader the Reader
    * @param pFinder the password finder
    */
    public PemReader(
      TextReader    reader,
      IPasswordFinder  pFinder)
    {
      if (reader == null)
        throw new ArgumentNullException("reader");

      this.reader = reader;
      this.pFinder = pFinder;
    }

    private const string BeginString = "-----BEGIN ";

    public object ReadObject()
    {
      string line;
      while ((line = reader.ReadLine()) != null)
      {
        int startPos = line.IndexOf(BeginString);
        if (startPos == -1)
          continue;

        startPos += BeginString.Length;

        int endPos = line.IndexOf('-', startPos);
        if (endPos == -1)
          endPos = line.Length;

        string headerName = line.Substring(startPos, endPos - startPos).Trim();
        //Console.WriteLine("[" + headerName + "]");

        string endMarker = "-----END " + headerName;

        if (headerName.EndsWith(" PRIVATE KEY"))
        {
          string type = headerName.Substring(0, headerName.Length - " PRIVATE KEY".Length);
          return ReadKeyPair(type, endMarker);
        }

        switch (headerName)
        {
          case "PUBLIC KEY":
            return ReadPublicKey(endMarker);
          case "RSA PUBLIC KEY":
            return ReadRsaPublicKey(endMarker);
          case "CERTIFICATE REQUEST":
          case "NEW CERTIFICATE REQUEST":
            return ReadCertificateRequest(endMarker);
          case "CERTIFICATE":
          case "X509 CERTIFICATE":
            return ReadCertificate(endMarker);
          case "PKCS7":
            return ReadPkcs7(endMarker);
          case "X509 CRL":
            return ReadCrl(endMarker);
          case "ATTRIBUTE CERTIFICATE":
            return ReadAttributeCertificate(endMarker);
          // TODO Add back in when tests done, and return type issue resolved
          //case "EC PARAMETERS":
          //  return ReadECParameters(endMarker);
          default:
            // TODO Throw an exception for an unknown header?

            // Ignore contents
            ReadBytes(endMarker);
            break;
        }
      }

      return null;
    }

    private byte[] ReadBytes(
      string endMarker)
    {
      return ReadBytesAndFields(endMarker, null);
    }

    private byte[] ReadBytesAndFields(
      string    endMarker,
      IDictionary  fields)
    {
      StringBuilder buf = new StringBuilder();

      string line;
      while ((line = reader.ReadLine()) != null
        && line.IndexOf(endMarker) == -1)
      {
        int colonPos = line.IndexOf(':');

        if (colonPos == -1)
        {
          buf.Append(line.Trim());
        }
        else if (fields != null)
        {
          // Process field
          string fieldName = line.Substring(0, colonPos).Trim();

          if (fieldName.StartsWith("X-"))
            fieldName = fieldName.Substring(2);

          string fieldValue = line.Substring(colonPos + 1).Trim();

          // TODO Complain if field already specified?
          fields[fieldName] = fieldValue;
        }
      }

      if (line == null)
      {
        throw new IOException(endMarker + " not found");
      }

      if (buf.Length % 4 != 0)
      {
        throw new IOException("base64 data appears to be truncated");
      }

      return Base64.Decode(buf.ToString());
    }

    private AsymmetricKeyParameter ReadRsaPublicKey(
      string endMarker) 
    {
      RsaPublicKeyStructure rsaPubStructure = RsaPublicKeyStructure.GetInstance(
        Asn1Object.FromByteArray(
        ReadBytes(endMarker)));

      return new RsaKeyParameters(
        false, // not private
        rsaPubStructure.Modulus, 
        rsaPubStructure.PublicExponent);
    }

    private AsymmetricKeyParameter ReadPublicKey(
      string endMarker)
    {
      return PublicKeyFactory.CreateKey(
        ReadBytes(endMarker));
    }

    /**
    * Reads in a X509Certificate.
    *
    * @return the X509Certificate
    * @throws IOException if an I/O error occured
    */
    private X509Certificate ReadCertificate(
      string endMarker)
    {
      byte[] bytes = ReadBytes(endMarker);

      try
      {
        return new X509CertificateParser().ReadCertificate(bytes);
      }
      catch (Exception e)
      {
        throw new PemException("problem parsing cert: " + e.ToString());
      }
    }

    /**
    * Reads in a X509CRL.
    *
    * @return the X509Certificate
    * @throws IOException if an I/O error occured
    */
    private X509Crl ReadCrl(
      string endMarker)
    {
      byte[] bytes = ReadBytes(endMarker);

      try
      {
        return new X509CrlParser().ReadCrl(bytes);
      }
      catch (Exception e)
      {
        throw new PemException("problem parsing cert: " + e.ToString());
      }
    }

    /**
    * Reads in a PKCS10 certification request.
    *
    * @return the certificate request.
    * @throws IOException if an I/O error occured
    */
    private Pkcs10CertificationRequest ReadCertificateRequest(
      string endMarker)
    {
      byte[] bytes = ReadBytes(endMarker);

      try
      {
        return new Pkcs10CertificationRequest(bytes);
      }
      catch (Exception e)
      {
        throw new PemException("problem parsing cert: " + e.ToString());
      }
    }

    /**
    * Reads in a X509 Attribute Certificate.
    *
    * @return the X509 Attribute Certificate
    * @throws IOException if an I/O error occured
    */
    private IX509AttributeCertificate ReadAttributeCertificate(
      string endMarker)
    {
      byte[] bytes = ReadBytes(endMarker);

      return new X509V2AttributeCertificate(bytes);
    }

    /**
    * Reads in a PKCS7 object. This returns a ContentInfo object suitable for use with the CMS
    * API.
    *
    * @return the X509Certificate
    * @throws IOException if an I/O error occured
    */
    // TODO Consider returning Asn1.Pkcs.ContentInfo
    private Asn1.Cms.ContentInfo ReadPkcs7(
      string endMarker)
    {
      byte[] bytes = ReadBytes(endMarker);

      try
      {
        return Asn1.Cms.ContentInfo.GetInstance(
          Asn1Object.FromByteArray(bytes));
      }
      catch (Exception e)
      {
        throw new PemException("problem parsing PKCS7 object: " + e.ToString());
      }
    }

    /**
    * Read a Key Pair
    */
    private AsymmetricCipherKeyPair ReadKeyPair(
      string  type,
      string  endMarker)
    {
      //
      // extract the key
      //
      IDictionary fields = new Hashtable();
      byte[] keyBytes = ReadBytesAndFields(endMarker, fields);

      string procType = (string) fields["Proc-Type"];

      if (procType == "4,ENCRYPTED")
      {
        if (pFinder == null)
          throw new PasswordException("No password finder specified, but a password is required");

        char[] password = pFinder.GetPassword();

        if (password == null)
          throw new PasswordException("Password is null, but a password is required");

        string dekInfo = (string) fields["DEK-Info"];
        string[] tknz = dekInfo.Split(',');

        string dekAlgName = tknz[0].Trim();
        byte[] iv = Hex.Decode(tknz[1].Trim());

        keyBytes = PemUtilities.Crypt(false, keyBytes, password, dekAlgName, iv);
      }

      try
      {
        AsymmetricKeyParameter pubSpec, privSpec;
        Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(keyBytes);

        switch (type)
        {
          case "RSA":
          {
            RsaPrivateKeyStructure rsa = new RsaPrivateKeyStructure(seq);

            pubSpec = new RsaKeyParameters(false, rsa.Modulus, rsa.PublicExponent);
            privSpec = new RsaPrivateCrtKeyParameters(
              rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent,
              rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2,
              rsa.Coefficient);

            break;
          }

          case "DSA":
          {
            // TODO Create an ASN1 object somewhere for this?
            //DerInteger v = (DerInteger)seq[0];
            DerInteger p = (DerInteger)seq[1];
            DerInteger q = (DerInteger)seq[2];
            DerInteger g = (DerInteger)seq[3];
            DerInteger y = (DerInteger)seq[4];
            DerInteger x = (DerInteger)seq[5];

            DsaParameters parameters = new DsaParameters(p.Value, q.Value, g.Value);

            privSpec = new DsaPrivateKeyParameters(x.Value, parameters);
            pubSpec = new DsaPublicKeyParameters(y.Value, parameters);

            break;
          }

          case "EC":
          {
            ECPrivateKeyStructure pKey = new ECPrivateKeyStructure(seq);
            AlgorithmIdentifier algId = new AlgorithmIdentifier(
              X9ObjectIdentifiers.IdECPublicKey, pKey.GetParameters());

            PrivateKeyInfo privInfo = new PrivateKeyInfo(algId, pKey.ToAsn1Object());

            // TODO Are the keys returned here ECDSA, as Java version forces?
            privSpec = PrivateKeyFactory.CreateKey(privInfo);

            DerBitString pubKey = pKey.GetPublicKey();
            if (pubKey != null)
            {
              SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, pubKey.GetBytes());

              // TODO Are the keys returned here ECDSA, as Java version forces?
              pubSpec = PublicKeyFactory.CreateKey(pubInfo);
            }
            else
            {
              pubSpec = ECKeyPairGenerator.GetCorrespondingPublicKey(
                (ECPrivateKeyParameters)privSpec);
            }

            break;
          }

          default:
            throw new ArgumentException("Unknown key type: " + type, "type");
        }

        return new AsymmetricCipherKeyPair(pubSpec, privSpec);
      }
      catch (IOException e)
      {
        throw e;
      }
      catch (Exception e)
      {
        throw new PemException(
          "problem creating " + type + " private key: " + e.ToString());
      }
    }

    // TODO Add an equivalent class for ECNamedCurveParameterSpec?
    //private ECNamedCurveParameterSpec ReadECParameters(
    private X9ECParameters ReadECParameters(
      string endMarker)
    {
      byte[] bytes = ReadBytes(endMarker);
      DerObjectIdentifier oid = (DerObjectIdentifier) Asn1Object.FromByteArray(bytes);

      //return ECNamedCurveTable.getParameterSpec(oid.Id);
      return GetCurveParameters(oid.Id);
    }

    //private static ECDomainParameters GetCurveParameters(
    private static X9ECParameters GetCurveParameters(
      string name)
    {
      // TODO ECGost3410NamedCurves support (returns ECDomainParameters though)
      X9ECParameters ecP = X962NamedCurves.GetByName(name);

      if (ecP == null)
      {
        ecP = SecNamedCurves.GetByName(name);
        if (ecP == null)
        {
          ecP = NistNamedCurves.GetByName(name);
          if (ecP == null)
          {
            ecP = TeleTrusTNamedCurves.GetByName(name);

            if (ecP == null)
              throw new Exception("unknown curve name: " + name);
          }
        }
      }

      //return new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed());
      return ecP;
    }
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.