private CmsEnvelopedData doGenerate(
            ICmsTypedData content,
            ICipherBuilderWithKey<AlgorithmIdentifier> contentEncryptor)
        {
            Asn1EncodableVector recipientInfos = new Asn1EncodableVector();
            AlgorithmIdentifier encAlgId;
            Asn1OctetString encContent;

            MemoryOutputStream bOut = new MemoryOutputStream();

            try
            {
                ICipher cOut = contentEncryptor.BuildCipher(bOut);

                content.Write(cOut.Stream);

                cOut.Stream.Close();
            }
            catch (IOException e)
            {
                throw new CmsException(e.Message, e);
            }

            byte[] encryptedContent = bOut.ToArray();

            encAlgId = contentEncryptor.AlgorithmDetails;

            encContent = new BerOctetString(encryptedContent);

            ISymmetricKey encKey = contentEncryptor.Key;

            for (IEnumerator<IRecipientInfoGenerator> it = recipientInfoGenerators.GetEnumerator(); it.MoveNext();)
            {
                IRecipientInfoGenerator recipient = (IRecipientInfoGenerator)it.Current;

                recipientInfos.Add(recipient.Generate(encKey));
            }

            EncryptedContentInfo eci = new EncryptedContentInfo(
                            content.ContentType,
                            encAlgId,
                            encContent);

            Asn1Set unprotectedAttrSet = null;
            if (unprotectedAttributeGenerator != null)
            {
                Asn1.Cms.AttributeTable attrTable = unprotectedAttributeGenerator.GetAttributes(new Dictionary<string, object>());

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

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

            return new CmsEnvelopedData(contentInfo);
        }
        private CmsEncryptedData doGenerate(
            ICmsTypedData content,
            ICipherBuilder <AlgorithmIdentifier> contentEncryptor)
        {
            AlgorithmIdentifier encAlgId;
            Asn1OctetString     encContent;

            MemoryOutputStream bOut = new MemoryOutputStream();

            try
            {
                ICipher cipher = contentEncryptor.BuildCipher(bOut);

                content.Write(cipher.Stream);

                cipher.Stream.Close();
            }
            catch (IOException)
            {
                throw new CmsException("");
            }

            byte[] encryptedContent = bOut.ToArray();

            encAlgId = contentEncryptor.AlgorithmDetails;

            encContent = new BerOctetString(encryptedContent);

            EncryptedContentInfo eci = new EncryptedContentInfo(
                content.ContentType,
                encAlgId,
                encContent);

            Asn1Set unprotectedAttrSet = null;

            if (unprotectedAttributeGenerator != null)
            {
                Asn1.Cms.AttributeTable attrTable = unprotectedAttributeGenerator.GetAttributes(new Dictionary <string, object>());

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

            ContentInfo contentInfo = new ContentInfo(
                CmsObjectIdentifiers.EncryptedData,
                new EncryptedData(eci, unprotectedAttrSet));

            return(new CmsEncryptedData(contentInfo));
        }
Пример #3
0
        private bool doVerify(bool isRawVerifier, IVerifierFactory <AlgorithmIdentifier> verifierFactory, IDigestFactory <AlgorithmIdentifier> digestFactory)
        {
            IStreamCalculator <IVerifier> contentVerifier = verifierFactory.CreateCalculator();
            Stream sigOut = contentVerifier.Stream;

            try
            {
                if (resultDigest == null)
                {
                    IStreamCalculator <IBlockResult> calc = digestFactory.CreateCalculator();
                    if (content != null)
                    {
                        Stream digOut = calc.Stream;

                        if (signedAttributeSet == null)
                        {
                            if (isRawVerifier)
                            {
                                content.Write(digOut);
                            }
                            else
                            {
                                Stream cOut = new TeeOutputStream(digOut, sigOut);

                                content.Write(cOut);

                                cOut.Close();
                            }
                        }
                        else
                        {
                            content.Write(digOut);
                            byte[] enc = this.GetEncodedSignedAttributes();
                            sigOut.Write(enc, 0, enc.Length);
                        }

                        digOut.Close();
                    }
                    else if (signedAttributeSet != null)
                    {
                        byte[] enc = this.GetEncodedSignedAttributes();

                        sigOut.Write(enc, 0, enc.Length);
                    }
                    else
                    {
                        // 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 = calc.GetResult().Collect();
                }
                else
                {
                    if (signedAttributeSet == null)
                    {
                        if (content != null)
                        {
                            content.Write(sigOut);
                        }
                    }
                    else
                    {
                        byte[] enc = this.GetEncodedSignedAttributes();

                        sigOut.Write(enc, 0, enc.Length);
                    }
                }

                sigOut.Close();
            }
            catch (Exception e)
            {
                throw new CmsException("can't process 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");
                    }
                }
            }

            Asn1.Cms.AttributeTable signedAttrTable = this.SignedAttributes;

            // RFC 6211 Validate Algorithm Identifier protection attribute if present
            {
                Asn1.Cms.AttributeTable unsignedAttrTable = this.UnsignedAttributes;
                if (unsignedAttrTable != null && unsignedAttrTable.GetAll(CmsAttributes.CmsAlgorithmProtect).Count > 0)
                {
                    throw new CmsException("A cmsAlgorithmProtect attribute MUST be a signed attribute");
                }
                if (signedAttrTable != null)
                {
                    Asn1EncodableVector protectionAttributes = signedAttrTable.GetAll(CmsAttributes.CmsAlgorithmProtect);
                    if (protectionAttributes.Count > 1)
                    {
                        throw new CmsException("Only one instance of a cmsAlgorithmProtect attribute can be present");
                    }

                    if (protectionAttributes.Count > 0)
                    {
                        Asn1.Cms.Attribute attr = Asn1.Cms.Attribute.GetInstance(protectionAttributes[0]);
                        if (attr.AttrValues.Count != 1)
                        {
                            throw new CmsException("A cmsAlgorithmProtect attribute MUST contain exactly one value");
                        }

                        CmsAlgorithmProtection algorithmProtection = CmsAlgorithmProtection.GetInstance(attr.AttrValues[0]);

                        if (!CmsUtilities.IsEquivalent(algorithmProtection.DigestAlgorithm, info.DigestAlgorithm))
                        {
                            throw new CmsException("CMS Algorithm Identifier Protection check failed for digestAlgorithm");
                        }

                        if (!CmsUtilities.IsEquivalent(algorithmProtection.SignatureAlgorithm, info.DigestEncryptionAlgorithm))
                        {
                            throw new CmsException("CMS Algorithm Identifier Protection check failed for signatureAlgorithm");
                        }
                    }
                }
            }

            // RFC 3852 11.2 Check the message-digest attribute is correct
            {
                Asn1Encodable 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.ConstantTimeAreEqual(resultDigest, signedMessageDigest.GetOctets()))
                    {
                        throw new CmsSignerDigestMismatchException("message-digest attribute value does not match calculated value");
                    }
                }
            }

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

                Asn1.Cms.AttributeTable unsignedAttrTable = this.UnsignedAttributes;
                if (unsignedAttrTable != null)
                {
                    Asn1EncodableVector csAttrs = unsignedAttrTable.GetAll(CmsAttributes.CounterSignature);
                    for (int i = 0; i < csAttrs.Count; ++i)
                    {
                        Asn1.Cms.Attribute csAttr = Asn1.Cms.Attribute.GetInstance(csAttrs[i]);
                        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
            {
                if (signedAttributeSet == null && resultDigest != null)
                {
                    if (isRawVerifier)
                    {
                        if (SignatureAlgorithmID.Algorithm.Equals(PkcsObjectIdentifiers.RsaEncryption))
                        {
                            DigestInfo digInfo = new DigestInfo(new AlgorithmIdentifier(digestAlgorithm.Algorithm, DerNull.Instance), resultDigest);
                            byte[]     data    = digInfo.GetEncoded(Asn1Encodable.Der);

                            sigOut.Write(data, 0, data.Length);

                            sigOut.Close();

                            return(contentVerifier.GetResult().IsVerified(this.GetSignature()));
                        }

                        sigOut.Write(resultDigest, 0, resultDigest.Length);

                        sigOut.Close();

                        return(contentVerifier.GetResult().IsVerified(this.GetSignature()));
                    }
                }

                sigOut.Close();

                return(contentVerifier.GetResult().IsVerified(this.GetSignature()));
            }
            catch (IOException e)
            {
                throw new CmsException("can't process mime object to create signature.", e);
            }
        }
        /**
         * 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(
            // FIXME Avoid accessing more than once to support CmsProcessableInputStream
            ICmsTypedData content,
            bool encapsulate)
        {
            // TODO
            //        if (signerInfs.isEmpty())
            //        {
            //            /* RFC 3852 5.2
            //             * "In the degenerate case where there are no signers, the
            //             * EncapsulatedContentInfo value being "signed" is irrelevant.  In this
            //             * case, the content type within the EncapsulatedContentInfo value being
            //             * "signed" MUST be id-data (as defined in section 4), and the content
            //             * field of the EncapsulatedContentInfo value MUST be omitted."
            //             */
            //            if (encapsulate)
            //            {
            //                throw new IllegalArgumentException("no signers, encapsulate must be false");
            //            }
            //            if (!DATA.equals(eContentType))
            //            {
            //                throw new IllegalArgumentException("no signers, eContentType must be id-data");
            //            }
            //        }
            //
            //        if (!DATA.equals(eContentType))
            //        {
            //            /* RFC 3852 5.3
            //             * [The 'signedAttrs']...
            //             * field is optional, but it MUST be present if the content type of
            //             * the EncapsulatedContentInfo value being signed is not id-data.
            //             */
            //            // TODO signedAttrs must be present for all signers
            //        }

            Asn1EncodableVector digestAlgs  = new Asn1EncodableVector();
            Asn1EncodableVector signerInfos = new Asn1EncodableVector();

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

            //
            // add the precalculated SignerInfo objects.
            //
            for (IEnumerator it = _signers.GetEnumerator(); it.MoveNext();)
            {
                SignerInformation signer = (SignerInformation)it.Current;
                digestAlgs.Add(CmsUtilities.fixAlgID(signer.DigestAlgorithmID));

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

            //
            // add the SignerInfo objects
            //
            DerObjectIdentifier contentTypeOID = content.ContentType;

            Asn1OctetString octs = null;

            if (content.GetContent() != null)
            {
                MemoryOutputStream bOut = null;

                if (encapsulate)
                {
                    bOut = new MemoryOutputStream();
                }

                Stream cOut = CmsUtilities.attachSignersToOutputStream(_signerGens, bOut);

                // Just in case it's unencapsulated and there are no signers!
                cOut = CmsUtilities.getSafeOutputStream(cOut);

                try
                {
                    content.Write(cOut);

                    cOut.Close();
                }
                catch (IOException e)
                {
                    throw new CmsException("data processing exception: " + e.Message, e);
                }

                if (encapsulate)
                {
                    octs = new BerOctetString(bOut.ToArray());
                }
            }

            for (IEnumerator it = _signerGens.GetEnumerator(); it.MoveNext();)
            {
                SignerInfoGenerator sGen = (SignerInfoGenerator)it.Current;
                SignerInfo          inf  = sGen.Generate(contentTypeOID);

                digestAlgs.Add(inf.DigestAlgorithm);
                signerInfos.Add(inf);

                byte[] calcDigest = sGen.getCalculatedDigest();

                if (calcDigest != null)
                {
                    _digests.Add(inf.DigestAlgorithm.Algorithm.Id, calcDigest);
                }
            }

            Asn1Set certificates = null;

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

            Asn1Set certrevlist = null;

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

            ContentInfo encInfo = new ContentInfo(contentTypeOID, octs);

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

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

            return(new CmsSignedData(content, contentInfo));
        }