def __post_init__(self) -> None: super(MonitorRequest, self).__post_init__() self.non_closing_signer = recover(data=self.packed_non_closing_data(), signature=self.non_closing_signature) self.reward_proof_signer = recover( data=self.packed_reward_proof_data(), signature=self.reward_proof_signature)
def __post_init__(self) -> None: super(MonitorRequest, self).__post_init__() assert is_checksum_address(self.token_network_address) self.non_closing_signer = to_checksum_address( recover( data=self.packed_non_closing_data(), signature=decode_hex(self.non_closing_signature), )) self.reward_proof_signer = to_checksum_address( recover( data=self.packed_reward_proof_data(), signature=decode_hex(self.reward_proof_signature), ))
def test_signature(): ping = Ping( nonce=0, current_protocol_version=constants.PROTOCOL_VERSION, signature=constants.EMPTY_SIGNATURE, ) ping.sign(signer) 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 = signer.sign(data=message_data, v=0) assert ADDRESS == recover(message_data, signature) # This signature will sometimes end up with v being 27, sometimes 28 signature = signer.sign(data=message_data, v=27) assert ADDRESS == recover(message_data, signature) # test that other v values are rejected signature = signature[:-1] + bytes([29]) with pytest.raises(InvalidSignature): recover(message_data, signature) signature = signature[:-1] + bytes([37]) with pytest.raises(InvalidSignature): recover(message_data, signature) signature = signature[:-1] + bytes([38]) with pytest.raises(InvalidSignature): recover(message_data, signature)
def validate_userid_signature(user: User) -> Optional[Address]: """ Validate a userId format and signature on displayName, and return its address""" # display_name should be an address in the USERID_RE format match = USERID_RE.match(user.user_id) if not match: return None encoded_address = match.group(1) address: Address = to_canonical_address(encoded_address) try: displayname = user.get_display_name() recovered = recover( data=user.user_id.encode(), signature=decode_hex(displayname), ) if not (address and recovered and recovered == address): return None except ( DecodeError, TypeError, InvalidSignature, MatrixRequestError, json.decoder.JSONDecodeError, ): return None return address
def is_signature_valid(self) -> bool: packed_data = self.sender + self.receiver + Web3.toBytes(text=self.timestamp_str) try: recovered_address = recover(packed_data, self.signature) except InvalidSignature: return False return is_same_address(recovered_address, self.sender)
def test_secret_request_5(): dict_data = { "type": "SecretRequest", "message_identifier": 9443946215632930647, "payment_identifier": 1322351847924173620, "amount": 100000000000000000, "expiration": 12000000, "secrethash": "0xaf1ca2932cb5c3e3045eedb17ce760419d2b3e5234eeefe6fd82475adeb4da10" } message = SecretRequest(message_identifier=dict_data["message_identifier"], payment_identifier=dict_data["payment_identifier"], secrethash=decode_hex(dict_data["secrethash"]), amount=dict_data["amount"], expiration=dict_data["expiration"]) message.sign(signer) data_was_signed = message._data_to_sign() print("SR signature: " + message.signature.hex()) assert recover(data_was_signed, message.signature) == to_canonical_address( "0x7ca28d3d760b4aa2b79e8d42cbdc187c7df9af40")
def test_processed(): message = Processed(message_identifier=MessageID(18237677588114994956)) message.sign(signer) data_was_signed = message._data_to_sign() print("Processed signature: " + message.signature.hex()) assert recover(data_was_signed, message.signature) == to_canonical_address( "0x7ca28d3d760b4aa2b79e8d42cbdc187c7df9af40")
def validate_userid_signature(user: User) -> Optional[Address]: """ Validate a userId format and signature on displayName, and return its address""" # display_name should be an address in the USERID_RE format match = USERID_RE.match(user.user_id) if not match: return None msg = ( "The User instance provided to validate_userid_signature must have the " "displayname attribute set. Make sure to warm the value using the " "DisplayNameCache.") displayname = user.displayname assert displayname is not None, msg encoded_address = match.group(1) address: Address = to_canonical_address(encoded_address) try: if DISPLAY_NAME_HEX_RE.match(displayname): signature_bytes = decode_hex(displayname) else: return None recovered = recover(data=user.user_id.encode(), signature=Signature(signature_bytes)) if not (address and recovered and recovered == address): return None except ( DecodeError, TypeError, InvalidSignature, MatrixRequestError, json.decoder.JSONDecodeError, ): return None return address
def test_our_signed_msg(): # Signed data dict_msg = { "type": "LockedTransfer", "chain_id": 33, "message_identifier": 12248562144413481135, "payment_identifier": 11640634370223461850, "payment_hash_invoice": "0x", "nonce": 1, "token_network_address": "0x877ec5961d18d3413fabbd67696b758fe95408d6", "token": "0xff10e500973a0b0071e2263421e4af60425834a6", "channel_identifier": 1, "transferred_amount": 0, "locked_amount": 100000000000000, "recipient": "0x29021129f5d038897f01bd4bc050525ca01a4758", "locksroot": "0x3985b475b7e3af72cdbcd2e41b22951c168b0e2ff41bcc9548ee98d14ec86784", "lock": { "type": "Lock", "amount": 100000000000000, "expiration": 195730, "secrethash": "0x3e6d58ba381898cf1a0ff6fbe65a3805419063ea9eb6ff6bc6f0dde45032d0dc" }, "target": "0x29021129f5d038897f01bd4bc050525ca01a4758", "initiator": "0x09fcbe7ceb49c944703b4820e29b0541edfe7e82", "fee": 0, "signature": "0x68b12d6de97e2be66a5d013a7118264ab696a45ebe7f9ef590c88286ba7804154e0a1418d78712d4aa227c33af23ebae2ff8114a7e3f3d9efb7e342235eba5941b" } # Construct message from dict (this includes and creates a sender field according to signature) message = message_from_dict(dict_msg) assert message.signature == decode_hex( "0x68b12d6de97e2be66a5d013a7118264ab696a45ebe7f9ef590c88286ba7804154e0a1418d78712d4aa227c33af23ebae2ff8114a7e3f3d9efb7e342235eba5941b" ) # TODO this assert condition. assert recover(message._data_to_sign(), message.signature) != to_canonical_address( "0x09fcbe7ceb49c944703b4820e29b0541edfe7e82")
def verify_request_monitoring(self, partner_address: Address, requesting_address: Address) -> bool: """ One should only use this method to verify integrity and signatures of a RequestMonitoring message. """ if not self.non_closing_signature: return False balance_proof_data = pack_balance_proof( nonce=self.balance_proof.nonce, balance_hash=self.balance_proof.balance_hash, additional_hash=self.balance_proof.additional_hash, canonical_identifier=CanonicalIdentifier( chain_identifier=self.balance_proof.chain_id, token_network_address=self.balance_proof.token_network_address, channel_identifier=self.balance_proof.channel_identifier, ), ) blinded_data = pack_signed_balance_proof( msg_type=MessageTypeId.BALANCE_PROOF_UPDATE, nonce=self.balance_proof.nonce, balance_hash=self.balance_proof.balance_hash, additional_hash=self.balance_proof.additional_hash, canonical_identifier=CanonicalIdentifier( chain_identifier=self.balance_proof.chain_id, token_network_address=self.balance_proof.token_network_address, channel_identifier=self.balance_proof.channel_identifier, ), partner_signature=self.balance_proof.signature, ) reward_proof_data = pack_reward_proof( chain_id=self.balance_proof.chain_id, token_network_address=self.balance_proof.token_network_address, reward_amount=self.reward_amount, monitoring_service_contract_address=self. monitoring_service_contract_address, non_closing_participant=requesting_address, non_closing_signature=self.non_closing_signature, ) reward_proof_signature = self.reward_proof_signature or EMPTY_SIGNATURE return (recover(balance_proof_data, self.balance_proof.signature) == partner_address and recover(blinded_data, self.non_closing_signature) == requesting_address and recover(reward_proof_data, reward_proof_signature) == requesting_address)
def test_working_raiden(): # Signed data dict_msg = { "type": "LockedTransfer", "chain_id": 33, "message_identifier": 1492744266262786169, "payment_identifier": 5037359832394936637, "payment_hash_invoice": "0x", "nonce": 9, "token_network_address": "0x877ec5961d18d3413fabbd67696b758fe95408d6", "token": "0xff10e500973a0b0071e2263421e4af60425834a6", "channel_identifier": 3, "transferred_amount": 100000000000000000, "locked_amount": 200000000000000000, "recipient": "0x5fd79c7dd13a67361f22dafdd3127c4ae639ec3b", "locksroot": "0x277d40c5b54433ce56255ca389d11207cc8ce64cac9fc2725cd30d0d1ce624a9", "lock": { "type": "Lock", "amount": 200000000000000000, "expiration": 252207, "secrethash": "0xde3a845acb01d53d24d0848ccc420e4f700e0bc67f007b7aa098880ab9fa131a" }, "target": "0x5fd79c7dd13a67361f22dafdd3127c4ae639ec3b", "initiator": "0xa358b95b3ee75e426d89f91d65a27e8d83bbf995", "fee": 0, "signature": "0x6f6ca17a6660dc4203409e3671dd7dc653d6ac01bc53cf5ba0259adb7766333b1a0850d4adff075735a2f7e4c6a20cb3271fbc86af5ad9ad87fe8752002bf9401b" } # Construct message from dict (this includes and creates a sender field according to signature) message = message_from_dict(dict_msg) assert message.signature == decode_hex( "0x6f6ca17a6660dc4203409e3671dd7dc653d6ac01bc53cf5ba0259adb7766333b1a0850d4adff075735a2f7e4c6a20cb3271fbc86af5ad9ad87fe8752002bf9401b" ) assert recover(message._data_to_sign(), message.signature) == to_canonical_address( "0xa358b95B3ee75e426d89F91d65a27E8d83bBF995")
def is_signature_valid(self): packed_data = (Web3.toBytes(hexstr=self.sender) + Web3.toBytes(hexstr=self.receiver) + encode_single('uint256', self.amount) + encode_single('uint256', self.expiration_block)) try: recovered_address = recover(packed_data, self.signature) except InvalidSignature: return False return is_same_address(recovered_address, self.sender)
def test_update_pfs(): balance_proof = BalanceProofUnsignedState.from_dict( make_balance_proof(signer=signer, amount=1).to_dict(), ) message = UpdatePFS.from_balance_proof( balance_proof=balance_proof, reveal_timeout=1, ) assert message.signature == b'' message.sign(signer) assert recover(message._data_to_sign(), message.signature) == ADDRESS
def test_recover(): account = to_canonical_address( "0x38e959391dD8598aE80d5d6D114a7822A09d313A") message = b"message" # generated with Metamask's web3.personal.sign signature = decode_hex( "0x1eff8317c59ab169037f5063a5129bb1bab0299fef0b5621d866b07be59e2c0a" "6a404e88d3360fb58bd13daf577807c2cf9b6b26d80fc929c52e952769a460981c") assert recover(data=message, signature=signature) == account
def test_reveal_secret_7(): print("Secret {} ".format(secret.hex())) print("SecretHash {} ".format(secrethash.hex())) message = RevealSecret(message_identifier=MessageID(2226977946511089099), secret=secret) message.sign(signer) data_was_signed = message._data_to_sign() print("Reveal Secret signature: " + message.signature.hex()) assert recover(data_was_signed, message.signature) == to_canonical_address( "0x7ca28d3d760b4aa2b79e8d42cbdc187c7df9af40")
def test_recover_address_from_matrix_server_domain_and_signature(): rsk_address = "0x6d369723521B4080A19457D5Fdd2194d633B0c3A" rsk_address_normalized = to_normalized_address(rsk_address) matrix_server_domain = "transport02.raiden.network" # generated with Metamask's web3.personal.sign signature = decode_hex( "a5c73a3717f8d466bd8fde0d2e2a358e0e67307e09bab65f8cc83e7de5a7af3b2293" "16addd32333cf04a5045bf2a740c91a090bdafd88bb92d26de34068f6c841b") assert recover(data=matrix_server_domain.encode(), signature=signature) == \ to_canonical_address(rsk_address_normalized)
def test_changing_route_metadata_will_invalidate_lock_transfer_signature(): one_locked_transfer = factories.create( factories.LockedTransferProperties(sender=ADDRESS, pkey=PRIVKEY)) new_route_metadata = factories.create( factories.RouteMetadataProperties( route=[factories.HOP2, factories.HOP1])) new_metadata = factories.create( factories.Metadata(routes=[new_route_metadata])) assert ADDRESS == recover(one_locked_transfer._data_to_sign(), one_locked_transfer.signature ), "signature does not match signer address" one_locked_transfer.metadata = new_metadata assert ADDRESS != recover( one_locked_transfer._data_to_sign(), one_locked_transfer.signature ), "signature should not be valid after data being altered"
def test_signature_without_secret(): dict_msg = { "type": "Delivered", "delivered_message_identifier": 15646344508401696016 } message = Delivered.from_dict_unsigned(dict_msg) message.sign(signer) data_was_signed = message._data_to_sign() print(message.signature.hex()) assert recover(data_was_signed, message.signature) == to_canonical_address( "0x09fcbe7ceb49c944703b4820e29b0541edfe7e82")
def test_delivered(): dict_msg = { "type": "Delivered", "delivered_message_identifier": 18237677588114994956 } message = Delivered.from_dict_unsigned(dict_msg) message.sign(signer) data_was_signed = message._data_to_sign() print("Delivered signature: " + message.signature.hex()) assert recover(data_was_signed, message.signature) == to_canonical_address( "0x7ca28d3d760b4aa2b79e8d42cbdc187c7df9af40")
def sender(self) -> Optional[Address]: # type: ignore if not self.signature: return None data_that_was_signed = self._data_to_sign() message_signature = self.signature try: address: Optional[Address] = recover(data=data_that_was_signed, signature=message_signature) except InvalidSignature: address = None return address
def test_update_non_closing_balance_proof(): dict_data = { "type": "Secret", "chain_id": 33, "message_identifier": 4174357123961474742, "payment_identifier": 5100335212362582814, "secret": "0xd1b2cb5b175436f60b6e59be64f4c7b59b3569b8f877c55f66c8f8a6ba8055f4", "nonce": 2, "token_network_address": "0x013b47e5eb40a476dc0e9a212d376899288561a2", "channel_identifier": 14, "transferred_amount": 20000000, "locked_amount": 0, "locksroot": "0x0000000000000000000000000000000000000000000000000000000000000000", "signature": "0x94d6dba985096b6259151664367443bcd83c5e8cc1913c34bd3542b4ac1b4e7772696e145445625eef4167080fddb3ebe730c71319bee66235864661d9dddc2b1c" } # dict_data = {"type": "Secret", "chain_id": 33, "message_identifier": 18237677588114994956, "payment_identifier": 1322351847924173620, "secret": "0xa4678d1f1db376f20854619fc8aa8021f88f318e14ff600aa051e8e4ded5d023", "nonce": 2, "token_network_address": "0x7351ed719de72db92a54c99ef2c4d287f69672a1", "channel_identifier": 3, "transferred_amount": 100000000000000000, "locked_amount": 0, "locksroot": "0x0000000000000000000000000000000000000000000000000000000000000000", "signature": "0x5c805ba51ac4776d879c276d54c1ed97905399e227e7b9ef50aa4f36605ac25e5ab707641c4bd85a0d89549841beaf4f0e06c839ad5460aaf26d4c68b9af822c1b"} balance_proof_msg = Unlock.from_dict(dict_data) balance_proof = balanceproof_from_envelope(balance_proof_msg) non_closing_signature = create_balance_proof_update_signature( "0x013b47e5eb40a476dc0e9a212d376899288561a2", 14, balance_proof.balance_hash, 2, balance_proof.message_hash, decode_hex( "0x94d6dba985096b6259151664367443bcd83c5e8cc1913c34bd3542b4ac1b4e7772696e145445625eef4167080fddb3ebe730c71319bee66235864661d9dddc2b1c" )) our_signed_data = pack_balance_proof_update( nonce=balance_proof.nonce, balance_hash=balance_proof.balance_hash, additional_hash=balance_proof.message_hash, canonical_identifier=balance_proof.canonical_identifier, partner_signature=Signature( decode_hex( "0x94d6dba985096b6259151664367443bcd83c5e8cc1913c34bd3542b4ac1b4e7772696e145445625eef4167080fddb3ebe730c71319bee66235864661d9dddc2b1c" ))) print("Update non consling blanace proof signature " + non_closing_signature.hex()) our_recovered_address = recover(data=our_signed_data, signature=Signature(non_closing_signature)) assert our_recovered_address == to_canonical_address( "0x7ca28d3d760b4aa2b79e8d42cbdc187c7df9af40")
def test_reveal_secret_9(): message = RevealSecret( message_identifier=MessageID(10945162236180065780), secret=Secret( decode_hex( "0xb8ed582d16853c82a9a9a384118fcd10889ab0a5a3224ec6008bd88582319fc3" ))) message.sign(signer) data_was_signed = message._data_to_sign() print("Reveal Secret signature 9: " + message.signature.hex()) assert recover(data_was_signed, message.signature) == to_canonical_address( "0x7ca28d3d760b4aa2b79e8d42cbdc187c7df9af40")
def test_update_pfs(): properties = factories.BalanceProofSignedStateProperties(pkey=PRIVKEY) balance_proof = factories.create(properties) channel_state = factories.create(factories.NettingChannelStateProperties()) channel_state.our_state.balance_proof = balance_proof channel_state.partner_state.balance_proof = balance_proof message = PFSCapacityUpdate.from_channel_state(channel_state=channel_state) assert message.signature == EMPTY_SIGNATURE privkey2, address2 = factories.make_privkey_address() signer2 = LocalSigner(privkey2) message.sign(signer2) assert recover(message._data_to_sign(), message.signature) == address2 assert message == DictSerializer.deserialize(DictSerializer.serialize(message))
def test_update_pfs(): balance_proof = make_balance_proof(signer=signer, amount=1) channel_state = make_channel_state() channel_state.our_state.balance_proof = balance_proof channel_state.partner_state.balance_proof = balance_proof message = UpdatePFS.from_channel_state(channel_state=channel_state) assert message.signature == b'' privkey2, address2 = make_privkey_address() signer2 = LocalSigner(privkey2) message.sign(signer2) assert recover(message._data_to_sign(), message.signature) == address2 assert message == UpdatePFS.from_dict(message.to_dict())
def test_recover_address_from_display_user_and_signature(): rsk_address = "0x6d369723521B4080A19457D5Fdd2194d633B0c3A" rsk_address_normalized = to_normalized_address(rsk_address) matrix_server_domain = "transport02.raiden.network" original_message = f'@{rsk_address_normalized}:{matrix_server_domain}' # generated with Metamask's web3.personal.sign signature = decode_hex( "0xbf289bbf32bbd20d7532f5ec39f3ab3e3d02bb82497c7de80edae06beb05f" "c327c63463d360d501c81f9e9d002744f7c0c67443536473558199e56d584f9cc341c" ) assert recover( data=original_message.encode(), signature=signature) == to_canonical_address(rsk_address_normalized)
def test_update_pfs(): properties = factories.BalanceProofSignedStateProperties(pkey=PRIVKEY) balance_proof = factories.create(properties) channel_state = factories.create(factories.NettingChannelStateProperties()) channel_state.our_state.balance_proof = balance_proof channel_state.partner_state.balance_proof = balance_proof message = UpdatePFS.from_channel_state(channel_state=channel_state) assert message.signature == b"" privkey2, address2 = factories.make_privkey_address() signer2 = LocalSigner(privkey2) message.sign(signer2) assert recover(message._data_to_sign(), message.signature) == address2 assert message == UpdatePFS.from_dict(message.to_dict())
async def check_password(self, user_id: str, password: str) -> bool: if not password: self.log.error("no password provided, user=%r", user_id) return 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, ) return False signature = 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, ) return False user_addr_hex = user_match.group(1) user_addr = unhexlify(user_addr_hex[2:]) rec_addr = 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) return False localpart = user_id.split(":", 1)[0][1:] self.log.info("eth login! valid signature. user=%r", user_id) if not (await self.account_handler.check_user_exists(user_id)): self.log.info("First login, creating new user: user=%r", user_id) registered_user_id = await self.account_handler.register_user( localpart=localpart) await self.account_handler.register_device(registered_user_id, device_id="raiden") return True
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 = 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_login_or_register_default_user(): ownserver = 'https://ownserver.com' api = Mock() api.base_url = ownserver server_name = urlparse(ownserver).netloc client = Mock() client.api = api # login will assert user is hex-encoded address and pw is server_name signed with that address def mock_login(user, pw, sync=True): recovered = recover(data=server_name.encode(), signature=decode_hex(pw)) if recovered != to_canonical_address(user): raise MatrixRequestError(403) client.user_id = f'@{user}:{server_name}' client.login = Mock(side_effect=mock_login) MockUser = create_autospec(User) client.get_user = Mock(side_effect=lambda user_id: MockUser(api, user_id)) signer = make_signer() user = login_or_register( client=client, signer=signer, ) # client.user_id will be set by login assert client.user_id.startswith( f'@{to_normalized_address(signer.address)}') # login_or_register returns our own user object assert isinstance(user, User) # get_user must have been called once to generate above user client.get_user.assert_called_once_with(client.user_id) # assert set_display_name was called once on ourselves assert user.set_display_name.call_count == 1 # assert the user.set_display_name was called with the signature of the user_id assert recover( data=client.user_id.encode(), signature=decode_hex(user.set_display_name.call_args[0][0]), ) == signer.address
def test_balance_proof_11(): dict_data = { "type": "Secret", "chain_id": 33, "message_identifier": 4334089825906208294, "payment_identifier": 15193824610622741555, "secret": "0x8c45240e576c4befd51d063549ce18859c5a2b3c356035884588a65c3dfcef4b", "nonce": 2, "token_network_address": "0x7351ed719de72db92a54c99ef2c4d287f69672a1", "channel_identifier": 1, "transferred_amount": 1000000000000000, "locked_amount": 0, "locksroot": "0x0000000000000000000000000000000000000000000000000000000000000000" } message = Unlock(chain_id=dict_data["chain_id"], message_identifier=dict_data["message_identifier"], payment_identifier=dict_data["payment_identifier"], secret=decode_hex(dict_data["secret"]), nonce=dict_data["nonce"], token_network_address=decode_hex( dict_data["token_network_address"]), channel_identifier=dict_data["channel_identifier"], transferred_amount=dict_data["transferred_amount"], locked_amount=dict_data["locked_amount"], locksroot=decode_hex(dict_data["locksroot"])) message.sign(signer) data_was_signed = message._data_to_sign() print("Balance Proof signature: " + message.signature.hex()) assert recover(data_was_signed, message.signature) == to_canonical_address( "0x7ca28d3d760b4aa2b79e8d42cbdc187c7df9af40")