mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-08 07:18:47 +00:00
Use HMAC DRNG for RSA PGP keys
This commit is contained in:
@@ -482,7 +482,13 @@ def derive_seed_phrase(bip85: BIP85, idx: int, words: int = 24) -> str:
|
||||
def derive_pgp_key(
|
||||
bip85: BIP85, idx: int, key_type: str = "ed25519", user_id: str = ""
|
||||
) -> tuple[str, str]:
|
||||
"""Derive a deterministic PGP private key and return it with its fingerprint."""
|
||||
"""Derive a deterministic PGP private key and return it with its fingerprint.
|
||||
|
||||
For RSA keys the randomness required during key generation is provided by
|
||||
an HMAC-SHA256 based deterministic generator seeded from the BIP-85
|
||||
entropy. This avoids use of Python's ``random`` module while ensuring the
|
||||
output remains stable across Python versions.
|
||||
"""
|
||||
|
||||
from pgpy import PGPKey, PGPUID
|
||||
from pgpy.packet.packets import PrivKeyV4
|
||||
@@ -514,14 +520,18 @@ def derive_pgp_key(
|
||||
if key_type.lower() == "rsa":
|
||||
|
||||
class DRNG:
|
||||
"""HMAC-SHA256 based deterministic random generator."""
|
||||
|
||||
def __init__(self, seed: bytes) -> None:
|
||||
self.seed = seed
|
||||
self.key = seed
|
||||
self.counter = 0
|
||||
|
||||
def __call__(self, n: int) -> bytes: # pragma: no cover - deterministic
|
||||
out = b""
|
||||
while len(out) < n:
|
||||
self.seed = hashlib.sha256(self.seed).digest()
|
||||
out += self.seed
|
||||
msg = self.counter.to_bytes(4, "big")
|
||||
out += hmac.new(self.key, msg, hashlib.sha256).digest()
|
||||
self.counter += 1
|
||||
return out[:n]
|
||||
|
||||
rsa_key = RSA.generate(2048, randfunc=DRNG(entropy))
|
||||
|
@@ -39,3 +39,21 @@ def test_pgp_key_determinism():
|
||||
entry = data["entries"][str(idx)]
|
||||
assert entry["key_type"] == "ed25519"
|
||||
assert entry["user_id"] == "Test"
|
||||
|
||||
|
||||
def test_pgp_rsa_key_determinism():
|
||||
"""RSA PGP keys should be derived deterministically."""
|
||||
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
tmp_path = Path(tmpdir)
|
||||
vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD)
|
||||
cfg_mgr = ConfigManager(vault, tmp_path)
|
||||
backup_mgr = BackupManager(tmp_path, cfg_mgr)
|
||||
entry_mgr = EntryManager(vault, backup_mgr)
|
||||
|
||||
idx = entry_mgr.add_pgp_key("pgp", TEST_SEED, key_type="rsa", user_id="Test")
|
||||
key1, fp1 = entry_mgr.get_pgp_key(idx, TEST_SEED)
|
||||
key2, fp2 = entry_mgr.get_pgp_key(idx, TEST_SEED)
|
||||
|
||||
assert fp1 == fp2
|
||||
assert key1 == key2
|
||||
|
Reference in New Issue
Block a user