aboutsummaryrefslogtreecommitdiff
path: root/pyecsca/sca/trace/test.py
blob: 4fc02362ffb37be54601b85b1fb9334260417371 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
from typing import Sequence, Optional

import numpy as np
from public import public
from scipy.stats import ttest_ind, ks_2samp

from .trace import Trace, CombinedTrace


def ttest_func(first_set: Sequence[Trace], second_set: Sequence[Trace],
               equal_var: bool) -> Optional[CombinedTrace]:
    if not first_set or not second_set or len(first_set) == 0 or len(second_set) == 0:
        return None
    first_stack = np.stack([first.samples for first in first_set])
    second_stack = np.stack([second.samples for second in second_set])
    result = ttest_ind(first_stack, second_stack, axis=0, equal_var=equal_var)
    return CombinedTrace(result[0], None, None)


@public
def welch_ttest(first_set: Sequence[Trace], second_set: Sequence[Trace]) -> Optional[CombinedTrace]:
    """
    Perform the Welch's t-test sample wise on two sets of traces `first_set` and `second_set`.
    Useful for Test Vector Leakage Analysis (TVLA).

    :param first_set:
    :param second_set:
    :return: Welch's t-values (samplewise)
    """
    return ttest_func(first_set, second_set, False)


@public
def student_ttest(first_set: Sequence[Trace], second_set: Sequence[Trace]) -> Optional[
        CombinedTrace]:
    """
    Perform the Students's t-test sample wise on two sets of traces `first_set` and `second_set`.
    Useful for Test Vector Leakage Analysis (TVLA).

    :param first_set:
    :param second_set:
    :return: Student's t-values (samplewise)
    """
    return ttest_func(first_set, second_set, True)


@public
def ks_test(first_set: Sequence[Trace], second_set: Sequence[Trace]) -> Optional[CombinedTrace]:
    """
    Perform the Kolmogorov-Smirnov two sample test on equality of distributions sample wise on
    two sets of traces `first_set` and `second_set`.

    :param first_set:
    :param second_set:
    :return: Kolmogorov-Smirnov test statistic values (samplewise)
    """
    if not first_set or not second_set or len(first_set) == 0 or len(second_set) == 0:
        return None
    first_stack = np.stack([first.samples for first in first_set])
    second_stack = np.stack([second.samples for second in second_set])
    results = np.empty(len(first_set[0].samples), dtype=first_set[0].samples.dtype)
    for i in range(len(first_set[0].samples)):
        results[i] = ks_2samp(first_stack[..., i], second_stack[..., i])[0]
    return CombinedTrace(results, None, None)