Lower KDF iteration default

This commit is contained in:
thePR0M3TH3AN
2025-07-13 14:40:15 -04:00
parent 7f43d79f6e
commit 96d5a1bb57
5 changed files with 13 additions and 11 deletions

View File

@@ -417,7 +417,7 @@ seedpass config set kdf_iterations 200000
seedpass config set backup_interval 3600
```
Lower iteration counts speed up vault decryption but make brute-force attacks easier. A long backup interval means fewer backups and increases the risk of data loss.
The default configuration uses **50,000** PBKDF2 iterations. Lower iteration counts speed up vault decryption but make brute-force attacks easier. A long backup interval means fewer backups and increases the risk of data loss.
## Running Tests
@@ -485,6 +485,7 @@ Mutation testing is disabled in the GitHub workflow due to reliability issues an
- **Potential Bugs and Limitations:** Be aware that the software may contain bugs and lacks certain features. Snapshot chunks are capped at 50 KB and the client rotates snapshots after enough delta events accumulate. The security of memory management and logs has not been thoroughly evaluated and may pose risks of leaking sensitive information.
- **Multiple Seeds Management:** While managing multiple seeds adds flexibility, it also increases the responsibility to secure each seed and its associated password.
- **No PBKDF2 Salt Required:** SeedPass deliberately omits an explicit PBKDF2 salt. Every password is derived from a unique 512-bit BIP-85 child seed, which already provides stronger per-password uniqueness than a conventional 128-bit salt.
- **Default KDF Iterations:** New profiles start with 50,000 PBKDF2 iterations. Adjust this with `seedpass config set kdf_iterations`.
- **KDF Iteration Caution:** Lowering `kdf_iterations` makes password cracking easier, while a high `backup_interval` leaves fewer recent backups.
## Contributing

View File

@@ -494,6 +494,7 @@ Mutation testing is disabled in the GitHub workflow due to reliability issues an
- **Potential Bugs and Limitations:** Be aware that the software may contain bugs and lacks certain features. Snapshot chunks are capped at 50KB and the client rotates snapshots after enough delta events accumulate. The security of memory management and logs has not been thoroughly evaluated and may pose risks of leaking sensitive information.
- **Multiple Seeds Management:** While managing multiple seeds adds flexibility, it also increases the responsibility to secure each seed and its associated password.
- **No PBKDF2 Salt Required:** SeedPass deliberately omits an explicit PBKDF2 salt. Every password is derived from a unique 512-bit BIP-85 child seed, which already provides stronger per-password uniqueness than a conventional 128-bit salt.
- **Default KDF Iterations:** New profiles start with 50,000 PBKDF2 iterations. Use `seedpass config set kdf_iterations` to change this.
## Contributing

View File

@@ -45,7 +45,7 @@ class ConfigManager:
"pin_hash": "",
"password_hash": "",
"inactivity_timeout": INACTIVITY_TIMEOUT,
"kdf_iterations": 100_000,
"kdf_iterations": 50_000,
"kdf_mode": "pbkdf2",
"additional_backup_path": "",
"backup_interval": 0,
@@ -66,7 +66,7 @@ class ConfigManager:
data.setdefault("pin_hash", "")
data.setdefault("password_hash", "")
data.setdefault("inactivity_timeout", INACTIVITY_TIMEOUT)
data.setdefault("kdf_iterations", 100_000)
data.setdefault("kdf_iterations", 50_000)
data.setdefault("kdf_mode", "pbkdf2")
data.setdefault("additional_backup_path", "")
data.setdefault("backup_interval", 0)
@@ -165,7 +165,7 @@ class ConfigManager:
def get_kdf_iterations(self) -> int:
"""Retrieve the PBKDF2 iteration count."""
config = self.load_config(require_pin=False)
return int(config.get("kdf_iterations", 100_000))
return int(config.get("kdf_iterations", 50_000))
def set_kdf_mode(self, mode: str) -> None:
"""Persist the key derivation function mode."""

View File

@@ -397,7 +397,7 @@ class PasswordManager:
iterations = (
self.config_manager.get_kdf_iterations()
if getattr(self, "config_manager", None)
else 100_000
else 50_000
)
print("Deriving key...")
if mode == "argon2":
@@ -466,7 +466,7 @@ class PasswordManager:
iterations = (
self.config_manager.get_kdf_iterations()
if getattr(self, "config_manager", None)
else 100_000
else 50_000
)
if mode == "argon2":
seed_key = derive_key_from_password_argon2(password)
@@ -618,7 +618,7 @@ class PasswordManager:
iterations = (
self.config_manager.get_kdf_iterations()
if getattr(self, "config_manager", None)
else 100_000
else 50_000
)
key = derive_key_from_password(password, iterations=iterations)
@@ -744,7 +744,7 @@ class PasswordManager:
iterations = (
self.config_manager.get_kdf_iterations()
if getattr(self, "config_manager", None)
else 100_000
else 50_000
)
seed_key = derive_key_from_password(password, iterations=iterations)
@@ -901,7 +901,7 @@ class PasswordManager:
iterations = (
self.config_manager.get_kdf_iterations()
if getattr(self, "config_manager", None)
else 100_000
else 50_000
)
seed_key = derive_key_from_password(password, iterations=iterations)

View File

@@ -23,7 +23,7 @@ def test_config_defaults_and_round_trip():
assert cfg["pin_hash"] == ""
assert cfg["password_hash"] == ""
assert cfg["additional_backup_path"] == ""
assert cfg["kdf_iterations"] == 100_000
assert cfg["kdf_iterations"] == 50_000
cfg_mgr.set_pin("1234")
cfg_mgr.set_relays(["wss://example.com"], require_pin=False)
@@ -154,7 +154,7 @@ def test_kdf_iterations_round_trip():
vault, _ = create_vault(Path(tmpdir), TEST_SEED, TEST_PASSWORD)
cfg_mgr = ConfigManager(vault, Path(tmpdir))
assert cfg_mgr.get_kdf_iterations() == 100_000
assert cfg_mgr.get_kdf_iterations() == 50_000
cfg_mgr.set_kdf_iterations(200_000)
assert cfg_mgr.get_kdf_iterations() == 200_000