2018-11-13 16:09:52 +00:00
|
|
|
from trezor import wire
|
|
|
|
from trezor.crypto import bip32
|
|
|
|
|
2018-12-07 13:26:59 +00:00
|
|
|
from apps.cardano import SEED_NAMESPACE
|
|
|
|
from apps.common import cache, storage
|
2018-11-13 16:09:52 +00:00
|
|
|
from apps.common.request_passphrase import protect_by_passphrase
|
|
|
|
|
|
|
|
|
|
|
|
class Keychain:
|
2018-11-14 18:58:07 +00:00
|
|
|
def __init__(self, path: list, root: bip32.HDNode):
|
|
|
|
self.path = path
|
2018-11-13 16:09:52 +00:00
|
|
|
self.root = root
|
|
|
|
|
2018-11-14 18:58:07 +00:00
|
|
|
def derive(self, node_path: list) -> bip32.HDNode:
|
|
|
|
# check we are in the cardano namespace
|
|
|
|
prefix = node_path[: len(self.path)]
|
|
|
|
suffix = node_path[len(self.path) :]
|
|
|
|
if prefix != self.path:
|
|
|
|
raise wire.DataError("Forbidden key path")
|
|
|
|
# derive child node from the root
|
2018-11-13 16:09:52 +00:00
|
|
|
node = self.root.clone()
|
2018-11-14 18:58:07 +00:00
|
|
|
for i in suffix:
|
2018-11-13 16:09:52 +00:00
|
|
|
node.derive_cardano(i)
|
|
|
|
return node
|
|
|
|
|
|
|
|
|
|
|
|
async def get_keychain(ctx: wire.Context) -> Keychain:
|
|
|
|
if not storage.is_initialized():
|
|
|
|
raise wire.ProcessError("Device is not initialized")
|
|
|
|
|
2018-11-14 18:58:07 +00:00
|
|
|
# derive the root node from mnemonic and passphrase
|
2018-11-13 16:09:52 +00:00
|
|
|
passphrase = cache.get_passphrase()
|
|
|
|
if passphrase is None:
|
|
|
|
passphrase = await protect_by_passphrase(ctx)
|
|
|
|
cache.set_passphrase(passphrase)
|
|
|
|
root = bip32.from_mnemonic_cardano(storage.get_mnemonic(), passphrase)
|
|
|
|
|
2018-11-14 18:58:07 +00:00
|
|
|
# derive the namespaced root node
|
2018-12-07 13:26:59 +00:00
|
|
|
for i in SEED_NAMESPACE[0]:
|
2018-11-14 18:58:07 +00:00
|
|
|
root.derive_cardano(i)
|
|
|
|
|
2018-12-07 13:26:59 +00:00
|
|
|
keychain = Keychain(SEED_NAMESPACE[0], root)
|
2018-11-13 16:09:52 +00:00
|
|
|
return keychain
|