Chapter 5: Secure Email

Contents

5.1 Introduction to Secure Email

To send email to a user securely, the email message needs to be encrypted with this user's public key (certificate.) Even if the message is intercepted, it cannot be read since only the intended recipient has the private key capable of decrypting it. A message can also be digitally signed by the sender's private key. This way, the sender's identity is authenticated by the recipient, and the integrity of the message is validated. Finally, a message can first be digitally signed and then encrypted.

The certificate-based cryptographic functionality of AspEncrypt can be combined with the email-sending functionality of AspEmail to send encrypted email, digitally signed email, and email that is first signed and then encrypted.

Persits Software AspEmail is our powerful free email component designed to work in tandem with AspEncrypt to send secure email in S/MIME format. To run the code samples of this chapter, you need to have AspEmail installed on your machine. AspEmail can be downloaded here.

To be able to read encrypted email, you need to obtain a personal digital certificate from a certification authority of your choice. We recommend InstantSSL by COMODO who offers free personal certificates. You also need to use an S/MIME-enabled email reader such as Outlook, Outlook Express, Mozilla Thunderbird, Windows Live Mail, etc.

5.2 CryptoMessage Object

AspEncrypt provides a special object, CryptoMessage, which encapsulates certificate-based encryption and digital signature functionality. An instance of the CryptoMessage object is created via the CryptoContext method CreateMessage. This method accepts an optional Boolean argument which should always be set to True to specify strong 168-bit Triple-DES encryption:

Set CM = Server.CreateObject("Persits.CryptoManager")
Set Context = CM.OpenContext( "", True )
Set Msg = Context.CreateMessage( True )
ICryptoManager objCM = new CryptoManager();
ICryptoContext objContext = objCM.OpenContext( "", true, Missing.Value );
ICryptoMessage objMsg = objContext.CreateMessage( true );

The CryptoMessage object then needs to be associated with one or several encrypting certificates via the method AddRecipientCert, or a single signing certificate via the method SetSignerCert. After that, the CryptoMessage object is passed to AspEmail's SendEncrypted, SendSigned, or SendSignedAndEncrypted methods to send signed and/or encrypted email as shown below.

The AddRecipientCert method can be called multiple times on the same CryptoMessage object with different certificates. The message will then be encrypted with all these certificates and can be decrypted by any one of the corresponding private keys.

5.3 Encrypted Email

To send encrypted email, the recipient certificate needs to be assigned to the CryptoMessage object via the AddRecipientCert method, and then this CryptoMessage object needs to be passed to AspEmail's SendEncrypted method as the argument.

Set CM = Server.CreateObject("Persits.CryptoManager")

' Create instance of AspEmail
Set Mail = Server.CreateObject("Persits.MailSender")

Set Context = CM.OpenContext("", True )

' Replace this with your own certificate path
CertPath = Server.MapPath("mycert.cer")
Set RecipientCert = CM.ImportCertFromFile( CertPath )

' Retrieve Email address from the certificate itself
Email = RecipientCert.Subject("e")

Set Msg = Context.CreateMessage( True )
Msg.AddRecipientCert RecipientCert

' Replace with your own SMTP server's address
Mail.Host = "smtp.mycompany.com"

Mail.Subject = "Encrypted message"
Mail.From = "sales@veryhotcakes.com"
Mail.FromName = "Very Hot Cakes, Inc."

Mail.AddAddress Email
Mail.Body = "Here is your receipt."

Mail.SendEncrypted Msg ' Use CryptoMessage object
ICryptoManager objCM = new CryptoManager();

// Create instance of AspEmail
IMailSender objMail = new MailSender();
ICryptoContext objContext = objCM.OpenContext( "", true, Missing.Value );
ICryptoMessage objMsg = objContext.CreateMessage( true );

// Replace this with your own certificate path
String strCertPath = Server.MapPath("mycert.cer");
ICryptoCert objRecipientCert = objCM.ImportCertFromFile( strCertPath );

// Retrieve Email address from the certificate itself
String strEmail = objRecipientCert.Subject["e"];

objMsg.AddRecipientCert( objRecipientCert );
// Replace with your own SMTP server's address
objMail.Host = "smtp.mycompany.com";

objMail.Subject = "Encrypted message";
objMail.From = "sales@veryhotcakes.com";
objMail.FromName = "Very Hot Cakes, Inc.";

objMail.AddAddress( strEmail, Missing.Value );

objMail.Body = "Here is your receipt.";
// Use CryptoMessage object
objMail.SendEncrypted( objMsg );

To send an encrypted message to yourself with the code sample above, you need to export your personal certificate into a .cer file. The code sample will attempt to open the file mycert.cer from the /Samples/manual_05 folder. Change the .cer file location in the script if necessary. You also need to change the value of the Mail.Host property to point to your own SMTP server.

Click the links below to run this code sample:

5.4 Signed Email

Signed email involves the sender's private key. Using the CertMover.exe utility included with the installation, you should move the signer certificate from the HKEY_CURRENT_USER to HKEY_LOCAL_MACHINE section of the registry before sending signed email in an ASP/ASP.NET environment.

To generate a digital signature, the CryptoMessage object must be assigned an instance of the CryptoCert object representing the signer certificate using the SetSignerCert method. This certificate must have an associated private key. The CryptoMessage object is then passed to AspEmail's SendSigned method.

The following code sample sends a signed email message using a certificate located in the MY store of the HKLM section of the registry:

Set CM = Server.CreateObject("Persits.CryptoManager")

' Create instance of AspEmail
Set Mail = Server.CreateObject("Persits.MailSender")

Set Context = CM.OpenContext("", True )

CM.LogonUser "domain", "account", "password""

Set Store = CM.OpenStore( "MY", True )
Set SenderCert = _
   Store.Certificates("d5 b9 c8 38 8f fb 41 b0 43 d6 47 2b b9 58 44 5e")

Set Msg = Context.CreateMessage( True )
Msg.SetSignerCert SenderCert

' Replace with your own SMTP server's address
Mail.Host = "smtp.mycompany.com"

Mail.Subject = "Signed message"
Mail.From = SenderCert.Subject("e")
Mail.FromName = "Very Hot Cakes, Inc."

Mail.AddAddress "name@company.com"
Mail.Body = "Here is your receipt."

Mail.SendSigned Msg ' Use CryptoMessage object
ICryptoManager objCM = new CryptoManager();

// Create instance of AspEmail
IMailSender objMail = new MailSender();

ICryptoContext objContext = objCM.OpenContext( "", true, Missing.Value );

objCM.LogonUser( "domain", "account", "password", Missing.Value );
ICryptoStore objStore = objCM.OpenStore( "MY", true );
ICryptoCert objSenderCert =
   objStore.Certificates["d5 b9 c8 38 8f fb 41 b0 43 d6 47 2b b9 58 44 5e"];

ICryptoMessage objMsg = objContext.CreateMessage( true );
objMsg.SetSignerCert( objSenderCert );

// Replace with your own SMTP server's address
objMail.Host = "smtp.mycompany.com";

objMail.Subject = "Signed message";
objMail.From = objSenderCert.Subject["e"];
objMail.FromName = "Very Hot Cakes, Inc.";

objMail.AddAddress( "name@company.com", Missing.Value );
objMail.Body = "Here is your receipt.";

// Use CryptoMessage object
objMail.SendSigned( objMsg );

Before running this code sample, you need to modify it to use your own certificate's serial number, and pass your own email address to the AddAddress method.

Click the links below to run this code sample:

You can also supply your signer certificate in a PFX (PKCS#12) file. A .pfx file can be obtained by exporting a certificate from your personal certificate store along with its private key as described in the previous chapter.

Once the .pfx file is created, you can place it on the server where AspEncrypt can access it via the CryptoContext method OpenStoreFromPFX. The following code fragment can be used to retrieve the signer certificate. Note that there is no need to move the certificate to the HKEY_LOCAL_MACHINE section of the registry.

...
Set Store = CM.OpenStoreFromPFX("c:\path\cert.pfx", "password")
Set SignerCert = Store.Certificates(1)
...
...
ICryptoStore objStore = objCM.OpenStoreFromPFX( @"c:\path\cert.pfx", "password" );
ICryptoCert objSignerCert = objStore.Certificates[1];
...

5.5 Signed and Encrypted Email

To send a mail message which is first signed and then encrypted, two instances of the CryptoMessage object must be used: one for signing and the other for encryption. Once the CryptoMessage objects are created and assigned the appropriate certificates, they are both passed to AspEmail's SendSignedAndEncrypted method, as follows:

Set CM = Server.CreateObject("Persits.CryptoManager")
' Create instance of AspEmail
Set Mail = Server.CreateObject("Persits.MailSender")

Set Context = CM.OpenContext("", True )

CM.LogonUser "domain", "account", "password"

' Obtain signer cert
Set Store = CM.OpenStore( "MY", True )
Set SenderCert = _
   Store.Certificates("d5 b9 c8 38 8f fb 41 b0 43 d6 47 2b b9 58 44 5e")

Set Msg1 = Context.CreateMessage( True )
Msg1.SetSignerCert SenderCert

' Replace this with your own certificate path
CertPath = Server.MapPath("mycert.cer")
Set RecipientCert = CM.ImportCertFromFile( CertPath )

Set Msg2 = Context.CreateMessage
Msg2.AddRecipientCert RecipientCert

' Replace with your own SMTP server's address
Mail.Host = "smtp.mycompany.com"

Mail.Subject = "Signed & Encrypted message"
Mail.From = SenderCert.Subject("e")
Mail.FromName = "Very Hot Cakes, Inc."

Mail.AddAddress RecipientCert.Subject("e")
Mail.Body = "Here is your receipt."
ICryptoManager objCM = new CryptoManager();

// Create instance of AspEmail
IMailSender objMail = new MailSender();

ICryptoContext objContext = objCM.OpenContext( "", true, Missing.Value );

objCM.LogonUser( "domain", "account", "password", Missing.Value );

// Obtain signer cert
ICryptoStore objStore = objCM.OpenStore( "MY", true );
ICryptoCert objSenderCert =
   objStore.Certificates["d5 b9 c8 38 8f fb 41 b0 43 d6 47 2b b9 58 44 5e"];

ICryptoMessage objMsg1 = objContext.CreateMessage( true );
objMsg1.SetSignerCert( objSenderCert );

// Replace this with your own certificate path
String strCertPath = Server.MapPath("mycert.cer");
ICryptoCert objRecipientCert = objCM.ImportCertFromFile( strCertPath );

ICryptoMessage objMsg2 = objContext.CreateMessage( true );
objMsg2.AddRecipientCert( objRecipientCert );

// Replace with your own SMTP server's address
objMail.Host = "smtp.mycompany.com";

objMail.Subject = "Signed & Encrypted message";
objMail.From = objSenderCert.Subject["e"];
objMail.FromName = "Very Hot Cakes, Inc.";

objMail.AddAddress( objRecipientCert.Subject["e"], Missing.Value );
objMail.Body = "Here is your receipt.";

// Use CryptoMessage object
objMail.SendSignedAndEncrypted( objMsg1, objMsg2 );

Click the links below to run this code sample:

5.6 Live Demos

The secure email functionality of AspEncrypt and AspEmail are demonstrated by the following live demo applications hosted on our server:

Chapter 4: Certificates and Certificate Stores Chapter 6: Digital Signatures