示例#1
0
 /*
  * tries to sign a MimeEntity
  */
 public static MimeEntity SignEntity(MimeEntity entity, MailboxAddress signer)
 {
     using (WindowsSecureMimeContext ctx = new WindowsSecureMimeContext(sys.StoreLocation.CurrentUser))
     {
         return(MultipartSigned.Create(ctx, signer, DigestAlgorithm.Sha1, entity));
     }
 }
示例#2
0
        public void TestPgpMimeSigning()
        {
            var self = new MailboxAddress("MimeKit UnitTests", "*****@*****.**");

            var cleartext = new TextPart("plain");

            cleartext.Text = "This is some cleartext that we'll end up signing...";

            using (var ctx = new DummyOpenPgpContext()) {
                var multipart = MultipartSigned.Create(ctx, self, DigestAlgorithm.Sha1, cleartext);
                Assert.AreEqual(2, multipart.Count, "The multipart/signed has an unexpected number of children.");

                var protocol = multipart.ContentType.Parameters["protocol"];
                Assert.AreEqual(ctx.SignatureProtocol, protocol, "The multipart/signed protocol does not match.");

                Assert.IsInstanceOfType(typeof(TextPart), multipart[0], "The first child is not a text part.");
                Assert.IsInstanceOfType(typeof(ApplicationPgpSignature), multipart[1], "The second child is not a detached signature.");

                var signatures = multipart.Verify(ctx);
                Assert.AreEqual(1, signatures.Count, "Verify returned an unexpected number of signatures.");
                foreach (var signature in signatures)
                {
                    try {
                        bool valid = signature.Verify();

                        Assert.IsTrue(valid, "Bad signature from {0}", signature.SignerCertificate.Email);
                    } catch (DigitalSignatureVerifyException ex) {
                        Assert.Fail("Failed to verify signature: {0}", ex);
                    }
                }
            }
        }
示例#3
0
        /*
         * Only signs the given MimeEntity
         */
        private MultipartSigned SignEntity(
            Node entityNode,
            MimeEntity entity)
        {
            // Retrieving signature node to use for signing operation
            var signatureNode = entityNode ["signature"];

            // Getting signature email as provided by caller
            var signatureAddress = GetSignatureMailboxAddress(signatureNode);

            // Figuring out signature Digest Algorithm to use for signature, defaulting to Sha256
            var algo = signatureNode.GetChildValue("digest-algorithm", _context, DigestAlgorithm.Sha256);

            // Creating our Gnu Privacy Guard context
            using (var ctx = new GnuPrivacyContext()) {
                // Setting password to retrieve signing certificate from GnuPG context
                ctx.Password = signatureAddress.Item1;

                // Signing content of email and returning to caller
                return(MultipartSigned.Create(
                           ctx,
                           signatureAddress.Item2,
                           algo,
                           entity));
            }
        }
示例#4
0
 public void Sign(MimeMessage message, PgpSecretKey key)
 {
     // digitally sign our message body using our custom GnuPG cryptography context
     using (var ctx = new MyGnuPGContext()) {
         message.Body = MultipartSigned.Create(ctx, key, DigestAlgorithm.Sha1, message.Body);
     }
 }
示例#5
0
        public static bool SendSignedMessage(MimeMessage message)
        {
            bool IsMailSigned = false;

            // digitally sign our message body using our custom S/MIME cryptography context
            try
            {
                using (var ctx = new SecureMimeContext())
                {
                    var signer = new CmsSigner(P12Stream(), "<PWD>")
                    {
                        DigestAlgorithm = DigestAlgorithm.Sha1
                    };

                    message.Body = MultipartSigned.Create(ctx, signer, message.Body);
                }
                SendEmailByMailServer(message);
                IsMailSigned = true;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.InnerException.ToString());
                IsMailSigned = false;
            }

            return(IsMailSigned);
        }
        /*
         * Only signs the given MimeEntity.
         */
        MultipartSigned SignEntity(Node entityNode, MimeEntity entity)
        {
            // Retrieving signature node to use for signing operation.
            var signatureNode = entityNode ["sign"];

            // Getting signature email as provided by caller.
            var signatureAddress = GetSignatureMailboxAddress(signatureNode);

            /*
             * Figuring out signature Digest Algorithm to use for signature, defaulting to SHA256.
             * SHA256 should be safe, since there are no known collision weaknesses in it.
             * Therefor we default to SHA256, unlesss caller explicitly tells us he wants to use another algorithm.
             */
            var algo = signatureNode.GetChildValue("digest-algorithm", _context, DigestAlgorithm.Sha256);

            /*
             * Creating our PGP context, passing in password specified by caller.
             */
            using (var ctx = _context.RaiseEvent(
                       ".p5.crypto.pgp-keys.context.create",
                       new Node("", false,
                                new Node [] {
                new Node("password", signatureAddress.Item1),
                new Node("fingerprint", signatureNode ["fingerprint"]?.GetExChildValue <string> ("fingerprint", _context, null) ??
                         _context.RaiseEvent("p5.auth.pgp.get-fingerprint").Get <string> (_context))
            }))
                             .Get <OpenPgpContext> (_context)) {
                // Signing content of email and returning to caller.
                return(MultipartSigned.Create(
                           ctx,
                           signatureAddress.Item2,
                           algo,
                           entity));
            }
        }
示例#7
0
        protected void WriteMdn(HttpResponse response, MimeMessage mdn, int status)
        {
            response.StatusCode = status;

            foreach (var header in mdn.Headers)
            {
                response.Headers.Add(header.Field, header.Value);
            }

            var contentType = ((MultipartSigned)mdn.Body).Headers[HeaderId.ContentType];

            response.Headers.Add("Content-Type", this.NormalizeHeaderValue(contentType));

            // Write MDN to response without header names.
            // Force 7bit encoding in MIME Response
            MultipartSigned mSigned = mdn.Body as MultipartSigned;

            Debug.Assert(mSigned != null, nameof(mSigned) + " != null");
            MultipartReport mReport = mSigned[0] as MultipartReport;

            Debug.Assert(mReport != null, nameof(mReport) + " != null");
            TextPart textReport = mReport[0] as TextPart;

            Debug.Assert(textReport != null, nameof(textReport) + " != null");
            textReport.ContentTransferEncoding = ContentEncoding.SevenBit;
            var notReport = mReport[1] as MessageDispositionNotification;

            Debug.Assert(notReport != null, nameof(notReport) + " != null");
            notReport.ContentTransferEncoding = ContentEncoding.SevenBit;
            mdn.Headers.Add(HeaderId.Date, As2DateUtil.Rfc822.GetFormat(DateTime.Now));
            mdn.WriteTo(response.Body);
        }
示例#8
0
        public void MultipartSign(MimeMessage message, X509Certificate2 certificate)
        {
            // digitally sign our message body using our custom S/MIME cryptography context
            using (var ctx = new MySecureMimeContext()) {
                var signer = new CmsSigner(certificate)
                {
                    DigestAlgorithm = DigestAlgorithm.Sha1
                };

                message.Body = MultipartSigned.Create(ctx, signer, message.Body);
            }
        }
示例#9
0
        public void MultipartSign(MimeMessage message)
        {
            // digitally sign our message body using our custom S/MIME cryptography context
            using (var ctx = new MySecureMimeContext()) {
                // Note: this assumes that the Sender address has an S/MIME signing certificate
                // and private key with an X.509 Subject Email identifier that matches the
                // sender's email address.
                var sender = message.From.Mailboxes.FirstOrDefault();

                message.Body = MultipartSigned.Create(ctx, sender, DigestAlgorithm.Sha1, message.Body);
            }
        }
示例#10
0
        public void TestMultipartSignedSignUsingKeys()
        {
            var body = new TextPart("plain")
            {
                Text = "This is some cleartext that we'll end up signing..."
            };
            var          self = new SecureMailboxAddress("MimeKit UnitTests", "*****@*****.**", "44CD48EEC90D8849961F36BA50DCD107AB0821A2");
            PgpSecretKey signer;

            using (var ctx = new DummyOpenPgpContext()) {
                signer = ctx.GetSigningKey(self);

                foreach (DigestAlgorithm digest in Enum.GetValues(typeof(DigestAlgorithm)))
                {
                    if (digest == DigestAlgorithm.None ||
                        digest == DigestAlgorithm.DoubleSha ||
                        digest == DigestAlgorithm.Tiger192 ||
                        digest == DigestAlgorithm.Haval5160 ||
                        digest == DigestAlgorithm.MD4)
                    {
                        continue;
                    }

                    var multipart = MultipartSigned.Create(signer, digest, body);

                    Assert.AreEqual(2, multipart.Count, "The multipart/signed has an unexpected number of children.");

                    var protocol = multipart.ContentType.Parameters["protocol"];
                    Assert.AreEqual("application/pgp-signature", protocol, "The multipart/signed protocol does not match.");

                    var micalg    = multipart.ContentType.Parameters["micalg"];
                    var algorithm = ctx.GetDigestAlgorithm(micalg);

                    Assert.AreEqual(digest, algorithm, "The multipart/signed micalg does not match.");

                    Assert.IsInstanceOf <TextPart> (multipart[0], "The first child is not a text part.");
                    Assert.IsInstanceOf <ApplicationPgpSignature> (multipart[1], "The second child is not a detached signature.");

                    var signatures = multipart.Verify();
                    Assert.AreEqual(1, signatures.Count, "Verify returned an unexpected number of signatures.");
                    foreach (var signature in signatures)
                    {
                        try {
                            bool valid = signature.Verify();

                            Assert.IsTrue(valid, "Bad signature from {0}", signature.SignerCertificate.Email);
                        } catch (DigitalSignatureVerifyException ex) {
                            Assert.Fail("Failed to verify signature: {0}", ex);
                        }
                    }
                }
            }
        }
示例#11
0
        /*
         * Processes a signed Multipart.
         */
        private void ProcessSignedMultipart(MultipartSigned signedMultipart, Node entityNode)
        {
            // Creating cryptographic context.
            using (var ctx = new GnuPrivacyContext()) {
                // Adding signatures.
                ProcessSignatures(entityNode, signedMultipart.Verify(ctx));

                // Looping through all entities in Multipart, processing recursively.
                foreach (var idxEntity in signedMultipart)
                {
                    ProcessEntity(idxEntity, entityNode);
                }
            }
        }
示例#12
0
        /// <summary>
        /// Creates an S/MIME message using the supplied MimeBodyPart. The signature is generated using the private key
        /// as supplied in the constructor. Our certificate, which is required to verify the signature is enclosed.
        /// </summary>
        /// <param name="mimeBodyPart"></param>
        /// <param name="digestMethod"></param>
        /// <returns></returns>
        public MimeMessage CreateSignedMimeMessage(MimeMessage mimeBodyPart, SMimeDigestMethod digestMethod)
        {
            MimeMessage message = new MimeMessage();

            using (var ctx = this.secContentFactory())
            {
                // Algorithm lookup
                DigestAlgorithm algorithm;
                if (digestMethod.Equals(SMimeDigestMethod.Sha1))
                {
                    algorithm = DigestAlgorithm.Sha1;
                }
                else if (digestMethod.Equals(SMimeDigestMethod.Sha512))
                {
                    algorithm = DigestAlgorithm.Sha512;
                }
                else
                {
                    throw new NotSupportedException($"Algorithm {digestMethod.GetAlgorithm()} not supported");
                }

                // Signer identification
                var cmsSigner = new CmsSigner(this.ourCertificate, this.privateKey)
                {
                    DigestAlgorithm = algorithm
                };

                // Create and sign message
                message.Body = MultipartSigned.Create(ctx, cmsSigner, mimeBodyPart.Body);

                // Force signed content to be transferred in binary format
                MimePart xml = (MimePart)message.BodyParts.First();
                xml.ContentTransferEncoding = ContentEncoding.Binary;
            }


            // Remove unused headers
            foreach (var header in message.Headers.Select(x => x.Id).ToList())
            {
                if (header != HeaderId.MessageId && header != HeaderId.MimeVersion && header != HeaderId.ContentType)
                {
                    message.Headers.Remove(header);
                }
            }

            return(message);
        }
示例#13
0
        public void TestSecureMimeSigning()
        {
            var self = new MailboxAddress("MimeKit UnitTests", "*****@*****.**");

            var cleartext = new TextPart("plain");

            cleartext.Text = "This is some cleartext that we'll end up signing...";

            using (var ctx = CreateContext()) {
                var multipart = MultipartSigned.Create(ctx, self, DigestAlgorithm.Sha1, cleartext);
                Assert.AreEqual(2, multipart.Count, "The multipart/signed has an unexpected number of children.");

                var protocol = multipart.ContentType.Parameters["protocol"];
                Assert.AreEqual(ctx.SignatureProtocol, protocol, "The multipart/signed protocol does not match.");

                Assert.IsInstanceOfType(typeof(TextPart), multipart[0], "The first child is not a text part.");
                Assert.IsInstanceOfType(typeof(ApplicationPkcs7Signature), multipart[1], "The second child is not a detached signature.");

                var signatures = multipart.Verify(ctx);
                Assert.AreEqual(1, signatures.Count, "Verify returned an unexpected number of signatures.");
                foreach (var signature in signatures)
                {
                    try {
                        bool valid = signature.Verify();

                        Assert.IsTrue(valid, "Bad signature from {0}", signature.SignerCertificate.Email);
                    } catch (DigitalSignatureVerifyException ex) {
                        Assert.Fail("Failed to verify signature: {0}", ex);
                    }

                    var algorithms = ((SecureMimeDigitalSignature)signature).EncryptionAlgorithms;
                    Assert.AreEqual(EncryptionAlgorithm.Camellia256, algorithms[0], "Expected Camellia-256 capability");
                    Assert.AreEqual(EncryptionAlgorithm.Aes256, algorithms[1], "Expected AES-256 capability");
                    Assert.AreEqual(EncryptionAlgorithm.Camellia192, algorithms[2], "Expected Camellia-192 capability");
                    Assert.AreEqual(EncryptionAlgorithm.Aes192, algorithms[3], "Expected AES-192 capability");
                    Assert.AreEqual(EncryptionAlgorithm.Camellia128, algorithms[4], "Expected Camellia-128 capability");
                    Assert.AreEqual(EncryptionAlgorithm.Aes128, algorithms[5], "Expected AES-128 capability");
                    Assert.AreEqual(EncryptionAlgorithm.Idea, algorithms[6], "Expected IDEA capability");
                    Assert.AreEqual(EncryptionAlgorithm.Cast5, algorithms[7], "Expected Cast5 capability");
                    Assert.AreEqual(EncryptionAlgorithm.TripleDes, algorithms[8], "Expected Triple-DES capability");
                    //Assert.AreEqual (EncryptionAlgorithm.RC2128, algorithms[9], "Expected RC2-128 capability");
                    //Assert.AreEqual (EncryptionAlgorithm.RC264, algorithms[10], "Expected RC2-64 capability");
                    //Assert.AreEqual (EncryptionAlgorithm.Des, algorithms[11], "Expected DES capability");
                    //Assert.AreEqual (EncryptionAlgorithm.RC240, algorithms[12], "Expected RC2-40 capability");
                }
            }
        }
示例#14
0
        /*
         * Processes a signed multipart.
         */
        void ProcessSignedMultipart(MultipartSigned signedMultipart, Node entityNode)
        {
            // Creating cryptographic context.
            using (var ctx = _context.RaiseEvent(
                       ".p5.crypto.pgp-keys.context.create",
                       new Node("", false)).Get <OpenPgpContext> (_context)) {
                // Adding signatures.
                ProcessSignatures(entityNode, signedMultipart.Verify(ctx));

                // Looping through all entities in Multipart, processing recursively.
                foreach (var idxEntity in signedMultipart)
                {
                    // Processing currently iterated MIME part.
                    ProcessEntity(idxEntity, entityNode);
                }
            }
        }
示例#15
0
        public void Sign(MimeMessage message)
        {
            // digitally sign our message body using our custom GnuPG cryptography context
            using (var ctx = new MyGnuPGContext()) {
                // Note: this assumes that the Sender address has an S/MIME signing certificate
                // and private key with an X.509 Subject Email identifier that matches the
                // sender's email address.
                //
                // If this is not the case, you can use a SecureMailboxAddress instead of a
                // normal MailboxAddress which would allow you to specify the fingerprint
                // of the sender's private PGP key. You could also choose to use one of the
                // Create() overloads that take a PgpSecretKey, instead.
                var sender = message.From.Mailboxes.FirstOrDefault();

                message.Body = MultipartSigned.Create(ctx, sender, DigestAlgorithm.Sha1, message.Body);
            }
        }
示例#16
0
 /*
  * returns true if email address can sign email
  */
 public static bool CanSign(string email)
 {
     try
     {
         MailboxAddress signer = new MailboxAddress("", email);
         TextPart       entity = new TextPart("text");
         using (WindowsSecureMimeContext ctx = new WindowsSecureMimeContext(sys.StoreLocation.CurrentUser))
         {
             MultipartSigned.Create(ctx, signer, DigestAlgorithm.Sha1, entity);
             return(true);
         }
     }
     catch
     {
         return(false);
     }
 }
示例#17
0
        /*
         * Cryptographically signs an entity.
         */
        static MultipartSigned Sign(
            MimeEntity entity,
            string armoredPrivateKey,
            string keyPassword)
        {
            var algo = DigestAlgorithm.Sha256;

            using (var ctx = new CreatePgpMimeContext {
                Password = keyPassword
            })
            {
                return(MultipartSigned.Create(
                           ctx,
                           PgpHelpers.GetSecretKeyFromAsciiArmored(armoredPrivateKey),
                           algo,
                           entity));
            }
        }
示例#18
0
        public bool VerifySignature(MultipartSigned multipartSigned, out DigitalSignatureCollection signatures)
        {
            var signed = multipartSigned;

            signatures = null;
            var valid = true;

            if (signed != null)
            {
                using (var ctx = this.secureContextFactory())
                {
                    signatures = signed.Verify(ctx);
                    foreach (var signature in signatures)
                    {
                        valid = signature.Verify();
                        if (!valid)
                        {
                            break;
                        }
                    }
                }
            }
            return(valid);
        }
示例#19
0
        public MimeMessage CreateSignedMimeMessage(MimeEntity mimeBodyPart, SMimeDigestMethod digestMethod)
        {
            if (mimeBodyPart is MimePart)
            {
                ((MimePart)mimeBodyPart).ContentTransferEncoding = ContentEncoding.Binary;
            }

            MultipartSigned multipart;

            using (var ctx = this.secContentFactory())
            {
                // Algorithm lookup
                DigestAlgorithm algorithm;
                if (digestMethod.Equals(SMimeDigestMethod.Sha1))
                {
                    algorithm = DigestAlgorithm.Sha1;
                }
                else if (digestMethod.Equals(SMimeDigestMethod.Sha512))
                {
                    algorithm = DigestAlgorithm.Sha512;
                }
                else
                {
                    throw new NotSupportedException($"Algorithm {digestMethod.GetAlgorithm()} not supported");
                }

                var micalg = ctx.GetDigestAlgorithmName(algorithm);
                var signed = new MultipartSigned();

                // set the protocol and micalg Content-Type parameters
                signed.ContentType.Parameters["protocol"] = ctx.SignatureProtocol;
                signed.ContentType.Parameters["micalg"]   = micalg;


                // add the modified/parsed entity as our first part
                signed.Add(mimeBodyPart);

                var cmsSigner = new CmsSigner(this.ourCertificate, this.privateKey)
                {
                    DigestAlgorithm = algorithm
                };
                ApplicationPkcs7Signature signature;
                using (var memory = new MemoryBlockStream())
                {
                    // var prepared = Prepare(entity, memory);
                    mimeBodyPart.WriteTo(memory);
                    memory.Position = 0;

                    // sign the cleartext content
                    signature = ctx.Sign(cmsSigner, memory);
                }

                // add the detached signature as the second part
                signed.Add(signature);

                // Create and sign message
                multipart = signed;
            }

            var message = new MimeMessage();

            message.Body = multipart;

            return(message);
        }
示例#20
0
 /*
  * extracts body parts from message and put into node
  */
 private static void ExtractBody(
     IEnumerable <MimeEntity> entities,
     Node node,
     bool skipSignature,
     MimeMessage msg,
     string basePath,
     string attachmentDirectory,
     string linkedAttachmentDirectory)
 {
     foreach (MimeEntity idxBody in entities)
     {
         if (idxBody is TextPart)
         {
             TextPart tp = idxBody as TextPart;
             if (idxBody.ContentType.MediaType == "text")
             {
                 if (idxBody.ContentType.MediaSubtype == "plain")
                 {
                     node["body"]["plain"].Value = tp.Text;
                 }
                 else if (idxBody.ContentType.MediaSubtype == "html")
                 {
                     node["body"]["html"].Value = CleanHtml(tp.Text);
                 }
             }
         }
         else if (idxBody is ApplicationPkcs7Mime)
         {
             ApplicationPkcs7Mime pkcs7 = idxBody as ApplicationPkcs7Mime;
             if (pkcs7.SecureMimeType == SecureMimeType.EnvelopedData)
             {
                 try
                 {
                     MimeEntity entity = pkcs7.Decrypt();
                     ExtractBody(new MimeEntity[] { entity }, node, false, msg, basePath, attachmentDirectory, linkedAttachmentDirectory);
                     node["encrypted"].Value = true;
                 }
                 catch (Exception err)
                 {
                     // couldn't decrypt
                     node["body"]["plain"].Value = "couldn't decrypt message, exceptions was; '" + err.Message + "'";
                     node["encrypted"].Value     = true;
                 }
             }
         }
         else if (!skipSignature && idxBody is MultipartSigned)
         {
             MultipartSigned signed = idxBody as MultipartSigned;
             bool            valid  = false;
             foreach (IDigitalSignature signature in signed.Verify())
             {
                 valid = signature.Verify();
                 if (!valid)
                 {
                     break;
                 }
             }
             node["signed"].Value = valid;
             ExtractBody(new MimeEntity[] { signed }, node, true, msg, basePath, attachmentDirectory, linkedAttachmentDirectory);
         }
         else if (idxBody is Multipart)
         {
             Multipart mp = idxBody as Multipart;
             ExtractBody(mp, node, false, msg, basePath, attachmentDirectory, linkedAttachmentDirectory);
         }
         else if (idxBody is MimePart)
         {
             // this is an attachment
             ExtractAttachments(idxBody as MimePart, msg, node, basePath, attachmentDirectory, linkedAttachmentDirectory);
         }
     }
 }
示例#21
0
 protected internal override void VisitMultipartSigned(MultipartSigned signed)
 {
     MultipartSigned++;
     base.VisitMultipartSigned(signed);
 }
示例#22
0
 /// <summary>
 /// Visit the multipart/signed MIME entity.
 /// </summary>
 /// <remarks>
 /// Visits the multipart/signed MIME entity.
 /// </remarks>
 /// <param name="signed">The multipart/signed MIME entity.</param>
 protected internal virtual void VisitMultipartSigned(MultipartSigned signed)
 {
     VisitMultipart(signed);
 }
示例#23
0
        protected ITransmissionResponse HandleResponse(HttpResponse httpResponse)
        {
            Trace span = this.root.Child();

            // tracer.newChild(root.context()).name("response").start();
            span.Record(Annotations.ServiceName("response"));
            span.Record(Annotations.ClientSend());

            try
            {
                HttpResponse response = httpResponse;
                span.Record(Annotations.Tag("code", response.StatusCode.ToString()));

                // span.tag("code", String.valueOf(response.getStatusLine().getStatusCode()));

                if (response.StatusCode != HttpStatusCode.OK)
                {
                    Logger.ErrorFormat(
                        "AS2 HTTP POST expected HTTP OK, but got : {0} from {1}",
                        response.StatusCode,
                        this.transmissionRequest.GetEndpoint().Address);

                    // Throws exception
                    this.HandleFailedRequest(response);
                }

                // handle normal HTTP OK response
                Logger.DebugFormat(
                    "AS2 transmission to {0} returned HTTP OK, verify MDN response",
                    this.transmissionRequest.GetEndpoint().Address);

                string contentTypeHeader = response.Headers["Content-Type"];
                if (string.IsNullOrWhiteSpace(contentTypeHeader))
                {
                    throw new HyperwayTransmissionException(
                              "No Content-Type header in response, probably a server error.");
                }

                // Read MIME Message
                MimeMessage mimeMessage;
                using (var m = new MemoryStream())
                {
                    // Add headers to MIME Message
                    foreach (var headerName in response.Headers.AllKeys)
                    {
                        var headerText = $"{headerName}: {response.Headers[headerName]}";
                        var headerData = Encoding.ASCII.GetBytes(headerText);
                        m.Write(headerData, 0, headerData.Length);
                        m.Write(new byte[] { 13, 10 }, 0, 2);
                    }
                    m.Write(new byte[] { 13, 10 }, 0, 2);

                    var messageData = response.Entity.Content;
                    m.Write(messageData, 0, messageData.Length);


                    m.Seek(0, SeekOrigin.Begin);
                    mimeMessage = MimeMessage.Load(m);
                    mimeMessage.Headers[HeaderId.ContentType] = response.Headers["Content-Type"];
                }

                SMimeReader sMimeReader = new SMimeReader(mimeMessage);

                // Timestamp of reception of MDN
                Timestamp t3 = this.timestampProvider.Generate(sMimeReader.GetSignature(), Direction.OUT);

                MultipartSigned signedMessage = mimeMessage.Body as MultipartSigned;
                using (this.secureMimeContext())
                {
                    Debug.Assert(signedMessage != null, nameof(signedMessage) + " != null");

                    var signatures      = signedMessage.Verify();
                    var signature       = signatures.First();
                    var mimeCertificate = signature.SignerCertificate as SecureMimeDigitalCertificate;


                    // Verify if the certificate used by the receiving Access Point in
                    // the response message does not match its certificate published by the SMP
                    Debug.Assert(mimeCertificate != null, nameof(mimeCertificate) + " != null");
                    X509Certificate certificate = mimeCertificate.Certificate;
                    if (!this.transmissionRequest.GetEndpoint().Certificate.Equals(certificate))
                    {
                        throw new HyperwayTransmissionException(
                                  String.Format(
                                      "Certificate in MDN ('{0}') does not match certificate from SMP ('{1}').",
                                      certificate.SubjectDN,                                          // .getSubjectX500Principal().getName(),
                                      this.transmissionRequest.GetEndpoint().Certificate.SubjectDN)); // .getSubjectX500Principal().getName()));
                    }

                    Logger.Debug("MDN signature was verified for : " + certificate.SubjectDN);
                }


                // Verifies the actual MDN
                MdnMimeMessageInspector mdnMimeMessageInspector = new MdnMimeMessageInspector(mimeMessage);
                String msg = mdnMimeMessageInspector.GetPlainTextPartAsText();

                if (!mdnMimeMessageInspector.IsOkOrWarning(new Mic(this.outboundMic)))
                {
                    Logger.ErrorFormat("AS2 transmission failed with some error message '{0}'.", msg);
                    throw new HyperwayTransmissionException(String.Format("AS2 transmission failed : {0}", msg));
                }

                // Read structured content
                MimeEntity mimeBodyPart    = mdnMimeMessageInspector.GetMessageDispositionNotificationPart();
                var        internetHeaders = mimeBodyPart.Headers;
                // InternetHeaders internetHeaders = new InternetHeaders((InputStream)mimeBodyPart.getContent());

                // Fetch timestamp if set
                DateTime date = t3.GetDate();
                if (internetHeaders.Any(x => x.Field == MdnHeader.Date))
                {
                    var dateText = internetHeaders.First(x => x.Field == MdnHeader.Date).Value;
                    date = As2DateUtil.Rfc822.Parse(dateText);
                }


                // Return TransmissionResponse
                return(new As2TransmissionResponse(
                           this.transmissionIdentifier,
                           this.transmissionRequest,
                           this.outboundMic,
                           MimeMessageHelper.ToBytes(mimeMessage),
                           t3,
                           date));
            }
            catch (TimestampException e)
            {
                throw new HyperwayTransmissionException(e.Message, e);
            }
            catch (Exception e)
            {
                throw new HyperwayTransmissionException("Unable to parse received content.", e);
            }
            finally
            {
                span.Record(Annotations.ClientRecv());
            }
        }