diff --git a/src/encryption.py b/src/encryption.py deleted file mode 100755 index acb3a75..0000000 --- a/src/encryption.py +++ /dev/null @@ -1,217 +0,0 @@ -#! /usr/bin/env python3 - -# Mirai Nikki Bot, a video frame posting bot for Pleroma -# Copyright (C) 2022 Anon -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import sys -import base64 -import os -import getpass -from cryptography.fernet import Fernet, InvalidToken -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC - -from collections import OrderedDict - - -class EncryptionFail(Exception): - pass - -class PasswordMismatch(Exception): - pass - - -# Return string from bytes -def salt_encode(b): - return base64.urlsafe_b64encode(b).decode() - - -# Return bytes from string -def salt_decode(s): - return base64.urlsafe_b64decode(s.encode()) - - -# Ordered Dictionaries -def change_encoding_dict(settings_server, encoding_type): - return OrderedDict([(k, encoding_type(v)) for k, v in settings_server.items()]) - - -# Return bytes from string -def encode_dict(settings_server): - return change_encoding_dict(settings_server, str.encode) - - -# Return string from bytes -def decode_dict(settings_server): - return change_encoding_dict(settings_server, bytes.decode) - - -# password: Bytes -# salt: Bytes -def derive_key(password, salt): - kdf = PBKDF2HMAC( - algorithm=hashes.SHA256(), - length=32, - salt=salt, - iterations=100000, - backend=default_backend() - ) - return base64.urlsafe_b64encode(kdf.derive(password)) - - -# Encryption functions -# message: Bytes -# key: Bytes -def encrypt(message, key): - f = Fernet(key) - token = f.encrypt(message) - return token - - -# token: Bytes -# key: Bytes -def decrypt(token, key): - f = Fernet(key) - message = f.decrypt(token) - return message - - -# password: bytes() -# salt: bytes() -# settings_server: dict() -> Byte values -# encryption_function: encrypt(message, key) : decrypt(token, key): -# Returns settings_server_decrypted dictionary with Byte() values. Will need to use -# ChangeEncodingDict to make them strings (recommended cfg file friendly) -def encrypt_settings(settings_server, password, salt, encryption_function): - key = derive_key(password, salt) - settings_server_decrypted = OrderedDict() - for setting in settings_server: - settings_server_decrypted[setting] = encryption_function(settings_server[setting], key) - return settings_server_decrypted - -def get_keyfile(keyfile=None): - if keyfile is not None: - with open(keyfile, "rb") as f: - return f.read() - return None - - -def get_pass(q): - try: - return getpass.getpass(q).encode() - except KeyboardInterrupt: - raise EncryptionFail("\nQuitting...") - - -def settings_server_encrypt(settings_server, keyfile=None): - try: - settings_server = encode_dict(settings_server) - salt = os.urandom(16) - password = get_keyfile(keyfile) - if password is None: - password = get_pass("Enter password: ") - password2 = get_pass("Enter password: ") - if password != password2: - raise PasswordMismatch("Passwords do not match") - encrypted = encrypt_settings(settings_server, password, salt, encrypt) - return salt_encode(salt), decode_dict(encrypted) - except PasswordMismatch as e: - raise EncryptionFail(str(e)) - except Exception as e: - err = str(e) - raise EncryptionFail("Encrypt Error: {}".format(err)) - - -def settings_server_decrypt(settings_server, settings_encrypt, keyfile=None): - try: - if not settings_encrypt["encrypt"]: - return settings_server - settings_server = encode_dict(settings_server) - password = get_keyfile(keyfile or settings_encrypt["keyfile"]) or get_pass("Enter password: ") - salt = salt_decode(settings_encrypt["salt"]) - decrypted = encrypt_settings(settings_server, password, salt, decrypt) - return decode_dict(decrypted) - except base64.binascii.Error: - raise EncryptionFail("Salt is invalid") - except InvalidToken: - raise EncryptionFail("Password or token is incorrect") - except Exception as e: - err = str(e) - raise EncryptionFail("Decrypt Error: {}".format(err)) - - -def main(): - import argparse - from pprint import pformat - - default_cfg = "cfg" - - parser = argparse.ArgumentParser( - description="A class to encrypt server credentials", - epilog="There are no additional parameters.", - add_help=True ) - parser.add_argument("--encrypt", help="Generate encrypted authentication.", action="store_true") - parser.add_argument("--decrypt", help="Decrypt encrypted authentication", action="store_true") - parser.add_argument("--recrypt", help="Recrypt encrypted authentication", action="store_true") - parser.add_argument("-k", "--keyfile", help="Keyfile used for decryption", default=None) - parser.add_argument("-c", "--cfg", help="Specify config file.", default=default_cfg) - - arguments = parser.parse_args() - - if arguments.recrypt: - arguments.encrypt = True - arguments.decrypt = True - - if arguments.encrypt or arguments.decrypt: - import importlib - cfg = importlib.import_module(arguments.cfg) - settings_server = cfg.settings_server - settings_encrypt = cfg.settings_encrypt - keyfile = arguments.keyfile or settings_encrypt["keyfile"] - - if arguments.decrypt and arguments.encrypt: - print("Re-encrypting") - - if arguments.decrypt: # arguments.decrypt - print("Decrypt...") - settings_server = settings_server_decrypt(settings_server, settings_encrypt, arguments.keyfile) - settings_encrypt = OrderedDict([ - ("encrypt", False), - ("salt", settings_encrypt["salt"]), - ("keyfile", arguments.keyfile) - ]) - - if arguments.encrypt: - print("Encrypt...") - salt, settings_server = settings_server_encrypt(settings_server, keyfile) - settings_encrypt = OrderedDict([ - ("encrypt", True), - ("salt", salt), - ("keyfile", arguments.keyfile) - ]) - - print("settings_server = {}".format(pformat(settings_server))) - print("settings_encrypt = {}".format(pformat(settings_encrypt))) - return 0 - - -if __name__ == "__main__": - try: - sys.exit(main()) - except EncryptionFail as e: - print(e) - sys.exit(1)