summaryrefslogtreecommitdiff
path: root/jwt/algorithms.py
diff options
context:
space:
mode:
authorStephen Rosen <sirosen@globus.org>2022-11-02 06:01:52 -0500
committerGitHub <noreply@github.com>2022-11-02 17:01:52 +0600
commit00cd759d86aae24176ead7bdbed273a07532443e (patch)
tree34f5fd7e5d0c55299fc5c8685fb558aeebaf9f4a /jwt/algorithms.py
parent345549567dbb58fd7bf901392cf6b1a626f36e24 (diff)
downloadpyjwt-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.py23
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