def sender(self) -> Optional[Address]: if not self.signature: return None data_that_was_signed = self._data_to_sign() message_signature = self.signature try: address: Optional[Address] = eth_recover( data=data_that_was_signed, signature=message_signature, ) except InvalidSignature: address = None return address
def check_password(self, user_id, password): if not password: self.log.error('no password provided, user=%r', user_id) defer.returnValue(False) if not self._password_re.match(password): self.log.error( 'invalid password format, must be 0x-prefixed hex, ' 'lowercase, 65-bytes hash. user=%r', user_id, ) defer.returnValue(False) signature = unhexlify(password[2:]) user_match = self._user_re.match(user_id) if not user_match or user_match.group(2) != self.hs_hostname: self.log.error( 'invalid user format, must start with 0x-prefixed hex, ' 'lowercase address. user=%r', user_id, ) defer.returnValue(False) user_addr_hex = user_match.group(1) user_addr = unhexlify(user_addr_hex[2:]) rec_addr = eth_recover(data=self.hs_hostname.encode(), signature=signature) if not rec_addr or rec_addr != user_addr: self.log.error( 'invalid account password/signature. user=%r, signer=%r', user_id, rec_addr, ) defer.returnValue(False) localpart = user_id.split(":", 1)[0][1:] self.log.info('eth login! valid signature. user=%r', user_id) if not (yield self.account_handler.check_user_exists(user_id)): self.log.info('first user login, registering: user=%r', user_id) yield self.account_handler.register(localpart=localpart) defer.returnValue(True)
def test_signature(): ping = Ping(nonce=0, current_protocol_version=constants.PROTOCOL_VERSION) ping.sign(PRIVKEY) assert ping.sender == ADDRESS # test that the valid v values are accepted message_data = ping._data_to_sign() # This signature will sometimes end up with v being 0, sometimes 1 signature = eth_sign(privkey=PRIVKEY, data=message_data, v=0) assert ADDRESS == eth_recover(message_data, signature) # This signature will sometimes end up with v being 27, sometimes 28 signature = eth_sign(privkey=PRIVKEY, data=message_data, v=27) assert ADDRESS == eth_recover(message_data, signature) # test that other v values are rejected signature = signature[:-1] + bytes([29]) with pytest.raises(InvalidSignature): eth_recover(message_data, signature) signature = signature[:-1] + bytes([37]) with pytest.raises(InvalidSignature): eth_recover(message_data, signature) signature = signature[:-1] + bytes([38]) with pytest.raises(InvalidSignature): eth_recover(message_data, signature)
def update_transfer( self, channel_identifier: typing.ChannelID, partner: typing.Address, balance_hash: typing.BalanceHash, nonce: typing.Nonce, additional_hash: typing.AdditionalHash, closing_signature: typing.Signature, non_closing_signature: typing.Signature, ): log_details = { 'token_network': pex(self.address), 'node': pex(self.node_address), 'partner': pex(partner), 'nonce': nonce, 'balance_hash': encode_hex(balance_hash), 'additional_hash': encode_hex(additional_hash), 'closing_signature': encode_hex(closing_signature), 'non_closing_signature': encode_hex(non_closing_signature), } log.debug('updateNonClosingBalanceProof called', **log_details) data_that_was_signed = pack_balance_proof( nonce=nonce, balance_hash=balance_hash, additional_hash=additional_hash, channel_identifier=channel_identifier, token_network_identifier=typing.TokenNetworkID(self.address), chain_id=self.proxy.contract.functions.chain_id().call(), ) try: signer_address = eth_recover( data=data_that_was_signed, signature=closing_signature, ) # InvalidSignature is raised by eth_utils.eth_recover if signature # is not bytes or has the incorrect length # # ValueError is raised if the PublicKey instantiation failed, let it # propagate because it's a memory pressure problem. # # Exception is raised if the public key recovery failed. except Exception: # pylint: disable=broad-except msg = "Couldn't verify the balance proof signature" log.critical(f'updateNonClosingBalanceProof failed, {msg}', **log_details) raise RaidenUnrecoverableError(msg) if signer_address != partner: msg = 'Invalid balance proof signature' log.critical(f'updateNonClosingBalanceProof failed, {msg}', **log_details) raise RaidenUnrecoverableError(msg) self._check_for_outdated_channel( self.node_address, partner, channel_identifier, ) detail = self.detail_channel( participant1=self.node_address, participant2=partner, channel_identifier=channel_identifier, ) if detail.state != ChannelState.CLOSED: msg = 'Channel is not in a closed state' log.critical(f'updateNonClosingBalanceProof failed, {msg}', **log_details) raise RaidenUnrecoverableError(msg) if detail.settle_block_number < self.client.block_number(): msg = ('updateNonClosingBalanceProof cannot be called ' 'because the settlement period is over') log.critical(f'updateNonClosingBalanceProof failed, {msg}', **log_details) raise RaidenRecoverableError(msg) self._check_channel_state_for_update( channel_identifier=channel_identifier, closer=partner, update_nonce=nonce, log_details=log_details, ) transaction_hash = self.proxy.transact( 'updateNonClosingBalanceProof', safe_gas_limit(GAS_REQUIRED_FOR_UPDATE_BALANCE_PROOF), channel_identifier, partner, self.node_address, balance_hash, nonce, additional_hash, closing_signature, non_closing_signature, ) self.client.poll(transaction_hash) receipt_or_none = check_transaction_threw(self.client, transaction_hash) if receipt_or_none: if detail.settle_block_number < receipt_or_none['blockNumber']: msg = ('updateNonClosingBalanceProof transaction ' 'was mined after settlement finished') log.critical(f'updateNonClosingBalanceProof failed, {msg}', **log_details) raise RaidenRecoverableError(msg) self._check_channel_state_for_update( channel_identifier=channel_identifier, closer=partner, update_nonce=nonce, log_details=log_details, ) # This should never happen if the settlement window and gas price # estimation is done properly channel_settled = self.channel_is_settled( participant1=self.node_address, participant2=partner, channel_identifier=channel_identifier, ) if channel_settled is True: msg = 'Channel is settled' log.critical(f'updateNonClosingBalanceProof failed, {msg}', **log_details) raise RaidenRecoverableError(msg) msg = 'Update NonClosing balance proof' log.critical(f'updateNonClosingBalanceProof failed, {msg}', **log_details) raise TransactionThrew(msg, receipt_or_none) log.info('updateNonClosingBalanceProof successful', **log_details)