There are three parts to using DKIM Core.
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.
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.
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.
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.
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.
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=
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.
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.
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.