Sign emails with DKIM

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.

      Tags: , , ,

One Response to “Sign emails with DKIM”

  1. Muhammad Akram Says:

    To send the Sign emails with DKIM is good its a great help.The concept of public key and the private key you have elaborate is informative.The steps you have described above are very clear and can be understand easily.The code in the blog is obviously very good.

Questions?

Consider using our Q&A forum for asking any questions.