def test_combine_ip_mod2(self): """This function tests the inner product mod 2 combiner function with two pairs of input and output.""" assert_array_equal( LTFArray.combiner_ip_mod2( array([ [1, 1, -3, 1], [-1, -1, -1, 1], [-2, -2, 2, 1] ]) ), [ 1, -1, -4 ] ) assert_array_equal( LTFArray.combiner_ip_mod2( array([ [1, 1, 1, 1, 1, 1], [-1, -1, -1, 1, -1, -1], [-2, -2, 2, 1, 10, 10] ]) ), [ 1, 1, -40 ] )
def test_learn_ip_mod2(self): """" Stupid test which gains code coverage """ instance_prng = RandomState(seed=TestLogisticRegression.seed_instance) model_prng = RandomState(seed=TestLogisticRegression.seed_model) instance = LTFArray( weight_array=LTFArray.normal_weights( TestLogisticRegression.n, TestLogisticRegression.k, random_instance=instance_prng), transform=LTFArray.transform_id, combiner=LTFArray.combiner_ip_mod2, ) lr_learner = LogisticRegression( TrainingSet(instance=instance, N=TestLogisticRegression.N), TestLogisticRegression.n, TestLogisticRegression.k, transformation=LTFArray.transform_id, combiner=LTFArray.combiner_xor, weights_prng=model_prng, ) lr_learner.learn()
class Benchmark(Experiment): """ Measures the time LTFArray.eval takes to evaluate a set of inputs. """ def __init__(self, progress_log_prefix, parameters): super().__init__(progress_log_prefix, parameters) self.set = None self.ltf_array = None def prepare(self): self.set = sample_inputs(self.parameters.n, self.parameters.N, RandomState(seed=self.parameters.seed_input)) self.ltf_array = LTFArray( weight_array=LTFArray.normal_weights(self.parameters.n, self.parameters.k), transform=self.parameters.transform, combiner=self.parameters.combiner, ) def run(self): self.ltf_array.eval(self.set) def analyze(self): return Result( experiment_id=self.id, pid=getpid(), measured_time=self.measured_time, )
def prepare(self): """ Initializes the instance, the training set and the learner to then run the logistic regression with the given parameters. """ self.instance = LTFArray( weight_array=LTFArray.normal_weights( self.parameters.n, self.parameters.k, random_instance=RandomState( seed=self.parameters.seed_instance)), transform=self.parameters.transformation, combiner=self.parameters.combiner, ) self.learner = LogisticRegression( tools.TrainingSet(instance=self.instance, N=self.parameters.N, random_instance=RandomState( self.parameters.seed_challenge)), self.parameters.n, self.parameters.k, transformation=self.instance.transform, combiner=self.instance.combiner, weights_prng=RandomState(seed=self.parameters.seed_model), logger=self.progress_logger, minibatch_size=self.parameters.mini_batch_size, convergance_decimals=self.parameters.convergence_decimals or 2, shuffle=self.parameters.shuffle, )
def test_training_set_challenges(self): """The TrainingSet should generate the same challenges for equal seeds.""" n = 8 k = 1 transformation = LTFArray.transform_id combiner = LTFArray.combiner_xor N = 1000 instance_prng = RandomState(0x4EFEA) weight_array = LTFArray.normal_weights(n, k, random_instance=instance_prng) instance = LTFArray( weight_array=weight_array, transform=transformation, combiner=combiner, ) challenge_seed = 0xAB17D training_set_1 = TrainingSet( instance=instance, N=N, random_instance=RandomState(challenge_seed)) training_set_2 = TrainingSet( instance=instance, N=N, random_instance=RandomState(challenge_seed)) self.assertTrue( array_equal(training_set_1.challenges, training_set_2.challenges), 'The challenges are not equal.', )
def main(): """ Run an example how to use pypuf. Developers Notice: Changes here need to be mirrored to README! """ # create a simulation with random (Gaussian) weights # for 64-bit 4-XOR instance = LTFArray( weight_array=LTFArray.normal_weights(n=64, k=2), transform=LTFArray.transform_atf, combiner=LTFArray.combiner_xor, ) # create the learner lr_learner = LogisticRegression( t_set=tools.TrainingSet(instance=instance, N=12000), n=64, k=2, transformation=LTFArray.transform_atf, combiner=LTFArray.combiner_xor, ) # learn and test the model model = lr_learner.learn() accuracy = 1 - tools.approx_dist(instance, model, 10000) # output the result print('Learned a 64bit 2-xor XOR Arbiter PUF from 12000 CRPs with accuracy %f' % accuracy)
def test_reliability(self): """This method tests the test_reliability calculation.""" n = 8 k = 8 N = 2**n transformation = LTFArray.transform_id combiner = LTFArray.combiner_xor instance = LTFArray( weight_array=LTFArray.normal_weights( n=n, k=k, random_instance=RandomState(0xA1A1)), transform=transformation, combiner=combiner, ) challenges = sample_inputs(n, N, random_instance=RandomState(0xFAB1A)) reliabilities = [] for challenge in challenges: reliabilities.append( PropertyTest.reliability(instance, reshape(challenge, (1, n)))) # For noiseless simulations the responses are always the same hence the reliability is 0% assert_array_equal(reliabilities, repeat(0.0, N)) noisy_instance = NoisyLTFArray( weight_array=NoisyLTFArray.normal_weights( n=n, k=k, random_instance=RandomState(0xA1A1)), transform=transformation, combiner=combiner, sigma_noise=15.0, random_instance=RandomState(0x5015E), ) for challenge in challenges: reliability = PropertyTest.reliability(noisy_instance, reshape(challenge, (1, n))) # For noisy simulations the responses should vary self.assertNotEqual(reliability, 0.0)
def run(self): self.instance = LTFArray(weight_array=LTFArray.normal_weights( self.n, self.k, random_instance=self.instance_prng), transform=self.transformation, combiner=self.combiner, bias=0.0) validation_size = int((self.N / 1.1) // 10) self.training_set = TrainingSet(instance=self.instance, N=self.N - validation_size, random_instance=self.challenge_prng) self.validation_set = TrainingSet(instance=self.instance, N=validation_size, random_instance=self.distance_prng) self.learner = CorrelationAttack( n=self.n, k=self.k, training_set=self.training_set, validation_set=self.validation_set, weights_prng=self.model_prng, lr_iteration_limit=self.lr_iteration_limit, mini_batch_size=self.mini_batch_size, convergence_decimals=self.convergence_decimals, shuffle=self.shuffle, logger=self.progress_logger, ) self.model = self.learner.learn()
def test_1_n_bent(self): test_array = array([ [1, -1, -1, 1, -1, 1], [-1, 1, 1, -1, -1, 1], ]) assert_array_equal(LTFArray.transform_1_n_bent(test_array, k=3), [ [ [1, -1, 1, -1, 1, -1], [1, -1, -1, 1, -1, 1], [1, -1, -1, 1, -1, 1], ], [ [1, -1, 1, -1, 1, -1], [-1, 1, 1, -1, -1, 1], [-1, 1, 1, -1, -1, 1], ], ]) test_array = array([ [1, -1, -1, 1, -1, 1], [-1, 1, 1, -1, -1, 1], ]) assert_array_equal(LTFArray.transform_1_n_bent(test_array, k=1), [ [ [1, -1, 1, -1, 1, -1], ], [ [1, -1, 1, -1, 1, -1], ], ])
def test_uniqueness_set(self): """This method tests the uniqueness set generation function.""" n = 8 k = 1 N = 2**n instance_count = 25 measurements = 2 transformation = LTFArray.transform_id combiner = LTFArray.combiner_xor instances = [ LTFArray(weight_array=LTFArray.normal_weights( n=n, k=k, random_instance=RandomState(0xA1A1 + i)), transform=transformation, combiner=combiner) for i in range(instance_count) ] challenges = sample_inputs(n, N, random_instance=RandomState(0xFAB10)) uniqueness_set = PropertyTest.uniqueness_set(instances, challenges, measurements=measurements) # Check uniqueness_set to have the expected number of elements self.assertEqual(len(uniqueness_set), N * measurements) # For normal distributed weights is the expected uniqueness near 0.5 self.assertEqual(round(mean(uniqueness_set), 1), 0.5)
def pipeline(N): instance = LTFArray( weight_array=LTFArray.normal_weights(n=64, k=2), transform=LTFArray.transform_atf, combiner=LTFArray.combiner_xor ) train_set = tools.TrainingSet(instance=instance, N=N) train_size = int(len(train_set.challenges) * 0.95) val_set = train_set.subset(slice(train_size, None)) train_set = train_set.subset(slice(None, train_size)) lr_learner = LogisticRegression( t_set=train_set, n=64, k=2, transformation=LTFArray.transform_atf, combiner=LTFArray.combiner_xor, ) model = lr_learner.learn() val_set_predicted_responses = model.eval(val_set.challenges) accuracy = accuracy_score(val_set_predicted_responses, val_set.responses) return accuracy
def prepare(self): self.set = sample_inputs(self.parameters.n, self.parameters.N, RandomState(seed=self.parameters.seed_input)) self.ltf_array = LTFArray( weight_array=LTFArray.normal_weights(self.parameters.n, self.parameters.k), transform=self.parameters.transform, combiner=self.parameters.combiner, )
def learn(self): """ Compute a model according to the given LTF Array parameters and training set. Note that this function can take long to return. :return: pypuf.simulation.arbiter_based.LTFArray The computed model. """ # log format def log_state(): """ This method is used to log a snapshot of learning variables while running. """ if self.logger is None: return self.logger.debug( '%i\t%f\t%f\t%s' % (self.iteration_count, distance, norm(updater.step), ','.join( map(str, model.weight_array.flatten())))) # let numpy raise exceptions seterr(all='raise') # we start with a random model model = LTFArray( weight_array=LTFArray.normal_weights(self.n, self.k, self.weights_mu, self.weights_sigma, self.weights_prng), transform=self.transformation, combiner=self.combiner, ) updater = self.RPropModelUpdate(model) converged = False distance = 1 self.iteration_count = 0 log_state() while not converged and self.iteration_count < self.iteration_limit: self.iteration_count += 1 # compute gradient & update model gradient = self.gradient(model) model.weight_array += updater.update(gradient) # check convergence converged = norm(updater.step) < 10**-self.convergence_decimals # log log_state() if not converged: self.converged = False else: self.converged = True return model
def test_combine_ip_mod2(self): assert_array_equal( LTFArray.combiner_ip_mod2( array([[1, 1, -3, 1], [-1, -1, -1, 1], [-2, -2, 2, 1]])), [1, -1, -4]) assert_array_equal( LTFArray.combiner_ip_mod2( array([[1, 1, 1, 1, 1, 1], [-1, -1, -1, 1, -1, -1], [-2, -2, 2, 1, 10, 10]])), [1, 1, -40])
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)
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)
def test_shift(self): """This method tests the shift transformation with predefined input and output.""" test_array = array([ [-1, 1, 1, -1, -1], [-1, -1, -1, -1, -1], [1, 1, -1, -1, -1], [1, 1, -1, -1, -1], [1, 2, 3, 4, 5], ], dtype=tools.BIT_TYPE) assert_array_equal(LTFArray.transform_shift(test_array, k=3), [[ [-1, 1, 1, -1, -1], [1, 1, -1, -1, -1], [1, -1, -1, -1, 1], ], [ [-1, -1, -1, -1, -1], [-1, -1, -1, -1, -1], [-1, -1, -1, -1, -1], ], [ [1, 1, -1, -1, -1], [1, -1, -1, -1, 1], [-1, -1, -1, 1, 1], ], [ [1, 1, -1, -1, -1], [1, -1, -1, -1, 1], [-1, -1, -1, 1, 1], ], [ [1, 2, 3, 4, 5], [2, 3, 4, 5, 1], [3, 4, 5, 1, 2], ]])
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)
def test_id(self): """ This method test the identity function for the predefined inputs (challenges). If every challenge is duplicated k times the function works correct. """ test_challenges = array([[ [-1, 1, 1, -1, -1], [-1, -1, -1, -1, -1], [1, 1, -1, -1, -1], ], [ [1, 1, 1, -1, -1], [-1, -1, -1, -1, -1], [-1, 1, -1, -1, -1], ], [ [-1, 1, 1, -1, -1], [-1, -1, -1, -1, -1], [-1, 1, -1, -1, -1], ]], dtype=tools.BIT_TYPE) for challenges in test_challenges: assert_array_equal( LTFArray.transform_id(challenges, k=4), [[challenges[0], challenges[0], challenges[0], challenges[0]], [challenges[1], challenges[1], challenges[1], challenges[1]], [challenges[2], challenges[2], challenges[2], challenges[2]]])
def test_generate_stacked_transform(self): """ This method tests the stacked transformation generation of identity and shift with predefined input and output. """ test_array = array([ [1, -1, 1, -1], [-1, -1, 1, -1], ], dtype=tools.BIT_TYPE) assert_array_equal( LTFArray.generate_stacked_transform( transform_1=LTFArray.transform_id, puf_count=2, transform_2=LTFArray.transform_shift)(test_array, k=4), [ [ [1, -1, 1, -1], [1, -1, 1, -1], [1, -1, 1, -1], [-1, 1, -1, 1], ], [ [-1, -1, 1, -1], [-1, -1, 1, -1], [-1, -1, 1, -1], [-1, 1, -1, -1], ], ])
def train(challenges, responses, t_pairs): try: with open('weights.txt', 'rb') as f: weights = np.load(f) except: print("[*] ENOWEIGHTS") # create instance frome same weights for accuracy calculation instance = LTFArray( weight_array=weights, transform=LTFArray.transform_atf, combiner=LTFArray.combiner_xor, ) # train model from obtained CRPs training_set = tools.ChallengeResponseSet(challenges, responses) lr_learner = LogisticRegression( t_set=training_set, n=48, k=4, transformation=LTFArray.transform_atf, combiner=LTFArray.combiner_xor, ) # learn and test the model model = lr_learner.learn() accuracy = 1 - tools.approx_dist(instance, model, 10000) print('Learned a 48-bit 4-xor XOR Arbiter PUF from {} CRPs with accuracy {}'.format(t_pairs, accuracy)) return model
def test_parse_file(self): """This method checks reading challenge-response pairs from a file.""" n, k, N = 128, 1, 10 instance = LTFArray(LTFArray.normal_weights(n, k), LTFArray.transform_atf, LTFArray.combiner_xor) original = TrainingSet(instance, N) f = NamedTemporaryFile('w') for vals in column_stack((original.challenges, original.responses)): f.write(' '.join(map(str, vals)) + '\n') f.flush() loaded = parse_file(f.name, n, in_11_notation=True) assert_array_equal(original.challenges, loaded.challenges) assert_array_equal(original.responses, loaded.responses) f.close()
def test_polynomial(self): """This method tests the polynomial transformation with predefined input and output for k=4 PUFs.""" test_array = array([ [-1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1] ]) assert_array_equal( LTFArray.transform_polynomial(test_array, k=4), [ [ [-1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1], [-1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1], [-1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1], [1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1] ] ] )
def test_shift(self): test_array = array([ [-1, 1, 1, -1, -1], [-1, -1, -1, -1, -1], [1, 1, -1, -1, -1], [1, 1, -1, -1, -1], [1, 2, 3, 4, 5], ]) assert_array_equal(LTFArray.transform_shift(test_array, k=3), [[ [-1, 1, 1, -1, -1], [1, 1, -1, -1, -1], [1, -1, -1, -1, 1], ], [ [-1, -1, -1, -1, -1], [-1, -1, -1, -1, -1], [-1, -1, -1, -1, -1], ], [ [1, 1, -1, -1, -1], [1, -1, -1, -1, 1], [-1, -1, -1, 1, 1], ], [ [1, 1, -1, -1, -1], [1, -1, -1, -1, 1], [-1, -1, -1, 1, 1], ], [ [1, 2, 3, 4, 5], [2, 3, 4, 5, 1], [3, 4, 5, 1, 2], ]])
def test_atf(self): test_array = array([ [-1, 1, 1, -1, -1], [-1, -1, -1, -1, -1], [1, 1, -1, -1, -1], [1, 1, 1, -1, -1], [-1, -1, -1, -1, -1], [-1, 1, -1, -1, -1], ]) assert_array_equal(LTFArray.transform_atf(test_array, k=3), [[ [-1, 1, 1, 1, -1], [-1, 1, 1, 1, -1], [-1, 1, 1, 1, -1], ], [ [-1, 1, -1, 1, -1], [-1, 1, -1, 1, -1], [-1, 1, -1, 1, -1], ], [ [-1, -1, -1, 1, -1], [-1, -1, -1, 1, -1], [-1, -1, -1, 1, -1], ], [ [1, 1, 1, 1, -1], [1, 1, 1, 1, -1], [1, 1, 1, 1, -1], ], [ [-1, 1, -1, 1, -1], [-1, 1, -1, 1, -1], [-1, 1, -1, 1, -1], ], [ [1, -1, -1, 1, -1], [1, -1, -1, 1, -1], [1, -1, -1, 1, -1], ]])
def test_reliability_statistic(self): """This method tests the reliability statistic of an instance set.""" n = 8 k = 1 N = 2**n instance_count = 2 measurements = 100 transformation = LTFArray.transform_id combiner = LTFArray.combiner_xor instances = [ LTFArray(weight_array=LTFArray.normal_weights( n=n, k=k, random_instance=RandomState(0xA1A1 + i)), transform=transformation, combiner=combiner) for i in range(instance_count) ] challenges = sample_inputs(n, N, random_instance=RandomState(0xFAB10)) property_test = PropertyTest(instances) reliability_statistic = property_test.reliability_statistic( challenges, measurements=measurements) # For an noiseless set of simulations the reliability must be 0% for key, value in reliability_statistic.items(): if key == 'sv': self.assertEqual(value, 0.0, '{}'.format(key)) elif key == 'samples': self.assertEqual(len(value), instance_count * N, '{}'.format(key)) else: self.assertEqual(value, 0.0, '{}'.format(key)) noisy_instances = [ NoisyLTFArray( weight_array=LTFArray.normal_weights( n=n, k=k, random_instance=RandomState(0xA1A1 + i)), transform=transformation, combiner=combiner, sigma_noise=0.5, random_instance=RandomState(0xCABE), ) for i in range(instance_count) ] noisy_property_test = PropertyTest(noisy_instances) noisy_reliability_statistic = noisy_property_test.reliability_statistic( challenges, measurements=measurements) self.assertNotEqual(noisy_reliability_statistic['mean'], 0.0)
def test_generate_random_permutations(self): """This method tests the random permutation transformation generation ith predefined inputs and outputs.""" test_array = array([ [1, 2, 3, 4], [5, 6, 2, 1], ], dtype=tools.BIT_TYPE) assert_array_equal( LTFArray.generate_random_permutation_transform( seed=0xbeef, nn=4, kk=3, )(test_array, k=3), [ [ [4, 1, 2, 3], [1, 4, 3, 2], [3, 1, 4, 2], ], [ [1, 5, 6, 2], [5, 1, 2, 6], [2, 5, 1, 6], ], ], ) assert_array_equal( LTFArray.generate_random_permutation_transform( seed=0xbeef, nn=4, kk=3, atf=True, )(test_array, k=3), [ [ [4 * 1 * 2 * 3, 1 * 2 * 3, 2 * 3, 3], [1 * 4 * 3 * 2, 4 * 3 * 2, 3 * 2, 2], [3 * 1 * 4 * 2, 1 * 4 * 2, 4 * 2, 2], ], [ [1 * 5 * 6 * 2, 5 * 6 * 2, 6 * 2, 2], [5 * 1 * 2 * 6, 1 * 2 * 6, 2 * 6, 6], [2 * 5 * 1 * 6, 5 * 1 * 6, 1 * 6, 6], ], ], )
def test_random_weights(self): for test_parameters in self.test_set: n = test_parameters[0] k = test_parameters[1] mu = test_parameters[2] sigma = test_parameters[3] self.assertTupleEqual( shape(LTFArray.normal_weights(n, k, mu, sigma)), (k, n))
def test_generate_random_permutations(self): """This method tests the random permutation transformation generation ith predefined inputs and outputs.""" test_array = array([ [1, 2, 3, 4], [10, 20, 30, 40], ]) assert_array_equal( LTFArray.generate_random_permutation_transform( seed=0xbeef, challenge_length=4, puf_count=3, )(test_array, k=3), [ [ [4, 1, 2, 3], [1, 4, 3, 2], [3, 1, 4, 2], ], [ [40, 10, 20, 30], [10, 40, 30, 20], [30, 10, 40, 20], ], ], ) assert_array_equal( LTFArray.generate_random_permutation_transform( seed=0xbeef, challenge_length=4, puf_count=3, atf=True, )(test_array, k=3), [ [ [4 * 1 * 2 * 3, 1 * 2 * 3, 2 * 3, 3], [1 * 4 * 3 * 2, 4 * 3 * 2, 3 * 2, 2], [3 * 1 * 4 * 2, 1 * 4 * 2, 4 * 2, 2], ], [ [40 * 10 * 20 * 30, 10 * 20 * 30, 20 * 30, 30], [10 * 40 * 30 * 20, 40 * 30 * 20, 30 * 20, 20], [30 * 10 * 40 * 20, 10 * 40 * 20, 40 * 20, 20], ], ], )
def test_ltf_eval(self): """ Test ltf_eval for correct evaluation of LTFs. """ N = 100 # number of random inputs per test set def ltf_eval_slow(challenge, weights): """ evaluate a single challenge with a single ltf specified by weights """ assert len(challenge) == len(weights) - 1 return dot(challenge, weights[:n]) + weights[n] # weights[n] is the bias for test_parameters in self.test_set: n = test_parameters[0] k = test_parameters[1] mu = test_parameters[2] sigma = test_parameters[3] inputs = tools.random_inputs(n, N, random_instance=RandomState(0xA1)) ltf_array = LTFArray( weight_array=LTFArray.normal_weights(n, k, mu, sigma), transform=LTFArray.transform_id, combiner=LTFArray.combiner_xor, ) fast_evaluation_result = around(ltf_array.ltf_eval( LTFArray.transform_id(inputs, k)), decimals=8) slow_evaluation_result = [] for challenge in inputs: slow_evaluation_result.append([ ltf_eval_slow(challenge, ltf_array.weight_array[l]) for l in range(k) ]) slow_evaluation_result = around(slow_evaluation_result, decimals=8) self.assertTupleEqual(shape(slow_evaluation_result), (N, k)) self.assertTupleEqual(shape(fast_evaluation_result), (N, k)) assert_array_equal(slow_evaluation_result, fast_evaluation_result)