feat(core): Support Electrum signatures in VerifyMessage.

pull/2126/head
Andrew Kozlik 2 years ago committed by Andrew Kozlik
parent 464bc0e3c5
commit 4d40d6dbfc

@ -0,0 +1 @@
Support Electrum signatures in VerifyMessage.

@ -1,14 +1,16 @@
from typing import TYPE_CHECKING
from trezor import wire
from trezor import utils, wire
from trezor.crypto import base58
from trezor.crypto.curve import secp256k1
from trezor.enums import InputScriptType
from trezor.messages import Success
from trezor.ui.layouts import confirm_signverify
from trezor.ui.layouts import confirm_signverify, show_success
from apps.common import coins
from apps.common import address_type, coins
from apps.common.signverify import decode_message, message_digest
from . import common
from .addresses import (
address_p2wpkh,
address_p2wpkh_in_p2sh,
@ -18,9 +20,44 @@ from .addresses import (
)
if TYPE_CHECKING:
from apps.common.coininfo import CoinInfo
from trezor.messages import VerifyMessage
def address_to_script_type(address: str, coin: CoinInfo) -> InputScriptType:
# Determines the script type from a non-multisig address.
if coin.bech32_prefix and address.startswith(coin.bech32_prefix):
witver, _ = common.decode_bech32_address(coin.bech32_prefix, address)
if witver == 0:
return InputScriptType.SPENDWITNESS
elif witver == 1:
return InputScriptType.SPENDTAPROOT
else:
raise wire.DataError("Invalid address")
if (
not utils.BITCOIN_ONLY
and coin.cashaddr_prefix is not None
and address.startswith(coin.cashaddr_prefix + ":")
):
return InputScriptType.SPENDADDRESS
try:
raw_address = base58.decode_check(address, coin.b58_hash)
except ValueError:
raise wire.DataError("Invalid address")
if address_type.check(coin.address_type, raw_address):
# p2pkh
return InputScriptType.SPENDADDRESS
elif address_type.check(coin.address_type_p2sh, raw_address):
# p2sh
return InputScriptType.SPENDP2SHWITNESS
raise wire.DataError("Invalid address")
async def verify_message(ctx: wire.Context, msg: VerifyMessage) -> Success:
message = msg.message
address = msg.address
@ -30,17 +67,16 @@ async def verify_message(ctx: wire.Context, msg: VerifyMessage) -> Success:
digest = message_digest(coin, message)
script_type = address_to_script_type(address, coin)
recid = signature[0]
if 27 <= recid <= 34:
# p2pkh
script_type = InputScriptType.SPENDADDRESS
elif 35 <= recid <= 38:
# p2pkh or no script type provided
pass # use the script type from the address
elif 35 <= recid <= 38 and script_type == InputScriptType.SPENDP2SHWITNESS:
# segwit-in-p2sh
script_type = InputScriptType.SPENDP2SHWITNESS
signature = bytes([signature[0] - 4]) + signature[1:]
elif 39 <= recid <= 42:
elif 39 <= recid <= 42 and script_type == InputScriptType.SPENDWITNESS:
# native segwit
script_type = InputScriptType.SPENDWITNESS
signature = bytes([signature[0] - 8]) + signature[1:]
else:
raise wire.ProcessError("Invalid signature")
@ -52,7 +88,7 @@ async def verify_message(ctx: wire.Context, msg: VerifyMessage) -> Success:
if script_type == InputScriptType.SPENDADDRESS:
addr = address_pkh(pubkey, coin)
if coin.cashaddr_prefix is not None:
if not utils.BITCOIN_ONLY and coin.cashaddr_prefix is not None:
addr = address_to_cashaddr(addr, coin)
elif script_type == InputScriptType.SPENDP2SHWITNESS:
addr = address_p2wpkh_in_p2sh(pubkey, coin)

@ -56,6 +56,18 @@ def test_message_verify(client: Client):
)
assert res is True
# no script type
res = btc.verify_message(
client,
"Bitcoin",
"3L6TyTisPBmrDAj6RoKmDzNnj4eQi54gD2",
bytes.fromhex(
"1f744de4516fac5c140808015664516a32fead94de89775cec7e24dbc24fe133075ac09301c4cc8e197bea4b6481661d5b8e9bf19d8b7b8a382ecdb53c2ee0750d"
),
"This is an example of a signed message.",
)
assert res is True
# trezor pubkey - FAIL - wrong sig
res = btc.verify_message(
client,

@ -56,6 +56,18 @@ def test_message_verify(client: Client):
)
assert res is True
# no script type
res = btc.verify_message(
client,
"Bitcoin",
"bc1qannfxke2tfd4l7vhepehpvt05y83v3qsf6nfkk",
bytes.fromhex(
"20b55d7600d9e9a7e2a49155ddf3cfdb8e796c207faab833010fa41fb7828889bc47cf62348a7aaa0923c0832a589fab541e8f12eb54fb711c90e2307f0f66b194"
),
"This is an example of a signed message.",
)
assert res is True
# trezor pubkey - FAIL - wrong sig
res = btc.verify_message(
client,

Loading…
Cancel
Save