You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-firmware/core/src/apps/bitcoin/verify_message.py

64 lines
1.9 KiB

from trezor import wire
from trezor.crypto.curve import secp256k1
from trezor.messages.InputScriptType import SPENDADDRESS, SPENDP2SHWITNESS, SPENDWITNESS
from trezor.messages.Success import Success
from apps.common import coins
from apps.common.signverify import message_digest, require_confirm_verify_message
from .addresses import (
address_p2wpkh,
address_p2wpkh_in_p2sh,
address_pkh,
address_short,
address_to_cashaddr,
)
async def verify_message(ctx, msg):
message = msg.message
address = msg.address
signature = msg.signature
coin_name = msg.coin_name or "Bitcoin"
coin = coins.by_name(coin_name)
digest = message_digest(coin, message)
script_type = None
recid = signature[0]
if recid >= 27 and recid <= 34:
script_type = SPENDADDRESS # p2pkh
elif recid >= 35 and recid <= 38:
script_type = SPENDP2SHWITNESS # segwit-in-p2sh
signature = bytes([signature[0] - 4]) + signature[1:]
elif recid >= 39 and recid <= 42:
script_type = SPENDWITNESS # native segwit
signature = bytes([signature[0] - 8]) + signature[1:]
else:
raise wire.ProcessError("Invalid signature")
pubkey = secp256k1.verify_recover(signature, digest)
if not pubkey:
raise wire.ProcessError("Invalid signature")
if script_type == SPENDADDRESS:
addr = address_pkh(pubkey, coin)
if coin.cashaddr_prefix is not None:
addr = address_to_cashaddr(addr, coin)
elif script_type == SPENDP2SHWITNESS:
addr = address_p2wpkh_in_p2sh(pubkey, coin)
elif script_type == SPENDWITNESS:
addr = address_p2wpkh(pubkey, coin)
else:
raise wire.ProcessError("Invalid signature")
if addr != address:
raise wire.ProcessError("Invalid signature")
await require_confirm_verify_message(
ctx, address_short(coin, address), "Verify message", message
)
return Success(message="Message verified")