def test_two_changes(self, client): # see 87be0736f202f7c2bff0781b42bad3e0cdcb54761939da69ea793a3735552c56 # tx: e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd # input 0: 0.31 BTC inp1 = messages.TxInputType( address_n=parse_path("44'/1'/0'/0/0"), amount=31000000, prev_hash=TXHASH_e5040e, prev_index=0, ) out1 = messages.TxOutputType( address="msj42CCGruhRsFrGATiUuh25dtxYtnpbTx", amount=30090000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out_change1 = messages.TxOutputType( address_n=parse_path("44'/1'/0'/1/0"), amount=900000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out_change2 = messages.TxOutputType( address_n=parse_path("44'/1'/0'/1/1"), amount=10000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses( [ request_input(0), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), request_output(1), request_output(2), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(TXHASH_e5040e), request_input(0, TXHASH_e5040e), request_output(0, TXHASH_e5040e), request_output(1, TXHASH_e5040e), request_input(0), request_output(0), request_output(1), request_output(2), request_output(0), request_output(1), request_output(2), request_finished(), ] ) btc.sign_tx( client, "Testnet", [inp1], [out1, out_change1, out_change2], prev_txes=TX_CACHE_TESTNET, )
def test_pin_passphrase(self, client): mnemonic = MNEMONIC12.split(" ") ret = client.call_raw( proto.RecoveryDevice( passphrase_protection=True, pin_protection=True, label="label", enforce_wordlist=True, )) # Confirm Recovery assert isinstance(ret, proto.ButtonRequest) client.debug.press_yes() ret = client.call_raw(proto.ButtonAck()) # Enter PIN for first time assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.Other) client.debug.input("654") ret = client.call_raw(proto.ButtonAck()) # Enter PIN for second time assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.Other) client.debug.input("654") ret = client.call_raw(proto.ButtonAck()) # Homescreen assert isinstance(ret, proto.ButtonRequest) client.debug.press_yes() ret = client.call_raw(proto.ButtonAck()) # Enter word count assert ret == proto.ButtonRequest( code=proto.ButtonRequestType.MnemonicWordCount) client.debug.input(str(len(mnemonic))) ret = client.call_raw(proto.ButtonAck()) # Homescreen assert isinstance(ret, proto.ButtonRequest) client.debug.press_yes() ret = client.call_raw(proto.ButtonAck()) # Enter mnemonic words assert ret == proto.ButtonRequest( code=proto.ButtonRequestType.MnemonicInput) client.transport.write(proto.ButtonAck()) for word in mnemonic: client.debug.input(word) ret = client.transport.read() # Confirm success assert isinstance(ret, proto.ButtonRequest) client.debug.press_yes() ret = client.call_raw(proto.ButtonAck()) # Workflow succesfully ended assert ret == proto.Success(message="Device recovered") # Mnemonic is the same client.init_device() assert client.debug.read_mnemonic_secret() == MNEMONIC12.encode() assert client.features.pin_protection is True assert client.features.passphrase_protection is True
def test_send_multisig_1(client: Client): # input: 338e2d02e0eaf8848e38925904e51546cf22e58db5b1860c4a0e72b69c56afe5 nodes = [ btc.get_public_node( client, parse_path(f"m/49h/1h/{i}h"), coin_name="Testnet" ).node for i in range(1, 4) ] # address: 2MuqUo9axjz6FfHjSqNMu8kbF1tCjisMrbt multisig = messages.MultisigRedeemScriptType( nodes=nodes, address_n=[1, 0], signatures=[b"", b"", b""], m=2 ) inp1 = messages.TxInputType( address_n=parse_path("m/49h/1h/1h/1/0"), prev_hash=TXHASH_338e2d, prev_index=0, script_type=messages.InputScriptType.SPENDP2SHWITNESS, multisig=multisig, amount=100_000, ) out1 = messages.TxOutputType( address="mu85iAHLpF16VyijB2wn5fcZrjT2bvrhnL", amount=100_000 - 10_000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) expected_responses = [ request_input(0), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(TXHASH_338e2d), request_input(0, TXHASH_338e2d), request_output(0, TXHASH_338e2d), request_output(1, TXHASH_338e2d), request_input(0), request_output(0), request_input(0), request_finished(), ] with client: client.set_expected_responses(expected_responses) signatures, _ = btc.sign_tx( client, "Testnet", [inp1], [out1], prev_txes=TX_API_TESTNET ) # store signature inp1.multisig.signatures[0] = signatures[0] # sign with third key inp1.address_n[2] = H_(3) with client: client.set_expected_responses(expected_responses) _, serialized_tx = btc.sign_tx( client, "Testnet", [inp1], [out1], prev_txes=TX_API_TESTNET ) assert_tx_matches( serialized_tx, hash_link="https://tbtc1.trezor.io/api/tx/0d5d04bffd49287d122f509bebd196b1ecba7cbc5f945c28bf8a26dea66e65de", tx_hex="01000000000101e5af569cb6720e4a0c86b1b58de522cf4615e5045992388e84f8eae0022d8e330000000023220020cf28684ff8a6dda1a7a9704dde113ddfcf236558da5ce35ad3f8477474dbdaf7ffffffff01905f0100000000001976a914953e62552a88c235c0691ec74b362a6803a7d93e88ac040047304402203aba48b0a98194a505420633eeca5acd8244061899e0a414f1b0d2de1d721b0f022001b32486e7c443e25cdfdfb14dc183ba31f5329d0078a25f7eb74f7209f347bb014830450221009cbdf84db2585abddf79165340cc0b54037f13bbe5318ec3619d0de680ebbf5d02206a2ef69e154700202ac72330e936c073f8a86cec9443273f4d8739db1019d55a0169522103d54ab3c8b81cb7f8f8088df4c62c105e8acaa2fb53b180f6bc6f922faecf3fdc21036aa47994f3f18f0976d6073ca79997003c3fa29c4f93907998fefc1151b4529b2102a092580f2828272517c402da9461425c5032860ab40180e041fbbb88ea2a520453ae00000000", )
def test_ping(self, client): with client: client.set_expected_responses([proto.ButtonRequest(), proto.Success()]) client.ping("msg", True)
def test_get_entropy(self): with self.client: self.setup_mnemonic_pin_passphrase() self.client.set_expected_responses( [proto.ButtonRequest(), proto.Entropy()]) self.client.get_entropy(10)
def test_reset_device(self, client): mnemonic = None strength = 128 def input_flow(): nonlocal mnemonic # 1. Confirm Reset # 2. Backup your seed # 3. Confirm warning yield from click_through(client.debug, screens=3, code=B.ResetDevice) # mnemonic phrases btn_code = yield assert btn_code == B.ResetDevice mnemonic = read_and_confirm_mnemonic(client.debug, words=12) # confirm recovery seed check btn_code = yield assert btn_code == B.Success client.debug.press_yes() # confirm success btn_code = yield assert btn_code == B.Success client.debug.press_yes() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), client: client.set_expected_responses( [ proto.ButtonRequest(code=B.ResetDevice), proto.EntropyRequest(), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.Success), proto.Success(), proto.Features(), ] ) client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="english", ) # generate mnemonic locally internal_entropy = client.debug.state().reset_entropy entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) # Compare that device generated proper mnemonic for given entropies assert mnemonic == expected_mnemonic # Check if device is properly initialized resp = client.call_raw(proto.Initialize()) assert resp.initialized is True assert resp.needs_backup is False assert resp.pin_protection is False assert resp.passphrase_protection is False assert resp.backup_type is proto.BackupType.Bip39 # backup attempt fails because backup was done in reset with pytest.raises(TrezorFailure, match="ProcessError: Seed already backed up"): device.backup(client)
def btn(code): return proto.ButtonRequest(code=code)
def test_opreturn(self): self.setup_mnemonic_nopin_nopassphrase() # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 # input 0: 0.0039 BTC inp1 = proto.TxInputType( address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=390000, prev_hash=TXHASH_d5f65e, prev_index=0, ) out1 = proto.TxOutputType( address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", amount=390000 - 10000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( op_return_data=b"test of the op_return data", amount=0, script_type=proto.OutputScriptType.PAYTOOPRETURN, ) with self.client: self.client.set_expected_responses([ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_d5f65e), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_d5f65e), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=TXHASH_d5f65e), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_d5f65e), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest( code=proto.ButtonRequestType.ConfirmOutput), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.ButtonRequest( code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) (signatures, serialized_tx) = btc.sign_tx(self.client, "Bitcoin", [inp1], [out1, out2]) assert ( serialized_tx.hex() == "010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006a4730440220187b7b9c340a32fc8445418ad11fb3827d2e8bac7d730e1c9ad800353e7ba62f02206c0c5820ba8882c82923a39aee8d36d6d32e13daed73f7a3d6199de5f8e7ddfd0121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff0260cc0500000000001976a914de9b2a8da088824e8fe51debea566617d851537888ac00000000000000001c6a1a74657374206f6620746865206f705f72657475726e206461746100000000" )
def test_send_both(self, client): inp1 = proto.TxInputType( address_n=parse_path("49'/1'/0'/1/0"), # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX amount=111145789, prev_hash=TXHASH_091446, prev_index=1, script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) inp2 = proto.TxInputType( address_n=parse_path("84'/1'/0'/1/0"), amount=7289000, prev_hash=TXHASH_65b811, prev_index=1, script_type=proto.InputScriptType.SPENDWITNESS, ) out1 = proto.TxOutputType( address="tb1q54un3q39sf7e7tlfq99d6ezys7qgc62a6rxllc", amount=12300000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( # address_n=parse_path("44'/1'/0'/0/0"), # script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, address="2N6UeBoqYEEnybg4cReFYDammpsyDw8R2Mc", script_type=proto.OutputScriptType.PAYTOADDRESS, amount=45600000, ) out3 = proto.TxOutputType( address="mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q", amount=111145789 + 7289000 - 11000 - 12300000 - 45600000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses( [ request_input(0), request_input(1), request_output(0), proto.ButtonRequest(code=B.ConfirmOutput), request_output(1), proto.ButtonRequest(code=B.ConfirmOutput), request_output(2), proto.ButtonRequest(code=B.ConfirmOutput), proto.ButtonRequest(code=B.SignTx), request_input(0), request_input(1), request_output(0), request_output(1), request_output(2), request_input(0), request_input(1), request_finished(), ] ) _, serialized_tx = btc.sign_tx( client, "Testnet", [inp1, inp2], [out1, out2, out3], prev_txes=TX_API ) assert ( serialized_tx.hex() == "010000000001028a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090100000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff7b010c5faeb41cc5c253121b6bf69bf1a7c5867cd7f2d91569fea0ecd311b8650100000000ffffffff03e0aebb0000000000160014a579388225827d9f2fe9014add644487808c695d00cdb7020000000017a91491233e24a9bf8dbb19c1187ad876a9380c12e787870d859b03000000001976a914a579388225827d9f2fe9014add644487808c695d88ac02483045022100ead79ee134f25bb585b48aee6284a4bb14e07f03cc130253e83450d095515e5202201e161e9402c8b26b666f2b67e5b668a404ef7e57858ae9a6a68c3837e65fdc69012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7902463043021f585c54a84dc7326fa60e22729accd41153c7dd4725bd4c8f751aa3a8cd8d6a0220631bfd83fc312cc6d5d129572a25178696d81eaf50c8c3f16c6121be4f4c029d012103505647c017ff2156eb6da20fae72173d3b681a1d0a629f95f49e884db300689f00000000" )
def test_attack_change_input_address(self, client): inp1 = messages.TxInputType( address_n=parse_path("44'/1'/4'/0/0"), # moUJnmge8SRXuediK7bW6t4YfrPqbE6hD7 prev_hash=TXHASH_d2dcda, amount=123400000, prev_index=1, script_type=messages.InputScriptType.SPENDADDRESS, ) out1 = messages.TxOutputType( address="mwue7mokpBRAsJtHqEMcRPanYBmsSmYKvY", amount=100000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out2 = messages.TxOutputType( address_n=parse_path("44'/1'/4'/1/0"), amount=123400000 - 5000 - 100000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) # Test if the transaction can be signed normally _, serialized_tx = btc.sign_tx( client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET ) assert ( serialized_tx.hex() == "0100000001243e15b53cc553d93ec4e27e16984adc3d885ef107c613a7577fea47f5dadcd2010000006b483045022100eedaadde3a771967beee39f1daa9e9450f72fccdec63488a96d71eeae4224b4002203a22be3c1677d3451c93a49550b69e8f8fc06328823c7e0f633dde13d67ef96b01210364430c9122948e525e2f1c6d88f00f47679274f0810fd8c63754954f310995c1ffffffff02a0860100000000001976a914b3cc67f3349974d0f1b50e9bb5dfdf226f888fa088ac18555907000000001976a914f80fb232a1e54b1fa732bc120cae72eabd7fcf6888ac00000000" ) attack_count = 2 def attack_processor(msg): nonlocal attack_count if msg.tx.inputs and msg.tx.inputs[0] == inp1: if attack_count > 0: attack_count -= 1 else: msg.tx.inputs[0].address_n[2] = H_(12) return msg client.set_filter(messages.TxAck, attack_processor) # Now run the attack, must trigger the exception with client: client.set_expected_responses( [ request_input(0), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), request_output(1), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(TXHASH_d2dcda), request_input(0, TXHASH_d2dcda), request_output(0, TXHASH_d2dcda), request_output(1, TXHASH_d2dcda), request_input(0), messages.Failure(code=messages.FailureType.ProcessError), ] ) # Now run the attack, must trigger the exception with pytest.raises(TrezorFailure) as exc: btc.sign_tx( client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET, ) assert exc.value.code == messages.FailureType.ProcessError if client.features.model == "1": assert exc.value.message.endswith("Failed to compile input") else: assert exc.value.message.endswith( "Transaction has changed during signing" )
def pin_request(client): return (messages.PinMatrixRequest() if client.features.model == "1" else messages.ButtonRequest())
def test_lots_of_change(self, client): # Tests if device implements prompting for multiple change addresses correctly # tx: c63e24ed820c5851b60c54613fbc4bcb37df6cd49b4c96143e99580a472f79fb # index 1: 0.0010 BTC # tx: 39a29e954977662ab3879c66fb251ef753e0912223a83d1dcb009111d28265e5 # index 1: 0.0254 BTC inp1 = messages.TxInputType( address_n=parse_path("44h/0h/1h/0/0"), amount=100000, prev_hash=TXHASH_c63e24, prev_index=1, ) inp2 = messages.TxInputType( address_n=parse_path("44h/0h/1h/0/1"), amount=2540000, prev_hash=TXHASH_39a29e, prev_index=1, ) outputs = [ messages.TxOutputType( address="1NwN6UduuVkJi6sw3gSiKZaCY5rHgVXC2h", amount=500000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) ] cnt = 20 for i in range(cnt): out = messages.TxOutputType( address_n=parse_path(f"44h/0h/1h/1/{i}"), amount=(100000 + 2540000 - 500000 - 39000) // cnt, script_type=messages.OutputScriptType.PAYTOADDRESS, ) outputs.append(out) request_change_outputs = [request_output(i + 1) for i in range(cnt)] with client: client.set_expected_responses( [ request_input(0), request_input(1), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), ] + request_change_outputs + [ messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(TXHASH_c63e24), request_input(0, TXHASH_c63e24), request_input(1, TXHASH_c63e24), request_output(0, TXHASH_c63e24), request_output(1, TXHASH_c63e24), request_input(1), request_meta(TXHASH_39a29e), request_input(0, TXHASH_39a29e), request_output(0, TXHASH_39a29e), request_output(1, TXHASH_39a29e), request_input(0), request_input(1), request_output(0), ] + request_change_outputs + [request_input(0), request_input(1), request_output(0)] + request_change_outputs + [request_output(0)] + request_change_outputs + [request_finished()] ) _, serialized_tx = btc.sign_tx( client, "Bitcoin", [inp1, inp2], outputs, prev_txes=TX_CACHE_MAINNET ) assert ( tx_hash(serialized_tx).hex() == "fae68e4a3a4b0540eb200e2218a6d8465eac469788ccb236e0d5822d105ddde9" )
def test_two_two(self, client): # tx: c6be22d34946593bcad1d2b013e12f74159e69574ffea21581dad115572e031c # input 1: 0.0010 BTC # tx: 58497a7757224d1ff1941488d23087071103e5bf855f4c1c44e5c8d9d82ca46e # input 1: 0.0011 BTC inp1 = messages.TxInputType( address_n=parse_path("44h/0h/0h/0/0"), amount=100000, prev_hash=TXHASH_c6be22, prev_index=1, ) inp2 = messages.TxInputType( address_n=parse_path("44h/0h/0h/0/1"), amount=110000, prev_hash=TXHASH_58497a, prev_index=1, ) out1 = messages.TxOutputType( address="15Jvu3nZNP7u2ipw2533Q9VVgEu2Lu9F2B", amount=210000 - 100000 - 10000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out2 = messages.TxOutputType( address_n=parse_path("44h/0h/0h/1/0"), amount=100000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses( [ request_input(0), request_input(1), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), request_output(1), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(TXHASH_c6be22), request_input(0, TXHASH_c6be22), request_output(0, TXHASH_c6be22), request_output(1, TXHASH_c6be22), request_input(1), request_meta(TXHASH_58497a), request_input(0, TXHASH_58497a), request_output(0, TXHASH_58497a), request_output(1, TXHASH_58497a), request_input(0), request_input(1), request_output(0), request_output(1), request_input(0), request_input(1), request_output(0), request_output(1), request_output(0), request_output(1), request_finished(), ] ) _, serialized_tx = btc.sign_tx( client, "Bitcoin", [inp1, inp2], [out1, out2], prev_txes=TX_CACHE_MAINNET, ) # Accepted by network: tx c63e24ed820c5851b60c54613fbc4bcb37df6cd49b4c96143e99580a472f79fb # The transaction was produced before Trezor implemented BIP-66, so the signature # is now different and txhash doesn't match what is on the blockchain. assert ( tx_hash(serialized_tx).hex() == "6f9775545830731a316a4c2a39515b1890e9c8ab0f9e21e7c6a6ca2c1499116d" )
def test_one_three_fee(self, client): # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 # input 0: 0.0039 BTC inp1 = messages.TxInputType( address_n=parse_path("44'/0'/0'/0/0"), amount=390000, prev_hash=TXHASH_d5f65e, prev_index=0, ) out1 = messages.TxOutputType( address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", amount=390000 - 80000 - 12000 - 10000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out2 = messages.TxOutputType( address="13uaUYn6XAooo88QvAqAVsiVvr2mAXutqP", amount=12000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out3 = messages.TxOutputType( address_n=parse_path("44'/0'/0'/1/0"), amount=80000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses( [ request_input(0), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), request_output(1), messages.ButtonRequest(code=B.ConfirmOutput), request_output(2), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(TXHASH_d5f65e), request_input(0, TXHASH_d5f65e), request_input(1, TXHASH_d5f65e), request_output(0, TXHASH_d5f65e), request_input(0), request_output(0), request_output(1), request_output(2), request_output(0), request_output(1), request_output(2), request_finished(), ] ) _, serialized_tx = btc.sign_tx( client, "Bitcoin", [inp1], [out1, out2, out3], prev_txes=TX_CACHE_MAINNET, ) assert ( tx_hash(serialized_tx).hex() == "fedbba83b115725a713c2b1a13db09fd33de582132d520a3f6ff72503ca5da61" )
def test_send_decred_change(self, client): inp1 = proto.TxInputType( # TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz address_n=parse_path("m/44'/1'/0'/0/0"), prev_hash=TXHASH_5e6e35, prev_index=0, script_type=proto.InputScriptType.SPENDADDRESS, decred_tree=0, ) inp2 = proto.TxInputType( # TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz address_n=parse_path("m/44'/1'/0'/0/0"), prev_hash=TXHASH_ccf95b, prev_index=1, script_type=proto.InputScriptType.SPENDADDRESS, decred_tree=0, ) inp3 = proto.TxInputType( # Tskt39YEvzoJ5KBDH4f1auNzG3jViVjZ2RV address_n=parse_path("m/44'/1'/0'/0/1"), prev_hash=TXHASH_f395ef, prev_index=0, script_type=proto.InputScriptType.SPENDADDRESS, decred_tree=0, ) out1 = proto.TxOutputType( address="TsWjioPrP8E1TuTMmTrVMM2BA4iPrjQXBpR", amount=489975000, script_type=proto.OutputScriptType.PAYTOADDRESS, decred_script_version=0, ) out2 = proto.TxOutputType( # TsaSFRwfN9muW5F6ZX36iSksc9hruiC5F97 address_n=parse_path("m/44'/1'/0'/1/0"), amount=100000000, script_type=proto.OutputScriptType.PAYTOADDRESS, decred_script_version=0, ) with client: client.set_expected_responses( [ request_input(0), request_meta(TXHASH_5e6e35), request_input(0, TXHASH_5e6e35), request_output(0, TXHASH_5e6e35), request_input(1), request_meta(TXHASH_ccf95b), request_input(0, TXHASH_ccf95b), request_output(0, TXHASH_ccf95b), request_output(1, TXHASH_ccf95b), request_input(2), request_meta(TXHASH_f395ef), request_input(0, TXHASH_f395ef), request_output(0, TXHASH_f395ef), request_output(1, TXHASH_f395ef), request_output(0), proto.ButtonRequest(code=B.ConfirmOutput), request_output(1), proto.ButtonRequest(code=B.SignTx), request_input(0), request_input(1), request_input(2), request_finished(), ] ) _, serialized_tx = btc.sign_tx( client, "Decred Testnet", [inp1, inp2, inp3], [out1, out2], prev_txes=TX_API, ) assert ( serialized_tx.hex() == "010000000370b95980a47b9bcb4ec2c2b450888a53179b1a5fdb23f5023cc533a300356e5e0000000000ffffffff74bc93bcfce18aff2e522d6822817522e2815a00175b2eae59ef20d20f5bf9cc0100000000ffffffff13317ab453832deabd684d2302eed42580c28ba3e715db66a731a8723eef95f30000000000ffffffff02d86c341d0000000000001976a9143eb656115197956125365348c542e37b6d3d259988ac00e1f5050000000000001976a9143ee6f9d662e7be18373d80e5eb44627014c2bf6688ac000000000000000003000000000000000000000000ffffffff6a47304402200e50a6d43c462045917792e7d03b4354900c3baccb7abef66f556a32b12f2ca6022031ae94fdf2a41dd6ed2e081faf0f8f1c64411a1b46eb26f7f35d94402b2bde110121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0000000000000000000000000ffffffff6a47304402204894c2f8e76c4645d2df600cdd01443aeb48807b72150c4bc10eebd126529532022054cd37462a3f0ddb85c75b4e874ab0c2aad7eebcff3e6c1ac20e1c16babe36720121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0000000000000000000000000ffffffff6b4830450221009f1ba584023da8aafd57374e83be68f1a097b906967ec9e50736f31bfc7989f102204a190fc2885e394572b5c2ced046657b1dd07abdb19144e21e78987968c7f17601210294e3e5e77e22eea0e4c0d30d89beb4db7f69b4bf1ae709e411d6a06618b8f852" )
def test_send_multisig_1(self, client): nodes = [ btc.get_public_node(client, parse_path("49'/1'/%d'" % index)) for index in range(1, 4) ] multisig = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[0, 0], signatures=[b"", b"", b""], m=2, ) inp1 = proto.TxInputType( address_n=parse_path("49'/1'/1'/0/0"), prev_hash=TXHASH_9c3192, prev_index=1, script_type=proto.InputScriptType.SPENDP2SHWITNESS, multisig=multisig, amount=1610436, ) out1 = proto.TxOutputType( address="tb1qch62pf820spe9mlq49ns5uexfnl6jzcezp7d328fw58lj0rhlhasge9hzy", amount=1605000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses( [ request_input(0), request_output(0), proto.ButtonRequest(code=B.ConfirmOutput), proto.ButtonRequest(code=B.SignTx), request_input(0), request_output(0), request_input(0), request_finished(), ] ) signatures, _ = btc.sign_tx( client, "Testnet", [inp1], [out1], prev_txes=TX_API ) # store signature inp1.multisig.signatures[0] = signatures[0] # sign with third key inp1.address_n[2] = H_(3) client.set_expected_responses( [ request_input(0), request_output(0), proto.ButtonRequest(code=B.ConfirmOutput), proto.ButtonRequest(code=B.SignTx), request_input(0), request_output(0), request_input(0), request_finished(), ] ) _, serialized_tx = btc.sign_tx( client, "Testnet", [inp1], [out1], prev_txes=TX_API ) assert ( serialized_tx.hex() == "01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c01000000232200208d398cfb58a1d9cdb59ccbce81559c095e8c6f4a3e64966ca385078d9879f95effffffff01887d180000000000220020c5f4a0a4ea7c0392efe0a9670a73264cffa90b19107cd8a8e9750ff93c77fdfb0400483045022100dd6342c65197af27d7894d8b8b88b16b568ee3b5ebfdc55fdfb7caa9650e3b4c02200c7074a5bcb0068f63d9014c7cd2b0490aba75822d315d41aad444e9b86adf5201483045022100e7e6c2d21109512ba0609e93903e84bfb7731ac3962ee2c1cad54a7a30ff99a20220421497930226c39fc3834e8d6da3fc876516239518b0e82e2dc1e3c46271a17c01695221021630971f20fa349ba940a6ba3706884c41579cd760c89901374358db5dd545b92102f2ff4b353702d2bb03d4c494be19d77d0ab53d16161b53fbcaf1afeef4ad0cb52103e9b6b1c691a12ce448f1aedbbd588e064869c79fbd760eae3b8cd8a5f1a224db53ae00000000" )
def test_reset_device_pin(self, client): mnemonic = None strength = 128 def input_flow(): nonlocal mnemonic # Confirm Reset btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # Enter new PIN yield client.debug.input("654") # Confirm PIN yield client.debug.input("654") # Confirm entropy btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # Backup your seed btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # Confirm warning btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # mnemonic phrases btn_code = yield assert btn_code == B.ResetDevice mnemonic = read_and_confirm_mnemonic(client.debug, words=12) # confirm recovery seed check btn_code = yield assert btn_code == B.Success client.debug.press_yes() # confirm success btn_code = yield assert btn_code == B.Success client.debug.press_yes() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), client: client.set_expected_responses( [ proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Other), proto.ButtonRequest(code=B.Other), proto.ButtonRequest(code=B.ResetDevice), proto.EntropyRequest(), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.Success), proto.Success(), proto.Features(), ] ) client.set_input_flow(input_flow) # PIN, passphrase, display random device.reset( client, display_random=True, strength=strength, passphrase_protection=True, pin_protection=True, label="test", language="english", ) # generate mnemonic locally internal_entropy = client.debug.state().reset_entropy entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) # Compare that device generated proper mnemonic for given entropies assert mnemonic == expected_mnemonic # Check if device is properly initialized resp = client.call_raw(proto.Initialize()) assert resp.initialized is True assert resp.needs_backup is False assert resp.pin_protection is True assert resp.passphrase_protection is True
def test_send_multisig_2(self, client): nodes = [ btc.get_public_node(client, parse_path("84'/1'/%d'" % index)) for index in range(1, 4) ] multisig = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[0, 1], signatures=[b"", b"", b""], m=2, ) inp1 = proto.TxInputType( address_n=parse_path("84'/1'/2'/0/1"), prev_hash=TXHASH_f41cbe, prev_index=0, script_type=proto.InputScriptType.SPENDWITNESS, multisig=multisig, amount=1605000, ) out1 = proto.TxOutputType( address="tb1qr6xa5v60zyt3ry9nmfew2fk5g9y3gerkjeu6xxdz7qga5kknz2ssld9z2z", amount=1604000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses( [ request_input(0), request_output(0), proto.ButtonRequest(code=B.ConfirmOutput), proto.ButtonRequest(code=B.SignTx), request_input(0), request_output(0), request_input(0), request_finished(), ] ) signatures, _ = btc.sign_tx( client, "Testnet", [inp1], [out1], prev_txes=TX_API ) # store signature inp1.multisig.signatures[1] = signatures[0] # sign with first key inp1.address_n[2] = H_(1) client.set_expected_responses( [ request_input(0), request_output(0), proto.ButtonRequest(code=B.ConfirmOutput), proto.ButtonRequest(code=B.SignTx), request_input(0), request_output(0), request_input(0), request_finished(), ] ) _, serialized_tx = btc.sign_tx( client, "Testnet", [inp1], [out1], prev_txes=TX_API ) assert ( serialized_tx.hex() == "010000000001012812fe3916f228cda6c7b57d5464541265a63ad118f430a805eeec8bddbe1cf40000000000ffffffff01a0791800000000002200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a10400473044022001b7f4f21a8ddcd5e0faaaee3b95515bf8b84f2a7cbfdf66996c64123617a5cf02202fc6a776a7225420dbca759ad4ac83a61d15bf8d2883b6bf1aa31de7437f9b6e0147304402206c4125c1189a3b3e93a77cdf54c60c0538b80e5a03ec74e6ac776dfa77706ee4022035be14de76259b9d8a24863131a06a65b95df02f7d3ace90d52b37e8d94b167f0169522103bab8ecdd9ae2c51a0dc858f4c751b27533143bf6013ba1725ba8a4ecebe7de8c21027d5e55696c875308b03f2ca3d8637f51d3e35da9456a5187aa14b3de8a89534f2103b78eabaea8b3a4868be4f4bb96d6f66973f7081faa7f1cafba321444611c241e53ae00000000" )
def test_attack_change_input_address(self): # This unit test attempts to modify input address after the Trezor checked # that it matches the change output self.setup_mnemonic_allallall() self.client.set_tx_api(tx_api["Testnet"]) inp1 = proto.TxInputType( address_n=parse_path("44'/1'/4'/0/0"), # moUJnmge8SRXuediK7bW6t4YfrPqbE6hD7 prev_hash=TXHASH_d2dcda, prev_index=1, script_type=proto.InputScriptType.SPENDADDRESS, ) out1 = proto.TxOutputType( address="mwue7mokpBRAsJtHqEMcRPanYBmsSmYKvY", amount=100000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address_n=parse_path("44'/1'/12345'/1/0"), amount=123400000 - 5000 - 100000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) global run_attack run_attack = True def attack_processor(req, msg): global run_attack if req.details.tx_hash is not None: return msg if req.request_type != proto.RequestType.TXINPUT: return msg if req.details.request_index != 0: return msg if not run_attack: return msg msg.inputs[0].address_n[2] = H_(12345) run_attack = False return msg # Test if the transaction can be signed normally (_, serialized_tx) = btc.sign_tx(self.client, "Testnet", [inp1], [out1, out2]) assert ( serialized_tx.hex() == "0100000001243e15b53cc553d93ec4e27e16984adc3d885ef107c613a7577fea47f5dadcd2010000006a47304402207d517dcb6b823bba4d252da096795a7f914d0c477aee26e554ba61653c45608a02202cba1e805c586c830472f399510be5d42c2fcfd67b8a6b0690cbe8a3e6e475e801210364430c9122948e525e2f1c6d88f00f47679274f0810fd8c63754954f310995c1ffffffff02a0860100000000001976a914b3cc67f3349974d0f1b50e9bb5dfdf226f888fa088ac18555907000000001976a91485a3f5b0d23cdd61f5f8e1eb8c9ca0890dd15a9788ac00000000" ) # Now run the attack, must trigger the exception with self.client: self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_d2dcda), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=TXHASH_d2dcda ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=TXHASH_d2dcda ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=1, tx_hash=TXHASH_d2dcda ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.Failure(code=proto.FailureType.ProcessError), ] ) # Now run the attack, must trigger the exception with pytest.raises(CallException) as exc: btc.sign_tx( self.client, "Testnet", [inp1], [out1, out2], debug_processor=attack_processor, ) assert exc.value.args[0] == proto.FailureType.ProcessError if TREZOR_VERSION == 1: assert exc.value.args[1].endswith("Failed to compile input") else: assert exc.value.args[1].endswith( "Transaction has changed during signing" )
def test_send_multisig_3_change(self, client): nodes = [ btc.get_public_node(client, parse_path("84'/1'/%d'" % index)) for index in range(1, 4) ] multisig = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[1, 0], signatures=[b"", b"", b""], m=2, ) multisig2 = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[1, 1], signatures=[b"", b"", b""], m=2, ) inp1 = proto.TxInputType( address_n=parse_path("84'/1'/1'/1/0"), prev_hash=TXHASH_c93480, prev_index=0, script_type=proto.InputScriptType.SPENDWITNESS, multisig=multisig, amount=1604000, ) out1 = proto.TxOutputType( address_n=parse_path("84'/1'/1'/1/1"), amount=1603000, multisig=multisig2, script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, ) with client: client.set_expected_responses( [ request_input(0), request_output(0), proto.ButtonRequest(code=B.SignTx), request_input(0), request_output(0), request_input(0), request_finished(), ] ) signatures, _ = btc.sign_tx( client, "Testnet", [inp1], [out1], prev_txes=TX_API ) # store signature inp1.multisig.signatures[0] = signatures[0] # sign with third key inp1.address_n[2] = H_(3) out1.address_n[2] = H_(3) client.set_expected_responses( [ request_input(0), request_output(0), proto.ButtonRequest(code=B.SignTx), request_input(0), request_output(0), request_input(0), request_finished(), ] ) _, serialized_tx = btc.sign_tx( client, "Testnet", [inp1], [out1], prev_txes=TX_API ) assert ( serialized_tx.hex() == "01000000000101fc7901dd033f8c02da14f3ac916b6498036b80b4a0b4dc124e02c2bb408034c90000000000ffffffff01b87518000000000017a914536250d41937e5b641082447580ff6a8e46c122a870400473044022003c26107a5a47f1f900ef8aa758977530cd13ea37a33971abae8d75cac2f9f34022039e2b8c2c1d0c24ff4fc026652e1f27ad8e3ed6c9bf485f61d9aa691cb57830801483045022100963b0dc0ab46e963a66ab6e69e5e41bac6c4fedc127cac12c560b029d54fe87402205b3bcdcf313dccd78e5dce0540e7d3c8cc1bf83f13c1f9f01811eb791fd35c8101695221039dba3a72f5dc3cad17aa924b5a03c34561465f997d0cb15993f2ca2c0be771c42103cd39f3f08bbd508dce4d307d57d0c70c258c285878bfda579fa260acc738c25d2102cd631ba95beca1d64766f5540885092d0bb384a3c13b6c3a5334d0ebacf51b9553ae00000000" )
def test_wipe_device(self, client): with client: client.set_expected_responses( [proto.ButtonRequest(), proto.Success(), proto.Features()] ) device.wipe(client)
def test_send_multisig_4_change(self, client): nodes = [ btc.get_public_node(client, parse_path("49'/1'/%d'" % index)) for index in range(1, 4) ] multisig = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[1, 1], signatures=[b"", b"", b""], m=2, ) multisig2 = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[1, 2], signatures=[b"", b"", b""], m=2, ) inp1 = proto.TxInputType( address_n=parse_path("49'/1'/1'/1/1"), prev_hash=TXHASH_31bc1c, prev_index=0, script_type=proto.InputScriptType.SPENDP2SHWITNESS, multisig=multisig, amount=1603000, ) out1 = proto.TxOutputType( address_n=parse_path("49'/1'/1'/1/2"), amount=1602000, multisig=multisig2, script_type=proto.OutputScriptType.PAYTOWITNESS, ) with client: client.set_expected_responses( [ request_input(0), request_output(0), proto.ButtonRequest(code=B.SignTx), request_input(0), request_output(0), request_input(0), request_finished(), ] ) signatures, _ = btc.sign_tx( client, "Testnet", [inp1], [out1], prev_txes=TX_API ) # store signature inp1.multisig.signatures[0] = signatures[0] # sign with third key inp1.address_n[2] = H_(3) out1.address_n[2] = H_(3) client.set_expected_responses( [ request_input(0), request_output(0), proto.ButtonRequest(code=B.SignTx), request_input(0), request_output(0), request_input(0), request_finished(), ] ) _, serialized_tx = btc.sign_tx( client, "Testnet", [inp1], [out1], prev_txes=TX_API ) assert ( serialized_tx.hex() == "01000000000101e5918f661488bb7f0a7d04fc1dad61b5d0bad5167a05b3a637e36ace881cbc310000000023220020fa6c73de618ec134eeec0c16f6dd04d46d4347e9a4fd0a95fd7938403a4949f9ffffffff01d071180000000000220020bcea2324dacbcde5a9db90cc26b8df9cbc72010e05cb68cf034df6f0e05239a2040047304402206bbddb45f12e31e77610fd85b50a83bad4426433b1c4860b1c5ddc0a69f803720220087b0607daab14830f4b4941f16b953b38e606ad70029bac24af7267f93c4242014730440220551a0cb6b0d5b3fa0cfd0b07bb5d751494b827b1c6a08702186696cfbc18278302204f37c382876c4117cca656654599b508f2d55fc3b083dc938e3cd8491b29719601695221036a5ec3abd10501409092246fe59c6d7a15fff1a933479483c3ba98b866c5b9742103559be875179d44e438db2c74de26e0bc9842cbdefd16018eae8a2ed989e474722103067b56aad037cd8b5f569b21f9025b76470a72dc69457813d2b76e98dc0cd01a53ae00000000" )
def test_get_entropy(self, client): with client: client.set_expected_responses([proto.ButtonRequest(), proto.Entropy()]) misc.get_entropy(client, 10)
def test_multisig_mismatch_inputs_single(self, client): # m/84'/1'/0' for "alcohol woman abuse ..." seed. node_int = deserialize( "Vpub5kFDCYhiYuAzjk7TBQPNFffbexHF7iAd8AVVgHQKUany7e6NQvthgk86d7DfH57DY2dwBK4PyVTDDaS1r2gjkdyJyUYGoV9qNujGSrW9Dpe" ) # m/84'/1'/0' for "all all ... all" seed. node_ext = deserialize( "Vpub5jR76XyyhBaQXPSRf3PBeY3gF914d9sf7DWFVhMESEQMCdNv35XiVvp8gZsFXAv222VPHLNnAEXxMPG8DPiSuhAXfEydBf55LTLBGHCDzH2" ) # tb1qpzmgzpcumztvmpu3q27wwdggqav26j9dgks92pvnne2lz9ferxgssmhzlq multisig_in = proto.MultisigRedeemScriptType( nodes=[node_int, node_ext], address_n=[0, 0], signatures=[b"", b""], m=1 ) multisig_out = proto.MultisigRedeemScriptType( nodes=[node_int, node_ext], address_n=[1, 0], signatures=[b"", b""], m=1 ) inp1 = proto.TxInputType( address_n=parse_path("84'/1'/0'/0/0"), amount=12300000, prev_hash=TXHASH_091446, prev_index=0, script_type=proto.InputScriptType.SPENDWITNESS, ) inp2 = proto.TxInputType( address_n=parse_path("84'/1'/0'/0/0"), prev_hash=TXHASH_a345b8, prev_index=0, script_type=proto.InputScriptType.SPENDWITNESS, multisig=multisig_in, amount=100, ) out1 = proto.TxOutputType( address="2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp", amount=5000000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address_n=parse_path("84'/1'/0'/1/0"), script_type=proto.OutputScriptType.PAYTOWITNESS, multisig=multisig_out, amount=12300000 + 100 - 5000000 - 10000, ) with client: client.set_expected_responses( [ request_input(0), request_input(1), request_output(0), proto.ButtonRequest(code=B.ConfirmOutput), request_output(1), # Ensure that the multisig output is not identified as a change output. proto.ButtonRequest(code=B.ConfirmOutput), proto.ButtonRequest(code=B.SignTx), request_input(0), request_input(1), request_output(0), request_output(1), request_input(0), request_input(1), request_finished(), ] ) _, serialized_tx = btc.sign_tx( client, "Testnet", [inp1, inp2], [out1, out2], prev_txes=TX_API ) assert ( serialized_tx.hex() == "010000000001028a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090000000000ffffffff48e37c58a68ab4899400dc0950a661817ea7bac3e4556044c685b35957b845a30000000000ffffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987f43c6f0000000000220020733ecfbbe7e47a74dde6c7645b60cdf627e90a585cde7733bc7fdaf9fe30b37402473044022037dc98b16be542a6e3e1ab32007a74192c43f2498170cc5e1dffb6847e3663e402206715102d0eb59e6461a97c78eb40a8679a04a8921fdafef25f0d3d16cc65de39012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f8620300473044022070a24bcb00041cbed465f1f546bc59e1e353a6e182393932d5ba96e20bc32ef702202ddc76a97c01465692d5b0a0a61d653f64b9ea833af1810022110fd4d505ff950147512103505f0d82bbdd251511591b34f36ad5eea37d3220c2b81a1189084431ddb3aa3d2103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f86252ae00000000" )
def test_reset_device(self, client): words = [] strength = 128 def input_flow(): # Confirm Reset btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # Backup your seed btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # Confirm warning btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # mnemonic phrases btn_code = yield assert btn_code == B.ResetDevice # 12 words, 3 pages for i in range(3): words.extend(client.debug.read_reset_word().split()) if i < 2: client.debug.swipe_down() else: # last page is confirmation client.debug.press_yes() # check backup words for _ in range(3): index = client.debug.read_reset_word_pos() client.debug.input(words[index]) # confirm recovery seed check btn_code = yield assert btn_code == B.Success client.debug.press_yes() # confirm success btn_code = yield assert btn_code == B.Success client.debug.press_yes() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), client: client.set_expected_responses( [ proto.ButtonRequest(code=B.ResetDevice), proto.EntropyRequest(), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.Success), proto.Success(), proto.Features(), ] ) client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="english", ) # generate mnemonic locally internal_entropy = client.debug.state().reset_entropy entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) # Compare that device generated proper mnemonic for given entropies assert " ".join(words) == expected_mnemonic # Check if device is properly initialized resp = client.call_raw(proto.Initialize()) assert resp.initialized is True assert resp.needs_backup is False assert resp.pin_protection is False assert resp.passphrase_protection is False
def test_2_of_3(self): self.setup_mnemonic_nopin_nopassphrase() # key1 = self.client.get_public_node([1]) # key2 = self.client.get_public_node([2]) # key3 = self.client.get_public_node([3]) # xpub: # print(bip32.serialize(self.client.get_public_node([]).node)) # xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy # pubkeys: # xpub/1: 0338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a6 # xpub/2: 038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e3 # xpub/3: 03477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a7902 # redeem script: # 52210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a621038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e32103477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a790253ae # multisig address: 3E7GDtuHqnqPmDgwH59pVC7AvySiSkbibz # tx: c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9cdefc4dba52 # input 1: 0.001 BTC node = bip32.deserialize( 'xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy' ) multisig = proto.MultisigRedeemScriptType( pubkeys=[ proto.HDNodePathType(node=node, address_n=[1]), proto.HDNodePathType(node=node, address_n=[2]), proto.HDNodePathType(node=node, address_n=[3]) ], signatures=[b'', b'', b''], m=2, ) # Let's go to sign with key 1 inp1 = proto.TxInputType( address_n=[1], prev_hash=TXHASH_c6091a, prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, multisig=multisig, ) out1 = proto.TxOutputType( address='12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss', amount=100000, script_type=proto.OutputScriptType.PAYTOADDRESS) with self.client: self.client.set_expected_responses([ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a)), proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=TXHASH_c6091a)), proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=TXHASH_c6091a)), proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=1, tx_hash=TXHASH_c6091a)), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.ButtonRequest( code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) # Now we have first signature (signatures1, _) = self.client.sign_tx('Bitcoin', [ inp1, ], [ out1, ]) assert hexlify( signatures1[0] ) == b'3045022100985cc1ba316d140eb4b2d4028d8cd1c451f87bff8ff679858732e516ad04cd3402207af6edda99972af0baa7702a3b7448517c8242e7bca669f6861771cdd16ee058' # --------------------------------------- # Let's do second signature using 3rd key multisig = proto.MultisigRedeemScriptType( pubkeys=[ proto.HDNodePathType(node=node, address_n=[1]), proto.HDNodePathType(node=node, address_n=[2]), proto.HDNodePathType(node=node, address_n=[3]) ], signatures=[signatures1[0], b'', b''], # Fill signature from previous signing process m=2, ) # Let's do a second signature with key 3 inp3 = proto.TxInputType( address_n=[3], prev_hash=TXHASH_c6091a, prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, multisig=multisig, ) with self.client: self.client.set_expected_responses([ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a)), proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=TXHASH_c6091a)), proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=TXHASH_c6091a)), proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=1, tx_hash=TXHASH_c6091a)), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.ButtonRequest( code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) (signatures2, serialized_tx) = self.client.sign_tx('Bitcoin', [ inp3, ], [ out1, ]) assert hexlify( signatures2[0] ) == b'3045022100f5428fe0531b3095675b40d87cab607ee036fac823b22e8dcec35b65aff6e52b022032129b4577ff923d321a1c70db5a6cec5bcc142cb2c51901af8b989cced23e0d' # Accepted by network: tx 8382a2b2e3ec8788800c1d46d285dfa9dd4051edddd75982fad166b9273e5ac6 assert hexlify( serialized_tx ) == b'010000000152ba4dfcde9c4bed88f55479cdea03e711ae586e9a89352a98230c4cdf1a09c601000000fdfe0000483045022100985cc1ba316d140eb4b2d4028d8cd1c451f87bff8ff679858732e516ad04cd3402207af6edda99972af0baa7702a3b7448517c8242e7bca669f6861771cdd16ee05801483045022100f5428fe0531b3095675b40d87cab607ee036fac823b22e8dcec35b65aff6e52b022032129b4577ff923d321a1c70db5a6cec5bcc142cb2c51901af8b989cced23e0d014c6952210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a621038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e32103477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a790253aeffffffff01a0860100000000001976a91412e8391ad256dcdc023365978418d658dfecba1c88ac00000000'
def test_2_of_3(self): self.setup_mnemonic_allallall() nodes = [ btc.get_public_node(self.client, parse_path("48'/0'/%d'" % index)).node for index in range(1, 4) ] multisig = proto.MultisigRedeemScriptType(nodes=nodes, address_n=[0, 0], signatures=[b"", b"", b""], m=2) # Let's go to sign with key 1 inp1 = proto.TxInputType( address_n=parse_path("48'/0'/1'/0/0"), prev_hash=TXHASH_c6091a, prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, multisig=multisig, ) out1 = proto.TxOutputType( address="12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss", amount=100000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses([ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest( code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) # Now we have first signature signatures1, _ = btc.sign_tx(self.client, "Bitcoin", [inp1], [out1], prev_txes=TX_API) assert ( signatures1[0].hex() == "3044022052f4a3dc5ca3e86ed66abb1e2b4d9b9ace7d96f5615944beea19e58280847c2902201bd3ff32a38366a4eed0373e27da26ebc0d2a4c2bbeffd83e8a60e313d95b9e3" ) # --------------------------------------- # Let's do second signature using 3rd key multisig = proto.MultisigRedeemScriptType( nodes=nodes, address_n=[0, 0], signatures=[ signatures1[0], b"", b"", ], # Fill signature from previous signing process m=2, ) # Let's do a second signature with key 3 inp3 = proto.TxInputType( address_n=parse_path("48'/0'/3'/0/0"), prev_hash=TXHASH_c6091a, prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, multisig=multisig, ) with self.client: self.client.set_expected_responses([ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest( code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) signatures2, serialized_tx = btc.sign_tx(self.client, "Bitcoin", [inp3], [out1], prev_txes=TX_API) assert ( signatures2[0].hex() == "304402203828fd48540811be6a1b12967e7012587c46e6f05c78d42471e7b25c06bc7afc0220749274bc1aa698335b00400c5ba946a70b6b46c711324fbc4989279737a57f49" ) assert ( serialized_tx.hex() == "010000000152ba4dfcde9c4bed88f55479cdea03e711ae586e9a89352a98230c4cdf1a09c601000000fc00473044022052f4a3dc5ca3e86ed66abb1e2b4d9b9ace7d96f5615944beea19e58280847c2902201bd3ff32a38366a4eed0373e27da26ebc0d2a4c2bbeffd83e8a60e313d95b9e30147304402203828fd48540811be6a1b12967e7012587c46e6f05c78d42471e7b25c06bc7afc0220749274bc1aa698335b00400c5ba946a70b6b46c711324fbc4989279737a57f49014c6952210203ed6187880ae932660086e55d4561a57952dd200aa3ed2aa66b73e5723a0ce7210360e7f32fd3c8dee27a166f6614c598929699ee66acdcbda5fb24571bf2ae1ca021037c4c7e5d3293ab0f97771dcfdf83caadab341f427f54713da8b2c590a834f03b53aeffffffff01a0860100000000001976a91412e8391ad256dcdc023365978418d658dfecba1c88ac00000000" )
def test_multisig(index): address_n, multisig = create_multisig(index, "m/0/0", signatures[0]) inp1 = proto.TxInputType( address_n=address_n, # TchpthUkRys1VQWgnQyLJNaA4MLBjVmRL2c multisig=multisig, prev_hash=TXHASH_3f7c39, prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, decred_tree=0, ) address_n, multisig = create_multisig(index, "m/0/1", signatures[1]) inp2 = proto.TxInputType( address_n=address_n, # TcnfDEfMhkM3oLWqiq9v9GmYgLK7qfjitKG multisig=multisig, prev_hash=TXHASH_16da18, prev_index=0, script_type=proto.InputScriptType.SPENDMULTISIG, decred_tree=0, ) address_n, multisig = create_multisig(index, "m/1/0") out1 = proto.TxOutputType( address_n=address_n, # TcrrURA3Bzj4isGU48PdSP9SDoU5oCpjEcb multisig=multisig, amount=99900000, script_type=proto.OutputScriptType.PAYTOMULTISIG, decred_script_version=0, ) out2 = proto.TxOutputType( address="TsWjioPrP8E1TuTMmTrVMM2BA4iPrjQXBpR", amount=300000000, script_type=proto.OutputScriptType.PAYTOADDRESS, decred_script_version=0, ) with client: client.set_expected_responses( [ request_input(0), request_meta(TXHASH_3f7c39), request_input(0, TXHASH_3f7c39), request_output(0, TXHASH_3f7c39), request_output(1, TXHASH_3f7c39), request_input(1), request_meta(TXHASH_16da18), request_input(0, TXHASH_16da18), request_output(0, TXHASH_16da18), request_output(1, TXHASH_16da18), request_output(0), request_output(1), proto.ButtonRequest(code=B.ConfirmOutput), proto.ButtonRequest(code=B.SignTx), request_input(0), request_input(1), request_finished(), ] ) signature, serialized_tx = btc.sign_tx( client, "Decred Testnet", [inp1, inp2], [out1, out2], prev_txes=TX_API, ) signatures[0][index] = signature[0] signatures[1][index] = signature[1] return serialized_tx
def test_attack_change_input_address(client: Client): # Simulates an attack where the user is coerced into unknowingly # transferring funds from one account to another one of their accounts, # potentially resulting in privacy issues. inp1 = messages.TxInputType( address_n=parse_path("m/49h/1h/0h/1/0"), # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX amount=123_456_789, prev_hash=TXHASH_20912f, prev_index=0, script_type=messages.InputScriptType.SPENDP2SHWITNESS, ) out1 = messages.TxOutputType( address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC", amount=12_300_000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out2 = messages.TxOutputType( address_n=parse_path("m/49h/1h/12h/1/0"), script_type=messages.OutputScriptType.PAYTOP2SHWITNESS, amount=123_456_789 - 11_000 - 12_300_000, ) # Test if the transaction can be signed normally. with client: client.set_expected_responses( [ request_input(0), request_output(0), # The user is required to confirm transfer to another account. messages.ButtonRequest(code=B.ConfirmOutput), request_output(1), messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(TXHASH_20912f), request_input(0, TXHASH_20912f), request_output(0, TXHASH_20912f), request_output(1, TXHASH_20912f), request_input(0), request_output(0), request_output(1), request_input(0), request_finished(), ] ) _, serialized_tx = btc.sign_tx( client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API_TESTNET ) # Transaction does not exist on the blockchain, not using assert_tx_matches() assert ( serialized_tx.hex() == "0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a9142f98413cb83ff8b3eaf1926192e68973cbd68a3a8702473044022013cbce7c575337ca05dbe03b5920a0805b510cd8dfd3180bd7c5d01cec6439cd0220050001be4bcefb585caf973caae0ffec682347f2127cc22f26efd93ee54fd852012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000" ) attack_count = 2 def attack_processor(msg): nonlocal attack_count if attack_count > 0 and msg.tx.inputs and msg.tx.inputs[0] == inp1: attack_count -= 1 msg.tx.inputs[0].address_n[2] = H_(12) return msg # Now run the attack, must trigger the exception with client: client.set_filter(messages.TxAck, attack_processor) with pytest.raises(TrezorFailure): btc.sign_tx( client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API_TESTNET )
def test_reset_device_shamir(self): strength = 128 # TODO: uncomment when python_shamir_mnemonic is uploaded to pypi # member_threshold = 2 def input_flow(): # Confirm Reset btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # Backup your seed btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # Confirm warning btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # shares info btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # Set & Confirm number of shares btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # threshold info btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # Set & confirm threshold value btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # Confirm show seeds btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # show & confirm shares all_mnemonics = [] for h in range(5): words = [] btn_code = yield assert btn_code == B.Other # mnemonic phrases # 20 word over 6 pages for strength 128, 33 words over 9 pages for strength 256 for i in range(6): time.sleep(1) words.extend(self.client.debug.state().reset_word.split()) if i < 5: self.client.debug.swipe_down() else: # last page is confirmation self.client.debug.press_yes() # check share for _ in range(3): time.sleep(1) index = self.client.debug.state().reset_word_pos self.client.debug.input(words[index]) all_mnemonics.extend([" ".join(words)]) # Confirm continue to next share btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # generate secret locally # internal_entropy = self.client.debug.state().reset_entropy # secret = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) # validate that all combinations will result in the correct master secret # validate_mnemonics(all_mnemonics, member_threshold, secret) # safety warning btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), self.client: self.client.set_expected_responses([ proto.ButtonRequest(code=B.ResetDevice), proto.EntropyRequest(), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Other), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Other), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Other), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Other), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Other), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.Success(), proto.Features(), ]) self.client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( self.client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="english", slip39=True, ) # Check if device is properly initialized resp = self.client.call_raw(proto.Initialize()) assert resp.initialized is True assert resp.needs_backup is False assert resp.pin_protection is False assert resp.passphrase_protection is False