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:
Scott Kitterman
2018-10-30 11:29:09 -04:00
parent 82d01d8a42
commit 8032276b57
5 changed files with 51 additions and 9 deletions
+11 -1
View File
@@ -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)
+13 -2
View File
@@ -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
View File
@@ -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
+3 -2
View File
@@ -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)
+1 -1
View File
@@ -25,7 +25,7 @@ from setuptools import setup
import os
import sys
version = "0.8.2"
version = "0.9.0"
kw = {} # Work-around for lack of 'or' requires in setuptools.
try: