NDCT/ndct/core/crypt.py

111 lines
2.7 KiB
Python
Raw Permalink Normal View History

2024-06-09 19:22:26 +01:00
import base64
import os
import hashlib
import json
from ast import literal_eval
from getpass import getpass
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from ndct.core.paths import KEY_PATH, DB_PATH
from ndct.core.log import log
class Crypt:
@staticmethod
def generate_key():
'''
Summary:
Generate a key used for symmetric encryption, using the hash of a user entered password for the salt.
Returns:
Encryption key
Encryption type:
128-bit AES
'''
if os.path.isfile(KEY_PATH):
log("Using existing key '{}' for encryption/decryption".format(KEY_PATH), 'info')
key = Crypt.get_key()
return key
else:
log("Attempting to use '{}' but no key found, create a new key or add an existing one".format(KEY_PATH), 'info')
password = getpass(prompt='New encryption key password: ')
password_bytes = password.encode()
salt = os.urandom(16)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
backend=default_backend()
)
key = base64.urlsafe_b64encode(kdf.derive(password_bytes))
with open(KEY_PATH, 'wb') as encryption_key:
encryption_key.write(key)
log("Stored encryption key as '{}'".format(KEY_PATH), 'info')
return key
@staticmethod
def get_key():
'''
Summary:
Get stored encryption key.
Returns:
Encryption key
Encryption type:
128-bit AES
'''
with open(KEY_PATH, 'rb') as encryption_key:
key = encryption_key.read()
return key
@staticmethod
def create_encrypted_file(filename, data):
'''
Summary:
Create an encrypted file from data that is passed to the function.
Takes:
filename: Name of encrypted file
data: Data to encrypt
'''
key = Crypt.generate_key()
fernet = Fernet(key)
encrypted_data = fernet.encrypt(str(data).encode())
with open(DB_PATH + filename, 'wb') as encrypted_file:
encrypted_file.write(encrypted_data)
@staticmethod
def get_encrypted_file_contents(filename):
'''
Summary:
Get the contents of an encrypted file to enable use of the stored data.
Takes:
filename: Name of file to get decrypted contents of
Returns:
Decrypted file contents
'''
key = Crypt.generate_key()
with open(DB_PATH + filename, 'rb') as encrypted_file:
data = encrypted_file.read()
fernet = Fernet(key)
temp_data = fernet.decrypt(data).decode()
temp_data_list = literal_eval(temp_data)
return temp_data_list