Exemplo n.º 1
0
    def test_transformations_combiner(self):
        """
        This test checks all combinations of transformations and combiners for SimulationMajorityLTFArray to run.
        """
        noise_prng = RandomState(seed=0xC0FFEE)
        weight_prng1 = RandomState(seed=0xBADA55)
        crp_count = 16  # number of random inputs per test set
        n = 64
        k = 2
        mu = 0
        sigma = 1
        vote_count = 1
        weight_array = LTFArray.normal_weights(n, k, mu, sigma, weight_prng1)

        inputs = tools.random_inputs(
            n, crp_count, random_instance=RandomState(seed=0xDEADDA7A))

        combiners = get_functions_with_prefix('combiner_',
                                              SimulationMajorityLTFArray)
        transformations = get_functions_with_prefix(
            'transform_', SimulationMajorityLTFArray)

        for transformation in transformations:
            for combiner in combiners:
                mv_noisy_ltf_array = SimulationMajorityLTFArray(
                    weight_array=weight_array,
                    transform=transformation,
                    combiner=combiner,
                    sigma_noise=1,
                    random_instance_noise=noise_prng,
                    vote_count=vote_count,
                )
                mv_noisy_ltf_array.eval(inputs)
Exemplo n.º 2
0
    def test_bias_influence(self):
        """
        This method tests the influence of the bias array. The results should be different.
        """
        n = 8
        k = 4
        mu = 1
        sigma = 0.5

        challenges = tools.all_inputs(n)

        weight_array = SimulationMajorityLTFArray.normal_weights(
            n, k, mu=mu, sigma=sigma, random_instance=RandomState(0xBADA556))
        bias_array = SimulationMajorityLTFArray.normal_weights(
            1,
            k,
            mu=mu,
            sigma=sigma * 2,
            random_instance=RandomState(0xBADAFF1))

        biased_ltf_array = SimulationMajorityLTFArray(
            weight_array=weight_array,
            transform=SimulationMajorityLTFArray.transform_id,
            combiner=SimulationMajorityLTFArray.combiner_xor,
            sigma_noise=sigma,
            random_instance_noise=RandomState(0xCCABAD),
            bias=bias_array,
        )
        ltf_array = SimulationMajorityLTFArray(
            weight_array=weight_array,
            transform=SimulationMajorityLTFArray.transform_id,
            combiner=SimulationMajorityLTFArray.combiner_xor,
            sigma_noise=sigma,
            random_instance_noise=RandomState(0xCCABAD),
            bias=None,
        )
        self.assertEqual(ltf_array.weight_array.shape,
                         biased_ltf_array.weight_array.shape)

        bias_array = biased_ltf_array.weight_array[:, -1]
        bias_array_compared = [
            bias == bias_array[0] for bias in bias_array[1:]
        ]
        # the bias values should be different for this test. It is possible that they are all equal but this chance is
        # low.
        self.assertFalse(array(bias_array_compared).all())

        biased_responses = biased_ltf_array.eval(challenges)
        responses = ltf_array.eval(challenges)

        # The arithmetic mean of the res
        self.assertFalse(array_equal(biased_responses, responses))
Exemplo n.º 3
0
 def create_mv_ltf_arrays(cls, n=8, k=1, instance_count=10, transformation=LTFArray.transform_id,
                          combiner=LTFArray.combiner_xor, bias=None, mu=0, sigma=1, weight_random_seed=0x123,
                          sigma_noise=0.5, noise_random_seed=0x321, vote_count=3):
     """
     This function can be used to create a list of SimulationMajorityLTFArray.
     :param n: int
               Number of stages of the PUF
     :param k: int
               Number different LTFArrays
     :param instance_count: int
                            Number of simulations to be instantiated.
     :param transformation: A function: array of int with shape(N,k,n), int number of PUFs k -> shape(N,k,n)
                            The function transforms input challenges in order to increase resistance against attacks.
     :param combiner: A function: array of int with shape(N,k,n) -> array of in with shape(N)
                      The functions combines the outputs of k PUFs to one bit results,
                      in oder to increase resistance against attacks.
     :param bias: None, float or a two dimensional array of float with shape (k, 1)
                  This bias value or array of bias values will be appended to the weight_array.
                  Use a single value if you want the same bias for all weight_vectors.
     :param mu: float
                Mean (“centre”) of the stage weight distribution of the PUF instance simulation.
     :param sigma: float
                   Standard deviation of the stage weight distribution of the PUF instance simulation.
     :param weight_random_seed: int
                                The seed which is used to initialize the pseudo-random number generator
                                which is used to generate the stage weights for the arbiter PUF simulation.
     :param sigma_noise: float
                         Standard deviation of the noise distribution.
     :param noise_random_seed: int
                               The seed which is used to initialize the pseudo-random number generator
                               which is used to generate the noise for the arbiter PUF simulation.
     :param vote_count: int
                        Number of evaluations which are used to choose a response with majority vote.
     :return: list of pypuf.simulation.arbiter_based.ltfarray.SimulationMajorityLTFArray
     """
     instances = []
     for seed_offset in range(instance_count):
         weight_array = LTFArray.normal_weights(n, k, mu, sigma,
                                                random_instance=RandomState(weight_random_seed + seed_offset))
         instances.append(
             SimulationMajorityLTFArray(
                 weight_array=weight_array,
                 transform=transformation,
                 combiner=combiner,
                 sigma_noise=sigma_noise,
                 random_instance_noise=RandomState(noise_random_seed + seed_offset),
                 bias=bias,
                 vote_count=vote_count,
             )
         )
     return instances
Exemplo n.º 4
0
    def test_majority_voting(self):
        """This method is used to test if majority vote works.
        The first test checks for unequal PUF responses with a LTFArray without noise and a SimulationMajorityLTFArray
        instance with noise. The second test checks if majority voting works and the instance with and without noise
        generate equal resonses.
        """
        weight_prng1 = RandomState(seed=0xBADA55)
        noise_prng = RandomState(seed=0xC0FFEE)
        crp_count = 16  # number of random inputs per test set
        n = 8
        k = 16
        mu = 0
        sigma = 1
        vote_count = 1

        weight_array = LTFArray.normal_weights(n, k, mu, sigma, weight_prng1)

        mv_noisy_ltf_array = SimulationMajorityLTFArray(
            weight_array=weight_array,
            transform=LTFArray.transform_id,
            combiner=LTFArray.combiner_xor,
            sigma_noise=1,
            random_instance_noise=noise_prng,
            vote_count=vote_count,
        )

        ltf_array = LTFArray(weight_array=weight_array,
                             transform=LTFArray.transform_id,
                             combiner=LTFArray.combiner_xor)

        inputs = tools.random_inputs(
            n, crp_count, random_instance=RandomState(seed=0xDEADDA7A))

        ltf_array_result = ltf_array.eval(inputs)
        mv_noisy_ltf_array_result = mv_noisy_ltf_array.eval(inputs)
        # These test checks if the output is different because of noise
        self.assertFalse(
            array_equal(ltf_array_result, mv_noisy_ltf_array_result),
            'These arrays must be different')

        # reset pseudo random number generator
        noise_prng = RandomState(seed=0xC0FFEE)
        # increase the vote_count in order to get equality
        vote_count = 2845
        mv_noisy_ltf_array = SimulationMajorityLTFArray(
            weight_array=weight_array,
            transform=LTFArray.transform_id,
            combiner=LTFArray.combiner_xor,
            sigma_noise=1,
            random_instance_noise=noise_prng,
            vote_count=vote_count,
        )
        # This checks if the majority vote works
        mv_noisy_ltf_array_result = mv_noisy_ltf_array.eval(inputs)
        assert_array_equal(mv_noisy_ltf_array_result, ltf_array_result)
Exemplo n.º 5
0
    def run(self):
        random = RandomState(seed=self.parameters.seed)
        sigma_noise = NoisyLTFArray.sigma_noise_from_random_weights(
            self.parameters.n, 1, self.parameters.sigma_noise_ratio)
        weights = LTFArray.normal_weights(self.parameters.n,
                                          self.parameters.k,
                                          random_instance=random)
        instance_mv = SimulationMajorityLTFArray(
            weights,
            LTFArray.transform_atf,
            LTFArray.combiner_xor,
            sigma_noise,
            random_instance_noise=random,
            vote_count=self.parameters.vote_count)

        self.stability = approx_stabilities(instance_mv, self.parameters.N,
                                            self.parameters.samples, random)
Exemplo n.º 6
0
    def test_majority_voting(self):
        weight_prng1 = RandomState(seed=0xBADA55)
        noise_prng = RandomState(seed=0xC0FFEE)
        crp_count = 16  # number of random inputs per test set
        n = 8
        k = 16
        mu = 0
        sigma = 1
        vote_count = 1

        weight_array = LTFArray.normal_weights(n, k, mu, sigma, weight_prng1)

        mv_noisy_ltf_array = SimulationMajorityLTFArray(
            weight_array=weight_array,
            transform=LTFArray.transform_id,
            combiner=LTFArray.combiner_xor,
            sigma_noise=1,
            random_instance_noise=noise_prng,
            vote_count=vote_count,
        )

        ltf_array = LTFArray(weight_array=weight_array,
                             transform=LTFArray.transform_id,
                             combiner=LTFArray.combiner_xor)

        inputs = array(
            list(
                tools.random_inputs(
                    n, crp_count,
                    random_instance=RandomState(seed=0xDEADDA7A))))

        ltf_array_result = ltf_array.eval(inputs)
        mv_noisy_ltf_array_result = mv_noisy_ltf_array.eval(inputs)
        # These test checks if the output is different because of noise
        self.assertFalse(
            array_equal(ltf_array_result, mv_noisy_ltf_array_result),
            'These arrays must be different')

        # reset pseudo random number generator
        noise_prng = RandomState(seed=0xC0FFEE)
        # increase the vote_count in order to get equality
        vote_count = 277
        mv_noisy_ltf_array = SimulationMajorityLTFArray(
            weight_array=weight_array,
            transform=LTFArray.transform_id,
            combiner=LTFArray.combiner_xor,
            sigma_noise=1,
            random_instance_noise=noise_prng,
            vote_count=vote_count,
        )
        # This checks if the majority vote works
        mv_noisy_ltf_array_result = mv_noisy_ltf_array.eval(inputs)
        assert_array_equal(mv_noisy_ltf_array_result, ltf_array_result)
Exemplo n.º 7
0
    def test_bias_influence_value(self):
        """
        This method tests the influence of the bias value. The results should be different.
        """
        n = 8
        k = 4
        mu = 1
        sigma = 0.5

        challenges = array(list(tools.all_inputs(n)))

        weight_array = SimulationMajorityLTFArray.normal_weights(n, k, mu=mu, sigma=sigma,
                                                                 random_instance=RandomState(0xBADA556))
        bias_value = 2.5

        biased_ltf_array = SimulationMajorityLTFArray(
            weight_array=weight_array,
            transform=SimulationMajorityLTFArray.transform_id,
            combiner=SimulationMajorityLTFArray.combiner_xor,
            sigma_noise=sigma,
            random_instance_noise=RandomState(0xCCABAD),
            bias=bias_value,
        )
        ltf_array = SimulationMajorityLTFArray(
            weight_array=weight_array,
            transform=SimulationMajorityLTFArray.transform_id,
            combiner=SimulationMajorityLTFArray.combiner_xor,
            sigma_noise=sigma,
            random_instance_noise=RandomState(0xCCABAD),
            bias=None,
        )
        # the second dimension of the weight_array plus one must be the number of elements in biased weight_array
        self.assertEqual(shape(ltf_array.weight_array)[1] + 1, shape(biased_ltf_array.weight_array)[1])

        bias_array = biased_ltf_array.weight_array[:, -1]
        bias_array_compared = [bias == bias_array[0] for bias in bias_array]
        # the bias values should be equal for this tests.
        self.assertTrue(array(bias_array_compared).all())

        biased_responses = biased_ltf_array.eval(challenges)
        responses = ltf_array.eval(challenges)

        # The arithmetic mean of the res
        self.assertFalse(array_equal(biased_responses, responses))
Exemplo n.º 8
0
def stability_figure_data(n, k, vote_count, sigma_noise_ratio, num, reps, random):
    """
    Returns a list of stabilities for randomly chosen challenges of randomly chosen MV XOR Arbiter PUF.
    :param n: Length of arbiter chains
    :param k: Number of arbiter chains
    :param vote_count: Number of votes for each chain
    :param sigma_noise_ratio: sigma_noise to sigma_model ratio of the arbiter chains
    :param num: number of challenges to compute stability for
    :param reps: number of samples per challenge to base the stability computation on
    :param random: random seed for all PRNG used here
    """
    sigma_noise = NoisyLTFArray.sigma_noise_from_random_weights(n, 1, sigma_noise_ratio)
    weights = LTFArray.normal_weights(n, k, random_instance=random)
    instance_mv = SimulationMajorityLTFArray(weights,
                                             LTFArray.transform_atf,
                                             LTFArray.combiner_xor,
                                             sigma_noise,
                                             random_instance_noise=random,
                                             vote_count=vote_count)

    stabilities = tools.approx_stabilities(instance_mv, num, reps, random)
    print('{' + ','.join(map(str, stabilities)) + '}')
Exemplo n.º 9
0
    def run(self):
        """
        Searches for the minimal number of votes which satisfy self.desired_stability and
        self.overall_desired_stability. The number of votes for a try is given by the interval between self.bottom and
        self.top.
        """
        # Random number generators
        instance_prng = RandomState(self.seed_instance)
        noise_prng = RandomState(self.seed_instance_noise)
        challenge_prng = RandomState(self.seed_challenges)

        # Weight array for the instance which should be learned
        weight_array = LTFArray.normal_weights(self.n,
                                               self.k,
                                               self.mu,
                                               self.sigma,
                                               random_instance=instance_prng)

        self.vote_count = 0
        # Search upper bound for binary search
        while self.overall_stab < self.overall_desired_stability:
            self.vote_count = self.vote_count * 2 + 1
            puf_instance = SimulationMajorityLTFArray(
                weight_array,
                LTFArray.transform_id,
                LTFArray.combiner_xor,
                self.sigma_noise,
                random_instance_noise=noise_prng,
                vote_count=self.vote_count)
            self.calculate_stabilities(puf_instance, challenge_prng)
        self.maximum_vote_count = self.vote_count

        # Binary search loop which is used to find the minimum number of votes in oder to satisfy
        # self.desired_stability and overall_desired_stability
        while self.minimum_vote_count < self.maximum_vote_count:
            # Set the number of vote counts
            self.vote_count = (self.minimum_vote_count +
                               self.maximum_vote_count) // 2
            # self.vote_count must be odd
            if self.vote_count % 2 == 0:
                self.vote_count = self.vote_count + 1

            puf_instance = SimulationMajorityLTFArray(
                weight_array,
                LTFArray.transform_id,
                LTFArray.combiner_xor,
                self.sigma_noise,
                random_instance_noise=noise_prng,
                vote_count=self.vote_count)
            self.calculate_stabilities(puf_instance, challenge_prng)

            #     overall_stab      vote_count
            msg = '%f\t' '%i\t' % (self.overall_stab, self.vote_count)

            # Interval adjustment
            if self.overall_stab >= self.overall_desired_stability:
                self.maximum_vote_count = self.vote_count - 1
                self.result_vote_count = self.vote_count
                self.result_overall_stab = self.overall_stab
            else:
                self.minimum_vote_count = self.vote_count + 1

            self.progress_logger.info(msg)