mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-10 23:40:58 +00:00
feat(core): Support Electrum signatures in VerifyMessage.
This commit is contained in:
parent
464bc0e3c5
commit
4d40d6dbfc
1
core/.changelog.d/2100.added
Normal file
1
core/.changelog.d/2100.added
Normal file
@ -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…
Reference in New Issue
Block a user