C #: отправка электронных писем безопасным способом правильно - PullRequest
2 голосов
/ 10 июня 2010

Экспериментировал с отправкой защищенных писем с использованием C # и задавался вопросом, правильно ли я все понял. В настоящее время у меня есть следующая программа:

using System;
using System.Net.Mail;
using System.Net;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.IO;
using System.Net.Security;

namespace Geekality.SecureEmail
{
    class Program
    {
        static bool OurCertificateValidation(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            var actualCertificate = X509Certificate.CreateFromCertFile("example.com.cert");

            return certificate.Equals(actualCertificate);
        }

        static void Main(string[] args)
        {
            // Register our own certificate validation
            ServicePointManager.ServerCertificateValidationCallback = OurCertificateValidation;

            // Message
            var from = new MailAddress("me@example.com", "Me");
            var to = new MailAddress("you@example.com", "Myself");

            var message = new MailMessage(from, to)
            {
                Subject = "Greetings!",
                Body = "How are you doing today?",
            };

            // Create client
            var client = new SmtpClient("smtp.example.com")
            {
                EnableSsl = true,
                Credentials = new NetworkCredential
                {
                    UserName = "me@example.com",
                    Password = "password",
                },
            };

            // Try to send
            using (client)
            {
                try
                {
                    client.Send(message);
                    Console.WriteLine("Message sent!");
                }
                catch (AuthenticationException e)
                {
                    Console.WriteLine("Authentication failed:");
                    Console.WriteLine(e.Message);
                }
                catch (SmtpException e)
                {
                    Console.WriteLine("SMTP error:");
                    Console.WriteLine(e.Message);
                }
            }

            Console.ReadKey(true);
        }
    }
}

Хотя данные были изменены на примерные значения. В любом случае, похоже, это хорошо работает из того, что я вижу. Любые комментарии о том, что я сделал? Особенно в том, как я делаю проверку сертификата. Это хороший способ сделать это? Или я пропустил что-то настолько плохое, что я мог бы также отправить письмо, не используя SSL?

Причина, по которой я выполняю проверку самостоятельно, заключается в том, что проверка по умолчанию завершилась неудачно, поскольку это сертификат, выданный самим собой, и почтовый домен, который я использую, отличается от используемого в сертификате. Я использую mail.mydomain.com , в то время как домен в сертификате выглядит как mywebhost.com . Поэтому я получил файл сертификата от Opera, используя его почтовый клиент, и сохранил его, чтобы я мог сравнить его с файлом, полученным при попытке отправить письмо. Это безопасный и хороший способ сделать эту проверку? Я также знаю хэш фактического сертификата и пытался использовать его для сравнения с тем, который я получаю при отправке электронного письма. Это также работает и было немного легче сделать, хотя в строках кода это почти то же самое. Просто сравнивая со строкой вместо файла. Является ли один из этих способов лучше, чем другой?

Ответы [ 2 ]

0 голосов
/ 10 июня 2010

Вы не проверяете срок действия сертификата и не проверяете, не был ли он отозван сервером.В общем, правильная проверка сертификата - вещь очень нетривиальная.

Проверка срока действия тривиальна - просто проверьте свойства сертификата ValidFrom и ValidTo.Момент проверки должен соответствовать между ними.Что касается проверки отзыва, - если у вас в любом случае есть самозаверяющий сертификат, есть небольшая вероятность того, что сопровождающие сервера потрудятся управлять списками отзыва сертификатов или установят сервер OCSP для онлайн-проверки.Таким образом, вы можете пропустить этот шаг в вашем конкретном случае .

Наконец, что если сервер поменяет сертификат на другой законный?Вам нужно будет изменить свой код (или файл с сертификатом), не так ли?

0 голосов
/ 10 июня 2010

Просто дополнительный вопрос к вашему коду - почему вы передаете параметры object s, X509Chain chain и SslPolicyErrors sslPolicyErrors в ваш метод OurCertificateValidation?На них не ссылаются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...