Posts Tagged ‘DKIM’

System.Net.Mail vs Mail.dll

Monday, December 17th, 2012

In this article we’ll try to describe advantages of Mail.dll over standard .NET System.Net.Mail namespace.

The fundamental difference is that with System.Net.Mail you can’t receive emails. System.Net.Mail does not have support for POP3 and IMAP protocols – two fundamental protocols for email retrieval, also .NET does not have any classes that would parse received email.

System.Net.Mail is great for sending simple emails, but Mail.dll gives you much more, even in terms of sending. You get appointments (iCal) and vCard support, you can send S/MIME signed and encrypted emails (if you plan to use EDI). It gives you easy to use template engine and VERP support out-of-the-box.

Here’s the comparison chart:

System.Net.Mail Mail.dll component
Send emails yes yes
SMTP protocol support (over SSL/TLS) yes yes
Send emails using VERP no yes
Send S/MIME encrypted emails no yes
Send S/MIME signed emails no yes
Send S/MIME signed emails (detached) no yes
Send DKIM (Domain Key Identified Mail) no yes
Templates support no yes
Receive emails no yes
IMAP protocol support (over SSL/TLS) no yes
POP3 protocol support (over SSL/TLS) no yes
Retrieve and parse emails no yes
Extract HTML, plain text, images no yes
Attachment retrieval no yes
Send and retrieve iCalendar appointments no yes
Send and retrieve vCards no yes
OAuth 1.1a/2.0 support no yes
Spam filter no yes
Bounce handling no yes
Convert HTML only emails to plain text no yes

If you need help or more information about any of these features visit Mail.dll samples.

Sign emails with DKIM

Sunday, December 2nd, 2012

DKIM is short for DomainKeys Identified Mail. It is a method for associating a domain name to an email message. It allows a person, role, or organization (domain owner) to claim some responsibility for the message.

DKIM adds a digital signature to the email message headers (using DKIM-Signature field), which can be validated by recipients. Signer also puts his/hers public key in the TXT DNS record. The verifier recovers the signer’s public key from the specified DNS record, and then verifies that the signature matches the message’s content.

Usually DKIM signature covers several most important message headers (From:, Subject:) and the message body.

The DKIM-Signature header field apart from the actual signature signature contains the domain name, the list of covered header fields, the signing algorithm, and the method by which text snippets are simplified for signing purposes (canonicalization).

Create private/public key for DKIM

The easiest way to generate public and private key for DKIM purposes is to use OpenSSL. The output is already Base64 encoded and ready to be used when createing DNS record and signing an email.

To create a private key:
openssl genrsa -out private.key 1024

To create a public key using the private key:
openssl rsa -in private.key -pubout -out public.key

Full listing follows:


c:\>openssl genrsa -out dkim_private.key 1024

Loading 'screen' into random state - done
Generating RSA private key, 1024 bit long modulus
...++++++
..++++++
e is 65537 (0x10001)

c:\>openssl rsa -in dkim_private.key -pubout -out dkim_public.key
writing RSA key

c:\>

Create DNS record for DKIM

Copy your public key from dkim_public.key file. Copy everything between “—–BEGIN PUBLIC KEY—–” and “—–END PUBLIC KEY—–” and remove new lines:


-----BEGIN PUBLIC KEY-----
MIG...AQAB
-----END PUBLIC KEY-----

Simplest DKIM DNS record has following format:

"v=DKIM1; p=MIG...AQAB; t=s"

  • v – is DKIM version (must be DKIM1)
  • p – is your public key
  • t=s – specifies that domain does not send mail using any subdomains
    • You can create such record manually or use many online DKIM DNS Record Creation Tools.

      Now choose your selector name. It can be any string, it can identify departments or even individual users. In this example we’ll use “alpha” as our selector name.

      The name of the DKIM TXT record is created as follows:

      selector + "._domainkey"

      e.g.: alpha._domainkey

      Now you’ll need to add this record to your DNS.

      Send DKIM signed message

      Sending DKIM signed messages is simple using Mail.dll .NET email component. First we’ll use PemReader class to create RSACryptoServiceProvider from the private key stored on disk in pem format. Then we’ll use Smtp class to connect and authenticate to our SMTP server and send the email message:

      // C#
      
      RSACryptoServiceProvider rsa = new PemReader().ReadPrivateKeyFromFile(@"d:\dkim_private.key");
      
      IMail email = Limilabs.Mail.Fluent.Mail.Text("text")
             .From("alice@example.com")
             .To("bob@mail.com")
             .Subject("subject")
             .DKIMSign(rsa, "alpha", "example.com")
             .Create();
      
      using(Smtp smtp = new Smtp())
      {
          smtp.Connect("smtp.example.com");  // or ConnectSSL for SSL
          smtp.UseBestLogin("alice@example.com", "password");
          smtp.SendMessage(email);                     
          smtp.Close();   
      } 
      
      ' VB.NET
      
      Dim rsa As RSACryptoServiceProvider = New PemReader().ReadPrivateKeyFromFile("d:\dkim_private.key")
      
      Dim email As IMail = Mail _
      		.Text("text") _
      		.From("alice@example.com") _
      		.[To]("bob@mail.com") _
      		.Subject("subject") _
      		.DKIMSign(rsa, "alpha", "example.com") _
      		.Create()
      
      Using smtp As New Smtp()
      	smtp.Connect("smtp.example.com")
      	' or ConnectSSL for SSL
      	smtp.UseBestLogin("alice@example.com", "password")
      	smtp.SendMessage(email)
      	smtp.Close()
      End Using
      

      Verify DKIM signed message

      Mail.dll .NET email component automatically queries DNS and validates DKIM signed messages:

      // C#
      
      var eml = ...;
      IMail email = new MailBuilder().CreateFromEml(eml);
      if (email.IsDKIMSigned)
      {
          bool isValid = email.CheckDKIMSignature();
      }
      
      ' VB.NET
      
      Dim eml = ...
      Dim email As IMail = New MailBuilder().CreateFromEml(eml)
      If email.IsDKIMSigned Then
          Dim isValid As Boolean = email.CheckDKIMSignature()
      End If
      

      You can use .NET IMAP component to receive messages from the IMAP server.

      Verify DKIM signed message – details

      Under the hood the recipient of the email queries the DNS server for TXT record for selector._domainkey.domainName (in our example it is: “alpha._domainkey.example.com”). Selector and domain name are stored inside the DKIM-Signature: email header. From the DNS record public key is extracted:

      C:\>nslookup
      Default Server:  UnKnown
      Address:  192.168.0.1
      
      > set type=TXT
      > alpha._domainkey.example.com
      Server:  UnKnown
      Address:  192.168.0.1
      
      Non-authoritative answer:
      alpha._domainkey.example.com      text =
      
              "v=DKIM1; p=MIG...AQAB; t=s"
      
      ...
      >
      

      As you can see we (as a receiver) get that same record we (as a sender) set in our DNS, now the recipient can use the p= parameter to get the public key and create RSACryptoServiceProvider . It can be later used to verify the signature.

      You can download .NET email component here.

Import certificate, private or public keys (PEM, CER, PFX)

Tuesday, November 22nd, 2011

Encrypted private key, RSA private key in PEM file

PEM stands for Privacy Enhanced Mail format. The PEM format is the most common format that Certificate Authorities issue certificates in. PEM certificates usually have extensions such as .pem, .crt, .cer, and .key. They are Base64 encoded ASCII files.

PemReader pem = new PemReader();
RSACryptoServiceProvider rsa = pem.ReadEncryptedPrivateKeyFromFile(
   "EncryptedPrivateKey.pem", // "EncryptedRSAPrivateKey.pem"
   "cypher");

This code handles following formats:

PKCS #8 EncryptedPrivateKeyInfo Encrypted Format:

-----BEGIN ENCRYPTED PRIVATE KEY-----
MIICojAcBgoqhkiG9w0BD .....

Private Key (Traditional SSLeay RSAPrivateKey format) Encrypted:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,24A667C253F8A1B9

mKz .....

You can remove the passphrase from the private key using openssl:
openssl rsa -in EncryptedPrivateKey.pem -out PrivateKey.pem

Unencrypted private key in PEM file

PemReader pem = new PemReader();
RSACryptoServiceProvider rsa = pem.ReadPrivateKeyFromFile("PrivateKey.pem");

This code handles following formats:

PKCS #8 PrivateKeyInfo Unencrypted:

-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0B ......

Private Key (Traditional SSLeay RSAPrivateKey format) Unencrypted:

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCcHVm .....

Public key in PEM file

PemReader pem = new PemReader();
RSACryptoServiceProvider rsa = pem.ReadPublicKeyFromFile("PublicKey.pem")

This code handles following formats:

Public Key (SubjecPublicKeyInfo):

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEB .....

Certificate/private key in PFX file

X509Certificate2 certificate  = new X509Certificate2(
   "certificate.pfx",
   "",
   X509KeyStorageFlags.PersistKeySet)

if (certificate.HasPrivateKey)
{
  using (var rsa = (RSACryptoServiceProvider)certificate.PrivateKey)
  {
    // ...
  }
}

Certificate in PEM/CER file

Note: The private key is never stored in a .pem/.cer certificate file.

X509Certificate2 certificate = new X509Certificate2("certificate.cer");

-or-

PemReader pem = new PemReader();
X509Certificate2 certificate = pem.ReadCertificateFromFile("certificate.cer");

This code handles following formats:


-----BEGIN CERTIFICATE-----
MIIFsTCCA5mgAwIBAgIKYQ .....