RFC 4870
Domain-Based Email Authentication Using Public Keys Advertised in the DNS (DomainKeys)
๐ RFC 4870 โจ
Network Working Group, Request for Comments 4870 ๐
- Title: Domain-Based Email Authentication Using Public Keys Advertised in the DNS (DomainKeys)
- Author: M. Delany, Yahoo! Inc
- Category: Historic
- Date: May 2007
- Obsoleted by: RFC 4871
So this one is Historic, and it's been obsoleted by RFC 4871 ๐
Status of This Memo ๐
Okay, the official vibe check: this memo defines a Historic Document for the Internet community. It does not specify an Internet standard of any kind. Distribution of this memo is unlimited ๐ธ
Copyright Notice ยฉ๏ธ
Copyright (C) The IETF Trust (2007). ๐
Abstract ๐ฎ
"DomainKeys" creates a domain-level authentication framework for email by using public key technology and the DNS to prove the provenance and contents of an email ๐
Here's the big idea: this document defines a framework for digitally signing email on a per-domain basis. The ultimate goal is to unequivocally prove and protect identity while keeping the semantics of Internet email as it is known today. Like, the email still works the way you already know it does ๐ฆ
Proof and protection of email identity may help with the global control of "spam" and "phishing" ๐
Table of Contents ๐๏ธ
1. Introduction ....................................................3
1.1. Lack of Authentication Is Damaging Internet Email ..........3
1.2. Digitally Signing Email Creates Credible Domain
Authentication .............................................4
1.3. Public Keys in the DNS .....................................4
1.4. Initial Deployment Is Likely at the Border MTA .............5
1.5. Conveying Verification Results to MUAs .....................5
1.6. Technical Minutiae Are Not Completely Covered ..............5
1.7. Motivation .................................................6
1.8. Benefits of DomainKeys .....................................6
1.9. Definitions ................................................7
1.10. Requirements Notation .....................................8
2. DomainKeys Overview .............................................8
3. DomainKeys Detailed View ........................................8
3.1. Determining the Sending Address of an Email ................9
3.2. Retrieving the Public Key Given the Sending Domain ........10
3.2.1. Introducing "selectors" ............................10
3.2.2. Public Key Signing and Verification Algorithm ......11
3.2.3. Public key Representation in the DNS ...............13
3.2.4. Key Sizes ..........................................14
3.3. Storing the Signature in the Email Header .................15
3.4. Preparation of Email for Transit and Signing ..............17
3.4.1. Preparation for Transit ............................18
3.4.2. Canonicalization for Signing .......................18
3.4.2.1. The "simple" Canonicalization Algorithm ...19
3.4.2.2. The "nofws" Canonicalization Algorithm ....19
3.5. The Signing Process .......................................20
3.5.1. Identifying the Sending Domain .....................20
3.5.2. Determining Whether an Email Should Be Signed ......21
3.5.3. Selecting a Private Key and Corresponding
Selector Information ...............................21
3.5.4. Calculating the Signature Value ....................21
3.5.5. Prepending the "DomainKey-Signature:" Header .......21
3.6. Policy Statement of Sending Domain ........................22
3.7. The Verification Process ..................................23
3.7.1. Presumption that Headers Are Not Reordered .........24
3.7.2. Verification Should Render a Binary Result .........24
3.7.3. Selecting the Most Appropriate
"DomainKey-Signature:" Header ......................24
3.7.4. Retrieve the Public Key Based on the
Signature Information ..............................26
3.7.5. Verify the Signature ...............................27
3.7.6. Retrieving Sending Domain Policy ...................27
3.7.7. Applying Local Policy ..............................27
3.8. Conveying Verification Results to MUAs ....................27
4. Example of Use .................................................29
4.1. The User Composes an Email ................................29
4.2. The Email Is Signed .......................................29
4.3. The Email Signature Is Verified ...........................30
5. Association with a Certificate Authority .......................31
5.1. The "DomainKey-X509:" Header ..............................31
6. Topics for Discussion ..........................................32
6.1. The Benefits of Selectors .................................32
6.2. Canonicalization of Email .................................33
6.3. Mailing Lists .............................................33
6.4. Roving Users ..............................................33
7. Security Considerations ........................................34
7.1. DNS .......................................................34
7.1.1. The DNS Is Not Currently Secure ....................34
7.1.2. DomainKeys Creates Additional DNS Load .............35
7.2. Key Management ............................................35
7.3. Implementation Risks ......................................35
7.4. Privacy Assumptions with Forwarding Addresses .............35
7.5. Cryptographic Processing Is Computationally Intensive .....36
8. The Trial ......................................................36
8.1. Goals .....................................................36
8.2. Results of Trial ..........................................37
9. Note to Implementors Regarding TXT Records .....................37
10. References ....................................................37
10.1. Normative References .....................................37
10.2. Informative References ...................................38
Appendix A - Syntax Rules for the Tag=Value Format .............39
Acknowledgments ................................................40
1. Introduction โจ
This document proposes an authentication framework for email. It stores public keys in the DNS and digitally signs email on a domain basis ๐ Separate documents talk about how this framework can be extended to validate the delivery path of email, and to facilitate per-user authentication ๐ง
The DomainKeys specification was a primary source for the DomainKeys Identified Mail [DKIM] specification. The reason this document is being submitted is as a historical reference for deployed implementations that were written before the DKIM specification ๐
1.1. Lack of Authentication Is Damaging Internet Email ๐ญ
Email authentication isn't really widespread right now. Not only is it hard to prove your own identity, it's impossible to stop other people from abusing your identity ๐
Most email exchanges don't really need authentication beyond context, honestly. But it's the rampant abuse of identity by "spammers", "phishers", and their criminal ilk that makes proof necessary. In other words, authentication is as much about protection as it is about proof ๐ก๏ธ
Here's the part that's lowkey wild: because email can't be authenticated well, the sender ends up with most of the say over what happens to inbound email, since senders can trivially assume any email address. Creating email authentication is the first step to giving that dispositional control back to the recipient ๐
For the purposes of this document, authentication is seen from a user perspective. It's meant to answer the question "who sent this email?", where "who" is the email address the recipient sees and "this email" is the content that the recipient sees ๐
1.2. Digitally Signing Email Creates Credible Domain Authentication ๐
DomainKeys combines public key cryptography and the DNS to provide credible domain-level authentication for email ๐
When an email claims to come from a certain domain, DomainKeys gives the recipient system a way to credibly determine that the email really did come from a person or system authorized to send email for that domain ๐ซถ
The authentication DomainKeys provides works in a bunch of scenarios where other authentication systems either fail or create complicated operational requirements. These include the following:
- forwarded email
- distributed sending systems
- authorized third-party sending
The base definition of DomainKeys is mainly meant to enable domain-level authenticity. Whether a given message was really sent by the purported user within the domain is outside the scope of the base definition. That said, this specification allows for the possibility that some domains may want to delegate fine-grained authentication to individual users ๐
1.3. Public Keys in the DNS ๐ธ
DomainKeys is different from traditional hierarchical public key systems. It leverages the DNS for public key management, which puts complete and direct control of key generation and management with the owner of the domain. So, if you control the DNS for a given domain, you control your DomainKeys for that domain ๐
The DNS is proposed as the initial mechanism for publishing public keys. DomainKeys is specifically designed to be extensible to other key-fetching services as they become available โจ
1.4. Initial Deployment Is Likely at the Border MTA ๐ช
For practical reasons, initial implementations of DomainKeys are expected to be deployed on Mail Transfer Agents (MTAs) that accept or relay email across administrative or organizational boundaries ๐ There are a bunch of advantages to deploying at the border MTA, including:
- a reduction in the number of MTAs that have to be changed to support an implementation of DomainKeys
- a reduction in the number of MTAs involved in transmitting the email between a signing system and a verifying system, which cuts down on the number of places that can make accidental changes to the contents
- removing the need to implement DomainKeys within an internal email network
That said, there's no necessity to deploy DomainKeys at the border. Signing and verifying can effectively happen anywhere from the border MTA right back to the Mail User Agent (MUA) ๐ฆ In particular, for many domains the best place to sign an email is likely to be at the point of SUBMISSION, where the sender is often authenticated through SMTP AUTH or other identifying mechanisms ๐ฅ
1.5. Conveying Verification Results to MUAs ๐ฌ
It follows that testing the authenticity of an email results in some action based on the results of the test. Oftentimes, the action is to notify the MUA in some way, typically via a header line ๐
The "Domainkey-Status:" header is defined in this specification for recording authentication results in the email ๐
1.6. Technical Minutiae Are Not Completely Covered ๐ค
The intent of this specification is to communicate the fundamental characteristics of DomainKeys for an implementor. But some aspects are derived from the functionality of the openssl command [OPENSSL]. Rather than duplicate that documentation, implementors are expected to understand the mechanics of the openssl command well enough to complete the implementation ๐ง โจ
1.7. Motivation ๐
okay so the whole point of DomainKeys is to give domain owners a simple, cheap, and "sufficiently effective" way to decide who is actually allowed to send email using their domain ๐ . The designers wanted a framework that:
- is transparent and compatible with the existing email infrastructure ๐
- requires no new infrastructure ๐ง
- can be implemented independently of clients in order to reduce deployment time โก
- does not require the use of a central certificate authority that might impose fees for certificates or introduce delays to deployment ๐ธ
- can be deployed incrementally ๐ธ
We think DomainKeys hits all of these, but it is not a perfect solution ๐. The current Internet puts a lot of compromises on any scheme like this, so please don't read this doc as saying DomainKeys is more credible than it actually is. That would be a major overclaim, bestie ๐ญ.
1.8. Benefits of DomainKeys ๐
Here's the tea: DomainKeys is solely an authentication system ๐ซถ. It is not a magic bullet for spam, and it is not an authorization system, a reputation system, a certification system, or a trust system. Don't come for it with those expectations ๐.
BUT a strong authentication system like DomainKeys creates an unimpeachable framework that comprehensive authorization systems, reputation systems, and their ilk can be built on top of ๐. Foundations are everything, periodt โจ.
1.9. Definitions ๐ง
Let's look at this sample email together ๐:
Line Data
Number Bytes Content
---- --- --------------------------------------------
01 46 From: "Joe SixPack" <joe@football.example.com>
02 40 To: "Suzie Q" <suzie@shopping.example.net>
03 25 Subject: Is dinner ready?
04 43 Date: Fri, 11 Jul 2003 21:00:37 -0700 (PDT)
05 40 Comment: This comment has a continuation
06 51 because this line begins with folding white space
07 60 Message-ID: <20030712040037.46341@football.example.com>
08 00
09 03 Hi.
10 00
11 37 We lost the game. Are you hungry yet?
12 00
13 04 Joe.
14 00
15 00
Line 01 is the first line of the email and the first line of the headers ๐.
Lines 05 and 06 make up the "Comment:" header ๐ฌ.
Line 06 is a continuation header line ๐งต.
Line 07 is the last line of the headers ๐.
Line 08 is the empty line that separates the header from the body ๐ซง.
Line 09 is the first line of the body ๐ฅน.
Lines 10, 12, 14, and 15 are empty lines ๐ซ .
Line 13 is the last non-empty line of the email ๐ .
Line 15 is the last line of the body and the last line of the email ๐ฌ.
Lines 01 to 15 make up the complete email โจ.
Line 01 is earlier than line 02, and line 02 is later than line 01. Yes, that's literally how lines work ๐.
1.10. Requirements Notation ๐
This document sometimes uses terms in capital letters. When the terms "MUST", "SHOULD", "RECOMMENDED", "MUST NOT", "SHOULD NOT", and "MAY" show up capitalized, they're flagging particular requirements of this spec ๐ฏ. You can read the meanings of these terms in [RFC2119] ๐.
2. DomainKeys Overview ๐ฆ
Okay, so under DomainKeys, a domain owner makes one or more private/public key pairs that get used to sign messages coming from that domain ๐. The domain owner puts the public key in their domain namespace (so, in a DNS record tied to that domain) and makes the private key available to the outbound email system ๐ค. When an authorized user of that domain submits an email, the email system uses the private key to digitally sign the email associated with the sending domain โ๏ธ. The signature gets added as a header, and the message is delivered to its recipients the usual way ๐ฌ.
When a message comes in with a DomainKey signature header, the receiving system can verify the signature like this:
- Extract the signature and claimed sending domain from the email.
- Fetch the public key from the claimed sending domain namespace.
- Use the public key to figure out whether the signature of the email was generated with the corresponding private key, and therefore whether the email was sent with the authority of the claimed sending domain ๐ต๏ธโโ๏ธ.
If an email shows up without a signature, or the signature verification fails, the receiving system grabs the policy of the claimed sending domain to find out what disposition the domain prefers for that email ๐.
Armed with all that info, the recipient system can apply local policy based on the results of the signature test ๐.
3. DomainKeys Detailed View ๐
This section gets into the specifics of DomainKeys that you need to build interoperable implementations ๐ ๏ธ. It answers these questions:
- Given an email, how is the sending domain determined?
- How is the public key retrieved for a sending domain?
- As email transits the email system, it can potentially go through a number of changes. Which parts of the email are included in the signature, and how are they protected from such transformations?
- How is the signature represented in the email?
- If a signature is not present, or a verification fails, how does the recipient determine the policy intent of the sending domain?
- Finally, on verifying the authenticity of an email, how is that result conveyed to participating MUAs?
There are lots of alternative design choices, and most of them lead to comparable functionality ๐ท. The big-picture criteria used to pick among the alternatives are:
- use deployed technology whenever possible ๐๏ธ
- prefer ease of implementation ๐งธ
- avoid trading risk for excessive flexibility or interoperability ๐ซ
- include basic flexibility ๐ฆ
Sticking to these criteria means some existing email implementations will need changes to participate in DomainKeys ๐ฅฒ. Ultimately, some hard choices have to be made about which requirements matter more ๐ค.
3.1. Determining the Sending Address of an Email ๐ฌ
The goal of DomainKeys is to give the recipient confidence that the email really came from the claimed sender ๐ซก. As with much of Internet email, agreeing on what counts as the "sender" is not easy. Forwarding systems and mailing lists add serious complications to what looks like a super simple question ๐. From the recipient's point of view, the authenticity claim should be aimed at the domain that's most visible to them ๐๏ธ.
First up, the most visible address is clearly the RFC 2822 "From:" address [RFC2822] ๐ . So a conforming email MUST contain a single "From:" header from which an email address with a domain name can be extracted.
A conforming email MAY contain a single RFC 2822 "Sender:" header from which an email address with a domain name can be extracted ๐.
If the email has a valid "From:" and a valid "Sender:" header, then the signer MUST use the sending address in the "Sender:" header ๐ซถ.
If the email has a valid "From:" and no "Sender:" header, then the signer MUST use the first sending address in the "From:" header ๐ธ.
In all other cases, a signer MUST NOT sign the email. Implementors should note that an email with a "Sender:" header and no "From:" header MUST NOT be signed ๐ซ๐. Not me signing something that doesn't match, no thank you ๐.
The domain name in the sending address is the "sending domain" ๐.
3.2. Retrieving the Public Key Given the Sending Domain ๐
To avoid namespace conflicts, it's proposed that the DNS namespace "_domainkey." be reserved within the sending domain for storing public keys ๐๏ธ. For example, if the sending domain is example.net, then the public keys for that domain are stored in the _domainkey.example.net namespace ๐ง.
3.2.1. Introducing "selectors" ๐ฏ
Now, to support multiple concurrent public keys per sending domain, the DNS namespace gets further subdivided with "selectors" โจ. Selectors are arbitrary names below the "_domainkey." namespace. A selector value and length MUST be legal in the DNS namespace and in email headers, with the additional provision that they cannot contain a semicolon ๐ซ;.
Examples of namespaces using selectors look like this ๐:
"coolumbeach._domainkey.example.net"
"sebastopol._domainkey.example.net"
"reykjavik._domainkey.example.net"
"default._domainkey.example.net"
and
"2005.pao._domainkey.example.net"
"2005.sql._domainkey.example.net"
"2005.rhv._domainkey.example.net"
Periods are allowed in selectors and are treated as component separators ๐งฉ. In the case of DNS queries, that means the period defines subdomain boundaries ๐ณ.
The domain owner decides how many public keys and corresponding selectors each domain gets ๐๏ธ. Lots of domain owners will be happy with just one selector, whereas administratively distributed organizations might manage different selectors and key pairs in different regions, or on different email servers ๐.
Beyond admin convenience, selectors make it possible to swap public keys on a routine basis without breaking anything ๐. If a domain wants to switch from the public key tied to selector "2005" to the one tied to selector "2006", it just makes sure both public keys are advertised in the DNS at the same time for the transition period, since email may be in transit before verification ๐ซง. At the start of the transition period, the outbound email servers get configured to sign with the "2006" private key ๐. At the end of the transition period, the "2005" public key gets removed from the DNS ๐.
Some domains may want to make selector values well known, but others will want to be careful not to allocate selector names in a way that lets outside parties harvest data ๐ต๏ธ. For example, if per-user keys are issued, the domain owner needs to decide whether to tie the selector directly to the user name, or to make it some unassociated random value, such as the fingerprint of the public key ๐ฒ๐.
3.2.2. Public Key Signing and Verification Algorithm โจ
okay so the default signature is an RSA signed SHA1 digest of the complete email ๐ฅ like, the whole thing gets hashed and then signed, no shortcuts ๐
For ease of explanation, we're going to use the openssl command all the way through this doc to show how keys and signatures get handled ๐ง
One way to make a 768-bit private key that works for DomainKeys is to run openssl like this:
$ openssl genrsa -out rsa.private 768
which gives you a file called rsa.private with key info that looks something like this:
-----BEGIN RSA PRIVATE KEY-----
MIIByQIBAAJhAKJ2lzDLZ8XlVambQfMXn3LRGKOD5o6lMIgulclWjZwP56LRqdg5
ZX15bhc/GsvW8xW/R5Sh1NnkJNyL/cqY1a+GzzL47t7EXzVc+nRLWT1kwTvFNGIo
AUsFUq+J6+OprwIDAQABAmBOX0UaLdWWusYzNol++nNZ0RLAtr1/LKMX3tk1MkLH
+Ug13EzB2RZjjDOWlUOY98yxW9/hX05Uc9V5MPo+q2Lzg8wBtyRLqlORd7pfxYCn
Kapi2RPMcR1CxEJdXOkLCFECMQDTO0fzuShRvL8q0m5sitIHlLA/L+0+r9KaSRM/
3WQrmUpV+fAC3C31XGjhHv2EuAkCMQDE5U2nP2ZWVlSbxOKBqX724amoL7rrkUew
ti9TEjfaBndGKF2yYF7/+g53ZowRkfcCME/xOJr58VN17pejSl1T8Icj88wGNHCs
FDWGAH4EKNwDSMnfLMG4WMBqd9rzYpkvGQIwLhAHDq2CX4hq2tZAt1zT2yYH7tTb
weiHAQxeHe0RK+x/UuZ2pRhuoSv63mwbMLEZAjAP2vy6Yn+f9SKw2mKuj1zLjEhG
6ppw+nKD50ncnPoP322UMxVNG4Eah0GYJ4DLP0U=
-----END RSA PRIVATE KEY-----
Once you've got a private key, you can use openssl to sign an email that's been prepped properly, like so:
$ openssl dgst -sign rsa.private -sha1 <input.file
which spits out signature data that looks like this when it's shown in Base64 [BASE64] format:
aoiDeX42BB/gP4ScqTdIQJcpAObYr+54yvctqc4rSEFYby9+omKD3pJ/TVxATeTz
msybuW3WZiamb+mvn7f3rhmnozHJ0yORQbnn4qJQhPbbPbWEQKW09AMJbyz/0lsl
We'll get into how this signature gets attached to the email later on in this doc ๐ฆ
To pull the public key out of the private key, use openssl like this:
$ openssl rsa -in rsa.private -out rsa.public -pubout -outform PEM
which gives you a file called rsa.public with key info that looks like this:
-----BEGIN PUBLIC KEY-----
MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhAKJ2lzDLZ8XlVambQfMXn3LRGKOD5o6l
MIgulclWjZwP56LRqdg5ZX15bhc/GsvW8xW/R5Sh1NnkJNyL/cqY1a+GzzL47t7E
XzVc+nRLWT1kwTvFNGIoAUsFUq+J6+OprwIDAQAB
-----END PUBLIC KEY-----
This public key data goes into the DNS ๐ธ
Once a verifying system has the signature, the canonical email contents, and the public key, it can check whether the signature is valid ๐ The openssl command to verify a signature looks like this:
$ openssl dgst -verify rsa.public -sha1 -signature sig.file <input.file
3.2.3. Public key Representation in the DNS ๐
ngl there's no standard way yet for storing public keys in the DNS ๐ญ so for now, the public key gets stored as a TXT record that's based on the Privacy-Enhanced Mail (PEM) format [PEM]. Basically that means a Base64 version of a DER encoded key. Here's what a 768-bit RSA key looks like in PEM form:
-----BEGIN PUBLIC KEY-----
MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhAKJ2lzDLZ8XlVambQfMXn3LRGKOD5o6l
MIgulclWjZwP56LRqdg5ZX15bhc/GsvW8xW/R5Sh1NnkJNyL/cqY1a+GzzL47t7E
XzVc+nRLWT1kwTvFNGIoAUsFUq+J6+OprwIDAQAB
-----END PUBLIC KEY-----
To save precious DNS packet space and keep things extensible ๐ the PEM wrapping MUST be removed. What's left, the public key data plus the other DomainKeys bits, gets stored as tag=value pairs separated by semicolons, like this:
brisbane._domainkey IN TXT "g=; k=rsa; p=MHww ... IDAQAB"
Verifiers MUST support key sizes of 512, 768, 1024, 1536 and 2048 bits. Signers MUST support at least one of the key sizes that verifiers support ๐
Here are the current valid tags:
g= granularity of the key. If it's there with a non-zero length value, this value MUST exactly match the local part of the sending address. This tag is optional.- The point of this tag is to limit which sending addresses can legitimately use this selector. An email whose sending address doesn't match the value of this tag counts as a failed verification ๐ซ
k= key type (rsa is the default). Signers and verifiers MUST support thersakey type. This tag is optional.n= Notes that may be of interest to a human. No program makes any interpretation of them. This tag is optional.p= public key data, encoded as a Base64 string. An empty value means this public key has been revoked. This tag MUST be present.t= a set of flags that define boolean attributes. The valid attributes are:y= testing mode. This domain is testing DomainKeys, and unverified email MUST NOT be treated differently from verified email. Recipient systems MAY wish to track testing mode results to help the sender ๐งช- This tag is optional.
(The syntax rules for the tag=value format are covered in Appendix A.)
Keeping the TXT record small is super important ๐ค because some content and caching DNS servers are reported to have trouble supporting large TXT records. In the example above, the encoding makes a 182-byte TXT record. The fact that it's under 512 bytes matters a lot, because it fits in a single UDP response packet ๐ฆ With careful choices of query values, a TXT record can hold a 2048 bit key too.
For that same size reason, the n tag SHOULD be used sparingly ๐ The most likely use for it is explaining why a public key got revoked. If that's the case, put the explanation in the n tag and take the public key value out of the p tag.
3.2.4. Key Sizes ๐
Picking the right key size is a trade-off between cost, performance, and risk ๐ง This spec doesn't define a minimum or maximum key size. That call is up to each domain owner ๐
Things that should shape that decision include:
- the practical constraint that a 2048-bit key is the largest key that fits within a 512-byte DNS UDP response packet
- larger keys impose higher CPU costs to verify and sign email
- keys can be replaced on a regular basis, so their lifetime can be relatively short
- the security goals of this specification are modest compared to typical goals of public key systems
In general, it is expected that most domain owners will use keys that are no larger than 1024 bits ๐ซถ
3.3. Storing the Signature in the Email Header
okay so the signature lives in its own little header called DomainKey-Signature: ๐ and that header carries ALL the signature stuff AND all the key-fetching info, so it's basically the whole package โจ
when you're generating the signed email, the DomainKey-Signature: header MUST precede the original email headers that get handed to the signature algorithm. ๐
the DomainKey-Signature: header is NOT part of the signature calculation. it's kinda the one header that stays out of the signed group ๐
for extensibility, the header is a bunch of tag=value pairs separated by semicolons. here's what it looks like:
DomainKey-Signature: a=rsa-sha1; s=brisbane; d=example.net;
q=dns; c=simple
these are the current valid tags, bestie ๐ฆ
a= The algorithm used to generate the signature. The default is"rsa-sha1", an RSA signed SHA1 digest. Signers and verifiers MUST support"rsa-sha1". ๐ธb= The signature data, encoded as a Base64 string. This tag MUST be present.- Whitespace is ignored in this value and MUST be removed when reassembling the original signature. Basically the signer can safely add folding whitespace to this value so it fits within line-length limits. ๐ง
c= Canonicalization algorithm. This is the method used to prep the headers and content before they go into the signing algorithm. This tag MUST be present. Verifiers MUST support"simple"and"nofws". Signers MUST support at least one of the algorithms verifiers support. ๐d= The domain name of the signing domain. This tag MUST be present. Together with the selector tag, this domain is the basis of the public key query. The value in this tag MUST match the domain of the sending email address or MUST be one of the parent domains of the sending email address. Domain name comparison is case insensitive. ๐- This matching process is called subdomain matching, since the sending email address has to be the domain itself or a subdomain of the value. ๐
h= A colon-separated list of header field names that tells you which headers were given to the signing algorithm. If present, the value MUST contain the complete list of headers, in the order they were presented to the signing algorithm. ๐ฅ- If present, this tag MUST include the header that was used to identify the sending domain, which is the
From:orSender:header. So this tag can never be empty. ๐ญ - If this tag is not present, every header after the signature header gets included, in the order they show up in the email. ๐
- A verifier MUST support this tag. A signer MAY support it too. If a signer generates this tag, it MUST include all email headers from the original email, because a verifier MAY remove or render suspicious any lines that aren't in the signature. ๐ซถ
- With duplicate headers, a signer may list duplicate entries in this tag. If a header is in this list, a verifier must include all occurrences of that header that come after the
DomainKey-Signature:header during verification. โจ - If a header on this list isn't found after the
DomainKey-Signature:header during verification, a verifier may "look" for a matching header that comes before it. Signers should not rely on this though, since early experience shows most verifiers don't try to "look" back before theDomainKey-Signature:header. ๐ - Whitespace is ignored in this value, and header comparisons are case insensitive. ๐
- If present, this tag MUST include the header that was used to identify the sending domain, which is the
q= The query method used to retrieve the public key. This tag MUST be present. Right now the only valid value is"dns", which is the DNS lookup algorithm described in this document. Verifiers and signers MUST support"dns". ๐ธs= The selector used to build the query for the public key. This tag MUST be present. For the DNS query type, this value gets prepended to the_domainkey.namespace of the sending domain. ๐ง
(Syntax rules for the tag=value format are covered in Appendix A.)
here's a signature header spread across multiple continuation lines, so you can see how it looks when it's wrapped:
DomainKey-Signature: a=rsa-sha1; s=brisbane; d=example.net;
c=simple; q=dns;
b=dzdVyOfAKCdLXdJOc9G2q8LoXSlEniSbav+yuU4zGeeruD00lszZ
VoG4ZHRNiYzR;
extreme care must be taken to make sure any new tags added to this header are defined and used ONLY for fetching and verifying the signature. ๐จ any semantics beyond verification can't be trusted, because this header isn't protected by the signature. ๐
if you need extra semantics that aren't about signature verification, they must only be added as subsequent headers that ARE protected by the signature. things like audit info describing the initial submission would fit there. ๐
3.4. Preparation of Email for Transit and Signing
okay bestie, the whole point of a crypto signature is that the signed stuff matches what gets checked later ๐ but email is different from basically every other Internet protocol, because the content gets changed all the time as it moves through the email system ๐ฉ
the good news is that most of the changes people make to email are pretty predictable, so they can be accounted for when you sign and verify โจ
so to give the signature the best shot at passing, submitted email should be prepped for transport BEFORE signing, and the data handed to the signing algorithm gets canonicalized to ignore the most common, minor changes ๐
3.4.1. Preparation for Transit
the SMTP protocol has a bunch of possible limits on email transport, especially around line lengths and 8-bit content ๐
the editor has noticed that most modern SMTP implementations accept 8-bit email and long lines, but some still don't ๐ so a DomainKeys implementation SHOULD prep an email so it works with the lowest common denominator of SMTP before presenting it for signing. ๐ผ
3.4.2. Canonicalization for Signing
DomainKeys is initially expected to be deployed at, or close to, an organization's email borders, not in MUAs or SUBMISSION servers ๐ช so the signing and verifying algorithms usually run AFTER the email has been packaged, transmogrified, and generally prepped for sending across the Internet via SMTP. that means the chance of it being changed afterward is lower ๐
still, real-world evidence shows some mail servers and relay systems do modify email in transit, which can break a signature ๐ฌ
there are two competing views on this, bestie ๐ for most senders, a mild change to the email doesn't matter for its authentication status. those senders want a canonicalization algorithm that survives small in-transit changes. ๐ฆ
other senders, though, feel that ANY change to the email, however minor, should make authentication fail. these senders don't want a modified email to look like it was authorized by them. so they prefer a canonicalization algorithm that does NOT put up with in-transit changes to the signed email. ๐ฅ
to cover both camps, two canonicalization algorithms are defined: the "simple" algorithm, which tolerates almost no modification, and the "nofws" algorithm, which tolerates common changes like whitespace replacement and header line rewrapping. ๐
a sender can pick either one when signing an email. but a verifier MUST be able to process email using EITHER algorithm. ๐
either algorithm can be used together with the h tag in the DomainKey-Signature: header. ๐ง
canonicalization just preps the email for the signing or verification algorithm. it doesn't change the transmitted data in any way โจ
3.4.2.1. The "simple" Canonicalization Algorithm
- Each line of the email is presented to the signing algorithm in the order it occurs in the complete email, from the first line of the headers to the last line of the body. ๐
- If the
htag is used, only those header lines (and their continuation lines, if any) that were added to thehtag list are included. ๐ - The
htag only constrains header lines. It has no bearing on body lines, which are always included. ๐ - Remove any local line terminator. ๐งน
- Append CRLF to the resulting line. ๐ธ
- All trailing empty lines are ignored. An empty line is a line of zero length after the local line terminator is removed. ๐ซง
If the body consists entirely of empty lines, then the header/body line is similarly ignored. ๐
3.4.2.2. The "nofws" Canonicalization Algorithm
the "No Folding Whitespace" algorithm (nofws) is more complicated than "simple" for two reasons: folding whitespace gets removed from ALL lines, and header continuation lines get unwrapped ๐งฉ
- Each line of the email is presented to the signing algorithm in the order it occurs in the complete email, from the first line of the headers to the last line of the body. ๐
- Header continuation lines are unwrapped so that header lines are processed as a single line. ๐ช
- If the
htag is used, only those header lines (and their continuation lines, if any) that were added to thehtag list are included. ๐ - The
htag only constrains header lines. It has no bearing on body lines, which are always included. ๐ - For each line in the email, remove all folding whitespace characters. Folding whitespace is defined in RFC 2822 as the decimal ASCII values 9 (HTAB), 10 (NL), 13 (CR), and 32 (SP). ๐งฝ
- Append CRLF to the resulting line. ๐ธ
- Trailing empty lines are ignored. An empty line is a line of zero length after the local line terminator is removed. Note that the test for an empty line happens AFTER all folding whitespace characters have been removed. ๐
If the body consists entirely of empty lines, then the header/body line is similarly ignored. ๐ซง
3.5. The Signing Process
the previous sections covered all the pieces and mechanisms needed to sign an email. this section puts them together into the full signing process ๐ง
a signer MUST only sign email from submissions that are authorized to use the sending address. no unauthorized signing, bestie ๐ซ
once the submission's authorization has been figured out, the signing process goes like this: ๐ช
- identify the sending domain
- decide whether the email should be signed
- select a private key and the matching selector information
- calculate the signature value
- prepend the
DomainKey-Signature:header
if an email can't be signed for some reason, it's a local policy decision what to do with it ๐คทโโ๏ธ๐
3.5.1. Identifying the Sending Domain ๐
okay so the sending domain is figured out by looking at the email address in the Sender: header ๐ฎ. if there's no Sender: header, you use the first email address in the From: header instead โจ that's your sending domain, bestie.
If the email has an invalid From: or an invalid Sender: header, it MUST NOT be signed. no cap, the broken ones don't get a signature ๐
โโ๏ธ
If the signer adds the h tag to the DomainKey-Signature: header, that tag MUST include the header that was used to determine the sending domain ๐
3.5.2. Determining Whether an Email Should Be Signed ๐ค
so obviously a signer can only sign for domains where it has a private key AND the matching public key and selector info ๐ but there are a bunch of other reasons a signer might choose not to sign an email too, which is very relatable tbh ๐
A signer MUST NOT sign an email if the email submission is not authorized to use the sending domain. not you, not your domain, not signing ๐ซ
A signer MUST NOT sign an email that already contains a DomainKey-Signature: header unless a Sender: header has been added that was not included in the original signature. the most obvious case where this happens is with mailing lists ๐ฌ
A signer SHOULD NOT remove an existing DomainKey-Signature: header. leave it alone, it's giving respect ๐ซถ
3.5.3. Selecting a Private Key and Corresponding Selector Information ๐๏ธ
this spec doesn't say how a signer should pick which private key and selector info to use ๐คทโโ๏ธ right now all selectors are equal as far as this spec is concerned, so the choice is mostly just whatever's administratively convenient for you โจ
3.5.4. Calculating the Signature Value ๐งฎ
The signer MUST use one of the defined canonicalization algorithms to present the email to the signing algorithm. canonicalization is ONLY for prepping the email for signing ๐ it does not change the transmitted email in any way, not even a little ๐ธ
To avoid possible ambiguity, a signing server may choose to remove any pre-existing DomainKey-Status: headers from the email prior to preparation for signing and transmission. clean slate energy ๐งนโจ
3.5.5. Prepending the "DomainKey-Signature:" Header ๐
the final step of signing is that the signer MUST prepend the DomainKey-Signature: header before it keeps going with transmitting the email ๐ it goes right at the front, periodt ๐
3.6. Policy Statement of Sending Domain ๐
okay so the receiving system ultimately decides what to do with inbound email, but authentication in email creates a need for the sending domain to say how it wants its mail treated ๐ like, is it participating in DomainKeys? is it just testing? does it sign ALL outbound email? the sending domain gets to spill that tea ๐ต
The sending domain policy is very simple and lives in the _domainkey TXT record in the DNS of the sending domain ๐ for example, in the example.com domain, the record is called _domainkey.example.com.
The contents of this TXT record are stored as tag=value pairs separated by semicolons, for example, as in the following:
_domainkey IN TXT "t=y; o=-; n=notes; r=emailAddress"
All tags are optional ๐ here are the current valid ones:
n= notes that may be of interest to a human ๐ no program interprets them, so they're just vibes for the humans.o= outbound signing policy.-means this domain signs ALL email ๐, and~is the default, meaning this domain may sign some email with DomainKeys ๐ฆr= a reporting email address ๐ฎ. if it's there, it defines where invalid verification results get reported. this tag is mainly for early implementers, and the content and frequency of the reports will be defined in a separate document, so stay tuned ๐t= a set of flags that define boolean attributes. the valid attribute is:y= testing mode ๐งช. this domain is testing DomainKeys, and unverified email MUST NOT be treated differently from verified email. recipient systems MAY wish to track testing mode results to assist the sender)
note that testing mode can't be turned off by this tag, so policy can't revert the testing mode setting of a Selector ๐ this tag is optional, fr fr.
(Syntax rules for the tag=value format are discussed in Appendix A. ๐)
Recipient systems SHOULD only retrieve this policy TXT record to determine policy when an email fails to verify or does not include a signature. Recipient systems SHOULD not retrieve this policy TXT record for email that successfully verifies. โจ also, "testing mode" SHOULD also be in the Selector TXT record if the domain owner is running a DomainKeys test ๐งช
If the policy TXT record does not exist, recipient systems MUST assume the default values. no record, default vibes ๐ธ
โ ๏ธ there's an important implication here. when a domain says it signs all email with the o=- setting, it's basically telling the recipient to treat unsigned mail with a LOT of suspicion ๐ณ that suspicion could reasonably go as far as rejecting the email. a verifying system MAY reject unverified email if a domain policy says it signs all email.
Of course, nothing compels a recipient MTA to follow the sender's policy ๐ during the trial, a sending domain would want to be super certain before setting this policy, since processing by recipient MTAs may be unpredictable ๐ข nonetheless, a domain that states it signs all email MUST expect that unverified email may be rejected by some receiving MTAs ๐
3.7. The Verification Process ๐ต๏ธโโ๏ธ
there's no defined or recommended limit on how long a selector and its public key can live ๐ฐ๏ธ but it is recommended that verification happen in a timely manner, and the most timely spot is during acceptance or local delivery by the MTA โก
Verifying a signature has three steps, bestie:
- extract signature information from the headers ๐ค
- retrieve the public key based on the signature information ๐
- check that the signature verifies against the contents โ
if any of these steps fails, the sending domain policy gets checked to help apply local policy ๐ง
3.7.1. Presumption that Headers Are Not Reordered ๐ โโ๏ธ
Indications from deployment of previous versions of this specification suggest that the canonicalization algorithms, together with the h tag in the DomainKey-Signature: header, let most email cryptographically survive intact between signing and verifying ๐
the one assumption that most early deployments make is that the headers included in the signature are NOT reordered before verification ๐ซฃ
nothing in this spec stops a verifier from "looking" for a header that may have been reordered (including one moved to a spot before the DomainKey-Signature: header) ๐ but honestly, reordered email is unlikely to verify successfully with most implementations, so bestie, be warned ๐
a second consequence of this assumption, especially with multiple DomainKey-Signature: headers, is that the first DomainKey-Signature: header in the email was the last signature added, so that's the one to verify ๐ฏ
3.7.2. Verification Should Render a Binary Result ๐
the symptoms of a failed verification are obvious (the signature doesn't verify) ๐ but figuring out the exact cause is way harder. if a selector can't be found, was it removed, or did the value get changed somehow in transit? if the signature line is missing, was it never there, or did an overzealous filter eat it? ๐ญ
for diagnostic purposes, the exact reason the verification failed SHOULD be recorded ๐ but when it comes to showing the end user, the result SHOULD be a simple binary result: either the email is verified or it isn't โจ if it can't be verified, it SHOULD be rendered the same as all unverified email, no matter whether it looks like it was signed ๐ซถ
3.7.3. Selecting the Most Appropriate "DomainKey-Signature:" Header ๐
usually a signed email has just one signature, aka one DomainKey-Signature: header ๐ but it's totally possible for an email to have multiple signatures. when that happens, a verifier MUST find the most appropriate signature to use and SHOULD ignore all the others ๐
finding the most appropriate signature uses these "best match" rules, and they get evaluated IN ORDER ๐ง
- Selecting the sending domain ๐ฎ
If the email contains a Sender: header, the sending domain is extracted from the Sender: address. If this extraction fails, the email SHALL fail verification ๐
If no Sender: header is present, the sending domain is extracted from the first address of the From: header. If this extraction fails, the email SHALL fail verification ๐
- Domain matching ๐
A signature can only match if the sending domain matches the d tag domain, according to the d tag subdomain matching rules ๐ท
htag matching ๐ฏ
If the signature contains the h tag list of headers, that list must include the header used to extract the sending domain in rule 1, above ๐ซถ
- Most secure signing algorithm ๐
While it is not yet the case, if additional algorithms are added to this specification, a verifier MUST use the signature that contains the most secure algorithm as defined by the future specification ๐ฎ For current implementations, that means verifiers MUST ignore signatures that are coded with an unrecognized signing algorithm ๐ โโ๏ธ
- Earlier signatures are preferred โฐ
If multiple signatures are equal as far as these rules apply, the signature from the earlier header MUST be used in preference to later signature headers ๐ฅ
Implementors MUST meticulously validate the format and values in the DomainKey-Signature: header. any inconsistency or unexpected value MUST result in ignoring that header ๐ซ being "liberal in what you accept" is definitely a bad strategy in this security context, no cap ๐ฅ
In all cases, if a verification fails, the DomainKey-Status: header SHOULD be generated and include a message to help explain the reason for the failure ๐จ๐
3.7.4. Retrieve the Public Key Based on the Signature Information ๐โจ
okay so bestie, the public key is needed to finish verification ๐ซถ and HOW you fetch it depends on the query type from the "q" tag in the "DomainKey-Signature:" header line. ngl it's giving "only fetch the key if pulling the signature info went completely right" ๐ no cap, don't go grabbing keys off a broken header ๐
Right now the ONLY valid query type is "dns" ๐ธ and here's how that slaps:
- Take the selector name from the "s" tag, the "_domainkey" namespace, and the domain from the "d" tag, and build the DNS TXT query string ๐ง
For example, if s=brisbane and d=example.net, the query string is "brisbane._domainkey.example.net".
- If the query for the public key fails to respond, the verifier SHOULD defer acceptance of this email (usually that means a 4XX SMTP response code) โณ
- If the query fails because there's no data there, the verifier MUST treat the email as unverified ๐ โโ๏ธ
- If the result doesn't match the format this spec defines, the verifier MUST treat the email as unverified ๐
- If the public key data isn't suitable for the algorithm in the "a" tag of the "DomainKey-Signature:" header, the verifier MUST treat the email as unverified ๐ฅ
Implementors MUST meticulously validate the format and values returned by the public key query ๐ Any inconsistency or unexpected value MUST result in an unverified email ๐ซ Being "liberal in what you accept" is definitely a bad strategy in this security context ๐ญ not on my watch bestie!
Latency-critical implementations may wish to start the public key query in parallel with calculating the SHA-1 hash โก because the public key isn't needed until the final RSA calculation is done ๐ฆ
3.7.5. Verify the Signature ๐
okay the vibe here is: you've got the signature info from the "DomainKey-Signature:" header AND the public key from the query, so now you can actually verify the signature of the email ๐ โจ
The canonicalization algorithm named by the "c" tag in that header decides how the data gets prepped for the verification algorithm ๐ง, and the "a" tag in the same header decides which verification algorithm to use ๐ that's the whole plot ๐
3.7.6. Retrieving Sending Domain Policy ๐
so if an email FAILS to verify, the policy of the sending domain MUST be consulted ๐จ for now that means checking the _domainkey TXT record in the DNS of the sending domain, as defined in Section 3.5.1 ๐ For example, if example.net is the sending domain, the TXT query is:
_domainkey.example.net
A verifier SHOULD consider the sending domain policy statement and act accordingly ๐ซถ what happens next is up to the receiver, but it MAY include rejecting the email ๐๐
3.7.7. Applying Local Policy ๐ธ
After all the verification stuff is done, the recipient system has authentication info that can help it decide what to do with the email โจ
It is beyond the scope of this specification to say what actions a recipient system should take ๐ง but an authenticated email gives the receiving system an opportunity that unauthenticated email simply doesn't ๐ Specifically, an authenticated email creates a predictable identifier that other decisions can reliably be built on, like trust and reputation ๐
Conversely, unauthenticated email lacks a reliable identifier for assigning trust and reputation ๐ฅ It is not unreasonable to treat unauthenticated email as having no trust and no positive reputation ๐ฆ
3.8. Conveying Verification Results to MUAs ๐ฌ
Apart from automated policy, the result of a signature verification SHOULD be conveyed to the user reading the email ๐ wait, read that again: the original says "should be conveyed," so it's a SHOULD-level vibe, not a MUST ๐
Most email clients can be set up to recognize specific headers and apply simple rules, like filing into a particular folder ๐ Since DomainKey signatures are expected to be initially verified at the border MTA, the results need to get to the email client ๐ช and that's done with the "DomainKey-Status:" header line prepended to the email โจ
The "DomainKey-Status:" header starts with a string that indicates the result of the verification ๐ Valid values are:
"good" - the signature was verified at the time of testing
"bad" - the signature failed the verification
"no key" - the public key query failed as the key does not
exist
"revoked" - the public key query failed as the key has been
revoked
"no signature" - this email has no "DomainKey-Signature:" header
"bad format" - the signature or the public key contains unexpected
data
"non-participant" - this sending domain has indicated that it does
not participate in DomainKeys
Verifiers may append additional data that expands on the reason for the particular status value ๐ง
A client SHOULD just look for "good" and assume that all other values mean verification couldn't be performed for some reason ๐ what the client does with that is entirely a local matter ๐
Here are some examples:
DomainKey-Status: good
DomainKey-Status: bad format
Although MTAs are expected to be DomainKey aware before MUAs, it's still possible that a DomainKey-aware MUA gets fooled by a spoofed "DomainKey-Status:" header that gets through a non-DomainKey-aware MTA ๐ฑ not ideal!
If this is seen as a serious problem, it may make sense to rule out the "good" value and only have values that effectively demote the email as far as the UA is concerned ๐ก๏ธ That way, successful spoofing attempts can only demote themselves ๐๐ซถ
- Example of Use ๐
This section shows the complete flow of an email from submission to final delivery, showing how all the pieces fit together ๐งฉ
4.1. The User Composes an Email ๐
From: "Joe SixPack" <joe@football.example.com>
To: "Suzie Q" <suzie@shopping.example.net>
Subject: Is dinner ready?
Date: Fri, 11 Jul 2003 21:00:37 -0700 (PDT)
Message-ID: <20030712040037.46341.5F8J@football.example.com>
Hi.
We lost the game. Are you hungry yet?
Joe.
4.2. The Email Is Signed โ๏ธ
This email is signed by the football.example.com outbound email server and now looks like this ๐ฆ
DomainKey-Signature: a=rsa-sha1; s=brisbane; d=football.example.com;
c=simple; q=dns;
b=dzdVyOfAKCdLXdJOc9G2q8LoXSlEniSbav+yuU4zGeeruD00lszZ
VoG4ZHRNiYzR;
Received: from dsl-10.2.3.4.football.example.com [10.2.3.4]
by submitserver.football.example.com with SUBMISSION;
Fri, 11 Jul 2003 21:01:54 -0700 (PDT)
From: "Joe SixPack" <joe@football.example.com>
To: "Suzie Q" <suzie@shopping.example.net>
Subject: Is dinner ready?
Date: Fri, 11 Jul 2003 21:00:37 -0700 (PDT)
Message-ID: <20030712040037.46341.5F8J@football.example.com>
Hi.
We lost the game. Are you hungry yet?
Joe.
The signing email server requires access to the private key associated with the "brisbane" selector to generate this signature ๐ Distribution and management of private keys are outside the scope of this document ๐ โโ๏ธ
4.3. The Email Signature Is Verified ๐
The signature is normally verified by an inbound SMTP server or possibly the final delivery agent ๐ฅ However, intervening MTAs can also perform this verification if they choose to do so ๐ง
The verification process uses the domain "football.example.com" extracted from the "From:" header and the selector "brisbane" from the "DomainKey-Signature:" header to form the DNS TXT query for:
brisbane._domainkey.football.example.com
Since there is no "h" tag in the "DomainKey-Signature:" header, signature verification starts with the line following the "DomainKey-Signature:" line ๐ธ The email is canonically prepared for verifying with the "simple" method โจ
The result of the query and subsequent verification of the signature is stored in the "DomainKey-Status:" header line ๐ After successful verification, the email looks like this:
DomainKey-Status: good
from=joe@football.example.com; domainkeys=pass
Received: from mout23.brisbane.football.example.com (192.168.1.1)
by shopping.example.net with SMTP;
Fri, 11 Jul 2003 21:01:59 -0700 (PDT)
DomainKey-Signature: a=rsa-sha1; s=brisbane; d=football.example.com;
c=simple; q=dns;
b=dzdVyOfAKCdLXdJOc9G2q8LoXSlEniSbav+yuU4zGeeruD00lszZ
VoG4ZHRNiYzR;
Received: from dsl-10.2.3.4.network.example.com [10.2.3.4]
by submitserver.example.com with SUBMISSION;
Fri, 11 Jul 2003 21:01:54 -0700 (PDT)
From: "Joe SixPack" <joe@football.example.com>
To: "Suzie Q" <suzie@shopping.example.net>
Subject: Is dinner ready?
Date: Fri, 11 Jul 2003 21:00:37 -0700 (PDT)
Message-ID: <20030712040037.46341.5F8J@football.example.com>
Hi.
We lost the game. Are you hungry yet?
Joe.
- Association with a Certificate Authority ๐๏ธ
A fundamental part of DomainKeys is that public keys get generated and advertised by each domain at no additional cost ๐ฐ This is super different from traditional Public Key Infrastructures, where there's typically a Certificate Authority (CA) who validates an applicant and issues a signed certificate (containing their public key), often for a recurring fee ๐ค
CAs do cost money, but they can also add extra value as part of their certification process ๐ Think about financial institutions, public utilities, law enforcement agencies, and the like ๐ฎโโ๏ธ In lots of cases, those entities justifiably need to stand out above and beyond the authentication DomainKeys offers ๐
Creating a link between DomainKeys and CA-issued certificates has the potential to tap into additional authentication mechanisms that are more authoritative than domain-owner-issued authentication ๐ฆ It is well beyond the scope of this specification to describe those authorities, apart from defining how the linkage could be achieved with the "DomainKey-X509:" header ๐ง
5.1. The "DomainKey-X509:" Header ๐
okay so the DomainKey-X509: header is the bit that links the public key used to sign the email to a certificate issued by a CA ๐โจ
the exact content, syntax, and semantics of this header are still TBD ๐ซ one idea is that it carries an encoding of the CA-issued certificate. another idea is that it carries a URL that points to that certificate ๐
either way, this header can only be checked if the signature verifies, and it MUST be part of the content signed by the matching DomainKey-Signature: header. no skipping that ๐
โโ๏ธ
also, MUAs are more likely than MTAs to be the ones confirming the link to the CA-issued certificate is valid ๐ partly because lots of MUAs already have built-in support from Secure/Multipurpose Internet Mail Extensions (S/MIME) [SMIME] and Secure Socket Layer (SSL) [SSL]. they're already doing the certificate thing, so it's easy for them ๐
the proof of linkage works by checking that the public key in the certificate matches the public key that signed the email ๐๐
here's an example of an email with the DomainKey-X509: header ๐
DomainKey-Signature: a=rsa-sha1; s=statements;
d=largebank.example.com; c=simple; q=dns;
b=dzdVyOfAKCdLXdJOc9G2q8LoXSlEniSbav+yuU4zGeeruD00lszZ
VoG4ZHRNiYzR;
DomainKey-X509: https://ca.example.net/largebank.example.com
From: "Large Bank" <statements@largebank.example.com>
To: "Suzie Q" <suzie@shopping.example.net>
Subject: Statement for Account: 1234-5678
...
the format of whatever gets retrieved from that URL isn't defined yet ๐คทโโ๏ธ and figuring out which CAs count as valid isn't settled either ๐ฅฒ
the whole CA-linkage thing is one part of DomainKeys that still needs to be sorted out with the relevant CAs and certificate-issuing entities ๐๏ธ the main takeaway is that a link to a higher authority is possible ๐
6. Topics for Discussion ๐
6.1. The Benefits of Selectors ๐ฆ
selectors are the heart of DomainKeys' flexibility โจ a domain admin can totally use one DomainKey for all outbound mail ๐โโ๏ธ or they can use lots of DomainKeys, each differentiated by selector and each assigned to a different server ๐ฅ๏ธ
for example, a big outbound email farm might have a unique DomainKey for every server, so their DNS could be advertising potentially hundreds of keys through their unique selectors ๐คฏ
another example is a corporate email admin who makes a separate DomainKey for each regional office's email server ๐ข๐ธ
basically, selectors let a domain owner hand out authority to send on behalf of that domain ๐ and combined with revoking by removal or Time to Live (TTL) expiration, the domain owner gets coarse-grained control over how long that authority lasts โณ
selectors are especially handy when a domain owner wants to hire a third-party mailing system to send a specific batch of mail ๐จ the owner can generate a special key pair and selector just for that mail-out ๐ but the owner has to give the private key and selector to the third party for the whole life of the mail-out ๐ซฃ
then, once the mail-out is completely delivered, the owner can revoke the public key by simply removing the entry from the DNS ๐งน done and dusted, bestie ๐
6.2. Canonicalization of Email ๐ท
it's unfortunate, but some email software routinely (and often unnecessarily) transforms email as it moves through the network ๐ค those transformations clash with the whole point of cryptographic signatures, which is detecting modifications ๐ซ
two canonicalization algorithms are defined in this spec, but the main goal of "nofws" is to give people a transition path to "simple" ๐ค๏ธ with a mix of "simple" and "nofws" email, a receiver can figure out which systems are changing email in ways that break the signature, and then give feedback to that modifying system ๐๐
6.3. Mailing Lists ๐ฌ
fitting existing Mailing List Managers (MLMs) into the DomainKeys system is complicated, ngl ๐ญ MLM behavior is super variable ๐ basically there are two types under consideration: ones that modify email so much that the original content can't be verified, and ones that make minimal or no changes at all ๐ญ
MLMs that modify email in a way that breaks verification MUST prepend a "Sender:" header, and they SHOULD prepend a "List-ID:" header before signing for distribution to list recipients ๐ฎ
a participating SUBMISSION server can tell it needs to re-sign an email if it spots a "Sender:" or "List-ID:" header coming from an authorized submission ๐ต๏ธโโ๏ธโจ
MLMs that don't modify email in a way that breaks verification MAY do the same stuff as a modifying MLM ๐
6.4. Roving Users ๐งณ
one scenario that's a real problem for any form of email authentication, DomainKeys included, is the roving user ๐ฅบ that's someone who has to use a third-party SUBMISSION service when they can't connect to their own SUBMISSION service ๐ก the classic example is a traveling salesperson getting redirected to a hotel email server to send email ๐จ
as far as DomainKeys is concerned, email like this clearly comes from a server that doesn't have authority to send on behalf of the salesperson's domain, so it looks just like a forgery ๐ฉ DomainKeys doesn't prescribe any specific action for it, but over time, this kind of email will likely get treated as second-class email ๐ฌ
the typical fix for roving users is to submit email through an authorized server for their domain ๐ฅ๏ธ maybe over a Virtual Private Network (VPN), a web interface, or even SMTP AUTH back to a SUBMISSION server ๐
those are perfectly fine solutions for lots of people ๐ but they aren't always available or possible for everyone ๐ซถ
one way to help this group of potentially disenfranchised users is for the domain to issue per-user DomainKeys ๐ง per-user DomainKeys are identified by a non-empty g tag value in the matching DNS record ๐ท๏ธ
7. Security Considerations ๐
7.1. DNS ๐
DomainKeys is primarily a security mechanism ๐ก๏ธ its core purpose is making claims about email authentication in a credible way โ but DomainKeys, like basically every Internet application, relies on the DNS, which has well-known security flaws [RFC3833] ๐ญ
7.1.1. The DNS Is Not Currently Secure ๐จ
the DNS is insecure right now, but the security problems are expected to be solved by DNS Security (DNSSEC) [DNSSEC], and every DNS user will get the benefits of that work ๐
also, the types of DNS attacks that matter to DomainKeys are super costly and way less rewarding than DNS attacks on other Internet applications ๐ธ
to systematically wreck DomainKeys, an attacker would need to run a very costly and very extensive attack on lots of parts of the DNS over a long period ๐ซ nobody knows for sure how attackers will respond ๐คทโโ๏ธ but the cost/benefit of pulling off prolonged DNS attacks like this is expected to be uneconomical ๐
last but not least, DomainKeys is only meant to be a "sufficient" way of proving authenticity ๐ง it isn't meant to give strong cryptographic proof about authorship or contents ๐ โโ๏ธ technologies like GnuPG and S/MIME handle those requirements ๐
7.1.2. DomainKeys Creates Additional DNS Load ๐
another DNS security issue comes from the extra DNS traffic caused by fetching selector-based data, plus fetching sending domain policy ๐ widespread deployment of DomainKeys is going to cause a significant jump in DNS queries to the claimed sending domain ๐ณ and with forgeries on a large scale, DNS servers could see a substantial increase in queries ๐๐
7.2. Key Management ๐
all public key systems need key pairs to be managed ๐๏ธ private keys especially need to be securely distributed to each signing mail server and protected on those servers ๐ if you know SSL, the key management issues are similar to managing SSL certificates ๐ค poor key management might let unauthorized people access private keys, which basically gives them access to your identity ๐ฑ
7.3. Implementation Risks ๐ ๏ธ
it's well recognized in cryptographic circles that lots of security failures come from poor implementations rather than poor algorithms ๐ for example, early SSL implementations were vulnerable because the implementors used predictable "random numbers" ๐ฒ
while some MTA software already supports various cryptographic techniques, such as TLS, a lot of it doesn't ๐ฅด this proposal brings cryptographic requirements into MTA software, which means a much higher duty of care to manage the increased risk ๐งฏ
there are tons of articles, books, courses, and consultants that help with programming security applications ๐ potential implementors are strongly encouraged to use all the resources they can to make sure their implementations are secure ๐ซถ
7.4. Privacy Assumptions with Forwarding Addresses ๐ต๏ธ
some people think they can get anonymity by using an email forwarding service ๐ that's never been particularly true, though ๐ bounces, over-quota messages, vacation messages, and web bugs all team up to expose the IP addresses and domain names tied to the delivery path ๐ญ and the DNS queries needed to verify a DomainKeys signature can give the sender even more info ๐
specifically, as mail gets forwarded through the mail network, the DNS queries for the selector will typically identify the DNS cache used by the forwarding and delivery MTAs ๐
7.5. Cryptographic Processing Is Computationally Intensive ๐ง
verifying a signature is computationally significant ๐ฅต early indications are that a typical mail server can expect a CPU demand increase of 8-15 percent ๐ that's modest compared to other common mail processing costs, like Bayesian filtering ๐งน but any increase in resource requirements can make a denial-of-service attack more effective against a mail system ๐ฅ
one constraint on these attacks is that the net computational cost of verifying is bounded by the maximum key size this spec allows, and it's essentially linear to the rate at which the verifying system accepts mail ๐ so the extra computational cost may boost a denial-of-service attack, but it doesn't add a non-linear component to those attacks ๐
8. The Trial ๐งช
the DomainKeys protocol was deployed as a trial to better understand what happens when you deploy wide-scale cryptographic email authentication ๐ฌ
Open Source implementations were made available in various places, most notably Source Forge [SOURCEFORGE], which links to tons of implementations, both Open Source and commercial ๐ป
8.1. Goals ๐ฏ
the main goals of the trial were to: ๐ธ
- understand the operational implications of running a DNS-based public key system for email ๐ฌ
- measure the effectiveness of the canonicalization algorithms ๐งช
- experiment with possible per-user key deployment models ๐ง
- fully define the semantics of the
DomainKey-X509:header ๐
8.2. Results of Trial ๐
Okay bestie, the DomainKeys trial ran for about 2 years ๐๏ธ, and numerous large ISPs plus many thousands of smaller domains jumped in to sign or verify with DomainKeys ๐ . The lowkey-unhinged number: at least one billion DomainKey signed emails transit the Internet each day between some 12,000 participating domains ๐ญ๐ฅ.
The operational and development experience from that trial got poured into DKIM ๐ฆ.
9. Note to Implementors Regarding TXT Records โจ
So the DNS is super flexible. You can have multiple TXT records for a single name, and those TXT records can each contain multiple strings ๐ง.
But here's the tea ๐ซ. Implementors of DomainKeys should expect a single TXT record for any particular name. If multiple TXT records come back, the implementation is free to pick any single one as the authoritative data. In other words, if a name server returns different TXT records for the same name, it can expect unpredictable results ๐. Yikes.
Within a single TXT record, concatenate multiple strings in the order presented and ignore string boundaries. Heads up ๐: a number of popular DNS command-line tools render multiple strings as separately quoted strings, which can be super misleading to a novice implementor.
10. References ๐
10.1. Normative References
- [BASE64] Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, October 2006. ๐ธ
- [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997. ๐
- [PEM] Linn, J., "Privacy Enhancement for Internet Electronic Mail: Part I: Message Encryption and Authentication Procedures", RFC 1421 February, 1993. ๐ฆ
10.2. Informative References
- [DKIM] Allman, E., Callas, J., Delany, M., Libbey, M., Fenton, J., and M. Thomas, "DomainKeys Identified Mail (DKIM) Signatures", RFC 4871, May 2007. ๐
- [DNSSEC]
http://www.ietf.org/html.charters/dnsext-charter.html๐ - [OPENSSL]
http://www.openssl.orgโจ - [RFC2822] Resnick, P., Editor, "Internet Message Format", RFC 2822, April 2001. ๐ฌ
- [RFC3833] Atkins, D. and R. Austein, "Threat Analysis of the Domain Name System (DNS)", RFC 3833, August 2004. ๐ก๏ธ
- [SMIME] Ramsdell, B., Ed., "Secure/Multipurpose Internet Mail Extensions (S/MIME) Version 3.1 Message Specification", RFC 3851, July 2004. ๐
- [SOURCEFORGE]
http://domainkeys.sourceforge.net๐ - [SSL]
http://wp.netscape.com/security/techbriefs/ssl.html๐ง
Appendix A - Syntax Rules for the Tag=Value Format ๐ซถ
A simple tag=value syntax is used to encode data in the response values for DNS queries, as well as headers embedded in emails. This section summarizes the syntactic rules for this encoding:
- A tag=value pair consists of three tokens: a "tag", the "=" character, and the "value" ๐ธ
- A tag MUST be one character long and MUST be a lowercase alphabetic character ๐ค
- Duplicate tags are not allowed ๐ โโ๏ธ
- A value MUST only consist of characters that are valid in RFC 2822 headers and DNS TXT records and are within the ASCII range of characters from SPACE (0x20) to TILDE (0x7E) inclusive. Values MUST NOT contain a semicolon, but they may contain "=" characters. ๐ซ
- A tag=value pair MUST be terminated by a semicolon or the end of the data ๐ช
- Values MUST be processed as case sensitive unless the specific tag description of semantics implies case insensitivity. ๐
- Values MAY be zero bytes long ๐ซง
- Whitespace MAY surround any of the tokens; however, whitespace within a value MUST be retained unless explicitly excluded by the specific tag description. Currently, the only tags that specifically ignore embedded whitespace are the "b" and "h" tags in the
DomainKey-Signature:header. ๐ - Tag=value pairs that represent the default value MAY be included to aid legibility. ๐
- Unrecognized tags MUST be ignored ๐
Acknowledgments ๐
The editor wishes to thank Russ Allbery, Eric Allman, Edwin Aoki, Claus Asmann, Steve Atkins, Jon Callas, Dave Crocker, Michael Cudahy, Jutta Degener, Timothy Der, Jim Fenton, Duncan Findlay, Phillip Hallam-Baker, Murray S. Kucherawy, John Levine, Miles Libbey, David Margrave, Justin Mason, David Mayne, Russell Nelson, Juan Altmayer Pizzorno, Blake Ramsdell, Scott Renfro, the Spamhaus.org team, Malte S. Stretz, Robert Sanders, Bradley Taylor, and Rand Wacker for their valuable suggestions and constructive criticism. Everyone on this list is iconic ๐
Author's Address ๐ฎ
Mark Delany
Yahoo! Inc
701 First Avenue
Sunnyvale, CA 95087
USA
EMail: markd+domainkeys@yahoo-inc.com
Full Copyright Statement ยฉ๏ธ
Copyright (C) The IETF Trust (2007).
This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.
This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Intellectual Property ๐งพ
The IETF takes no position regarding the validity or scope of any Intellectual Property Rights or other rights that might be claimed to pertain to the implementation or use of the technology described in this document, or the extent to which any license under such rights might or might not be available. Nor does it represent that it has made any independent effort to identify any such rights. Information on the procedures with respect to rights in RFC documents can be found in BCP 78 and BCP 79.
Copies of IPR disclosures made to the IETF Secretariat and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification, can be obtained from the IETF on-line IPR repository at http://www.ietf.org/ipr.
The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. Please address the information to the IETF at ietf-ipr@ietf.org.
Acknowledgement ๐ท
Funding for the RFC Editor function is currently provided by the Internet Society. โจ
๐ฆ where this page comes from
- ietf: rfc4870 2007-05
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms