signmessage: also accept Trezor-type sigs for p2wpkh and p2wpkh-p2sh addrs
The signatures we create are unchanged but we now also accept signatures created by Trezor and others. see https://github.com/spesmilo/electrum/issues/3861
This commit is contained in:
@@ -173,19 +173,34 @@ class ECPubkey(object):
|
||||
return ECPubkey._from_libsecp256k1_pubkey_ptr(pubkey)
|
||||
|
||||
@classmethod
|
||||
def from_signature65(cls, sig: bytes, msg_hash: bytes) -> Tuple['ECPubkey', bool]:
|
||||
def from_signature65(cls, sig: bytes, msg_hash: bytes) -> Tuple['ECPubkey', bool, Optional[str]]:
|
||||
if len(sig) != 65:
|
||||
raise Exception(f'wrong encoding used for signature? len={len(sig)} (should be 65)')
|
||||
nV = sig[0]
|
||||
if not (27 <= nV <= 34):
|
||||
# as per BIP-0137:
|
||||
# 27-30: p2pkh (uncompressed)
|
||||
# 31-34: p2pkh (compressed)
|
||||
# 35-38: p2wpkh-p2sh
|
||||
# 39-42: p2wpkh
|
||||
# However, the signatures we create do not respect this, and we instead always use 27-34,
|
||||
# only distinguishing between compressed/uncompressed, so we treat those values as "any".
|
||||
if not (27 <= nV <= 42):
|
||||
raise Exception("Bad encoding")
|
||||
if nV >= 31:
|
||||
compressed = True
|
||||
txin_type_guess = None
|
||||
compressed = True
|
||||
if nV >= 39:
|
||||
nV -= 12
|
||||
txin_type_guess = "p2wpkh"
|
||||
elif nV >= 35:
|
||||
nV -= 8
|
||||
txin_type_guess = "p2wpkh-p2sh"
|
||||
elif nV >= 31:
|
||||
nV -= 4
|
||||
else:
|
||||
compressed = False
|
||||
recid = nV - 27
|
||||
return cls.from_sig_string(sig[1:], recid, msg_hash), compressed
|
||||
pubkey = cls.from_sig_string(sig[1:], recid, msg_hash)
|
||||
return pubkey, compressed, txin_type_guess
|
||||
|
||||
@classmethod
|
||||
def from_x_and_y(cls, x: int, y: int) -> 'ECPubkey':
|
||||
@@ -294,7 +309,7 @@ class ECPubkey(object):
|
||||
assert_bytes(message)
|
||||
h = algo(message)
|
||||
try:
|
||||
public_key, compressed = self.from_signature65(sig65, h)
|
||||
public_key, compressed, txin_type_guess = self.from_signature65(sig65, h)
|
||||
except Exception:
|
||||
return False
|
||||
# check public key
|
||||
@@ -376,12 +391,13 @@ def verify_message_with_address(address: str, sig65: bytes, message: bytes, *, n
|
||||
if net is None: net = constants.net
|
||||
h = sha256d(msg_magic(message))
|
||||
try:
|
||||
public_key, compressed = ECPubkey.from_signature65(sig65, h)
|
||||
public_key, compressed, txin_type_guess = ECPubkey.from_signature65(sig65, h)
|
||||
except Exception as e:
|
||||
return False
|
||||
# check public key using the address
|
||||
pubkey_hex = public_key.get_public_key_hex(compressed)
|
||||
for txin_type in ['p2pkh','p2wpkh','p2wpkh-p2sh']:
|
||||
txin_types = (txin_type_guess,) if txin_type_guess else ('p2pkh', 'p2wpkh', 'p2wpkh-p2sh')
|
||||
for txin_type in txin_types:
|
||||
addr = pubkey_to_address(txin_type, pubkey_hex, net=net)
|
||||
if address == addr:
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user