Skip to content

Commit

Permalink
BIP-85 passwords
Browse files Browse the repository at this point in the history
  • Loading branch information
scgbckbone committed Jul 13, 2022
1 parent 435a058 commit 3f67f1f
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 1 deletion.
10 changes: 10 additions & 0 deletions bip85/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from pycoin.symbols.btc import network as BTC
from pycoin.encoding.bytes32 import from_bytes_32, to_bytes_32
import base58
import base64


class BIP85(object):
Expand Down Expand Up @@ -59,6 +60,15 @@ def bip32_xprv_to_hex(self, path, width, xprv_string):
ent = self.bip32_xprv_to_entropy(path, xprv_string)
return ent[0:width].hex()

def bip32_xprv_to_pwd(self, path, pwd_len, xprv_string):
# export entropy as hex
if not 20 <= pwd_len <= 86:
raise ValueError("'pwd_len' has to be in closed interval <20..86>")
path = self._decorate_path(path)
ent = self.bip32_xprv_to_entropy(path, xprv_string)
ent_b64 = base64.b64encode(ent).decode().strip()
return ent_b64[:pwd_len]

def bip32_xprv_to_xprv(self, path, xprv_string):
path = self._decorate_path(path)
ent = self.bip32_xprv_to_entropy(path, xprv_string)
Expand Down
9 changes: 8 additions & 1 deletion bip85/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,19 @@ def wif(xprv_string, index):


def hex(xprv_string, index, width):
# m/83696968'/128169p'/index'
# m/83696968'/128169p'/width'/index'
bip85 = BIP85()
path = f"83696968p/128169p/{width}p/{index}p"
return bip85.bip32_xprv_to_hex(path, width, xprv_string)


def pwd(xprv_string, index, pwd_len):
# m/83696968'/707764'/pwd_len'/index'
bip85 = BIP85()
path = f"83696968p/707764p/{pwd_len}p/{index}p"
return bip85.bip32_xprv_to_pwd(path, pwd_len, xprv_string)


def xprv(xprv_string, index):
# 83696968'/32'/index'
bip85 = BIP85()
Expand Down
10 changes: 10 additions & 0 deletions bip85/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ def main():
required=True,
help='Number of bytes to generate')
subparsers.add_parser('xprv', help='Derive an XPRV (master private key)')
app_pwd_parser = subparsers.add_parser('pwd',
help='Derive a password')
app_pwd_parser.add_argument('--pwd-len',
type=int,
choices=range(20,87),
metavar="[20-86]",
required=True,
help='Desired password length')
args = parser.parse_args()
xprv = _get_xprv_from_args(args)
print(f"Using master private key: {xprv}")
Expand All @@ -77,6 +85,8 @@ def main():
print(app.hex(xprv, args.index, args.num_bytes))
elif args.bip85_app == 'xprv':
print(app.xprv(xprv, args.index))
elif args.bip85_app == "pwd":
print(app.pwd(xprv, args.index, args.pwd_len))


if __name__ == "__main__":
Expand Down
20 changes: 20 additions & 0 deletions bip85/tests/test_bip85.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,26 @@ def test_hex(path, width, expect):
bip85 = BIP85()
assert bip85.bip32_xprv_to_hex(path, width, XPRV) == expect

@pytest.mark.parametrize('path, pwd_len, expect', [
("83696968'/707764'/20'/0'", 20, "RrH7uVI0XlpddCbiuYV+"),
("83696968'/707764'/21'/0'", 21, "dKLoepugzdVJvdL56ogNV"),
("83696968'/707764'/24'/0'", 24, "vtV6sdNQTKpuefUMOHOKwUp1"),
("83696968'/707764'/32'/1234'", 32, "mBhJgXCJd6IpdOu1cc/D1wU+5sxj/1tK"),
("83696968'/707764'/64'/1234'", 64, "HBqosVLBhKneX8ZCZgLdvmA8biOdUV2S/AteE5Rs8sMT0pfG3aItk/IrHGEpY9um"),
("83696968'/707764'/86'/1234'", 86, "7n3VQ63qjgY6OJBQxqWYToNRfzzN5J8DwN1D8JqlZfnsF+1LdPXG3gkOXighX4iKyKip8nRIhVVVObh/G41F7g"),
])
def test_pwd(path, pwd_len, expect):
bip85 = BIP85()
assert bip85.bip32_xprv_to_pwd(path, pwd_len, XPRV) == expect

def test_pwd_out_of_range():
bip85 = BIP85()
with pytest.raises(ValueError):
bip85.bip32_xprv_to_pwd("83696968'/707764'/87'/0'", 87, XPRV)

with pytest.raises(ValueError):
bip85.bip32_xprv_to_pwd("83696968'/707764'/19'/0'", 19, XPRV)

def test_bipentropy_applications():
assert app.bip39(XPRV, 'english', 18, 0) == \
'near account window bike charge season chef number sketch tomorrow excuse sniff circle vital hockey outdoor supply token'
Expand Down

0 comments on commit 3f67f1f

Please sign in to comment.