From d4221bcaffa5ec0d1e189a70f3d89443d96caad7 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Sat, 5 Jul 2025 07:39:22 -0400 Subject: [PATCH] Add SeedQR encoding and test --- src/password_manager/manager.py | 4 ++++ src/password_manager/seedqr.py | 14 ++++++++++++++ src/tests/test_seedqr_encoding.py | 15 +++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/password_manager/seedqr.py create mode 100644 src/tests/test_seedqr_encoding.py diff --git a/src/password_manager/manager.py b/src/password_manager/manager.py index 65776e8..06b7726 100644 --- a/src/password_manager/manager.py +++ b/src/password_manager/manager.py @@ -1273,6 +1273,10 @@ class PasswordManager: else: print(colored("\n[+] Retrieved Seed Phrase:\n", "green")) print(colored(phrase, "yellow")) + if confirm_action("Show SeedQR? (Y/N): "): + from password_manager.seedqr import encode_seedqr + + TotpManager.print_qr_code(encode_seedqr(phrase)) if confirm_action("Show derived entropy as hex? (Y/N): "): from local_bip85.bip85 import BIP85 from bip_utils import Bip39SeedGenerator diff --git a/src/password_manager/seedqr.py b/src/password_manager/seedqr.py new file mode 100644 index 0000000..928075c --- /dev/null +++ b/src/password_manager/seedqr.py @@ -0,0 +1,14 @@ +"""SeedQR encoding utilities.""" + +from __future__ import annotations + +from bip_utils.bip.bip39.bip39_mnemonic import Bip39Languages +from bip_utils.bip.bip39.bip39_mnemonic_utils import Bip39WordsListGetter + + +def encode_seedqr(mnemonic: str) -> str: + """Return SeedQR digit stream for a BIP-39 mnemonic.""" + wordlist = Bip39WordsListGetter().GetByLanguage(Bip39Languages.ENGLISH) + words = mnemonic.strip().split() + indices = [wordlist.GetWordIdx(word.lower()) for word in words] + return "".join(f"{idx:04d}" for idx in indices) diff --git a/src/tests/test_seedqr_encoding.py b/src/tests/test_seedqr_encoding.py new file mode 100644 index 0000000..7d0b5e7 --- /dev/null +++ b/src/tests/test_seedqr_encoding.py @@ -0,0 +1,15 @@ +import sys +from pathlib import Path + +sys.path.append(str(Path(__file__).resolve().parents[1])) + +from password_manager.seedqr import encode_seedqr + + +def test_seedqr_standard_example(): + phrase = ( + "vacuum bridge buddy supreme exclude milk consider tail " + "expand wasp pattern nuclear" + ) + expected = "192402220235174306311124037817700641198012901210" + assert encode_seedqr(phrase) == expected