Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

#37 Incorrectly signs header with repeated header fields

v0.4.1
open
nobody
5
2009-06-01
2006-08-11
Mark Martinec
No

Investigating why some messages fail verification
turned up incorrect algorithm for signing mail with
multiple occurrences of header fields such as
Received, interspersed with other header fields.

Here is an example of a simple yet valid mail message,
signed with dk-filter 0.4.1 (the example was
minimized, but is based on a real-life mail):

Received: from one by localhost; Mon, 7 Aug 2006
11:00:00 +0000
Message-ID: <x@ijs.si>
Received: from two by localhost; Mon, 7 Aug 2006
10:00:00 +0000
From: <test@ijs.si>
To: <test@ijs.si>
Date: Mon, 7 Aug 2006 10:00:00 +0000

xxx
------

(no lines are to be wrapped). Note the double
occurrence of Received:, with some other header field
placed between them. This message signed with
dk-filter based on a test key below yields (sorry for
wraps):

DomainKey-Signature: a=rsa-sha1; s=test; d=ijs.si;
c=simple; q=dns; h=received:message-id:from:to:date;
b=Actzxhvhsd0Hf+gX3Gbc5K5tbTOfgxU3JQzQxUBEAGv0fgciwQXfTG6rn/fMSjt9n
0rAHR1C269oA6leqYtPeA==

signing key was:
-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBAMmbBVIk6ts9pbDLqsf4ZonIp0HsPYwI1u+WysmdDIeoYdXAX98e
FaH6CFzmMoSnpRVgczsSIrsETIpSXL7qj9cCAwEAAQJAKRbEPdqyVx64X1ETLJBu
7ZQMqr3oSVsf21LjX7X3cMo+qvgmaNUL+QyQGXCqhRlkWJ5K/3aqh+mQN0Lq4bEx
eQIhAPmQiz4YqCFt+pVTv387AtPRMtaqJy19htuD6qoC3emNAiEAzs3iNm++wAMn
FO5EC1JO+9CJnZsQI9wk6VBnAWY0G/MCIQDuO2ZAi8cLynG31K9sJAfp7bzLILiv
ezGeIUqEqqHuDQIgCAFuVV8kCjjVBXlnxuxrxFHBUgmTqV+3ShTjt+kl8UMCIC8k
t+coPoWtUb3KYxv1i5z+DIjzWOOxhatGHH7gOtgU
-----END RSA PRIVATE KEY-----

If you work out the example manually, strictly
following draft-delany-domainkeys-base-06, it gives
different signature (b=mJCMa6FM5k5tRv...). The one
given above (b=Actzxh...) corresponds to a message
with all Received header fields collected together at
the top of the message, i.e.:

DomainKey-Signature: a=rsa-sha1; s=test; d=ijs.si;
c=simple; q=dns;
h=received:message-id:from:to:date;
b=Actzxhvhsd0Hf+gX3Gbc5K5tbTOfgxU3JQzQxUBEAGv0fgciwQXfTG6rn/fMSjt9n
0rAHR1C269oA6leqYtPeA==
Received: from one by localhost; Mon, 7 Aug 2006
11:00:00 +0000
Received: from two by localhost; Mon, 7 Aug 2006
10:00:00 +0000
Message-ID: <x@ijs.si>
From: <test@ijs.si>
To: <test@ijs.si>
Date: Mon, 7 Aug 2006 10:00:00 +0000

xxx

...which is wrong according to
draft-delany-domainkeys-base-06, and according to
other implementations of DomainKeys, and does not even
match verification done by the same milter. The draft
is specific about keeping the order intact:

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

o If the "h" tag is used, only those header lines (and
their continuation lines if any) added to the "h" tag
list are included.

Discussion

  • Mark Martinec
    Mark Martinec
    2006-08-11

    mail sample and a signing test key

     
    Attachments
    • assigned_to: nobody --> sm-msk
     
  • Logged In: YES
    user_id=1048957
    Originator: NO

    The code which handles this was written against a much earlier draft, shortly after "h=" was added to DomainKeys, and that version wasn't as clear about how to handle a header which appears multiple times in a message but is only referenced once in the value of "h=". My interpretation at the time resulted in the implementation you've observed. I remember discussion about this on the DK developers list too at the time.

    I'm hoping this is a simple fix, but I have my doubts.

     
  • Logged In: YES
    user_id=1048957
    Originator: NO

    The draft is not specific enough for a header which appears more than once below the signature header yet is mentioned only once in h=. The base-06 spec says this on page 17:

    If a header is included in this list, a verifier must include all occurrences of that header, subsequent to the "DomainKey-Signature:" header in the verification.

    Coupled with your citation, that means if I see "received" once in "h=" while there was more than one instance of that header below the signature header, I have to play them all back in the order in which they were found. That is, if "h=received:message-id:from:to:date:subject", a verifier should replay all the Received headers in order, then the Message-Id header, then the From, then To, then Date, then Subject. As your example shows, that's what this implementation does.

    What you're saying is that "h=" means "replay all the headers in order unless they don't appear in this list", which isn't how I interpreted the specification.

     
  • Logged In: YES
    user_id=1048957
    Originator: NO

    I consulted the author of the domainkeys-base draft, who confirmed that my interpretation is what he intended on verifying. Moreover, the spec is unclear as to what should happen when the number of Received: headers below the signature and the number of "received" entries in the "h=" value aren't equal. In fact, as "h=" is defined, if the signer signs one Received: header but multiple such headers are below the signature on verification, there's no way the signature can verify. In particular, this paragraph is almost self-contradictory:

    > In the presence of duplicate headers, a signer may include duplicate entries in the list of
    > headers in this tag. If a header is included in this list, a verifier must include all
    > occurrences of that header, subsequent to the "DomainKey-Signature:" header in the verification.

    ...because in fact if the signer doesn't include duplicate entries (as I decided not to, treating the second sentence as dominant), there's no guarantee of symmetry.

    He says he may try to get this cleared up before the RFC issues.

    This is one area where the DKIM specification is a lot more clear than the DK one is.

    I will look into why dk-milter doesn't verify its own messages and sort that out.

     
    • assigned_to: sm-msk --> nobody