public SignerInfo Generate(DerObjectIdentifier contentType)
        {
            try
            {
                /* 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;

                AlgorithmIdentifier digestEncryptionAlgorithm = sigEncAlgFinder.FindEncryptionAlgorithm(signer.AlgorithmDetails);

                AlgorithmIdentifier digestAlg = null;

                if (signedGen != null)
                {
                    digestAlg = digester.AlgorithmDetails;

                    digestCalculator.Stream.Close();
                    calculatedDigest = digestCalculator.GetResult().Collect();

                    IDictionary <string, object> parameters = getBaseParameters(contentType, digester.AlgorithmDetails, digestEncryptionAlgorithm, calculatedDigest);
                    Asn1.Cms.AttributeTable      signed     = signedGen.GetAttributes(parameters);

                    signedAttr = getAttributeSet(signed);

                    // sig must be composed from the DER encoding.
                    Stream sOut = signerCalculator.Stream;
                    byte[] data = signedAttr.GetEncoded(Asn1Encodable.Der);

                    sOut.Write(data, 0, data.Length);
                }
                else
                {
                    if (digester != null)
                    {
                        digestAlg = digester.AlgorithmDetails;

                        digestCalculator.Stream.Close();
                        calculatedDigest = digestCalculator.GetResult().Collect();
                    }
                    else
                    {
                        digestAlg        = digAlgFinder.Find(signer.AlgorithmDetails);
                        calculatedDigest = null;
                    }
                }

                signerCalculator.Stream.Close();

                byte[] sigBytes = signerCalculator.GetResult().Collect();

                Asn1Set unsignedAttr = null;
                if (unsignedGen != null)
                {
                    IDictionary <string, object> parameters = getBaseParameters(contentType, digestAlg, digestEncryptionAlgorithm, calculatedDigest);
                    parameters.Add(CmsAttributeTableParameter.Signature, Arrays.Clone(sigBytes));

                    Asn1.Cms.AttributeTable unsigned = unsignedGen.GetAttributes(parameters);

                    unsignedAttr = getAttributeSet(unsigned);
                }

                return(new SignerInfo(sigId, digestAlg,
                                      signedAttr, digestEncryptionAlgorithm, new DerOctetString(sigBytes), unsignedAttr));
            }
            catch (IOException e)
            {
                throw new CmsException("encoding error.", e);
            }
        }