mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-09 07:48:57 +00:00
Enforce 12-word managed account seeds
This commit is contained in:
@@ -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 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 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 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"` |
|
| 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` |
|
| 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` |
|
| 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:**
|
**Description:**
|
||||||
Creates a managed account derived from the current seed profile. The child profile is stored in `.seedpass/<parent_fp>/accounts/<child_fp>`.
|
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:**
|
**Usage Example:**
|
||||||
```bash
|
```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.
|
When loaded, the breadcrumb shows `<parent_fp> > Managed Account > <child_fp>`. Press Enter on the main menu to return to the parent profile.
|
||||||
|
@@ -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.
|
- **origin** (`string`, optional): Source identifier for imported data.
|
||||||
- **value** (`string`, optional): For `key_value` entries, stores the secret value.
|
- **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.
|
- **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.
|
- **fingerprint** (`string`, managed_account only): Identifier of the child profile, used for its directory name.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@@ -481,11 +481,13 @@ class EntryManager:
|
|||||||
parent_seed: str,
|
parent_seed: str,
|
||||||
*,
|
*,
|
||||||
index: int | None = None,
|
index: int | None = None,
|
||||||
word_count: int = 24,
|
|
||||||
notes: str = "",
|
notes: str = "",
|
||||||
archived: bool = False,
|
archived: bool = False,
|
||||||
) -> int:
|
) -> 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:
|
if index is None:
|
||||||
index = self.get_next_index()
|
index = self.get_next_index()
|
||||||
@@ -497,6 +499,8 @@ class EntryManager:
|
|||||||
seed_bytes = Bip39SeedGenerator(parent_seed).Generate()
|
seed_bytes = Bip39SeedGenerator(parent_seed).Generate()
|
||||||
bip85 = BIP85(seed_bytes)
|
bip85 = BIP85(seed_bytes)
|
||||||
|
|
||||||
|
word_count = 12
|
||||||
|
|
||||||
seed_phrase = derive_seed_phrase(bip85, index, word_count)
|
seed_phrase = derive_seed_phrase(bip85, index, word_count)
|
||||||
fingerprint = generate_fingerprint(seed_phrase)
|
fingerprint = generate_fingerprint(seed_phrase)
|
||||||
|
|
||||||
@@ -540,7 +544,7 @@ class EntryManager:
|
|||||||
seed_bytes = Bip39SeedGenerator(parent_seed).Generate()
|
seed_bytes = Bip39SeedGenerator(parent_seed).Generate()
|
||||||
bip85 = BIP85(seed_bytes)
|
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))
|
seed_index = int(entry.get("index", index))
|
||||||
return derive_seed_phrase(bip85, seed_index, words)
|
return derive_seed_phrase(bip85, seed_index, words)
|
||||||
|
|
||||||
|
@@ -1464,14 +1464,9 @@ class PasswordManager:
|
|||||||
if not label:
|
if not label:
|
||||||
print(colored("Error: Label cannot be empty.", "red"))
|
print(colored("Error: Label cannot be empty.", "red"))
|
||||||
return
|
return
|
||||||
words_input = input("Word count (12 or 24, default 24): ").strip()
|
|
||||||
notes = input("Notes (optional): ").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(
|
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)
|
seed = self.entry_manager.get_managed_account_seed(index, self.parent_seed)
|
||||||
self.is_dirty = True
|
self.is_dirty = True
|
||||||
|
@@ -26,7 +26,7 @@ def test_add_managed_account_fields_and_dir():
|
|||||||
tmp_path = Path(tmpdir)
|
tmp_path = Path(tmpdir)
|
||||||
mgr = setup_entry_manager(tmp_path)
|
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)
|
entry = mgr.retrieve_entry(idx)
|
||||||
|
|
||||||
assert entry["type"] == "managed_account"
|
assert entry["type"] == "managed_account"
|
||||||
|
@@ -29,7 +29,7 @@ def test_add_and_get_managed_account_seed():
|
|||||||
tmp_path = Path(tmpdir)
|
tmp_path = Path(tmpdir)
|
||||||
mgr = setup_mgr(tmp_path)
|
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)
|
entry = mgr.retrieve_entry(idx)
|
||||||
assert entry["type"] == "managed_account"
|
assert entry["type"] == "managed_account"
|
||||||
assert entry["kind"] == "managed_account"
|
assert entry["kind"] == "managed_account"
|
||||||
|
Reference in New Issue
Block a user