# 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/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 long_to_base64(data, size=0):
#     return base64.urlsafe_b64encode(long_to_bytes(data, size)).strip(b"=")


import hashlib
import ecdsa
from jose.backends.base import Key
from jose.constants import ALGORITHMS
from jose.exceptions import JWKError
from jose.utils import base64_to_long, long_to_base64
class ECDSAECKey(Key):
    """
    Performs signing and verification operations using
    ECDSA and the specified hash function

    This class requires the ecdsa package to be installed.

    This is based off of the implementation in PyJWT 0.3.2
    """

    SHA256 = hashlib.sha256
    SHA384 = hashlib.sha384
    SHA512 = hashlib.sha512

    CURVE_MAP = {
        SHA256: ecdsa.curves.NIST256p,
        SHA384: ecdsa.curves.NIST384p,
        SHA512: ecdsa.curves.NIST521p,
    }
    CURVE_NAMES = (
        (ecdsa.curves.NIST256p, "P-256"),
        (ecdsa.curves.NIST384p, "P-384"),
        (ecdsa.curves.NIST521p, "P-521"),
    )

    def __init__(self, key, algorithm):
        if algorithm not in ALGORITHMS.EC:
            raise JWKError("hash_alg: %s is not a valid hash algorithm" % algorithm)

        self.hash_alg = {

# 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/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 long_to_base64(data, size=0):
#     return base64.urlsafe_b64encode(long_to_bytes(data, size)).strip(b"=")


# Path: jose/backends/ecdsa_backend.py
import hashlib
import ecdsa
from jose.backends.base import Key
from jose.constants import ALGORITHMS
from jose.exceptions import JWKError
from jose.utils import base64_to_long, long_to_base64

class ECDSAECKey(Key):
    """
    Performs signing and verification operations using
    ECDSA and the specified hash function

    This class requires the ecdsa package to be installed.

    This is based off of the implementation in PyJWT 0.3.2
    """

    SHA256 = hashlib.sha256
    SHA384 = hashlib.sha384
    SHA512 = hashlib.sha512

    CURVE_MAP = {
        SHA256: ecdsa.curves.NIST256p,
        SHA384: ecdsa.curves.NIST384p,
        SHA512: ecdsa.curves.NIST521p,
    }
    CURVE_NAMES = (
        (ecdsa.curves.NIST256p, "P-256"),
        (ecdsa.curves.NIST384p, "P-384"),
        (ecdsa.curves.NIST521p, "P-521"),
    )

    def __init__(self, key, algorithm):
        if algorithm not in ALGORITHMS.EC:
            raise JWKError("hash_alg: %s is not a valid hash algorithm" % algorithm)

        self.hash_alg = {

            ALGORITHMS.ES256: self.SHA256,