Skip to content

DomainKeys Identified Mail

Introduction

DomainKeys Identified Mail (DKIM) is used to detect if an e-mail is spoofed (forged).

It's used to prevent spam and phishing. Signing your mail with DKIM will help

detect spam that pretends to come from your domain. It also ensures that your

letters pass spam filter checks. Otherwise, letters you send may not end up in the

inbox.

An email is signed with a private key. This allows the receiver to check if the email

comes from the domain it claims to be from. The receiver looks up the sender's

public key in the domain's DNS record. A valid signature guarantees that the sending

mail server has access to the private key and that the email body has not been

tampered with during transit.

DKIM, SPF, and DMARC are designed to work together.

DKIM Header

In our setup, the mail server will sign the message with its private key. Here

is what the DKIM header looks like:

DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=mail; bh=gVJEBqfjoVwtQhV
        vV3FHh0UQBW0m9unTpuaaGORFGKI=; h=subject:date:from;
        d=example.com; b=Jv/9zpB2AJGosO4/uYlZxFEm1UFOTy56JBi/nhsjg
        Am5Qe+rkuKYru5mSqvP01ii/sQRI4exNbG/S8ihdcEXsr5fr8yK4IvLkY8jO5O0xMhblyS
        PbFGMw7SW2AwLWu95OyHK5teZPzE/SS5U39Zlqs7tS1m8iZo2tPBa70t9204na8/eOT6N7
        8IzNIfRHJfF4dNGVX61t9xknkcJrJdC6npO0l4MVTky66safTbcCjlM6JihbUd5j4uOU5I
        WREE02CLQKWg5c/UnjQQ96Dt308f2RvxeWA6P8hxsjD/FLDIR2U1ZEQyo7k03KCJbdRVw8
        IHJTdENGGL3p7aM1v8wdg==

|| border=1 width=100%25 class="sortable simpletable"

||# Tag ||# Indicates ||# Example ||

|| v || version || v=1 ||

|| a || algorithm || a=rsa-sha256 ||

|| d || domain || d=example.com ||

|| s || selector || s=mail ||

|| c || canonicalization algorithm || c=simple/simple ||

|| h || header fields || h=subject:date:from ||

|| bh || body hash || bh=gVJEBqfjoVwtQhVvV3FHh0UQBW0m9unTpuaaGORFGKI= ||

|| b || signature || b=Jv/9zpB2AJGosO4/uYlZxFEm1UFOTy56JBi/nhsjgAm5Qe+rku\

KYru5mSqvP01ii/sQRI4exNbG/S8ihdcEXsr5fr8yK4IvLkY8j\

O5O0xMhblySPbFGMw7SW2AwLWu95OyHK5teZPzE/SS5U39Zlqs\

7tS1m8iZo2tPBa70t9204na8/eOT6N78IzNIfRHJfF4dNGVX61\

t9xknkcJrJdC6npO0l4MVTky66safTbcCjlM6JihbUd5j4uOU5\

IWREE02CLQKWg5c/UnjQQ96Dt308f2RvxeWA6P8hxsjD/FLDIR\

2U1ZEQyo7k03KCJbdRVw8IHJTdENGGL3p7aM1v8wdg== ||

Tip: Many mail clients let you view the mail headers in the email you receive. If you

display all headers, you can see the DKIM header.

A receiving SMTP server will perform a DNS lookup based on the domain name and selector. In the example above, it will look up the TXT record of mail._domainkey.example.com.

This TXT record returned should look like below:

"k=rsa; t=s; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDmzRmJRQxLEuyYiyMg4suA2Sy
MwR5MGHpP9diNT1hRiwUd/mZp1ro7kIDTKS8ttkI6z6eTRW9e9dDOxzSxNuXmume60Cjbu08gOyhPG3
GfWdg7QkdN6kR4V75MFlw624VY35DaXBvnlTJTgRg/EW72O1DiYVThkyCgpSYS8nmEQIDAQAB"

Security Notes

DKIM-signatures can be used to prove that a mail server sent a letter.

Note that DKIM does not provide end-to-end integrity. For this, both sender and receiver will need to use PGP.

OpenSMTPd and DKIM

For OpenSMTPd to sign its mail with DKIM, you will need to create a public and private

DKIM key:

$ openssl genrsa -out private.key 1024
$ openssl rsa -in private.key -pubout -out public.key
$ chmod og-rwx private.key
$ chmod og-wx public.key
$ chmod u-w public.key private.key
$ doas mkdir /etc/mail/dkim
$ doas mv private.key public.key /etc/mail/dkim/
$ doas chown -R _smtpd:_dovecot /etc/mail/dkim/

We then create a DKIM record by taking the public key, removing the first and last

line, then joining all the lines together:

$ doas cat /etc/mail/dkim/public.key | awk '/-----/{if (NR!=1)print "";next}{printf $0}' -

Running this command on public.key should produce text like the following:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmseF9Dm8Dx1LtmLMD56d628JBNaQus8aEcdYYzvBVQ4rhetZzv/ZMafjTEf2RLoOQ+pb7pqL4G86lCZSF+Eeu2ODWQQGYqGVV0xUK5QJSnsGF5UKKscrxmTHSPPtoAQJt25fxNd3PtvH2ZonAGkZkntk+u6Wn5xxlI9hMOVxLUwIDAQAB

This key should go into the DKIM DNS records:

_adsp._domainkey   86400   IN      TXT     "dkim=discardable;"
mail._domainkey   86400   IN      TXT     "k=rsa; t=s; p=<public key>"

The final result should look like this:

_adsp._domainkey   86400   IN      TXT     "dkim=discardable;"
mail._domainkey   86400   IN      TXT     "k=rsa; t=s; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmseF9Dm8Dx1LtmLMD56d628JBNaQus8aEcdYYzvBVQ4rhetZzv/ZMafjTEf2RLoOQ+pb7pqL4G86lCZSF+Eeu2ODWQQGYqGVV0xUK5QJSnsGF5UKKscrxmTHSPPtoAQJt25fxNd3PtvH2ZonAGkZkntk+u6Wn5xxlI9hMOVxLUwIDAQAB"