swarmauri_crypto_jwe 0.3.0.dev5__tar.gz → 0.11.0.dev2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,25 +1,26 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: swarmauri_crypto_jwe
3
- Version: 0.3.0.dev5
3
+ Version: 0.11.0.dev2
4
4
  Summary: RFC 7516/7518 compliant JWE crypto provider for Swarmauri
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
7
7
  Keywords: swarmauri,sdk,standards,crypto,jwe,cryptography
8
8
  Author: Jacob Stewart
9
9
  Author-email: jacob@swarmauri.com
10
- Requires-Python: >=3.10,<3.13
10
+ Requires-Python: >=3.10,<3.15
11
11
  Classifier: License :: OSI Approved :: Apache Software License
12
12
  Classifier: Natural Language :: English
13
- Classifier: Programming Language :: Python :: 3.10
14
- Classifier: Programming Language :: Python :: 3.11
15
- Classifier: Programming Language :: Python :: 3.12
16
- Classifier: Programming Language :: Python :: 3.13
17
13
  Classifier: Development Status :: 3 - Alpha
18
14
  Classifier: Topic :: Security :: Cryptography
19
15
  Classifier: Intended Audience :: Developers
20
16
  Classifier: Programming Language :: Python
21
17
  Classifier: Programming Language :: Python :: 3
22
18
  Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
23
24
  Provides-Extra: cbor
24
25
  Provides-Extra: json
25
26
  Requires-Dist: cbor2 ; extra == "cbor"
@@ -28,17 +29,21 @@ Requires-Dist: swarmauri_base
28
29
  Requires-Dist: swarmauri_core
29
30
  Description-Content-Type: text/markdown
30
31
 
31
- ![Swarmauri Logo](https://github.com/swarmauri/swarmauri-sdk/blob/3d4d1cfa949399d7019ae9d8f296afba773dfb7f/assets/swarmauri.brand.theme.svg)
32
+ ![Swarmauri Logo](https://raw.githubusercontent.com/swarmauri/swarmauri-sdk/master/assets/swarmauri_sdk_brand.png)
32
33
 
33
34
  <p align="center">
34
- <a href="https://pypi.org/project/swarmauri_crypto_jwe/"><img src="https://img.shields.io/pypi/dm/swarmauri_crypto_jwe" alt="PyPI - Downloads"/></a>
35
- <a href="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/standards/swarmauri_crypto_jwe/"><img alt="Hits" src="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/standards/swarmauri_crypto_jwe.svg"/></a>
36
- <a href="https://pypi.org/project/swarmauri_crypto_jwe/"><img src="https://img.shields.io/pypi/pyversions/swarmauri_crypto_jwe" alt="PyPI - Python Version"/></a>
37
- <a href="https://pypi.org/project/swarmauri_crypto_jwe/"><img src="https://img.shields.io/pypi/l/swarmauri_crypto_jwe" alt="PyPI - License"/></a>
38
- <a href="https://pypi.org/project/swarmauri_crypto_jwe/"><img src="https://img.shields.io/pypi/v/swarmauri_crypto_jwe?label=swarmauri_crypto_jwe&color=green" alt="PyPI - swarmauri_crypto_jwe"/></a>
39
- </p>
40
-
41
- ---
35
+ <a href="https://pepy.tech/project/swarmauri_crypto_jwe/">
36
+ <img src="https://static.pepy.tech/badge/swarmauri_crypto_jwe/month" alt="PyPI - Downloads"/></a>
37
+ <a href="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/standards/swarmauri_crypto_jwe/">
38
+ <img alt="Hits" src="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/standards/swarmauri_crypto_jwe.svg"/></a>
39
+ <a href="https://pypi.org/project/swarmauri_crypto_jwe/">
40
+ <img src="https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue" alt="PyPI - Python Version"/></a>
41
+ <a href="https://pypi.org/project/swarmauri_crypto_jwe/">
42
+ <img src="https://img.shields.io/pypi/l/swarmauri_crypto_jwe" alt="PyPI - License"/></a>
43
+ <a href="https://pypi.org/project/swarmauri_crypto_jwe/">
44
+ <img src="https://img.shields.io/pypi/v/swarmauri_crypto_jwe?label=swarmauri_crypto_jwe&color=green" alt="PyPI - swarmauri_crypto_jwe"/></a>
45
+ <a href="https://discord.gg/N4UpBuQv8T">
46
+ <img src="https://img.shields.io/badge/Discord-Join%20Chat-5865F2?logo=discord&logoColor=white" alt="Discord"/></a></p>
42
47
 
43
48
  ## Swarmauri Crypto JWE
44
49
 
@@ -127,9 +132,9 @@ crypto = pm.load("swarmauri.cryptos", "JweCrypto")
127
132
 
128
133
  **Parameters**
129
134
 
130
- - `alg` `JWAAlg` member describing the key management algorithm (`JWAAlg.RSA_OAEP_256`, `JWAAlg.DIR`, etc.).
131
- - `enc` `JWAAlg` member describing the content encryption algorithm (`JWAAlg.A256GCM`, `JWAAlg.A128GCM`, etc.).
132
- - `key` mapping containing the key material used for encryption:
135
+ - `alg` ? `JWAAlg` member describing the key management algorithm (`JWAAlg.RSA_OAEP_256`, `JWAAlg.DIR`, etc.).
136
+ - `enc` ? `JWAAlg` member describing the content encryption algorithm (`JWAAlg.A256GCM`, `JWAAlg.A128GCM`, etc.).
137
+ - `key` ? mapping containing the key material used for encryption:
133
138
  - `{"k": bytes}` for direct symmetric keys (`dir`).
134
139
  - `{"pub": rsa_public_key}` for RSA OAEP, where the public key may be PEM bytes or an `RSAPublicKey` instance.
135
140
  - `{"pub": ec_public_key}` for ECDH-ES with PEM, JWK, or key objects.
@@ -146,3 +151,5 @@ The provider is registered under the `swarmauri.cryptos` entry point as `JweCryp
146
151
  If you want to contribute to swarmauri-sdk, read up on our
147
152
  [guidelines for contributing](https://github.com/swarmauri/swarmauri-sdk/blob/master/CONTRIBUTING.md)
148
153
  that will help you get started.
154
+
155
+
@@ -1,14 +1,18 @@
1
- ![Swarmauri Logo](https://github.com/swarmauri/swarmauri-sdk/blob/3d4d1cfa949399d7019ae9d8f296afba773dfb7f/assets/swarmauri.brand.theme.svg)
1
+ ![Swarmauri Logo](https://raw.githubusercontent.com/swarmauri/swarmauri-sdk/master/assets/swarmauri_sdk_brand.png)
2
2
 
3
3
  <p align="center">
4
- <a href="https://pypi.org/project/swarmauri_crypto_jwe/"><img src="https://img.shields.io/pypi/dm/swarmauri_crypto_jwe" alt="PyPI - Downloads"/></a>
5
- <a href="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/standards/swarmauri_crypto_jwe/"><img alt="Hits" src="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/standards/swarmauri_crypto_jwe.svg"/></a>
6
- <a href="https://pypi.org/project/swarmauri_crypto_jwe/"><img src="https://img.shields.io/pypi/pyversions/swarmauri_crypto_jwe" alt="PyPI - Python Version"/></a>
7
- <a href="https://pypi.org/project/swarmauri_crypto_jwe/"><img src="https://img.shields.io/pypi/l/swarmauri_crypto_jwe" alt="PyPI - License"/></a>
8
- <a href="https://pypi.org/project/swarmauri_crypto_jwe/"><img src="https://img.shields.io/pypi/v/swarmauri_crypto_jwe?label=swarmauri_crypto_jwe&color=green" alt="PyPI - swarmauri_crypto_jwe"/></a>
9
- </p>
10
-
11
- ---
4
+ <a href="https://pepy.tech/project/swarmauri_crypto_jwe/">
5
+ <img src="https://static.pepy.tech/badge/swarmauri_crypto_jwe/month" alt="PyPI - Downloads"/></a>
6
+ <a href="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/standards/swarmauri_crypto_jwe/">
7
+ <img alt="Hits" src="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/standards/swarmauri_crypto_jwe.svg"/></a>
8
+ <a href="https://pypi.org/project/swarmauri_crypto_jwe/">
9
+ <img src="https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue" alt="PyPI - Python Version"/></a>
10
+ <a href="https://pypi.org/project/swarmauri_crypto_jwe/">
11
+ <img src="https://img.shields.io/pypi/l/swarmauri_crypto_jwe" alt="PyPI - License"/></a>
12
+ <a href="https://pypi.org/project/swarmauri_crypto_jwe/">
13
+ <img src="https://img.shields.io/pypi/v/swarmauri_crypto_jwe?label=swarmauri_crypto_jwe&color=green" alt="PyPI - swarmauri_crypto_jwe"/></a>
14
+ <a href="https://discord.gg/N4UpBuQv8T">
15
+ <img src="https://img.shields.io/badge/Discord-Join%20Chat-5865F2?logo=discord&logoColor=white" alt="Discord"/></a></p>
12
16
 
13
17
  ## Swarmauri Crypto JWE
14
18
 
@@ -97,9 +101,9 @@ crypto = pm.load("swarmauri.cryptos", "JweCrypto")
97
101
 
98
102
  **Parameters**
99
103
 
100
- - `alg` `JWAAlg` member describing the key management algorithm (`JWAAlg.RSA_OAEP_256`, `JWAAlg.DIR`, etc.).
101
- - `enc` `JWAAlg` member describing the content encryption algorithm (`JWAAlg.A256GCM`, `JWAAlg.A128GCM`, etc.).
102
- - `key` mapping containing the key material used for encryption:
104
+ - `alg` ? `JWAAlg` member describing the key management algorithm (`JWAAlg.RSA_OAEP_256`, `JWAAlg.DIR`, etc.).
105
+ - `enc` ? `JWAAlg` member describing the content encryption algorithm (`JWAAlg.A256GCM`, `JWAAlg.A128GCM`, etc.).
106
+ - `key` ? mapping containing the key material used for encryption:
103
107
  - `{"k": bytes}` for direct symmetric keys (`dir`).
104
108
  - `{"pub": rsa_public_key}` for RSA OAEP, where the public key may be PEM bytes or an `RSAPublicKey` instance.
105
109
  - `{"pub": ec_public_key}` for ECDH-ES with PEM, JWK, or key objects.
@@ -115,4 +119,5 @@ The provider is registered under the `swarmauri.cryptos` entry point as `JweCryp
115
119
 
116
120
  If you want to contribute to swarmauri-sdk, read up on our
117
121
  [guidelines for contributing](https://github.com/swarmauri/swarmauri-sdk/blob/master/CONTRIBUTING.md)
118
- that will help you get started.
122
+ that will help you get started.
123
+
@@ -1,24 +1,25 @@
1
1
  [project]
2
2
  name = "swarmauri_crypto_jwe"
3
- version = "0.3.0.dev5"
3
+ version = "0.11.0.dev2"
4
4
  description = "RFC 7516/7518 compliant JWE crypto provider for Swarmauri"
5
5
  license = "Apache-2.0"
6
6
  readme = "README.md"
7
- requires-python = ">=3.10,<3.13"
7
+ requires-python = ">=3.10,<3.15"
8
8
  authors = [{ name = "Jacob Stewart", email = "jacob@swarmauri.com" }]
9
9
  classifiers = [
10
10
  "License :: OSI Approved :: Apache Software License",
11
11
  "Natural Language :: English",
12
- "Programming Language :: Python :: 3.10",
13
- "Programming Language :: Python :: 3.11",
14
- "Programming Language :: Python :: 3.12",
15
- "Programming Language :: Python :: 3.13",
16
12
  "Development Status :: 3 - Alpha",
17
13
  "Topic :: Security :: Cryptography",
18
14
  "Intended Audience :: Developers",
19
15
  "Programming Language :: Python",
20
16
  "Programming Language :: Python :: 3",
21
17
  "Programming Language :: Python :: 3 :: Only",
18
+ "Programming Language :: Python :: 3.10",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Programming Language :: Python :: 3.13",
22
+ "Programming Language :: Python :: 3.14",
22
23
  ]
23
24
  dependencies = [
24
25
  "swarmauri_core",
@@ -47,7 +47,9 @@ def _cek_len_for_enc(enc: JWAAlg) -> int:
47
47
  return 24
48
48
  if enc == JWAAlg.A256GCM:
49
49
  return 32
50
- raise ValueError(f"Unsupported enc '{enc.value}'. Use A128GCM/A192GCM/A256GCM.")
50
+ raise ValueError(
51
+ f"Unsupported enc '{enc.value}'. Use A128GCM/A192GCM/A256GCM."
52
+ )
51
53
 
52
54
 
53
55
  def _hash_for_oaep(alg: JWAAlg):
@@ -68,7 +70,9 @@ def _compute_aad(protected_b64: str, aad_bytes: Optional[bytes]) -> bytes:
68
70
  return (protected_b64 + "." + _b64u(aad_bytes)).encode("ascii")
69
71
 
70
72
 
71
- def _jwk_ec_public_numbers(jwk: Mapping[str, Any]) -> ec.EllipticCurvePublicNumbers:
73
+ def _jwk_ec_public_numbers(
74
+ jwk: Mapping[str, Any],
75
+ ) -> ec.EllipticCurvePublicNumbers:
72
76
  crv = jwk.get("crv")
73
77
  curve_map = {
74
78
  "P-256": ec.SECP256R1(),
@@ -85,7 +89,11 @@ def _jwk_ec_public_numbers(jwk: Mapping[str, Any]) -> ec.EllipticCurvePublicNumb
85
89
  def _ec_jwk_from_public_key(pk: ec.EllipticCurvePublicKey) -> Dict[str, Any]:
86
90
  numbers = pk.public_numbers()
87
91
  crv = pk.curve.name
88
- crv_map = {"secp256r1": "P-256", "secp384r1": "P-384", "secp521r1": "P-521"}
92
+ crv_map = {
93
+ "secp256r1": "P-256",
94
+ "secp384r1": "P-384",
95
+ "secp521r1": "P-521",
96
+ }
89
97
  if crv not in crv_map:
90
98
  raise ValueError(f"Unsupported EC curve: {crv}")
91
99
  size = (pk.curve.key_size + 7) // 8
@@ -96,7 +104,8 @@ def _ec_jwk_from_public_key(pk: ec.EllipticCurvePublicKey) -> Dict[str, Any]:
96
104
 
97
105
  def _x25519_jwk_from_public_key(pk: x25519.X25519PublicKey) -> Dict[str, Any]:
98
106
  raw = pk.public_bytes(
99
- encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw
107
+ encoding=serialization.Encoding.Raw,
108
+ format=serialization.PublicFormat.Raw,
100
109
  )
101
110
  return {"kty": "OKP", "crv": "X25519", "x": _b64u(raw)}
102
111
 
@@ -105,7 +114,9 @@ def _load_rsa_public(key: Any) -> rsa.RSAPublicKey:
105
114
  if isinstance(key, rsa.RSAPublicKey):
106
115
  return key
107
116
  if isinstance(key, (bytes, bytearray, str)):
108
- data = key if isinstance(key, (bytes, bytearray)) else key.encode("utf-8")
117
+ data = (
118
+ key if isinstance(key, (bytes, bytearray)) else key.encode("utf-8")
119
+ )
109
120
  pk = load_pem_public_key(data)
110
121
  if not isinstance(pk, rsa.RSAPublicKey):
111
122
  raise TypeError("PEM provided is not an RSA public key")
@@ -128,7 +139,9 @@ def _load_rsa_private(
128
139
  elif isinstance(password, (bytes, bytearray)):
129
140
  pwd = bytes(password)
130
141
  if isinstance(key, (bytes, bytearray, str)):
131
- data = key if isinstance(key, (bytes, bytearray)) else key.encode("utf-8")
142
+ data = (
143
+ key if isinstance(key, (bytes, bytearray)) else key.encode("utf-8")
144
+ )
132
145
  sk = load_pem_private_key(data, password=pwd)
133
146
  if not isinstance(sk, rsa.RSAPrivateKey):
134
147
  raise TypeError("PEM provided is not an RSA private key")
@@ -146,7 +159,7 @@ def _load_ecdh_recipient_public(jwk_or_pem: Any) -> Tuple[str, Any]:
146
159
  x = _b64u_dec(jwk_or_pem["x"])
147
160
  return "X25519", x25519.X25519PublicKey.from_public_bytes(x)
148
161
  raise ValueError(
149
- f"Unsupported JWK kty/crv for ECDH-ES: {kty}/{jwk_or_pem.get('crv')}"
162
+ f"Unsupported JWK kty/crv for ECDH-ES: {kty}/{jwk_or_pem.get('crv')}" # noqa: E501
150
163
  )
151
164
  if isinstance(jwk_or_pem, (bytes, bytearray, str)):
152
165
  data = (
@@ -225,7 +238,8 @@ class JweCrypto:
225
238
  ) -> JWECompact:
226
239
  """Encrypt a payload into a compact JWE string.
227
240
 
228
- payload (Union[bytes, str, Mapping[str, Any]]): Data to encrypt. Strings and
241
+ payload (Union[bytes, str, Mapping[str, Any]]): Data to encrypt.
242
+ Strings and
229
243
  mappings are encoded as UTF-8 JSON.
230
244
  alg (JWAAlg): Key management algorithm.
231
245
  enc (JWAAlg): Content encryption algorithm.
@@ -259,11 +273,13 @@ class JweCrypto:
259
273
  if alg == JWAAlg.DIR:
260
274
  secret = key.get("k")
261
275
  secret_b = (
262
- secret.encode("utf-8") if isinstance(secret, str) else bytes(secret)
276
+ secret.encode("utf-8")
277
+ if isinstance(secret, str)
278
+ else bytes(secret)
263
279
  )
264
280
  if len(secret_b) != _cek_len_for_enc(enc):
265
281
  raise ValueError(
266
- f"'dir' key size must equal enc key size ({_cek_len_for_enc(enc)} bytes)"
282
+ f"'dir' key size must equal enc key size ({_cek_len_for_enc(enc)} bytes)" # noqa: E501
267
283
  )
268
284
  cek = secret_b
269
285
  elif alg in (JWAAlg.RSA_OAEP, JWAAlg.RSA_OAEP_256):
@@ -351,19 +367,23 @@ class JweCrypto:
351
367
 
352
368
  jwe (JWECompact): Serialized JWE to decode.
353
369
  dir_key (Union[bytes, str]): Symmetric key when ``alg='dir'`` is used.
354
- rsa_private_pem (Union[str, bytes]): RSA private key in PEM encoding for
370
+ rsa_private_pem (Union[str, bytes]): RSA private key in PEM encoding
371
+ for
355
372
  RSA-OAEP algorithms.
356
373
  rsa_private_password (Union[str, bytes]): Password for the RSA key.
357
374
  ecdh_private_key (Any): Private key for ECDH-ES.
358
375
  expected_algs (Iterable[JWAAlg]): Allowed algorithm values.
359
376
  expected_encs (Iterable[JWAAlg]): Allowed encryption values.
360
377
  aad (Union[bytes, str]): Additional authenticated data.
361
- RETURNS (JweDecryptResult): Header and plaintext of the decrypted token.
378
+ RETURNS (JweDecryptResult): Header and plaintext of the decrypted
379
+ token.
362
380
  """
363
381
 
364
382
  parts = jwe.split(".")
365
383
  if len(parts) != 5:
366
- raise ValueError("Invalid JWE compact: expected 5 dot-separated parts.")
384
+ raise ValueError(
385
+ "Invalid JWE compact: expected 5 dot-separated parts."
386
+ )
367
387
  b64_prot, b64_ekey, b64_iv, b64_ct, b64_tag = parts
368
388
 
369
389
  header = json.loads(_b64u_dec(b64_prot))
@@ -389,33 +409,49 @@ class JweCrypto:
389
409
  if dir_key is None:
390
410
  raise ValueError("dir_key is required for alg='dir'.")
391
411
  cek = (
392
- dir_key.encode("utf-8") if isinstance(dir_key, str) else bytes(dir_key)
412
+ dir_key.encode("utf-8")
413
+ if isinstance(dir_key, str)
414
+ else bytes(dir_key)
393
415
  )
394
416
  if len(cek) != _cek_len_for_enc(enc):
395
417
  raise ValueError("dir_key length mismatch for enc.")
396
418
  elif alg in (JWAAlg.RSA_OAEP, JWAAlg.RSA_OAEP_256):
397
419
  if rsa_private_pem is None:
398
- raise ValueError("rsa_private_pem is required for RSA-OAEP decryption.")
399
- sk = _load_rsa_private(rsa_private_pem, password=rsa_private_password)
420
+ raise ValueError(
421
+ "rsa_private_pem is required for RSA-OAEP decryption."
422
+ )
423
+ sk = _load_rsa_private(
424
+ rsa_private_pem, password=rsa_private_password
425
+ )
400
426
  ekey = _b64u_dec(b64_ekey)
401
427
  hash_alg = _hash_for_oaep(alg)
402
428
  cek = sk.decrypt(
403
429
  ekey,
404
430
  padding.OAEP(
405
- mgf=padding.MGF1(algorithm=hash_alg), algorithm=hash_alg, label=None
431
+ mgf=padding.MGF1(algorithm=hash_alg),
432
+ algorithm=hash_alg,
433
+ label=None,
406
434
  ),
407
435
  )
408
436
  elif alg == JWAAlg.ECDH_ES:
409
437
  if ecdh_private_key is None:
410
- raise ValueError("ecdh_private_key is required for ECDH-ES decryption.")
438
+ raise ValueError(
439
+ "ecdh_private_key is required for ECDH-ES decryption."
440
+ )
411
441
  epk = header.get("epk")
412
442
  if not isinstance(epk, Mapping):
413
- raise ValueError("Missing/invalid 'epk' in JWE header for ECDH-ES.")
443
+ raise ValueError(
444
+ "Missing/invalid 'epk' in JWE header for ECDH-ES."
445
+ )
414
446
  if epk.get("kty") == "OKP" and epk.get("crv") == "X25519":
415
447
  if not isinstance(ecdh_private_key, x25519.X25519PrivateKey):
416
- raise TypeError("ECDH-ES with X25519 requires an X25519PrivateKey.")
448
+ raise TypeError(
449
+ "ECDH-ES with X25519 requires an X25519PrivateKey."
450
+ )
417
451
  z = ecdh_private_key.exchange(
418
- x25519.X25519PublicKey.from_public_bytes(_b64u_dec(epk["x"]))
452
+ x25519.X25519PublicKey.from_public_bytes(
453
+ _b64u_dec(epk["x"])
454
+ )
419
455
  )
420
456
  elif epk.get("kty") == "EC":
421
457
  crv = epk.get("crv")
@@ -426,7 +462,9 @@ class JweCrypto:
426
462
  }.get(crv)
427
463
  if curve is None:
428
464
  raise ValueError(f"Unsupported EC curve in epk: {crv}")
429
- if not isinstance(ecdh_private_key, ec.EllipticCurvePrivateKey):
465
+ if not isinstance(
466
+ ecdh_private_key, ec.EllipticCurvePrivateKey
467
+ ):
430
468
  raise TypeError(
431
469
  "ECDH-ES with EC requires an EllipticCurvePrivateKey."
432
470
  )
@@ -454,7 +492,9 @@ class JweCrypto:
454
492
  try:
455
493
  pt = zlib.decompress(pt)
456
494
  except Exception as exc: # noqa: BLE001
457
- raise ValueError(f"Failed to decompress (zip=DEF): {exc}") from exc
495
+ raise ValueError(
496
+ f"Failed to decompress (zip=DEF): {exc}"
497
+ ) from exc
458
498
 
459
499
  return JweDecryptResult(header=header, plaintext=pt)
460
500