# Path: jose/constants.py
# ALGORITHMS = Algorithms()
# 
# Path: jose/exceptions.py
# class JWEError(JOSEError):
#     """Base error for all JWE errors"""
# 
#     pass
# 
# class JWKError(JOSEError):
#     pass
# 
# Path: jose/utils.py
# def base64_to_long(data):
#     if isinstance(data, str):
#         data = data.encode("ascii")
# 
#     # urlsafe_b64decode will happily convert b64encoded data
#     _d = base64.urlsafe_b64decode(bytes(data) + b"==")
#     return int_arr_to_long(struct.unpack("%sB" % len(_d), _d))
# 
# def base64url_decode(input):
#     """Helper method to base64url_decode a string.
# 
#     Args:
#         input (str): A base64url_encoded string to decode.
# 
#     """
#     rem = len(input) % 4
# 
#     if rem > 0:
#         input += b"=" * (4 - rem)
# 
#     return base64.urlsafe_b64decode(input)
# 
# def base64url_encode(input):
#     """Helper method to base64url_encode a string.
# 
#     Args:
#         input (str): A base64url_encoded string to encode.
# 
#     """
#     return base64.urlsafe_b64encode(input).replace(b"=", b"")
# 
# def ensure_binary(s):
#     """Coerce **s** to bytes."""
# 
#     if isinstance(s, bytes):
#         return s
#     if isinstance(s, str):
#         return s.encode("utf-8", "strict")
#     raise TypeError(f"not expecting type '{type(s)}'")
# 
# def long_to_base64(data, size=0):
#     return base64.urlsafe_b64encode(long_to_bytes(data, size)).strip(b"=")
# 
# 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()


import math
import warnings
from cryptography.exceptions import InvalidSignature, InvalidTag
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.bindings.openssl.binding import Binding
from cryptography.hazmat.primitives import hashes, hmac, serialization
from cryptography.hazmat.primitives.asymmetric import ec, padding, rsa
from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature, encode_dss_signature
from cryptography.hazmat.primitives.ciphers import Cipher, aead, algorithms, modes
from cryptography.hazmat.primitives.keywrap import InvalidUnwrap, aes_key_unwrap, aes_key_wrap
from cryptography.hazmat.primitives.padding import PKCS7
from cryptography.hazmat.primitives.serialization import load_pem_private_key, load_pem_public_key
from cryptography.utils import int_to_bytes
from cryptography.x509 import load_pem_x509_certificate
from ..constants import ALGORITHMS
from ..exceptions import JWEError, JWKError
from ..utils import base64_to_long, base64url_decode, base64url_encode, ensure_binary, long_to_base64
from .base import Key
                    raise ValueError("tag cannot be None")
                cipher = aead.AESGCM(self._key)
                cipher_text_and_tag = cipher_text + tag
                try:
                    plain_text = cipher.decrypt(iv, cipher_text_and_tag, aad)
                except InvalidTag:
                    raise JWEError("Invalid JWE Auth Tag")
            else:
                cipher = Cipher(algorithms.AES(self._key), mode, backend=default_backend())
                decryptor = cipher.decryptor()
                padded_plain_text = decryptor.update(cipher_text)
                padded_plain_text += decryptor.finalize()
                unpadder = PKCS7(algorithms.AES.block_size).unpadder()
                plain_text = unpadder.update(padded_plain_text)
                plain_text += unpadder.finalize()

            return plain_text
        except Exception as e:
            raise JWEError(e)

    def wrap_key(self, key_data):
        key_data = ensure_binary(key_data)
        cipher_text = aes_key_wrap(self._key, key_data, default_backend())
        return cipher_text  # IV, cipher text, auth tag

    def unwrap_key(self, wrapped_key):
        wrapped_key = ensure_binary(wrapped_key)
        try:
            plain_text = aes_key_unwrap(self._key, wrapped_key, default_backend())
        except InvalidUnwrap as cause:

# Path: jose/constants.py
# ALGORITHMS = Algorithms()
# 
# Path: jose/exceptions.py
# class JWEError(JOSEError):
#     """Base error for all JWE errors"""
# 
#     pass
# 
# class JWKError(JOSEError):
#     pass
# 
# Path: jose/utils.py
# def base64_to_long(data):
#     if isinstance(data, str):
#         data = data.encode("ascii")
# 
#     # urlsafe_b64decode will happily convert b64encoded data
#     _d = base64.urlsafe_b64decode(bytes(data) + b"==")
#     return int_arr_to_long(struct.unpack("%sB" % len(_d), _d))
# 
# def base64url_decode(input):
#     """Helper method to base64url_decode a string.
# 
#     Args:
#         input (str): A base64url_encoded string to decode.
# 
#     """
#     rem = len(input) % 4
# 
#     if rem > 0:
#         input += b"=" * (4 - rem)
# 
#     return base64.urlsafe_b64decode(input)
# 
# def base64url_encode(input):
#     """Helper method to base64url_encode a string.
# 
#     Args:
#         input (str): A base64url_encoded string to encode.
# 
#     """
#     return base64.urlsafe_b64encode(input).replace(b"=", b"")
# 
# def ensure_binary(s):
#     """Coerce **s** to bytes."""
# 
#     if isinstance(s, bytes):
#         return s
#     if isinstance(s, str):
#         return s.encode("utf-8", "strict")
#     raise TypeError(f"not expecting type '{type(s)}'")
# 
# def long_to_base64(data, size=0):
#     return base64.urlsafe_b64encode(long_to_bytes(data, size)).strip(b"=")
# 
# 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/backends/cryptography_backend.py
import math
import warnings
from cryptography.exceptions import InvalidSignature, InvalidTag
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.bindings.openssl.binding import Binding
from cryptography.hazmat.primitives import hashes, hmac, serialization
from cryptography.hazmat.primitives.asymmetric import ec, padding, rsa
from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature, encode_dss_signature
from cryptography.hazmat.primitives.ciphers import Cipher, aead, algorithms, modes
from cryptography.hazmat.primitives.keywrap import InvalidUnwrap, aes_key_unwrap, aes_key_wrap
from cryptography.hazmat.primitives.padding import PKCS7
from cryptography.hazmat.primitives.serialization import load_pem_private_key, load_pem_public_key
from cryptography.utils import int_to_bytes
from cryptography.x509 import load_pem_x509_certificate
from ..constants import ALGORITHMS
from ..exceptions import JWEError, JWKError
from ..utils import base64_to_long, base64url_decode, base64url_encode, ensure_binary, long_to_base64
from .base import Key

                    raise ValueError("tag cannot be None")
                cipher = aead.AESGCM(self._key)
                cipher_text_and_tag = cipher_text + tag
                try:
                    plain_text = cipher.decrypt(iv, cipher_text_and_tag, aad)
                except InvalidTag:
                    raise JWEError("Invalid JWE Auth Tag")
            else:
                cipher = Cipher(algorithms.AES(self._key), mode, backend=default_backend())
                decryptor = cipher.decryptor()
                padded_plain_text = decryptor.update(cipher_text)
                padded_plain_text += decryptor.finalize()
                unpadder = PKCS7(algorithms.AES.block_size).unpadder()
                plain_text = unpadder.update(padded_plain_text)
                plain_text += unpadder.finalize()

            return plain_text
        except Exception as e:
            raise JWEError(e)

    def wrap_key(self, key_data):
        key_data = ensure_binary(key_data)
        cipher_text = aes_key_wrap(self._key, key_data, default_backend())
        return cipher_text  # IV, cipher text, auth tag

    def unwrap_key(self, wrapped_key):
        wrapped_key = ensure_binary(wrapped_key)
        try:
            plain_text = aes_key_unwrap(self._key, wrapped_key, default_backend())
        except InvalidUnwrap as cause:

            raise JWEError(cause)