尝试使用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获取证书文件并存储它,以便我可以将它与我在尝试发送电子邮件时获得的文件进行比较。这是一种安全且好的方法来进行此验证吗?我也知道实际证书的哈希,并试图用它来与我在发送电子邮件时得到的那个进行比较。这也很有用,虽然在代码行中它几乎是一样的。只是与字符串而不是文件进行比较。这些方法中的任何一种都比其他方式更好吗?
答案 0 :(得分:0)
您的代码只是一个附带问题 - 为什么要将参数object s
,X509Chain chain
和SslPolicyErrors sslPolicyErrors
传递到您的OurCertificateValidation
方法中?它们没有被引用。
答案 1 :(得分:0)
您没有检查证书有效期,也没有检查服务器是否已撤销它。一般来说,正确的证书验证是非常重要的事情。
有效期检查很简单 - 只需检查证书的ValidFrom和ValidTo属性即可。验证的时刻必须介于两者之间。至于撤销检查, - 如果您还有自签名证书,服务器维护人员很可能会费心管理CRL或安装OCSP服务器进行在线验证。因此,您可以在特定情况下跳过此步骤 。
最后,如果服务器将证书更改为另一个合法的证书怎么办?您将需要更改您的代码(或带有证书的文件),不是吗?