core/seed: add SLIP-0077 derivation to Keychain (#398)

Following #66 and #317, it would allow deriving confidential addresses and
unblinding confidential transactions' outputs.
pull/475/head
Roman Zeyde 5 years ago committed by Pavol Rusnak
parent db86092319
commit 680e18a4ba

@ -1,5 +1,6 @@
from trezor import wire
from trezor.crypto import bip32, hashlib, hmac
from trezor.crypto.curve import secp256k1
from apps.common import HARDENED, cache, mnemonic, storage
from apps.common.request_passphrase import protect_by_passphrase
@ -48,7 +49,7 @@ class Keychain:
def __del__(self) -> None:
for root in self.roots:
if root is not None:
if root is not None and hasattr(root, "__del__"):
root.__del__()
del self.roots
del self.seed
@ -93,6 +94,17 @@ class Keychain:
node.derive_path(suffix)
return node
def derive_slip77_blinding_private_key(self, script: bytes) -> bytes:
"""Following the derivation by Elements/Liquid."""
master_node = self.derive(node_path=[b"SLIP-0077"], curve_name="slip21")
return hmac.new(
key=master_node.key(), msg=script, digestmod=hashlib.sha256
).digest()
def derive_slip77_blinding_public_key(self, script: bytes) -> bytes:
private_key = self.derive_slip77_blinding_private_key(script)
return secp256k1.publickey(private_key)
async def get_keychain(ctx: wire.Context, namespaces: list) -> Keychain:
if not storage.is_initialized():

@ -1,9 +1,10 @@
from common import *
from apps.common import HARDENED
from apps.common import HARDENED, coins
from apps.common.seed import Keychain, Slip21Node, _path_hardened
from apps.wallet.sign_tx import scripts, addresses
from trezor import wire
from trezor.crypto import bip39
from trezor.crypto.curve import secp256k1
class TestKeychain(unittest.TestCase):
@ -115,6 +116,21 @@ class TestKeychain(unittest.TestCase):
with self.assertRaises(wire.DataError):
keychain.derive([b"SLIP-9999", b"Authentication key"], "slip21").key()
def test_slip77(self):
seed = bip39.seed("alcohol woman abuse must during monitor noble actual mixed trade anger aisle", "")
keychain = Keychain(seed, [["slip21", b"SLIP-0077"], ["secp256k1"]])
node = keychain.derive([44 | HARDENED, 1 | HARDENED, 0 | HARDENED, 0, 0])
coin = coins.by_name('Elements')
pubkey_hash = addresses.ecdsa_hash_pubkey(node.public_key(), coin)
script = scripts.output_script_p2pkh(pubkey_hash)
private_key = keychain.derive_slip77_blinding_private_key(script)
self.assertEqual(private_key, unhexlify(b"26f1dc2c52222394236d76e0809516255cfcca94069fd5187c0f090d18f42ad6"))
public_key = keychain.derive_slip77_blinding_public_key(script)
self.assertEqual(public_key, unhexlify(b"03e84cd853fea825bd94f5d2d46580ae0d059c734707fa7a08f5e2f612a51c1acb"))
self.assertEqual(secp256k1.publickey(private_key), public_key)
if __name__ == '__main__':
unittest.main()

Loading…
Cancel
Save