Initial commit
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
from .password_hasher import PasswordHasher
|
||||
from .integrity_checker import IntegrityChecker
|
||||
from .crypto_manager import CryptoManager
|
||||
from .audit_logger import AuditLogger
|
||||
from .account_manager import AccountManager
|
||||
@@ -0,0 +1,62 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class AccountManager:
|
||||
"""
|
||||
Класс для управления учётными записями пользователей.
|
||||
"""
|
||||
|
||||
def __init__(self, db_file: str | None):
|
||||
self.db_file = Path(db_file) if db_file else None
|
||||
if isinstance(self.db_file, Path) and not self.db_file.exists():
|
||||
self._save_db({})
|
||||
|
||||
def set_db_file(self, db_file: str | None) -> None:
|
||||
self.db_file = Path(db_file) if db_file else None
|
||||
if isinstance(self.db_file, Path) and not self.db_file.exists():
|
||||
self._save_db({})
|
||||
|
||||
def _load_db(self) -> dict:
|
||||
if not isinstance(self.db_file, Path):
|
||||
return {}
|
||||
if self.db_file.exists():
|
||||
return json.loads(self.db_file.read_text(encoding="utf-8"))
|
||||
return {}
|
||||
|
||||
def _save_db(self, data: dict) -> None:
|
||||
if not isinstance(self.db_file, Path):
|
||||
raise RuntimeError("База данных не открыта")
|
||||
self.db_file.write_text(json.dumps(
|
||||
data, indent=2, ensure_ascii=False), encoding="utf-8")
|
||||
|
||||
def add_user(self, username: str, password_hash: str, salt: str) -> None:
|
||||
data = self._load_db()
|
||||
data[username] = {"hash": password_hash, "salt": salt}
|
||||
self._save_db(data)
|
||||
|
||||
def update_user(self, username: str, password_hash: str, salt: str) -> bool:
|
||||
data = self._load_db()
|
||||
if username not in data:
|
||||
return False
|
||||
data[username] = {"hash": password_hash, "salt": salt}
|
||||
self._save_db(data)
|
||||
return True
|
||||
|
||||
def delete_user(self, username: str) -> bool:
|
||||
data = self._load_db()
|
||||
if username not in data:
|
||||
return False
|
||||
del data[username]
|
||||
self._save_db(data)
|
||||
return True
|
||||
|
||||
def get_user(self, username: str) -> dict | None:
|
||||
data = self._load_db()
|
||||
return data.get(username)
|
||||
|
||||
def list_users(self) -> list[str]:
|
||||
if not isinstance(self.db_file, Path):
|
||||
return []
|
||||
data = self._load_db()
|
||||
return list(data.keys())
|
||||
@@ -0,0 +1,17 @@
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class AuditLogger:
|
||||
"""
|
||||
Класс для ведения журнала событий.
|
||||
"""
|
||||
|
||||
def __init__(self, log_file: str):
|
||||
self.log_file = Path(log_file)
|
||||
|
||||
def log(self, event: str) -> None:
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
line = f"[{timestamp}] {event}\n"
|
||||
with open(self.log_file, "a", encoding="utf-8") as f:
|
||||
f.write(line)
|
||||
@@ -0,0 +1,23 @@
|
||||
from cryptography.fernet import Fernet
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class CryptoManager:
|
||||
"""
|
||||
Класс для симметричного шифрования и расшифрования файлов.
|
||||
"""
|
||||
|
||||
def generate_key(self) -> bytes:
|
||||
return Fernet.generate_key()
|
||||
|
||||
def encrypt_file(self, file_path: str, key: bytes, output_path: str) -> None:
|
||||
fernet = Fernet(key)
|
||||
data = Path(file_path).read_bytes()
|
||||
encrypted = fernet.encrypt(data)
|
||||
Path(output_path).write_bytes(encrypted)
|
||||
|
||||
def decrypt_file(self, file_path: str, key: bytes, output_path: str) -> None:
|
||||
fernet = Fernet(key)
|
||||
data = Path(file_path).read_bytes()
|
||||
decrypted = fernet.decrypt(data)
|
||||
Path(output_path).write_bytes(decrypted)
|
||||
@@ -0,0 +1,26 @@
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class IntegrityChecker:
|
||||
"""
|
||||
Класс для проверки целостности файлов по хэш-сумме.
|
||||
"""
|
||||
|
||||
def calculate_hash(self, file_path: str) -> str:
|
||||
hasher = hashlib.sha256()
|
||||
with open(file_path, "rb") as f:
|
||||
for chunk in iter(lambda: f.read(4096), b""):
|
||||
hasher.update(chunk)
|
||||
return hasher.hexdigest()
|
||||
|
||||
def save_hash(self, file_path: str, hash_file: str) -> None:
|
||||
file_hash = self.calculate_hash(file_path)
|
||||
Path(hash_file).write_text(file_hash, encoding="utf-8")
|
||||
|
||||
def verify_hash(self, file_path: str, hash_file: str) -> bool:
|
||||
if not Path(hash_file).exists():
|
||||
return False
|
||||
expected = Path(hash_file).read_text(encoding="utf-8").strip()
|
||||
actual = self.calculate_hash(file_path)
|
||||
return expected == actual
|
||||
@@ -0,0 +1,19 @@
|
||||
import hashlib
|
||||
import secrets
|
||||
|
||||
|
||||
class PasswordHasher:
|
||||
"""
|
||||
Класс для безопасного хэширования паролей с использованием соли.
|
||||
"""
|
||||
|
||||
def generate_salt(self, length: int = 16) -> str:
|
||||
return secrets.token_hex(length)
|
||||
|
||||
def hash_password(self, password: str, salt: str) -> str:
|
||||
hasher = hashlib.sha256()
|
||||
hasher.update(salt.encode("utf-8") + password.encode("utf-8"))
|
||||
return hasher.hexdigest()
|
||||
|
||||
def verify_password(self, password: str, salt: str, expected_hash: str) -> bool:
|
||||
return self.hash_password(password, salt) == expected_hash
|
||||
Reference in New Issue
Block a user