RFC 4870

Domain-Based Email Authentication Using Public Keys Advertised in the DNS (DomainKeys)

๐Ÿ“… published May 2007, from ietf

๐Ÿ“œ 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 (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:

  1. Extract the signature and claimed sending domain from the email.
  2. Fetch the public key from the claimed sending domain namespace.
  3. 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 the rsa key 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: or Sender: 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 the DomainKey-Signature: header. ๐Ÿ™ˆ
    • Whitespace is ignored in this value, and header comparisons are case insensitive. ๐ŸŽ€
  • 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 h tag is used, only those header lines (and their continuation lines, if any) that were added to the h tag list are included. ๐ŸŽ€
  • The h tag 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 h tag is used, only those header lines (and their continuation lines, if any) that were added to the h tag list are included. ๐ŸŽ€
  • The h tag 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: ๐Ÿชœ

  1. identify the sending domain
  2. decide whether the email should be signed
  3. select a private key and the matching selector information
  4. calculate the signature value
  5. 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 ๐Ÿงš

  1. 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 ๐Ÿ’€

  1. Domain matching ๐Ÿ”

A signature can only match if the sending domain matches the d tag domain, according to the d tag subdomain matching rules ๐ŸŒท

  1. h tag 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 ๐Ÿซถ

  1. 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 ๐Ÿ™…โ€โ™€๏ธ

  1. 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:

  1. 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".

  1. 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) โณ
  2. If the query fails because there's no data there, the verifier MUST treat the email as unverified ๐Ÿ™…โ€โ™€๏ธ
  3. If the result doesn't match the format this spec defines, the verifier MUST treat the email as unverified ๐Ÿ’€
  4. 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 ๐Ÿ’€๐Ÿซถ

  1. 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.
  1. 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


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

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