CMSSignedDataStreamGenerator.cs :  » PDF » iTextSharp » Org » BouncyCastle » Cms » 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 » Cms » CMSSignedDataStreamGenerator.cs
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.IO;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.Utilities.IO;
using Org.BouncyCastle.X509;

namespace Org.BouncyCastle.Cms{
    /**
    * General class for generating a pkcs7-signature message stream.
    * <p>
    * A simple example of usage.
    * </p>
    * <pre>
    *      IX509Store                   certs...
    *      CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
    *
    *      gen.AddSigner(privateKey, cert, CmsSignedDataStreamGenerator.DIGEST_SHA1);
    *
    *      gen.AddCertificates(certs);
    *
    *      Stream sigOut = gen.Open(bOut);
    *
    *      sigOut.Write(Encoding.UTF8.GetBytes("Hello World!"));
    *
    *      sigOut.Close();
    * </pre>
    */
    public class CmsSignedDataStreamGenerator
        : CmsSignedGenerator
    {
    private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;

    private readonly ArrayList _signerInfs = new ArrayList();
    private readonly ISet       _messageDigestOids = new HashSet();
    private readonly Hashtable _messageDigests = new Hashtable();
    private readonly Hashtable _messageHashes = new Hashtable();
    private bool _messageDigestsLocked;
        private int _bufferSize;

    private class SignerInf
        {
      private readonly CmsSignedDataStreamGenerator outer;

      private readonly AsymmetricKeyParameter    _key;
      private readonly SignerIdentifier      _signerIdentifier;
      private readonly string            _digestOID;
      private readonly string            _encOID;
      private readonly CmsAttributeTableGenerator  _sAttr;
      private readonly CmsAttributeTableGenerator  _unsAttr;

      internal SignerInf(
        CmsSignedDataStreamGenerator  outer,
        AsymmetricKeyParameter      key,
        SignerIdentifier        signerIdentifier,
        string              digestOID,
        string              encOID,
        CmsAttributeTableGenerator    sAttr,
        CmsAttributeTableGenerator    unsAttr)
      {
        this.outer = outer;

        _key = key;
        _signerIdentifier = signerIdentifier;
        _digestOID = digestOID;
        _encOID = encOID;
        _sAttr = sAttr;
        _unsAttr = unsAttr;
      }

      internal AlgorithmIdentifier DigestAlgorithmID
      {
        get { return new AlgorithmIdentifier(new DerObjectIdentifier(this._digestOID), DerNull.Instance); }
      }

      internal SignerInfo ToSignerInfo(
                DerObjectIdentifier contentType)
            {
        string digestName = Helper.GetDigestAlgName(_digestOID);
        string encName = Helper.GetEncryptionAlgName(_encOID);
        string signatureName = digestName + "with" + encName;

        AlgorithmIdentifier digAlgId = DigestAlgorithmID;

        byte[] hash = (byte[])outer._messageHashes[Helper.GetDigestAlgName(this._digestOID)];
        outer._digests[_digestOID] = hash.Clone();

        byte[] bytesToSign = hash;
        ISigner sig;

        /* RFC 3852 5.4
         * The result of the message digest calculation process depends on
         * whether the signedAttrs field is present.  When the field is absent,
         * the result is just the message digest of the content as described
         * 
         * above.  When the field is present, however, the result is the message
         * digest of the complete DER encoding of the SignedAttrs value
         * contained in the signedAttrs field.
         */
        Asn1Set signedAttr = null;
        if (_sAttr != null)
        {
          IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash);
//          Asn1.Cms.AttributeTable signed = _sAttr.GetAttributes(Collections.unmodifiableMap(parameters));
          Asn1.Cms.AttributeTable signed = _sAttr.GetAttributes(parameters);

          // TODO Handle countersignatures (see CMSSignedDataGenerator)

          signedAttr = outer.GetAttributeSet(signed);

                  // sig must be composed from the DER encoding.
          bytesToSign = signedAttr.GetEncoded(Asn1Encodable.Der);
                sig = Helper.GetSignatureInstance(signatureName);
        }
        else
        {
          // Note: Need to use raw signatures here since we have already calculated the digest
          if (encName.Equals("RSA"))
          {
            DigestInfo dInfo = new DigestInfo(digAlgId, hash);
            bytesToSign = dInfo.GetEncoded(Asn1Encodable.Der);
            sig = Helper.GetSignatureInstance("RSA");
          }
          else if (encName.Equals("DSA"))
          {
            sig = Helper.GetSignatureInstance("NONEwithDSA");
          }
          // TODO Add support for raw PSS
//          else if (encName.equals("RSAandMGF1"))
//          {
//            sig = CMSSignedHelper.INSTANCE.getSignatureInstance("NONEWITHRSAPSS", _sigProvider);
//            try
//            {
//              // Init the params this way to avoid having a 'raw' version of each PSS algorithm
//              Signature sig2 = CMSSignedHelper.INSTANCE.getSignatureInstance(signatureName, _sigProvider);
//              PSSParameterSpec spec = (PSSParameterSpec)sig2.getParameters().getParameterSpec(PSSParameterSpec.class);
//              sig.setParameter(spec);
//            }
//            catch (Exception e)
//            {
//              throw new SignatureException("algorithm: " + encName + " could not be configured.");
//            }
//          }
          else
          {
            throw new SignatureException("algorithm: " + encName + " not supported in base signatures.");
          }
        }

        sig.Init(true, new ParametersWithRandom(_key, outer.rand));
        sig.BlockUpdate(bytesToSign, 0, bytesToSign.Length);
        byte[] sigBytes = sig.GenerateSignature();

        Asn1Set unsignedAttr = null;
        if (_unsAttr != null)
        {
          IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash);
          parameters[CmsAttributeTableParameter.Signature] = sigBytes.Clone();

//          Asn1.Cms.AttributeTable unsigned = _unsAttr.getAttributes(Collections.unmodifiableMap(parameters));
          Asn1.Cms.AttributeTable unsigned = _unsAttr.GetAttributes(parameters);

          unsignedAttr = outer.GetAttributeSet(unsigned);
        }

        // TODO[RSAPSS] Need the ability to specify non-default parameters
        Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName);
        AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier(
          new DerObjectIdentifier(_encOID), sigX509Parameters);

        return new SignerInfo(_signerIdentifier, digAlgId,
          signedAttr, encAlgId, new DerOctetString(sigBytes), unsignedAttr);
            }
        }

    public CmsSignedDataStreamGenerator()
        {
        }

    /// <summary>Constructor allowing specific source of randomness</summary>
    /// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
    public CmsSignedDataStreamGenerator(
      SecureRandom rand)
      : base(rand)
    {
    }

    /**
        * Set the underlying string size for encapsulated data
        *
        * @param bufferSize length of octet strings to buffer the data.
        */
        public void SetBufferSize(
            int bufferSize)
        {
            _bufferSize = bufferSize;
        }

    public void AddDigests(
           params string[] digestOids)
    {
           AddDigests((IEnumerable) digestOids);
    }

    public void AddDigests(
      IEnumerable digestOids)
    {
      foreach (string digestOid in digestOids)
      {
        ConfigureDigest(digestOid);
      }
    }

    /**
        * add a signer - no attributes other than the default ones will be
        * provided here.
        * @throws NoSuchAlgorithmException
        * @throws InvalidKeyException
        */
        public void AddSigner(
            AsymmetricKeyParameter  privateKey,
            X509Certificate      cert,
            string          digestOid)
        {
      AddSigner(privateKey, cert, digestOid,
        new DefaultSignedAttributeTableGenerator(), null);
    }

    /**
     * add a signer, specifying the digest encryption algorithm - no attributes other than the default ones will be
     * provided here.
     * @throws NoSuchProviderException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     */
    public void AddSigner(
      AsymmetricKeyParameter  privateKey,
      X509Certificate      cert,
      string          encryptionOid,
      string          digestOid)
    {
      AddSigner(privateKey, cert, encryptionOid, digestOid,
        new DefaultSignedAttributeTableGenerator(),
        (CmsAttributeTableGenerator)null);
    }

        /**
        * add a signer with extra signed/unsigned attributes.
        * @throws NoSuchAlgorithmException
        * @throws InvalidKeyException
        */
        public void AddSigner(
            AsymmetricKeyParameter  privateKey,
            X509Certificate      cert,
            string          digestOid,
            Asn1.Cms.AttributeTable  signedAttr,
            Asn1.Cms.AttributeTable  unsignedAttr)
        {
      AddSigner(privateKey, cert, digestOid,
        new DefaultSignedAttributeTableGenerator(signedAttr),
        new SimpleAttributeTableGenerator(unsignedAttr));
    }

    /**
     * add a signer with extra signed/unsigned attributes - specifying digest
     * encryption algorithm.
     * @throws NoSuchProviderException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     */
    public void AddSigner(
      AsymmetricKeyParameter  privateKey,
      X509Certificate      cert,
      string          encryptionOid,
      string          digestOid,
      Asn1.Cms.AttributeTable  signedAttr,
      Asn1.Cms.AttributeTable  unsignedAttr)
    {
      AddSigner(privateKey, cert, encryptionOid, digestOid,
        new DefaultSignedAttributeTableGenerator(signedAttr),
        new SimpleAttributeTableGenerator(unsignedAttr));
    }

    public void AddSigner(
      AsymmetricKeyParameter    privateKey,
      X509Certificate        cert,
      string            digestOid,
      CmsAttributeTableGenerator  signedAttrGenerator,
      CmsAttributeTableGenerator  unsignedAttrGenerator)
    {
      AddSigner(privateKey, cert, GetEncOid(privateKey, digestOid), digestOid,
        signedAttrGenerator, unsignedAttrGenerator);
        }

    public void AddSigner(
      AsymmetricKeyParameter    privateKey,
      X509Certificate        cert,
      string            encryptionOid,
      string            digestOid,
      CmsAttributeTableGenerator  signedAttrGenerator,
      CmsAttributeTableGenerator  unsignedAttrGenerator)
    {
      ConfigureDigest(digestOid);

      _signerInfs.Add(new SignerInf(this, privateKey, GetSignerIdentifier(cert), digestOid, encryptionOid,
        signedAttrGenerator, unsignedAttrGenerator));
    }

    /**
    * add a signer - no attributes other than the default ones will be
    * provided here.
    * @throws NoSuchAlgorithmException
    * @throws InvalidKeyException
    */
    public void AddSigner(
      AsymmetricKeyParameter  privateKey,
      byte[]          subjectKeyID,
      string          digestOid)
    {
      AddSigner(privateKey, subjectKeyID, digestOid, new DefaultSignedAttributeTableGenerator(),
        (CmsAttributeTableGenerator)null);
    }

    /**
     * add a signer - no attributes other than the default ones will be
     * provided here.
     * @throws NoSuchProviderException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     */
    public void AddSigner(
      AsymmetricKeyParameter  privateKey,
      byte[]          subjectKeyID,
      string          encryptionOid,
      string          digestOid)
    {
      AddSigner(privateKey, subjectKeyID, encryptionOid, digestOid,
        new DefaultSignedAttributeTableGenerator(),
        (CmsAttributeTableGenerator)null);
    }

    /**
    * add a signer with extra signed/unsigned attributes.
    * @throws NoSuchAlgorithmException
    * @throws InvalidKeyException
    */
    public void AddSigner(
      AsymmetricKeyParameter  privateKey,
      byte[]          subjectKeyID,
      string          digestOid,
      Asn1.Cms.AttributeTable  signedAttr,
      Asn1.Cms.AttributeTable  unsignedAttr)
      {
          AddSigner(privateKey, subjectKeyID, digestOid,
        new DefaultSignedAttributeTableGenerator(signedAttr),
        new SimpleAttributeTableGenerator(unsignedAttr));
    }

    public void AddSigner(
      AsymmetricKeyParameter    privateKey,
      byte[]            subjectKeyID,
      string            digestOid,
      CmsAttributeTableGenerator  signedAttrGenerator,
      CmsAttributeTableGenerator  unsignedAttrGenerator)
    {
      AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOid),
        digestOid, signedAttrGenerator, unsignedAttrGenerator);
    }

    public void AddSigner(
      AsymmetricKeyParameter    privateKey,
      byte[]            subjectKeyID,
      string            encryptionOid,
      string            digestOid,
      CmsAttributeTableGenerator  signedAttrGenerator,
      CmsAttributeTableGenerator  unsignedAttrGenerator)
    {
      ConfigureDigest(digestOid);

      _signerInfs.Add(new SignerInf(this, privateKey, GetSignerIdentifier(subjectKeyID), digestOid, encryptionOid,
        signedAttrGenerator, unsignedAttrGenerator));
    }

    internal override void AddSignerCallback(
      SignerInformation si)
    {
      // FIXME If there were parameters in si.DigestAlgorithmID.Parameters, they are lost
      // NB: Would need to call FixAlgID on the DigestAlgorithmID

      // For precalculated signers, just need to register the algorithm, not configure a digest
      RegisterDigestOid(si.DigestAlgorithmID.ObjectID.Id);
    }

    /**
        * generate a signed object that for a CMS Signed Data object
        */
        public Stream Open(
            Stream outStream)
        {
            return Open(outStream, false);
        }

        /**
        * generate a signed object that for a CMS Signed Data
        * object - if encapsulate is true a copy
        * of the message will be included in the signature with the
        * default content type "data".
        */
        public Stream Open(
            Stream  outStream,
            bool  encapsulate)
        {
            return Open(outStream, Data, encapsulate);
        }

    /**
     * generate a signed object that for a CMS Signed Data
     * object using the given provider - if encapsulate is true a copy
     * of the message will be included in the signature with the
     * default content type "data". If dataOutputStream is non null the data
     * being signed will be written to the stream as it is processed.
     * @param out stream the CMS object is to be written to.
     * @param encapsulate true if data should be encapsulated.
     * @param dataOutputStream output stream to copy the data being signed to.
     */
    public Stream Open(
      Stream  outStream,
      bool  encapsulate,
      Stream  dataOutputStream)
    {
      return Open(outStream, Data, encapsulate, dataOutputStream);
    }

    /**
        * generate a signed object that for a CMS Signed Data
        * object - if encapsulate is true a copy
        * of the message will be included in the signature. The content type
        * is set according to the OID represented by the string signedContentType.
        */
        public Stream Open(
            Stream  outStream,
            string  signedContentType,
            bool  encapsulate)
        {
      return Open(outStream, signedContentType, encapsulate, null);
    }

    /**
    * generate a signed object that for a CMS Signed Data
    * object using the given provider - if encapsulate is true a copy
    * of the message will be included in the signature. The content type
    * is set according to the OID represented by the string signedContentType.
    * @param out stream the CMS object is to be written to.
    * @param signedContentType OID for data to be signed.
    * @param encapsulate true if data should be encapsulated.
    * @param dataOutputStream output stream to copy the data being signed to.
    */
    public Stream Open(
      Stream  outStream,
      string  signedContentType,
      bool  encapsulate,
      Stream  dataOutputStream)
    {
      if (outStream == null)
        throw new ArgumentNullException("outStream");
      if (!outStream.CanWrite)
        throw new ArgumentException("Expected writeable stream", "outStream");
      if (dataOutputStream != null && !dataOutputStream.CanWrite)
        throw new ArgumentException("Expected writeable stream", "dataOutputStream");

      _messageDigestsLocked = true;
      
      //
            // ContentInfo
            //
            BerSequenceGenerator sGen = new BerSequenceGenerator(outStream);

      sGen.AddObject(CmsObjectIdentifiers.SignedData);

      //
            // Signed Data
            //
            BerSequenceGenerator sigGen = new BerSequenceGenerator(
        sGen.GetRawOutputStream(), 0, true);

      sigGen.AddObject(CalculateVersion(signedContentType));

      Asn1EncodableVector digestAlgs = new Asn1EncodableVector();

      foreach (string digestOid in _messageDigestOids)
            {
        digestAlgs.Add(
                new AlgorithmIdentifier(new DerObjectIdentifier(digestOid), DerNull.Instance));
            }

            {
        byte[] tmp = new DerSet(digestAlgs).GetEncoded();
        sigGen.GetRawOutputStream().Write(tmp, 0, tmp.Length);
      }

      BerSequenceGenerator eiGen = new BerSequenceGenerator(sigGen.GetRawOutputStream());
      eiGen.AddObject(new DerObjectIdentifier(signedContentType));

          // If encapsulating, add the data as an octet string in the sequence
      Stream encapStream = encapsulate
        ?  CmsUtilities.CreateBerOctetOutputStream(eiGen.GetRawOutputStream(), 0, true, _bufferSize)
        :  null;

          // Also send the data to 'dataOutputStream' if necessary
      Stream teeStream = GetSafeTeeOutputStream(dataOutputStream, encapStream);

          // Let all the digests see the data as it is written
      Stream digStream = AttachDigestsToOutputStream(_messageDigests.Values, teeStream);

      return new CmsSignedDataOutputStream(this, digStream, signedContentType, sGen, sigGen, eiGen);
        }

    private void RegisterDigestOid(
      string digestOid)
    {
           if (_messageDigestsLocked)
           {
             if (!_messageDigestOids.Contains(digestOid))
          throw new InvalidOperationException("Cannot register new digest OIDs after the data stream is opened");
           }
           else
           {
        _messageDigestOids.Add(digestOid);
           }
    }

    private void ConfigureDigest(
      string digestOid)
    {
           RegisterDigestOid(digestOid);

           string digestName = Helper.GetDigestAlgName(digestOid);
      IDigest dig = (IDigest)_messageDigests[digestName];
      if (dig == null)
      {
        if (_messageDigestsLocked)
          throw new InvalidOperationException("Cannot configure new digests after the data stream is opened");

              dig = Helper.GetDigestInstance(digestName);
              _messageDigests[digestName] = dig;
            }
    }

    // RFC3852, section 5.1:
    // IF ((certificates is present) AND
    //    (any certificates with a type of other are present)) OR
    //    ((crls is present) AND
    //    (any crls with a type of other are present))
    // THEN version MUST be 5
    // ELSE
    //    IF (certificates is present) AND
    //       (any version 2 attribute certificates are present)
    //    THEN version MUST be 4
    //    ELSE
    //       IF ((certificates is present) AND
    //          (any version 1 attribute certificates are present)) OR
    //          (any SignerInfo structures are version 3) OR
    //          (encapContentInfo eContentType is other than id-data)
    //       THEN version MUST be 3
    //       ELSE version MUST be 1
    //
    private DerInteger CalculateVersion(
      string contentOid)
    {
      bool otherCert = false;
      bool otherCrl = false;
      bool attrCertV1Found = false;
      bool attrCertV2Found = false;

      if (_certs != null)
      {
        foreach (object obj in _certs)
        {
          if (obj is Asn1TaggedObject)
          {
            Asn1TaggedObject tagged = (Asn1TaggedObject) obj;

            if (tagged.TagNo == 1)
            {
              attrCertV1Found = true;
            }
            else if (tagged.TagNo == 2)
            {
              attrCertV2Found = true;
            }
            else if (tagged.TagNo == 3)
            {
              otherCert = true;
              break;
            }
          }
        }
      }

      if (otherCert)
      {
        return new DerInteger(5);
      }

      if (_crls != null)
      {
        foreach (object obj in _crls)
        {
          if (obj is Asn1TaggedObject)
          {
            otherCrl = true;
            break;
          }
        }
      }

      if (otherCrl)
      {
        return new DerInteger(5);
      }

      if (attrCertV2Found)
      {
        return new DerInteger(4);
      }

      if (attrCertV1Found)
      {
        return new DerInteger(3);
      }

      if (contentOid.Equals(Data)
        && !CheckForVersion3(_signers))
      {
        return new DerInteger(1);
      }

      return new DerInteger(3);
        }

    private bool CheckForVersion3(
      IList signerInfos)
    {
      foreach (SignerInformation si in signerInfos)
      {
        SignerInfo s = SignerInfo.GetInstance(si.ToSignerInfo());

        if (s.Version.Value.IntValue == 3)
        {
          return true;
        }
      }

      return false;
    }

    private static Stream AttachDigestsToOutputStream(ICollection digests, Stream s)
    {
      Stream result = s;
      foreach (IDigest digest in digests)
      {
        result = GetSafeTeeOutputStream(result, new DigOutputStream(digest));
      }
      return result;
    }

    private static Stream GetSafeOutputStream(Stream s)
    {
      if (s == null)
        return new NullOutputStream();
      return s;
    }

    private static Stream GetSafeTeeOutputStream(Stream s1, Stream s2)
    {
      if (s1 == null)
        return GetSafeOutputStream(s2);
      if (s2 == null)
        return GetSafeOutputStream(s1);
      return new TeeOutputStream(s1, s2);
    }

    private class NullOutputStream
            : BaseOutputStream
        {
            public override void WriteByte(
        byte b)
            {
                // do nothing
            }

      public override void Write(
        byte[]  buffer,
        int    offset,
        int    count)
      {
        // do nothing
      }
    }

    private class TeeOutputStream
      : BaseOutputStream
    {
      private readonly Stream s1, s2;

      public TeeOutputStream(Stream dataOutputStream, Stream digStream)
      {
        Debug.Assert(dataOutputStream.CanWrite);
        Debug.Assert(digStream.CanWrite);

        this.s1 = dataOutputStream;
        this.s2 = digStream;
      }

      public override void Write(byte[] buffer, int offset, int count)
      {
        s1.Write(buffer, offset, count);
        s2.Write(buffer, offset, count);
      }

      public override void WriteByte(byte b)
      {
        s1.WriteByte(b);
        s2.WriteByte(b);
      }

      public override void Close()
      {
        s1.Close();
        s2.Close();
      }
    }

    private class CmsSignedDataOutputStream
            : BaseOutputStream
        {
      private readonly CmsSignedDataStreamGenerator outer;

      private Stream          _out;
            private DerObjectIdentifier    _contentOID;
            private BerSequenceGenerator  _sGen;
            private BerSequenceGenerator  _sigGen;
            private BerSequenceGenerator  _eiGen;

      public CmsSignedDataOutputStream(
        CmsSignedDataStreamGenerator  outer,
        Stream              outStream,
                string              contentOID,
                BerSequenceGenerator      sGen,
                BerSequenceGenerator      sigGen,
                BerSequenceGenerator      eiGen)
            {
        this.outer = outer;

        _out = outStream;
                _contentOID = new DerObjectIdentifier(contentOID);
                _sGen = sGen;
                _sigGen = sigGen;
                _eiGen = eiGen;
            }

      public override void WriteByte(
                byte b)
            {
                _out.WriteByte(b);
            }

      public override void Write(
                byte[]  bytes,
                int    off,
                int    len)
            {
                _out.Write(bytes, off, len);
            }

      public override void Close()
            {
                _out.Close();
                _eiGen.Close();

        outer._digests.Clear();    // clear the current preserved digest state

        if (outer._certs.Count > 0)
        {
          Asn1Set certs = CmsUtilities.CreateBerSetFromList(outer._certs);

          WriteToGenerator(_sigGen, new BerTaggedObject(false, 0, certs));
        }

        if (outer._crls.Count > 0)
        {
          Asn1Set crls = CmsUtilities.CreateBerSetFromList(outer._crls);

          WriteToGenerator(_sigGen, new BerTaggedObject(false, 1, crls));
        }

        //
        // Calculate the digest hashes
        //
        foreach (DictionaryEntry de in outer._messageDigests)
        {
          outer._messageHashes.Add(de.Key, DigestUtilities.DoFinal((IDigest)de.Value));
        }

        // TODO If the digest OIDs for precalculated signers weren't mixed in with
        // the others, we could fill in outer._digests here, instead of SignerInf.ToSignerInfo

        //
                // add the precalculated SignerInfo objects.
                //
                Asn1EncodableVector signerInfos = new Asn1EncodableVector();

        foreach (SignerInformation signer in outer._signers)
        {
                    signerInfos.Add(signer.ToSignerInfo());
                }
        
        //
                // add the SignerInfo objects
                //
        foreach (SignerInf signer in outer._signerInfs)
        {
                    try
                    {
                        signerInfos.Add(signer.ToSignerInfo(_contentOID));
                    }
                    catch (IOException e)
                    {
                        throw new CmsStreamException("encoding error." + e);
                    }
          catch (InvalidKeyException e)
          {
            throw new CmsStreamException("key inappropriate for signature.", e);
          }
                    catch (SignatureException e)
                    {
                        throw new CmsStreamException("error creating signature." + e);
                    }
                    catch (CertificateEncodingException e)
                    {
                        throw new CmsStreamException("error creating sid." + e);
                    }
          catch (SecurityUtilityException e)
          {
            throw new CmsStreamException("unknown signature algorithm." + e);
          }
                }

        WriteToGenerator(_sigGen, new DerSet(signerInfos));

        _sigGen.Close();
                _sGen.Close();
        base.Close();
      }

      private static void WriteToGenerator(
        Asn1Generator  ag,
        Asn1Encodable  ae)
      {
        byte[] encoded = ae.GetEncoded();
        ag.GetRawOutputStream().Write(encoded, 0, encoded.Length);
      }
    }
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.