| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- import hashlib
- import hmac
- import os
- from jose.backends.base import Key
- from jose.constants import ALGORITHMS
- from jose.exceptions import JWKError
- from jose.utils import base64url_decode, base64url_encode
- def get_random_bytes(num_bytes):
- return bytes(os.urandom(num_bytes))
- class HMACKey(Key):
- """
- Performs signing and verification operations using HMAC
- and the specified hash function.
- """
- HASHES = {ALGORITHMS.HS256: hashlib.sha256, ALGORITHMS.HS384: hashlib.sha384, ALGORITHMS.HS512: hashlib.sha512}
- def __init__(self, key, algorithm):
- if algorithm not in ALGORITHMS.HMAC:
- raise JWKError("hash_alg: %s is not a valid hash algorithm" % algorithm)
- self._algorithm = algorithm
- self._hash_alg = self.HASHES.get(algorithm)
- if isinstance(key, dict):
- self.prepared_key = self._process_jwk(key)
- return
- if not isinstance(key, str) and not isinstance(key, bytes):
- raise JWKError("Expecting a string- or bytes-formatted key.")
- if isinstance(key, str):
- key = key.encode("utf-8")
- invalid_strings = [
- b"-----BEGIN PUBLIC KEY-----",
- b"-----BEGIN RSA PUBLIC KEY-----",
- b"-----BEGIN CERTIFICATE-----",
- b"ssh-rsa",
- ]
- if any(string_value in key for string_value in invalid_strings):
- raise JWKError(
- "The specified key is an asymmetric key or x509 certificate and"
- " should not be used as an HMAC secret."
- )
- self.prepared_key = key
- def _process_jwk(self, jwk_dict):
- if not jwk_dict.get("kty") == "oct":
- raise JWKError("Incorrect key type. Expected: 'oct', Received: %s" % jwk_dict.get("kty"))
- k = jwk_dict.get("k")
- k = k.encode("utf-8")
- k = bytes(k)
- k = base64url_decode(k)
- return k
- def sign(self, msg):
- return hmac.new(self.prepared_key, msg, self._hash_alg).digest()
- def verify(self, msg, sig):
- return hmac.compare_digest(sig, self.sign(msg))
- def to_dict(self):
- return {
- "alg": self._algorithm,
- "kty": "oct",
- "k": base64url_encode(self.prepared_key).decode("ASCII"),
- }
|