DNS-Based Defense: DKIM
Domain Keys Identified Mail (DKIM) lets us lock down who can send an email for our domain via cryptography. It can be used in addition to SPF. When we set up a domain to use DKIM, we add a public key to the DNS records for our domain, and then our mail server uses the corresponding private key to sign our outgoing emails. That way, when the mail server at another domain receives an email claiming to be from our domain, that mail server can look up our public key in DNS and verify that the signature on the email is legitimate.
Joe asks: how do signatures prevent forged email?
Alice wants to send out messages and prove that they came from her. Public key signatures give her a way to do that.
First, Alice creates a public/private key pair. She keeps the private key private but distributes the public key far and wide via DNS. These keys are just really big numbers, hundreds of digits long. But these numbers aren’t chosen at random. There’s a mathematical relationship between them. The relationship between the private and public keys allows for some pretty interesting things:
- Alice can write a message and use the private key to create a signature for the message.
- Bob can look at the message, the signature, and the public key and then harness the power of math to prove that the signature was created by someone who had the private key. If Bob trusts that no one copied the private key from Alice, then Bob knows that Alice wrote the message.
- Eve can’t figure out the private key even if she sees the message, the signature, and the public key.
This just describes what the signatures make possible. If you’d like to read more about the math behind this, read the excellent descriptions in either Serious Cryptography, Cryptography Engineering, or crypto101.io.
Let’s look at how that would play out in our example with Alice and Bob.
Alice wants legitimate emails from her domain, alice.com, to be trusted by other mail servers. With DKIM she can create a public/private key pair for this purpose. She’ll keep the private key on her mail server. She’ll make the public key available as a TXT record for a specific subdomain. Then, when she authenticates to her mail server to send an email to Bob, her mail server will sign the email using the private key. A signed email would have a special DKIM header that would look something like this:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
At first glance, this bunch of gibberish might not inspire a lot of faith. But this actually gives bob.com a lot of information to use to validate the incoming email. Let’s go through each of the tags in this header.
a=rsa-sha256;This tells bob.com what kind of signature is being used. In this case, it’s an RSA signature with an SHA-256 hash. We won’t dig into the relative merits of this particular choice of algorithm. For now, we can be content knowing that alice.com has a way to specify the signature to be used for each outgoing email.
c=relaxed/relaxed;This lets alice.com tell the other mail server that some minor changes to some of the headers could take place and that’s ok. In this case, minor changes are things like capitalization changes and differences in whitespace.
d=alice.com;This tells bob.com what domain is signing this email. Bob will use this when looking up the DNS record to verify the signature.
s=aliceselector;The selector is a DKIM concept that lets bob.com look up the right DNS record. The selector and domain from this example would be used together to look up the TXT record for the following machine via DNS:
aliceselector._domainkey.alice.com. More explicitly, the receiving mail server combines the
the domainto construct the machine name to query in DNS. We’d query that DNS record like this: