# Path: subspace/pyelliptic/openssl.py
# class CipherName:
# class _OpenSSL:
#     def __init__(self, name, pointer, blocksize):
#     def __str__(self):
#     def get_pointer(self):
#     def get_name(self):
#     def get_blocksize(self):
#     def __init__(self, library):
#     def _set_ciphers(self):
#     def _set_curves(self):
#     def BN_num_bytes(self, x):
#     def get_cipher(self, name):
#     def get_curve(self, name):
#     def get_curve_by_id(self, id):
#     def rand(self, size):
#     def malloc(self, data, size):
# 
# Path: subspace/pyelliptic/cipher.py
# class Cipher:
#     """
#     Symmetric encryption
# 
#         import pyelliptic
#         iv = pyelliptic.Cipher.gen_IV('aes-256-cfb')
#         ctx = pyelliptic.Cipher("secretkey", iv, 1, ciphername='aes-256-cfb')
#         ciphertext = ctx.update('test1')
#         ciphertext += ctx.update('test2')
#         ciphertext += ctx.final()
# 
#         ctx2 = pyelliptic.Cipher("secretkey", iv, 0, ciphername='aes-256-cfb')
#         print ctx2.ciphering(ciphertext)
#     """
#     def __init__(self, key, iv, do, ciphername='aes-256-cbc'):
#         """
#         do == 1 => Encrypt; do == 0 => Decrypt
#         """
#         self.cipher = OpenSSL.get_cipher(ciphername)
#         self.ctx = OpenSSL.EVP_CIPHER_CTX_new()
#         if do == 1 or do == 0:
#             k = OpenSSL.malloc(key, len(key))
#             IV = OpenSSL.malloc(iv, len(iv))
#             OpenSSL.EVP_CipherInit_ex(
#                 self.ctx, self.cipher.get_pointer(), 0, k, IV, do)
#         else:
#             raise Exception("RTFM ...")
# 
#     @staticmethod
#     def get_all_cipher():
#         """
#         static method, returns all ciphers available
#         """
#         return OpenSSL.cipher_algo.keys()
# 
#     @staticmethod
#     def get_blocksize(ciphername):
#         cipher = OpenSSL.get_cipher(ciphername)
#         return cipher.get_blocksize()
# 
#     @staticmethod
#     def gen_IV(ciphername):
#         cipher = OpenSSL.get_cipher(ciphername)
#         return OpenSSL.rand(cipher.get_blocksize())
# 
#     def update(self, input):
#         i = OpenSSL.c_int(0)
#         buffer = OpenSSL.malloc(b"", len(input) + self.cipher.get_blocksize())
#         inp = OpenSSL.malloc(input, len(input))
#         if OpenSSL.EVP_CipherUpdate(self.ctx, OpenSSL.byref(buffer),
#                                     OpenSSL.byref(i), inp, len(input)) == 0:
#             raise Exception("[OpenSSL] EVP_CipherUpdate FAIL ...")
#         return buffer.raw[0:i.value]
# 
#     def final(self):
#         i = OpenSSL.c_int(0)
#         buffer = OpenSSL.malloc(b"", self.cipher.get_blocksize())
#         if (OpenSSL.EVP_CipherFinal_ex(self.ctx, OpenSSL.byref(buffer),
#                                        OpenSSL.byref(i))) == 0:
#             raise Exception("[OpenSSL] EVP_CipherFinal_ex FAIL ...")
#         return buffer.raw[0:i.value]
# 
#     def ciphering(self, input):
#         """
#         Do update and final in one method
#         """
#         buff = self.update(input)
#         return buff + self.final()
# 
#     def __del__(self):
#         OpenSSL.EVP_CIPHER_CTX_cleanup(self.ctx)
#         OpenSSL.EVP_CIPHER_CTX_free(self.ctx)
# 
# Path: subspace/pyelliptic/hash.py
# def hmac_sha256(k, m):
#     """
#     Compute the key and the message with HMAC SHA5256
#     """
#     key = OpenSSL.malloc(k, len(k))
#     d = OpenSSL.malloc(m, len(m))
#     md = OpenSSL.malloc(0, 32)
#     i = OpenSSL.pointer(OpenSSL.c_int(0))
#     OpenSSL.HMAC(OpenSSL.EVP_sha256(), key, len(k), d, len(m), md, i)
#     return md.raw
# 
# def equals(a, b):
#     if isinstance(a, str):
#         return _equals_str(a, b)
#     else:
#         return _equals_bytes(a, b)


from hashlib import sha512
from .openssl import OpenSSL
from .cipher import Cipher
from .hash import hmac_sha256, equals
from struct import pack, unpack

    @staticmethod
    def raw_encrypt(data, pubkey_x, pubkey_y, curve='sect283r1',
                    ephemcurve=None, ciphername='aes-256-cbc'):
        if ephemcurve is None:
            ephemcurve = curve
        ephem = ECC(curve=ephemcurve)
        key = sha512(ephem.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest()
        key_e, key_m = key[:32], key[32:]
        pubkey = ephem.get_pubkey()
        iv = OpenSSL.rand(OpenSSL.get_cipher(ciphername).get_blocksize())
        ctx = Cipher(key_e, iv, 1, ciphername)
        ciphertext = iv + ephem.pubkey_x + ephem.pubkey_y + ctx.ciphering(data)
        mac = hmac_sha256(key_m, ciphertext)
        return ciphertext + mac

    def decrypt(self, data, ciphername='aes-256-cbc'):
        """
        Decrypt data with ECIES method using the local private key
        """
        blocksize = OpenSSL.get_cipher(ciphername).get_blocksize()
        iv = data[:blocksize]
        i = blocksize
        curve, pubkey_x, pubkey_y, i2 = ECC._decode_keys(data[i:])
        i += i2
        ciphertext = data[i:len(data)-32]
        i += len(ciphertext)
        mac = data[i:]
        key = sha512(self.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest()
        key_e, key_m = key[:32], key[32:]

# Path: subspace/pyelliptic/openssl.py
# class CipherName:
# class _OpenSSL:
#     def __init__(self, name, pointer, blocksize):
#     def __str__(self):
#     def get_pointer(self):
#     def get_name(self):
#     def get_blocksize(self):
#     def __init__(self, library):
#     def _set_ciphers(self):
#     def _set_curves(self):
#     def BN_num_bytes(self, x):
#     def get_cipher(self, name):
#     def get_curve(self, name):
#     def get_curve_by_id(self, id):
#     def rand(self, size):
#     def malloc(self, data, size):
# 
# Path: subspace/pyelliptic/cipher.py
# class Cipher:
#     """
#     Symmetric encryption
# 
#         import pyelliptic
#         iv = pyelliptic.Cipher.gen_IV('aes-256-cfb')
#         ctx = pyelliptic.Cipher("secretkey", iv, 1, ciphername='aes-256-cfb')
#         ciphertext = ctx.update('test1')
#         ciphertext += ctx.update('test2')
#         ciphertext += ctx.final()
# 
#         ctx2 = pyelliptic.Cipher("secretkey", iv, 0, ciphername='aes-256-cfb')
#         print ctx2.ciphering(ciphertext)
#     """
#     def __init__(self, key, iv, do, ciphername='aes-256-cbc'):
#         """
#         do == 1 => Encrypt; do == 0 => Decrypt
#         """
#         self.cipher = OpenSSL.get_cipher(ciphername)
#         self.ctx = OpenSSL.EVP_CIPHER_CTX_new()
#         if do == 1 or do == 0:
#             k = OpenSSL.malloc(key, len(key))
#             IV = OpenSSL.malloc(iv, len(iv))
#             OpenSSL.EVP_CipherInit_ex(
#                 self.ctx, self.cipher.get_pointer(), 0, k, IV, do)
#         else:
#             raise Exception("RTFM ...")
# 
#     @staticmethod
#     def get_all_cipher():
#         """
#         static method, returns all ciphers available
#         """
#         return OpenSSL.cipher_algo.keys()
# 
#     @staticmethod
#     def get_blocksize(ciphername):
#         cipher = OpenSSL.get_cipher(ciphername)
#         return cipher.get_blocksize()
# 
#     @staticmethod
#     def gen_IV(ciphername):
#         cipher = OpenSSL.get_cipher(ciphername)
#         return OpenSSL.rand(cipher.get_blocksize())
# 
#     def update(self, input):
#         i = OpenSSL.c_int(0)
#         buffer = OpenSSL.malloc(b"", len(input) + self.cipher.get_blocksize())
#         inp = OpenSSL.malloc(input, len(input))
#         if OpenSSL.EVP_CipherUpdate(self.ctx, OpenSSL.byref(buffer),
#                                     OpenSSL.byref(i), inp, len(input)) == 0:
#             raise Exception("[OpenSSL] EVP_CipherUpdate FAIL ...")
#         return buffer.raw[0:i.value]
# 
#     def final(self):
#         i = OpenSSL.c_int(0)
#         buffer = OpenSSL.malloc(b"", self.cipher.get_blocksize())
#         if (OpenSSL.EVP_CipherFinal_ex(self.ctx, OpenSSL.byref(buffer),
#                                        OpenSSL.byref(i))) == 0:
#             raise Exception("[OpenSSL] EVP_CipherFinal_ex FAIL ...")
#         return buffer.raw[0:i.value]
# 
#     def ciphering(self, input):
#         """
#         Do update and final in one method
#         """
#         buff = self.update(input)
#         return buff + self.final()
# 
#     def __del__(self):
#         OpenSSL.EVP_CIPHER_CTX_cleanup(self.ctx)
#         OpenSSL.EVP_CIPHER_CTX_free(self.ctx)
# 
# Path: subspace/pyelliptic/hash.py
# def hmac_sha256(k, m):
#     """
#     Compute the key and the message with HMAC SHA5256
#     """
#     key = OpenSSL.malloc(k, len(k))
#     d = OpenSSL.malloc(m, len(m))
#     md = OpenSSL.malloc(0, 32)
#     i = OpenSSL.pointer(OpenSSL.c_int(0))
#     OpenSSL.HMAC(OpenSSL.EVP_sha256(), key, len(k), d, len(m), md, i)
#     return md.raw
# 
# def equals(a, b):
#     if isinstance(a, str):
#         return _equals_str(a, b)
#     else:
#         return _equals_bytes(a, b)


# Path: subspace/pyelliptic/ecc.py
from hashlib import sha512
from .openssl import OpenSSL
from .cipher import Cipher
from .hash import hmac_sha256, equals
from struct import pack, unpack


    @staticmethod
    def raw_encrypt(data, pubkey_x, pubkey_y, curve='sect283r1',
                    ephemcurve=None, ciphername='aes-256-cbc'):
        if ephemcurve is None:
            ephemcurve = curve
        ephem = ECC(curve=ephemcurve)
        key = sha512(ephem.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest()
        key_e, key_m = key[:32], key[32:]
        pubkey = ephem.get_pubkey()
        iv = OpenSSL.rand(OpenSSL.get_cipher(ciphername).get_blocksize())
        ctx = Cipher(key_e, iv, 1, ciphername)
        ciphertext = iv + ephem.pubkey_x + ephem.pubkey_y + ctx.ciphering(data)
        mac = hmac_sha256(key_m, ciphertext)
        return ciphertext + mac

    def decrypt(self, data, ciphername='aes-256-cbc'):
        """
        Decrypt data with ECIES method using the local private key
        """
        blocksize = OpenSSL.get_cipher(ciphername).get_blocksize()
        iv = data[:blocksize]
        i = blocksize
        curve, pubkey_x, pubkey_y, i2 = ECC._decode_keys(data[i:])
        i += i2
        ciphertext = data[i:len(data)-32]
        i += len(ciphertext)
        mac = data[i:]
        key = sha512(self.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest()
        key_e, key_m = key[:32], key[32:]

        if not equals(hmac_sha256(key_m, data[:len(data) - 32]), mac):