From 869d147ffe7e52b1df30275e15b4e178eb5ada5e Mon Sep 17 00:00:00 2001 From: Entity069 Date: Tue, 17 Dec 2024 00:39:48 +0530 Subject: [PATCH] Added logging and integrity check for log files --- logger.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.py | 4 ++++ manager.py | 14 ++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 logger.py diff --git a/logger.py b/logger.py new file mode 100644 index 0000000..3a526bb --- /dev/null +++ b/logger.py @@ -0,0 +1,65 @@ +import os +import hashlib +from datetime import datetime + +class IntegrityError(Exception): + def __init__(self, message): + super().__init__(message) + +class ActionLogger: + def __init__(self, log_file="action_log.txt"): + self.log_file = log_file + self.init_log() + + def init_log(self): + if not os.path.exists(self.log_file): + with open(self.log_file, 'a+') as log: + genesis_entry = "GENESIS_ENTRY" + genesis_hash = hashlib.sha256(genesis_entry.encode()).hexdigest() + timestamp = datetime.now().isoformat() + log.write(f"[{timestamp}] GENESIS {genesis_hash}\n") + + def log_action(self, action): + with open(self.log_file, 'r') as log: + last_line = log.readlines()[-1] + + last_hash = last_line.strip().split()[-1] + timestamp = datetime.now().isoformat() + log_entry = f"[{timestamp}] {action}" + log_hash = hashlib.sha256(f"{log_entry} {last_hash}".encode()).hexdigest() + + with open(self.log_file, 'a') as log: + log.write(f"{log_entry} {log_hash}\n") + + def verify_genesis_log_integrity(self): + genesis_entry = "GENESIS_ENTRY" + if open(self.log_file, 'r').readline().strip().split()[-1] != hashlib.sha256(genesis_entry.encode()).hexdigest(): + raise IntegrityError(f"Log integrity failed: GENESIS_ENTRY") + + def verify_log_integrity(self): + self.verify_genesis_log_integrity() + with open(self.log_file, 'r') as log: + lines = log.readlines() + lines = [line.strip() for line in lines] + + for i in range(1, len(lines)): + prev_line = lines[i - 1].strip() + curr_line = lines[i].strip() + + prev_hash = prev_line.split()[-1] + curr_entry = " ".join(curr_line.split()[:-1]) + curr_hash = curr_line.split()[-1] + + computed_hash = hashlib.sha256(f"{curr_entry} {prev_hash}".encode()).hexdigest() + + if computed_hash != curr_hash: + raise IntegrityError(f"Log integrity failed: Line {i+1}") + + return True + + def print_logs(self): + with open(self.log_file, 'r') as log: + print("=== LOG START ===") + for line in log: + print(line.strip()) + print("=== LOG END ===") diff --git a/main.py b/main.py index 57ab52b..40f6ba6 100644 --- a/main.py +++ b/main.py @@ -9,6 +9,7 @@ def main(): } pm = PasswordManager() + pm.verify_log_integrity() print("""What would you like to do? 1. Create a new key @@ -17,6 +18,7 @@ def main(): 4. Load an existing password file 5. Add a password 6. Get a password + 7. Print log q. Quit """) @@ -42,6 +44,8 @@ def main(): elif choice == '6': site = input("Enter site: ").strip() print(f"Password for {site}: {pm.get_password(site)}") + elif choice == '7': + pm.print_logs() elif choice == 'q': done = True print("Goodbye!") diff --git a/manager.py b/manager.py index 212f675..81cf064 100644 --- a/manager.py +++ b/manager.py @@ -1,5 +1,6 @@ from cryptography.fernet import Fernet +from logger import ActionLogger class PasswordManager: @@ -7,21 +8,25 @@ def __init__(self): self.key = None self.password_file = None self.password_dict = {} + self.logger = ActionLogger() def create_key(self, path): self.key = Fernet.generate_key() with open(path, 'wb') as f: f.write(self.key) + self.logger.log_action(f"CREATE_KEY {path}") def load_key(self, path): with open(path, 'rb') as f: self.key = f.read() + self.logger.log_action(f"LOAD_KEY {path}") def create_password_file(self, path, initial_values=None): self.password_file = path if initial_values is not None: for site, password in initial_values.items(): self.add_password(site, password) + self.logger.log_action(f"CREATE_PASSWORD_FILE {path}") def load_password_file(self, path): self.password_file = path @@ -29,6 +34,7 @@ def load_password_file(self, path): for line in f: site, encrypted = line.split(":") self.password_dict[site] = Fernet(self.key).decrypt(encrypted.encode()).decode() + self.logger.log_action(f"LOAD_PASSWORD_FILE {path}") def add_password(self, site, password): self.password_dict[site] = password @@ -36,6 +42,14 @@ def add_password(self, site, password): with open(self.password_file, 'a+') as f: encrypted = Fernet(self.key).encrypt(password.encode()).decode() f.write(f"{site}:{encrypted}\n") + self.logger.log_action(f"ADD_PASSWORD {site}") def get_password(self, site): + self.logger.log_action(f"GET_PASSWORD {site}") return self.password_dict.get(site, "Password not found.") + + def verify_log_integrity(self): + return self.logger.verify_log_integrity() + + def print_logs(self): + self.logger.print_logs()