анализ подписанной и зашифрованной электронной почты

Я пишу приложение, которое должно уметь читать подписанные и зашифрованные электронные письма и анализировать их содержимое. Я могу заставить все работать нормально только для зашифрованных писем, но не знаю, что делать, когда я получаю электронное письмо, которое также подписано. После того, как я расшифрую это электронное письмо, вместо ожидаемых 4 частей в объекте Multipart, у меня останется только 1 часть в объекте MimePart с именем файла smime.p7m. Я не знаю, как разбить этот файл или проверить подпись. Я нашел документацию по проверке подписи (http://www.mimekit.net/docs/html/Working-With-SMime.htm#Verify), но я не понимаю, как это работает. Очевидно, есть кое-что, чего я просто не понимаю на данный момент.

Ниже приведен пример кода, который я использую. Обратите внимание, что это будет реорганизовано после того, как я все выясню, но этот код до сих пор работает нормально для всех проверенных мной электронных писем, которые не подписаны (могут быть или не могут быть зашифрованы).

public void decryptAndSendEmails()
{
    List<EmailMessage> emails = getEmails();
    foreach (var email in emails)
    {
        var decryptedEmailMessage = new EmailMessage(service);
        MimeMessage message;

        using (var stream = new MemoryStream(email.MimeContent.Content, false))
        {
            message = MimeMessage.Load(stream);
        }

        var pkcs7 = message.BodyParts.OfType<ApplicationPkcs7Mime>().FirstOrDefault();

        if (pkcs7 != null)
        {
            //If the SecureMimeType has not been set as it should, set it to EnvelopedData
            if (pkcs7.SecureMimeType == SecureMimeType.Unknown)
            {
                var content = new MemoryStream();
                pkcs7.Content.DecodeTo(content);
                content.Position = 0;

                pkcs7 = new ApplicationPkcs7Mime(SecureMimeType.EnvelopedData, content);
            }

            using (var ctx = new TemporarySecureMimeContext())
            {
                using (var stream = File.OpenRead(ConfigurationManager.AppSettings["certLocation"]))
                {
                    ctx.Import(stream, ConfigurationManager.AppSettings["certPassword"]);
                }

                var decrypted = pkcs7.Decrypt(ctx);
                var decryptedParts = new List<MimePart>();
                if (decrypted is Multipart)
                {
                    decryptedParts = breakMultiPart((Multipart)decrypted);
                }
                else if (decrypted is MimePart)
                {
                    decryptedParts.Add((MimePart)decrypted);
                }
                else
                {
                    throw new InvalidOperationException("Unknown Mime part found");
                }

                var textParts = decryptedParts.Where(r => r is TextPart);
                var htmlParts = textParts.Where(x => ((TextPart)x).IsHtml);
                var textBodyParts = textParts.Where(x => !((TextPart)x).IsHtml);
                var attachmentParts = decryptedParts.Where(r => !(r is TextPart));

                if (htmlParts.Any())
                {
                    if (htmlParts.Count() > 1)
                    {
                        throw new InvalidOperationException("multiple html body parts.");
                    }
                    var htmlPart = (TextPart)htmlParts.First();
                    decryptedEmailMessage.Body = new MessageBody(BodyType.HTML, htmlPart.Text);
                }
                else
                {
                    //Text body
                    if (textBodyParts.Count() > 1)
                    {
                        throw new InvalidOperationException("multiple text body parts.");
                    }
                    var textPart = (TextPart)textBodyParts.First();
                    decryptedEmailMessage.Body = new MessageBody(BodyType.Text, textPart.Text);
                }

                foreach (var part in attachmentParts)
                {
                    var content = new MemoryStream();
                    part.Content.DecodeTo(content);
                    content.Position = 0;

                        decryptedEmailMessage.Attachments.AddFileAttachment(part.FileName, content);

                    if (!part.IsAttachment)
                    {
                        decryptedEmailMessage.Attachments.First(r => r.Name == part.FileName).IsInline = true;
                        decryptedEmailMessage.Attachments.First(r => r.Name == part.FileName).ContentId = part.ContentId;
                    }
                }
            }
            ////do stuff with decrypted Email
        }

        else
        {
            //The email is not encrypted
            decryptedEmailMessage = email;
            //do stuff with decrypted Email
        }
    }
}

person dmoore1181    schedule 03.01.2019    source источник
comment
FWIW, MimeKit 2.1.2 (выпущенный несколько дней назад) полностью исправляет SecureMimeType.Unknown, так что обходной путь больше не требуется. Тем не менее, каково значение decrypted.ContentType.MimeType? decrypted.GetType() возвращает MimeKit.Cryptography.ApplicationPkcs7Mime? Я могу представить, что расшифрованная часть - это еще одна application/pkcs7-mime часть, которую вы должны вызвать Verify(), но это всего лишь предположение.   -  person jstedfast    schedule 04.01.2019


Ответы (1)


Я наконец понял это, используя комбинацию комментария от @jstedfast и информации, которую я нашел в Невозможно расшифровать p7m с помощью MimeKit. Ниже приведен код для устранения этой проблемы:

public void decryptAndSendEmails()
{
List<EmailMessage> emails = getEmails();

foreach (var email in emails)
{
    var decryptedEmailMessage = new EmailMessage(service);
    MimeMessage message;

    using (var stream = new MemoryStream(email.MimeContent.Content, false))
    {
        message = MimeMessage.Load(stream);
    }

    var pkcs7 = message.BodyParts.OfType<ApplicationPkcs7Mime>().FirstOrDefault();

    if (pkcs7 != null)
    {
        using (var ctx = new TemporarySecureMimeContext())
        {
            using (var stream = File.OpenRead(ConfigurationManager.AppSettings["certLocation"]))
            {
                ctx.Import(stream, ConfigurationManager.AppSettings["certPassword"]);
            }


            var decrypted = pkcs7.Decrypt(ctx);

            if (decrypted != null && decrypted is MimePart && ((MimePart)decrypted).FileName == "smime.p7m")
            {
                //We need to verify the signature
                var signedDecryptedEntity = decrypted as ApplicationPkcs7Mime;
                signedDecryptedEntity.Verify(ctx, out decrypted); //the real decrypted data
            }

            var decryptedParts = new List<MimePart>();
            if (decrypted is Multipart)
            {
                decryptedParts = breakMultiPart((Multipart)decrypted);
            }
            else if (decrypted is MimePart)
            {
                decryptedParts.Add((MimePart)decrypted);
            }
            else
            {
                throw new InvalidOperationException("Unknown Mime part found");
            }

            var textParts = decryptedParts.Where(r => r is TextPart);
            var htmlParts = textParts.Where(x => ((TextPart)x).IsHtml);
            var textBodyParts = textParts.Where(x => !((TextPart)x).IsHtml);
            var attachmentParts = decryptedParts.Where(r => !(r is TextPart));

            if (htmlParts.Any())
            {
                if (htmlParts.Count() > 1)
                {
                    throw new InvalidOperationException("multiple html body parts.");
                }
                var htmlPart = (TextPart)htmlParts.First();
                decryptedEmailMessage.Body = new MessageBody(BodyType.HTML, htmlPart.Text);
            }
            else
            {
                //Text body
                if (textBodyParts.Count() > 1)
                {
                    throw new InvalidOperationException("multiple text body parts.");
                }
                var textPart = (TextPart)textBodyParts.First();
                decryptedEmailMessage.Body = new MessageBody(BodyType.Text, textPart.Text);
            }

            foreach (var part in attachmentParts)
            {
                var content = new MemoryStream();
                part.Content.DecodeTo(content);
                content.Position = 0;

                decryptedEmailMessage.Attachments.AddFileAttachment(part.FileName, content);

                if (!part.IsAttachment)
                {
                    decryptedEmailMessage.Attachments.First(r => r.Name == part.FileName).IsInline = true;
                    decryptedEmailMessage.Attachments.First(r => r.Name == part.FileName).ContentId = part.ContentId;
                }
            }
        }
        //Do Something with email (decryptedEmailMessage)
    }

    else
    {
        //The email is not encrypted
        decryptedEmailMessage = email;
        //Do Something with email (decryptedEmailMessage)
    }

}

}

person dmoore1181    schedule 04.01.2019