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 2024-01-05 22:59:09 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-jwcrypto (Old) and /work/SRC/openSUSE:Factory/.python-jwcrypto.new.28375 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-jwcrypto" Fri Jan 5 22:59:09 2024 rev:15 rq:1136285 version:1.5.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-jwcrypto/python-jwcrypto.changes 2023-12-09 22:49:00.722326431 +0100 +++ /work/SRC/openSUSE:Factory/.python-jwcrypto.new.28375/python-jwcrypto.changes 2024-01-05 22:59:11.213391570 +0100 @@ -1,0 +2,9 @@ +Tue Jan 2 21:07:17 UTC 2024 - Dirk Müller <dmuel...@suse.com> + +- update to 1.5.1: + * Fix X22519 import/export from PEM + * Read the Docs now requires a config file + * chore: refactor for removing pdb symbols + * Fix potential DoS issue with p2c header + +------------------------------------------------------------------- Old: ---- jwcrypto-1.5.0.tar.gz New: ---- jwcrypto-1.5.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-jwcrypto.spec ++++++ --- /var/tmp/diff_new_pack.j0tC4Q/_old 2024-01-05 22:59:11.889416340 +0100 +++ /var/tmp/diff_new_pack.j0tC4Q/_new 2024-01-05 22:59:11.893416487 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-jwcrypto # -# 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 @@ -16,12 +16,8 @@ # -%{?!python_module:%define python_module() python-%{**} python3-%{**}} - -%define skip_python2 1 - Name: python-jwcrypto -Version: 1.5.0 +Version: 1.5.1 Release: 0 Summary: Python module package implementing JOSE Web standards License: LGPL-3.0-only @@ -29,8 +25,10 @@ Source: https://files.pythonhosted.org/packages/source/j/jwcrypto/jwcrypto-%{version}.tar.gz BuildRequires: %{python_module Deprecated} BuildRequires: %{python_module cryptography >= 3.4} +BuildRequires: %{python_module pip} BuildRequires: %{python_module pytest} BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module wheel} BuildRequires: fdupes BuildRequires: python-rpm-macros Requires: python-Deprecated @@ -51,10 +49,10 @@ %setup -q -n jwcrypto-%{version} %build -%python_build +%pyproject_wheel %install -%python_install +%pyproject_install rm -rv %{buildroot}%{_datadir}/doc/jwcrypto %python_expand %fdupes %{buildroot}%{$python_sitelib} @@ -62,7 +60,8 @@ %pytest jwcrypto %files %{python_files} -%{python_sitelib}/* +%{python_sitelib}/jwcrypto +%{python_sitelib}/jwcrypto-%{version}.dist-info %license LICENSE %doc README.md ++++++ jwcrypto-1.5.0.tar.gz -> jwcrypto-1.5.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jwcrypto-1.5.0/PKG-INFO new/jwcrypto-1.5.1/PKG-INFO --- old/jwcrypto-1.5.0/PKG-INFO 2023-05-30 19:45:13.820392600 +0200 +++ new/jwcrypto-1.5.1/PKG-INFO 2023-12-26 20:51:00.196697500 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: jwcrypto -Version: 1.5.0 +Version: 1.5.1 Summary: Implementation of JOSE Web standards Home-page: https://github.com/latchset/jwcrypto Maintainer: JWCrypto Project Contributors diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jwcrypto-1.5.0/jwcrypto/VERSION new/jwcrypto-1.5.1/jwcrypto/VERSION --- old/jwcrypto-1.5.0/jwcrypto/VERSION 2023-05-30 19:44:53.000000000 +0200 +++ new/jwcrypto-1.5.1/jwcrypto/VERSION 2023-12-26 20:50:49.000000000 +0100 @@ -1 +1 @@ -1.5.0 +1.5.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jwcrypto-1.5.0/jwcrypto/jwa.py new/jwcrypto-1.5.1/jwcrypto/jwa.py --- old/jwcrypto-1.5.0/jwcrypto/jwa.py 2023-05-30 19:44:53.000000000 +0200 +++ new/jwcrypto-1.5.1/jwcrypto/jwa.py 2023-12-26 20:50:49.000000000 +0100 @@ -28,6 +28,8 @@ # Implements RFC 7518 - JSON Web Algorithms (JWA) +default_max_pbkdf2_iterations = 16384 + class JWAAlgorithm(metaclass=ABCMeta): @@ -588,6 +590,9 @@ self.aeskwmap = {128: _A128KW, 192: _A192KW, 256: _A256KW} def _get_key(self, alg, key, p2s, p2c): + if p2c > default_max_pbkdf2_iterations: + raise ValueError('Invalid p2c value, too large') + if not isinstance(key, JWK): # backwards compatibility for old interface if isinstance(key, bytes): @@ -870,10 +875,10 @@ class _RawJWE: - def encrypt(self, k, a, m): + def encrypt(self, k, aad, m): raise NotImplementedError - def decrypt(self, k, a, iv, e, t): + def decrypt(self, k, aad, iv, e, t): raise NotImplementedError @@ -887,10 +892,10 @@ self.blocksize = algorithms.AES.block_size self.wrap_key_size = self.keysize * 2 - def _mac(self, k, a, iv, e): - al = _encode_int(_bitsize(a), 64) + def _mac(self, k, aad, iv, e): + al = _encode_int(_bitsize(aad), 64) h = hmac.HMAC(k, self.hashfn, backend=self.backend) - h.update(a) + h.update(aad) h.update(iv) h.update(e) h.update(al) @@ -898,12 +903,12 @@ return m[:_inbytes(self.keysize)] # RFC 7518 - 5.2.2 - def encrypt(self, k, a, m): + def encrypt(self, k, aad, m): """ Encrypt according to the selected encryption and hashing functions. :param k: Encryption key - :param a: Additional Authentication Data + :param aad: Additional Authentication Data :param m: Plaintext Returns a dictionary with the computed data. @@ -924,15 +929,15 @@ e = encryptor.update(padded_data) + encryptor.finalize() # mac - t = self._mac(hkey, a, iv, e) + t = self._mac(hkey, aad, iv, e) return (iv, e, t) - def decrypt(self, k, a, iv, e, t): + def decrypt(self, k, aad, iv, e, t): """ Decrypt according to the selected encryption and hashing functions. :param k: Encryption key - :param a: Additional Authenticated Data + :param aad: Additional Authenticated Data :param iv: Initialization Vector :param e: Ciphertext :param t: Authentication Tag @@ -946,7 +951,7 @@ dkey = k[_inbytes(self.keysize):] # verify mac - if not constant_time.bytes_eq(t, self._mac(hkey, a, iv, e)): + if not constant_time.bytes_eq(t, self._mac(hkey, aad, iv, e)): raise InvalidSignature('Failed to verify MAC') # decrypt @@ -1003,12 +1008,12 @@ self.wrap_key_size = self.keysize # RFC 7518 - 5.3 - def encrypt(self, k, a, m): + def encrypt(self, k, aad, m): """ Encrypt according to the selected encryption and hashing functions. :param k: Encryption key - :param a: Additional Authentication Data + :param aad: Additional Authentication Data :param m: Plaintext Returns a dictionary with the computed data. @@ -1017,16 +1022,16 @@ cipher = Cipher(algorithms.AES(k), modes.GCM(iv), backend=self.backend) encryptor = cipher.encryptor() - encryptor.authenticate_additional_data(a) + encryptor.authenticate_additional_data(aad) e = encryptor.update(m) + encryptor.finalize() return (iv, e, encryptor.tag) - def decrypt(self, k, a, iv, e, t): + def decrypt(self, k, aad, iv, e, t): """ Decrypt according to the selected encryption and hashing functions. :param k: Encryption key - :param a: Additional Authenticated Data + :param aad: Additional Authenticated Data :param iv: Initialization Vector :param e: Ciphertext :param t: Authentication Tag @@ -1036,7 +1041,7 @@ cipher = Cipher(algorithms.AES(k), modes.GCM(iv, t), backend=self.backend) decryptor = cipher.decryptor() - decryptor.authenticate_additional_data(a) + decryptor.authenticate_additional_data(aad) return decryptor.update(e) + decryptor.finalize() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jwcrypto-1.5.0/jwcrypto/jwe.py new/jwcrypto-1.5.1/jwcrypto/jwe.py --- old/jwcrypto-1.5.0/jwcrypto/jwe.py 2023-05-30 19:44:53.000000000 +0200 +++ new/jwcrypto-1.5.1/jwcrypto/jwe.py 2023-12-26 20:50:49.000000000 +0100 @@ -525,17 +525,17 @@ o['header'] = json_encode(djwe['header']) except ValueError as e: - c = raw_jwe.split('.') - if len(c) != 5: + data = raw_jwe.split('.') + if len(data) != 5: raise InvalidJWEData() from e - p = base64url_decode(c[0]) + p = base64url_decode(data[0]) o['protected'] = p.decode('utf-8') - ekey = base64url_decode(c[1]) + ekey = base64url_decode(data[1]) if ekey != b'': - o['encrypted_key'] = base64url_decode(c[1]) - o['iv'] = base64url_decode(c[2]) - o['ciphertext'] = base64url_decode(c[3]) - o['tag'] = base64url_decode(c[4]) + o['encrypted_key'] = base64url_decode(data[1]) + o['iv'] = base64url_decode(data[2]) + o['ciphertext'] = base64url_decode(data[3]) + o['tag'] = base64url_decode(data[4]) self.objects = o @@ -581,11 +581,11 @@ try: return self.serialize() == other.serialize() except Exception: # pylint: disable=broad-except - a = {'plaintext': self.plaintext} - a.update(self.objects) - b = {'plaintext': other.plaintext} - b.update(other.objects) - return a == b + data1 = {'plaintext': self.plaintext} + data1.update(self.objects) + data2 = {'plaintext': other.plaintext} + data2.update(other.objects) + return data1 == data2 def __str__(self): try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jwcrypto-1.5.0/jwcrypto/jwk.py new/jwcrypto-1.5.1/jwcrypto/jwk.py --- old/jwcrypto-1.5.0/jwcrypto/jwk.py 2023-05-30 19:44:53.000000000 +0200 +++ new/jwcrypto-1.5.1/jwcrypto/jwk.py 2023-12-26 20:50:49.000000000 +0100 @@ -606,11 +606,11 @@ # check key_ops if 'key_ops' in newkey: for ko in newkey['key_ops']: - c = 0 + cnt = 0 for cko in newkey['key_ops']: if ko == cko: - c += 1 - if c != 1: + cnt += 1 + if cnt != 1: raise InvalidJWKValue('Duplicate values in "key_ops"') # check use/key_ops consistency @@ -971,9 +971,13 @@ self._import_pyca_pri_ec(key) elif isinstance(key, ec.EllipticCurvePublicKey): self._import_pyca_pub_ec(key) - elif isinstance(key, (Ed25519PrivateKey, Ed448PrivateKey)): + elif isinstance(key, (Ed25519PrivateKey, + Ed448PrivateKey, + X25519PrivateKey)): self._import_pyca_pri_okp(key) - elif isinstance(key, (Ed25519PublicKey, Ed448PublicKey)): + elif isinstance(key, (Ed25519PublicKey, + Ed448PublicKey, + X25519PublicKey)): self._import_pyca_pub_okp(key) else: raise InvalidJWKValue('Unknown key object %r' % key) @@ -1028,26 +1032,26 @@ :return: A serialized bytes buffer containing a PEM formatted key. :rtype: `bytes` """ - e = serialization.Encoding.PEM + enc = serialization.Encoding.PEM if private_key: if not self.has_private: raise InvalidJWKType("No private key available") f = serialization.PrivateFormat.PKCS8 if password is None: - a = serialization.NoEncryption() + enc_alg = serialization.NoEncryption() elif isinstance(password, bytes): - a = serialization.BestAvailableEncryption(password) + enc_alg = serialization.BestAvailableEncryption(password) elif password is False: raise ValueError("The password must be None or a bytes string") else: raise TypeError("The password string must be bytes") return self._get_private_key().private_bytes( - encoding=e, format=f, encryption_algorithm=a) + encoding=enc, format=f, encryption_algorithm=enc_alg) else: if not self.has_public: raise InvalidJWKType("No public key available") f = serialization.PublicFormat.SubjectPublicKeyInfo - return self._get_public_key().public_bytes(encoding=e, format=f) + return self._get_public_key().public_bytes(encoding=enc, format=f) @classmethod def from_pyca(cls, key): @@ -1280,6 +1284,7 @@ Creates a special key 'keys' that is of a type derived from 'set' The 'keys' attribute accepts only :class:`jwcrypto.jwk.JWK` elements. """ + def __init__(self, *args, **kwargs): super(JWKSet, self).__init__() super(JWKSet, self).__setitem__('keys', _JWKkeys()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jwcrypto-1.5.0/jwcrypto/jws.py new/jwcrypto-1.5.1/jwcrypto/jws.py --- old/jwcrypto-1.5.0/jwcrypto/jws.py 2023-05-30 19:44:53.000000000 +0200 +++ new/jwcrypto-1.5.1/jwcrypto/jws.py 2023-12-26 20:50:49.000000000 +0100 @@ -279,18 +279,20 @@ raise InvalidJWSSignature('No "alg" in headers') if alg: if 'alg' in p and alg != p['alg']: - raise InvalidJWSSignature('"alg" mismatch, requested ' - '"%s", found "%s"' % (alg, - p['alg'])) - a = alg + raise InvalidJWSSignature( + '"alg" mismatch, requested' + f''' "{alg}", found "{p['alg']}"''' + ) + resulting_alg = alg else: - a = p['alg'] + resulting_alg = p['alg'] # the following will verify the "alg" is supported and the signature # verifies if isinstance(key, JWK): - c = JWSCore(a, key, protected, payload, self._allowed_algs) - c.verify(signature) + signer = JWSCore(resulting_alg, key, protected, + payload, self._allowed_algs) + signer.verify(signature) self.verifylog.append("Success") elif isinstance(key, JWKSet): keys = key @@ -303,8 +305,11 @@ for k in keys: try: - c = JWSCore(a, k, protected, payload, self._allowed_algs) - c.verify(signature) + signer2 = JWSCore( + resulting_alg, k, protected, + payload, self._allowed_algs + ) + signer2.verify(signature) self.verifylog.append("Success") break except Exception as e: # pylint: disable=broad-except @@ -455,16 +460,16 @@ o['payload'] = djws['payload'] except ValueError: - c = raw_jws.split('.') - if len(c) != 3: + data = raw_jws.split('.') + if len(data) != 3: raise InvalidJWSObject('Unrecognized' ' representation') from None - p = base64url_decode(str(c[0])) + p = base64url_decode(str(data[0])) if len(p) > 0: o['protected'] = p.decode('utf-8') self._deserialize_b64(o, o['protected']) - o['payload'] = base64url_decode(str(c[1])) - o['signature'] = base64url_decode(str(c[2])) + o['payload'] = base64url_decode(str(data[1])) + o['signature'] = base64url_decode(str(data[2])) self.objects = o diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jwcrypto-1.5.0/jwcrypto/jwt.py new/jwcrypto-1.5.1/jwcrypto/jwt.py --- old/jwcrypto-1.5.0/jwcrypto/jwt.py 2023-05-30 19:44:53.000000000 +0200 +++ new/jwcrypto-1.5.1/jwcrypto/jwt.py 2023-12-26 20:50:49.000000000 +0100 @@ -256,20 +256,20 @@ return self._claims @claims.setter - def claims(self, c): - if not isinstance(c, dict): + def claims(self, data): + if not isinstance(data, dict): if not self._reg_claims: # no default_claims, can return immediately - self._claims = c + self._claims = data return - c = json_decode(c) + data = json_decode(data) else: # _add_default_claims modifies its argument # so we must always copy it. - c = copy.deepcopy(c) + data = copy.deepcopy(data) - self._add_default_claims(c) - self._claims = json_encode(c) + self._add_default_claims(data) + self._claims = json_encode(data) @property def token(self): @@ -661,10 +661,10 @@ decryption key, or a (:class:`jwcrypto.jwk.JWKSet`) that contains a key indexed by the 'kid' header. """ - c = jwt.count('.') - if c == 2: + data = jwt.count('.') + if data == 2: self.token = JWS() - elif c == 4: + elif data == 4: self.token = JWE() else: raise ValueError("Token format unrecognized") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jwcrypto-1.5.0/jwcrypto/tests.py new/jwcrypto-1.5.1/jwcrypto/tests.py --- old/jwcrypto-1.5.0/jwcrypto/tests.py 2023-05-30 19:44:53.000000000 +0200 +++ new/jwcrypto-1.5.1/jwcrypto/tests.py 2023-12-26 20:50:49.000000000 +0100 @@ -367,6 +367,16 @@ -----END PUBLIC KEY----- """ +X25519PrivatePEM = b"""-----BEGIN PRIVATE KEY----- +MC4CAQAwBQYDK2VuBCIEIBjAbPTtNY6CUuR5FG1+xb1u5nSRokrNaQYEsgu9O+hP +-----END PRIVATE KEY----- +""" + +X25519PublicPEM = b"""-----BEGIN PUBLIC KEY----- +MCowBQYDK2VuAyEAW+m9ugi1psQFx6dtTl6J/XZ4JFP019S+oq4wyAoWPnQ= +-----END PUBLIC KEY----- +""" + ECPublicPEM = b"""-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhvGzt82WMJxqTuXCZxnvwrx4enQj 6xc+erlhbTq8gTMAJBzNRPbpuj4NOwTCwjohrtY0TAkthwTuixuojpGKmw== @@ -381,6 +391,13 @@ "y": "ACQczUT26bo-DTsEwsI6Ia7WNEwJLYcE7osbqI6Rips" } +X25519PublicJWK = { + 'crv': 'X25519', + 'kid': '9cgLEZD5VsaV9dUPNehs2pOwxtmH-EWHJY-pC74Wjak', + 'kty': 'OKP', + 'x': 'W-m9ugi1psQFx6dtTl6J_XZ4JFP019S-oq4wyAoWPnQ' +} + class TestJWK(unittest.TestCase): def test_create_pubKeys(self): @@ -570,6 +587,11 @@ self.assertEqual(pub_ec.export_to_pem(), ECPublicPEM) self.assertEqual(json_decode(pub_ec.export()), ECPublicJWK) + def test_import_x25519_from_pem(self): + pub_x25519 = jwk.JWK.from_pem(X25519PublicPEM) + self.assertEqual(pub_x25519.export_to_pem(), X25519PublicPEM) + self.assertEqual(json_decode(pub_x25519.export()), X25519PublicJWK) + def test_export_symmetric(self): key = jwk.JWK(**SymmetricKeys['keys'][0]) self.assertTrue(key.is_symmetric) @@ -681,10 +703,10 @@ pubkey = jwk.JWK.from_pem(Ed25519PublicPEM) self.assertTrue(pubkey.has_public) self.assertFalse(pubkey.has_private) - c = jws.JWS() - c.deserialize(sig, pubkey, alg="EdDSA") - self.assertTrue(c.objects['valid']) - self.assertEqual(c.payload, payload) + jws_token = jws.JWS() + jws_token.deserialize(sig, pubkey, alg="EdDSA") + self.assertTrue(jws_token.objects['valid']) + self.assertEqual(jws_token.payload, payload) def test_jwk_as_dict(self): key = jwk.JWK(**PublicKeys['keys'][0]) @@ -1796,9 +1818,9 @@ t.make_signed_token(key) token = t.serialize() - c = jwt.JWT() - c.deserialize(token, key) - self.assertEqual('{}', c.claims) + _jwt = jwt.JWT() + _jwt.deserialize(token, key) + self.assertEqual('{}', _jwt.claims) # empty string is also valid t = jwt.JWT('{"alg":"HS256"}', '') @@ -1811,9 +1833,9 @@ t.make_signed_token(key) token = t.serialize() - c = jwt.JWT() - c.deserialize(token, key) - self.assertEqual(' ', c.claims) + _jwt = jwt.JWT() + _jwt.deserialize(token, key) + self.assertEqual(' ', _jwt.claims) def test_Issue_209(self): key = jwk.JWK(**A3_key) @@ -2077,6 +2099,18 @@ key = jwk.JWK.from_password('password') self.assertRaises(ValueError, enc.add_recipient, key) + # Test p2c iteration checks + maxiter = jwa.default_max_pbkdf2_iterations + p2cenc = jwe.JWE(plaintext='plain', + protected={"alg": "PBES2-HS256+A128KW", + "enc": "A256CBC-HS512", + "p2c": maxiter + 1, + "p2s": base64url_encode("A" * 16)}) + with self.assertRaisesRegex(ValueError, 'too large'): + p2cenc.add_recipient(key) + jwa.default_max_pbkdf2_iterations += 2 + p2cenc.add_recipient(key) + class JWATests(unittest.TestCase): def test_jwa_create(self): @@ -2189,26 +2223,26 @@ def test_jws_equality(self): key = jwk.JWK.generate(kty='oct', size=256) payload = "My Integrity protected message" - a = jws.JWS(payload.encode('utf-8')) - b = jws.JWS(payload.encode('utf-8')) - self.assertEqual(a, b) - - a.add_signature(key, None, - json_encode({"alg": "HS256"}), - json_encode({"kid": key.thumbprint()})) + signer_a = jws.JWS(payload.encode('utf-8')) + signer_b = jws.JWS(payload.encode('utf-8')) + self.assertEqual(signer_a, signer_b) + + signer_a.add_signature(key, None, + json_encode({"alg": "HS256"}), + json_encode({"kid": key.thumbprint()})) # One is signed, the other is not - self.assertNotEqual(a, b) + self.assertNotEqual(signer_a, signer_b) - b.add_signature(key, None, - json_encode({"alg": "HS256"}), - json_encode({"kid": key.thumbprint()})) + signer_b.add_signature(key, None, + json_encode({"alg": "HS256"}), + json_encode({"kid": key.thumbprint()})) # This kind of signature is deterministic so they should be equal - self.assertEqual(a, b) + self.assertEqual(signer_a, signer_b) - c = jws.JWS.from_jose_token(a.serialize()) - self.assertNotEqual(a, c) - c.verify(key) - self.assertEqual(a, c) + signer_c = jws.JWS.from_jose_token(signer_a.serialize()) + self.assertNotEqual(signer_a, signer_c) + signer_c.verify(key) + self.assertEqual(signer_a, signer_c) def test_jws_representations(self): key = jwk.JWK.generate(kty='oct', size=256) @@ -2228,24 +2262,24 @@ def test_jwe_equality(self): key = jwk.JWK.generate(kty='oct', size=256) payload = "My Encrypted message" - a = jwe.JWE(payload.encode('utf-8'), - json_encode({"alg": "A256KW", - "enc": "A256CBC-HS512"})) - b = jwe.JWE(payload.encode('utf-8'), - json_encode({"alg": "A256KW", - "enc": "A256CBC-HS512"})) - self.assertEqual(a, b) + signer_a = jwe.JWE(payload.encode('utf-8'), + json_encode({"alg": "A256KW", + "enc": "A256CBC-HS512"})) + signer_b = jwe.JWE(payload.encode('utf-8'), + json_encode({"alg": "A256KW", + "enc": "A256CBC-HS512"})) + self.assertEqual(signer_a, signer_b) - a.add_recipient(key) + signer_a.add_recipient(key) # One is encrypted, the other is not - self.assertNotEqual(a, b) + self.assertNotEqual(signer_a, signer_b) - b.add_recipient(key) + signer_b.add_recipient(key) # Encryption generates a random CEK so tokens will always differ - self.assertNotEqual(a, b) + self.assertNotEqual(signer_a, signer_b) - c = jwe.JWE.from_jose_token(a.serialize()) - self.assertEqual(a, c) + signer_c = jwe.JWE.from_jose_token(signer_a.serialize()) + self.assertEqual(signer_a, signer_c) def test_jwe_representations(self): key = jwk.JWK.generate(kty='oct', size=256) @@ -2267,29 +2301,29 @@ def test_jwt_equality(self): key = jwk.JWK.generate(kty='oct', size=256) - a = jwt.JWT(header={"alg": "HS256"}, - claims={"info": "I'm a signed token"}) - b = jwt.JWT(header={"alg": "HS256"}, - claims={"info": "I'm a signed token"}) - self.assertEqual(a, b) + signer_a = jwt.JWT(header={"alg": "HS256"}, + claims={"info": "I'm a signed token"}) + signer_b = jwt.JWT(header={"alg": "HS256"}, + claims={"info": "I'm a signed token"}) + self.assertEqual(signer_a, signer_b) - a.make_signed_token(key) + signer_a.make_signed_token(key) # One is signed, the other is not - self.assertNotEqual(a, b) + self.assertNotEqual(signer_a, signer_b) - b.make_signed_token(key) + signer_b.make_signed_token(key) # This kind of signature is deterministic so they should be equal - self.assertEqual(a, b) + self.assertEqual(signer_a, signer_b) - c = jwt.JWT.from_jose_token(a.serialize()) - self.assertNotEqual(a, c) - c.validate(key) - self.assertEqual(a, c) + signer_c = jwt.JWT.from_jose_token(signer_a.serialize()) + self.assertNotEqual(signer_a, signer_c) + signer_c.validate(key) + self.assertEqual(signer_a, signer_c) ea = jwt.JWT(header={"alg": "A256KW", "enc": "A256CBC-HS512"}, - claims=a.serialize()) + claims=signer_a.serialize()) eb = jwt.JWT(header={"alg": "A256KW", "enc": "A256CBC-HS512"}, - claims=b.serialize()) + claims=signer_b.serialize()) self.assertEqual(ea, eb) ea.make_encrypted_token(key) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jwcrypto-1.5.0/jwcrypto.egg-info/PKG-INFO new/jwcrypto-1.5.1/jwcrypto.egg-info/PKG-INFO --- old/jwcrypto-1.5.0/jwcrypto.egg-info/PKG-INFO 2023-05-30 19:45:13.000000000 +0200 +++ new/jwcrypto-1.5.1/jwcrypto.egg-info/PKG-INFO 2023-12-26 20:51:00.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: jwcrypto -Version: 1.5.0 +Version: 1.5.1 Summary: Implementation of JOSE Web standards Home-page: https://github.com/latchset/jwcrypto Maintainer: JWCrypto Project Contributors