mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-08 07:18:47 +00:00
Merge pull request #131 from PR0M3TH3AN/codex/create-change_encryption_mode-method
Implement encryption mode switching
This commit is contained in:
@@ -12,6 +12,10 @@ import bcrypt
|
||||
|
||||
from password_manager.vault import Vault
|
||||
from nostr.client import DEFAULT_RELAYS as DEFAULT_NOSTR_RELAYS
|
||||
from utils.key_derivation import (
|
||||
EncryptionMode,
|
||||
DEFAULT_ENCRYPTION_MODE,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -41,6 +45,7 @@ class ConfigManager:
|
||||
"relays": list(DEFAULT_NOSTR_RELAYS),
|
||||
"pin_hash": "",
|
||||
"password_hash": "",
|
||||
"encryption_mode": DEFAULT_ENCRYPTION_MODE.value,
|
||||
}
|
||||
try:
|
||||
data = self.vault.load_config()
|
||||
@@ -50,6 +55,7 @@ class ConfigManager:
|
||||
data.setdefault("relays", list(DEFAULT_NOSTR_RELAYS))
|
||||
data.setdefault("pin_hash", "")
|
||||
data.setdefault("password_hash", "")
|
||||
data.setdefault("encryption_mode", DEFAULT_ENCRYPTION_MODE.value)
|
||||
|
||||
# Migrate legacy hashed_password.enc if present and password_hash is missing
|
||||
legacy_file = self.fingerprint_dir / "hashed_password.enc"
|
||||
@@ -113,3 +119,9 @@ class ConfigManager:
|
||||
config = self.load_config(require_pin=False)
|
||||
config["password_hash"] = password_hash
|
||||
self.save_config(config)
|
||||
|
||||
def set_encryption_mode(self, mode: EncryptionMode) -> None:
|
||||
"""Persist the selected encryption mode in the config."""
|
||||
config = self.load_config(require_pin=False)
|
||||
config["encryption_mode"] = mode.value
|
||||
self.save_config(config)
|
||||
|
@@ -723,6 +723,7 @@ class PasswordManager:
|
||||
)
|
||||
|
||||
self.store_hashed_password(password)
|
||||
self.config_manager.set_encryption_mode(self.encryption_mode)
|
||||
logging.info("User password hashed and stored successfully.")
|
||||
|
||||
seed_mgr.encrypt_parent_seed(seed)
|
||||
@@ -1459,3 +1460,53 @@ class PasswordManager:
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to change password: {e}", exc_info=True)
|
||||
print(colored(f"Error: Failed to change password: {e}", "red"))
|
||||
|
||||
def change_encryption_mode(self, new_mode: EncryptionMode) -> None:
|
||||
"""Re-encrypt the index using a different encryption mode."""
|
||||
try:
|
||||
password = prompt_existing_password("Enter your current master password: ")
|
||||
if not self.verify_password(password):
|
||||
print(colored("Incorrect password.", "red"))
|
||||
return
|
||||
|
||||
index_data = self.vault.load_index()
|
||||
config_data = self.config_manager.load_config(require_pin=False)
|
||||
|
||||
new_key = derive_index_key(self.parent_seed, password, new_mode)
|
||||
new_mgr = EncryptionManager(new_key, self.fingerprint_dir)
|
||||
|
||||
self.vault.set_encryption_manager(new_mgr)
|
||||
self.vault.save_index(index_data)
|
||||
self.config_manager.vault = self.vault
|
||||
config_data["encryption_mode"] = new_mode.value
|
||||
self.config_manager.save_config(config_data)
|
||||
|
||||
self.encryption_manager = new_mgr
|
||||
self.password_generator.encryption_manager = new_mgr
|
||||
self.encryption_mode = new_mode
|
||||
|
||||
relay_list = config_data.get("relays", list(DEFAULT_RELAYS))
|
||||
self.nostr_client = NostrClient(
|
||||
encryption_manager=self.encryption_manager,
|
||||
fingerprint=self.current_fingerprint,
|
||||
relays=relay_list,
|
||||
parent_seed=getattr(self, "parent_seed", None),
|
||||
)
|
||||
|
||||
print(colored("Encryption mode changed successfully.", "green"))
|
||||
|
||||
try:
|
||||
encrypted_data = self.get_encrypted_data()
|
||||
if encrypted_data:
|
||||
summary = f"mode-change-{int(time.time())}"
|
||||
self.nostr_client.publish_json_to_nostr(
|
||||
encrypted_data,
|
||||
alt_summary=summary,
|
||||
)
|
||||
except Exception as nostr_error:
|
||||
logging.error(
|
||||
f"Failed to post updated index to Nostr after encryption mode change: {nostr_error}"
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to change encryption mode: {e}", exc_info=True)
|
||||
print(colored(f"Error: Failed to change encryption mode: {e}", "red"))
|
||||
|
56
src/tests/test_encryption_mode_change.py
Normal file
56
src/tests/test_encryption_mode_change.py
Normal file
@@ -0,0 +1,56 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
from helpers import create_vault, TEST_SEED, TEST_PASSWORD
|
||||
|
||||
sys.path.append(str(Path(__file__).resolve().parents[1]))
|
||||
|
||||
from password_manager.entry_management import EntryManager
|
||||
from password_manager.config_manager import ConfigManager
|
||||
from password_manager.vault import Vault
|
||||
from password_manager.manager import PasswordManager
|
||||
from utils.key_derivation import EncryptionMode
|
||||
|
||||
|
||||
def test_change_encryption_mode(monkeypatch):
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
fp = Path(tmpdir)
|
||||
vault, enc_mgr = create_vault(
|
||||
fp, TEST_SEED, TEST_PASSWORD, EncryptionMode.SEED_ONLY
|
||||
)
|
||||
entry_mgr = EntryManager(vault, fp)
|
||||
cfg_mgr = ConfigManager(vault, fp)
|
||||
vault.save_index({"passwords": {}})
|
||||
|
||||
pm = PasswordManager.__new__(PasswordManager)
|
||||
pm.encryption_manager = enc_mgr
|
||||
pm.entry_manager = entry_mgr
|
||||
pm.config_manager = cfg_mgr
|
||||
pm.vault = vault
|
||||
pm.password_generator = SimpleNamespace(encryption_manager=enc_mgr)
|
||||
pm.fingerprint_dir = fp
|
||||
pm.current_fingerprint = "fp"
|
||||
pm.parent_seed = TEST_SEED
|
||||
pm.encryption_mode = EncryptionMode.SEED_ONLY
|
||||
|
||||
monkeypatch.setattr(
|
||||
"password_manager.manager.prompt_existing_password",
|
||||
lambda *_: TEST_PASSWORD,
|
||||
)
|
||||
pm.verify_password = lambda pw: True
|
||||
|
||||
with patch("password_manager.manager.NostrClient") as MockClient:
|
||||
mock = MockClient.return_value
|
||||
pm.nostr_client = mock
|
||||
pm.change_encryption_mode(EncryptionMode.SEED_PLUS_PW)
|
||||
mock.publish_json_to_nostr.assert_called_once()
|
||||
|
||||
assert pm.encryption_mode is EncryptionMode.SEED_PLUS_PW
|
||||
assert pm.password_generator.encryption_manager is pm.encryption_manager
|
||||
loaded = vault.load_index()
|
||||
assert loaded["passwords"] == {}
|
||||
cfg = cfg_mgr.load_config(require_pin=False)
|
||||
assert cfg["encryption_mode"] == EncryptionMode.SEED_PLUS_PW.value
|
Reference in New Issue
Block a user