firmware/testing/test_bip39pw.py
2019-04-01 13:48:30 -04:00

110 lines
3.1 KiB
Python

# (c) Copyright 2018 by Coinkite Inc. This file is part of Coldcard <coldcardwallet.com>
# and is covered by GPLv3 license found in COPYING.
#
# BIP39 seed word encryption
#
import pytest, time
from pycoin.key.BIP32Node import BIP32Node
from pycoin.contrib.msg_signing import verify_message
from base64 import b64encode
from binascii import b2a_hex, a2b_hex
from ckcc_protocol.protocol import CCProtocolPacker, CCProtoError, CCUserRefused
from ckcc_protocol.constants import *
import json
from mnemonic import Mnemonic
# add the BIP39 test vectors
vectors = json.load(open('bip39-vectors.json'))['english']
@pytest.mark.parametrize('vector', vectors)
def test_b9p_vectors(dev, set_seed_words, need_keypress, vector, pw='RoZert'[::-1].upper()):
# Test all BIP39 vectors. Slow.
_, words, cooked, xprv = vector
seed = Mnemonic.to_seed(words, passphrase=pw)
assert seed == a2b_hex(cooked)
set_seed_words(words)
dev.send_recv(CCProtocolPacker.bip39_passphrase(pw), timeout=None)
need_keypress('y')
xpub = None
while xpub == None:
time.sleep(0.050)
xpub = dev.send_recv(CCProtocolPacker.get_passphrase_done(), timeout=None)
# check our math (ignore testnet vs. mainnet)
got = BIP32Node.from_wallet_key(xpub)
exp = BIP32Node.from_wallet_key(xprv)
assert got.public_pair() == exp.public_pair()
@pytest.mark.parametrize('pw', ['test 2', 'with some spaces',
'123 12l3kj1l2k3j 1l2k3j 1l2k3j ',
'a'*99,
'' # keep last, resets state
])
def test_b9p_basic(dev, need_keypress, pw, reset_seed_words, cap_story):
# reset from previous runs
words = reset_seed_words()
dev.send_recv(CCProtocolPacker.bip39_passphrase(pw), timeout=None)
if pw:
time.sleep(0.050)
title, body = cap_story()
assert pw not in body
# verify display of passphrase
need_keypress('2')
time.sleep(0.050)
title, body = cap_story()
assert pw in body
need_keypress('y')
done = None
while done == None:
time.sleep(0.050)
done = dev.send_recv(CCProtocolPacker.get_passphrase_done(), timeout=None)
xpub = done
assert xpub[1:4] == 'pub'
got = BIP32Node.from_wallet_key(xpub)
# what it should be
seed = Mnemonic.to_seed(words, passphrase=pw)
expect = BIP32Node.from_master_secret(seed)
assert got.public_pair() == expect.public_pair()
@pytest.mark.parametrize('pw', [
'a'*1000, # way too big
'a'*100, # just too big
])
def test_b39_fails(dev, pw):
with pytest.raises(CCProtoError):
dev.send_recv(CCProtocolPacker.bip39_passphrase(pw), timeout=None)
def test_b39p_refused(dev, need_keypress, pw='testing 123'):
# user can refuse the passphrase (cancel)
dev.send_recv(CCProtocolPacker.bip39_passphrase(pw), timeout=None)
need_keypress('x')
with pytest.raises(CCUserRefused):
done = None
while done == None:
time.sleep(0.050)
done = dev.send_recv(CCProtocolPacker.get_passphrase_done(), timeout=None)
# EOF