protected override void Dispose(bool disposing)
            {
                try
                {
                    if (!disposing)
                    {
                        return;
                    }

                    _out.Dispose();

                    // TODO Parent context(s) should really be be closed explicitly

                    _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 SignerInfoGenerator.Generate

                    //
                    // collect all the SignerInfo objects
                    //
                    var signerInfos = new Asn1EncodableVector();

                    //
                    // add the generated SignerInfo objects
                    //
                    {
                        foreach (DigestAndSignerInfoGeneratorHolder holder in _outer._signerInfs)
                        {
                            AlgorithmIdentifier digestAlgorithm = holder.DigestAlgorithm;

                            var calculatedDigest = (byte[])_outer._messageHashes[Helper.GetDigestAlgName(holder.DigestOID)];
                            _outer._digests[holder.DigestOID] = calculatedDigest.Clone();

                            signerInfos.Add(holder.SignerInf.Generate(_contentOID, digestAlgorithm, calculatedDigest));
                        }
                    }

                    //
                    // add the precalculated SignerInfo objects.
                    //
                    {
                        foreach (SignerInformation signer in _outer._signers)
                        {
                            // TODO Verify the content type and calculated digest match the precalculated SignerInfo
                            //						if (!signer.ContentType.Equals(_contentOID))
                            //						{
                            //							// TODO The precalculated content type did not match - error?
                            //						}
                            //
                            //						byte[] calculatedDigest = (byte[])outer._digests[signer.DigestAlgOid];
                            //						if (calculatedDigest == null)
                            //						{
                            //							// TODO We can't confirm this digest because we didn't calculate it - error?
                            //						}
                            //						else
                            //						{
                            //							if (!Arrays.AreEqual(signer.GetContentDigest(), calculatedDigest))
                            //							{
                            //								// TODO The precalculated digest did not match - error?
                            //							}
                            //						}

                            signerInfos.Add(signer.ToSignerInfo());
                        }
                    }

                    WriteToGenerator(_sigGen, new DerSet(signerInfos));

                    _sigGen.Close();
                    _sGen.Close();
                }
                finally
                {
                    base.Dispose(disposing);
                }
            }
Ejemplo n.º 2
0
        /**
         * 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 CmsSignedData Generate(string signedContentType, // FIXME Avoid accessing more than once to support CmsProcessableInputStream
                                      CmsProcessable content, bool encapsulate)
        {
            var digestAlgs  = new Asn1EncodableVector();
            var signerInfos = new Asn1EncodableVector();

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

            //
            // add the precalculated SignerInfo objects.
            //
            foreach (SignerInformation signer in _signers)
            {
                digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));

                // TODO Verify the content type and calculated digest match the precalculated SignerInfo
                signerInfos.Add(signer.ToSignerInfo());
            }

            //
            // add the SignerInfo objects
            //
            bool isCounterSignature = (signedContentType == null);

            DerObjectIdentifier contentTypeOid = isCounterSignature ? null : new DerObjectIdentifier(signedContentType);

            foreach (SignerInf signer in _signerInfs)
            {
                try
                {
                    digestAlgs.Add(signer.DigestAlgorithmID);
                    signerInfos.Add(signer.ToSignerInfo(contentTypeOid, content, rand));
                }
                catch (IOException e)
                {
                    throw new CmsException("encoding error.", e);
                }
                catch (InvalidKeyException e)
                {
                    throw new CmsException("key inappropriate for signature.", e);
                }
                catch (SignatureException e)
                {
                    throw new CmsException("error creating signature.", e);
                }
                catch (CertificateEncodingException e)
                {
                    throw new CmsException("error creating sid.", e);
                }
            }

            Asn1Set certificates = null;

            if (_certs.Count != 0)
            {
                certificates = CmsUtilities.CreateBerSetFromList(_certs);
            }

            Asn1Set certrevlist = null;

            if (_crls.Count != 0)
            {
                certrevlist = CmsUtilities.CreateBerSetFromList(_crls);
            }

            Asn1OctetString octs = null;

            if (encapsulate)
            {
                var bOut = new MemoryStream();
                if (content != null)
                {
                    try
                    {
                        content.Write(bOut);
                    }
                    catch (IOException e)
                    {
                        throw new CmsException("encapsulation error.", e);
                    }
                }
                octs = new BerOctetString(bOut.ToArray());
            }

            var encInfo = new ContentInfo(contentTypeOid, octs);

            var sd = new SignedData(new DerSet(digestAlgs), encInfo, certificates, certrevlist, new DerSet(signerInfos));

            var contentInfo = new ContentInfo(CmsObjectIdentifiers.SignedData, sd);

            return(new CmsSignedData(content, contentInfo));
        }
Ejemplo n.º 3
0
        /**
         * Replace the certificate and CRL information associated with this
         * CmsSignedData object with the new one passed in.
         *
         * @param signedData the signed data object to be used as a base.
         * @param x509Certs the new certificates to be used.
         * @param x509Crls the new CRLs to be used.
         * @return a new signed data object.
         * @exception CmsException if there is an error processing the stores
         */
        public static CmsSignedData ReplaceCertificatesAndCrls(
            CmsSignedData signedData,
            IX509Store x509Certs,
            IX509Store x509Crls,
            IX509Store x509AttrCerts)
        {
            if (x509AttrCerts != null)
            {
                throw Platform.CreateNotImplementedException("Currently can't replace attribute certificates");
            }

            //
            // copy
            //
            CmsSignedData cms = new CmsSignedData(signedData);

            //
            // replace the certs and crls in the SignedData object
            //
            Asn1Set certs = null;

            try
            {
                Asn1Set asn1Set = CmsUtilities.CreateBerSetFromList(
                    CmsUtilities.GetCertificatesFromStore(x509Certs));

                if (asn1Set.Count != 0)
                {
                    certs = asn1Set;
                }
            }
            catch (X509StoreException e)
            {
                throw new CmsException("error getting certificates from store", e);
            }

            Asn1Set crls = null;

            try
            {
                Asn1Set asn1Set = CmsUtilities.CreateBerSetFromList(
                    CmsUtilities.GetCrlsFromStore(x509Crls));

                if (asn1Set.Count != 0)
                {
                    crls = asn1Set;
                }
            }
            catch (X509StoreException e)
            {
                throw new CmsException("error getting CRLs from store", e);
            }

            //
            // replace the CMS structure.
            //
            SignedData old = signedData.signedData;

            cms.signedData = new SignedData(
                old.DigestAlgorithms,
                old.EncapContentInfo,
                certs,
                crls,
                old.SignerInfos);

            //
            // replace the contentInfo with the new one
            //
            cms.contentInfo = new ContentInfo(cms.contentInfo.ContentType, cms.signedData);

            return(cms);
        }