diff options
author | Stephen Rosen <sirosen@globus.org> | 2022-11-02 06:01:52 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-02 17:01:52 +0600 |
commit | 00cd759d86aae24176ead7bdbed273a07532443e (patch) | |
tree | 34f5fd7e5d0c55299fc5c8685fb558aeebaf9f4a /jwt/algorithms.py | |
parent | 345549567dbb58fd7bf901392cf6b1a626f36e24 (diff) | |
download | pyjwt-00cd759d86aae24176ead7bdbed273a07532443e.tar.gz |
Add `Algorithm.compute_hash_digest` and use it to implement at_hash validation example (#775)
* Add compute_hash_digest to Algorithm objects
`Algorithm.compute_hash_digest` is defined as a method which inspects
the object to see that it has the requisite attributes, `hash_alg`.
If `hash_alg` is not set, then the method raises a
NotImplementedError. This applies to classes like NoneAlgorithm.
If `hash_alg` is set, then it is checked for
```
has_crypto # is cryptography available?
and isinstance(hash_alg, type)
and issubclass(hash_alg, hashes.HashAlgorithm)
```
to see which API for computing a digest is appropriate --
`hashlib` vs `cryptography.hazmat.primitives.hashes`.
These checks could be avoided at runtime if it were necessary to
optimize further (e.g. attach compute_hash_digest methods to classes
with a class decorator) but this is not clearly a worthwhile
optimization. Such perf tuning is intentionally omitted for now.
* Add doc example of OIDC login flow
The goal of this doc example is to demonstrate usage of
`get_algorithm_by_name` and `compute_hash_digest` for the purpose of
`at_hash` validation. It is not meant to be a "guaranteed correct" and
spec-compliant example.
closes #314
Diffstat (limited to 'jwt/algorithms.py')
-rw-r--r-- | jwt/algorithms.py | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/jwt/algorithms.py b/jwt/algorithms.py index 93fadf4..4fae441 100644 --- a/jwt/algorithms.py +++ b/jwt/algorithms.py @@ -18,6 +18,7 @@ from .utils import ( try: import cryptography.exceptions from cryptography.exceptions import InvalidSignature + from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import ec, padding from cryptography.hazmat.primitives.asymmetric.ec import ( @@ -111,6 +112,28 @@ class Algorithm: The interface for an algorithm used to sign and verify tokens. """ + def compute_hash_digest(self, bytestr: bytes) -> bytes: + """ + Compute a hash digest using the specified algorithm's hash algorithm. + + If there is no hash algorithm, raises a NotImplementedError. + """ + # lookup self.hash_alg if defined in a way that mypy can understand + hash_alg = getattr(self, "hash_alg", None) + if hash_alg is None: + raise NotImplementedError + + if ( + has_crypto + and isinstance(hash_alg, type) + and issubclass(hash_alg, hashes.HashAlgorithm) + ): + digest = hashes.Hash(hash_alg(), backend=default_backend()) + digest.update(bytestr) + return digest.finalize() + else: + return hash_alg(bytestr).digest() + def prepare_key(self, key): """ Performs necessary validation and conversions on the key and returns |