Example #1
0
 internal protected virtual Asn1Set GetAttributeSet(
     AttributeTable attr)
 {
     return(attr == null
         ? null
         : new DerSet(attr.ToAsn1EncodableVector()));
 }
Example #2
0
        /**
         * return a table of the unauthenticated attributes indexed by
         * the OID of the attribute.
         * @exception java.io.IOException
         */
        public AttributeTable GetUnauthAttrs()
        {
            if (unauthAttrs == null && unauthAttrNotRead)
            {
                Asn1SetParser s = authData.GetUnauthAttrs();

                unauthAttrNotRead = false;

                if (s != null)
                {
                    Asn1EncodableVector v = new Asn1EncodableVector();

                    IAsn1Convertible o;
                    while ((o = s.ReadObject()) != null)
                    {
                        Asn1SequenceParser seq = (Asn1SequenceParser)o;

                        v.Add(seq.ToAsn1Object());
                    }

                    unauthAttrs = new AttributeTable(new DerSet(v));
                }
            }

            return(unauthAttrs);
        }
Example #3
0
        /**
         * return a table of the unprotected attributes indexed by
         * the OID of the attribute.
         * @throws IOException
         */
        public AttributeTable GetUnprotectedAttributes()
        {
            if (_unprotectedAttributes == null && _attrNotRead)
            {
                Asn1SetParser asn1Set = this.envelopedData.GetUnprotectedAttrs();

                _attrNotRead = false;

                if (asn1Set != null)
                {
                    Asn1EncodableVector v = new Asn1EncodableVector();
                    IAsn1Convertible    o;

                    while ((o = asn1Set.ReadObject()) != null)
                    {
                        Asn1SequenceParser seq = (Asn1SequenceParser)o;

                        v.Add(seq.ToAsn1Object());
                    }

                    _unprotectedAttributes = new AttributeTable(new DerSet(v));
                }
            }

            return(_unprotectedAttributes);
        }
Example #4
0
        /**
         * Return a new table with the passed in attribute added.
         *
         * @param attrType
         * @param attrValue
         * @return
         */
        public AttributeTable Add(DerObjectIdentifier attrType, Asn1Encodable attrValue)
        {
            AttributeTable newTable = new AttributeTable(attributes);

            newTable.AddAttribute(new Attribute(attrType, new DerSet(attrValue)));

            return(newTable);
        }
Example #5
0
        public AttributeTable Remove(DerObjectIdentifier attrType)
        {
            AttributeTable newTable = new AttributeTable(attributes);

            newTable.attributes.Remove(attrType);

            return(newTable);
        }
 /**
  * add a signer with extra signed/unsigned attributes.
  *
  * @param key signing key to use
  * @param cert certificate containing corresponding public key
  * @param digestOID digest algorithm OID
  * @param signedAttr table of attributes to be included in signature
  * @param unsignedAttr table of attributes to be included as unsigned
  */
 public void AddSigner(
     AsymmetricKeyParameter privateKey,
     X509Certificate cert,
     string digestOID,
     AttributeTable signedAttr,
     AttributeTable unsignedAttr)
 {
     AddSigner(privateKey, cert, Helper.GetEncOid(privateKey, digestOID), digestOID,
               signedAttr, unsignedAttr);
 }
 /**
  * add a signer with extra signed/unsigned attributes.
  *
  * @param key signing key to use
  * @param subjectKeyID subjectKeyID of corresponding public key
  * @param digestOID digest algorithm OID
  * @param signedAttr table of attributes to be included in signature
  * @param unsignedAttr table of attributes to be included as unsigned
  */
 public void AddSigner(
     AsymmetricKeyParameter privateKey,
     byte[]                                  subjectKeyID,
     string digestOID,
     AttributeTable signedAttr,
     AttributeTable unsignedAttr)
 {
     AddSigner(privateKey, subjectKeyID, Helper.GetEncOid(privateKey, digestOID), digestOID,
               signedAttr, unsignedAttr);
 }
Example #8
0
 /**
  * add a signer with extra signed/unsigned attributes.
  * @throws NoSuchAlgorithmException
  * @throws InvalidKeyException
  */
 public void AddSigner(
     AsymmetricKeyParameter privateKey,
     byte[]                                  subjectKeyID,
     string digestOid,
     AttributeTable signedAttr,
     AttributeTable unsignedAttr)
 {
     AddSigner(privateKey, subjectKeyID, digestOid,
               new DefaultSignedAttributeTableGenerator(signedAttr),
               new SimpleAttributeTableGenerator(unsignedAttr));
 }
Example #9
0
 /**
  * add a signer with extra signed/unsigned attributes.
  * @throws NoSuchAlgorithmException
  * @throws InvalidKeyException
  */
 public void AddSigner(
     AsymmetricKeyParameter privateKey,
     X509Certificate cert,
     string digestOid,
     AttributeTable signedAttr,
     AttributeTable unsignedAttr)
 {
     AddSigner(privateKey, cert, digestOid,
               new DefaultSignedAttributeTableGenerator(signedAttr),
               new SimpleAttributeTableGenerator(unsignedAttr));
 }
 private void doAddSigner(
     AsymmetricKeyParameter privateKey,
     SignerIdentifier signerIdentifier,
     string encryptionOID,
     string digestOID,
     CmsAttributeTableGenerator signedAttrGen,
     CmsAttributeTableGenerator unsignedAttrGen,
     AttributeTable baseSignedTable)
 {
     signerInfs.Add(new SignerInf(this, privateKey, signerIdentifier, digestOID, encryptionOID,
                                  signedAttrGen, unsignedAttrGen, baseSignedTable));
 }
 /**
  * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
  *
  * @param key signing key to use
  * @param subjectKeyID subjectKeyID of corresponding public key
  * @param encryptionOID digest encryption algorithm OID
  * @param digestOID digest algorithm OID
  * @param signedAttr table of attributes to be included in signature
  * @param unsignedAttr table of attributes to be included as unsigned
  */
 public void AddSigner(
     AsymmetricKeyParameter privateKey,
     byte[]                                  subjectKeyID,
     string encryptionOID,
     string digestOID,
     AttributeTable signedAttr,
     AttributeTable unsignedAttr)
 {
     doAddSigner(privateKey, GetSignerIdentifier(subjectKeyID), encryptionOID, digestOID,
                 new DefaultSignedAttributeTableGenerator(signedAttr),
                 new SimpleAttributeTableGenerator(unsignedAttr),
                 signedAttr);
 }
 internal SignerInf(
     CmsSignedGenerator outer,
     ISignatureFactory sigCalc,
     SignerIdentifier signerIdentifier,
     CmsAttributeTableGenerator sAttr,
     CmsAttributeTableGenerator unsAttr,
     AttributeTable baseSignedTable)
 {
     this.outer            = outer;
     this.sigCalc          = sigCalc;
     this.signerIdentifier = signerIdentifier;
     this.digestOID        = new DefaultDigestAlgorithmIdentifierFinder().find((AlgorithmIdentifier)sigCalc.AlgorithmDetails).Algorithm.Id;
     this.encOID           = ((AlgorithmIdentifier)sigCalc.AlgorithmDetails).Algorithm.Id;
     this.sAttr            = sAttr;
     this.unsAttr          = unsAttr;
     this.baseSignedTable  = baseSignedTable;
 }
Example #13
0
        private Asn1Object GetSingleValuedSignedAttribute(
            DerObjectIdentifier attrOID, string printableName)
        {
            AttributeTable unsignedAttrTable = this.UnsignedAttributes;

            if (unsignedAttrTable != null &&
                unsignedAttrTable.GetAll(attrOID).Count > 0)
            {
                throw new CmsException("The " + printableName
                                       + " attribute MUST NOT be an unsigned attribute");
            }

            AttributeTable signedAttrTable = this.SignedAttributes;

            if (signedAttrTable == null)
            {
                return(null);
            }

            Asn1EncodableVector v = signedAttrTable.GetAll(attrOID);

            switch (v.Count)
            {
            case 0:
                return(null);

            case 1:
                Attribute t          = (Attribute)v[0];
                Asn1Set   attrValues = t.AttrValues;

                if (attrValues.Count != 1)
                {
                    throw new CmsException("A " + printableName
                                           + " attribute MUST have a single attribute value");
                }

                return(attrValues[0].ToAsn1Object());

            default:
                throw new CmsException("The SignedAttributes in a signerInfo MUST NOT include multiple instances of the "
                                       + printableName + " attribute");
            }
        }
            public override void Close()
            {
                Platform.Dispose(_out);

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

                _eiGen.Close();

                if (_outer.unprotectedAttributeGenerator != null)
                {
                    AttributeTable attrTable = _outer.unprotectedAttributeGenerator.GetAttributes(Platform.CreateHashtable());

                    Asn1Set unprotectedAttrs = new BerSet(attrTable.ToAsn1EncodableVector());

                    _envGen.AddObject(new DerTaggedObject(false, 1, unprotectedAttrs));
                }

                _envGen.Close();
                _cGen.Close();
                base.Close();
            }
Example #15
0
        /**
         * Return a signer information object with passed in SignerInformationStore representing counter
         * signatures attached as an unsigned attribute.
         *
         * @param signerInformation the signerInfo to be used as the basis.
         * @param counterSigners signer info objects carrying counter signature.
         * @return a copy of the original SignerInformationObject with the changed attributes.
         */
        public static SignerInformation AddCounterSigners(
            SignerInformation signerInformation,
            SignerInformationStore counterSigners)
        {
            // TODO Perform checks from RFC 3852 11.4

            SignerInfo          sInfo        = signerInformation.info;
            AttributeTable      unsignedAttr = signerInformation.UnsignedAttributes;
            Asn1EncodableVector v;

            if (unsignedAttr != null)
            {
                v = unsignedAttr.ToAsn1EncodableVector();
            }
            else
            {
                v = new Asn1EncodableVector();
            }

            Asn1EncodableVector sigs = new Asn1EncodableVector();

            foreach (SignerInformation sigInf in counterSigners.GetSigners())
            {
                sigs.Add(sigInf.ToSignerInfo());
            }

            v.Add(new Attribute(CmsAttributes.CounterSignature, new DerSet(sigs)));

            return(new SignerInformation(
                       new SignerInfo(
                           sInfo.SignerID,
                           sInfo.DigestAlgorithm,
                           sInfo.AuthenticatedAttributes,
                           sInfo.DigestEncryptionAlgorithm,
                           sInfo.EncryptedDigest,
                           new DerSet(v)),
                       signerInformation.contentType,
                       signerInformation.content,
                       null));
        }
            internal SignerInf(
                CmsSignedGenerator outer,
                AsymmetricKeyParameter key,
                SignerIdentifier signerIdentifier,
                string digestOID,
                string encOID,
                CmsAttributeTableGenerator sAttr,
                CmsAttributeTableGenerator unsAttr,
                AttributeTable baseSignedTable)
            {
                string digestName = Helper.GetDigestAlgName(digestOID);

                string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);

                this.outer            = outer;
                this.sigCalc          = new Asn1SignatureFactory(signatureName, key);
                this.signerIdentifier = signerIdentifier;
                this.digestOID        = digestOID;
                this.encOID           = encOID;
                this.sAttr            = sAttr;
                this.unsAttr          = unsAttr;
                this.baseSignedTable  = baseSignedTable;
            }
Example #17
0
        /**
         * Return a signer information object with the passed in unsigned
         * attributes replacing the ones that are current associated with
         * the object passed in.
         *
         * @param signerInformation the signerInfo to be used as the basis.
         * @param unsignedAttributes the unsigned attributes to add.
         * @return a copy of the original SignerInformationObject with the changed attributes.
         */
        public static SignerInformation ReplaceUnsignedAttributes(
            SignerInformation signerInformation,
            AttributeTable unsignedAttributes)
        {
            SignerInfo sInfo        = signerInformation.info;
            Asn1Set    unsignedAttr = null;

            if (unsignedAttributes != null)
            {
                unsignedAttr = new DerSet(unsignedAttributes.ToAsn1EncodableVector());
            }

            return(new SignerInformation(
                       new SignerInfo(
                           sInfo.SignerID,
                           sInfo.DigestAlgorithm,
                           sInfo.AuthenticatedAttributes,
                           sInfo.DigestEncryptionAlgorithm,
                           sInfo.EncryptedDigest,
                           unsignedAttr),
                       signerInformation.contentType,
                       signerInformation.content,
                       null));
        }
Example #18
0
        /**
         * Return a SignerInformationStore containing the counter signatures attached to this
         * signer. If no counter signatures are present an empty store is returned.
         */
        public SignerInformationStore GetCounterSignatures()
        {
            // TODO There are several checks implied by the RFC3852 comments that are missing

            /*
             * The countersignature attribute MUST be an unsigned attribute; it MUST
             * NOT be a signed attribute, an authenticated attribute, an
             * unauthenticated attribute, or an unprotected attribute.
             */
            AttributeTable unsignedAttributeTable = UnsignedAttributes;

            if (unsignedAttributeTable == null)
            {
                return(new SignerInformationStore(Platform.CreateArrayList(0)));
            }

            IList counterSignatures = Platform.CreateArrayList();

            /*
             * The UnsignedAttributes syntax is defined as a SET OF Attributes.  The
             * UnsignedAttributes in a signerInfo may include multiple instances of
             * the countersignature attribute.
             */
            Asn1EncodableVector allCSAttrs = unsignedAttributeTable.GetAll(CmsAttributes.CounterSignature);

            foreach (Attribute counterSignatureAttribute in allCSAttrs)
            {
                /*
                 * A countersignature attribute can have multiple attribute values.  The
                 * syntax is defined as a SET OF AttributeValue, and there MUST be one
                 * or more instances of AttributeValue present.
                 */
                Asn1Set values = counterSignatureAttribute.AttrValues;
                if (values.Count < 1)
                {
                    // TODO Throw an appropriate exception?
                }

                foreach (Asn1Encodable asn1Obj in values)
                {
                    /*
                     * Countersignature values have the same meaning as SignerInfo values
                     * for ordinary signatures, except that:
                     *
                     * 1. The signedAttributes field MUST NOT contain a content-type
                     *    attribute; there is no content type for countersignatures.
                     *
                     * 2. The signedAttributes field MUST contain a message-digest
                     *    attribute if it contains any other attributes.
                     *
                     * 3. The input to the message-digesting process is the contents
                     *    octets of the DER encoding of the signatureValue field of the
                     *    SignerInfo value with which the attribute is associated.
                     */
                    SignerInfo si = SignerInfo.GetInstance(asn1Obj.ToAsn1Object());

                    string digestName = CmsSignedHelper.Instance.GetDigestAlgName(si.DigestAlgorithm.Algorithm.Id);

                    counterSignatures.Add(new SignerInformation(si, null, null, new CounterSignatureDigestCalculator(digestName, GetSignature())));
                }
            }

            return(new SignerInformationStore(counterSignatures));
        }
        /// <summary>
        /// Generate an enveloped object that contains a CMS Enveloped Data
        /// object using the passed in key generator.
        /// </summary>
        private CmsEnvelopedData Generate(
            CmsProcessable content,
            string encryptionOid,
            CipherKeyGenerator keyGen)
        {
            AlgorithmIdentifier encAlgId = null;
            KeyParameter        encKey;
            Asn1OctetString     encContent;

            try
            {
                byte[] encKeyBytes = keyGen.GenerateKey();
                encKey = ParameterUtilities.CreateKeyParameter(encryptionOid, encKeyBytes);

                Asn1Encodable asn1Params = GenerateAsn1Parameters(encryptionOid, encKeyBytes);

                ICipherParameters cipherParameters;
                encAlgId = GetAlgorithmIdentifier(
                    encryptionOid, encKey, asn1Params, out cipherParameters);

                IBufferedCipher cipher = CipherUtilities.GetCipher(encryptionOid);
                cipher.Init(true, new ParametersWithRandom(cipherParameters, rand));

                MemoryStream bOut = new MemoryStream();
                CipherStream cOut = new CipherStream(bOut, null, cipher);

                content.Write(cOut);

                Platform.Dispose(cOut);

                encContent = new BerOctetString(bOut.ToArray());
            }
            catch (SecurityUtilityException e)
            {
                throw new CmsException("couldn't create cipher.", e);
            }
            catch (InvalidKeyException e)
            {
                throw new CmsException("key invalid in message.", e);
            }
            catch (IOException e)
            {
                throw new CmsException("exception decoding algorithm parameters.", e);
            }


            Asn1EncodableVector recipientInfos = new Asn1EncodableVector();

            foreach (RecipientInfoGenerator rig in recipientInfoGenerators)
            {
                try
                {
                    recipientInfos.Add(rig.Generate(encKey, rand));
                }
                catch (InvalidKeyException e)
                {
                    throw new CmsException("key inappropriate for algorithm.", e);
                }
                catch (GeneralSecurityException e)
                {
                    throw new CmsException("error making encrypted content.", e);
                }
            }

            EncryptedContentInfo eci = new EncryptedContentInfo(
                CmsObjectIdentifiers.Data,
                encAlgId,
                encContent);

            Asn1Set unprotectedAttrSet = null;

            if (unprotectedAttributeGenerator != null)
            {
                AttributeTable attrTable = unprotectedAttributeGenerator.GetAttributes(Platform.CreateHashtable());

                unprotectedAttrSet = new BerSet(attrTable.ToAsn1EncodableVector());
            }

            ContentInfo contentInfo = new ContentInfo(
                CmsObjectIdentifiers.EnvelopedData,
                new EnvelopedData(null, new DerSet(recipientInfos), eci, unprotectedAttrSet));

            return(new CmsEnvelopedData(contentInfo));
        }
            internal SignerInfo ToSignerInfo(
                DerObjectIdentifier contentType,
                CmsProcessable content,
                SecureRandom random)
            {
                AlgorithmIdentifier digAlgId = DigestAlgorithmID;
                string digestName            = Helper.GetDigestAlgName(digestOID);

                string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);

                byte[] hash;
                if (outer._digests.Contains(digestOID))
                {
                    hash = (byte[])outer._digests[digestOID];
                }
                else
                {
                    IDigest dig = Helper.GetDigestInstance(digestName);
                    if (content != null)
                    {
                        content.Write(new DigOutputStream(dig));
                    }
                    hash = DigestUtilities.DoFinal(dig);
                    outer._digests.Add(digestOID, hash.Clone());
                }

                IStreamCalculator calculator = sigCalc.CreateCalculator();

#if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT || PORTABLE
                Stream sigStr = calculator.Stream;
#else
                Stream sigStr = new BufferedStream(calculator.Stream);
#endif

                Asn1Set signedAttr = null;
                if (sAttr != null)
                {
                    IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash);

//					Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(Collections.unmodifiableMap(parameters));
                    AttributeTable signed = sAttr.GetAttributes(parameters);

                    if (contentType == null) //counter signature
                    {
                        if (signed != null && signed[CmsAttributes.ContentType] != null)
                        {
                            IDictionary tmpSigned = signed.ToDictionary();
                            tmpSigned.Remove(CmsAttributes.ContentType);
                            signed = new AttributeTable(tmpSigned);
                        }
                    }

                    // TODO Validate proposed signed attributes

                    signedAttr = outer.GetAttributeSet(signed);

                    // sig must be composed from the DER encoding.
                    new DerOutputStream(sigStr).WriteObject(signedAttr);
                }
                else if (content != null)
                {
                    // TODO Use raw signature of the hash value instead
                    content.Write(sigStr);
                }

                Platform.Dispose(sigStr);
                byte[] sigBytes = ((IBlockResult)calculator.GetResult()).Collect();

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

//					Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(Collections.unmodifiableMap(baseParameters));
                    AttributeTable unsigned = unsAttr.GetAttributes(baseParameters);

                    // TODO Validate proposed unsigned attributes

                    unsignedAttr = outer.GetAttributeSet(unsigned);
                }

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

                return(new SignerInfo(signerIdentifier, digAlgId,
                                      signedAttr, encAlgId, new DerOctetString(sigBytes), unsignedAttr));
            }
Example #21
0
            public SignerInfo Generate(DerObjectIdentifier contentType, AlgorithmIdentifier digestAlgorithm,
                                       byte[] calculatedDigest)
            {
                try
                {
                    string digestName    = Helper.GetDigestAlgName(_digestOID);
                    string signatureName = digestName + "with" + _encName;

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

                    byte[] bytesToSign = calculatedDigest;

                    /* 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, digestAlgorithm, calculatedDigest);

//						Asn1.Cms.AttributeTable signed = _sAttr.GetAttributes(Collections.unmodifiableMap(parameters));
                        AttributeTable signed = _sAttr.GetAttributes(parameters);

                        if (contentType == null) //counter signature
                        {
                            if (signed != null && signed[CmsAttributes.ContentType] != null)
                            {
                                IDictionary tmpSigned = signed.ToDictionary();
                                tmpSigned.Remove(CmsAttributes.ContentType);
                                signed = new AttributeTable(tmpSigned);
                            }
                        }

                        signedAttr = outer.GetAttributeSet(signed);

                        // sig must be composed from the DER encoding.
                        bytesToSign = signedAttr.GetEncoded(Asn1Encodable.Der);
                    }
                    else
                    {
                        // Note: Need to use raw signatures here since we have already calculated the digest
                        if (_encName.Equals("RSA"))
                        {
                            DigestInfo dInfo = new DigestInfo(digestAlgorithm, calculatedDigest);
                            bytesToSign = dInfo.GetEncoded(Asn1Encodable.Der);
                        }
                    }

                    _sig.BlockUpdate(bytesToSign, 0, bytesToSign.Length);
                    byte[] sigBytes = _sig.GenerateSignature();

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

//						Asn1.Cms.AttributeTable unsigned = _unsAttr.getAttributes(Collections.unmodifiableMap(parameters));
                        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 digestEncryptionAlgorithm = Helper.GetEncAlgorithmIdentifier(
                        new DerObjectIdentifier(_encOID), sigX509Parameters);

                    return(new SignerInfo(_signerIdentifier, digestAlgorithm,
                                          signedAttr, digestEncryptionAlgorithm, new DerOctetString(sigBytes), unsignedAttr));
                }
                catch (IOException e)
                {
                    throw new CmsStreamException("encoding error.", e);
                }
                catch (SignatureException e)
                {
                    throw new CmsStreamException("error creating signature.", e);
                }
            }
Example #22
0
        private bool DoVerify(
            AsymmetricKeyParameter key)
        {
            string  digestName = Helper.GetDigestAlgName(this.DigestAlgOid);
            IDigest digest     = Helper.GetDigestInstance(digestName);

            DerObjectIdentifier sigAlgOid = this.encryptionAlgorithm.Algorithm;
            Asn1Encodable       sigParams = this.encryptionAlgorithm.Parameters;
            ISigner             sig;

            if (sigAlgOid.Equals(PkcsObjectIdentifiers.IdRsassaPss))
            {
                // RFC 4056 2.2
                // When the id-RSASSA-PSS algorithm identifier is used for a signature,
                // the AlgorithmIdentifier parameters field MUST contain RSASSA-PSS-params.
                if (sigParams == null)
                {
                    throw new CmsException("RSASSA-PSS signature must specify algorithm parameters");
                }

                try
                {
                    // TODO Provide abstract configuration mechanism
                    // (via alternate SignerUtilities.GetSigner method taking ASN.1 params)

                    RsassaPssParameters pss = RsassaPssParameters.GetInstance(
                        sigParams.ToAsn1Object());

                    if (!pss.HashAlgorithm.Algorithm.Equals(this.digestAlgorithm.Algorithm))
                    {
                        throw new CmsException("RSASSA-PSS signature parameters specified incorrect hash algorithm");
                    }
                    if (!pss.MaskGenAlgorithm.Algorithm.Equals(PkcsObjectIdentifiers.IdMgf1))
                    {
                        throw new CmsException("RSASSA-PSS signature parameters specified unknown MGF");
                    }

                    IDigest pssDigest    = DigestUtilities.GetDigest(pss.HashAlgorithm.Algorithm);
                    int     saltLength   = pss.SaltLength.Value.IntValue;
                    byte    trailerField = (byte)pss.TrailerField.Value.IntValue;

                    // RFC 4055 3.1
                    // The value MUST be 1, which represents the trailer field with hexadecimal value 0xBC
                    if (trailerField != 1)
                    {
                        throw new CmsException("RSASSA-PSS signature parameters must have trailerField of 1");
                    }

                    sig = new PssSigner(new RsaBlindedEngine(), pssDigest, saltLength);
                }
                catch (Exception e)
                {
                    throw new CmsException("failed to set RSASSA-PSS signature parameters", e);
                }
            }
            else
            {
                // TODO Probably too strong a check at the moment
//				if (sigParams != null)
//					throw new CmsException("unrecognised signature parameters provided");

                string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(this.EncryptionAlgOid);

                sig = Helper.GetSignatureInstance(signatureName);

                //sig = Helper.GetSignatureInstance(this.EncryptionAlgOid);
                //sig = SignerUtilities.GetSigner(sigAlgOid);
            }

            try
            {
                if (digestCalculator != null)
                {
                    resultDigest = digestCalculator.GetDigest();
                }
                else
                {
                    if (content != null)
                    {
                        content.Write(new DigOutputStream(digest));
                    }
                    else if (signedAttributeSet == null)
                    {
                        // TODO Get rid of this exception and just treat content==null as empty not missing?
                        throw new CmsException("data not encapsulated in signature - use detached constructor.");
                    }

                    resultDigest = DigestUtilities.DoFinal(digest);
                }
            }
            catch (IOException e)
            {
                throw new CmsException("can't process mime object to create signature.", e);
            }

            // RFC 3852 11.1 Check the content-type attribute is correct
            {
                Asn1Object validContentType = GetSingleValuedSignedAttribute(
                    CmsAttributes.ContentType, "content-type");
                if (validContentType == null)
                {
                    if (!isCounterSignature && signedAttributeSet != null)
                    {
                        throw new CmsException("The content-type attribute type MUST be present whenever signed attributes are present in signed-data");
                    }
                }
                else
                {
                    if (isCounterSignature)
                    {
                        throw new CmsException("[For counter signatures,] the signedAttributes field MUST NOT contain a content-type attribute");
                    }

                    if (!(validContentType is DerObjectIdentifier))
                    {
                        throw new CmsException("content-type attribute value not of ASN.1 type 'OBJECT IDENTIFIER'");
                    }

                    DerObjectIdentifier signedContentType = (DerObjectIdentifier)validContentType;

                    if (!signedContentType.Equals(contentType))
                    {
                        throw new CmsException("content-type attribute value does not match eContentType");
                    }
                }
            }

            // RFC 3852 11.2 Check the message-digest attribute is correct
            {
                Asn1Object validMessageDigest = GetSingleValuedSignedAttribute(
                    CmsAttributes.MessageDigest, "message-digest");
                if (validMessageDigest == null)
                {
                    if (signedAttributeSet != null)
                    {
                        throw new CmsException("the message-digest signed attribute type MUST be present when there are any signed attributes present");
                    }
                }
                else
                {
                    if (!(validMessageDigest is Asn1OctetString))
                    {
                        throw new CmsException("message-digest attribute value not of ASN.1 type 'OCTET STRING'");
                    }

                    Asn1OctetString signedMessageDigest = (Asn1OctetString)validMessageDigest;

                    if (!Arrays.AreEqual(resultDigest, signedMessageDigest.GetOctets()))
                    {
                        throw new CmsException("message-digest attribute value does not match calculated value");
                    }
                }
            }

            // RFC 3852 11.4 Validate countersignature attribute(s)
            {
                AttributeTable signedAttrTable = this.SignedAttributes;
                if (signedAttrTable != null &&
                    signedAttrTable.GetAll(CmsAttributes.CounterSignature).Count > 0)
                {
                    throw new CmsException("A countersignature attribute MUST NOT be a signed attribute");
                }

                AttributeTable unsignedAttrTable = this.UnsignedAttributes;
                if (unsignedAttrTable != null)
                {
                    foreach (Attribute csAttr in unsignedAttrTable.GetAll(CmsAttributes.CounterSignature))
                    {
                        if (csAttr.AttrValues.Count < 1)
                        {
                            throw new CmsException("A countersignature attribute MUST contain at least one AttributeValue");
                        }

                        // Note: We don't recursively validate the countersignature value
                    }
                }
            }

            try
            {
                sig.Init(false, key);

                if (signedAttributeSet == null)
                {
                    if (digestCalculator != null)
                    {
                        // need to decrypt signature and check message bytes
                        return(VerifyDigest(resultDigest, key, this.GetSignature()));
                    }
                    else if (content != null)
                    {
                        // TODO Use raw signature of the hash value instead
                        content.Write(new SigOutputStream(sig));
                    }
                }
                else
                {
                    byte[] tmp = this.GetEncodedSignedAttributes();
                    sig.BlockUpdate(tmp, 0, tmp.Length);
                }

                return(sig.VerifySignature(this.GetSignature()));
            }
            catch (InvalidKeyException e)
            {
                throw new CmsException("key not appropriate to signature in message.", e);
            }
            catch (IOException e)
            {
                throw new CmsException("can't process mime object to create signature.", e);
            }
            catch (SignatureException e)
            {
                throw new CmsException("invalid signature format in message: " + e.Message, e);
            }
        }