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.