""" Cryptography related stuff - mostly encrypting and decrypting user data. """ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC from cryptography.fernet import Fernet import base64 import os def get_key(password: str) -> bytes: """ Derives a bytes key from a given password. Useful when you want to generate the same key over and over again. E.g. to encrypt/decrypt locally stored user data. """ password = password.encode() salt = b'?\x0f\xa1\x97otT\xe48\xc9O\xb4\x1f\xef\xf5\xea' kdf = PBKDF2HMAC( algorithm=hashes.SHA256, length=32, salt=salt, iterations=100000, backend=default_backend() ) key = base64.urlsafe_b64encode(kdf.derive(password)) return key def encrypt_and_write_to_file(password: str, strdata: str, file_path: str) -> bool: """ Encrypts the given string data and stores them in a file. """ try: key = get_key(password) f = Fernet(key) encrypted = f.encrypt(strdata.encode()) if os.path.exists(file_path): with open(file_path, "wb") as ef: ef.write(encrypted) else: os.system(f"touch {file_path}") with open(file_path, "wb") as ef: ef.write(encrypted) return 0 except: return 1 def read_from_file_and_decrypt(password: str, file_path: str) -> str: """ Reads contents of an encrypted file and decrypts them. """ try: key = get_key(password) f = Fernet(key) if os.path.exists(file_path): with open(file_path, "rb") as ef: decrypted = f.decrypt(ef.read()) else: os.system(f"touch {file_path}") with open(file_path, "rb") as ef: decrypted = f.decrypt(ef.read()) return decrypted.decode() except: return ""