Exemplo n.º 1
0
    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
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
    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)
Exemplo n.º 5
0
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)
Exemplo n.º 6
0
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)
Exemplo n.º 7
0
    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)