DomainKeys Identified Mail
- See also: Email authentication for an overview and terminology.
DomainKeys Identified Mail (DKIM) is an email authentication method using a digital signature added to the headers of a message, usually by the Mail Submission Agent. The signature provides strong assurance that there was no alteration of selected headers or the body of a message after it was signed by someone with access to the domain owner's private key.
The signature can be verified by doing a DNS query for a public key in the signer's domain. Thus DKIM security depends on the distribution of public keys through DNS, rather than through a Public Key Infrastructure.
Verification does not depend on IP addresses or the path a message followed from signer to verifier. Thus DKIM avoids the forwarding problem seen by IP-based authentication methods.
DKIM does not prevent "replay" abuse. The advantage of path independence is also a vulnerability. A single signed message may be replayed to a million different recipients, and all will see valid signatures. Without additional evidence of complicity, the signer of a DKIM message cannot be held responsible for replay abuse.
DKIM signatures do not protect the message envelope, which includes the Return Address and the Recipient Addresses. Note, however, that the From: and To: headers can be protected. If you receive an email supposedly from your bank addressed to "Customer", asking for your password or other information that identifies you, that message is probably not from your bank. Rejection of such "phishing" emails could even be automated. Any signed message where the header addresses differ from the envelope addresses should at least be flagged as suspicious.
Another limitation of DKIM is that a message must be received in its entirety to complete the verification. IP-based authentications are generally quicker, as they don't require any processing of data for individual messages.
IP-based and signature-based methods should be treated as complements, not competitors. They each cover a different range of the risk spectrum. If recipients in your domain get a million ads for Viagra, you can hold responsible the domain that authorized the transmission of all those messages (the last hop in a chain of relays). If you are the Treasury Secretary, and you get a message from the Bank of America saying "We agree to sell our bank for $330 billion.", but the DKIM signature fails to verify, you better make a call to confirm.
How it works
Senders that wish to use DKIM should generate one or more public/private key pairs, and publish the public keys as text records under their domain name in DNS. Each key pair should have a different "key selector" (a convenient name like key123). A typical DNS record might look like:
key123._domainkey.example.com. 1800 IN TXT "k=rsa\; h=sha1\; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9QJxtJz2h7HFjbCtSoZtqhp2MXvNEE+5p IYzTPoS2iUw0XfDzggR7NTMLzSG+wtAm0mkW3gORdK8Jxtc5aogZOQSsDAH0pRvXIGSlfXH+bj sNkVbyAruThjCCvRPsUatkiYftoKWVMdR5NzLR2LOusrqXSjMvOmhBT7AyfWeqSQIDAQAB\;"
1) The signer uses the sender's private key to generate a signature of the message body and selected headers, then prepends a signature header to the existing message headers:
DKIM-Signature: v=1; a=rsa-sha1; d=example.com; s=key123; c=simple/simple; q=dns/txt; firstname.lastname@example.org; t=1254853305; h=From:Subject:Date:To:MIME-Version:Content-Type; bh=gfX4RO+Zk2GcDhXrOb73MFSp+9A=; b=WorXlU7jfNMwDEGD2kWjCD3nrvgecLInaLgTRImzQfkPAFDr2izAS718CR2bow0k bMCMhmovbmRBpeD/BDrkZgAzL0lmqn/npatDvRrCqbJbkjqhdAgVpcfWgu17LL4d miAnUtcLCd62WWE1BYBxD+NIiKasRjiLcaf8AHc1QI8=;
2) The verifier extracts from the sig header, the domain (d=example.com) and the key selector (s=key123), and does a DNS query to retrieve the public key from "key123._domainkey.example.com".
3) After receiving the headers, the signature (b=WorX1...) can be verified against the selected headers (h=From:Subject:...) and the body hash (bh=gfX4...), using the specified encryption and hashing algorithms (rsa and sha1). Note that we don't need to have the entire body yet. Inclusion of the body hash in the DKIM header means the signature can be verified as soon as the headers are received.
4) If the result was "pass", all that remains is to hash the body of the message, and compare the new hash against the one in the sig header. If all is well, the verifier can add an authentication header to the message:
Authentication-Results: mta148.mail.re1.yahoo.com from=mail.example.com; domainkeys=pass (ok); from=example.com; dkim=pass (ok)
TXT is the code for a text record in DNS. Text records can store any text strings the domain owner wants to publish.
_domainkey is a "label" used to distinguish DKIM records from other TXT records published by the domain. The underscore is illegal in domain names, but legal in DNS records. This ensures no conflict with any real domain name.
1800 seconds is the lifetime of the DNS record after it has left the server on which it was published. This allows frequently used records to be read from a cache, instead of doing a fresh query every time.
Everything between the double quotes is part of the text string, except the backslashes, which are used to "escape" the semicolons (i.e. the semicolons are part of the record, but not the backslahes). Some additional formatting was done to make this record presentable in this article. It was one long line running off the right edge of the window. In this article, we split it into convenient chunks, and indented the chunks in the style of an email header. The leading whitespace and newlines are not part of the record.
The TXT record for DKIM consists of a number of key=value pairs. This syntax takes a little more space, but it allows for future growth of DKIM by simply adding new key items. This record specifies an encryption algorithm (k=) a hash algorithm (h=) and a public key value (p=). The public key is 216 base64 characters, so it fits easily within DNS limits (255 characters per string, 512 bytes in a DNS packet). Each base64 character encodes 6 bits, so the total key length is 1296 bits (216 * 6), and this is considered quite secure.
The Authentication-Results header above shows that there were actually two signatures in this message. DomainKeys was the predecessor to DKIM, so this is probably a legacy system in the sender's domain.
If a signature is invalid, a receiver might save bandwidth by aborting the data transfer. However, there is no provision in SMTP to do this. Many transmitters will simply ignore anything short of a TCP reset, and keep sending data. Then when there is no reply, they will start over and send the whole message again.
- See section 4.1.4 of RFC-4686 for an analysis of the "chosen message replay attack" and possible defenses.