mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-10 00:09:04 +00:00
Add KDF config with per-file metadata
This commit is contained in:
@@ -3,11 +3,15 @@ from pathlib import Path
|
||||
|
||||
from hypothesis import given, strategies as st, settings, HealthCheck
|
||||
from mnemonic import Mnemonic
|
||||
import hashlib
|
||||
import base64
|
||||
import os
|
||||
|
||||
from utils.key_derivation import (
|
||||
derive_key_from_password,
|
||||
derive_key_from_password_argon2,
|
||||
derive_index_key,
|
||||
KdfConfig,
|
||||
)
|
||||
from utils.fingerprint import generate_fingerprint
|
||||
from seedpass.core.encryption import EncryptionManager
|
||||
@@ -36,16 +40,27 @@ def test_fuzz_key_round_trip(password, seed_bytes, config, mode, tmp_path: Path)
|
||||
seed_phrase = Mnemonic("english").to_mnemonic(seed_bytes)
|
||||
fp = generate_fingerprint(seed_phrase)
|
||||
if mode == "argon2":
|
||||
key = derive_key_from_password_argon2(
|
||||
password, fp, time_cost=1, memory_cost=8, parallelism=1
|
||||
cfg = KdfConfig(
|
||||
params={"time_cost": 1, "memory_cost": 8, "parallelism": 1},
|
||||
salt_b64=base64.b64encode(
|
||||
hashlib.sha256(fp.encode()).digest()[:16]
|
||||
).decode(),
|
||||
)
|
||||
key = derive_key_from_password_argon2(password, cfg)
|
||||
else:
|
||||
key = derive_key_from_password(password, fp, iterations=1)
|
||||
cfg = KdfConfig(
|
||||
name="pbkdf2",
|
||||
params={"iterations": 1},
|
||||
salt_b64=base64.b64encode(
|
||||
hashlib.sha256(fp.encode()).digest()[:16]
|
||||
).decode(),
|
||||
)
|
||||
|
||||
enc_mgr = EncryptionManager(key, tmp_path)
|
||||
|
||||
# Parent seed round trip
|
||||
enc_mgr.encrypt_parent_seed(seed_phrase)
|
||||
enc_mgr.encrypt_parent_seed(seed_phrase, kdf=cfg)
|
||||
assert enc_mgr.decrypt_parent_seed() == seed_phrase
|
||||
|
||||
# JSON data round trip
|
||||
|
@@ -1,4 +1,6 @@
|
||||
import bcrypt
|
||||
import hashlib
|
||||
import base64
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from types import SimpleNamespace
|
||||
@@ -7,6 +9,7 @@ from utils.key_derivation import (
|
||||
derive_key_from_password,
|
||||
derive_key_from_password_argon2,
|
||||
derive_index_key,
|
||||
KdfConfig,
|
||||
)
|
||||
from seedpass.core.encryption import EncryptionManager
|
||||
from seedpass.core.vault import Vault
|
||||
@@ -21,10 +24,24 @@ def _setup_profile(tmp: Path, mode: str):
|
||||
argon_kwargs = dict(time_cost=1, memory_cost=8, parallelism=1)
|
||||
fp = tmp.name
|
||||
if mode == "argon2":
|
||||
seed_key = derive_key_from_password_argon2(TEST_PASSWORD, fp, **argon_kwargs)
|
||||
cfg = KdfConfig(
|
||||
params=argon_kwargs,
|
||||
salt_b64=base64.b64encode(
|
||||
hashlib.sha256(fp.encode()).digest()[:16]
|
||||
).decode(),
|
||||
)
|
||||
seed_key = derive_key_from_password_argon2(TEST_PASSWORD, cfg)
|
||||
EncryptionManager(seed_key, tmp).encrypt_parent_seed(TEST_SEED, kdf=cfg)
|
||||
else:
|
||||
seed_key = derive_key_from_password(TEST_PASSWORD, fp, iterations=1)
|
||||
EncryptionManager(seed_key, tmp).encrypt_parent_seed(TEST_SEED)
|
||||
cfg = KdfConfig(
|
||||
name="pbkdf2",
|
||||
params={"iterations": 1},
|
||||
salt_b64=base64.b64encode(
|
||||
hashlib.sha256(fp.encode()).digest()[:16]
|
||||
).decode(),
|
||||
)
|
||||
EncryptionManager(seed_key, tmp).encrypt_parent_seed(TEST_SEED, kdf=cfg)
|
||||
|
||||
index_key = derive_index_key(TEST_SEED)
|
||||
enc_mgr = EncryptionManager(index_key, tmp)
|
||||
@@ -65,9 +82,9 @@ def test_setup_encryption_manager_kdf_modes(monkeypatch):
|
||||
)
|
||||
if mode == "argon2":
|
||||
monkeypatch.setattr(
|
||||
"seedpass.core.manager.derive_key_from_password_argon2",
|
||||
lambda pw, fp: derive_key_from_password_argon2(
|
||||
pw, fp, **argon_kwargs
|
||||
"seedpass.core.manager.KdfConfig",
|
||||
lambda salt_b64, **_: KdfConfig(
|
||||
params=argon_kwargs, salt_b64=salt_b64
|
||||
),
|
||||
)
|
||||
monkeypatch.setattr(PasswordManager, "initialize_bip85", lambda self: None)
|
||||
@@ -76,3 +93,26 @@ def test_setup_encryption_manager_kdf_modes(monkeypatch):
|
||||
)
|
||||
assert pm.setup_encryption_manager(path, exit_on_fail=False)
|
||||
assert pm.parent_seed == TEST_SEED
|
||||
|
||||
|
||||
def test_kdf_param_round_trip(tmp_path):
|
||||
cfg = KdfConfig(
|
||||
params={"time_cost": 3, "memory_cost": 32, "parallelism": 1},
|
||||
salt_b64=base64.b64encode(b"static-salt-1234").decode(),
|
||||
)
|
||||
key = derive_key_from_password_argon2(TEST_PASSWORD, cfg)
|
||||
mgr = EncryptionManager(key, tmp_path)
|
||||
mgr.encrypt_parent_seed(TEST_SEED, kdf=cfg)
|
||||
stored = mgr.get_file_kdf(Path("parent_seed.enc"))
|
||||
assert stored.params == cfg.params
|
||||
|
||||
|
||||
def test_vault_kdf_migration(tmp_path):
|
||||
index_key = derive_index_key(TEST_SEED)
|
||||
mgr = EncryptionManager(index_key, tmp_path)
|
||||
vault = Vault(mgr, tmp_path)
|
||||
old_kdf = KdfConfig(name="hkdf", version=0, params={}, salt_b64="")
|
||||
mgr.save_json_data({"entries": {}}, vault.index_file, kdf=old_kdf)
|
||||
vault.load_index()
|
||||
new_kdf = mgr.get_file_kdf(vault.index_file)
|
||||
assert new_kdf.version == KdfConfig().version
|
||||
|
@@ -1,11 +1,15 @@
|
||||
import logging
|
||||
import pytest
|
||||
import logging
|
||||
import hashlib
|
||||
import base64
|
||||
from utils.fingerprint import generate_fingerprint
|
||||
from utils.key_derivation import (
|
||||
derive_key_from_password,
|
||||
derive_key_from_password_argon2,
|
||||
derive_index_key_seed_only,
|
||||
derive_index_key,
|
||||
KdfConfig,
|
||||
)
|
||||
|
||||
|
||||
@@ -48,15 +52,17 @@ def test_argon2_fingerprint_affects_key():
|
||||
fp1 = generate_fingerprint("seed one")
|
||||
fp2 = generate_fingerprint("seed two")
|
||||
|
||||
k1 = derive_key_from_password_argon2(
|
||||
password, fp1, time_cost=1, memory_cost=8, parallelism=1
|
||||
cfg1 = KdfConfig(
|
||||
params={"time_cost": 1, "memory_cost": 8, "parallelism": 1},
|
||||
salt_b64=base64.b64encode(hashlib.sha256(fp1.encode()).digest()[:16]).decode(),
|
||||
)
|
||||
k2 = derive_key_from_password_argon2(
|
||||
password, fp1, time_cost=1, memory_cost=8, parallelism=1
|
||||
)
|
||||
k3 = derive_key_from_password_argon2(
|
||||
password, fp2, time_cost=1, memory_cost=8, parallelism=1
|
||||
cfg2 = KdfConfig(
|
||||
params={"time_cost": 1, "memory_cost": 8, "parallelism": 1},
|
||||
salt_b64=base64.b64encode(hashlib.sha256(fp2.encode()).digest()[:16]).decode(),
|
||||
)
|
||||
k1 = derive_key_from_password_argon2(password, cfg1)
|
||||
k2 = derive_key_from_password_argon2(password, cfg1)
|
||||
k3 = derive_key_from_password_argon2(password, cfg2)
|
||||
|
||||
assert k1 == k2
|
||||
assert k1 != k3
|
||||
|
Reference in New Issue
Block a user