Bump version to 0.9.0 since this is now a feature release
- Update oversigned (frozen) header field list to reduce signature
fragility (removes 'date' and 'subject' fields from being oversigned by
default - see usage section of README for information on how to restore
the previous behavior)
- Added new add_should_not for DKIM/ARC classes to prevent additional
header fields from being signed
- Added 'from' to should sign list (to prevent it from not being signed at
all in the unusual event that 'from' is locally removed from the frozen
header field set (LP: #1525048)
- Updates for experimental ARC support:
- Specified that for ARC, Authentication-Results should not be signed
This commit is contained in:
@@ -1,9 +1,19 @@
|
||||
UNRELEASED Version 0.8.2
|
||||
UNRELEASED Version 0.9.0
|
||||
- Update oversigned (frozen) header field list to reduce signature
|
||||
fragility (removes 'date' and 'subject' fields from being oversigned by
|
||||
default - see usage section of README for information on how to restore
|
||||
the previous behavior)
|
||||
- Added new add_should_not for DKIM/ARC classes to prevent additional
|
||||
header fields from being signed
|
||||
- Added 'from' to should sign list (to prevent it from not being signed at
|
||||
all in the unusual event that 'from' is locally removed from the frozen
|
||||
header field set (LP: #1525048)
|
||||
- Updates for experimental ARC support:
|
||||
- Limit to rsa-sha256, rsa-sha1 not used by ARC and multi-signature
|
||||
design TBD
|
||||
- Raise error when ARC signing if i= instance limit value of 50 is
|
||||
exceeded
|
||||
- Specified that for ARC, Authentication-Results should not be signed
|
||||
- Fix DNS lookups to be compatible with EAI addresses in domains and
|
||||
selectors (John Levine)
|
||||
- Add type Hinting for sign and verify functions (LP: #1782596)
|
||||
|
||||
@@ -11,7 +11,7 @@ signing and verification.
|
||||
|
||||
VERSION
|
||||
|
||||
This is dkimpy 0.8.0.
|
||||
This is dkimpy 0.9.0.
|
||||
|
||||
REQUIREMENTS
|
||||
|
||||
@@ -91,6 +91,17 @@ function takes an RFC822 formatted message, and returns True or False depending
|
||||
on whether the signature verifies correctly. There is also a DKIM class which
|
||||
can be used to perform these functions in a more modern way.
|
||||
|
||||
In version 0.9.0, the default set of header fields that are oversigned was
|
||||
changed from 'from', 'subject', 'date' to 'from' to reduce fragility of
|
||||
signatures. To restore the previous behavior, you can add them back after
|
||||
instantiating your DKIM class using the add_frozen function as shown in the
|
||||
following example:
|
||||
|
||||
>>> dkim = DKIM()
|
||||
>>> dkim.add_frozen((b'date',b'subject'))
|
||||
>>> [text(x) for x in sorted(dkim.frozen_sign)]
|
||||
['date', 'from', 'subject']
|
||||
|
||||
RFC8301 updated DKIM requirements in two ways:
|
||||
|
||||
1. It set the minimum valid RSA key size to 1024 bits.
|
||||
@@ -145,7 +156,7 @@ code 1.
|
||||
As of version 0.6.0, dkimpy provides experimental support for ARC (Authenticated
|
||||
Received Chain):
|
||||
|
||||
https://tools.ietf.org/html/draft-ietf-dmarc-arc-protocol-01
|
||||
https://tools.ietf.org/html/draft-ietf-dmarc-arc-protocol-18
|
||||
|
||||
This new functionality is marked experimental because the protocol is still
|
||||
under development. There are no guarantees about API stability or
|
||||
|
||||
+23
-3
@@ -486,12 +486,12 @@ class DomainSigner(object):
|
||||
#:
|
||||
#: The short list below is the result more of instinct than logic.
|
||||
#: @since: 0.5
|
||||
FROZEN = (b'from',b'date',b'subject')
|
||||
FROZEN = (b'from',)
|
||||
|
||||
#: The rfc6376 recommended header fields to sign
|
||||
#: @since: 0.5
|
||||
SHOULD = (
|
||||
b'sender', b'reply-to', b'subject', b'date', b'message-id', b'to', b'cc',
|
||||
b'from', b'sender', b'reply-to', b'subject', b'date', b'message-id', b'to', b'cc',
|
||||
b'mime-version', b'content-type', b'content-transfer-encoding',
|
||||
b'content-id', b'content-description', b'resent-date', b'resent-from',
|
||||
b'resent-sender', b'resent-to', b'resent-cc', b'resent-message-id',
|
||||
@@ -526,11 +526,30 @@ class DomainSigner(object):
|
||||
>>> dkim = DKIM()
|
||||
>>> dkim.add_frozen(DKIM.RFC5322_SINGLETON)
|
||||
>>> [text(x) for x in sorted(dkim.frozen_sign)]
|
||||
['cc', 'date', 'from', 'in-reply-to', 'message-id', 'references', 'reply-to', 'sender', 'subject', 'to']
|
||||
['cc', 'date', 'from', 'in-reply-to', 'message-id', 'references', 'reply-to', 'sender', 'to']
|
||||
>>> dkim2 = DKIM()
|
||||
>>> dkim2.add_frozen((b'date',b'subject'))
|
||||
>>> [text(x) for x in sorted(dkim2.frozen_sign)]
|
||||
['date', 'from', 'subject']
|
||||
"""
|
||||
self.frozen_sign.update(x.lower() for x in s
|
||||
if x.lower() not in self.should_not_sign)
|
||||
|
||||
|
||||
def add_should_not(self,s):
|
||||
""" Add headers not in should_not_sign to frozen_sign.
|
||||
@param s: list of headers to add to frozen_sign
|
||||
@since: 0.5
|
||||
|
||||
>>> dkim = DKIM()
|
||||
>>> dkim.add_should_not(DKIM.RFC5322_SINGLETON)
|
||||
>>> [text(x) for x in sorted(dkim.should_not_sign)]
|
||||
['bcc', 'cc', 'comments', 'date', 'dkim-signature', 'in-reply-to', 'keywords', 'message-id', 'received', 'references', 'reply-to', 'resent-bcc', 'return-path', 'sender', 'to']
|
||||
"""
|
||||
self.should_not_sign.update(x.lower() for x in s
|
||||
if x.lower() not in self.frozen_sign)
|
||||
|
||||
|
||||
#: Load a new message to be signed or verified.
|
||||
#: @param message: an RFC822 formatted message to be signed or verified
|
||||
#: (with either \\n or \\r\\n line endings)
|
||||
@@ -900,6 +919,7 @@ class ARC(DomainSigner):
|
||||
timestamp=None, standardize=False):
|
||||
|
||||
INSTANCE_LIMIT = 50 # Maximum allowed i= value
|
||||
self.add_should_not(('Authentication-Results',))
|
||||
# check if authres has been imported
|
||||
try:
|
||||
AuthenticationResultsHeader
|
||||
|
||||
@@ -69,11 +69,12 @@ Y+vtSBczUiKERHv1yRbcaQtZFh5wtiRrN04BLUTD21MycBX5jYchHjPY/wIDAQAB"""
|
||||
return _dns_responses[domain]
|
||||
|
||||
def test_signs_and_verifies(self):
|
||||
# A message verifies after being signed.
|
||||
# A message verifies after being signed
|
||||
self.maxDiff = None
|
||||
sig_lines = dkim.arc_sign(
|
||||
self.message, b"test", b"example.com", self.key, b"lists.example.org", timestamp="12345")
|
||||
|
||||
expected_sig = [b'ARC-Seal: i=1; cv=none; a=rsa-sha256; d=example.com; s=test; t=12345; \r\n b=3jOfBfTKcq+3r3Xv158DybT4mWFxrGcop+cgyLUX2ETCMHqNXYwGx2h+NY46tr\r\n k0Lg6R8i+560+KC8PLcCURYYJNJUHLHPIifhddy1aMNL9l4CoI+Oz+rocd2IZeb/\r\n I9V5amOUOWnAlOvyrSt0XfzLJRTS8qJW3Is1CRkkgyLoI=\r\n', b'ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; \r\n d=example.com; s=test; t=12345; h=message-id : \r\n date : from : to : subject : date : from : \r\n subject; \r\n bh=wE7NXSkgnx9PGiavN4OZhJztvkqPDlemV3OGuEnLwNo=; \r\n b=Bj/AEKhmzMbltWXrfLA8UZNp6/5cj8/IzqbgQec4vGobDZRsa\r\n C0YIPM4tcqK2uTS62kwh40cndXTDsCppvRsBy1sIO3eRNyuLUOh\r\n 0XGrz0AdLQMv+IOdyQqZfMVkq8DuQ4Qdl7ee99uYf3D8S+L7GuD\r\n wJSk7dyH+P2BKxz2nyB0=\r\n', b'ARC-Authentication-Results: i=1; lists.example.org; arc=none;\r\n spf=pass smtp.mfrom=jqd@d1.example;\r\n dkim=pass (1024-bit key) header.i=@d1.example;\r\n dmarc=pass\r\n']
|
||||
expected_sig = [b'ARC-Seal: i=1; cv=none; a=rsa-sha256; d=example.com; s=test; t=12345; \r\n b=2DTLaiAcKznJwwNOWoOG8WBsdTq+/S92TZbURDxkgjGCmsSw8czQiisf02sC92\r\n 0nswz3JItA80l70iguM00onrj3eCe41yRDzB8lQL3kbrDyM+wUewmyhPoifRTsng\r\n t9ELTFrax4kCeHv6SdNz3uJfGYwQc+WCFEchXt3szNTRM=\r\n', b'ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; \r\n d=example.com; s=test; t=12345; h=message-id : \r\n date : from : to : subject : from; \r\n bh=wE7NXSkgnx9PGiavN4OZhJztvkqPDlemV3OGuEnLwNo=; \r\n b=a0f6qc3k9eECTSR155A0TQS+LjqPFWfI/brQBA83EUz00SNxj\r\n 1wmWykvs1hhBVeM0r1kEQc6CKbzRYaBNSiFj4q8JBpRIujLz1qL\r\n yGmPuAI6ddu/Z/1hQxgpVcp/odmI1UMV2R+d+yQ7tUp3EQxF/GY\r\n Nt22rV4rNmDmANZVqJ90=\r\n', b'ARC-Authentication-Results: i=1; lists.example.org; arc=none;\r\n spf=pass smtp.mfrom=jqd@d1.example;\r\n dkim=pass (1024-bit key) header.i=@d1.example;\r\n dmarc=pass\r\n']
|
||||
|
||||
self.assertEqual(expected_sig, sig_lines)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user