# Path: jose/backends/base.py
# class Key:
#     """
#     A simple interface for implementing JWK keys.
#     """
# 
#     def __init__(self, key, algorithm):
#         pass
# 
#     def sign(self, msg):
#         raise NotImplementedError()
# 
#     def verify(self, msg, sig):
#         raise NotImplementedError()
# 
#     def public_key(self):
#         raise NotImplementedError()
# 
#     def to_pem(self):
#         raise NotImplementedError()
# 
#     def to_dict(self):
#         raise NotImplementedError()
# 
#     def encrypt(self, plain_text, aad=None):
#         """
#         Encrypt the plain text and generate an auth tag if appropriate
# 
#         Args:
#             plain_text (bytes): Data to encrypt
#             aad (bytes, optional): Authenticated Additional Data if key's algorithm supports auth mode
# 
#         Returns:
#             (bytes, bytes, bytes): IV, cipher text, and auth tag
#         """
#         raise NotImplementedError()
# 
#     def decrypt(self, cipher_text, iv=None, aad=None, tag=None):
#         """
#         Decrypt the cipher text and validate the auth tag if present
#         Args:
#             cipher_text (bytes): Cipher text to decrypt
#             iv (bytes): IV if block mode
#             aad (bytes): Additional Authenticated Data to verify if auth mode
#             tag (bytes): Authentication tag if auth mode
# 
#         Returns:
#             bytes: Decrypted value
#         """
#         raise NotImplementedError()
# 
#     def wrap_key(self, key_data):
#         """
#         Wrap the the plain text key data
# 
#         Args:
#             key_data (bytes): Key data to wrap
# 
#         Returns:
#             bytes: Wrapped key
#         """
#         raise NotImplementedError()
# 
#     def unwrap_key(self, wrapped_key):
#         """
#         Unwrap the the wrapped key data
# 
#         Args:
#             wrapped_key (bytes): Wrapped key data to unwrap
# 
#         Returns:
#             bytes: Unwrapped key
#         """
#         raise NotImplementedError()
# 
# Path: jose/constants.py
# ALGORITHMS = Algorithms()
# 
# Path: jose/exceptions.py
# class JWKError(JOSEError):
#     pass


from jose.backends.base import Key
from jose.constants import ALGORITHMS
from jose.exceptions import JWKError
    from jose.backends import RSAKey  # noqa: F401
    from jose.backends import ECKey  # noqa: F401
    from jose.backends import AESKey  # noqa: F401
    from jose.backends import DIRKey  # noqa: F401
    from jose.backends import HMACKey  # noqa: F401
        from jose.backends import RSAKey  # noqa: F811
        from jose.backends import ECKey  # noqa: F811
        from jose.backends import AESKey  # noqa: F811
        from jose.backends import DIRKey  # noqa: F811
        return AESKey
    elif algorithm == ALGORITHMS.DIR:

        return DIRKey
    return None


def register_key(algorithm, key_class):
    if not issubclass(key_class, Key):
        raise TypeError("Key class is not a subclass of jwk.Key")
    ALGORITHMS.KEYS[algorithm] = key_class
    ALGORITHMS.SUPPORTED.add(algorithm)
    return True


def construct(key_data, algorithm=None):
    """
    Construct a Key object for the given algorithm with the given
    key_data.
    """

    # Allow for pulling the algorithm off of the passed in jwk.
    if not algorithm and isinstance(key_data, dict):
        algorithm = key_data.get("alg", None)

    if not algorithm:
        raise JWKError("Unable to find an algorithm for key: %s" % key_data)

    key_class = get_key(algorithm)
    if not key_class:

# Path: jose/backends/base.py
# class Key:
#     """
#     A simple interface for implementing JWK keys.
#     """
# 
#     def __init__(self, key, algorithm):
#         pass
# 
#     def sign(self, msg):
#         raise NotImplementedError()
# 
#     def verify(self, msg, sig):
#         raise NotImplementedError()
# 
#     def public_key(self):
#         raise NotImplementedError()
# 
#     def to_pem(self):
#         raise NotImplementedError()
# 
#     def to_dict(self):
#         raise NotImplementedError()
# 
#     def encrypt(self, plain_text, aad=None):
#         """
#         Encrypt the plain text and generate an auth tag if appropriate
# 
#         Args:
#             plain_text (bytes): Data to encrypt
#             aad (bytes, optional): Authenticated Additional Data if key's algorithm supports auth mode
# 
#         Returns:
#             (bytes, bytes, bytes): IV, cipher text, and auth tag
#         """
#         raise NotImplementedError()
# 
#     def decrypt(self, cipher_text, iv=None, aad=None, tag=None):
#         """
#         Decrypt the cipher text and validate the auth tag if present
#         Args:
#             cipher_text (bytes): Cipher text to decrypt
#             iv (bytes): IV if block mode
#             aad (bytes): Additional Authenticated Data to verify if auth mode
#             tag (bytes): Authentication tag if auth mode
# 
#         Returns:
#             bytes: Decrypted value
#         """
#         raise NotImplementedError()
# 
#     def wrap_key(self, key_data):
#         """
#         Wrap the the plain text key data
# 
#         Args:
#             key_data (bytes): Key data to wrap
# 
#         Returns:
#             bytes: Wrapped key
#         """
#         raise NotImplementedError()
# 
#     def unwrap_key(self, wrapped_key):
#         """
#         Unwrap the the wrapped key data
# 
#         Args:
#             wrapped_key (bytes): Wrapped key data to unwrap
# 
#         Returns:
#             bytes: Unwrapped key
#         """
#         raise NotImplementedError()
# 
# Path: jose/constants.py
# ALGORITHMS = Algorithms()
# 
# Path: jose/exceptions.py
# class JWKError(JOSEError):
#     pass


# Path: jose/jwk.py
from jose.backends.base import Key
from jose.constants import ALGORITHMS
from jose.exceptions import JWKError
    from jose.backends import RSAKey  # noqa: F401
    from jose.backends import ECKey  # noqa: F401
    from jose.backends import AESKey  # noqa: F401
    from jose.backends import DIRKey  # noqa: F401
    from jose.backends import HMACKey  # noqa: F401
        from jose.backends import RSAKey  # noqa: F811
        from jose.backends import ECKey  # noqa: F811
        from jose.backends import AESKey  # noqa: F811
        from jose.backends import DIRKey  # noqa: F811

        return AESKey
    elif algorithm == ALGORITHMS.DIR:

        return DIRKey
    return None


def register_key(algorithm, key_class):
    if not issubclass(key_class, Key):
        raise TypeError("Key class is not a subclass of jwk.Key")
    ALGORITHMS.KEYS[algorithm] = key_class
    ALGORITHMS.SUPPORTED.add(algorithm)
    return True


def construct(key_data, algorithm=None):
    """
    Construct a Key object for the given algorithm with the given
    key_data.
    """

    # Allow for pulling the algorithm off of the passed in jwk.
    if not algorithm and isinstance(key_data, dict):
        algorithm = key_data.get("alg", None)

    if not algorithm:
        raise JWKError("Unable to find an algorithm for key: %s" % key_data)

    key_class = get_key(algorithm)
    if not key_class:

        raise JWKError("Unable to find an algorithm for key: %s" % key_data)