Exemplo n.º 1
0
    def test_validation_result(self, valid_count, invalid_passes):
        """
        ``validate_passes`` returns a ``_ValidationResult`` instance which
        describes the valid and invalid passes.
        """
        message = u"hello world"
        valid_passes = make_passes(
            self.signing_key,
            message,
            list(RandomToken.create() for i in range(valid_count)),
        )
        all_passes = valid_passes + list(
            pass_.pass_text.encode("ascii") for pass_ in invalid_passes)
        shuffle(all_passes)

        self.assertThat(
            _ValidationResult.validate_passes(
                message,
                all_passes,
                self.signing_key,
            ),
            Equals(
                _ValidationResult(
                    valid=list(idx for (idx, pass_) in enumerate(all_passes)
                               if pass_ in valid_passes),
                    signature_check_failed=list(
                        idx for (idx, pass_) in enumerate(all_passes)
                        if pass_ not in valid_passes),
                ), ),
        )
Exemplo n.º 2
0
def get_passes(message, count, signing_key):
    """
    :param unicode message: Request-binding message for PrivacyPass.

    :param int count: The number of passes to get.

    :param SigningKEy signing_key: The key to use to sign the passes.

    :return list[Pass]: ``count`` new random passes signed with the given key
        and bound to the given message.
    """
    return list(
        Pass(*pass_.split(u" ")) for pass_ in make_passes(
            signing_key,
            message,
            list(RandomToken.create() for n in range(count)),
        ))
Exemplo n.º 3
0
    def test_allocate_buckets_fails_without_enough_passes(self):
        """
        ``remote_allocate_buckets`` fails with ``MorePassesRequired`` if it is
        passed fewer passes than it requires for the amount of data to be
        stored.
        """
        # Hypothesis causes our storage server to be used many times.  Clean
        # up between iterations.
        cleanup_storage_server(self.anonymous_storage_server)

        required_passes = 2
        share_nums = {3, 7}
        allocated_size = int(
            (required_passes * self.pass_value) / len(share_nums))
        storage_index = b"0123456789"
        renew_secret = b"x" * 32
        cancel_secret = b"y" * 32
        valid_passes = make_passes(
            self.signing_key,
            allocate_buckets_message(storage_index),
            list(RandomToken.create() for i in range(required_passes - 1)),
        )

        allocate_buckets = lambda: self.storage_server.doRemoteCall(
            "allocate_buckets",
            (
                valid_passes,
                storage_index,
                renew_secret,
                cancel_secret,
                share_nums,
                allocated_size,
                LocalReferenceable(None),
            ),
            {},
        )
        self.assertThat(
            allocate_buckets,
            raises(MorePassesRequired),
        )
Exemplo n.º 4
0
    def test_mutable_share_sizes(self, slot, secrets, sharenums,
                                 test_and_write_vectors_for_shares):
        """
        ``share_sizes`` returns the size of the requested mutable shares in the
        requested slot.
        """
        # hypothesis causes our storage server to be used many times.  Clean
        # up between iterations.
        cleanup_storage_server(self.anonymous_storage_server)

        tw_vectors = {
            k: v.for_call()
            for (k, v) in test_and_write_vectors_for_shares.items()
        }

        # Create an initial share to toy with.
        required_pass_count = get_required_new_passes_for_mutable_write(
            self.pass_value,
            dict.fromkeys(tw_vectors.keys(), 0),
            tw_vectors,
        )
        valid_passes = make_passes(
            self.signing_key,
            slot_testv_and_readv_and_writev_message(slot),
            list(RandomToken.create() for i in range(required_pass_count)),
        )
        test, read = self.storage_server.doRemoteCall(
            "slot_testv_and_readv_and_writev",
            (),
            dict(
                passes=valid_passes,
                storage_index=slot,
                secrets=secrets,
                tw_vectors=tw_vectors,
                r_vector=[],
            ),
        )
        self.assertThat(
            test,
            Equals(True),
            "Server denied initial write.",
        )

        expected_sizes = {
            sharenum: get_implied_data_length(data_vector, new_length)
            for (sharenum, (testv, data_vector,
                            new_length)) in tw_vectors.items()
            if sharenums is None or sharenum in sharenums
        }

        actual_sizes = self.storage_server.doRemoteCall(
            "share_sizes",
            (
                slot,
                sharenums,
            ),
            {},
        )
        self.assertThat(
            actual_sizes,
            Equals(expected_sizes),
        )
Exemplo n.º 5
0
    def _test_lease_operation_fails_without_passes(
        self,
        storage_index,
        secrets,
        sharenums,
        allocated_size,
        lease_operation,
        lease_operation_message,
    ):
        """
        Assert that a lease-taking operation fails if it is not supplied with
        enough passes to cover the cost of the lease.

        :param lease_operation: A two-argument callable.  It is called with a
            storage server and a list of passes.  It should perform the
            lease-taking operation.

        :param lease_operation_message: A one-argument callable.  It is called
            with a storage index.  It should return the ZKAPAuthorizer binding
            message for the lease-taking operation.
        """
        # hypothesis causes our storage server to be used many times.  Clean
        # up between iterations.
        cleanup_storage_server(self.anonymous_storage_server)

        renew_secret, cancel_secret = secrets

        required_count = required_passes(self.pass_value,
                                         [allocated_size] * len(sharenums))
        # Create some shares at a slot which will require lease renewal.
        write_toy_shares(
            self.anonymous_storage_server,
            storage_index,
            renew_secret,
            cancel_secret,
            sharenums,
            allocated_size,
            LocalReferenceable(None),
        )

        # Advance time to a point where the lease is expired.  This simplifies
        # the logic behind how many passes will be required by the lease
        # operation (all of them).  If there is prorating for partially
        # expired leases then the calculation for a non-expired lease involves
        # more work.
        #
        # Add some slop here because time.time() is used by some parts of the
        # system. :/
        self.clock.advance(self.storage_server.LEASE_PERIOD.total_seconds() +
                           10.0)

        # Attempt the lease operation with one fewer pass than is required.
        passes = make_passes(
            self.signing_key,
            lease_operation_message(storage_index),
            list(RandomToken.create() for i in range(required_count - 1)),
        )
        try:
            result = lease_operation(self.storage_server, passes)
        except MorePassesRequired as e:
            self.assertThat(
                e,
                Equals(
                    MorePassesRequired(
                        valid_count=len(passes),
                        required_count=required_count,
                        signature_check_failed=[],
                    ), ),
            )
        else:
            self.fail("Expected MorePassesRequired, got {}".format(result))
Exemplo n.º 6
0
    def _test_extend_mutable_fails_without_passes(
        self,
        storage_index,
        secrets,
        test_and_write_vectors_for_shares,
        make_data_vector,
    ):
        """
        Verify that increasing the storage requirements of a slot without
        supplying more passes fails.

        :param make_data_vector: A one-argument callable.  It will be called
            with the current length of a slot share.  It should return a write
            vector which will increase the storage requirements of that slot
            share by at least ``self.pass_value``.
        """
        # hypothesis causes our storage server to be used many times.  Clean
        # up between iterations.
        cleanup_storage_server(self.anonymous_storage_server)

        tw_vectors = {
            k: v.for_call()
            for (k, v) in test_and_write_vectors_for_shares.items()
        }

        note("tw_vectors summarized: {}".format(summarize(tw_vectors)))

        # print("test suite")
        required_pass_count = get_required_new_passes_for_mutable_write(
            self.pass_value,
            dict.fromkeys(tw_vectors.keys(), 0),
            tw_vectors,
        )

        valid_passes = make_passes(
            self.signing_key,
            slot_testv_and_readv_and_writev_message(storage_index),
            list(RandomToken.create() for i in range(required_pass_count)),
        )

        # Create an initial share to toy with.
        test, read = self.storage_server.doRemoteCall(
            "slot_testv_and_readv_and_writev",
            (),
            dict(
                passes=valid_passes,
                storage_index=storage_index,
                secrets=secrets,
                tw_vectors=tw_vectors,
                r_vector=[],
            ),
        )
        self.assertThat(
            test,
            Equals(True),
            "Server denied initial write.",
        )

        # Pick any share to make larger.
        sharenum = next(iter(tw_vectors))
        _, data_vector, new_length = tw_vectors[sharenum]
        current_length = get_implied_data_length(data_vector, new_length)

        new_tw_vectors = {
            sharenum: make_data_vector(current_length),
        }

        note("new tw_vectors: {}".format(summarize(new_tw_vectors)))

        do_extend = lambda: self.storage_server.doRemoteCall(
            "slot_testv_and_readv_and_writev",
            (),
            dict(
                passes=[],
                storage_index=storage_index,
                secrets=secrets,
                tw_vectors=new_tw_vectors,
                r_vector=[],
            ),
        )

        try:
            result = do_extend()
        except MorePassesRequired as e:
            self.assertThat(
                e,
                Equals(
                    MorePassesRequired(
                        valid_count=0,
                        required_count=1,
                        signature_check_failed=[],
                    ), ),
            )
        else:
            self.fail("expected MorePassesRequired, got {}".format(result))