def run(attack_traces: np.ndarray,
            attack_keys: np.ndarray,
            attack_plain: np.ndarray,
            round_: int,
            operation: int,
            subkey: int,
            offset: int = 15,
            single_order: bool = False,
            debug_mode_enabled: bool = False,
            bit: int = 0) -> np.ndarray:
        """ The run method of dpa

        :param attack_traces: the traces to use for attacking
        :param attack_keys: the keys to use for attacking
        :param attack_plain: the plaintexts to use for attacking
        :param round_: the AES round to attack
        :param operation: the AES operation to attack, represented as an integer from 0 to 3
        :param subkey: the subkey index to analyze. Must be in the range [0-15].
        :param offset: offset to use for dpa.
        :param single_order: only use single order.
        :param debug_mode_enabled: whether to enable debug mode
        :param bit: which bit to select.
        :return: the calculated subkey corresponding to the subkey index specified
        """

        print("Executing Differential Power Analysis")

        result = np.zeros(16, dtype=int)
        if single_order:
            offset = 0
        # Init progress bar with amount of iterations.
        if subkey == 16:

            bar = progressbar.ProgressBar(
                max_value=16 * (255),
                widgets=progress_bar_util.get_widgets(debug_mode_enabled))
            for i in range(16):
                dpa = DPA(attack_traces, attack_keys, attack_plain, bit)
                dpa.set_offset(offset)
                result[i] = dpa.solve_subkey(i,
                                             debug_mode_enabled,
                                             round_=round_,
                                             operation=operation,
                                             bar=bar)

        else:
            bar = progressbar.ProgressBar(
                max_value=255,
                widgets=progress_bar_util.get_widgets(debug_mode_enabled))

            dpa = DPA(attack_traces, attack_keys, attack_plain, bit)
            dpa.set_offset(offset)
            result[subkey] = dpa.solve_subkey(subkey,
                                              debug_mode_enabled,
                                              round_=round_,
                                              operation=operation,
                                              bar=bar)
        bar.finish()
        print('The final key is: ', result)
        return result
Beispiel #2
0
    def run(aligned: np.ndarray, unaligned: np.ndarray, algorithm: int,
            output: str, debug_mode_enabled: bool):
        """Aligns traces with specified algorithm and outputs an aligned file

        :param aligned: File of 1 or more aligned traces.
        :param unaligned: File of unaligned traces
        :param algorithm: algorithm to use
        :param output: filename to output to.
        :param debug_mode_enabled: debug mode flag.
        :return:
        """

        print("Executing trace alignment.")

        bar = progressbar.ProgressBar(
            max_value=len(unaligned),
            widgets=progress_bar_util.get_widgets(debug_mode_enabled))
        if algorithm == 0:
            outputarray = Aligner.dtw(aligned, unaligned, bar)
            np.save(output, outputarray)
        elif algorithm == 1:
            outputarray = Aligner.fft(aligned, unaligned, bar)
            np.save(output, outputarray)
        bar.finish()
        return 0
    def test_get_widgets(self):
        """
        Tests if the normal widgets are returned correctly
        """

        real_widgets = progress_bar_util.CONST_DEFAULT_WIDGETS
        result = progress_bar_util.get_widgets(False)

        self.assertEqual(real_widgets, result)
    def test_get_widgets_debug(self):
        """
        Tests if the debug widgets are returned correctly
        """

        real_widgets = progress_bar_util.CONST_DEFAULT_DEBUG_WIDGETS
        result = progress_bar_util.get_widgets(True)

        self.assertEqual(real_widgets, result)
Beispiel #5
0
    def test_log_progressbar_forbidden(self):
        """Tests whether trying to log to a progressbar while not in debug mode does not work"""
        log_handler = loghandler.LogHandler("test_file8", False)

        log_bar = progressbar.ProgressBar(
            widgets=progress_bar_util.get_widgets(True))
        log_handler.log_to_debug_progressbar(log_bar, "test123")

        # Test if the debug message while logging is equal to the desired string
        desired_value = {progress_bar_util.CONST_DEBUG_STRING: None}
        self.assertEqual(log_bar.dynamic_messages, desired_value)
Beispiel #6
0
    def test_log_to_debug_progressbar(self):
        """"This tests whether loghandler to the progressbar works"""

        log_handler = loghandler.LogHandler("test_file4", True)
        test_string = "Test123"

        # Create a progressbar and debug a certain test string
        log_bar = progressbar.ProgressBar(
            widgets=progress_bar_util.get_widgets(True))
        log_handler.log_to_debug_progressbar(log_bar, test_string)

        log_handler.stop_logging()

        # Test if the debug message while loghandler is equal to the desired string
        desired_value = {progress_bar_util.CONST_DEBUG_STRING: test_string}
        self.assertEqual(log_bar.dynamic_messages, desired_value)

        os.remove(log_handler.file_name)
    def run(traces: np.ndarray, keys: np.ndarray, plain: np.ndarray,
            subkey: int, num_features: int, feature_select: int):
        """
        Runs Linear Regression Analysis

        :param traces: the traces to use
        :param keys: the keys to use
        :param plain: the plaintexts corresponding to the traces
        :param subkey: the specific subkey index to calculate.
                       16 is used to indicate that the whole key should be returned
        :param num_features: the number of features to select with feature selection
        :param feature_select: the type of feature selection to use.
        :return: the (sub)key most likely to be the real (sub)key
        """

        print('This performs Linear Regression Analysis')

        lra = LRA(traces, plain)

        lra.bar = progressbar.ProgressBar(
            max_value=2 * lra.KEY_SIZE,
            widgets=progress_bar_util.get_widgets(False))

        result = [0 for _ in range(16)]
        subkey_indices = [subkey]
        if subkey == 16:
            subkey_indices = list(range(16))
            lra.bar.max_value *= 16

        for i in subkey_indices:
            if feature_select != 0:
                feature_indices = DataPartitioner.select_features(
                    traces, keys, plain, i, feature_select, num_features, 1, 0,
                    True)
                lra.traces = traces[:, feature_indices]
                lra.dimension_leakage_points = len(lra.traces[0])

            result[i] = lra.solve_subkey(i)

        print('The final key is: ', result)

        return result
Beispiel #8
0
    def test_stop_logging_to_progressbar(self):
        """Tests whether the stop_logging function stops the loghandler to the progressbar"""

        log_handler = loghandler.LogHandler("test_file6", True)
        test_string = "Test123"

        # Create a progressbar and debug a certain test string
        log_bar = progressbar.ProgressBar(
            widgets=progress_bar_util.get_widgets(True))
        log_handler.log_to_debug_progressbar(log_bar, test_string)
        log_handler.stop_logging()

        # Write again a message which shouldnt be logged
        test_string2 = "Test456"
        log_handler.log_to_debug_progressbar(log_bar, test_string2)

        # Test if the debug message while loghandler is equal to the desired string
        desired_value = {progress_bar_util.CONST_DEBUG_STRING: test_string}
        self.assertEqual(log_bar.dynamic_messages, desired_value)

        os.remove(log_handler.file_name)
Beispiel #9
0
    def run(traces: np.ndarray,
            plains: np.ndarray,
            keys: np.ndarray,
            attack_traces: np.ndarray,
            subkey: int,
            debug_mode_enabled: bool = False) -> List[int]:
        """ The run method of pia

        :param traces: the traces to use
        :param plains: the plaintexts to use
        :param keys: the keys to use
        :param attack_traces: the traces to use for attacking
        :param subkey: the subkey index to analyze. Must be in the range [0-15].
        :param debug_mode_enabled: whether to enable debug mode
        :return: the calculated subkey corresponding to the subkey index specified
        """

        print("Executing Perceived Information Analysis")

        bar = progressbar.ProgressBar(
            max_value=len(attack_traces[0]) * (16 if subkey == 16 else 1),
            widgets=progress_bar_util.get_widgets(debug_mode_enabled))
        warnings.simplefilter("ignore", category=RuntimeWarning)

        perceived_information = [0] * len(attack_traces[0])
        max_pia = -float("inf")

        bar.start()

        indices = [subkey]
        if subkey == 16:
            indices = range(subkey)

        for i in indices:

            subkeys = [0] * len(keys)

            for j in range(len(keys)):
                subkeys[j] = int(keys[j][i])

            dummy_interp1d = interp1d(range(2), range(2))

            leakage_per_byte_value_matrix = [
                list() for _ in range(Pia.KEY_SIZE)
            ]
            model_sampled_pdf_per_byte_value_array = np.array(
                [dummy_interp1d for _ in range(Pia.KEY_SIZE)])

            for j in range(len(traces[0])):
                for k in range(len(traces)):
                    key = subkeys[k]
                    plain = plains[k][i]
                    byte = key ^ plain
                    leakage_per_byte_value_matrix[byte].append(traces[k][j])

            for j in range(len(leakage_per_byte_value_matrix)):
                model_mu, model_std = norm.fit(
                    leakage_per_byte_value_matrix[j])
                model_sampled_pdf_per_byte_value_array[j] = Pia.sample_pdf(
                    model_mu, model_std, 10)

            scaling_factor = 1.0 / (len(traces) * len(attack_traces))

            for j in range(len(attack_traces[0])):
                column = attack_traces[:, j]

                chip_mu, chip_std = norm.fit(column)
                chip_sampled_pdf = Pia.sample_pdf(chip_mu, chip_std, 10)

                pia = 0
                for cell in column:
                    for k in range(Pia.KEY_SIZE):
                        model_sampled_pdf = model_sampled_pdf_per_byte_value_array[
                            k]

                        if not np.isclose(chip_std, 0.0):

                            model_probability = model_sampled_pdf(cell)
                            chip_probability = chip_sampled_pdf(cell)

                            # The sampling sometimes returns a negative probability. Correct this.
                            if model_probability <= 0.0:
                                model_probability = 0.000001

                            if chip_probability <= 0.0:
                                chip_probability = 0.0

                            pia += chip_probability * math.log2(
                                model_probability)

                pia *= scaling_factor

                _, bin_edges = np.histogram(column, bins='auto')
                bin_values = np.digitize(column, bin_edges)

                o = np.array(bin_values, dtype=int)
                shannon_entropy = drv.entropy(o)

                pia = shannon_entropy - pia

                perceived_information[j] += pia

                if bar.value < bar.max_value:
                    bar.update(bar.value + 1)

                if pia > max_pia:
                    max_pia = pia

        for i in range(len(perceived_information)):
            perceived_information[i] /= max_pia * (16 if subkey == 16 else 1)

        bar.finish()
        plt.plot(perceived_information)
        plt.show()

        warnings.simplefilter("default")

        print("Done!")

        return perceived_information
    def run(template_traces: np.ndarray,
            template_keys: np.ndarray,
            template_plaintext: np.ndarray,
            attack_traces: np.ndarray,
            attack_keys: np.ndarray,
            attack_plain: np.ndarray,
            pooled: bool,
            num_points_of_interest: int,
            spacing_points_of_interest: int,
            subkey: int,
            gpu: bool = False,
            leakage_model: bool = True,
            debug_mode_enabled: bool = False,
            feature_select: int = 0) -> np.array:
        """ Method used to select correct version of Template Attack.

        :param template_traces: the traces to use
        :param template_keys: the keys to use
        :param template_plaintext: the plaintexts to use
        :param attack_traces: the traces to use for attacking
        :param attack_keys: the keys to use for attacking
        :param attack_plain: the plaintexts to use for attacking
        :param pooled: whether to do a pooled attack
        :param num_points_of_interest: number of points of interest to use
        :param spacing_points_of_interest: spacing between the points of interest
        :param subkey: the subkey index to analyze. Must be in the range [0-16]. 16 signals the full key.
        :param gpu: whether or not to use gpu for this attack
        :param leakage_model: the leakage model to use
        :param debug_mode_enabled: whether to enable debug mode
        :param feature_select: which feature selection method to use, see main for which number is which.
        :return: array containing the calculated key
        """

        # Init progress bar with rough amount of iterations
        num_subkeys = 16 if subkey == 16 else 1  # Attack takes roughly equal time per subkey so * 16 for whole key
        max_value = len(attack_traces) * 256 * num_subkeys
        bar = progressbar.ProgressBar(
            max_value=max_value,
            widgets=progress_bar_util.get_widgets(debug_mode_enabled))

        ta = TA(template_traces, template_keys, template_plaintext,
                attack_traces, attack_keys, attack_plain)

        indices = []

        if feature_select > 0:

            print("Feature selection is being calculated...")

            if num_subkeys == 16:
                for i in range(16):

                    temp = DataPartitioner.select_features(
                        template_traces, template_keys, template_plaintext, i,
                        feature_select, num_points_of_interest, 1, 0,
                        leakage_model)
                    for j in temp:
                        indices.append(j)
            else:
                # Select at least 10 features
                num_features = max(num_points_of_interest, 10)
                indices = DataPartitioner.select_features(
                    template_traces, template_keys, template_plaintext, subkey,
                    feature_select, num_features, 1, 0, leakage_model)

            ta.template_traces, ta.attack_traces = template_traces[:,
                                                                   indices], attack_traces[:,
                                                                                           indices]

        if pooled:
            result = ta.run_pooled(num_points_of_interest,
                                   spacing_points_of_interest, subkey, bar,
                                   gpu, leakage_model, debug_mode_enabled)
        else:
            result = ta.run_normal(num_points_of_interest,
                                   spacing_points_of_interest, subkey, bar,
                                   gpu, leakage_model, debug_mode_enabled)

        bar.finish()

        print('The final key is: ', result)
        return result
    def run(traces: np.ndarray,
            keys: np.ndarray,
            plain: np.ndarray,
            attack_traces: np.ndarray,
            attack_keys: np.ndarray,
            attack_plain: np.ndarray,
            round_: int,
            operation: int,
            subkey: int,
            feature_select: int,
            num_features: int,
            hamming_weight: bool = False,
            debug_mode_enabled: bool = False,
            online: bool = False,
            conditional_averaging: bool = False) -> np.ndarray:
        """ The run method of cpa

        :param traces: the traces to use
        :param keys: the keys to use
        :param plain: the plaintexts to use
        :param attack_traces: the traces to use for attacking
        :param attack_keys: the keys to use for attacking
        :param attack_plain: the plaintexts to use for attacking
        :param round_: the AES round to attack
        :param operation: the AES operation to attack, represented as an integer from 0 to 3
        :param feature_select: which feature select method to use.
        :param num_features: the number of features to select
        :param subkey: the subkey index to analyze. Must be in the range [0-15].
        :param hamming_weight: whether to use the hamming_weight leakage model
        :param debug_mode_enabled: whether to enable debug mode
        :param online: use online correlation calculation.
        :param conditional_averaging: whether to use conditional averaging.
        :return: the calculated subkey corresponding to the subkey index specified
        """

        print("Executing Correlation Power Analysis")

        result = np.zeros(16, dtype=int)
        # Init progress bar with amount of iterations.
        if subkey == 16:

            bar = progressbar.ProgressBar(
                max_value=16 * 255,
                widgets=progress_bar_util.get_widgets(debug_mode_enabled))
            for i in range(16):

                if feature_select > 0:
                    indices = data_partitioner.DataPartitioner.select_features(
                        traces, keys, plain, i, feature_select, num_features,
                        round_, operation, hamming_weight)
                    cpa = CPA(attack_traces[:, indices], attack_keys,
                              attack_plain, online)
                else:
                    cpa = CPA(attack_traces, attack_keys, attack_plain, online)
                result[i] = cpa.solve_subkey(
                    i,
                    hamming_weight,
                    debug_mode_enabled,
                    round_=round_,
                    operation=operation,
                    bar=bar,
                    conditional_averaging=conditional_averaging)

        else:
            bar = progressbar.ProgressBar(
                max_value=255,
                widgets=progress_bar_util.get_widgets(debug_mode_enabled))

            if feature_select > 0:
                indices = data_partitioner.DataPartitioner.select_features(
                    traces, keys, plain, subkey, feature_select, num_features,
                    round_, operation, hamming_weight)
                cpa = CPA(attack_traces[:, indices], attack_keys, attack_plain,
                          online)
            else:
                cpa = CPA(attack_traces, attack_keys, attack_plain, online)
            result[subkey] = cpa.solve_subkey(
                subkey,
                hamming_weight,
                debug_mode_enabled,
                round_=round_,
                operation=operation,
                bar=bar,
                conditional_averaging=conditional_averaging)
        bar.finish()
        print('The final key is: ', result)
        return result
    def run(profiling_traces: np.ndarray, profiling_keys: np.ndarray, profiling_plaintext: np.ndarray,
            attack_traces: np.ndarray, attack_keys: np.ndarray, attack_plaintext: np.ndarray, round_: int,
            operation: int, num_traces: int, num_attack_traces: int, subkey: int, feature_select: int,
            num_features: int, use_gpu: bool = False, hamming_weight: bool = False, debug_mode_enabled: bool = False) \
            -> List[int]:
        """
        Runs a full stochastic attack

        :param profiling_traces: the traces to use
        :param profiling_keys: the keys to use
        :param profiling_plaintext: the plaintexts to use
        :param attack_traces: the traces to use for attacking
        :param attack_keys: the keys to use for attacking
        :param attack_plaintext: the plaintexts to use for attacking
        :param round_: the AES round to attack
        :param operation: the AES operation to attack, represented as an integer from 0 to 3
        :param num_traces: number of data points to process
        :param num_attack_traces: number of data points to attack
        :param feature_select: which feature select method to use.
        :param num_features: the number of features to select
        :param subkey: the subkey index to analyze. Must be in the range [0-16], 16 signaling the whole key.
        :param use_gpu: whether or not to use gpu acceleration
        :param hamming_weight: whether or not to use the hamming_weight leakage model
        :param debug_mode_enabled: whether or not to enable debug mode
        :returns: list containing the (sub)key
        """

        print('This performs a stochastic attack.')

        # Instantiate a SA (Stochastic Attack) object to call dynamic method.
        sa = SA(profiling_traces, profiling_keys, profiling_plaintext,
                attack_traces, attack_keys, attack_plaintext)
        sa.log_handler = LogHandler('sa', debug_mode_enabled)

        if sa.log_handler is not None:
            sa.log_handler.log_to_debug_file(
                'RUNNING stochastic attack with \n'
                'TEMPLATE_TRACES: {} \n'
                'NUM_FEATURES: {} \n'
                'ATTACK_TRACES: {} \n'
                'SUBKEY: {}.'.format(len(sa.profiling_traces), num_features,
                                     len(sa.attack_traces), subkey))

        # Init progress bar with estimated amount of iterations
        num_subkeys = 16 if subkey == 16 else 1
        max_value = num_attack_traces * 256 * num_subkeys * 15
        bar = progressbar.ProgressBar(
            max_value=max_value,
            widgets=progress_bar_util.get_widgets(debug_mode_enabled))

        result = [0 for _ in range(16)]

        # call method that returns the key, currently with no arguments taken from the user.
        if subkey == 16:
            for i in range(subkey):
                result[i] = sa.solve_subkey(
                    i,
                    use_gpu,
                    bar,
                    feature_select=feature_select,
                    num_features=num_features,
                    num_traces=num_traces,
                    num_attack_traces=num_attack_traces,
                    hamming_weight=hamming_weight,
                    aes_round=round_,
                    aes_operation=operation)
        else:
            result[subkey] = sa.solve_subkey(
                subkey,
                use_gpu,
                bar,
                feature_select=feature_select,
                num_features=num_features,
                num_traces=num_traces,
                num_attack_traces=num_attack_traces,
                hamming_weight=hamming_weight,
                aes_round=round_,
                aes_operation=operation)

        bar.finish()

        print('The final key is: ', result)
        return result