This post will again be a paraphrase of that which is found in RFC 4870. Now that we have seen how public keys are stored in DNS, we will next look at how a signing server generates the message signature. The signature of the email is stored in the “DomainKey-Signature:” header which contains all of the signature and key-fetching data.
When generating the signed email, the “DomainKey-Signature:” header must precede the original email headers presented to the signature algorithm. This means that it occurs before the To:, From:, Date: headers but not before the Received: headers, which are inserted into the message upon receipt of the message by the receiving or relaying email servers.
The various tag/value pairs in the DomainKey-Signature: header are separated by semicolons, for example, as in the following:
DomainKey-Signature: a=rsa-sha1; s=brisbane; d=example.net; q=dns; c=simple
The current valid tags are as follows:
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 (ie, the message contents which goes through the encryption algorithm), 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. In other words, line wraps and spaces are collapsed and removed.
c = Canonicalization algorithm. Canonicalization is the method by which the headers and message content are prepared for presentation to the signing algorithm. This tag must be present. Verifiers must support “simple” and “nofws”. Signers must support at least one of the verifier-supported algorithms. We will look more into canonicalization in a future post.
d = The domain name of the signing domain. This tag must be present. In conjunction with the selector tag, this domain forms the basis of the public key query. The value in this tag must match the domain of the sending email address (From: or Sender: address, not the envelope sender) or must be one of the parent domains of the sending email address. Domain name comparison is case insensitive.
h = A colon-separated list of header field names that identify the headers presented to the signing algorithm. If present, the value must contain the complete list of headers in the order presented to the signing algorithm.
If present, this tag must include the header that was used to identify the sending domain, i.e., the “From:” or “Sender:” header; thus, this tag can never contain an empty value.
If this tag is not present, all headers subsequent to the signature header are included in the order found in the email.
A verifier must support this tag. A signer may support this tag. If a signer generates this tag, it must include all email headers in the original email, as a verifier MAY remove or render suspicious, lines that are not included in the signature.
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. Currently, the only valid value is “dns”. Verifiers and signers must support “dns”.
s = The selector used to form the query for the public key. This tag must be present. In the DNS query type, this value is prepended to the “_domainkey.” namespace of the sending domain.
Here is an example of a signature header spread across multiple continuation lines:
DomainKey-Signature: a=rsa-sha1; s=brisbane; d=example.net;
In my next post, we’ll take a look at some examples.