Skip to content

Commit c32751a

Browse files
mflaxmanMichael Flaxman
and
Michael Flaxman
authored
add passphrase support to multiwallet (#31)
* add passphrase support * update docs Co-authored-by: Michael Flaxman <[email protected]>
1 parent f51340f commit c32751a

File tree

3 files changed

+48
-13
lines changed

3 files changed

+48
-13
lines changed

docs/multiwallet.md

-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ On TAILs, you need to setup an [Administration Password](https://tails.boum.org/
5555

5656
## Product Roadmap
5757

58-
* Add passphrase
5958
* Show change addresses (not just receiving addresses)
6059
* Save outputs to a file?
6160
* Dispay QR codes?

multiwallet.py

+47-11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import readline
44
import sys
55
from cmd import Cmd
6+
from getpass import getpass
67
from platform import platform
78
from pkg_resources import DistributionNotFound, get_distribution
89

@@ -32,6 +33,13 @@
3233
RESET_TERMINAL_COLOR = "\033[0m"
3334

3435

36+
ADVANCED_WARNING_STRING = (
37+
"WARNING: this feature is for advanced users ONLY. "
38+
"A mistake here could cause loss of funds. "
39+
"Are you sure you want to continue?"
40+
)
41+
42+
3543
def blue_fg(string):
3644
return f"\033[34m{string}{RESET_TERMINAL_COLOR}"
3745

@@ -161,17 +169,39 @@ def _get_path(is_testnet):
161169
if use_default_path:
162170
return default_path
163171
else:
164-
scary_string = (
165-
"WARNING: this feature is for advanced users. "
166-
"A mistake here could cause loss of funds. "
167-
"Are you sure you want to continue?"
168-
)
169-
if _get_bool(prompt=scary_string, default=False, scary_text=True):
172+
if _get_bool(prompt=ADVANCED_WARNING_STRING, default=False, scary_text=True):
170173
return _get_path_string()
171174
else:
172175
return _get_path(is_testnet)
173176

174177

178+
def _get_confirmed_pw():
179+
first = getpass(prompt="Enter custom passphrase: ")
180+
second = getpass(prompt="Confirm custom passphrase: ")
181+
if first != second:
182+
print_red("Passphrases don't match, please try again.")
183+
return _get_confirmed_pw()
184+
return first
185+
186+
187+
def _get_password():
188+
if not _get_bool(
189+
prompt="Use a passphrase (advanced users only)?",
190+
default=False,
191+
):
192+
return ""
193+
194+
# Reconfirm
195+
if _get_bool(
196+
prompt=ADVANCED_WARNING_STRING,
197+
default=False,
198+
scary_text=True,
199+
):
200+
return _get_confirmed_pw()
201+
else:
202+
return ""
203+
204+
175205
class WordCompleter:
176206
def __init__(self, wordlist):
177207
self.wordlist = wordlist
@@ -393,9 +423,10 @@ def __init__(self):
393423

394424
def do_generate_seed(self, arg):
395425
"""Seedpicker implementation: calculate bitcoin public and private key information from BIP39 words you draw out of a hat"""
426+
396427
first_words = _get_bip39_firstwords()
397428
use_default_checksum = _get_bool(
398-
prompt="Use default checksum index for BIP39 seed phrase?", default=True
429+
prompt="Use the default checksum index?", default=True
399430
)
400431
valid_checksums_generator = calc_valid_seedpicker_checksums(
401432
first_words=first_words
@@ -436,6 +467,8 @@ def do_generate_seed(self, arg):
436467
)
437468
last_word = valid_checksum_words[index]
438469

470+
password = _get_password()
471+
439472
is_testnet = not _get_bool(prompt="Use Mainnet?", default=False)
440473
path_to_use = _get_path(is_testnet=is_testnet)
441474

@@ -446,15 +479,18 @@ def do_generate_seed(self, arg):
446479
else:
447480
SLIP132_VERSION_BYTES = "02aa7ed3"
448481

449-
hd_priv = HDPrivateKey.from_mnemonic(first_words + " " + last_word)
482+
hd_priv = HDPrivateKey.from_mnemonic(
483+
mnemonic=f"{first_words} {last_word}", password=password.encode()
484+
)
450485
print(yellow_fg("SECRET INFO") + red_fg(" (guard this VERY carefully)"))
451486
print_green(f"Last word: {last_word}")
452487
print_green(
453-
f"Full ({len(first_words.split()) + 1} word) mnemonic (including last word: {first_words + ' ' + last_word})"
488+
f"Full ({len(first_words.split()) + 1} word) mnemonic (including last word): {first_words + ' ' + last_word}"
454489
)
455-
print("")
456-
print_yellow(f"PUBLIC KEY INFO ({'testnet' if is_testnet else 'mainnet'})")
490+
if password:
491+
print_green(f"Passphrase: {password}")
457492

493+
print_yellow(f"\nPUBLIC KEY INFO ({'testnet' if is_testnet else 'mainnet'})")
458494
print_yellow("Copy-paste this into Specter-Desktop:")
459495
print_green(
460496
" [{}{}]{}".format(

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setup(
77
name="buidl",
8-
version="0.2.5",
8+
version="0.2.6",
99
author="Example Author",
1010
author_email="[email protected]",
1111
description="An easy-to-use and fully featured bitcoin library written in pure python (no dependencies).",

0 commit comments

Comments
 (0)