Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-jwcrypto for openSUSE:Factory 
checked in at 2021-08-11 11:47:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-jwcrypto (Old)
 and      /work/SRC/openSUSE:Factory/.python-jwcrypto.new.1899 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-jwcrypto"

Wed Aug 11 11:47:01 2021 rev:11 rq:910436 version:1.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-jwcrypto/python-jwcrypto.changes  
2021-07-10 22:53:31.640210115 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-jwcrypto.new.1899/python-jwcrypto.changes    
    2021-08-11 11:47:09.861750310 +0200
@@ -1,0 +2,13 @@
+Thu Aug  5 19:05:35 UTC 2021 - Michael Str??der <mich...@stroeder.com>
+
+- update to 1.0
+  * Create SECURITY.md
+  * Allow empty payloads in JWS tokens
+  * Add tests to check empty payload support
+  * Drop python2 compatibility
+  * Fix python3 pylint issues
+  * Add explicit support to check 'typ' in JWT
+  * Drop support for importing old MutableMapping
+  * Disable annoying pep8 naming checks
+
+-------------------------------------------------------------------

Old:
----
  jwcrypto-0.9.1.tar.gz

New:
----
  jwcrypto-1.0.tar.gz

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

Other differences:
------------------
++++++ python-jwcrypto.spec ++++++
--- /var/tmp/diff_new_pack.efevCa/_old  2021-08-11 11:47:11.973747770 +0200
+++ /var/tmp/diff_new_pack.efevCa/_new  2021-08-11 11:47:11.973747770 +0200
@@ -18,8 +18,10 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 
+%define skip_python2 1
+
 Name:           python-jwcrypto
-Version:        0.9.1
+Version:        1.0
 Release:        0
 Summary:        Python module package implementing JOSE Web standards
 License:        LGPL-3.0-only
@@ -62,6 +64,6 @@
 %files %{python_files}
 %{python_sitelib}/*
 %license LICENSE
-%doc README.md
+%doc README.md SECURITY.md
 
 %changelog

++++++ jwcrypto-0.9.1.tar.gz -> jwcrypto-1.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/.github/workflows/build.yml 
new/jwcrypto-1.0/.github/workflows/build.yml
--- old/jwcrypto-0.9.1/.github/workflows/build.yml      2021-06-09 
20:43:19.000000000 +0200
+++ new/jwcrypto-1.0/.github/workflows/build.yml        2021-08-02 
10:49:08.000000000 +0200
@@ -14,7 +14,6 @@
                 "fail-fast": false,
                 "matrix": {
                     "name": [
-                        "python-27",
                         "python-36",
                         "python-37",
                         "python-38",
@@ -22,16 +21,10 @@
                         "doc",
                         "sphinx",
                         "lint",
-                        "pep8py3",
+                        "pep8",
                     ],
                     "include": [
                         {
-                            "name": "python-27",
-                            "python": "2.7",
-                            "toxenv": "py27",
-                            "arch": "x64",
-                        },
-                        {
                             "name": "python-36",
                             "python": "3.6",
                             "toxenv": "py36",
@@ -74,9 +67,9 @@
                             "arch": "x64",
                         },
                         {
-                            "name": "pep8py3",
+                            "name": "pep8",
                             "python": "3.9",
-                            "toxenv": "pep8py3",
+                            "toxenv": "pep8",
                             "arch": "x64",
                         },
                     ],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/.github/workflows/codeql-analysis.yml 
new/jwcrypto-1.0/.github/workflows/codeql-analysis.yml
--- old/jwcrypto-0.9.1/.github/workflows/codeql-analysis.yml    2021-06-09 
20:43:19.000000000 +0200
+++ new/jwcrypto-1.0/.github/workflows/codeql-analysis.yml      2021-08-02 
10:49:08.000000000 +0200
@@ -17,6 +17,9 @@
   pull_request:
     # The branches below must be a subset of the branches above
     branches: [ master ]
+    paths-ignore:
+      - '**/*.md'
+      - '**/*.txt'
   schedule:
     - cron: '31 10 * * 5'
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/Makefile new/jwcrypto-1.0/Makefile
--- old/jwcrypto-0.9.1/Makefile 2021-06-01 16:52:31.000000000 +0200
+++ new/jwcrypto-1.0/Makefile   2021-08-02 10:49:08.000000000 +0200
@@ -7,8 +7,7 @@
 
 pep8:
        # Check style consistency
-       tox -e pep8py2
-       tox -e pep8py3
+       tox -e pep8
 
 clean:
        rm -fr build dist *.egg-info
@@ -25,7 +24,6 @@
 
 test:
        rm -f .coverage
-       tox -e py27
        tox -e py36 --skip-missing-interpreter
        tox -e py37 --skip-missing-interpreter
        tox -e py38 --skip-missing-interpreter
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/PKG-INFO new/jwcrypto-1.0/PKG-INFO
--- old/jwcrypto-0.9.1/PKG-INFO 2021-06-09 20:43:44.513565800 +0200
+++ new/jwcrypto-1.0/PKG-INFO   2021-08-02 10:49:25.848379100 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: jwcrypto
-Version: 0.9.1
+Version: 1.0
 Summary: Implementation of JOSE Web standards
 Home-page: https://github.com/latchset/jwcrypto
 Maintainer: JWCrypto Project Contributors
@@ -8,7 +8,6 @@
 License: LGPLv3+
 Description: UNKNOWN
 Platform: UNKNOWN
-Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/README.md new/jwcrypto-1.0/README.md
--- old/jwcrypto-0.9.1/README.md        2021-06-09 20:43:19.000000000 +0200
+++ new/jwcrypto-1.0/README.md  2021-08-02 10:49:08.000000000 +0200
@@ -2,6 +2,7 @@
 
[![Changelog](https://img.shields.io/github/v/release/latchset/jwcrypto?label=changelog)](https://github.com/latchset/jwcrypto/releases)
 [![Build 
Status](https://github.com/latchset/jwcrypto/actions/workflows/build.yml/badge.svg)](https://github.com/latchset/jwcrypto/actions/workflows/build.yml)
 [![ppc64le 
Build](https://github.com/latchset/jwcrypto/actions/workflows/ppc64le.yml/badge.svg)](https://github.com/latchset/jwcrypto/actions/workflows/ppc64le.yml)
+[![Code 
Scan](https://github.com/latchset/jwcrypto/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/latchset/jwcrypto/actions/workflows/codeql-analysis.yml)
 
 JWCrypto
 ========
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/SECURITY.md 
new/jwcrypto-1.0/SECURITY.md
--- old/jwcrypto-0.9.1/SECURITY.md      1970-01-01 01:00:00.000000000 +0100
+++ new/jwcrypto-1.0/SECURITY.md        2021-08-02 10:49:08.000000000 +0200
@@ -0,0 +1,16 @@
+# Security Policy
+
+## Supported Versions
+
+| Version | Supported          |
+| ------- | ------------------ |
+| 0.8 +   | :white_check_mark: |
+| < 0.8   | :x:                |
+
+## Reporting a Vulnerability
+
+Please contact s...@redhat.com if you have found a security vulnerability
+
+Expect a response within 2 business days (not on week ends or holidays).
+
+If the vulnerbaility is confirmed and accepted you will be given instruction 
on any embargo or disclosure timeline via email.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/docs/source/conf.py 
new/jwcrypto-1.0/docs/source/conf.py
--- old/jwcrypto-0.9.1/docs/source/conf.py      2021-06-09 20:43:19.000000000 
+0200
+++ new/jwcrypto-1.0/docs/source/conf.py        2021-08-02 10:49:08.000000000 
+0200
@@ -53,9 +53,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = '0.9'
+version = '1.0'
 # The full version, including alpha/beta/rc tags.
-release = '0.9.1'
+release = '1.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/docs/source/index.rst 
new/jwcrypto-1.0/docs/source/index.rst
--- old/jwcrypto-0.9.1/docs/source/index.rst    2015-07-10 18:38:15.000000000 
+0200
+++ new/jwcrypto-1.0/docs/source/index.rst      2021-08-02 10:49:08.000000000 
+0200
@@ -10,8 +10,7 @@
 Encryption (JOSE) Web Standards as they are being developed in the
 JOSE_ IETF Working Group and related technology.
 
-JWCrypto is Python2 and Python3 compatible and uses the Cryptography_
-package for all the crypto functions.
+JWCrypto uses the Cryptography_ package for all the crypto functions.
 
 .. _JOSE: https://datatracker.ietf.org/wg/jose/charter/
 .. _Cryptography: https://cryptography.io/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/jwcrypto/common.py 
new/jwcrypto-1.0/jwcrypto/common.py
--- old/jwcrypto-0.9.1/jwcrypto/common.py       2021-02-08 21:02:01.000000000 
+0100
+++ new/jwcrypto-1.0/jwcrypto/common.py 2021-08-02 10:49:08.000000000 +0200
@@ -4,10 +4,7 @@
 import json
 from base64 import urlsafe_b64decode, urlsafe_b64encode
 from collections import namedtuple
-try:
-    from collections.abc import MutableMapping
-except ImportError:
-    from collections import MutableMapping
+from collections.abc import MutableMapping
 
 # Padding stripping versions as described in
 # RFC 7515 Appendix C
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/jwcrypto/jwa.py 
new/jwcrypto-1.0/jwcrypto/jwa.py
--- old/jwcrypto-0.9.1/jwcrypto/jwa.py  2021-02-08 21:02:01.000000000 +0100
+++ new/jwcrypto-1.0/jwcrypto/jwa.py    2021-08-02 10:49:08.000000000 +0200
@@ -1,8 +1,8 @@
 # Copyright (C) 2016 JWCrypto Project Contributors - see LICENSE file
 
-import abc
 import os
 import struct
+from abc import ABCMeta, abstractmethod
 from binascii import hexlify, unhexlify
 
 from cryptography.exceptions import InvalidSignature
@@ -17,8 +17,6 @@
 from cryptography.hazmat.primitives.keywrap import aes_key_unwrap, aes_key_wrap
 from cryptography.hazmat.primitives.padding import PKCS7
 
-import six
-
 from jwcrypto.common import InvalidCEKeyLength
 from jwcrypto.common import InvalidJWAAlgorithm
 from jwcrypto.common import InvalidJWEKeyLength
@@ -31,33 +29,32 @@
 # Implements RFC 7518 - JSON Web Algorithms (JWA)
 
 
-@six.add_metaclass(abc.ABCMeta)
-class JWAAlgorithm(object):
+class JWAAlgorithm(metaclass=ABCMeta):
 
-    @abc.abstractproperty
+    @property
+    @abstractmethod
     def name(self):
         """The algorithm Name"""
-        pass
 
-    @abc.abstractproperty
+    @property
+    @abstractmethod
     def description(self):
         """A short description"""
-        pass
 
-    @abc.abstractproperty
+    @property
+    @abstractmethod
     def keysize(self):
         """The actual/recommended/minimum key size"""
-        pass
 
-    @abc.abstractproperty
+    @property
+    @abstractmethod
     def algorithm_usage_location(self):
         """One of 'alg', 'enc' or 'JWK'"""
-        pass
 
-    @abc.abstractproperty
+    @property
+    @abstractmethod
     def algorithm_use(self):
         """One of 'sig', 'kex', 'enc'"""
-        pass
 
 
 def _bitsize(x):
@@ -1104,21 +1101,21 @@
         try:
             return cls.instantiate_alg(name, use='sig')
         except KeyError:
-            raise InvalidJWAAlgorithm(
-                '%s is not a valid Signign algorithm name' % name)
+            raise InvalidJWAAlgorithm('%s is not a valid Signign algorithm'
+                                      ' name' % name) from None
 
     @classmethod
     def keymgmt_alg(cls, name):
         try:
             return cls.instantiate_alg(name, use='kex')
         except KeyError:
-            raise InvalidJWAAlgorithm(
-                '%s is not a valid Key Management algorithm name' % name)
+            raise InvalidJWAAlgorithm('%s is not a valid Key Management'
+                                      ' algorithm name' % name) from None
 
     @classmethod
     def encryption_alg(cls, name):
         try:
             return cls.instantiate_alg(name, use='enc')
         except KeyError:
-            raise InvalidJWAAlgorithm(
-                '%s is not a valid Encryption algorithm name' % name)
+            raise InvalidJWAAlgorithm('%s is not a valid Encryption'
+                                      ' algorithm name' % name) from None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/jwcrypto/jwe.py 
new/jwcrypto-1.0/jwcrypto/jwe.py
--- old/jwcrypto-0.9.1/jwcrypto/jwe.py  2021-02-08 21:02:01.000000000 +0100
+++ new/jwcrypto-1.0/jwcrypto/jwe.py    2021-08-02 10:49:08.000000000 +0200
@@ -477,10 +477,10 @@
                     if 'header' in djwe:
                         o['header'] = json_encode(djwe['header'])
 
-            except ValueError:
+            except ValueError as e:
                 c = raw_jwe.split('.')
                 if len(c) != 5:
-                    raise InvalidJWEData()
+                    raise InvalidJWEData() from e
                 p = base64url_decode(c[0])
                 o['protected'] = p.decode('utf-8')
                 ekey = base64url_decode(c[1])
@@ -493,7 +493,7 @@
             self.objects = o
 
         except Exception as e:  # pylint: disable=broad-except
-            raise InvalidJWEData('Invalid format', repr(e))
+            raise InvalidJWEData('Invalid format', repr(e)) from e
 
         if key:
             self.decrypt(key)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/jwcrypto/jwk.py 
new/jwcrypto-1.0/jwcrypto/jwk.py
--- old/jwcrypto-0.9.1/jwcrypto/jwk.py  2021-06-09 20:43:19.000000000 +0200
+++ new/jwcrypto-1.0/jwcrypto/jwk.py    2021-08-02 10:49:08.000000000 +0200
@@ -13,8 +13,6 @@
 
 from deprecated import deprecated
 
-from six import iteritems
-
 from jwcrypto.common import JWException
 from jwcrypto.common import base64url_decode, base64url_encode
 from jwcrypto.common import json_decode, json_encode
@@ -263,8 +261,6 @@
     on the key type or other constraints.
     """
 
-    pass
-
 
 class JWK(dict):
     """JSON Web Key object
@@ -318,8 +314,8 @@
         try:
             kty = kwargs['kty']
             gen = getattr(obj, '_generate_%s' % kty)
-        except (KeyError, AttributeError):
-            raise InvalidJWKType(kty)
+        except (KeyError, AttributeError) as e:
+            raise InvalidJWKType(kty) from e
         gen(kwargs)
         return obj
 
@@ -328,8 +324,8 @@
         try:
             kty = params.pop('generate')
             gen = getattr(self, '_generate_%s' % kty)
-        except (KeyError, AttributeError):
-            raise InvalidJWKType(kty)
+        except (KeyError, AttributeError) as e:
+            raise InvalidJWKType(kty) from e
 
         gen(params)
 
@@ -341,8 +337,8 @@
             try:
                 from jwcrypto.jwa import JWA
                 alg = JWA.instantiate_alg(params['alg'])
-            except KeyError:
-                raise ValueError("Invalid 'alg' parameter")
+            except KeyError as e:
+                raise ValueError("Invalid 'alg' parameter") from e
             size = alg.keysize
         return size
 
@@ -451,13 +447,13 @@
             raise InvalidJWKValue('Must specify "crv" for OKP key generation')
         try:
             key = _OKP_CURVES_TABLE[params['crv']].privkey.generate()
-        except KeyError:
+        except KeyError as e:
             raise InvalidJWKValue('"%s" is not a supported curve for the '
-                                  'OKP key type' % params['crv'])
+                                  'OKP key type' % params['crv']) from e
         self._import_pyca_pri_okp(key, **params)
 
     def _okp_curve_from_pyca_key(self, key):
-        for name, val in iteritems(_OKP_CURVES_TABLE):
+        for name, val in _OKP_CURVES_TABLE.items():
             if isinstance(key, (val.pubkey, val.privkey)):
                 return name
         raise InvalidJWKValue('Invalid OKP Key object %r' % key)
@@ -509,7 +505,7 @@
                 while name in names:
                     names.remove(name)
 
-        for name, val in iteritems(JWKValuesRegistry[kty]):
+        for name, val in JWKValuesRegistry[kty].items():
             if val.required and name not in newkey:
                 raise InvalidJWKValue('Missing required value %s' % name)
             if val.type == ParmType.unsupported and name in newkey:
@@ -518,18 +514,18 @@
                 # Check that the value is base64url encoded
                 try:
                     base64url_decode(newkey[name])
-                except Exception:  # pylint: disable=broad-except
+                except Exception as e:  # pylint: disable=broad-except
                     raise InvalidJWKValue(
                         '"%s" is not base64url encoded' % name
-                    )
+                    ) from e
             if val.type == ParmType.b64u and name in newkey:
                 # Check that the value is Base64urlUInt encoded
                 try:
                     self._decode_int(newkey[name])
-                except Exception:  # pylint: disable=broad-except
+                except Exception as e:  # pylint: disable=broad-except
                     raise InvalidJWKValue(
                         '"%s" is not Base64urlUInt encoded' % name
-                    )
+                    ) from e
 
         # Unknown key parameters are allowed
         for name in names:
@@ -581,7 +577,7 @@
         try:
             jkey = json_decode(key)
         except Exception as e:  # pylint: disable=broad-except
-            raise InvalidJWKValue(e)
+            raise InvalidJWKValue from e
         obj.import_key(**jkey)
         return obj
 
@@ -761,8 +757,8 @@
         crv = self.get('crv')
         try:
             pubkey = _OKP_CURVES_TABLE[crv].pubkey
-        except KeyError:
-            raise InvalidJWKValue('Unknown curve "%s"' % crv)
+        except KeyError as e:
+            raise InvalidJWKValue('Unknown curve "%s"' % crv) from e
 
         x = base64url_decode(self.get('x'))
         return pubkey.from_public_bytes(x)
@@ -771,8 +767,8 @@
         crv = self.get('crv')
         try:
             privkey = _OKP_CURVES_TABLE[crv].privkey
-        except KeyError:
-            raise InvalidJWKValue('Unknown curve "%s"' % crv)
+        except KeyError as e:
+            raise InvalidJWKValue('Unknown curve "%s"' % crv) from e
 
         d = base64url_decode(self.get('d'))
         return privkey.from_private_bytes(d)
@@ -883,6 +879,7 @@
                         data, backend=default_backend())
                     key = cert.public_key()
                 except ValueError:
+                    # pylint: disable=raise-missing-from
                     raise e
 
         self.import_from_pyca(key)
@@ -950,7 +947,7 @@
         """
 
         t = {'kty': self.get('kty')}
-        for name, val in iteritems(JWKValuesRegistry[t['kty']]):
+        for name, val in JWKValuesRegistry[t['kty']].items():
             if val.required:
                 t[name] = self.get(name)
         digest = hashes.Hash(hashalg, backend=default_backend())
@@ -980,17 +977,17 @@
                     # is used to indicate a 'None' key
                     if v == b'' and kty != 'oct' and item != 'k':
                         raise ValueError
-                except Exception:  # pylint: disable=broad-except
+                except Exception as e:  # pylint: disable=broad-except
                     raise InvalidJWKValue(
                         '"%s" is not base64url encoded' % item
-                    )
+                    ) from e
             elif JWKValuesRegistry[kty][item].type == ParmType.b64u:
                 try:
                     self._decode_int(value)
-                except Exception:  # pylint: disable=broad-except
+                except Exception as e:  # pylint: disable=broad-except
                     raise InvalidJWKValue(
                         '"%s" is not Base64urlUInt encoded' % item
-                    )
+                    ) from e
             super(JWK, self).__setitem__(item, value)
             return
 
@@ -1013,7 +1010,7 @@
         super(JWK, self).__setitem__(item, value)
 
     def update(self, *args, **kwargs):
-        for k, v in iteritems(dict(*args, **kwargs)):
+        for k, v in dict(*args, **kwargs).items():
             self.__setitem__(k, v)
 
     def setdefault(self, key, default=None):
@@ -1055,7 +1052,7 @@
                         return self.get(item)
             raise KeyError
         except KeyError:
-            raise AttributeError
+            raise AttributeError(item) from None
 
     def __setattr__(self, item, value):
         try:
@@ -1066,7 +1063,7 @@
                     self.__setitem__(item, value)
             super(JWK, self).__setattr__(item, value)
         except KeyError:
-            raise AttributeError
+            raise AttributeError(item) from None
 
     @classmethod
     def from_password(cls, password):
@@ -1079,7 +1076,7 @@
         try:
             params['k'] = base64url_encode(password.encode('utf8'))
         except Exception as e:  # pylint: disable=broad-except
-            raise InvalidJWKValue(e)
+            raise InvalidJWKValue from e
         obj.import_key(**params)
         return obj
 
@@ -1130,7 +1127,7 @@
             super(JWKSet, self).__setitem__(key, val)
 
     def update(self, *args, **kwargs):
-        for k, v in iteritems(dict(*args, **kwargs)):
+        for k, v in dict(*args, **kwargs).items():
             self.__setitem__(k, v)
 
     def setdefault(self, key, default=None):
@@ -1151,7 +1148,7 @@
                               a JSON object
         """
         exp_dict = dict()
-        for k, v in iteritems(self):
+        for k, v in self.items():
             if k == 'keys':
                 keys = list()
                 for jwk in v:
@@ -1169,13 +1166,13 @@
         """
         try:
             jwkset = json_decode(keyset)
-        except Exception:  # pylint: disable=broad-except
-            raise InvalidJWKValue()
+        except Exception as e:  # pylint: disable=broad-except
+            raise InvalidJWKValue from e
 
         if 'keys' not in jwkset:
-            raise InvalidJWKValue()
+            raise InvalidJWKValue
 
-        for k, v in iteritems(jwkset):
+        for k, v in jwkset.items():
             if k == 'keys':
                 for jwk in v:
                     self['keys'].add(JWK(**jwk))
@@ -1203,7 +1200,7 @@
 
     def __repr__(self):
         repr_dict = dict()
-        for k, v in iteritems(self):
+        for k, v in self.items():
             if k == 'keys':
                 keys = list()
                 for jwk in v:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/jwcrypto/jws.py 
new/jwcrypto-1.0/jwcrypto/jws.py
--- old/jwcrypto-0.9.1/jwcrypto/jws.py  2021-02-08 21:02:01.000000000 +0100
+++ new/jwcrypto-1.0/jwcrypto/jws.py    2021-08-02 10:49:08.000000000 +0200
@@ -163,7 +163,7 @@
             sigin = b'.'.join([self.protected.encode('utf-8'), payload])
             self.engine.verify(self.key, sigin, signature)
         except Exception as e:  # pylint: disable=broad-except
-            raise InvalidJWSSignature('Verification failed', repr(e))
+            raise InvalidJWSSignature('Verification failed') from e
         return True
 
 
@@ -180,8 +180,7 @@
         :param header_registry: Optional additions to the header registry
         """
         self.objects = dict()
-        if payload:
-            self.objects['payload'] = payload
+        self.objects['payload'] = payload
         self.verifylog = None
         self._allowed_algs = None
         self.header_registry = JWSEHeaderRegistry(JWSHeaderRegistry)
@@ -400,7 +399,8 @@
             except ValueError:
                 c = raw_jws.split('.')
                 if len(c) != 3:
-                    raise InvalidJWSObject('Unrecognized representation')
+                    raise InvalidJWSObject('Unrecognized'
+                                           ' representation') from None
                 p = base64url_decode(str(c[0]))
                 if len(p) > 0:
                     o['protected'] = p.decode('utf-8')
@@ -411,7 +411,7 @@
             self.objects = o
 
         except Exception as e:  # pylint: disable=broad-except
-            raise InvalidJWSObject('Invalid format', repr(e))
+            raise InvalidJWSObject('Invalid format') from e
 
         if key:
             self.verify(key, alg)
@@ -427,8 +427,7 @@
         :param protected: The Protected Header (optional)
         :param header: The Unprotected Header (optional)
 
-        :raises InvalidJWSObject: if no payload has been set on the object,
-                                  or invalid headers are provided.
+        :raises InvalidJWSObject: if invalid headers are provided.
         :raises ValueError: if the key is not a :class:`JWK` object.
         :raises ValueError: if the algorithm is missing or is not provided
          by one of the headers.
@@ -436,9 +435,6 @@
          unknown or otherwise not yet implemented.
         """
 
-        if not self.objects.get('payload', None):
-            raise InvalidJWSObject('Missing Payload')
-
         b64 = True
 
         p = dict()
@@ -481,7 +477,8 @@
             raise ValueError('"alg" not specified')
 
         c = JWSCore(
-            alg, key, protected, self.objects['payload'], self.allowed_algs
+            alg, key, protected, self.objects.get('payload'),
+            self.allowed_algs
         )
         sig = c.sign()
 
@@ -539,7 +536,7 @@
             else:
                 raise InvalidJWSOperation("Can't use compact encoding "
                                           "without protected header")
-            if self.objects.get('payload', False):
+            if self.objects.get('payload'):
                 if self.objects.get('b64', True):
                     payload = base64url_encode(self.objects['payload'])
                 else:
@@ -558,11 +555,11 @@
         else:
             obj = self.objects
             sig = dict()
-            if self.objects.get('payload', False):
-                if self.objects.get('b64', True):
-                    sig['payload'] = base64url_encode(self.objects['payload'])
-                else:
-                    sig['payload'] = self.objects['payload']
+            payload = self.objects.get('payload', '')
+            if self.objects.get('b64', True):
+                sig['payload'] = base64url_encode(payload)
+            else:
+                sig['payload'] = payload
             if 'signature' in obj:
                 if not obj.get('valid', False):
                     raise InvalidJWSSignature("No valid signature found")
@@ -590,11 +587,9 @@
 
     @property
     def payload(self):
-        if 'payload' not in self.objects:
-            raise InvalidJWSOperation("Payload not available")
         if not self.is_valid:
             raise InvalidJWSOperation("Payload not verified")
-        return self.objects['payload']
+        return self.objects.get('payload')
 
     def detach_payload(self):
         self.objects.pop('payload', None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/jwcrypto/jwt.py 
new/jwcrypto-1.0/jwcrypto/jwt.py
--- old/jwcrypto-0.9.1/jwcrypto/jwt.py  2021-06-09 20:43:19.000000000 +0200
+++ new/jwcrypto-1.0/jwcrypto/jwt.py    2021-08-02 10:49:08.000000000 +0200
@@ -3,8 +3,6 @@
 import time
 import uuid
 
-from six import string_types
-
 from jwcrypto.common import JWException, json_decode, json_encode
 from jwcrypto.jwe import JWE
 from jwcrypto.jwk import JWK, JWKSet
@@ -306,17 +304,17 @@
     def _check_string_claim(self, name, claims):
         if name not in claims:
             return
-        if not isinstance(claims[name], string_types):
+        if not isinstance(claims[name], str):
             raise JWTInvalidClaimFormat("Claim %s is not a StringOrURI type")
 
     def _check_array_or_string_claim(self, name, claims):
         if name not in claims:
             return
         if isinstance(claims[name], list):
-            if any(not isinstance(claim, string_types) for claim in claims):
+            if any(not isinstance(claim, str) for claim in claims):
                 raise JWTInvalidClaimFormat(
                     "Claim %s contains non StringOrURI types" % (name, ))
-        elif not isinstance(claims[name], string_types):
+        elif not isinstance(claims[name], str):
             raise JWTInvalidClaimFormat(
                 "Claim %s is not a StringOrURI type" % (name, ))
 
@@ -325,9 +323,9 @@
             return
         try:
             int(claims[name])
-        except ValueError:
+        except ValueError as e:
             raise JWTInvalidClaimFormat(
-                "Claim %s is not an integer" % (name, ))
+                "Claim %s is not an integer" % (name, )) from e
 
     def _check_exp(self, claim, limit, leeway):
         if claim < limit - leeway:
@@ -347,6 +345,7 @@
         self._check_integer_claim('nbf', claims)
         self._check_integer_claim('iat', claims)
         self._check_string_claim('jti', claims)
+        self._check_string_claim('typ', claims)
 
         if self._check_claims is None:
             if 'exp' in claims:
@@ -363,10 +362,11 @@
             claims = json_decode(self.claims)
             if not isinstance(claims, dict):
                 raise ValueError()
-        except ValueError:
+        except ValueError as e:
             if self._check_claims is not None:
-                raise JWTInvalidClaimFormat(
-                    "Claims check requested but claims is not a json dict")
+                raise JWTInvalidClaimFormat("Claims check requested "
+                                            "but claims is not a json "
+                                            "dict") from e
             return
 
         self._check_default_claims(claims)
@@ -407,12 +407,28 @@
                 else:
                     self._check_nbf(claims[name], time.time(), self._leeway)
 
+            elif name == 'typ':
+                if value is not None:
+                    if self.norm_typ(value) != self.norm_typ(claims[name]):
+                        raise JWTInvalidClaimValue("Invalid '%s' value. '%s'"
+                                                   " does not normalize to "
+                                                   "'%s'" % (name,
+                                                             claims[name],
+                                                             value))
+
             else:
                 if value is not None and value != claims[name]:
                     raise JWTInvalidClaimValue(
                         "Invalid '%s' value. Expected '%s' got '%s'" % (
                             name, value, claims[name]))
 
+    def norm_typ(self, val):
+        lc = val.lower()
+        if '/' in lc:
+            return lc
+        else:
+            return 'application/' + lc
+
     def make_signed_token(self, key):
         """Signs the payload.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/jwcrypto/tests.py 
new/jwcrypto-1.0/jwcrypto/tests.py
--- old/jwcrypto-0.9.1/jwcrypto/tests.py        2021-06-09 20:43:19.000000000 
+0200
+++ new/jwcrypto-1.0/jwcrypto/tests.py  2021-08-02 10:49:08.000000000 +0200
@@ -934,6 +934,21 @@
         jws_verify.verify(key.public())
         self.assertEqual(jws_verify.payload, payload)
 
+    def test_jws_issue_224(self):
+        key = jwk.JWK().generate(kty='oct')
+
+        # Test Empty payload is supported for creating and verifying signatures
+        s = jws.JWS(payload='')
+        s.add_signature(key, None, json_encode({"alg": "HS256"}))
+        o1 = s.serialize(compact=True)
+        self.assertTrue('..' in o1)
+        o2 = json_decode(s.serialize())
+        self.assertEqual(o2['payload'], '')
+
+        t = jws.JWS()
+        t.deserialize(o1)
+        t.verify(key)
+
 
 E_A1_plaintext = \
     [84, 104, 101, 32, 116, 114, 117, 101, 32, 115, 105, 103, 110, 32,
@@ -1492,6 +1507,38 @@
                 check_claims={"iss": "test", "exp": None,
                               "string_claim": "test"})
 
+    def test_claims_typ(self):
+        key = jwk.JWK().generate(kty='oct')
+        claims = '{"typ":"application/test"}'
+        string_header = '{"alg":"HS256"}'
+        t = jwt.JWT(string_header, claims)
+        t.make_signed_token(key)
+        token = t.serialize()
+
+        # Same typ w/o application prefix
+        jwt.JWT(jwt=token, key=key, check_claims={"typ": "test"})
+        self.assertRaises(jwt.JWTInvalidClaimValue, jwt.JWT, jwt=token,
+                          key=key, check_claims={"typ": "wrong"})
+
+        # Same typ w/ application prefix
+        jwt.JWT(jwt=token, key=key, check_claims={"typ": "application/test"})
+        self.assertRaises(jwt.JWTInvalidClaimValue, jwt.JWT, jwt=token,
+                          key=key, check_claims={"typ": "application/wrong"})
+
+        # check that a '/' in the name makes it not be matched with
+        # 'application/' prefix
+        claims = '{"typ":"diffmime/test"}'
+        t = jwt.JWT(string_header, claims)
+        t.make_signed_token(key)
+        token = t.serialize()
+        self.assertRaises(jwt.JWTInvalidClaimValue, jwt.JWT, jwt=token,
+                          key=key, check_claims={"typ": "application/test"})
+        self.assertRaises(jwt.JWTInvalidClaimValue, jwt.JWT, jwt=token,
+                          key=key, check_claims={"typ": "test"})
+
+        # finally make sure it doesn't raise if not checked.
+        jwt.JWT(jwt=token, key=key)
+
     def test_empty_claims(self):
         key = jwk.JWK().generate(kty='oct')
 
@@ -1505,12 +1552,12 @@
         c.deserialize(token, key)
         self.assertEqual('{}', c.claims)
 
-        # empty string is not valid
+        # empty string is also valid
         t = jwt.JWT('{"alg":"HS256"}', '')
-        self.assertEqual('', t.claims)
-        self.assertRaises(jws.InvalidJWSObject, t.make_signed_token, key)
+        t.make_signed_token(key)
+        token = t.serialize()
 
-        # but a space is fine
+        # also a space is fine
         t = jwt.JWT('{"alg":"HS256"}', ' ')
         self.assertEqual(' ', t.claims)
         t.make_signed_token(key)
@@ -1640,8 +1687,8 @@
 
     def test_no_default_rsa_1_5(self):
         s = jws.JWS('test')
-        with self.assertRaisesRegexp(jws.InvalidJWSOperation,
-                                     'Algorithm not allowed'):
+        with self.assertRaisesRegex(jws.InvalidJWSOperation,
+                                    'Algorithm not allowed'):
             s.add_signature(A2_key, alg="RSA1_5")
 
     def test_pbes2_hs256_aeskw(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/jwcrypto.egg-info/PKG-INFO 
new/jwcrypto-1.0/jwcrypto.egg-info/PKG-INFO
--- old/jwcrypto-0.9.1/jwcrypto.egg-info/PKG-INFO       2021-06-09 
20:43:44.000000000 +0200
+++ new/jwcrypto-1.0/jwcrypto.egg-info/PKG-INFO 2021-08-02 10:49:25.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: jwcrypto
-Version: 0.9.1
+Version: 1.0
 Summary: Implementation of JOSE Web standards
 Home-page: https://github.com/latchset/jwcrypto
 Maintainer: JWCrypto Project Contributors
@@ -8,7 +8,6 @@
 License: LGPLv3+
 Description: UNKNOWN
 Platform: UNKNOWN
-Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/jwcrypto.egg-info/SOURCES.txt 
new/jwcrypto-1.0/jwcrypto.egg-info/SOURCES.txt
--- old/jwcrypto-0.9.1/jwcrypto.egg-info/SOURCES.txt    2021-06-09 
20:43:44.000000000 +0200
+++ new/jwcrypto-1.0/jwcrypto.egg-info/SOURCES.txt      2021-08-02 
10:49:25.000000000 +0200
@@ -4,6 +4,7 @@
 MANIFEST.in
 Makefile
 README.md
+SECURITY.md
 setup.cfg
 setup.py
 tox.ini
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/jwcrypto.egg-info/requires.txt 
new/jwcrypto-1.0/jwcrypto.egg-info/requires.txt
--- old/jwcrypto-0.9.1/jwcrypto.egg-info/requires.txt   2021-06-09 
20:43:44.000000000 +0200
+++ new/jwcrypto-1.0/jwcrypto.egg-info/requires.txt     2021-08-02 
10:49:25.000000000 +0200
@@ -1,3 +1,2 @@
 cryptography>=2.3
 deprecated
-six
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/setup.py new/jwcrypto-1.0/setup.py
--- old/jwcrypto-0.9.1/setup.py 2021-06-09 20:43:19.000000000 +0200
+++ new/jwcrypto-1.0/setup.py   2021-08-02 10:49:08.000000000 +0200
@@ -6,7 +6,7 @@
 
 setup(
     name = 'jwcrypto',
-    version = '0.9.1',
+    version = '1.0',
     license = 'LGPLv3+',
     maintainer = 'JWCrypto Project Contributors',
     maintainer_email = 's...@redhat.com',
@@ -14,7 +14,6 @@
     packages = ['jwcrypto'],
     description = 'Implementation of JOSE Web standards',
     classifiers = [
-        'Programming Language :: Python :: 2.7',
         'Programming Language :: Python :: 3.6',
         'Programming Language :: Python :: 3.7',
         'Programming Language :: Python :: 3.8',
@@ -27,6 +26,5 @@
     install_requires = [
         'cryptography >= 2.3',
         'deprecated',
-        'six',
     ],
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.9.1/tox.ini new/jwcrypto-1.0/tox.ini
--- old/jwcrypto-0.9.1/tox.ini  2021-06-09 20:43:19.000000000 +0200
+++ new/jwcrypto-1.0/tox.ini    2021-08-02 10:49:08.000000000 +0200
@@ -1,5 +1,5 @@
 [tox]
-envlist = lint,py27,py36,py37,py38,py39,pep8py2,pep8py3,doc,sphinx
+envlist = lint,py36,py37,py38,py39,pep8,doc,sphinx
 skip_missing_interpreters = true
 
 [testenv]
@@ -15,37 +15,28 @@
     {envpython} -m coverage report -m
 
 [testenv:lint]
-basepython = python2.7
+basepython = python3.9
 deps =
     pylint
 #sitepackages = True
 commands =
     {envpython} -m pylint -d c,r,i,W0613 -r n -f colorized --notes= 
--disable=star-args ./jwcrypto
 
-[testenv:pep8py2]
-basepython = python2.7
-deps =
-    flake8
-    flake8-import-order
-    pep8-naming
-commands =
-    {envpython} -m flake8 {posargs} jwcrypto
-
-[testenv:pep8py3]
+[testenv:pep8]
 basepython = python3
 deps =
     flake8
     flake8-import-order
     pep8-naming
 commands =
-    {envpython} -m flake8 {posargs} jwcrypto
+    {envpython} -m flake8 {posargs} --ignore=N802,N818 jwcrypto
 
 [testenv:doc]
 deps =
     doc8
     docutils
     markdown
-basepython = python2.7
+basepython = python3
 commands =
     doc8 --allow-long-titles README.md
     markdown_py README.md -f {toxworkdir}/README.md.html

Reply via email to