def test_run_too_much_traces(self):
        """ Tests a run with more traces asked than provided."""

        traces = np.array([[1, 2, 3], [4, 5, 6], [7, 0.4, 9], [2, 3, 12]])
        plain = np.array([[1], [2], [1], [2]])
        keys = plain

        with self.assertRaises(SystemExit) as cm:
            DataPartitioner.get_traces(traces, keys, plain, 5, 1, 0, 1, 2, 1, 0, True)

        # Test whether the right exit code was used.
        self.assertEqual(cm.exception.code, 1)
def cpa(traces_file: str, keys_file: str, plain_file: str, subkey: int, leakage_model: bool,
        num_traces: int, num_attack_traces: int, num_features: int, feature_select: int, round_: int,
        operation: int, debug_mode: bool, version: int):
    """
    Performs different CPA attacks.

    :param traces_file: the traces file to use
    :param keys_file: the keys file to use
    :param plain_file: the plaintexts file to use
    :param subkey: the subkey index to analyze. Must be in the range [0-15]
    :param leakage_model: the leakage model to use.
    :param round_: the AES round to attack.
    :param num_traces: the amount of traces to analyze starting from trace 0.
    :param num_attack_traces: the amount of attack traces to analyze starting from trace 0.
    :param num_features: the number of features
    :param operation: the AES operation to 'attack', represented as an integer from 0 to 3.
    :param feature_select: which feature select to use
    :param debug_mode: whether to enable debug mode
    :param version: pick which version of CPA you want, the default is offline CPA.
    """

    online, conditional_averaging = False, False
    if version == 1:
        online = True
    elif version == 2:
        conditional_averaging = True

    traces, keys, plain = FileLoader.main(traces_file, keys_file, plain_file)
    profiling_traces, profiling_keys, profiling_plaintext, attack_traces, attack_keys, attack_plaintext = \
        DataPartitioner.get_traces(traces, keys, plain, num_traces, subkey,
                                   0, num_attack_traces, num_features, round_, operation, leakage_model)
    CPA.run(profiling_traces, profiling_keys, profiling_plaintext, attack_traces, attack_keys, attack_plaintext,
            round_, operation, subkey, feature_select, num_features, leakage_model,
            debug_mode_enabled=debug_mode, online=online, conditional_averaging=conditional_averaging)
def ta(traces_file: str, keys_file: str, plain_file: str, points_of_interest: int, pooled: bool, spacing: int,
       subkey: int, num_traces: int, gpu: bool, leakage_model: bool, debug_mode: bool, num_attack_traces: int,
       feature_select: int):
    """
    Performs (pooled) template attack.

    :param traces_file: the traces file to use.
    :param keys_file: the keys file to use.
    :param plain_file: the plaintexts file to use.
    :param points_of_interest: the number of points of interest to extract.
    :param pooled: whether to use pooled attack.
    :param spacing: spacing between the points of interest.
    :param subkey: the subkey index to analyze. Must be in the range [0-16], 16 signaling the whole key to be found out.
    :param num_traces: the amount of traces to analyze starting from trace 0
    :param gpu: whether or not to use gpu for this attack
    :param leakage_model: the leakage model to use
    :param debug_mode: whether to enable debug mode
    :param num_attack_traces: the number of attack traces.
    :param feature_select: which feature select to use, default is none.
    """
    traces, keys, plain = FileLoader.main(traces_file, keys_file, plain_file)

    profiling_traces, profiling_keys, profiling_plaintext, attack_traces, attack_keys, attack_plaintext = \
        DataPartitioner.get_traces(traces, keys, plain, num_traces, subkey,
                                   0, num_attack_traces, 0, 1, 0, leakage_model)

    if not pooled and profiling_traces.shape[0] < profiling_traces.shape[1]:
        print("ERROR: profiling traces are smaller than features, please run Pooled Template Attack instead of"
              " normal Template attack for a more accurate result.")
        exit(1)

    TA.run(profiling_traces, profiling_keys, profiling_plaintext, attack_traces, attack_keys, attack_plaintext,
           pooled, points_of_interest, spacing, subkey, gpu, leakage_model, debug_mode, feature_select)
def sa(traces_file: str, keys_file: str, plain_file: str, round_: int, operation: int, num_traces: int,
       num_attack_traces: int, subkey: int, gpu: bool, leakage_model: bool, num_features: int, feature_select: int,
       debug_mode: bool):
    """
    Performs stochastic attack.

    :param traces_file: the traces file to use.
    :param keys_file: the keys file to use.
    :param plain_file: the plaintexts file to use.
    :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: the amount of traces to analyze starting from trace 0.
    :param num_attack_traces: the amount of attack traces to analyze starting from trace 0.
    :param subkey: the subkey index to analyze. Must be in the range [0-16], 16 signaling the whole key to be found out.
    :param gpu: enables gpu acceleration if set to true.
    :param num_features: number of features to select for.
    :param feature_select: which feature select to use, default is pearson.
    :param leakage_model: the leakage model to use.
    :param debug_mode: whether to enable debug mode
    """

    traces, keys, plain = FileLoader.main(traces_file, keys_file, plain_file)
    profiling_traces, profiling_keys, profiling_plaintext, attack_traces, attack_keys, attack_plaintext = \
        DataPartitioner.get_traces(traces, keys, plain, num_traces, subkey,
                                   0, num_attack_traces, num_features, round_, operation, leakage_model)
    SA.run(profiling_traces, profiling_keys, profiling_plaintext, attack_traces, attack_keys, attack_plaintext,
           round_, operation, len(profiling_traces), num_attack_traces, subkey, feature_select, num_features, gpu,
           leakage_model, debug_mode_enabled=debug_mode)
def mia(traces_file: str, keys_file: str, plain_file: str, subkey: int, leakage_model: bool,
        num_traces: int, num_attack_traces: int, num_features: int, feature_select: int, round_: int,
        operation: int, debug_mode: bool):
    """Performs MIA (Mutual Information Analysis) attack.

    :param traces_file: the traces file to use
    :param keys_file: the keys file to use
    :param plain_file: the plaintexts file to use
    :param subkey: the subkey index to analyze. Must be in the range [0-15]
    :param leakage_model: the leakage model to use.
    :param round_: the AES round to attack.
    :param num_traces: the amount of traces to analyze starting from trace 0.
    :param num_attack_traces: the amount of attack traces to analyze starting from trace 0.
    :param num_features: the number of features
    :param operation: the AES operation to 'attack', represented as an integer from 0 to 3.
    :param feature_select: which feature select to use
    :param debug_mode: whether to enable debug mode
    """
    traces, keys, plain = FileLoader.main(traces_file, keys_file, plain_file)
    profiling_traces, profiling_keys, profiling_plaintext, attack_traces, attack_keys, attack_plaintext = \
        DataPartitioner.get_traces(traces, keys, plain, num_traces, subkey,
                                   0, num_attack_traces, num_features, round_, operation, leakage_model)
    Mia.run(profiling_traces, profiling_keys, profiling_plaintext, attack_traces, attack_keys, attack_plaintext,
            round_, operation, subkey, feature_select,
            num_features, leakage_model, debug_mode_enabled=debug_mode)
    def test_mia_run(self):
        """"This tests the run method of MIA with a reduced data set"""
        traces, keys, plain = FileLoader.main(CONST_DEFAULT_TRACES_FILE,
                                              CONST_DEFAULT_KEYS_FILE,
                                              CONST_DEFAULT_PLAIN_FILE)

        profiling_traces, profiling_keys, profiling_plaintext, attack_traces, attack_keys, attack_plaintext = \
            DataPartitioner.get_traces(traces, keys, plain, 1000, 0,
                                       0, 1000, 10, 1, 0, False)

        expected = np.array([43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
        self.assertTrue(np.array_equal(Mia.run(profiling_traces, profiling_keys, profiling_plaintext, attack_traces,
                        attack_keys, attack_plaintext, 1, 0, 0, 1, 10, True), expected))
    def test_basic_run(self):
        """ Tests a run with normal amount of traces to select."""

        traces = np.array([[1, 2, 3], [4, 5, 6],  [7, 0.4, 9], [2, 3, 12]])
        plain = np.array([[1], [2], [1], [2]])
        keys = plain

        profiling_traces, profiling_keys, profiling_plaintext, attack_traces, attack_keys, attack_plaintext = \
            DataPartitioner.get_traces(traces, keys, plain, 2, 1, 0, 1, 2, 1, 0, True)

        # Test whether the dimensions of the returned traces match the expectations.
        self.assertEqual(len(profiling_traces), 2)
        self.assertEqual(len(profiling_traces[0]), 3)
def pia(traces_file: str, keys_file: str, plain_file: str, subkey: int, num_traces: int, num_attack_traces: int,
        round_: int,
        debug_mode: bool):
    """Performs PIA (Perceived Information Analysis).

    :param traces_file: the traces file to use
    :param keys_file: the keys file to use
    :param plain_file: the plaintexts file to use
    :param subkey: the subkey index to analyze. Must be in the range [0-15]
    :param round_: the AES round to attack.
    :param num_traces: the amount of traces to analyze starting from trace 0.
    :param num_attack_traces: the amount of attack traces to analyze starting from trace 0.
    :param num_features: the number of features
    :param feature_select: which feature select to use
    :param debug_mode: whether to enable debug mode
    """
    traces, keys, plain = FileLoader.main(traces_file, keys_file, plain_file)
    profiling_traces, profiling_keys, profiling_plaintext, attack_traces, attack_keys, attack_plaintext = \
        DataPartitioner.get_traces(traces, keys, plain, num_traces, subkey,
                                   0, num_attack_traces, 5000, round_, 0, False)

    Pia.run(profiling_traces, profiling_plaintext, profiling_keys, attack_traces, subkey, debug_mode_enabled=debug_mode)
def dpa(traces_file: str, keys_file: str, plain_file: str, subkey: int, num_attack_traces: int,
        round_: int, operation: int, debug_mode: bool, bit: int, offset: int, single_order: bool):
    """Performs different DPA attacks.

    :param traces_file: the traces file to use
    :param keys_file: the keys file to use
    :param plain_file: the plaintexts file to use
    :param subkey: the subkey index to analyze. Must be in the range [0-15]
    :param round_: the AES round to attack.
    :param num_attack_traces: the amount of attack traces to analyze starting from trace 0.
    :param operation: the AES operation to 'attack', represented as an integer from 0 to 3.
    :param debug_mode: whether to enable debug mode
    :param bit: which bit to attack
    :param offset: the offset to use
    :param single_order: enables single order DPA
    """
    traces, keys, plain = FileLoader.main(traces_file, keys_file, plain_file)
    profiling_traces, profiling_keys, profiling_plaintext, attack_traces, attack_keys, attack_plaintext = \
        DataPartitioner.get_traces(traces, keys, plain, 0, subkey,
                                   0, num_attack_traces, 0, round_, operation, False)
    DPA.run(attack_traces, attack_keys, attack_plaintext,
            round_, operation, subkey, offset=offset, single_order=single_order,
            debug_mode_enabled=debug_mode, bit=bit)