Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
repos:
- repo: https://github.com/asottile/pyupgrade
rev: v3.22.0
hooks:
- id: pyupgrade
args: [--py311-plus]

- repo: https://github.com/psf/black
rev: 25.1.0
hooks:
Expand Down
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Unreleased
- **Breaking change**: Drop support for Python 3.10.
- Correct COSE signing header annotations to accept dictionaries and ResolvedHeader in strict type checkers.
- Annotate factory class methods (``COSE.new``, ``CWT.new``, ``Claims.new``, ``Claims.from_json``, ``Signer.new``, ``Signer.from_jwk``, ``Signer.from_pem``, ``COSEMessage.loads``, etc.) to return ``Self`` for strict type checkers.
- Modernize type annotations to PEP 604/585 syntax (e.g. ``X | None``, ``dict[str, Any]``) and add pyupgrade (``--py311-plus``) to pre-commit.
- Follow RFC 9597 (CWT Claims in COSE Headers), which supersedes draft-ietf-cose-cwt-claims-in-headers-06.
- **Breaking change**: ``COSEHeaders.CWT_CLAIMS`` is now ``15``, the label assigned by IANA in RFC 9597 (it was ``13``, the label requested by draft-06). IANA assigned ``13`` to the unrelated ``kcwt`` header parameter (RFC 9528), so ``13`` is no longer interpreted as CWT Claims. Tokens using the draft label are no longer cross-checked by ``CWT.decode()``.
- ``CWT.decode()`` now checks the CWT Claims header parameter in unprotected headers and in every COSE layer of a nested CWT, not only in the protected header of the innermost layer.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1323,7 +1323,7 @@ except Exception as err:
print(err)
```

A raw CWT structure (Dict[int, Any]) can also be used as follows:
A raw CWT structure (dict[int, Any]) can also be used as follows:

```py
import cwt
Expand Down
8 changes: 4 additions & 4 deletions cwt/algs/asymmetric.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, List
from typing import Any

from cryptography.x509 import Certificate, DNSName, load_der_x509_certificate
from cryptography.x509.oid import NameOID
Expand All @@ -9,12 +9,12 @@


class AsymmetricKey(COSEKeyInterface):
def __init__(self, params: Dict[int, Any]):
def __init__(self, params: dict[int, Any]):
super().__init__(params)

self._key: Any = b""
self._cert: Certificate = None
self._intermediates: List[Certificate] = []
self._intermediates: list[Certificate] = []

if 33 in params:
if not isinstance(params[33], (bytes, list)):
Expand All @@ -26,7 +26,7 @@ def __init__(self, params: Dict[int, Any]):
self._intermediates.append(load_der_x509_certificate(c))
return

def validate_certificate(self, ca_certs: List[Certificate]) -> bool:
def validate_certificate(self, ca_certs: list[Certificate]) -> bool:
if not ca_certs:
raise ValueError("ca_certs should be set.")
if not self._cert:
Expand Down
30 changes: 15 additions & 15 deletions cwt/algs/ec2.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, Optional, Union
from typing import Any

import cryptography
from cryptography.hazmat.primitives import hashes
Expand Down Expand Up @@ -38,7 +38,7 @@ class EC2Key(AsymmetricKey):
COSE_KEY_OPERATION_VALUES["deriveBits"],
]

def __init__(self, params: Dict[int, Any]):
def __init__(self, params: dict[int, Any]):
super().__init__(params)
self._public_key: Any = None
self._private_key: Any = None
Expand Down Expand Up @@ -72,7 +72,7 @@ def __init__(self, params: Dict[int, Any]):

# Validate alg and key_ops.
if self._key_ops:
if set(self._key_ops) & set([3, 4, 5, 6, 9, 10]):
if set(self._key_ops) & {3, 4, 5, 6, 9, 10}:
raise ValueError("Unknown or not permissible key_ops(4) for EC2.")

if not self._alg and not self._key_ops:
Expand All @@ -99,9 +99,9 @@ def __init__(self, params: Dict[int, Any]):
if self._key_ops:
if -4 in params:
# private key for signing.
if not (set(self._key_ops) & set([1, 2])):
if not (set(self._key_ops) & {1, 2}):
raise ValueError("Invalid key_ops for signing key.")
if set(self._key_ops) & set([7, 8]):
if set(self._key_ops) & {7, 8}:
raise ValueError("Signing key should not be used for key derivation.")
else:
# public key for signing.
Expand All @@ -119,9 +119,9 @@ def __init__(self, params: Dict[int, Any]):
if self._key_ops:
if -4 in params:
# private key for key derivation.
if not (set(self._key_ops) & set([7, 8])):
if not (set(self._key_ops) & {7, 8}):
raise ValueError("Invalid key_ops for key derivation.")
if set(self._key_ops) & set([1, 2]):
if set(self._key_ops) & {1, 2}:
raise ValueError("ECDHE key should not be used for signing.")
else:
# public key for key derivation.
Expand All @@ -147,9 +147,9 @@ def __init__(self, params: Dict[int, Any]):
else:
if -4 in params:
# private key.
if set(self._key_ops) & set([1, 2]):
if set(self._key_ops) & {1, 2}:
# private key for signing.
if set(self._key_ops) & set([7, 8]):
if set(self._key_ops) & {7, 8}:
raise ValueError("EC2 Private key should not be used for both signing and key derivation.")
if self._crv == 1:
self._alg = -7 # ES256
Expand All @@ -164,7 +164,7 @@ def __init__(self, params: Dict[int, Any]):
if 2 in self._key_ops:
if len(self._key_ops) > 1:
raise ValueError("Invalid key_ops for public key.")
elif not (set(self._key_ops) & set([7, 8])):
elif not (set(self._key_ops) & {7, 8}):
raise ValueError("Invalid key_ops for public key.")

if self._alg in COSE_ALGORITHMS_CKDM_KEY_AGREEMENT_ES.values():
Expand Down Expand Up @@ -223,9 +223,9 @@ def __init__(self, params: Dict[int, Any]):
return

@staticmethod
def to_cose_key(k: Union[EllipticCurvePrivateKey, EllipticCurvePublicKey]) -> Dict[int, Any]:
def to_cose_key(k: EllipticCurvePrivateKey | EllipticCurvePublicKey) -> dict[int, Any]:
key_len: int = 32
cose_key: Dict[int, Any] = {}
cose_key: dict[int, Any] = {}

cose_key[1] = COSE_KEY_TYPES["EC2"]
if not hasattr(k, "curve"):
Expand All @@ -250,14 +250,14 @@ def to_cose_key(k: Union[EllipticCurvePrivateKey, EllipticCurvePublicKey]) -> Di
return cose_key

@property
def key(self) -> Union[EllipticCurvePublicKey, EllipticCurvePrivateKey]:
def key(self) -> EllipticCurvePublicKey | EllipticCurvePrivateKey:
return self._key

@property
def crv(self) -> int:
return self._crv

def to_dict(self) -> Dict[int, Any]:
def to_dict(self) -> dict[int, Any]:
res = super().to_dict()
res[-1] = self._crv
res[-2] = self._x
Expand Down Expand Up @@ -288,7 +288,7 @@ def verify(self, msg: bytes, sig: bytes):
except ValueError as err:
raise VerifyError("Invalid signature.") from err

def derive_bytes(self, length: int, material: bytes = b"", info: bytes = b"", public_key: Optional[Any] = None) -> bytes:
def derive_bytes(self, length: int, material: bytes = b"", info: bytes = b"", public_key: Any | None = None) -> bytes:
if self._public_key:
raise ValueError("Public key cannot be used for key derivation.")
if not public_key:
Expand Down
70 changes: 35 additions & 35 deletions cwt/algs/okp.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, Optional, Union
from typing import Any

import cryptography
from cryptography.hazmat.primitives import hashes
Expand Down Expand Up @@ -46,7 +46,7 @@ class OKPKey(AsymmetricKey):
COSE_KEY_OPERATION_VALUES["deriveBits"],
]

def __init__(self, params: Dict[int, Any]):
def __init__(self, params: dict[int, Any]):
super().__init__(params)
self._public_key: Any = None
self._private_key: Any = None
Expand Down Expand Up @@ -90,16 +90,16 @@ def __init__(self, params: Dict[int, Any]):

# Validate alg and key_ops.
if self._key_ops:
if set(self._key_ops) & set([3, 4, 5, 6, 9, 10]):
if set(self._key_ops) & {3, 4, 5, 6, 9, 10}:
raise ValueError("Unknown or not permissible key_ops(4) for OKP.")
if self._alg:
if self._alg in COSE_ALGORITHMS_SIG_OKP.values():
if self._key_ops:
if -4 in params:
# private key for signing.
if not (set(self._key_ops) & set([1, 2])):
if not (set(self._key_ops) & {1, 2}):
raise ValueError("Invalid key_ops for signing key.")
if set(self._key_ops) & set([7, 8]):
if set(self._key_ops) & {7, 8}:
raise ValueError("Signing key should not be used for key derivation.")
else:
# public key for signing.
Expand All @@ -124,9 +124,9 @@ def __init__(self, params: Dict[int, Any]):
if self._key_ops:
if -4 in params:
# private key for key derivation.
if not (set(self._key_ops) & set([7, 8])):
if not (set(self._key_ops) & {7, 8}):
raise ValueError("Invalid key_ops for key derivation.")
if set(self._key_ops) & set([1, 2]):
if set(self._key_ops) & {1, 2}:
raise ValueError("Private key for ECDHE should not be used for signing.")
else:
# public key for key derivation.
Expand All @@ -140,17 +140,17 @@ def __init__(self, params: Dict[int, Any]):
if self._crv in [4, 5]: # X25519/X448
if self._key_ops:
# private key for key derivation.
if not (set(self._key_ops) & set([7, 8])):
if not (set(self._key_ops) & {7, 8}):
raise ValueError("Invalid key_ops for X25519/448 private key.")
if set(self._key_ops) & set([1, 2]):
if set(self._key_ops) & {1, 2}:
raise ValueError("Invalid key_ops for X25519/448 private key.")
else:
self._key_ops = [7, 8]
else: # Ed25519/Ed448
if self._key_ops:
if not (set(self._key_ops) & set([1, 2])):
if not (set(self._key_ops) & {1, 2}):
raise ValueError("Invalid key_ops for Ed25519/448 private key.")
if set(self._key_ops) & set([7, 8]):
if set(self._key_ops) & {7, 8}:
raise ValueError("Invalid key_ops for Ed25519/448 private key.")
else:
self._key_ops = [1, 2]
Expand Down Expand Up @@ -213,18 +213,18 @@ def __init__(self, params: Dict[int, Any]):

@staticmethod
def to_cose_key(
k: Union[
Ed448PrivateKey,
Ed448PublicKey,
Ed25519PrivateKey,
Ed25519PublicKey,
X448PrivateKey,
X448PublicKey,
X25519PrivateKey,
X25519PublicKey,
],
) -> Dict[int, Any]:
cose_key: Dict[int, Any] = {}
k: (
Ed448PrivateKey
| Ed448PublicKey
| Ed25519PrivateKey
| Ed25519PublicKey
| X448PrivateKey
| X448PublicKey
| X25519PrivateKey
| X25519PublicKey
),
) -> dict[int, Any]:
cose_key: dict[int, Any] = {}

cose_key[1] = COSE_KEY_TYPES["OKP"]
cose_key[-1] = 6 # Ed25519
Expand Down Expand Up @@ -263,23 +263,23 @@ def to_cose_key(
@property
def key(
self,
) -> Union[
Ed448PrivateKey,
Ed448PublicKey,
Ed25519PrivateKey,
Ed25519PublicKey,
X448PrivateKey,
X448PublicKey,
X25519PrivateKey,
X25519PublicKey,
]:
) -> (
Ed448PrivateKey
| Ed448PublicKey
| Ed25519PrivateKey
| Ed25519PublicKey
| X448PrivateKey
| X448PublicKey
| X25519PrivateKey
| X25519PublicKey
):
return self._key

@property
def crv(self) -> int:
return self._crv

def to_dict(self) -> Dict[int, Any]:
def to_dict(self) -> dict[int, Any]:
res = super().to_dict()
res[-1] = self._crv
res[-2] = self._x
Expand All @@ -304,7 +304,7 @@ def verify(self, msg: bytes, sig: bytes):
except cryptography.exceptions.InvalidSignature as err:
raise VerifyError("Failed to verify.") from err

def derive_bytes(self, length: int, material: bytes = b"", info: bytes = b"", public_key: Optional[Any] = None) -> bytes:
def derive_bytes(self, length: int, material: bytes = b"", info: bytes = b"", public_key: Any | None = None) -> bytes:
if self._public_key:
raise ValueError("Public key cannot be used for key derivation.")
if not public_key:
Expand Down
6 changes: 3 additions & 3 deletions cwt/algs/raw.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from typing import Any, Dict
from typing import Any

from ..cose_key_interface import COSEKeyInterface


class RawKey(COSEKeyInterface):
def __init__(self, params: Dict[int, Any]):
def __init__(self, params: dict[int, Any]):
super().__init__(params)

self._key: bytes = b""
Expand All @@ -28,7 +28,7 @@ def key(self) -> bytes:
def to_bytes(self) -> bytes:
return self._key

def to_dict(self) -> Dict[int, Any]:
def to_dict(self) -> dict[int, Any]:
res = super().to_dict()
res[-1] = self._key
return res
6 changes: 3 additions & 3 deletions cwt/algs/rsa.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict
from typing import Any

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
Expand All @@ -23,7 +23,7 @@ class RSAKey(AsymmetricKey):
COSE_KEY_OPERATION_VALUES["verify"],
]

def __init__(self, params: Dict[int, Any]):
def __init__(self, params: dict[int, Any]):
super().__init__(params)

self._key: Any = None
Expand Down Expand Up @@ -115,7 +115,7 @@ def __init__(self, params: Dict[int, Any]):
self._key = private_numbers.private_key()
return

def to_dict(self) -> Dict[int, Any]:
def to_dict(self) -> dict[int, Any]:
return self._dict

def sign(self, msg: bytes) -> bytes:
Expand Down
Loading
Loading