Raise version. Verify message with coincurve.

This commit is contained in:
tecnovert 2021-01-19 15:10:42 +02:00
parent d12e24cecb
commit c3cff91fca
No known key found for this signature in database
GPG Key ID: 8ED6D8750C4E3F93
4 changed files with 49 additions and 14 deletions

View File

@ -1,3 +1,3 @@
name = "basicswap" name = "basicswap"
__version__ = "0.0.11" __version__ = "0.0.12"

View File

@ -3523,7 +3523,7 @@ class BasicSwap(BaseApp):
# Verify proof of funds # Verify proof of funds
bid_proof_address = replaceAddrPrefix(bid_data.proof_address, Coins.PART, self.chain) bid_proof_address = replaceAddrPrefix(bid_data.proof_address, Coins.PART, self.chain)
mm = chainparams[coin_to]['message_magic'] mm = chainparams[coin_to]['message_magic']
passed = self.callcoinrpc(Coins.PART, 'verifymessage', [bid_proof_address, bid_data.proof_signature, bid_data.proof_address + '_swap_proof', mm]) passed = self.ci(Coins.PART).verifyMessage(bid_proof_address, bid_data.proof_address + '_swap_proof', bid_data.proof_signature, mm)
assert(passed is True), 'Proof of funds signature invalid' assert(passed is True), 'Proof of funds signature invalid'
if self.coin_clients[coin_to]['use_segwit']: if self.coin_clients[coin_to]['use_segwit']:

View File

@ -6,6 +6,7 @@
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import time import time
import base64
import hashlib import hashlib
import logging import logging
from io import BytesIO from io import BytesIO
@ -14,10 +15,12 @@ from basicswap.contrib.test_framework import segwit_addr
from .util import ( from .util import (
decodeScriptNum, decodeScriptNum,
getCompactSizeLen, getCompactSizeLen,
SerialiseNumCompact,
dumpj, dumpj,
format_amount, format_amount,
make_int, make_int,
toWIF, toWIF,
assert_cond,
decodeAddress) decodeAddress)
from coincurve.keys import ( from coincurve.keys import (
PrivateKey, PrivateKey,
@ -61,7 +64,6 @@ from .contrib.test_framework.script import (
from .chainparams import CoinInterface, Coins, chainparams from .chainparams import CoinInterface, Coins, chainparams
from .rpc import make_rpc_func from .rpc import make_rpc_func
from .util import assert_cond
def findOutput(tx, script_pk): def findOutput(tx, script_pk):
@ -859,6 +861,26 @@ class BTCInterface(CoinInterface):
rv = pubkey.verify_compact(sig, message_hash, hasher=None) rv = pubkey.verify_compact(sig, message_hash, hasher=None)
assert(rv is True) assert(rv is True)
def verifyMessage(self, address, message, signature, message_magic=None):
if message_magic is None:
message_magic = chainparams[self.coin_type()]['message_magic']
message_bytes = SerialiseNumCompact(len(message_magic)) + bytes(message_magic, 'utf-8') + SerialiseNumCompact(len(message)) + bytes(message, 'utf-8')
message_hash = hashlib.sha256(hashlib.sha256(message_bytes).digest()).digest()
signature_bytes = base64.b64decode(signature)
rec_id = (signature_bytes[0] - 27) & 3
signature_bytes = signature_bytes[1:] + bytes((rec_id,))
try:
pubkey = PublicKey.from_signature_and_message(signature_bytes, message_hash, hasher=None)
except Exception as e:
logging.info('verifyMessage failed: ' + str(e))
return False
address_hash = self.decodeAddress(address)
pubkey_hash = hash160(pubkey.format())
return True if address_hash == pubkey_hash else False
def testBTCInterface(): def testBTCInterface():
print('testBTCInterface') print('testBTCInterface')

View File

@ -7,6 +7,7 @@
import json import json
import time import time
import struct
import decimal import decimal
import hashlib import hashlib
@ -113,9 +114,9 @@ def decodeWif(network_key):
def toWIF(prefix_byte, b, compressed=True): def toWIF(prefix_byte, b, compressed=True):
b = bytes((prefix_byte, )) + b b = bytes((prefix_byte,)) + b
if compressed: if compressed:
b += bytes((0x01, )) b += bytes((0x01,))
b += hashlib.sha256(hashlib.sha256(b).digest()).digest()[:4] b += hashlib.sha256(hashlib.sha256(b).digest()).digest()[:4]
return b58encode(b) return b58encode(b)
@ -163,9 +164,9 @@ def pubkeyToAddress(prefix, pubkey):
def SerialiseNum(n): def SerialiseNum(n):
if n == 0: if n == 0:
return bytes([0x00]) return bytes((0x00,))
if n > 0 and n <= 16: if n > 0 and n <= 16:
return bytes([0x50 + n]) return bytes((0x50 + n,))
rv = bytearray() rv = bytearray()
neg = n < 0 neg = n < 0
absvalue = -n if neg else n absvalue = -n if neg else n
@ -176,7 +177,7 @@ def SerialiseNum(n):
rv.append(0x80 if neg else 0) rv.append(0x80 if neg else 0)
elif neg: elif neg:
rv[-1] |= 0x80 rv[-1] |= 0x80
return bytes([len(rv)]) + rv return bytes((len(rv),)) + rv
def DeserialiseNum(b, o=0): def DeserialiseNum(b, o=0):
@ -222,15 +223,27 @@ def getCompactSizeLen(v):
# Compact Size # Compact Size
if v < 253: if v < 253:
return 1 return 1
if v < 0xffff: # USHRT_MAX if v <= 0xffff: # USHRT_MAX
return 3 return 3
if v < 0xffffffff: # UINT_MAX if v <= 0xffffffff: # UINT_MAX
return 5 return 5
if v < 0xffffffffffffffff: # UINT_MAX if v <= 0xffffffffffffffff: # UINT_MAX
return 9 return 9
raise ValueError('Value too large') raise ValueError('Value too large')
def SerialiseNumCompact(v):
if v < 253:
return bytes((v,))
if v <= 0xffff: # USHRT_MAX
return struct.pack("<BH", 253, v)
if v <= 0xffffffff: # UINT_MAX
return struct.pack("<BI", 254, v)
if v <= 0xffffffffffffffff: # UINT_MAX
return struct.pack("<BQ", 255, v)
raise ValueError('Value too large')
def float_to_str(f): def float_to_str(f):
# stackoverflow.com/questions/38847690 # stackoverflow.com/questions/38847690
d1 = decimal_ctx.create_decimal(repr(f)) d1 = decimal_ctx.create_decimal(repr(f))
@ -314,10 +327,10 @@ def format_timestamp(value, with_seconds=False):
def getP2SHScriptForHash(p2sh): def getP2SHScriptForHash(p2sh):
return bytes([OpCodes.OP_HASH160, 0x14]) \ return bytes((OpCodes.OP_HASH160, 0x14)) \
+ p2sh \ + p2sh \
+ bytes([OpCodes.OP_EQUAL]) + bytes((OpCodes.OP_EQUAL,))
def getP2WSH(script): def getP2WSH(script):
return bytes([OpCodes.OP_0, 0x20]) + hashlib.sha256(script).digest() return bytes((OpCodes.OP_0, 0x20)) + hashlib.sha256(script).digest()