diff --git a/core/tests/test_apps.cardano.address.py b/core/tests/test_apps.cardano.address.py index b68d28c6ce..67c94870bc 100644 --- a/core/tests/test_apps.cardano.address.py +++ b/core/tests/test_apps.cardano.address.py @@ -1,6 +1,6 @@ from common import * from trezor import wire -from trezor.crypto import bip32, slip39 +from trezor.crypto import cardano, slip39 from trezor.enums import CardanoAddressType from trezor.messages import CardanoAddressParametersType from trezor.messages import CardanoBlockchainPointerType @@ -17,12 +17,14 @@ if not utils.BITCOIN_ONLY: @unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin") class TestCardanoAddress(unittest.TestCase): - def test_hardened_address_derivation_scheme(self): + def setUp(self): mnemonic = "all all all all all all all all all all all all" passphrase = "" - node = bip32.from_mnemonic_cardano(mnemonic, passphrase) - keychain = Keychain(node) + secret = cardano.derive_icarus(mnemonic, passphrase, False) + node = cardano.from_secret(secret) + self.keychain = Keychain(node) + def test_hardened_address_derivation_scheme(self): addresses = [ "Ae2tdPwUPEZ98eHFwxSsPBDz73amioKpr58Vw85mP1tMkzq8siaftiejJ3j", "Ae2tdPwUPEZKA971NCHuHqaEnxZDFWPzH3fEsLpDnbEpG6UeMRHnRzCzEwK", @@ -35,7 +37,7 @@ class TestCardanoAddress(unittest.TestCase): address_type=CardanoAddressType.BYRON, address_n=[0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, 0x80000000 + i], ) - address = derive_human_readable_address(keychain, address_parameters, protocol_magics.MAINNET, network_ids.MAINNET) + address = derive_human_readable_address(self.keychain, address_parameters, protocol_magics.MAINNET, network_ids.MAINNET) self.assertEqual(expected, address) nodes = [ @@ -60,18 +62,13 @@ class TestCardanoAddress(unittest.TestCase): ] for i, (priv, ext, pub, chain) in enumerate(nodes): - n = keychain.derive([0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, 0x80000000 + i]) + n = self.keychain.derive([0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, 0x80000000 + i]) self.assertEqual(hexlify(n.private_key()), priv) self.assertEqual(hexlify(n.private_key_ext()), ext) self.assertEqual(hexlify(seed.remove_ed25519_prefix(n.public_key())), pub) self.assertEqual(hexlify(n.chain_code()), chain) def test_non_hardened_address_derivation_scheme(self): - mnemonic = "all all all all all all all all all all all all" - passphrase = "" - node = bip32.from_mnemonic_cardano(mnemonic, passphrase) - keychain = Keychain(node) - addresses = [ "Ae2tdPwUPEZ5YUb8sM3eS8JqKgrRLzhiu71crfuH2MFtqaYr5ACNRdsswsZ", "Ae2tdPwUPEZJb8r1VZxweSwHDTYtqeYqF39rZmVbrNK62JHd4Wd7Ytsc8eG", @@ -84,7 +81,7 @@ class TestCardanoAddress(unittest.TestCase): address_type=CardanoAddressType.BYRON, address_n=[0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, i], ) - address = derive_human_readable_address(keychain, address_parameters, protocol_magics.MAINNET, network_ids.MAINNET) + address = derive_human_readable_address(self.keychain, address_parameters, protocol_magics.MAINNET, network_ids.MAINNET) self.assertEqual(address, expected) nodes = [ @@ -109,7 +106,7 @@ class TestCardanoAddress(unittest.TestCase): ] for i, (priv, ext, pub, chain) in enumerate(nodes): - n = keychain.derive([0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, i]) + n = self.keychain.derive([0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, i]) self.assertEqual(hexlify(n.private_key()), priv) self.assertEqual(hexlify(n.private_key_ext()), ext) self.assertEqual(hexlify(seed.remove_ed25519_prefix(n.public_key())), pub) @@ -117,17 +114,12 @@ class TestCardanoAddress(unittest.TestCase): def test_root_address_derivation_scheme(self): - mnemonic = "all all all all all all all all all all all all" - passphrase = "" - node = bip32.from_mnemonic_cardano(mnemonic, passphrase) - keychain = Keychain(node) - # 44'/1815' address_parameters = CardanoAddressParametersType( address_type=CardanoAddressType.BYRON, address_n=[0x80000000 | 44, 0x80000000 | 1815], ) - address = derive_human_readable_address(keychain, address_parameters, protocol_magics.MAINNET, network_ids.MAINNET) + address = derive_human_readable_address(self.keychain, address_parameters, protocol_magics.MAINNET, network_ids.MAINNET) self.assertEqual(address, "Ae2tdPwUPEZ2FGHX3yCKPSbSgyuuTYgMxNq652zKopxT4TuWvEd8Utd92w3") priv, ext, pub, chain = ( @@ -137,7 +129,7 @@ class TestCardanoAddress(unittest.TestCase): b"02ac67c59a8b0264724a635774ca2c242afa10d7ab70e2bf0a8f7d4bb10f1f7a" ) - n = keychain.derive([0x80000000 | 44, 0x80000000 | 1815]) + n = self.keychain.derive([0x80000000 | 44, 0x80000000 | 1815]) self.assertEqual(hexlify(n.private_key()), priv) self.assertEqual(hexlify(n.private_key_ext()), ext) self.assertEqual(hexlify(seed.remove_ed25519_prefix(n.public_key())), pub) @@ -164,7 +156,7 @@ class TestCardanoAddress(unittest.TestCase): identifier, exponent, ems = slip39.recover_ems(mnemonics) master_secret = slip39.decrypt(ems, passphrase, exponent, identifier) - node = bip32.from_seed(master_secret, "ed25519 cardano seed") + node = cardano.from_seed_slip23(master_secret) # Check root node. root_priv = b"c0fe4a6973df4de06262693fc9186f71faf292960350882d49456bf108d13954" @@ -231,7 +223,7 @@ class TestCardanoAddress(unittest.TestCase): identifier, exponent, ems = slip39.recover_ems(mnemonics) master_secret = slip39.decrypt(ems, passphrase, exponent, identifier) - node = bip32.from_seed(master_secret, "ed25519 cardano seed") + node = cardano.from_seed_slip23(master_secret) # Check root node. root_priv = b"90633724b5daf770a8b420b8658e7d8bc21e066b60ec8cd4d5730681cc294e4f" @@ -286,11 +278,6 @@ class TestCardanoAddress(unittest.TestCase): self.assertEqual(hexlify(n.chain_code()), chain) def test_testnet_byron_address(self): - mnemonic = "all all all all all all all all all all all all" - passphrase = "" - node = bip32.from_mnemonic_cardano(mnemonic, passphrase) - keychain = Keychain(node) - addresses = [ "2657WMsDfac5F3zbgs9BwNWx3dhGAJERkAL93gPa68NJ2i8mbCHm2pLUHWSj8Mfea", "2657WMsDfac6ezKWszxLFqJjSUgpg9NgxKc1koqi24sVpRaPhiwMaExk4useKn5HA", @@ -303,15 +290,10 @@ class TestCardanoAddress(unittest.TestCase): address_type=CardanoAddressType.BYRON, address_n=[0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, i], ) - address = derive_human_readable_address(keychain, address_parameters, protocol_magics.TESTNET, 0) + address = derive_human_readable_address(self.keychain, address_parameters, protocol_magics.TESTNET, 0) self.assertEqual(expected, address) def test_derive_address(self): - mnemonic = "all all all all all all all all all all all all" - passphrase = "" - node = bip32.from_mnemonic_cardano(mnemonic, passphrase) - keychain = Keychain(node) - address_parameters = { "BASE": CardanoAddressParametersType( address_type=CardanoAddressType.BASE, @@ -429,7 +411,7 @@ class TestCardanoAddress(unittest.TestCase): for network_id, address_type, address_parameters, expected_address in test_vectors: validate_address_parameters(address_parameters) - actual_address = derive_human_readable_address(keychain, address_parameters, protocol_magics.MAINNET, network_id) + actual_address = derive_human_readable_address(self.keychain, address_parameters, protocol_magics.MAINNET, network_id) self.assertEqual(actual_address, expected_address) diff --git a/core/tests/test_apps.cardano.get_public_key.py b/core/tests/test_apps.cardano.get_public_key.py index bc4da1aa35..4b1b17ea90 100644 --- a/core/tests/test_apps.cardano.get_public_key.py +++ b/core/tests/test_apps.cardano.get_public_key.py @@ -2,16 +2,21 @@ from common import * from apps.cardano.seed import Keychain from apps.cardano.get_public_key import _get_public_key -from trezor.crypto import bip32, slip39 +from trezor.crypto import cardano, slip39 @unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin") class TestCardanoGetPublicKey(unittest.TestCase): + @staticmethod + def make_keychain_bip39(mnemonic, passphrase): + secret = cardano.derive_icarus(mnemonic, passphrase, True) + node = cardano.from_secret(secret) + return Keychain(node) + def test_get_public_key_scheme_12_words(self): mnemonic = "all all all all all all all all all all all all" passphrase = "" - node = bip32.from_mnemonic_cardano(mnemonic, passphrase) - keychain = Keychain(node) + keychain = self.make_keychain_bip39(mnemonic, passphrase) derivation_paths = [ [0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, 0x80000000], @@ -71,8 +76,7 @@ class TestCardanoGetPublicKey(unittest.TestCase): def test_get_public_key_scheme_18_words(self): mnemonic = "found differ bulb shadow wrist blue bind vessel deposit tip pelican action surprise weapon check fiction muscle this" passphrase = "" - node = bip32.from_mnemonic_cardano(mnemonic, passphrase) - keychain = Keychain(node) + keychain = self.make_keychain_bip39(mnemonic, passphrase) derivation_paths = [ [0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, 0x80000000], @@ -105,8 +109,7 @@ class TestCardanoGetPublicKey(unittest.TestCase): def test_get_public_key_scheme_24_words(self): mnemonic = "balance exotic ranch knife glory slow tape favorite yard gym awake ill exist useless parent aim pig stay effort into square gasp credit butter" passphrase = "" - node = bip32.from_mnemonic_cardano(mnemonic, passphrase) - keychain = Keychain(node) + keychain = self.make_keychain_bip39(mnemonic, passphrase) derivation_paths = [ [0x80000000 | 44, 0x80000000 | 1815, 0x80000000, 0, 0x80000000], @@ -149,7 +152,7 @@ class TestCardanoGetPublicKey(unittest.TestCase): identifier, exponent, ems = slip39.recover_ems(mnemonics) master_secret = slip39.decrypt(ems, passphrase, exponent, identifier) - node = bip32.from_seed(master_secret, "ed25519 cardano seed") + node = cardano.from_seed_slip23(master_secret) keychain = Keychain(node) @@ -198,7 +201,7 @@ class TestCardanoGetPublicKey(unittest.TestCase): identifier, exponent, ems = slip39.recover_ems(mnemonics) master_secret = slip39.decrypt(ems, passphrase, exponent, identifier) - node = bip32.from_seed(master_secret, "ed25519 cardano seed") + node = cardano.from_seed_slip23(master_secret) keychain = Keychain(node) diff --git a/core/tests/test_apps.cardano.keychain.py b/core/tests/test_apps.cardano.keychain.py deleted file mode 100644 index 5e2645f3fd..0000000000 --- a/core/tests/test_apps.cardano.keychain.py +++ /dev/null @@ -1,66 +0,0 @@ -from common import * -from trezor import wire -from trezor.crypto import bip32, slip39 - -from apps.common import seed -from apps.common.paths import HARDENED - -if not utils.BITCOIN_ONLY: - from apps.cardano.seed import Keychain - from apps.cardano.get_public_key import _get_public_key - - -@unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin") -class TestCardanoKeychain(unittest.TestCase): - def test_various_paths_at_once(self): - mnemonic = "test walk nut penalty hip pave soap entry language right filter choice" - passphrase = "" - node = bip32.from_mnemonic_cardano(mnemonic, passphrase) - keychain = Keychain(node) - - derivation_paths = [ - [44 | HARDENED, 1815 | HARDENED, HARDENED, 0, 0], - [44 | HARDENED, 1815 | HARDENED, HARDENED, 0, 1], - [1852 | HARDENED, 1815 | HARDENED, HARDENED, 0, 0], - [1852 | HARDENED, 1815 | HARDENED, HARDENED, 0, 1], - [44 | HARDENED, 1815 | HARDENED, HARDENED, 0, 2], - [1852 | HARDENED, 1815 | HARDENED, HARDENED, 0, 2] - ] - - public_keys = [ - b'badd2852ccda7492364be0f88f2ba0b78c5f2d7179a941f1d19f756112b66afa', - b'34377409140c061d76778626d43456880d5471c1cbade8c372cb6a3be9678072', - b'73fea80d424276ad0978d4fe5310e8bc2d485f5f6bb3bf87612989f112ad5a7d', - b'f626ab887eb5f40b502463ccf2ec5a7311676ee9e5d55c492059a366c0b4d4a1', - b'408ee7b2d1c84d7899dba07150fae88c5411974f1762cb659dd928db8aac206b', - b'86e8a3880767e1ed521a47de1e031d47f33d5a8095be467bffbbd3295e27258e' - ] - - chain_codes = [ - b"e1c5d15875d3ed68667978af38fe3fe586511d87a784c0962a333c21e63a865d", - b"15c987276326a82defa4cb6762d43442f09e5dcbcc37fa0c58f24ae2dba3d3eb", - b"dd75e154da417becec55cdd249327454138f082110297d5e87ab25e15fad150f", - b"f7ab126f2884db9059fa09ca83be6b8bd0250426aeb62191bdd9861457b8bc91", - b"18d5c9d20c8d23bed068c9ff3a1126b940f0e537f9d94891828a999dda6fafd1", - b"580bba4bb0b9c56974e16a6998322a91e857e2fac28674404da993f6197fd29f" - ] - - xpub_keys = [ - "badd2852ccda7492364be0f88f2ba0b78c5f2d7179a941f1d19f756112b66afae1c5d15875d3ed68667978af38fe3fe586511d87a784c0962a333c21e63a865d", - "34377409140c061d76778626d43456880d5471c1cbade8c372cb6a3be967807215c987276326a82defa4cb6762d43442f09e5dcbcc37fa0c58f24ae2dba3d3eb", - "73fea80d424276ad0978d4fe5310e8bc2d485f5f6bb3bf87612989f112ad5a7ddd75e154da417becec55cdd249327454138f082110297d5e87ab25e15fad150f", - "f626ab887eb5f40b502463ccf2ec5a7311676ee9e5d55c492059a366c0b4d4a1f7ab126f2884db9059fa09ca83be6b8bd0250426aeb62191bdd9861457b8bc91", - "408ee7b2d1c84d7899dba07150fae88c5411974f1762cb659dd928db8aac206b18d5c9d20c8d23bed068c9ff3a1126b940f0e537f9d94891828a999dda6fafd1", - "86e8a3880767e1ed521a47de1e031d47f33d5a8095be467bffbbd3295e27258e580bba4bb0b9c56974e16a6998322a91e857e2fac28674404da993f6197fd29f" - ] - - for index, derivation_path in enumerate(derivation_paths): - key = _get_public_key(keychain, derivation_path) - - self.assertEqual(hexlify(key.node.public_key), public_keys[index]) - self.assertEqual(hexlify(key.node.chain_code), chain_codes[index]) - self.assertEqual(key.xpub, xpub_keys[index]) - - -if __name__ == '__main__': - unittest.main() diff --git a/core/tests/test_apps.cardano.native_script.py b/core/tests/test_apps.cardano.native_script.py index 0a344fee8f..ccad1c6aa7 100644 --- a/core/tests/test_apps.cardano.native_script.py +++ b/core/tests/test_apps.cardano.native_script.py @@ -1,6 +1,6 @@ from common import * from trezor import wire -from trezor.crypto import bip32 +from trezor.crypto import cardano from trezor.enums import CardanoNativeScriptType from trezor.messages import CardanoNativeScript @@ -280,7 +280,8 @@ class TestCardanoNativeScript(unittest.TestCase): def test_get_native_script_hash(self): mnemonic = "all all all all all all all all all all all all" passphrase = "" - node = bip32.from_mnemonic_cardano(mnemonic, passphrase) + secret = cardano.derive_icarus(mnemonic, passphrase, False) + node = cardano.from_secret(secret) keychain = Keychain(node) for script, expected_hash in VALID_NATIVE_SCRIPTS: diff --git a/core/tests/test_apps.cardano.seed.py b/core/tests/test_apps.cardano.seed.py new file mode 100644 index 0000000000..180b400dc0 --- /dev/null +++ b/core/tests/test_apps.cardano.seed.py @@ -0,0 +1,122 @@ +from common import * +from trezor.crypto import cardano + +from apps.common.paths import HARDENED + +if not utils.BITCOIN_ONLY: + from apps.cardano.seed import Keychain + from apps.cardano.get_public_key import _get_public_key + + +@unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin") +class TestCardanoKeychain(unittest.TestCase): + def test_various_paths_at_once(self): + mnemonic = ( + "test walk nut penalty hip pave soap entry language right filter choice" + ) + passphrase = "" + secret = cardano.derive_icarus(mnemonic, passphrase, True) + node = cardano.from_secret(secret) + keychain = Keychain(node) + + derivation_paths = [ + [44 | HARDENED, 1815 | HARDENED, HARDENED, 0, 0], + [44 | HARDENED, 1815 | HARDENED, HARDENED, 0, 1], + [1852 | HARDENED, 1815 | HARDENED, HARDENED, 0, 0], + [1852 | HARDENED, 1815 | HARDENED, HARDENED, 0, 1], + [44 | HARDENED, 1815 | HARDENED, HARDENED, 0, 2], + [1852 | HARDENED, 1815 | HARDENED, HARDENED, 0, 2], + ] + + public_keys = [ + b"badd2852ccda7492364be0f88f2ba0b78c5f2d7179a941f1d19f756112b66afa", + b"34377409140c061d76778626d43456880d5471c1cbade8c372cb6a3be9678072", + b"73fea80d424276ad0978d4fe5310e8bc2d485f5f6bb3bf87612989f112ad5a7d", + b"f626ab887eb5f40b502463ccf2ec5a7311676ee9e5d55c492059a366c0b4d4a1", + b"408ee7b2d1c84d7899dba07150fae88c5411974f1762cb659dd928db8aac206b", + b"86e8a3880767e1ed521a47de1e031d47f33d5a8095be467bffbbd3295e27258e", + ] + + chain_codes = [ + b"e1c5d15875d3ed68667978af38fe3fe586511d87a784c0962a333c21e63a865d", + b"15c987276326a82defa4cb6762d43442f09e5dcbcc37fa0c58f24ae2dba3d3eb", + b"dd75e154da417becec55cdd249327454138f082110297d5e87ab25e15fad150f", + b"f7ab126f2884db9059fa09ca83be6b8bd0250426aeb62191bdd9861457b8bc91", + b"18d5c9d20c8d23bed068c9ff3a1126b940f0e537f9d94891828a999dda6fafd1", + b"580bba4bb0b9c56974e16a6998322a91e857e2fac28674404da993f6197fd29f", + ] + + xpub_keys = [ + "badd2852ccda7492364be0f88f2ba0b78c5f2d7179a941f1d19f756112b66afae1c5d15875d3ed68667978af38fe3fe586511d87a784c0962a333c21e63a865d", + "34377409140c061d76778626d43456880d5471c1cbade8c372cb6a3be967807215c987276326a82defa4cb6762d43442f09e5dcbcc37fa0c58f24ae2dba3d3eb", + "73fea80d424276ad0978d4fe5310e8bc2d485f5f6bb3bf87612989f112ad5a7ddd75e154da417becec55cdd249327454138f082110297d5e87ab25e15fad150f", + "f626ab887eb5f40b502463ccf2ec5a7311676ee9e5d55c492059a366c0b4d4a1f7ab126f2884db9059fa09ca83be6b8bd0250426aeb62191bdd9861457b8bc91", + "408ee7b2d1c84d7899dba07150fae88c5411974f1762cb659dd928db8aac206b18d5c9d20c8d23bed068c9ff3a1126b940f0e537f9d94891828a999dda6fafd1", + "86e8a3880767e1ed521a47de1e031d47f33d5a8095be467bffbbd3295e27258e580bba4bb0b9c56974e16a6998322a91e857e2fac28674404da993f6197fd29f", + ] + + for index, derivation_path in enumerate(derivation_paths): + key = _get_public_key(keychain, derivation_path) + + self.assertEqual(hexlify(key.node.public_key), public_keys[index]) + self.assertEqual(hexlify(key.node.chain_code), chain_codes[index]) + self.assertEqual(key.xpub, xpub_keys[index]) + + +@unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin") +class TestCardanoDerivation(unittest.TestCase): + def test_icarus(self): + # vectors from: + # https://github.com/cardano-foundation/CIPs/blob/master/CIP-0003/Icarus.md + mnemonic = "eight country switch draw meat scout mystery blade tip drift useless good keep usage title" + + secret = cardano.derive_icarus(mnemonic, "", False) + self.assertEqual( + hexlify(secret).decode(), + "c065afd2832cd8b087c4d9ab7011f481ee1e0721e78ea5dd609f3ab3f156d245" + "d176bd8fd4ec60b4731c3918a2a72a0226c0cd119ec35b47e4d55884667f552a" + "23f7fdcd4a10c6cd2c7393ac61d877873e248f417634aa3d812af327ffe9d620", + ) + secret_trezor = cardano.derive_icarus(mnemonic, "", True) + self.assertEqual(secret, secret_trezor) + + secret = cardano.derive_icarus(mnemonic, "foo", False) + self.assertEqual( + hexlify(secret).decode(), + "70531039904019351e1afb361cd1b312a4d0565d4ff9f8062d38acf4b15cce41" + "d7b5738d9c893feea55512a3004acb0d222c35d3e3d5cde943a15a9824cbac59" + "443cf67e589614076ba01e354b1a432e0e6db3b59e37fc56b5fb0222970a010e", + ) + secret_trezor = cardano.derive_icarus(mnemonic, "foo", True) + self.assertEqual(secret, secret_trezor) + + def test_icarus_trezor(self): + mnemonic = ( + "void come effort suffer camp survey warrior heavy " + "shoot primary clutch crush open amazing screen patrol " + "group space point ten exist slush involve unfold" + ) + secret = cardano.derive_icarus(mnemonic, "", True) + self.assertEqual( + hexlify(secret).decode(), + "409bb7a2998ec48029c8d2956fabd043a368ccc9b5120e42dd8a5c7145d08f45" + "e8e8664d06f62b4fc3bab0134778af27ddf059a4ad1eb0efefeedd8189bbfe00" + "deb289c5cdc2cf8ccfa19aea63b28424a4b0045b4b762292d46b73aa1c5cc99a", + ) + secret_icarus = cardano.derive_icarus(mnemonic, "", False) + self.assertNotEqual(secret, secret_icarus) + + PASSPHRASE = "foo" + secret = cardano.derive_icarus(mnemonic, PASSPHRASE, True) + self.assertEqual( + hexlify(secret).decode(), + "c8ab7a160a66bfa7a118f553c4eebfe7444e36e449dac7d6eeae21f3bbaa9551" + "8593025160068776a4d61c0efc4f698585bb59f1aebe93c58e1eaf557ab59502" + "d9f68fbea3049bc2255d15fc63803e9c3dbb78abff2d53f8356794807d402568", + ) + secret_icarus = cardano.derive_icarus(mnemonic, PASSPHRASE, False) + self.assertNotEqual(secret, secret_icarus) + + +if __name__ == "__main__": + unittest.main()