Sending Encrypted Emails With S/MIME Protocol
(
May 21 2007 - 02:10:15 PM by
Jonathan DeMarks) - [
print article]
Executive Overview
If you've ever needed to send an encrypted email you know the pain of dealing with third party encryption and decryption tools especially if you need to try to explain and support them for people in management. The S/MIME protocol takes care of all the dirty work for you, allowing seemingly transparent encryption and decryption that works beautifully with all the major email applications available today.
The Pain of S/MIME
The problem encountered by programmers is how to programmatically send S/MIME encrypted emails from an automated process without going bald from the almost endless complexity introduced by this method. Today I will present an overview of how an S/MIME email is sent and what is involved in the process as well as hand out some sample code in the form of a C# console application.
How S/MIME Emails Work (Basically…)
In as short terms as possible, a normal email message is just plain text. S/MIME extends this by wrapping that text in binary. It is possible to think of it as stuffing envelopes inside of envelopes (to use a mail analogy.) The email message is the letter, which can then be signed (another envelope) and then encrypted (yet another, possibly metal envelope.)
Show Me the Code
So here’s a simple C# example of just that (I use C# because it is simple to understand and free to use.) It takes a signing certificate, and encrypting certificate, to, from, a subject, a body, the server, its port, and if the email is in HTML or not. The encoding must be in 7bit, but that’s ok because it must be at least that to use attachments (which are not demonstrated but could easily be done.)
using System;
using System.IO;
using System.Text;
using System.Net.Mail;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
namespace EncryptedSMIME
{
class Program
{
static void Main(string[] args)
{
SendEncryptedEmail("Cert.pfx", "thawte.cer",
"\"Noah Body\" <nbody@email.com>",
"\"John Doe\" <jdoe@email.com>",
"Test C# Encrypted HTML EMail",
"This email is encrypted and signed.",
"smtp.singingeels.com", 25, false);
}
static void SendEncryptedEmail(
string SigningCertPath, string EncryptingCertPath,
string To, string From, string Subject, string Body,
string SmtpServer, int SmtpPort, bool HTML)
{
X509Certificate2 SignCert = new X509Certificate2(SigningCertPath, "password");
X509Certificate2 EncryptCert = new X509Certificate2(EncryptingCertPath, "");
StringBuilder Message = new StringBuilder();
Message.AppendLine("Content-Type: text/" + ((HTML) ? "html" : "plain") +
"; charset=\"iso-8859-1\"");
Message.AppendLine("Content-Transfer-Encoding: 7bit");
Message.AppendLine();
Message.AppendLine(Body);
byte[] BodyBytes = Encoding.ASCII.GetBytes(Message.ToString());
EnvelopedCms ECms = new EnvelopedCms(new ContentInfo(BodyBytes));
CmsRecipient Recipient = new CmsRecipient(
SubjectIdentifierType.IssuerAndSerialNumber, EncryptCert);
ECms.Encrypt(Recipient);
byte[] EncryptedBytes = ECms.Encode();
SignedCms Cms = new SignedCms(new ContentInfo(EncryptedBytes));
CmsSigner Signer = new CmsSigner
(SubjectIdentifierType.IssuerAndSerialNumber, SignCert);
Cms.ComputeSignature(Signer);
byte[] SignedBytes = Cms.Encode();
MailMessage Msg = new MailMessage();
Msg.To.Add(new MailAddress(To));
Msg.From = new MailAddress(From);
Msg.Subject = Subject;
MemoryStream ms = new MemoryStream(EncryptedBytes);
AlternateView av = new AlternateView(ms,
"application/pkcs7-mime; smime-type=signed-data;name=smime.p7m");
Msg.AlternateViews.Add(av);
SmtpClient smtp = new SmtpClient(SmtpServer, SmtpPort);
smtp.UseDefaultCredentials = true;
smtp.Send(Msg);
}
}
}
About the Encryption
The encryption used is an asymmetric certificate type. This means that the sender has the public key and the recipient has the private key. If you find yourself sending to a list of people, try to find another way as giving multiple people a private key is not necessarily a good idea from a security perspective, however if the email is only going to one person or to an automated process which further controls security, it is a simple way to get the job done.
Final Words
This is not a simple code example, but it does work. You may take the sample and use it directly or modify for your own uses. Please note the security concerns addressed in the above paragraph and happy coding to you!