DKIM Core

DKIM Core Technical Specification

There are three parts to using DKIM Core.

  1. Create a selector and associated key pair
  2. Publish the public key
  3. Attach the token to each email

Through this document we'll show some concrete examples where the token example.com is being attached to an email using a selector of feb2009.myesp.

1. Create the selector and associated key pair

The selector is used to identify the keys used to attach a token to a piece of email. It does appear in the header of the email sent, but isn’t otherwise visible or meaningful to the final recipient. Any time you generate a new key pair you need to choose a new selector.

A selector is a string of no more than 63 lower-case alphanumeric characters (a-z or 0-9) followed by a period “.”, followed by another string of no more than 63 lower-case alphanumeric characters.

You can choose any string you like as a selector but many DKIM examples assume that new key pairs will be regenerated monthly and use the month as part of the selector string and that’s also the format we use in examples here. There is no security advantage to making the selector long or complex, so something that is short and easy to type is a good choice.

The key pair consists of a private key and a public key. These are a standard RSA key pair, generated as described in RFC 3447 (but there's no need to read the RFC, just use an existing library that complies with it).

As an example, a key pair can be generated using the openssl command line tool:

    openssl genrsa -out example.com.priv 1024
    openssl rsa -in example.com.priv -pubout >example.com.pub

There is an online wizard at dkimcore.org/tools to generate keys for testing.

2. Publish the public key

You publish the public key by creating a “TXT” record in the DNS for the hostname created by concatenating the selector, the literal string “._domainkey.” and the token. Using our example, that would be the hostname feb2009.myesp._domainkey.example.com

The content of the TXT record can be created by concatenating the literal string “v=DKIM1;t=s;n=core;p=” and the public key. Using our example that would be

v=DKIM1;t=s;n=core;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCun+PG2rZvD9wjsgD+3RWLOz5UUXS0wtFFsMyyu2Mn9pNIW+hxgoAhDuQtZTqSZRAxT6p+eoV08NuH2qsn+7pXgrKYyJOxunT6Ak4jlua2Yq6wO7hmdt+jEHhA2zOiRW14yx/rbg3/TWT9+GXtDPGMkXky4d5h1Zzc1EEGbJAplQIDAQAB

(If you use openssl to generate the keys as shown above you only paste the key itself into TXT record, not the surrounding “-----BEGIN PUBLIC KEY-----” and “-----END PUBLIC KEY-----” lines, and you wrap the key into a single long line).

Depending on the nameserver you use you may need to escape the semicolons in the nameserver configuration file.

The key wizard at dkimcore.org/tools can provide sample entries formatted for bind or tinydns.

3. Attach the token to the email

First, make sure the email is in a valid format.

It’s likely that the email will already consist solely of 7-bit ascii characters. If it doesn’t, you'll need to convert it to 7-bit only text, using base64 or quoted-printable content encoding, as described in RFC 2045.

If there are any bare CR or LF characters within the email, convert them to two character CRLF sequences.

Then handle the body and the header of the message separately.

3.1 Find the body hash

First, remove any empty lines at the end of the body. If there is no trailing CRLF at the end of the body, add one. Then take an SHA256 hash of the body, including the final CRLF, as described in RFC 4634. This is the body hash.

3.2 Find the header hash

Then take a subset of the headers - any header in this list:

Then convert these headers to a canonical form. Fold the header names to lower-case. So, "SUBJect: AbC" is converted to "subject: AbC". Then unfold any header that has continuation lines, as described in RFC 2822, so that each header consists of a single line terminated by CRLF.

Then, within each line, replace any sequence of spaces or tabs with a single space. Finally, remove any space before or after the colon that separates the header name from the header content.

For example, these headers

From: steve@example.com
Comments: Some sort of comment
Subject: An Extremely          Long and pedagogic subject line, which we
          will fold here

would become this canonical form

from:steve@example.com
subject:An Extremely Long and pedagogic subject line, which we will fold here

Then create an “empty” DKIM-Signature header, like this:

dkim-signature:v=1;a=rsa-sha256;bh=BODYHASH;c=relaxed;d=TOKEN;h=HEADERS;s=SELECTOR;b=

BODYHASH
replace this with the body hash, base-64 encoded
TOKEN
replace this with the domain you're using as the token
SELECTOR
replace this with the selector associated with the key pair
HEADERS
replace this with a list of the header names that were found in the subset above, e.g. “h=from:subject”. They must be in the same order here as they are in the header.

Then the “empty” DKIM-Signature header is appended to the canonical headers, without a trailing CRLF. Then an SHA256 hash of the canonical headers, including the dkim-signature, is taken as described in RFC 4634. This is the header hash.

Then throw the canonical headers away, they're not needed for anything else.

3.2 Generate the DKIM-Signature header

Sign the header hash using RSA, as decribed in RFC 3447, giving the signature.

Create a DKIM-Signature header:

DKIM-Signature: v=1;a=rsa-sha256;bh=BODYHASH;c=relaxed;d=TOKEN;h=HEADERS;s=SELECTOR;b=SIGNATURE

SIGNATURE is the RSA signature we just calculated, encoded in base-64. BODYHASH, TOKEN, SELECTOR and HEADERS are as described in the previous section.

You can add whitespace, or break the line, after any semicolon.

(If you create this header by reusing the “empty” header in the previous section then you should at least insert a space after the colon separating the header name from the rest of the line.)

Then prepend the DKIM-Signature header to the original message to give the final message with the DKIM Core token attached, ready to send.

3.3 Multiple Tokens

It is possible to attach multiple tokens to an email. (See the deployment guide for some reasons someone may want to do that).

The simplest way to attach multiple tokens to a message is simply to attach the first token a described above, then to take the resulting email and perform the same process again to attach the second token, and so on.

The body of the message, and the headers other than the DKIM-Signature header don’t change, though, and a DKIM Core implementation can take advantage of that to be more efficient. It could create the body hash and a partial hash of the canonical headers just once and reuse that by adding a new “empty” DKIM-Signature header to the header hash for each token.