diff --git a/electrum/commands.py b/electrum/commands.py index beaaa43c413..0cdf4576922 100644 --- a/electrum/commands.py +++ b/electrum/commands.py @@ -918,7 +918,12 @@ async def signmessage(self, address, message, password=None, wallet: Abstract_Wa raise UserFacingException(f"address must be a str instead of {type(address)}") if not isinstance(message, str): raise UserFacingException(f"message must be a str instead of {type(message)}") - sig = wallet.sign_message(address=address, message=message, password=password) + sig = wallet.sign_message( + address=address, + message=message, + password=password, + strip_inputs=False, # respect whitespaces for CLI + ) return base64.b64encode(sig).decode('ascii') @command('') @@ -935,7 +940,12 @@ async def verifymessage(self, address, signature, message): raise UserFacingException(f"signature must be a str instead of {type(signature)}") if not isinstance(message, str): raise UserFacingException(f"message must be a str instead of {type(message)}") - return Abstract_Wallet.verify_message(address=address, signature=signature, message=message) + return Abstract_Wallet.verify_message( + address=address, + signature=signature, + message=message, + strip_inputs=False, # respect whitespaces for CLI + ) def _get_fee_policy(self, fee: str, feerate: str): if fee is not None and feerate is not None: diff --git a/electrum/gui/qml/qedaemon.py b/electrum/gui/qml/qedaemon.py index 749ee319e9b..b0779c100dc 100644 --- a/electrum/gui/qml/qedaemon.py +++ b/electrum/gui/qml/qedaemon.py @@ -506,9 +506,6 @@ def startNetwork(self): @pyqtSlot(str, str, str, result=bool) def verifyMessage(self, address, message, signature): - address = address.strip() - message = message.strip() - signature = signature.strip() try: return Abstract_Wallet.verify_message(address=address, signature=signature, message=message) except UserFacingException as e: diff --git a/electrum/gui/qml/qewallet.py b/electrum/gui/qml/qewallet.py index 5d3e233d449..88e602e221e 100644 --- a/electrum/gui/qml/qewallet.py +++ b/electrum/gui/qml/qewallet.py @@ -848,9 +848,6 @@ def isAddressMine(self, addr): @pyqtSlot(str, str) @auth_protect(message=_("Sign message?")) def signMessage(self, address, message): - # strip, as in qt gui and in qml verifyMessage (see #4327) - address = address.strip() - message = message.strip() try: sig = self.wallet.sign_message(address=address, message=message, password=self.password) except UserFacingException as e: diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py index 20244bb4932..ffc8da7df39 100644 --- a/electrum/gui/qt/main_window.py +++ b/electrum/gui/qt/main_window.py @@ -2132,12 +2132,10 @@ def do_sign( signature_e: ButtonsTextEdit, password, ) -> None: - address = address_e.text().strip() - message = message_e.toPlainText().strip() task = partial( self.wallet.sign_message, - address=address, - message=message, + address=address_e.text(), + message=message_e.toPlainText(), password=password, ) @@ -2157,13 +2155,11 @@ def do_verify( message_e: QTextEdit, signature_e: ButtonsTextEdit, ) -> None: - address = address_e.text().strip() - message = message_e.toPlainText().strip() task = partial( self.wallet.verify_message, - address=address, + address=address_e.text(), signature=str(signature_e.toPlainText()), - message=message, + message=message_e.toPlainText(), ) def on_result(verified): diff --git a/electrum/wallet.py b/electrum/wallet.py index 55d8a730709..0d2210376fd 100644 --- a/electrum/wallet.py +++ b/electrum/wallet.py @@ -3234,10 +3234,14 @@ def update_password(self, old_pw, new_pw, *, encrypt_storage: bool = True, xpub_ def _update_password_for_keystore(self, old_pw: Optional[str], new_pw: Optional[str]) -> None: pass - def sign_message(self, *, address: str, message: str, password) -> bytes: + def sign_message(self, *, address: str, message: str, password, strip_inputs: bool = True) -> bytes: """Caller must handle UserFacingException.""" assert isinstance(address, str), f"address must be str. got {type(address)}" assert isinstance(message, str), f"message must be str. got {type(message)}" + if strip_inputs: + # stripping whitespaces leads to better UX for GUIs, but it's counter-productive for CLI + address = address.strip() + message = message.strip() if not bitcoin.is_address(address): raise UserFacingException(_("Invalid Bitcoin address.")) if self.is_watching_only(): @@ -3260,11 +3264,16 @@ def sign_message(self, *, address: str, message: str, password) -> bytes: return self.keystore.sign_message(index, message, password, script_type=txin_type) @classmethod - def verify_message(cls, *, address: str, signature: str, message: str) -> bool: + def verify_message(cls, *, address: str, signature: str, message: str, strip_inputs: bool = True) -> bool: """Caller must handle UserFacingException.""" assert isinstance(address, str), f"address must be str. got {type(address)}" assert isinstance(signature, str), f"signature must be str. got {type(signature)}" assert isinstance(message, str), f"message must be str. got {type(message)}" + if strip_inputs: + # stripping whitespaces leads to better UX for GUIs, but it's counter-productive for CLI + address = address.strip() + signature = signature.strip() + message = message.strip() if not is_address(address): raise UserFacingException(_("Invalid Bitcoin address.")) try: