mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-05 21:10:57 +00:00
feat(signing): show and verify label when signing
This commit is contained in:
parent
3da09ff85e
commit
ec36da26fd
@ -356,6 +356,10 @@ message TxAck {
|
|||||||
optional bytes orig_hash = 10; // tx_hash of the original transaction where this output was present (used when creating a replacement transaction)
|
optional bytes orig_hash = 10; // tx_hash of the original transaction where this output was present (used when creating a replacement transaction)
|
||||||
optional uint32 orig_index = 11; // index of the output in the original transaction (used when creating a replacement transaction)
|
optional uint32 orig_index = 11; // index of the output in the original transaction (used when creating a replacement transaction)
|
||||||
optional uint32 payment_req_index = 12 [(experimental_field)=true]; // index of the PaymentRequest containing this output
|
optional uint32 payment_req_index = 12 [(experimental_field)=true]; // index of the PaymentRequest containing this output
|
||||||
|
optional string label = 13; // label stored in Suite
|
||||||
|
optional bytes label_sig = 14; // sig(label|label_pk) stored in Suite, previously computed by Trezor
|
||||||
|
optional string label_pk = 15; // pubkey of the contact corresponding to the label
|
||||||
|
optional bytes address_pk_sig = 16; // signature of the address (signed by the receiver)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,6 +181,41 @@ class BasicApprover(Approver):
|
|||||||
|
|
||||||
await super()._add_output(txo, script_pubkey)
|
await super()._add_output(txo, script_pubkey)
|
||||||
|
|
||||||
|
async def confirm_output_label(self, txo: TxOutput) -> None:
|
||||||
|
from trezor.crypto.curve import secp256k1
|
||||||
|
from apps.common.signverify import message_digest
|
||||||
|
from apps.bitcoin.addresses import address_pkh
|
||||||
|
from apps.bitcoin.keychain import get_keychain_for_coin
|
||||||
|
from apps.common import coins
|
||||||
|
|
||||||
|
coin_testnet = coins.by_name("Testnet")
|
||||||
|
|
||||||
|
# Derive master public key
|
||||||
|
FIRST_TESTNET_ADDRESS_PATH = [2147483692, 2147483649, 2147483648, 0, 0]
|
||||||
|
keychain_testnet = await get_keychain_for_coin(coin_testnet)
|
||||||
|
master_node = keychain_testnet.derive(FIRST_TESTNET_ADDRESS_PATH)
|
||||||
|
master_pk = master_node.public_key()
|
||||||
|
|
||||||
|
if not txo.label or not txo.label_sig:
|
||||||
|
raise DataError("Missing label or label signature.")
|
||||||
|
|
||||||
|
# Verify that txo.label_sig matches label_message signed by my master key
|
||||||
|
label_message = txo.label + "/" + (txo.label_pk or txo.address)
|
||||||
|
label_message_digest = message_digest(coin_testnet, label_message.encode())
|
||||||
|
if not secp256k1.verify(master_pk, txo.label_sig, label_message_digest):
|
||||||
|
raise DataError("Invalid signature of label.")
|
||||||
|
|
||||||
|
# Verify that txo.address_pk_sig matches txo.address signed by txo.label_pk
|
||||||
|
if txo.label_pk and txo.address_pk_sig:
|
||||||
|
address_digest = message_digest(self.coin, txo.address.encode())
|
||||||
|
address_pk_sig_rec = secp256k1.verify_recover(txo.address_pk_sig, address_digest)
|
||||||
|
if txo.label_pk != address_pkh(address_pk_sig_rec, coin_testnet):
|
||||||
|
raise DataError("Invalid signature of address.")
|
||||||
|
elif not txo.label_pk and not txo.address_pk_sig:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise DataError("Both label public key and address public key signature must be present.")
|
||||||
|
|
||||||
async def add_change_output(self, txo: TxOutput, script_pubkey: bytes) -> None:
|
async def add_change_output(self, txo: TxOutput, script_pubkey: bytes) -> None:
|
||||||
await super().add_change_output(txo, script_pubkey)
|
await super().add_change_output(txo, script_pubkey)
|
||||||
self.change_count += 1
|
self.change_count += 1
|
||||||
@ -196,6 +231,9 @@ class BasicApprover(Approver):
|
|||||||
|
|
||||||
await super().add_external_output(txo, script_pubkey, tx_info, orig_txo)
|
await super().add_external_output(txo, script_pubkey, tx_info, orig_txo)
|
||||||
|
|
||||||
|
if txo.label:
|
||||||
|
await self.confirm_output_label(txo)
|
||||||
|
|
||||||
if orig_txo:
|
if orig_txo:
|
||||||
if txo.amount < orig_txo.amount:
|
if txo.amount < orig_txo.amount:
|
||||||
# Replacement transactions may need to decrease the value of external outputs to
|
# Replacement transactions may need to decrease the value of external outputs to
|
||||||
|
@ -96,7 +96,9 @@ async def confirm_output(
|
|||||||
title = None
|
title = None
|
||||||
|
|
||||||
address_label = None
|
address_label = None
|
||||||
if output.address_n and not output.multisig:
|
if output.label:
|
||||||
|
address_label = output.label
|
||||||
|
elif output.address_n and not output.multisig:
|
||||||
from trezor import utils
|
from trezor import utils
|
||||||
|
|
||||||
# Showing the account string only for model_tr layout
|
# Showing the account string only for model_tr layout
|
||||||
|
12
python/src/trezorlib/messages.py
generated
12
python/src/trezorlib/messages.py
generated
@ -2046,6 +2046,10 @@ class TxOutputType(protobuf.MessageType):
|
|||||||
10: protobuf.Field("orig_hash", "bytes", repeated=False, required=False, default=None),
|
10: protobuf.Field("orig_hash", "bytes", repeated=False, required=False, default=None),
|
||||||
11: protobuf.Field("orig_index", "uint32", repeated=False, required=False, default=None),
|
11: protobuf.Field("orig_index", "uint32", repeated=False, required=False, default=None),
|
||||||
12: protobuf.Field("payment_req_index", "uint32", repeated=False, required=False, default=None),
|
12: protobuf.Field("payment_req_index", "uint32", repeated=False, required=False, default=None),
|
||||||
|
13: protobuf.Field("label", "string", repeated=False, required=False, default=None),
|
||||||
|
14: protobuf.Field("label_sig", "bytes", repeated=False, required=False, default=None),
|
||||||
|
15: protobuf.Field("label_pk", "string", repeated=False, required=False, default=None),
|
||||||
|
16: protobuf.Field("address_pk_sig", "bytes", repeated=False, required=False, default=None),
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@ -2060,6 +2064,10 @@ class TxOutputType(protobuf.MessageType):
|
|||||||
orig_hash: Optional["bytes"] = None,
|
orig_hash: Optional["bytes"] = None,
|
||||||
orig_index: Optional["int"] = None,
|
orig_index: Optional["int"] = None,
|
||||||
payment_req_index: Optional["int"] = None,
|
payment_req_index: Optional["int"] = None,
|
||||||
|
label: Optional["str"] = None,
|
||||||
|
label_sig: Optional["bytes"] = None,
|
||||||
|
label_pk: Optional["str"] = None,
|
||||||
|
address_pk_sig: Optional["bytes"] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.address_n: Sequence["int"] = address_n if address_n is not None else []
|
self.address_n: Sequence["int"] = address_n if address_n is not None else []
|
||||||
self.amount = amount
|
self.amount = amount
|
||||||
@ -2070,6 +2078,10 @@ class TxOutputType(protobuf.MessageType):
|
|||||||
self.orig_hash = orig_hash
|
self.orig_hash = orig_hash
|
||||||
self.orig_index = orig_index
|
self.orig_index = orig_index
|
||||||
self.payment_req_index = payment_req_index
|
self.payment_req_index = payment_req_index
|
||||||
|
self.label = label
|
||||||
|
self.label_sig = label_sig
|
||||||
|
self.label_pk = label_pk
|
||||||
|
self.address_pk_sig = address_pk_sig
|
||||||
|
|
||||||
|
|
||||||
class PaymentRequestMemo(protobuf.MessageType):
|
class PaymentRequestMemo(protobuf.MessageType):
|
||||||
|
Loading…
Reference in New Issue
Block a user