Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-dkimpy for openSUSE:Factory 
checked in at 2024-01-06 19:38:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-dkimpy (Old)
 and      /work/SRC/openSUSE:Factory/.python-dkimpy.new.28375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-dkimpy"

Sat Jan  6 19:38:04 2024 rev:6 rq:1137284 version:1.1.5

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-dkimpy/python-dkimpy.changes      
2023-06-18 23:08:28.189650071 +0200
+++ /work/SRC/openSUSE:Factory/.python-dkimpy.new.28375/python-dkimpy.changes   
2024-01-06 19:38:05.602285235 +0100
@@ -1,0 +2,44 @@
+Sat Jan  6 18:02:16 UTC 2024 - Dirk Müller <dmuel...@suse.com>
+
+- update to 1.1.5:
+  * Use dns.resolver.resolve instead of dns.resolver.query
+    due to deprecation
+  * Treat dns.resolver.NoNameservers like NXDOMAIN (not an
+    error)
+  * Confine errors from dnspython to dnsplug and use dkim
+    errors, since dkim.__init__.py doesn't import dns and
+    needs dkim errors
+  * Catch nacl.exceptions.ValueError and raise
+    KeyFormatError, similar to how RSA key errors are treated
+  * Create ed25519 key files with secure permissions to
+    avoid risk of insecure chmode call/race condition
+  * Properly cleanup temporary directories in tests
+  * Verify correct AMS header is used for ARC seal
+    verification (André Cruz)
+  * Document dropping of Python 2 support
+  * Fix traceback when attempting to verify an unsigned
+    message using async verify
+  * Add domain validity check for ascii domains (no
+    specials)
+  * Add option to specify index number of signature to
+    verify to dkimverify
+  * Correct signature indexing error introduced in 1.0.0
+    that prevents verification of multiple signatures in a
+    single message
+  * Correct dkim.verify processing to avoid errors when
+    verifying messages with no DKIM signatures
+  * Update dnsplug for DNS Python (dns) 2.0 compatibility
+  * Provide more specific error message when ed25519
+    private key is invalid
+  * Add support for PKCS#8 for private keys, openssl 3
+    default
+  * Add limitations section to README to document current
+    IDN status
+  * Add USE_ASYNC flag to allow async to be disabled when
+    aiodns is installed (LP: #1954331)
+  * Add new dkim.DnsTimeoutError class to report queried
+    domain and selector along with timeout error from dnspython
+  * Invalid Authentication-Results header fields are
+    ignored for ARC signing
+
+-------------------------------------------------------------------

Old:
----
  dkimpy-1.0.5.tar.gz

New:
----
  dkimpy-1.1.5.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-dkimpy.spec ++++++
--- /var/tmp/diff_new_pack.bq8BcV/_old  2024-01-06 19:38:07.162342240 +0100
+++ /var/tmp/diff_new_pack.bq8BcV/_new  2024-01-06 19:38:07.174342678 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-dkimpy
 #
-# Copyright (c) 2023 SUSE LLC
+# Copyright (c) 2024 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
 %{?sle15_python_module_pythons}
 %define commands arcsign arcverify dkimsign dkimverify dknewkey
 Name:           python-dkimpy
-Version:        1.0.5
+Version:        1.1.5
 Release:        0
 Summary:        DKIM (DomainKeys Identified Mail)
 License:        BSD-2-Clause
@@ -28,6 +28,7 @@
 Patch0:         no-optional.patch
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  fdupes
+BuildRequires:  openssl
 BuildRequires:  python-rpm-macros
 Requires:       python-PyNaCl
 Requires:       python-authres

++++++ dkimpy-1.0.5.tar.gz -> dkimpy-1.1.5.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/ChangeLog new/dkimpy-1.1.5/ChangeLog
--- old/dkimpy-1.0.5/ChangeLog  2020-08-09 04:34:58.000000000 +0200
+++ new/dkimpy-1.1.5/ChangeLog  2023-07-28 17:57:20.000000000 +0200
@@ -1,14 +1,56 @@
-2020-08-08 Version 1.0.5
-    - Update dnsplug for DNS Python (dns) 2.0 compatibility (LP: #1888583)
-    - Fix @param srv_id typos (LP: #1890532)
+2023-07-28 Version 1.1.5
+   - Use dns.resolver.resolve instead of dns.resolver.query due to deprecation
+     (LP: 2028783) - Thanks to Pedro Vicente for the report and the fix
 
-2020-04-06 Version 1.0.4
-    - Correct dkim.verify processing to avoid errors when verifying messages
-      with no DKIM signatures
+2023-05-12 Version 1.1.4
+   - Treat dns.resolver.NoNameservers like NXDOMAIN (not an error) (Thanks to
+     David for the patch and the report)
+   - Confine errors from dnspython to dnsplug and use dkim errors, since
+     dkim.__init__.py doesn't import dns and needs dkim errors (LP: #2018646)
+
+2023-04-30 Version 1.1.3
+   - Catch nacl.exceptions.ValueError and raise KeyFormatError, similar to how
+     RSA key errors are treated (LP: #2018021)
+   - Create ed25519 key files with secure permissions to avoid risk of
+     insecure chmode call/race condition (Thanks to Hanno Böck for the report
+     and the suggested fix) (LP: #2017430)
+   - Properly cleanup temporary directories in tests
+
+2023-04-09 Version 1.1.2
+   - Verify correct AMS header is used for ARC seal verification (André Cruz)
 
-2020-01-15 Version 1.0.3
+2023-03-09 Version 1.1.1
+    - Document dropping of Python 2 support (dropped as of 1.1.0) (LP:
+      #20086738)
+    - Fix traceback when attempting to verify an unsigned message using
+      async verify (Thanks to Nikita Sychev for the report and a suggested
+      fix) (LP: #2008723)
+
+2023-02-25 Version 1.1.0
+    - Add domain validity check for ascii domains (no specials)
+    - Add option to specify index number of signature to verify to dkimverify
+      (Thanks to Nick Baugh for the change)
     - Correct signature indexing error introduced in 1.0.0 that prevents
       verification of multiple signatures in a single message
+    - Correct dkim.verify processing to avoid errors when verifying messages
+      with no DKIM signatures
+    - Update dnsplug for DNS Python (dns) 2.0 compatibility (LP: #1888583)
+    - Fix @param srv_id typos (LP: #1890532)
+    - Provide more specific error message when ed25519 private key is invalid
+      (See LP 1901569 for background)
+    - Add support for PKCS#8 for private keys, openssl 3 default (LP:
+      #1978835) - Thanks to Adrien (spitap) for the change
+    - Add limitations section to README to document current IDN status
+    - Add USE_ASYNC flag to allow async to be disabled when aiodns is
+      installed (LP: #1954331) - see README.md for details
+    - Add new dkim.DnsTimeoutError class to report queried domain and selector
+      along with timeout error from dnspython (LP: #1873449)
+    - Invalid Authentication-Results header fields are ignored for ARC signing
+      (LP: #1884044)
+    - Correct base64 validation regexp so that valid signature with == split
+      between two lines are not incorrectly evaluated as invalid (LP:
+      #2002295) - Thanks to <https://launchpad.net/~obadz> for the report and
+      the proposed fix
 
 2019-12-31 Version 1.0.2
     - dknewkey: On posix operating systems set file permissions to 600 for
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/PKG-INFO new/dkimpy-1.1.5/PKG-INFO
--- old/dkimpy-1.0.5/PKG-INFO   2020-08-09 04:35:02.000000000 +0200
+++ new/dkimpy-1.1.5/PKG-INFO   2023-07-28 18:02:28.864313000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: dkimpy
-Version: 1.0.5
+Version: 1.1.5
 Summary: DKIM (DomainKeys Identified Mail), ARC (Authenticated Receive Chain), 
and TLSRPT (TLS Report) email signing and verification
 Home-page: https://launchpad.net/dkimpy
 Author: Scott Kitterman
@@ -21,7 +21,7 @@
         
         # VERSION
         
-        This is dkimpy 1.0.5.
+        This is dkimpy 1.1.5.
         
         # REQUIREMENTS
         
@@ -32,12 +32,10 @@
         Similarly, extras_requires feature 'asyncio' will add the extra 
dependencies
         needed for asyncio.
         
-         - Python 2.x >= 2.7, or Python 3.x >= 3.5.  Recent versions have not 
been
-           tested on python < 2.7 or python3 < 3.4, but may still work on 
python2.6
-           and python 3.1 - 3.3.
-         - dnspython or pydns. dnspython is preferred if both are present and
+         - Python 3.x >= 3.5.  Recent versions have not been on python3 < 3.4, 
but
+           may still work on earlier python3 versions.
+         - dnspython or py3dns. dnspython is preferred if both are present and
            installed to satisfy the DNS module requirement if neither are 
installed.
-         - argparse.  Standard library in python2.7 and later.
          - authres.  Needed for ARC.
          - PyNaCl.  Needed for use of ed25519 capability.
          - aiodns.  Needed for asycnio (Requires python3.5 or later)
@@ -91,8 +89,10 @@
          ships with test runners for dkimpy.  After downloading the test 
suite, you
          can run the signing and validation tests like this:
         
-        ```python2.7 ./testarc.py sign runners/arcsigntest.py```
-        ```python2.7 ./testarc.py validate runners/arcverifytest.py```
+        ```python3 ./testarc.py sign runners/arcsigntest.py```
+        ```python3 ./testarc.py validate runners/arcverifytest.py```
+        
+        As ov version 1.1.0, python2.7 is no longer supported.
         
         # USAGE
         
@@ -160,7 +160,10 @@
         
         dknewkey is s script that produces private and public key pairs 
suitable
         for use with DKIM.  Note that the private key file format used for 
ed25519 is
-        not standardized (there is no standard) and is unique to dkimpy.
+        not standardized (there is no standard) and is unique to dkimpy.  
Creation of
+        keys should be done in a secure environment.  If an unauthorized 
entity gains
+        access to current private keys they can generate signed email that 
will pass
+        DKIM checkes and will be difficult to repudiate.
         
         dkimsign is a filter that reads an RFC822 message on standard input, 
and
         writes the same message on standard output with a DKIM-Signature line
@@ -184,6 +187,9 @@
         In addition to arcsign and arcverify, the dkim module now provides
         arc_sign and arc_verify functions as well as an ARC class.
         
+        If an invalid authentication results header field is included in the 
set for
+        ARC, it is ignored and no error is raised.
+        
         Both DKIM ed25519 and ARC are now considered stable (no longer 
experimantal).
         
         ## ASYNC SUPPORT
@@ -205,6 +211,9 @@
         
         This feature requires python3.5 or newer.
         
+        If aiodns is available, the async functions will be used.  To avoide 
async
+        when aiodns is availale, set dkim.USE_ASYNC = False.
+        
         ## TLSRPT (TLS Report)
         
         As of version 1.0, the RFC 8460 tlsrpt service type is supported:
@@ -224,6 +233,13 @@
         valid.  If set to tlsrpt=True, the service type is not required, but 
other
         RFC 8460 requirements are applied.
         
+        # LIMITATIONS
+        
+        Dkimpy will correctly sign/verify messages with ASCII or UTF-8 content.
+        Messages that contain other types of content will not verify 
correctly.  It
+        does not yet implement RFC 8616, Email Authentication for 
Internationalized
+        Mail.
+        
         # FEEDBACK
         
         Bug reports may be submitted to the bug tracker for the dkimpy project 
on
@@ -236,7 +252,6 @@
 Classifier: License :: DFSG approved
 Classifier: Natural Language :: English
 Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 3
 Classifier: Topic :: Communications :: Email :: Mail Transport Agents
 Classifier: Topic :: Communications :: Email :: Filters
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/README.md new/dkimpy-1.1.5/README.md
--- old/dkimpy-1.0.5/README.md  2020-08-08 23:04:57.000000000 +0200
+++ new/dkimpy-1.1.5/README.md  2023-07-28 17:59:27.000000000 +0200
@@ -13,7 +13,7 @@
 
 # VERSION
 
-This is dkimpy 1.0.5.
+This is dkimpy 1.1.5.
 
 # REQUIREMENTS
 
@@ -24,12 +24,10 @@
 Similarly, extras_requires feature 'asyncio' will add the extra dependencies
 needed for asyncio.
 
- - Python 2.x >= 2.7, or Python 3.x >= 3.5.  Recent versions have not been
-   tested on python < 2.7 or python3 < 3.4, but may still work on python2.6
-   and python 3.1 - 3.3.
- - dnspython or pydns. dnspython is preferred if both are present and
+ - Python 3.x >= 3.5.  Recent versions have not been on python3 < 3.4, but
+   may still work on earlier python3 versions.
+ - dnspython or py3dns. dnspython is preferred if both are present and
    installed to satisfy the DNS module requirement if neither are installed.
- - argparse.  Standard library in python2.7 and later.
  - authres.  Needed for ARC.
  - PyNaCl.  Needed for use of ed25519 capability.
  - aiodns.  Needed for asycnio (Requires python3.5 or later)
@@ -83,8 +81,10 @@
  ships with test runners for dkimpy.  After downloading the test suite, you
  can run the signing and validation tests like this:
 
-```python2.7 ./testarc.py sign runners/arcsigntest.py```
-```python2.7 ./testarc.py validate runners/arcverifytest.py```
+```python3 ./testarc.py sign runners/arcsigntest.py```
+```python3 ./testarc.py validate runners/arcverifytest.py```
+
+As ov version 1.1.0, python2.7 is no longer supported.
 
 # USAGE
 
@@ -152,7 +152,10 @@
 
 dknewkey is s script that produces private and public key pairs suitable
 for use with DKIM.  Note that the private key file format used for ed25519 is
-not standardized (there is no standard) and is unique to dkimpy.
+not standardized (there is no standard) and is unique to dkimpy.  Creation of
+keys should be done in a secure environment.  If an unauthorized entity gains
+access to current private keys they can generate signed email that will pass
+DKIM checkes and will be difficult to repudiate.
 
 dkimsign is a filter that reads an RFC822 message on standard input, and
 writes the same message on standard output with a DKIM-Signature line
@@ -176,6 +179,9 @@
 In addition to arcsign and arcverify, the dkim module now provides
 arc_sign and arc_verify functions as well as an ARC class.
 
+If an invalid authentication results header field is included in the set for
+ARC, it is ignored and no error is raised.
+
 Both DKIM ed25519 and ARC are now considered stable (no longer experimantal).
 
 ## ASYNC SUPPORT
@@ -197,6 +203,9 @@
 
 This feature requires python3.5 or newer.
 
+If aiodns is available, the async functions will be used.  To avoide async
+when aiodns is availale, set dkim.USE_ASYNC = False.
+
 ## TLSRPT (TLS Report)
 
 As of version 1.0, the RFC 8460 tlsrpt service type is supported:
@@ -216,6 +225,13 @@
 valid.  If set to tlsrpt=True, the service type is not required, but other
 RFC 8460 requirements are applied.
 
+# LIMITATIONS
+
+Dkimpy will correctly sign/verify messages with ASCII or UTF-8 content.
+Messages that contain other types of content will not verify correctly.  It
+does not yet implement RFC 8616, Email Authentication for Internationalized
+Mail.
+
 # FEEDBACK
 
 Bug reports may be submitted to the bug tracker for the dkimpy project on
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkim/__init__.py 
new/dkimpy-1.1.5/dkim/__init__.py
--- old/dkimpy-1.0.5/dkim/__init__.py   2020-08-08 23:05:10.000000000 +0200
+++ new/dkimpy-1.1.5/dkim/__init__.py   2023-05-12 07:08:45.000000000 +0200
@@ -40,9 +40,12 @@
 import time
 import binascii
 
+# Set to False to not use async functions even though aiodns is installed.
+USE_ASYNC = True
+
 # only needed for arc
 try:
-    from authres import AuthenticationResultsHeader
+    import authres
 except ImportError:
     pass
 
@@ -72,13 +75,17 @@
 try:
     from dkim.dnsplug import get_txt
 except ImportError:
-    try:
-        import aiodns
-        from dkim.asyncsupport import get_txt_async as get_txt
-    except:
-        # Only true if not using async
-        def get_txt(s,timeout=5):
-            raise RuntimeError("DKIM.verify requires DNS or dnspython module")
+    if USE_ASYNC:
+        try:
+            import aiodns
+            from dkim.asyncsupport import get_txt_async as get_txt
+        except:
+            # Only true if not using async
+            def get_txt(s,timeout=5):
+                raise RuntimeError("DKIM.verify requires DNS or dnspython 
module")
+    else:
+        raise RuntimeError("DKIM.verify requires DNS or dnspython module")
+
 from dkim.util import (
     get_default_logger,
     InvalidTagValueList,
@@ -94,6 +101,8 @@
     "ValidationError",
     "AuthresNotFoundError",
     "NaClNotFoundError",
+    "DnsTimeoutError",
+    "USE_ASYNC",
     "CV_Pass",
     "CV_Fail",
     "CV_None",
@@ -187,6 +196,9 @@
 class UnknownKeyTypeError(DKIMException):
     """ Key type (k tag) is not known (rsa/ed25519) """
 
+class DnsTimeoutError(DKIMException):
+    """ DNS query for public key timed out """
+
 
 def select_headers(headers, include_headers):
     """Select message header fields to be signed/verified.
@@ -272,13 +284,13 @@
         raise ValidationError("unknown signature algorithm: %s" % sig[b'a'])
 
     if b'b' in sig:
-        if re.match(br"[\s0-9A-Za-z+/]+=*$", sig[b'b']) is None:
+        if re.match(br"[\s0-9A-Za-z+/]+[\s=]*$", sig[b'b']) is None:
             raise ValidationError("b= value is not valid base64 (%s)" % 
sig[b'b'])
         if len(re.sub(br"\s+", b"", sig[b'b'])) % 4 != 0:
             raise ValidationError("b= value is not valid base64 (%s)" % 
sig[b'b'])
 
     if b'bh' in sig:
-        if re.match(br"[\s0-9A-Za-z+/]+=*$", sig[b'bh']) is None:
+        if re.match(br"[\s0-9A-Za-z+/]+[\s=]*$", sig[b'b']) is None:
             raise ValidationError("bh= value is not valid base64 (%s)" % 
sig[b'bh'])
         if len(re.sub(br"\s+", b"", sig[b'bh'])) % 4 != 0:
             raise ValidationError("bh= value is not valid base64 (%s)" % 
sig[b'bh'])
@@ -286,6 +298,16 @@
     if b'cv' in sig and sig[b'cv'] not in (CV_Pass, CV_Fail, CV_None):
         raise ValidationError("cv= value is not valid (%s)" % sig[b'cv'])
 
+    # Limit domain validation to ASCII domains because too hard
+    try:
+        str(sig[b'd'], 'ascii')
+        # No specials, which is close enough
+        if re.findall(b"[\(\)<>\[\]:;@\\,]", sig[b'd']):
+            raise ValidationError("d= value is not valid (%s)" % sig[b'd'])
+    except UnicodeDecodeError as e:
+        # Not an ASCII domain
+        pass
+
     # Nasty hack to support both str and bytes... check for both the
     # character and integer values.
     if not arc and b'i' in sig and (
@@ -446,6 +468,8 @@
               pk = nacl.signing.VerifyKey(pub[b'p'], 
encoder=nacl.encoding.Base64Encoder)
           except NameError:
               raise NaClNotFoundError('pynacl module required for ed25519 
signing, see README.md')
+          except nacl.exceptions.ValueError as e:
+              raise KeyFormatError("could not parse ed25519 public key (%s): 
%s" % (pub[b'p'],e))
           keysize = 256
           ktag = b'ed25519'
   except KeyError:
@@ -455,9 +479,9 @@
           pk = parse_public_key(base64.b64decode(pub[b'p']))
           keysize = bitsize(pk['modulus'])
       except KeyError:
-          raise KeyFormatError("incomplete public key: %s" % s)
+          raise KeyFormatError("incomplete RSA public key: %s" % s)
       except (TypeError,UnparsableKeyError) as e:
-          raise KeyFormatError("could not parse public key (%s): %s" % 
(pub[b'p'],e))
+          raise KeyFormatError("could not parse RSA public key (%s): %s" % 
(pub[b'p'],e))
       ktag = b'rsa'
   if pub[b'k'] != b'rsa' and pub[b'k'] != b'ed25519':
       raise KeyFormatError('unknown algorithm in k= tag: 
{0}'.format(pub[b'k']))
@@ -778,6 +802,10 @@
     except binascii.Error as e:
       self.logger.error('KeyFormatError: {0}'.format(e))
       return False
+    except DnsTimeoutError as e:
+      self.logger.error('DnsTimeoutError: Domain: {0} Selector: {1} Error 
message: {2}'.format(
+          sig[b'd'], sig[b's'], e))
+      return False
     return self.verify_sig_process(sig, include_headers, sig_header, dnsfunc)
 
 
@@ -832,6 +860,8 @@
             pk = nacl.signing.SigningKey(privkey, 
encoder=nacl.encoding.Base64Encoder)
         except NameError:
             raise NaClNotFoundError('pynacl module required for ed25519 
signing, see README.md')
+        except nacl.exceptions.ValueError:
+            raise KeyFormatError('invalid ed25519 private key or format')
 
     if identity is not None and not identity.endswith(domain):
         raise ParameterError("identity must end with domain")
@@ -1009,10 +1039,10 @@
     self.add_should_not(('Authentication-Results',))
     # check if authres has been imported
     try:
-        AuthenticationResultsHeader
+        authres.AuthenticationResultsHeader
     except:
         self.logger.debug("authres package not installed")
-        raise AuthresNotFoundError
+        raise authres.AuthresNotFoundError
 
     try:
         pk = parse_pem_private_key(privkey)
@@ -1021,8 +1051,14 @@
 
     # extract, parse, filter & group AR headers
     ar_headers = [res.strip() for [ar, res] in self.headers if ar == 
b'Authentication-Results']
-    grouped_headers = [(res, 
AuthenticationResultsHeader.parse('Authentication-Results: ' + 
res.decode('utf-8')))
-                       for res in ar_headers]
+
+    grouped_headers = []
+    for res in ar_headers:
+        try: # see LP: #1884044
+            grouped_headers.append((res, 
authres.AuthenticationResultsHeader.parse('Authentication-Results: ' + 
res.decode('utf-8'))))
+        except authres.core.SyntaxError:
+            # Skip over invalid AR header fields
+            pass
     auth_headers = [res for res in grouped_headers if res[1].authserv_id == 
srv_id.decode('utf-8')]
 
     if len(auth_headers) == 0:
@@ -1036,7 +1072,7 @@
     auth_results = srv_id + b'; ' + (b';' + self.linesep + b'  ').join(results)
 
     # extract cv
-    parsed_auth_results = 
AuthenticationResultsHeader.parse('Authentication-Results: ' + 
auth_results.decode('utf-8'))
+    parsed_auth_results = 
authres.AuthenticationResultsHeader.parse('Authentication-Results: ' + 
auth_results.decode('utf-8'))
     arc_results = [res for res in parsed_auth_results.results if res.method == 
'arc']
     if len(arc_results) == 0:
       chain_validation_status = CV_None
@@ -1259,7 +1295,9 @@
     # we can't use the AMS provided above, as it's already been canonicalized 
relaxed
     # for use in validating the AS.  However the AMS is included in the AMS 
itself,
     # and this can use simple canonicalization
-    raw_ams_header = [(x, y) for (x, y) in self.headers if x.lower() == 
b'arc-message-signature'][0]
+    raw_ams_header = [
+       (x, y) for (x, y) in self.headers if x.lower() == 
b'arc-message-signature' and b" i="+sig[b'i']+b";" in y.lower()
+    ][0]
 
     # Only relaxed canonicalization used by ARC
     if b'c' not in sig:
@@ -1357,7 +1395,7 @@
 
 
 # aiodns requires Python 3.5+, so no async before that
-if sys.version_info >= (3, 5):
+if sys.version_info >= (3, 5) and USE_ASYNC:
     try:
         import aiodns
         from dkim.asyncsupport import verify_async
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkim/asn1.py 
new/dkimpy-1.1.5/dkim/asn1.py
--- old/dkimpy-1.0.5/dkim/asn1.py       2020-04-06 06:06:13.000000000 +0200
+++ new/dkimpy-1.1.5/dkim/asn1.py       2023-04-30 16:18:48.000000000 +0200
@@ -84,6 +84,9 @@
               elif tag == SEQUENCE:
                   r.append(asn1_parse(t[1], data[i:i+length]))
                   i += length
+              elif tag == OCTET_STRING:
+                  r.append(data[i:i+length])
+                  i += length
               else:
                   raise ASN1FormatError(
                       "Unexpected tag in template: %02x" % tag)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkim/asyncsupport.py 
new/dkimpy-1.1.5/dkim/asyncsupport.py
--- old/dkimpy-1.0.5/dkim/asyncsupport.py       2020-04-06 06:27:45.000000000 
+0200
+++ new/dkimpy-1.1.5/dkim/asyncsupport.py       2023-04-30 15:58:34.000000000 
+0200
@@ -94,8 +94,11 @@
 
 
   async def verify(self,idx=0,dnsfunc=get_txt_async):
-    sig, include_headers, sigheaders = self.verify_headerprep(idx=0)
-    return await self.verify_sig(sig, include_headers, sigheaders[idx], 
dnsfunc)
+    prep = self.verify_headerprep(idx)
+    if prep:
+        sig, include_headers, sigheaders = prep
+        return await self.verify_sig(sig, include_headers, sigheaders[idx], 
dnsfunc)
+    return False # No signature
 
 
 async def verify_async(message, logger=None, dnsfunc=None, minkey=1024,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkim/crypto.py 
new/dkimpy-1.1.5/dkim/crypto.py
--- old/dkimpy-1.0.5/dkim/crypto.py     2020-04-06 06:27:45.000000000 +0200
+++ new/dkimpy-1.1.5/dkim/crypto.py     2023-04-30 16:18:48.000000000 +0200
@@ -48,6 +48,13 @@
     NULL,
     )
 
+ASN1_PKCS8_PrivateKey = [
+    (SEQUENCE, [
+        (INTEGER,),
+        (SEQUENCE, [ (OBJECT_IDENTIFIER,), (NULL,),]),
+        (OCTET_STRING,),
+    ]) 
+]
 
 ASN1_Object = [
     (SEQUENCE, [
@@ -133,13 +140,19 @@
 def parse_private_key(data):
     """Parse an RSA private key.
 
-    @param data: DER-encoded RFC8017 RSAPrivateKey.
+    @param data: DER-encoded RFC8017 RSAPrivateKey or CMS-encoded RFC5958 
asymetric key package.
     @return: RSA private key
     """
     try:
         pka = asn1_parse(ASN1_RSAPrivateKey, data)
-    except ASN1FormatError as e:
-        raise UnparsableKeyError('Unparsable private key: ' + str(e))
+    except ASN1FormatError:
+        try:
+            #If it fails it might be because of PKCS#8 (key generated with 
openSSL 3.X)
+            pkt = asn1_parse(ASN1_PKCS8_PrivateKey, data)
+            pka = asn1_parse(ASN1_RSAPrivateKey, pkt[0][2])
+        except ASN1FormatError as e:
+            raise UnparsableKeyError("Unparsable private key (are your sure it 
is encoded in PKCS#1 or PKCS#8 standard ?):\n" + str(e))
+
     pk = {
         'version': pka[0][0],
         'modulus': pka[0][1],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkim/dkimverify.py 
new/dkimpy-1.1.5/dkim/dkimverify.py
--- old/dkimpy-1.0.5/dkim/dkimverify.py 2020-08-08 23:04:57.000000000 +0200
+++ new/dkimpy-1.1.5/dkim/dkimverify.py 2023-04-30 16:18:48.000000000 +0200
@@ -24,11 +24,17 @@
 from __future__ import print_function
 
 import sys
+import argparse
 
 import dkim
 
-
 def main():
+    parser = argparse.ArgumentParser(
+        description='Verify DKIM signature for email messages.',
+        epilog="message to be verified follows commands on stdin")
+    parser.add_argument('--index', metavar='N', type=int, default=0,
+        help='Index of DKIM signature header to verify: default=0')
+    args=parser.parse_args()
     if sys.version_info[0] >= 3:
         # Make sys.stdin a binary stream.
         sys.stdin = sys.stdin.detach()
@@ -38,9 +44,9 @@
     if verbose:
         import logging
         d = dkim.DKIM(message, logger=logging)
-        res = d.verify()
     else:
-        res = dkim.verify(message)
+        d = dkim.DKIM(message)
+    res = d.verify(args.index)
     if not res:
         print("signature verification failed")
         sys.exit(1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkim/dknewkey.py 
new/dkimpy-1.1.5/dkim/dknewkey.py
--- old/dkimpy-1.0.5/dkim/dknewkey.py   2020-04-06 06:06:13.000000000 +0200
+++ new/dkimpy-1.1.5/dkim/dknewkey.py   2023-04-30 16:18:48.000000000 +0200
@@ -43,15 +43,17 @@
 def eprint(*args, **kwargs):
     print(*args, file=sys.stderr, **kwargs)
 
-def GenRSAKeys(private_key_file):
+def GenRSAKeys(private_key_file, verbose=True):
   """ Generates a suitable private key.  Output is unprotected.
   You should encrypt your keys.
   """
-  eprint('generating ' + private_key_file)
+  if verbose:
+    eprint('generating ' + private_key_file)
   subprocess.check_call([OPENSSL_BINARY, 'genrsa', '-out', private_key_file,
-                         str(BITS_REQUIRED)])
+                         str(BITS_REQUIRED)], 
+                         stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
 
-def GenEd25519Keys(private_key_file):
+def GenEd25519Keys(private_key_file, verbose=True):
     """Generates a base64 encoded private key for ed25519 DKIM signing.
     Output is unprotected.  You should protect your keys.
     """
@@ -59,21 +61,26 @@
     import nacl.encoding
     import os
     skg = nacl.signing.SigningKey(seed=os.urandom(32))
-    eprint('generating ' + private_key_file)
+    if verbose:
+        eprint('generating ' + private_key_file)
     priv_key = skg.generate()
+    if os.name == 'posix':
+        old_umask = os.umask(0o077)
     with open(private_key_file, 'w') as pkf:
         
pkf.write(priv_key.encode(encoder=nacl.encoding.Base64Encoder).decode("utf-8"))
     if os.name == 'posix':
-        os.chmod(private_key_file, 0o600)
+        os.umask(old_umask)
     return(priv_key)
 
-def ExtractRSADnsPublicKey(private_key_file, dns_file):
+def ExtractRSADnsPublicKey(private_key_file, dns_file, verbose=True):
   """ Given a key, extract the bit we should place in DNS.
   """
-  eprint('extracting ' + private_key_file)
+  if verbose:
+    eprint('extracting ' + private_key_file)
   working_file = tempfile.NamedTemporaryFile(delete=False).name
   subprocess.check_call([OPENSSL_BINARY, 'rsa', '-in', private_key_file,
-                         '-out', working_file, '-pubout', '-outform', 'PEM'])
+                         '-out', working_file, '-pubout', '-outform', 'PEM'],
+                          stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
   try:
       with open(working_file) as wf:
           y = ''
@@ -84,17 +91,19 @@
   finally:
       os.unlink(working_file)
   with open(dns_file, 'w') as dns_fp:
-      eprint('writing ' + dns_file)
+      if verbose:
+        eprint('writing ' + dns_file)
       dns_fp.write("v=DKIM1; k=rsa; h=sha256; p={0}".format(output))
 
-def ExtractEd25519PublicKey(dns_file, priv_key):
+def ExtractEd25519PublicKey(dns_file, priv_key, verbose=True):
     """ Given a ed25519 key, extract the bit we should place in DNS.
     """
     import nacl.encoding # Yes, pep-8, but let's not make everyone install nacl
     pubkey = priv_key.verify_key
     output = pubkey.encode(encoder=nacl.encoding.Base64Encoder).decode("utf-8")
     with open(dns_file, 'w') as dns_fp:
-        eprint('writing ' + dns_file)
+        if verbose:
+            eprint('writing ' + dns_file)
         dns_fp.write("v=DKIM1; k=ed25519; p={0}".format(output))
 
 def main():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkim/dnsplug.py 
new/dkimpy-1.1.5/dkim/dnsplug.py
--- old/dkimpy-1.0.5/dkim/dnsplug.py    2020-08-08 22:55:43.000000000 +0200
+++ new/dkimpy-1.1.5/dkim/dnsplug.py    2023-07-28 17:54:58.000000000 +0200
@@ -27,12 +27,18 @@
 
 def get_txt_dnspython(name, timeout=5):
     """Return a TXT record associated with a DNS name."""
+    import dkim
     try:
-      a = dns.resolver.query(name, dns.rdatatype.TXT,raise_on_no_answer=False, 
lifetime=timeout)
+      a = dns.resolver.resolve(name, 
dns.rdatatype.TXT,raise_on_no_answer=False, lifetime=timeout, search=True)
       for r in a.response.answer:
           if r.rdtype == dns.rdatatype.TXT:
               return b"".join(list(r.items)[0].strings)
     except dns.resolver.NXDOMAIN: pass
+    except dns.resolver.NoNameservers: pass
+    except dns.resolver.NoResolverConfiguration as e:
+        raise dkim.DnsTimeoutError('dns.resolver.NoResolverConfiguration: 
{0}'.format(e))
+    except dns.exception.Timeout as e:
+        raise dkim.DnsTimeoutError('dns.exception.Timeout: {0}'.format(e))
     return None
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkim/tests/__init__.py 
new/dkimpy-1.1.5/dkim/tests/__init__.py
--- old/dkimpy-1.0.5/dkim/tests/__init__.py     2020-04-06 06:27:45.000000000 
+0200
+++ new/dkimpy-1.1.5/dkim/tests/__init__.py     2023-04-30 16:18:48.000000000 
+0200
@@ -35,6 +35,7 @@
         test_util,
         test_arc,
         test_dnsplug,
+        test_dkim_generate,
         )
     modules = [
         test_canonicalization,
@@ -46,6 +47,7 @@
         test_util,
         test_arc,
         test_dnsplug,
+        test_dkim_generate,
         ]
     suites = [x.test_suite() for x in modules]
     return unittest.TestSuite(suites)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkim/tests/data/2048_testkey_PKCS8.key 
new/dkimpy-1.1.5/dkim/tests/data/2048_testkey_PKCS8.key
--- old/dkimpy-1.0.5/dkim/tests/data/2048_testkey_PKCS8.key     1970-01-01 
01:00:00.000000000 +0100
+++ new/dkimpy-1.1.5/dkim/tests/data/2048_testkey_PKCS8.key     2023-04-30 
16:18:48.000000000 +0200
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDYMGhEok34XiUg
+szO7cuYph/dw0lliI18+wwX0ybUNwjkmc89jfRNZ6OEF5BfuyMYAoHB96D9EhIAI
+qXzjmvFtjZIrYTyzb2X/4Cml7uxGLiekSFjrANL1mybg36FKeMAV59s078++IrcQ
+Trr1E6e7q127/YRwCGy+KZQ0Sl2CrL+IdPuCK5WAJtYT1zQ/h3PQ/xUcHLnUtem5
+BOirg7sweoxdfZWsXu7WeGDYiFOOV5pMmdueFfun5CJe8MfdEJ4YsXqxCxa2yqrN
+klkX4RSphEfwreU/sv0DsWj/eaWmFDhagvd2AwixId/lFYGsY2X7G6bs/SqThoBk
+9GftRGihAgMBAAECggEAYiHjCpiUBPQTLVs61dEridmWp8dL3IDK6K3VA88VmMe7
+cmlqT7JEOPE9R5PIi1Lmkf1B4t0r7tmoVoY80wIPqhdzrK5IQ/kCl1n0/cXMyXSE
++Q0AE7h9ihAh3zyTtb7HDop+1fIvXhLa/xOFyN5hqo34j+9dkQ858T3lcLD67mfO
+1/lpBhwEeF/7+wg2MiwM/4Rd217ReUgdgXTKZ8DYtLr+TFagv/8E8zAgHVqnklHf
+yEGR5+O94WYpqbanagfivxmogHsW6Eu5Ub/RJuWj06AvhRQSkPgVV5pl1zv0EP2w
+vhAl2YVzorRJDEzclmP+PyTzp+sPbrIqywof+K89WwKBgQDddD6eqISrWC4Vo2CZ
+WvBetiC48KKKjWwcFGERHGYqrmZMTDVYKqSUO7PvcgHIVyElYnlcqJWqyyQDBhy/
+ShOZjQ0oy9SblZMoVjLYONS0iFDoz2of8/kvY+kuzh+3iU9Qg6BI+lfRSd8KjGBB
+xsLOoUhzQceXqmx5SmOGIn6EmwKBgQD56efYqmYj/GGLz/gyfyElsQFUWG0tyNjm
+ujufTxjhEDWw3pnS3vUVG/gleGJH7f9vzCfEI4WlBuZUidrwM64cnF4QXQwuhT7p
+5U+nKNVfJpMeglehgVl6vSi/L1ovilCNo5A4aQJxyS73KTcU1UAZ4/VZnrvYrV/f
+ysxWTrx1cwKBgDAAyKofoVJ69NJf7cqQOdZt6D3ue21JJowXpsrMuyC5WRdk1ZNc
++vvezSw0LEq/CEJQTDpXmMnC6vV017pnVkRMnPOg618mVxXBSZgxCXpwqgktHLX8
+bqFlKOCqcZmZPAYZ4h6vlWWae6yPrTXU3dlogInrUlZ/7K+F/njO9VnNAoGBAOvp
+QsPDruGfd9GMQ2YfngG/glrFkmKa6y16dZfgCcNDEvvgVeK6Ny5zFZ8Bcf0mjG9T
+j+JWCe2LgtggvfzrPBuj/COEQmCTxZzzq2pHYIwOlOhC8Ef0G6yCbbl0ELU54uqh
+kR2++uDAokYMsQNIftcx2kR8VCSpHQzbmmKKttpDAoGBAIGVTOJtRi3nvmz1q3Zy
+vad1gTrkyy/gtjuE+8KNKhWwnC+MYXsSOykh+x6GQQ1gHRjk6GMsQxwl3xbHvzdG
+yp7Fc3aWkJbARSINOcAblH8JWdCMGBY/FlSogl0ptROVFxkyM2DnchM1bSsJ9wvf
+xB4hqm1VSknnOCCK+NekIC48
+-----END PRIVATE KEY-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/dkimpy-1.0.5/dkim/tests/data/2048_testkey_PKCS8.key.pub.txt 
new/dkimpy-1.1.5/dkim/tests/data/2048_testkey_PKCS8.key.pub.txt
--- old/dkimpy-1.0.5/dkim/tests/data/2048_testkey_PKCS8.key.pub.txt     
1970-01-01 01:00:00.000000000 +0100
+++ new/dkimpy-1.1.5/dkim/tests/data/2048_testkey_PKCS8.key.pub.txt     
2023-04-30 16:18:48.000000000 +0200
@@ -0,0 +1 @@
+v=DKIM1; g=*; k=rsa; 
p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2DBoRKJN+F4lILMzu3LmKYf3cNJZYiNfPsMF9Mm1DcI5JnPPY30TWejhBeQX7sjGAKBwfeg/RISACKl845rxbY2SK2E8s29l/+Appe7sRi4npEhY6wDS9Zsm4N+hSnjAFefbNO/PviK3EE669ROnu6tdu/2EcAhsvimUNEpdgqy/iHT7giuVgCbWE9c0P4dz0P8VHBy51LXpuQToq4O7MHqMXX2VrF7u1nhg2IhTjleaTJnbnhX7p+QiXvDH3RCeGLF6sQsWtsqqzZJZF+EUqYRH8K3lP7L9A7Fo/3mlphQ4WoL3dgMIsSHf5RWBrGNl+xum7P0qk4aAZPRn7URooQIDAQAB
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkim/tests/data/rfc6376.w1258.msg 
new/dkimpy-1.1.5/dkim/tests/data/rfc6376.w1258.msg
--- old/dkimpy-1.0.5/dkim/tests/data/rfc6376.w1258.msg  1970-01-01 
01:00:00.000000000 +0100
+++ new/dkimpy-1.1.5/dkim/tests/data/rfc6376.w1258.msg  2023-04-30 
16:18:48.000000000 +0200
@@ -0,0 +1,12 @@
+From: Tomá? SixPack <Tomá?@football.example.com>
+To: Suzie Q <su...@shopping.example.net>
+Subject: Is dinner ready?
+Date: Fri, 11 Jul 2003 21:00:37 -0700 (PDT)
+Message-ID: <20030712040037.46341.5...@football.example.com>
+
+Hi.
+
+We lost the game.  Are you hungry yet?
+
+Tomá?.
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkim/tests/data/test.message.baddomain 
new/dkimpy-1.1.5/dkim/tests/data/test.message.baddomain
--- old/dkimpy-1.0.5/dkim/tests/data/test.message.baddomain     1970-01-01 
01:00:00.000000000 +0100
+++ new/dkimpy-1.1.5/dkim/tests/data/test.message.baddomain     2023-04-30 
16:18:48.000000000 +0200
@@ -0,0 +1,16 @@
+DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple;
+ d=legitimate.com(.attacker.com; i=@legitimate.com(.attacker.com;
+ q=dns/txt; s=test; t=1587514615; h=message-id : date : from : to :
+ subject : from; bh=wE7NXSkgnx9PGiavN4OZhJztvkqPDlemV3OGuEnLwNo=;
+ b=LsTV4fcR29N8CuUyrGn92jsTb67oAHx88vVIefoaUDghWxF5TpCyqcWbk/94Nt4PyxwUZ
+ pgzF4UM/zF1rclCeNm/V4m0wMj3X2eeOIUUa8GRQ0g7DzixiQ5qHLUGpRT4BHfPmdHZHYj8
+ xv7+1O0/SJDK0YkaBjvhjDfkOoJhMmc=
+Authentication-Results: lists.example.org; arc=none; spf=pass 
smtp.mfrom=jqd@d1.example; dkim=pass (1024-bit key) header.i=@d1.example; 
dmarc=pass
+Received: from localhost
+Message-ID: <exam...@example.com>
+Date: Mon, 01 Jan 2011 01:02:03 +0400
+From: Test User <t...@example.com>
+To: someb...@example.com
+Subject: Testing
+
+This is a test message.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkim/tests/test_dkim.py 
new/dkimpy-1.1.5/dkim/tests/test_dkim.py
--- old/dkimpy-1.0.5/dkim/tests/test_dkim.py    2020-08-08 23:04:57.000000000 
+0200
+++ new/dkimpy-1.1.5/dkim/tests/test_dkim.py    2023-04-30 16:18:48.000000000 
+0200
@@ -60,6 +60,8 @@
         self.message3 = read_test_data("rfc6376.msg")
         self.message4 = read_test_data("rfc6376.signed.msg")
         self.message5 = read_test_data("rfc6376.signed.rsa.msg")
+        self.message6 = read_test_data("test.message.baddomain")
+        self.message7 = read_test_data("rfc6376.w1258.msg")
         self.key = read_test_data("test.private")
         self.rfckey = read_test_data("rfc8032_7_1.key")
 
@@ -196,6 +198,23 @@
         self.assertTrue(domain in _dns_responses,domain)
         return _dns_responses[domain]
 
+    def dnsfunc7(self, domain, timeout=5):
+        sample_dns = """\
+k=rsa; s=email;\
+p=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANmBe10IgY+u7h3enWTukkqtUD5PR52T\
+b/mPfjC0QJTocVBq6Za/PlzfV+Py92VaCak19F4WrbVTK5Gg5tW220MCAwEAAQ=="""
+
+        _dns_responses = {
+          'test._domainkey.legitimate.com(.attacker.com.': 
read_test_data("test.txt"),
+        }
+        try:
+            domain = domain.decode('ascii')
+        except UnicodeDecodeError:
+            return None
+        self.assertTrue(domain in _dns_responses,domain)
+        return _dns_responses[domain]
+
+
     def test_verifies(self):
         # A message verifies after being signed.
         for header_algo in (b"simple", b"relaxed"):
@@ -231,6 +250,17 @@
                 d = dkim.DKIM(self.message4)
                 res = d.verify(dnsfunc=self.dnsfunc5)
                 self.assertTrue(res)
+    def test_non_utf8(self):
+        # A message with Windows-1258 encoding is signed and verifies.
+        for header_algo in (b"simple", b"relaxed"):
+            for body_algo in (b"simple", b"relaxed"):
+                sig = dkim.sign(
+                    self.message7, b"test", b"football.example.com", self.key,
+                    canonicalize=(header_algo, body_algo), 
signature_algorithm=b'rsa-sha256')
+                d = dkim.DKIM(self.message7)
+                res = d.verify(dnsfunc=self.dnsfunc5)
+                # As of 1.1.0 this won't verify, but at least we don't crash.  
FIXME
+                self.assertFalse(res)
 
     def test_catch_bad_key(self):
         # Raise correct error for defective public key.
@@ -279,6 +309,18 @@
                 res = dkim.verify(sig + self.message, dnsfunc=self.dnsfunc4)
                 self.assertFalse(res)
 
+    def test_invalid_domain_sign(self):
+        # RFC6376 says domain can be Alpha, Num, - only.
+        sig = dkim.sign(
+            self.message, b"test", b"legitimate.com(.attacker.com", self.key)
+        res = dkim.verify(sig + self.message, dnsfunc=self.dnsfunc7)
+        self.assertFalse(res)
+
+    def test_invalid_domain_verify(self):
+        # RFC6376 says domain can be Alpha, Num, - only.
+        res = dkim.verify(self.message6, dnsfunc=self.dnsfunc7)
+        self.assertFalse(res)
+
     def test_simple_signature(self):
         # A message verifies after being signed with SHOULD headers
         for header_algo in (b"simple", b"relaxed"):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkim/tests/test_dkim_generate.py 
new/dkimpy-1.1.5/dkim/tests/test_dkim_generate.py
--- old/dkimpy-1.0.5/dkim/tests/test_dkim_generate.py   1970-01-01 
01:00:00.000000000 +0100
+++ new/dkimpy-1.1.5/dkim/tests/test_dkim_generate.py   2023-04-30 
16:18:48.000000000 +0200
@@ -0,0 +1,115 @@
+# This software is provided 'as-is', without any express or implied
+# warranty.  In no event will the author be held liable for any damages
+# arising from the use of this software.
+#
+# Permission is granted to anyone to use this software for any purpose,
+# including commercial applications, and to alter it and redistribute it
+# freely, subject to the following restrictions:
+#
+# 1. The origin of this software must not be misrepresented; you must not
+#    claim that you wrote the original software. If you use this software
+#    in a product, an acknowledgment in the product documentation would be
+#    appreciated but is not required.
+# 2. Altered source versions must be plainly marked as such, and must not be
+#    misrepresented as being the original software.
+# 3. This notice may not be removed or altered from any source distribution.
+#
+# Copyright (c) 2011 William Grant <m...@williamgrant.id.au>
+# Copyright (c) 2022 Adrien Precigout <d...@asdrip.fr>
+
+import os.path
+import tempfile
+import unittest
+
+import dkim
+import dkim.dknewkey as dknewkey
+
+def read_data(path):
+    """Get the content of the given test data file."""
+
+    with open(path, 'rb') as f:
+        return f.read()
+
+
+class TestSignAndVerify(unittest.TestCase):
+    """End-to-end signature and verification tests with a generated key."""
+
+    def setUp(self):
+        message_dir = os.path.join(os.path.dirname(__file__), 'data', 
"test.message")
+        self.message = read_data(message_dir)
+        self.ed25519_dns_key_file = ""
+        self.rsa_dns_key_file = ""
+    
+
+    def test_generate_verifies_new_RSA_key(self):
+        #Create temporary dir
+        tmpdir = tempfile.TemporaryDirectory()
+        keydir = tmpdir.name
+        rsa_key_file = os.path.join(keydir, "dkim.rsa.key")
+        self.rsa_dns_key_file = os.path.join(keydir, "dkim.rsa.key.pub.txt")
+        #Generate a rsa key
+        dknewkey.GenRSAKeys(rsa_key_file, False)
+        dknewkey.ExtractRSADnsPublicKey(rsa_key_file, self.rsa_dns_key_file, 
False)
+        #Load the key
+        rsakey = read_data(rsa_key_file)
+        #Test signature with the newely generated key  
+        for header_algo in (b"simple", b"relaxed"):
+            for body_algo in (b"simple", b"relaxed"):
+                sig = dkim.sign(
+                    self.message, b"test", b"example.com", rsakey,
+                    canonicalize=(header_algo, body_algo))
+                res = dkim.verify(sig + self.message, dnsfunc=self.dnsfuncRSA)
+                self.assertTrue(res)
+        tmpdir.cleanup()
+
+
+    def test_generate_verifies_Ed25519_key(self):
+        #Create temporary dir
+        tmpdir = tempfile.TemporaryDirectory()
+        keydir = tmpdir.name
+        ed25519_key_file = os.path.join(keydir, "dkim.ed25519.key")
+        self.ed25519_dns_key_file = os.path.join(keydir, 
"dkim.ed25519.key.pub.txt")
+        #Generate a ed25519 key
+        pkt = dknewkey.GenEd25519Keys(ed25519_key_file, False)
+        dknewkey.ExtractEd25519PublicKey(self.ed25519_dns_key_file, pkt, False)
+        #Load the key
+        ed25519key = read_data(ed25519_key_file)
+        #Test signature with the newely generated key 
+        for header_algo in (b"simple", b"relaxed"):
+            for body_algo in (b"simple", b"relaxed"):
+                sig = dkim.sign(
+                    self.message, b"test1", b"example.com", ed25519key,
+                    signature_algorithm=b'ed25519-sha256',
+                    canonicalize=(header_algo, body_algo))
+                res = dkim.verify(sig + self.message, 
dnsfunc=self.dnsfuncED25519)
+                self.assertTrue(res)
+        tmpdir.cleanup()
+
+
+    def dnsfuncRSA(self, domain, timeout=5):
+        _dns_responses = {
+            'test._domainkey.example.com.': read_data(self.rsa_dns_key_file),
+        }
+        try:
+            domain = domain.decode('ascii')
+        except UnicodeDecodeError:
+            return None
+        self.assertTrue(domain in _dns_responses,domain)
+        return _dns_responses[domain]
+
+    def dnsfuncED25519(self, domain, timeout=5):
+        _dns_responses = {
+            'test1._domainkey.example.com.': 
read_data(self.ed25519_dns_key_file),
+        }
+        try:
+            domain = domain.decode('ascii')
+        except UnicodeDecodeError:
+            return None
+        self.assertTrue(domain in _dns_responses,domain)
+        return _dns_responses[domain]
+
+   
+
+def test_suite():
+    from unittest import TestLoader
+    return TestLoader().loadTestsFromName(__name__)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkim/tests/test_dkim_rsavariants.py 
new/dkimpy-1.1.5/dkim/tests/test_dkim_rsavariants.py
--- old/dkimpy-1.0.5/dkim/tests/test_dkim_rsavariants.py        2020-04-06 
06:27:45.000000000 +0200
+++ new/dkimpy-1.1.5/dkim/tests/test_dkim_rsavariants.py        2023-04-30 
16:18:48.000000000 +0200
@@ -41,6 +41,7 @@
         self.message = read_test_data("test.message")
         self.key1024 = read_test_data("1024_testkey.key")
         self.key2048 = read_test_data("2048_testkey.key")
+        self.key2048PKCS8 = read_test_data("2048_testkey_PKCS8.key")
 
     def dnsfunc(self, domain, timeout=5):
         _dns_responses = {
@@ -48,6 +49,7 @@
           'test2._domainkey.example.com.': 
read_test_data("1024_testkey_wo_markers.pub.rsa.txt"),
           'test3._domainkey.example.com.': 
read_test_data("2048_testkey_wo_markers.pub.txt"),
           'test4._domainkey.example.com.': 
read_test_data("2048_testkey_wo_markers.pub.rsa.txt"),
+          'test5._domainkey.example.com.': 
read_test_data("2048_testkey_PKCS8.key.pub.txt")
         }
         try:
             domain = domain.decode('ascii')
@@ -56,7 +58,6 @@
         self.assertTrue(domain in _dns_responses,domain)
         return _dns_responses[domain]
 
-
     def test_verifies_SubjectPublicKeyInfo1024(self):
         # A message verifies after being signed.
         for header_algo in (b"simple", b"relaxed"):
@@ -67,8 +68,6 @@
                 res = dkim.verify(sig + self.message, dnsfunc=self.dnsfunc)
                 self.assertTrue(res)
 
-
-
     def test_verifies_RSAPublicKey1024(self):
         # A message verifies after being signed.
         for header_algo in (b"simple", b"relaxed"):
@@ -102,6 +101,16 @@
                 self.assertTrue(res)
 
 
+    def test_verifies_RSAPublicKey2048PKCS8(self):
+        #A message verifies after being signed (with PKCS8 private key)
+        for header_algo in (b"simple", b"relaxed"):
+            for body_algo in (b"simple", b"relaxed"):
+                sig = dkim.sign(
+                    self.message, b"test5", b"example.com", self.key2048PKCS8,
+                    canonicalize=(header_algo, body_algo))
+                res = dkim.verify(sig + self.message, dnsfunc=self.dnsfunc)
+                self.assertTrue(res)
+
 def test_suite():
     from unittest import TestLoader
     return TestLoader().loadTestsFromName(__name__)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkimpy.egg-info/PKG-INFO 
new/dkimpy-1.1.5/dkimpy.egg-info/PKG-INFO
--- old/dkimpy-1.0.5/dkimpy.egg-info/PKG-INFO   2020-08-09 04:35:02.000000000 
+0200
+++ new/dkimpy-1.1.5/dkimpy.egg-info/PKG-INFO   2023-07-28 18:02:28.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: dkimpy
-Version: 1.0.5
+Version: 1.1.5
 Summary: DKIM (DomainKeys Identified Mail), ARC (Authenticated Receive Chain), 
and TLSRPT (TLS Report) email signing and verification
 Home-page: https://launchpad.net/dkimpy
 Author: Scott Kitterman
@@ -21,7 +21,7 @@
         
         # VERSION
         
-        This is dkimpy 1.0.5.
+        This is dkimpy 1.1.5.
         
         # REQUIREMENTS
         
@@ -32,12 +32,10 @@
         Similarly, extras_requires feature 'asyncio' will add the extra 
dependencies
         needed for asyncio.
         
-         - Python 2.x >= 2.7, or Python 3.x >= 3.5.  Recent versions have not 
been
-           tested on python < 2.7 or python3 < 3.4, but may still work on 
python2.6
-           and python 3.1 - 3.3.
-         - dnspython or pydns. dnspython is preferred if both are present and
+         - Python 3.x >= 3.5.  Recent versions have not been on python3 < 3.4, 
but
+           may still work on earlier python3 versions.
+         - dnspython or py3dns. dnspython is preferred if both are present and
            installed to satisfy the DNS module requirement if neither are 
installed.
-         - argparse.  Standard library in python2.7 and later.
          - authres.  Needed for ARC.
          - PyNaCl.  Needed for use of ed25519 capability.
          - aiodns.  Needed for asycnio (Requires python3.5 or later)
@@ -91,8 +89,10 @@
          ships with test runners for dkimpy.  After downloading the test 
suite, you
          can run the signing and validation tests like this:
         
-        ```python2.7 ./testarc.py sign runners/arcsigntest.py```
-        ```python2.7 ./testarc.py validate runners/arcverifytest.py```
+        ```python3 ./testarc.py sign runners/arcsigntest.py```
+        ```python3 ./testarc.py validate runners/arcverifytest.py```
+        
+        As ov version 1.1.0, python2.7 is no longer supported.
         
         # USAGE
         
@@ -160,7 +160,10 @@
         
         dknewkey is s script that produces private and public key pairs 
suitable
         for use with DKIM.  Note that the private key file format used for 
ed25519 is
-        not standardized (there is no standard) and is unique to dkimpy.
+        not standardized (there is no standard) and is unique to dkimpy.  
Creation of
+        keys should be done in a secure environment.  If an unauthorized 
entity gains
+        access to current private keys they can generate signed email that 
will pass
+        DKIM checkes and will be difficult to repudiate.
         
         dkimsign is a filter that reads an RFC822 message on standard input, 
and
         writes the same message on standard output with a DKIM-Signature line
@@ -184,6 +187,9 @@
         In addition to arcsign and arcverify, the dkim module now provides
         arc_sign and arc_verify functions as well as an ARC class.
         
+        If an invalid authentication results header field is included in the 
set for
+        ARC, it is ignored and no error is raised.
+        
         Both DKIM ed25519 and ARC are now considered stable (no longer 
experimantal).
         
         ## ASYNC SUPPORT
@@ -205,6 +211,9 @@
         
         This feature requires python3.5 or newer.
         
+        If aiodns is available, the async functions will be used.  To avoide 
async
+        when aiodns is availale, set dkim.USE_ASYNC = False.
+        
         ## TLSRPT (TLS Report)
         
         As of version 1.0, the RFC 8460 tlsrpt service type is supported:
@@ -224,6 +233,13 @@
         valid.  If set to tlsrpt=True, the service type is not required, but 
other
         RFC 8460 requirements are applied.
         
+        # LIMITATIONS
+        
+        Dkimpy will correctly sign/verify messages with ASCII or UTF-8 content.
+        Messages that contain other types of content will not verify 
correctly.  It
+        does not yet implement RFC 8616, Email Authentication for 
Internationalized
+        Mail.
+        
         # FEEDBACK
         
         Bug reports may be submitted to the bug tracker for the dkimpy project 
on
@@ -236,7 +252,6 @@
 Classifier: License :: DFSG approved
 Classifier: Natural Language :: English
 Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 3
 Classifier: Topic :: Communications :: Email :: Mail Transport Agents
 Classifier: Topic :: Communications :: Email :: Filters
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkimpy.egg-info/SOURCES.txt 
new/dkimpy-1.1.5/dkimpy.egg-info/SOURCES.txt
--- old/dkimpy-1.0.5/dkimpy.egg-info/SOURCES.txt        2020-08-09 
04:35:02.000000000 +0200
+++ new/dkimpy-1.1.5/dkimpy.egg-info/SOURCES.txt        2023-07-28 
18:02:28.000000000 +0200
@@ -23,6 +23,7 @@
 dkim/tests/test_crypto.py
 dkim/tests/test_dkim.py
 dkim/tests/test_dkim_ed25519.py
+dkim/tests/test_dkim_generate.py
 dkim/tests/test_dkim_rsavariants.py
 dkim/tests/test_dkim_tlsrpt.py
 dkim/tests/test_dnsplug.py
@@ -31,6 +32,8 @@
 dkim/tests/data/1024_testkey_wo_markers.pub.rsa.txt
 dkim/tests/data/1024_testkey_wo_markers.pub.txt
 dkim/tests/data/2048_testkey.key
+dkim/tests/data/2048_testkey_PKCS8.key
+dkim/tests/data/2048_testkey_PKCS8.key.pub.txt
 dkim/tests/data/2048_testkey_wo_markers.pub.rsa.txt
 dkim/tests/data/2048_testkey_wo_markers.pub.txt
 dkim/tests/data/badk.txt
@@ -44,8 +47,10 @@
 dkim/tests/data/rfc6376.msg
 dkim/tests/data/rfc6376.signed.msg
 dkim/tests/data/rfc6376.signed.rsa.msg
+dkim/tests/data/rfc6376.w1258.msg
 dkim/tests/data/rfc8032_7_1.key
 dkim/tests/data/test.message
+dkim/tests/data/test.message.baddomain
 dkim/tests/data/test.private
 dkim/tests/data/test.txt
 dkim/tests/data/test2.message
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/dkimpy.egg-info/requires.txt 
new/dkimpy-1.1.5/dkimpy.egg-info/requires.txt
--- old/dkimpy-1.0.5/dkimpy.egg-info/requires.txt       2020-08-09 
04:35:02.000000000 +0200
+++ new/dkimpy-1.1.5/dkimpy.egg-info/requires.txt       2023-07-28 
18:02:28.000000000 +0200
@@ -1,4 +1,4 @@
-dnspython>=1.16.0
+Py3DNS
 
 [ARC]
 authres
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/man/dkimverify.1 
new/dkimpy-1.1.5/man/dkimverify.1
--- old/dkimpy-1.0.5/man/dkimverify.1   2020-08-08 23:04:57.000000000 +0200
+++ new/dkimpy-1.1.5/man/dkimverify.1   2023-04-30 16:18:48.000000000 +0200
@@ -133,7 +133,7 @@
 \-
 Script for DKIM verifying messages on stdin
 .SH "VERSION"
-0\.6\.0
+1\.1\.0
 
 .SH "DESCRIPTION"
 
@@ -141,6 +141,13 @@
 code 0 if the signature verifies successfully. Otherwise, it returns with exit
 code 1.
 
+.SH "USAGE"
+usage: dkimverify.py [\-h] [\-\-index N] <message
+
+optional arguments:
+  \-h, \-\-help  show this help message and exit
+  \-\-index N   Index of DKIM signature header to verify: default=0
+
 .SH "AUTHORS"
 This version of \fBdkimverify\fR was written by Greg Hewgill 
<g...@hewgill.com>.
 .PP
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dkimpy-1.0.5/setup.py new/dkimpy-1.1.5/setup.py
--- old/dkimpy-1.0.5/setup.py   2020-08-08 23:04:57.000000000 +0200
+++ new/dkimpy-1.1.5/setup.py   2023-07-28 17:59:47.000000000 +0200
@@ -25,17 +25,14 @@
 import os
 import sys
 
-version = "1.0.5"
+version = "1.1.5"
 
 kw = {}  # Work-around for lack of 'or' requires in setuptools.
 try:
     import DNS
-    if sys.version_info[0] == 2:
-        kw['install_requires'] = ['PyDNS']
-    else:
-        kw['install_requires'] = ['Py3DNS']
+    kw['install_requires'] = ['Py3DNS']
 except ImportError:  # If PyDNS is not installed, prefer dnspython
-    kw['install_requires'] = ['dnspython>=1.16.0']
+    kw['install_requires'] = ['dnspython>=2.0.0']
 
 with open("README.md", "r") as fh:
     long_description = fh.read()
@@ -73,7 +70,6 @@
       'License :: DFSG approved',
       'Natural Language :: English',
       'Operating System :: OS Independent',
-      'Programming Language :: Python',
       'Programming Language :: Python :: 3',
       'Topic :: Communications :: Email :: Mail Transport Agents',
       'Topic :: Communications :: Email :: Filters',

++++++ no-optional.patch ++++++
--- /var/tmp/diff_new_pack.bq8BcV/_old  2024-01-06 19:38:07.850367381 +0100
+++ /var/tmp/diff_new_pack.bq8BcV/_new  2024-01-06 19:38:07.882368551 +0100
@@ -1,14 +1,14 @@
-Index: dkimpy-1.0.3/dkim/__init__.py
+Index: dkimpy-1.1.5/dkim/__init__.py
 ===================================================================
---- dkimpy-1.0.3.orig/dkim/__init__.py
-+++ dkimpy-1.0.3/dkim/__init__.py
-@@ -40,18 +40,9 @@ import sys
- import time
- import binascii
+--- dkimpy-1.1.5.orig/dkim/__init__.py
++++ dkimpy-1.1.5/dkim/__init__.py
+@@ -43,18 +43,9 @@ import binascii
+ # Set to False to not use async functions even though aiodns is installed.
+ USE_ASYNC = True
  
 -# only needed for arc
 -try:
--    from authres import AuthenticationResultsHeader
+-    import authres
 -except ImportError:
 -    pass
 -
@@ -18,10 +18,19 @@
 -    import nacl.encoding
 -except ImportError:
 -    pass
-+from authres import AuthenticationResultsHeader
++import authres
 +import nacl.signing
 +import nacl.encoding
  
  from dkim.canonicalization import (
      CanonicalizationPolicy,
+@@ -1181,7 +1172,7 @@ class ARC(DomainSigner):
+     if chain_validation_status == CV_Fail:
+       self.headers.reverse()
+     if b'h' in as_fields:
+-        raise ValidationError("h= tag not permitted in ARC-Seal header 
field")    
++        raise ValidationError("h= tag not permitted in ARC-Seal header field")
+     res = self.gen_header(as_fields, as_include_headers, canon_policy,
+                            b"ARC-Seal", pk, standardize)
+ 
 

Reply via email to