From c646369d66ab171695b8ba055c9fb529ff16f135 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Tue, 15 Mar 2011 16:30:16 +1100 Subject: [PATCH 1/2] Update fix for bug 587783 verifying relaxed signatures --- ChangeLog | 5 +++++ dkim/__init__.py | 17 +++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3b1984a..c642ab4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Not yet released + - when verifying Relaxed mode signatures, the partial DKIM-Signature + header must be canonicalized before hashing (Martin Pool) + + 2008-06-25 Version 0.3 - length parameter to sign() is now a boolean diff --git a/dkim/__init__.py b/dkim/__init__.py index 81e502c..9a42462 100644 --- a/dkim/__init__.py +++ b/dkim/__init__.py @@ -313,18 +313,23 @@ def sign(message, selector, domain, privkey, identity=None, canonicalize=(Simple ('bh', bodyhash), ('b', ""), ] if x] - sig = "DKIM-Signature: " + "; ".join("%s=%s" % x for x in sigfields) - sig = fold(sig) + sig_value = fold("; ".join("%s=%s" % x for x in sigfields)) + dkim_header = canonicalize[0].canonicalize_headers([ + ['DKIM-Signature', ' ' + sig_value]])[0] + # the dkim sig is hashed with no trailing crlf, even if the + # canonicalization algorithm would add one. + if dkim_header[1][-2:] == '\r\n': + dkim_header = (dkim_header[0], dkim_header[1][:-2]) + sign_headers.append(dkim_header) if debuglog is not None: - print >>debuglog, "sign headers:", sign_headers + [("DKIM-Signature", " "+"; ".join("%s=%s" % x for x in sigfields))] + print >>debuglog, "sign headers:", sign_headers h = hashlib.sha256() for x in sign_headers: h.update(x[0]) h.update(":") h.update(x[1]) - h.update(sig) d = h.digest() if debuglog is not None: print >>debuglog, "sign digest:", " ".join("%02x" % ord(x) for x in d) @@ -334,9 +339,9 @@ def sign(message, selector, domain, privkey, identity=None, canonicalize=(Simple d, HASHID_SHA256, pk['privateExponent'], pk['modulus']) except DigestTooLargeError: raise ParameterError("digest too large for modulus") - sig += base64.b64encode(sig2) + sig_value += base64.b64encode(sig2) - return sig + "\r\n" + return 'DKIM-Signature: ' + sig_value + "\r\n" def verify(message, debuglog=None, dnsfunc=dnstxt): """Verify a DKIM signature on an RFC822 formatted message. From ae64299e147b777e576ea025c05eae492e9ecf01 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Tue, 15 Mar 2011 16:43:25 +1100 Subject: [PATCH 2/2] ChangeLog correction --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index c642ab4..c90e6ac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ Not yet released - - when verifying Relaxed mode signatures, the partial DKIM-Signature + - when producing Relaxed mode signatures, the partial DKIM-Signature header must be canonicalized before hashing (Martin Pool)