Esempio n. 1
0
def test_use_vladimir_without_development_installation(import_mocker, mocker):

    # Expected error message (Related object)
    from tests.utils.middleware import EvilMiddleWare
    import_path = f'{EvilMiddleWare.__module__}.{EvilMiddleWare.__name__}'
    message = DevelopmentInstallationRequired.MESSAGE.format(
        importable_name=import_path)
    del EvilMiddleWare

    with import_mocker:
        from nucypher.characters.unlawful import Vladimir  # Import OK
        with pytest.raises(DevelopmentInstallationRequired,
                           match=message):  # Expect lazy failure
            Vladimir.from_target_ursula(target_ursula=mocker.Mock())
Esempio n. 2
0
def test_treasure_map_cannot_be_duplicated(blockchain_ursulas,
                                           blockchain_alice, blockchain_bob,
                                           agency):
    # Setup the policy details
    n = 3
    policy_end_datetime = maya.now() + datetime.timedelta(days=5)
    label = b"this_is_the_path_to_which_access_is_being_granted"

    # Create the Policy, Granting access to Bob
    policy = blockchain_alice.grant(
        bob=blockchain_bob,
        label=label,
        m=2,
        n=n,
        rate=int(1e18),  # one ether
        expiration=policy_end_datetime)

    u = blockchain_bob.matching_nodes_among(blockchain_alice.known_nodes)[0]
    saved_map = u.treasure_maps[bytes.fromhex(policy.treasure_map.public_id())]
    assert saved_map == policy.treasure_map
    # This Ursula was actually a Vladimir.
    # Thus, he has access to the (encrypted) TreasureMap and can use its details to
    # try to store his own fake details.
    vladimir = Vladimir.from_target_ursula(u)
    node_on_which_to_store_bad_map = blockchain_ursulas[1]
    with pytest.raises(vladimir.network_middleware.UnexpectedResponse) as e:
        vladimir.publish_fraudulent_treasure_map(
            legit_treasure_map=saved_map,
            target_node=node_on_which_to_store_bad_map)
    assert e.value.status == 402
Esempio n. 3
0
def test_alice_refuses_to_make_arrangement_unless_ursula_is_valid(
        blockchain_alice, idle_blockchain_policy, blockchain_ursulas):
    target = list(blockchain_ursulas)[2]
    # First, let's imagine that Alice has sampled a Vladimir while making this policy.
    vladimir = Vladimir.from_target_ursula(target)

    message = vladimir._signable_interface_info_message()
    signature = vladimir._crypto_power.power_ups(SigningPower).sign(message)

    vladimir.substantiate_stamp()
    vladimir._Teacher__interface_signature = signature

    class FakeArrangement:
        federated = False
        ursula = vladimir

        def __bytes__(self):
            return b""

    vladimir.node_storage.store_node_certificate(
        certificate=target.certificate)

    with pytest.raises(vladimir.InvalidNode):
        idle_blockchain_policy.propose_arrangement(
            network_middleware=blockchain_alice.network_middleware,
            arrangement=FakeArrangement())
def test_vladimir_cannot_verify_interface_with_ursulas_signing_key(
        blockchain_ursulas):
    his_target = list(blockchain_ursulas)[4]

    # Vladimir has his own ether address; he hopes to publish it along with Ursula's details
    # so that Alice (or whomever) pays him instead of Ursula, even though Ursula is providing the service.

    # He finds a target and verifies that its interface is valid.
    assert his_target.validate_interface()

    # Now Vladimir imitates Ursula - copying her public keys and interface info, but inserting his ether address.
    vladimir = Vladimir.from_target_ursula(his_target, claim_signing_key=True)

    # Vladimir can substantiate the stamp using his own ether address...
    vladimir._Ursula__substantiate_stamp()
    vladimir.validate_worker = lambda: True
    vladimir.validate_worker()  # lol

    # Now, even though his public signing key matches Ursulas...
    assert vladimir.stamp == his_target.stamp

    # ...he is unable to pretend that his interface is valid
    # because the interface validity check contains the canonical public address as part of its message.
    with pytest.raises(vladimir.InvalidNode):
        vladimir.validate_interface()

    # Consequently, the metadata as a whole is also invalid.
    with pytest.raises(vladimir.InvalidNode):
        vladimir.validate_metadata()
def test_vladimir_uses_his_own_signing_key(blockchain_alice,
                                           blockchain_ursulas):
    """
    Similar to the attack above, but this time Vladimir makes his own interface signature
    using his own signing key, which he claims is Ursula's.
    """
    his_target = list(blockchain_ursulas)[4]
    vladimir = Vladimir.from_target_ursula(target_ursula=his_target)

    message = vladimir._signable_interface_info_message()
    signature = vladimir._crypto_power.power_ups(SigningPower).sign(
        vladimir.timestamp_bytes() + message)
    vladimir._Teacher__interface_signature = signature
    vladimir._Ursula__substantiate_stamp()

    vladimir._worker_is_bonded_to_staker = lambda: True
    vladimir._staker_is_really_staking = lambda: True
    vladimir.validate_worker()  # lol

    # With this slightly more sophisticated attack, his metadata does appear valid.
    vladimir.validate_metadata()

    # However, the actual handshake proves him wrong.
    with pytest.raises(vladimir.InvalidNode):
        vladimir.verify_node(blockchain_alice.network_middleware.client,
                             certificate_filepath="doesn't matter")
Esempio n. 6
0
def test_vladimir_uses_his_own_signing_key(blockchain_alice,
                                           blockchain_ursulas):
    """
    Similar to the attack above, but this time Vladimir makes his own interface signature
    using his own signing key, which he claims is Ursula's.
    """
    his_target = list(blockchain_ursulas)[4]

    fraduluent_keys = CryptoPower(
        power_ups=Ursula._default_crypto_powerups)  # TODO: Why is this unused?

    vladimir = Vladimir.from_target_ursula(target_ursula=his_target)

    message = vladimir._signable_interface_info_message()
    signature = vladimir._crypto_power.power_ups(SigningPower).sign(
        vladimir.timestamp_bytes() + message)
    vladimir._interface_signature_object = signature

    vladimir.substantiate_stamp(password=INSECURE_DEVELOPMENT_PASSWORD)

    # With this slightly more sophisticated attack, his metadata does appear valid.
    vladimir.validate_metadata()

    # However, the actual handshake proves him wrong.
    with pytest.raises(vladimir.InvalidNode):
        vladimir.verify_node(blockchain_alice.network_middleware,
                             certificate_filepath="doesn't matter")
def test_vladimir_illegal_interface_key_does_not_propagate(blockchain_ursulas):
    """
    Although Ursulas propagate each other's interface information, as demonstrated above,
    they do not propagate interface information for Vladimir.

    Specifically, if Vladimir tries to perform the most obvious imitation attack -
    propagating his own wallet address along with Ursula's information - the validity
    check will catch it and Ursula will refuse to propagate it and also record Vladimir's
    details.
    """
    ursulas = list(blockchain_ursulas)
    ursula_whom_vladimir_will_imitate, other_ursula = ursulas[0], ursulas[1]

    # Vladimir sees Ursula on the network and tries to use her public information.
    vladimir = Vladimir.from_target_ursula(ursula_whom_vladimir_will_imitate)

    # This Ursula is totally legit...
    ursula_whom_vladimir_will_imitate.verify_node(MockRestMiddleware())

    vladimir.network_middleware.propagate_shitty_interface_id(other_ursula, bytes(vladimir))

    # So far, Ursula hasn't noticed any Vladimirs.
    assert other_ursula.suspicious_activities_witnessed['vladimirs'] == []

    # ...but now, Ursula will now try to learn about Vladimir on a different thread.
    other_ursula.block_until_specific_nodes_are_known([vladimir.checksum_address])
    vladimir_as_learned = other_ursula.known_nodes[vladimir.checksum_address]

    # OK, so cool, let's see what happens when Ursula tries to learn with Vlad as the teacher.
    other_ursula._current_teacher_node = vladimir_as_learned
    result = other_ursula.learn_from_teacher_node()
def test_alice_refuses_to_make_arrangement_unless_ursula_is_valid(
        blockchain_alice, idle_blockchain_policy, blockchain_ursulas):

    target = list(blockchain_ursulas)[2]
    # First, let's imagine that Alice has sampled a Vladimir while making this policy.
    vladimir = Vladimir.from_target_ursula(target)

    message = vladimir._signable_interface_info_message()
    signature = vladimir._crypto_power.power_ups(SigningPower).sign(message)

    vladimir._Ursula__substantiate_stamp()
    vladimir._Teacher__interface_signature = signature
    vladimir.node_storage.store_node_certificate(
        certificate=target.certificate)

    # Ideally, a fishy node shouldn't be present in `known_nodes`,
    # but I guess we're testing the case when it became fishy somewhere between we learned about it
    # and the proposal arrangement.
    blockchain_alice.known_nodes.record_node(vladimir)
    blockchain_alice.known_nodes.record_fleet_state()

    with pytest.raises(vladimir.InvalidNode):
        idle_blockchain_policy._propose_arrangement(
            address=vladimir.checksum_address,
            network_middleware=blockchain_alice.network_middleware)
Esempio n. 9
0
def test_vladimir_invalidity_without_stake(testerchain, blockchain_ursulas, blockchain_alice):
    his_target = list(blockchain_ursulas)[4]
    vladimir = Vladimir.from_target_ursula(target_ursula=his_target)

    message = vladimir._signable_interface_info_message()
    signature = vladimir._crypto_power.power_ups(SigningPower).sign(vladimir.timestamp_bytes() + message)
    vladimir._Teacher__interface_signature = signature
    vladimir.substantiate_stamp()

    # However, the actual handshake proves him wrong.
    with pytest.raises(vladimir.InvalidNode):
        vladimir.verify_node(blockchain_alice.network_middleware.client, certificate_filepath="doesn't matter")
Esempio n. 10
0
def test_vladimir_illegal_interface_key_does_not_propagate(blockchain_ursulas):
    """
    Although Ursulas propagate each other's interface information, as demonstrated above,
    they do not propagate interface information for Vladimir.

    Specifically, if Vladimir tries to perform the most obvious imitation attack -
    propagating his own wallet address along with Ursula's information - the validity
    check will catch it and Ursula will refuse to propagate it and also record Vladimir's
    details.
    """

    warnings = []

    def warning_trapper(event):
        if event['log_level'] == LogLevel.warn:
            warnings.append(event)

    ursulas = list(blockchain_ursulas)
    ursula_whom_vladimir_will_imitate, other_ursula = ursulas[0], ursulas[1]

    # Vladimir sees Ursula on the network and tries to use her public information.
    vladimir = Vladimir.from_target_ursula(ursula_whom_vladimir_will_imitate)

    # This Ursula is totally legit...
    ursula_whom_vladimir_will_imitate.verify_node(MockRestMiddleware())

    globalLogPublisher.addObserver(warning_trapper)
    vladimir.network_middleware.propagate_shitty_interface_id(
        other_ursula, vladimir.metadata())
    globalLogPublisher.removeObserver(warning_trapper)

    # So far, Ursula hasn't noticed any Vladimirs.
    assert len(warnings) == 0

    # ...but now, Ursula will now try to learn about Vladimir on a different thread.
    other_ursula.block_until_specific_nodes_are_known(
        [vladimir.checksum_address])
    vladimir_as_learned = other_ursula.known_nodes[vladimir.checksum_address]

    # OK, so cool, let's see what happens when Ursula tries to learn with Vlad as the teacher.
    other_ursula._current_teacher_node = vladimir_as_learned

    globalLogPublisher.addObserver(warning_trapper)
    result = other_ursula.learn_from_teacher_node()
    globalLogPublisher.removeObserver(warning_trapper)

    # Indeed, Ursula noticed that something was up.
    assert len(warnings) == 1
    warning = warnings[0]['log_format']
    assert "Teacher " + str(vladimir_as_learned) + " is invalid" in warning
    assert "Metadata signature is invalid" in warning  # TODO: Cleanup logging templates
Esempio n. 11
0
def test_vladimir_illegal_interface_key_does_not_propagate(blockchain_ursulas):
    """
    Although Ursulas propagate each other's interface information, as demonstrated above,
    they do not propagate interface information for Vladimir.

    Specifically, if Vladimir tries to perform the most obvious imitation attack -
    propagating his own wallet address along with Ursula's information - the validity
    check will catch it and Ursula will refuse to propagate it and also record Vladimir's
    details.
    """
    ursulas = list(blockchain_ursulas)
    ursula_whom_vladimir_will_imitate, other_ursula = ursulas[0], ursulas[1]

    # Vladimir sees Ursula on the network and tries to use her public information.
    vladimir = Vladimir.from_target_ursula(ursula_whom_vladimir_will_imitate)

    # This Ursula is totally legit...
    ursula_whom_vladimir_will_imitate.verify_node(MockRestMiddleware(),
                                                  accept_federated_only=True)

    learning_callers = []
    crosstown_traffic.decorator = crosstownTaskListDecoratorFactory(
        learning_callers)

    vladimir.network_middleware.propagate_shitty_interface_id(
        other_ursula, bytes(vladimir))

    # So far, Ursula hasn't noticed any Vladimirs.
    assert other_ursula.suspicious_activities_witnessed['vladimirs'] == []

    # ...but now, Ursula will now try to learn about Vladimir on a different thread.
    # We only passed one node (Vladimir)...
    learn_about_vladimir = learning_callers.pop()
    #  ...so there was only one learning caller in the queue (now none since we popped it just now).
    assert len(learning_callers) == 0

    # OK, so cool, let's see what happens when Ursula tries to learn about Vlad.
    learn_about_vladimir()

    # And indeed, Ursula noticed the situation.
    # She didn't record Vladimir's address.
    assert vladimir not in other_ursula.known_nodes

    # But she *did* record the actual Ursula's address.
    assert ursula_whom_vladimir_will_imitate in other_ursula.known_nodes

    # Furthermore, she properly marked Vladimir as suspicious.
    assert vladimir in other_ursula.suspicious_activities_witnessed[
        'vladimirs']
Esempio n. 12
0
def test_treasure_map_cannot_be_duplicated(blockchain_ursulas,
                                           blockchain_alice, blockchain_bob,
                                           agency):
    # Setup the policy details
    n = 3
    policy_end_datetime = maya.now() + datetime.timedelta(days=5)
    label = b"this_is_the_path_to_which_access_is_being_granted"

    # Create the Policy, Granting access to Bob
    policy = blockchain_alice.grant(
        bob=blockchain_bob,
        label=label,
        m=2,
        n=n,
        rate=int(1e18),  # one ether
        expiration=policy_end_datetime)

    matching_ursulas = blockchain_bob.matching_nodes_among(blockchain_ursulas)
    completed_ursulas = policy.treasure_map_publisher.block_until_success_is_reasonably_likely(
    )
    # Ursulas in `treasure_map_publisher` are not real Ursulas, but just some metadata of remote ones.
    # We need a real one to access its datastore.
    first_completed_ursula = [
        ursula for ursula in matching_ursulas if ursula in completed_ursulas
    ][0]

    with first_completed_ursula.datastore.describe(
            TreasureMap, policy.treasure_map._hrac.hex()) as saved_map_record:
        assert saved_map_record.treasure_map == bytes(policy.treasure_map)

    # This Ursula was actually a Vladimir.
    # Thus, he has access to the (encrypted) TreasureMap and can use its details to
    # try to store his own fake details.
    vladimir = Vladimir.from_target_ursula(first_completed_ursula)

    ursulas_who_probably_do_not_have_the_map = [
        u for u in blockchain_ursulas if not u in matching_ursulas
    ]
    node_on_which_to_store_bad_map = ursulas_who_probably_do_not_have_the_map[
        0]
    with pytest.raises(vladimir.network_middleware.UnexpectedResponse) as e:
        vladimir.publish_fraudulent_treasure_map(
            legit_treasure_map=policy.treasure_map,
            target_node=node_on_which_to_store_bad_map)
    assert e.value.status == 402
Esempio n. 13
0
def test_alice_refuses_to_make_arrangement_unless_ursula_is_valid(blockchain_alice,
                                                                  idle_blockchain_policy,
                                                                  blockchain_ursulas):
    target = list(blockchain_ursulas)[2]
    # First, let's imagine that Alice has sampled a Vladimir while making this policy.
    vladimir = Vladimir.from_target_ursula(target)

    message = vladimir._signable_interface_info_message()
    signature = vladimir._crypto_power.power_ups(SigningPower).sign(message)

    vladimir.substantiate_stamp()
    vladimir._interface_signature_object = signature

    class FakeArrangement:
        federated = False

    with pytest.raises(vladimir.InvalidNode):
        idle_blockchain_policy.consider_arrangement(network_middleware=blockchain_alice.network_middleware,
                                                    arrangement=FakeArrangement(),
                                                    ursula=vladimir)
def test_vladimir_uses_his_own_signing_key(blockchain_alice, blockchain_ursulas):
    """
    Similar to the attack above, but this time Vladimir makes his own interface signature
    using his own signing key, which he claims is Ursula's.
    """
    his_target = list(blockchain_ursulas)[4]
    vladimir = Vladimir.from_target_ursula(target_ursula=his_target)

    message = vladimir._signable_interface_info_message()
    signature = vladimir._crypto_power.power_ups(SigningPower).sign(vladimir.timestamp_bytes() + message)
    vladimir._Teacher__interface_signature = signature
    vladimir.substantiate_stamp(client_password=INSECURE_DEVELOPMENT_PASSWORD)

    # With this slightly more sophisticated attack, his metadata does appear valid.
    vladimir._is_valid_worker = lambda: True  # bypass staking verification TODO: Split into two tests
    vladimir.validate_metadata()

    # However, the actual handshake proves him wrong.
    with pytest.raises(vladimir.InvalidNode):
        vladimir.verify_node(blockchain_alice.network_middleware, certificate_filepath="doesn't matter")
Esempio n. 15
0
def test_alice_refuses_to_select_node_unless_ursula_is_valid(blockchain_alice,
                                                             idle_blockchain_policy,
                                                             blockchain_ursulas):

    target = list(blockchain_ursulas)[2]
    # First, let's imagine that Alice has sampled a Vladimir while making this policy.
    vladimir = Vladimir.from_target_ursula(target,
                                           substitute_verifying_key=True,
                                           sign_metadata=True)

    vladimir.node_storage.store_node_certificate(certificate=target.certificate, port=vladimir.rest_interface.port)

    # Ideally, a fishy node will be present in `known_nodes`,
    # This tests the case when it became fishy after discovering it
    # but before being selected for a policy.
    blockchain_alice.known_nodes.record_node(vladimir)
    blockchain_alice.known_nodes.record_fleet_state()

    with pytest.raises(vladimir.InvalidNode):
        idle_blockchain_policy._ping_node(address=vladimir.checksum_address,
                                          network_middleware=blockchain_alice.network_middleware)
Esempio n. 16
0
def remote_vladimir(**kwds):
    vladimir = Vladimir.from_target_ursula(**kwds)
    remote_vladimir = Ursula.from_metadata_bytes(bytes(
        vladimir.metadata())).mature()
    return remote_vladimir