Enforce 12-word managed account seeds

This commit is contained in:
thePR0M3TH3AN
2025-07-07 22:28:09 -04:00
parent 988a50e066
commit 34784eefe0
6 changed files with 15 additions and 14 deletions

View File

@@ -81,7 +81,7 @@ The following table provides a quick reference to all available advanced CLI com
| Add Notes to an Entry | `add-notes` | `-AN` | `--add-notes` | `seedpass add-notes --index 3 --notes "This is a secured account"` |
| Add Tags to an Entry | `add-tags` | `-AT` | `--add-tags` | `seedpass add-tags --index 3 --tags "personal,finance"` |
| Add Key/Value entry | `add-kv` | `-KV` | `--add-kv` | `seedpass add-kv --label "API" --value "secret"`
| Add Managed Account | `add-managed` | `-AM` | `--add-managed` | `seedpass add-managed --label "Account" --words 12`
| Add Managed Account | `add-managed` | `-AM` | `--add-managed` | `seedpass add-managed --label "Account"`
| Search by Tag or Title | `search-by` | `-SB` | `--search-by` | `seedpass search-by --tag "work"` or `seedpass search-by --title "GitHub"` |
| Automatically Post Deltas After Edit | `auto-post` | `-AP` | `--auto-post` | `seedpass auto-post --enable` or `seedpass auto-post --disable` |
| Initial Setup Prompt for Seed Generation/Import | `setup` | `-ST` | `--setup` | `seedpass setup` |
@@ -612,9 +612,11 @@ seedpass add-kv --label "API" --value "secret" --notes "Service token"
**Description:**
Creates a managed account derived from the current seed profile. The child profile is stored in `.seedpass/<parent_fp>/accounts/<child_fp>`.
Managed account seeds are always **12 words** long.
**Usage Example:**
```bash
seedpass add-managed --label "Account" --words 12
seedpass add-managed --label "Account"
```
When loaded, the breadcrumb shows `<parent_fp> > Managed Account > <child_fp>`. Press Enter on the main menu to return to the parent profile.

View File

@@ -95,7 +95,7 @@ Each entry is stored within `seedpass_entries_db.json.enc` under the `entries` d
- **origin** (`string`, optional): Source identifier for imported data.
- **value** (`string`, optional): For `key_value` entries, stores the secret value.
- **index** (`integer`, optional): BIP-85 derivation index for entries that derive material from a seed.
- **word_count** (`integer`, managed_account only): Number of words when deriving the child seed (12 or 24).
- **word_count** (`integer`, managed_account only): Number of words in the child seed. Managed accounts always use `12`.
- **fingerprint** (`string`, managed_account only): Identifier of the child profile, used for its directory name.
Example:

View File

@@ -481,11 +481,13 @@ class EntryManager:
parent_seed: str,
*,
index: int | None = None,
word_count: int = 24,
notes: str = "",
archived: bool = False,
) -> int:
"""Add a new managed account seed entry."""
"""Add a new managed account seed entry.
Managed accounts always use a 12-word seed phrase.
"""
if index is None:
index = self.get_next_index()
@@ -497,6 +499,8 @@ class EntryManager:
seed_bytes = Bip39SeedGenerator(parent_seed).Generate()
bip85 = BIP85(seed_bytes)
word_count = 12
seed_phrase = derive_seed_phrase(bip85, index, word_count)
fingerprint = generate_fingerprint(seed_phrase)
@@ -540,7 +544,7 @@ class EntryManager:
seed_bytes = Bip39SeedGenerator(parent_seed).Generate()
bip85 = BIP85(seed_bytes)
words = int(entry.get("word_count", 24))
words = int(entry.get("word_count", 12))
seed_index = int(entry.get("index", index))
return derive_seed_phrase(bip85, seed_index, words)

View File

@@ -1464,14 +1464,9 @@ class PasswordManager:
if not label:
print(colored("Error: Label cannot be empty.", "red"))
return
words_input = input("Word count (12 or 24, default 24): ").strip()
notes = input("Notes (optional): ").strip()
if words_input and words_input not in {"12", "24"}:
print(colored("Invalid word count. Choose 12 or 24.", "red"))
return
words = int(words_input) if words_input else 24
index = self.entry_manager.add_managed_account(
label, self.parent_seed, word_count=words, notes=notes
label, self.parent_seed, notes=notes
)
seed = self.entry_manager.get_managed_account_seed(index, self.parent_seed)
self.is_dirty = True

View File

@@ -26,7 +26,7 @@ def test_add_managed_account_fields_and_dir():
tmp_path = Path(tmpdir)
mgr = setup_entry_manager(tmp_path)
idx = mgr.add_managed_account("acct", TEST_SEED, word_count=12)
idx = mgr.add_managed_account("acct", TEST_SEED)
entry = mgr.retrieve_entry(idx)
assert entry["type"] == "managed_account"

View File

@@ -29,7 +29,7 @@ def test_add_and_get_managed_account_seed():
tmp_path = Path(tmpdir)
mgr = setup_mgr(tmp_path)
idx = mgr.add_managed_account("acct", TEST_SEED, word_count=12)
idx = mgr.add_managed_account("acct", TEST_SEED)
entry = mgr.retrieve_entry(idx)
assert entry["type"] == "managed_account"
assert entry["kind"] == "managed_account"