from typing import Optional, BinaryIO, Tuple

from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateKey, EllipticCurvePublicKey
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey, RSAPrivateKey


def get_random_bytes(length: int) -> bytes: ...

def pad_data(data: bytes) -> bytes: ...
def unpad_data(data: bytes) -> bytes: ...

def generate_rsa_key() -> Tuple[RSAPrivateKey, RSAPublicKey]: ...
def load_rsa_private_key(der_private_key: bytes, password: Optional[str] = ...) -> RSAPrivateKey: ...
def load_rsa_public_key(der_public_key: bytes) -> RSAPublicKey: ...
def unload_rsa_private_key(private_key: RSAPrivateKey) -> bytes: ...
def unload_rsa_public_key(public_key: RSAPublicKey) -> bytes: ...

def generate_ec_key() -> (EllipticCurvePrivateKey, EllipticCurvePublicKey): ...
def load_ec_private_key(private_key: bytes) -> EllipticCurvePrivateKey: ...
def load_ec_public_key(public_key: bytes) -> EllipticCurvePublicKey: ...
def unload_ec_private_key(private_key: EllipticCurvePrivateKey) -> bytes: ...
def unload_ec_public_key(public_key: EllipticCurvePublicKey) -> bytes: ...

def encrypt_aes_v1(data: bytes, key: bytes, iv: Optional[bytes] = ..., use_padding: bool = ...) -> bytes: ...
def decrypt_aes_v1(data: bytes, key: bytes, use_padding: bool = ...) -> bytes: ...

def encrypt_aes_v2(data: bytes, key: bytes, nonce: bytes = ...) -> bytes: ...
def decrypt_aes_v2(data: bytes, key: bytes) -> bytes: ...

def encrypt_rsa(data: bytes, rsa_key: RSAPublicKey) -> bytes: ...
def decrypt_rsa(data: bytes, rsa_key: RSAPrivateKey) -> bytes: ...

def encrypt_ec(data: bytes, ec_public_key: EllipticCurvePublicKey) -> bytes: ...
def decrypt_ec(data: bytes, ec_private_key: EllipticCurvePrivateKey) -> bytes: ...

def derive_key_v1(password: str, salt: bytes, iterations: int) -> bytes: ...
def derive_keyhash_v1(password: str, salt: bytes, iterations: int) -> bytes: ...
def derive_keyhash_v2(domain: str, password: str, salt: bytes, iterations: int) -> bytes: ...

def hmac_sha512(key: bytes, data: bytes) -> bytes: ...

def generate_hkdf_key(info: str, phrase: str) -> bytes: ...

class StreamCrypter:
    key: bytes
    is_gcm: bool
    @property
    def bytes_read(self) -> int: ...
    def set_stream(self, stream: BinaryIO, for_encrypt: bool) -> BinaryIO: ...


