Пример #1
0
    def export(container, leakages_filename, values_filename, name=None, batch_size=100):
        """
        export method is used to export an existing container into an NpyContainer.

        It creates a session and use a ContainerDumpEngine to recopy the traces delivered by the original container
        into a NpyContainer.

        :param container: container to be exported
        :param leakages_filename: name of the npy file to create corresponding to the leakages
        :param values_filename: name of the npy file to create corresponding to the values
        :param name: name for the session
        :param batch_size: batch_size for the session
        :return: 
        """

        leakage, value = container[0]
        out = NpyContainer._void_container(leakages_filename, values_filename, container.number_of_traces, leakage.shape, leakage.dtype,
                                           value.shape, value.dtype)

        from lascar import Session
        from lascar.engine import ContainerDumpEngine

        session = Session(container, engine=ContainerDumpEngine(out), name=name if name else 'NpyContainer')
        session.run(batch_size)

        return out
Пример #2
0
def show_nicv(values, traces, nr_digits=4):
    """ Compute the Normalized Inter-Class Variance as in the article """
    import numpy as np

    values = np.array(values, dtype=np.uint8)
    traces = np.array(traces)

    from lascar import TraceBatchContainer, Session, NicvEngine, hamming

    # Use the Hamming weight of leaked values and add some noise
    # through the 'leakage_processing' parameter
    t = TraceBatchContainer(
        traces,
        values,
        leakage_processing=lambda x: np.array(
            [hamming(i) for i in x], dtype=np.uint
        )
        + np.random.normal(0, 0.5, len(x)),
    )

    s = Session(t)

    ## Input value leakage
    # s.add_engines([NicvEngine('a'+str(i), lambda v,z=i:v[z], range(9)) for i in range(nr_digits)])

    ## Difference leakage
    s.add_engines([NicvEngine('a'+str(i), lambda v,z=i:np.int8(v[z]) - np.int8(STORED_PIN[z]), range(-9,8)) for i in range(nr_digits)])

    ## below is a variant on the carry bit
    # s.add_engines([NicvEngine('c'+str(i), lambda v,z=i:v[z]>int(STORED_PIN[z]), range(16)) for i in range(nr_digits)])

    s.run()

    return np.array([s[eng]._finalize() for eng in s.engines if eng not in ['mean', 'var']])
Пример #3
0
    def export(
        container,
        filename,
        name=None,
        leakages_dataset_name="leakages",
        values_dataset_name="values",
        batch_size=100,
    ):
        """
        export method is used to export an existing container into an Hdf5Container.

        It creates a session and use a ContainerDumpEngine to recopy the traces delivered by the original container.

        :param container: container to be exported
        :param filename: name of the Hdf5Container to vuild
        :param leakages_dataset_name:
        :param values_dataset_name:
        :param batch_size:
        :return:
        """

        leakage, value = container[0]
        out = Hdf5Container.void_container(
            filename,
            container.number_of_traces,
            leakage.shape,
            leakage.dtype,
            value.shape,
            value.dtype,
            leakages_dataset_name,
            values_dataset_name,
        )

        from lascar import Session
        from lascar.engine import ContainerDumpEngine

        session = Session(
            container,
            engine=ContainerDumpEngine(out),
            name=name if name else "Hdf5Container",
        )
        session.run(batch_size)
        # Adding mean/var: to leakage_dataset_name as attributes
        try:
            out._file[leakages_dataset_name].attrs["mean"] = session[
                "mean"].finalize()
            out._file[leakages_dataset_name].attrs["var"] = session[
                "var"].finalize()
        except:
            pass

        return out
Пример #4
0
    def export(container,
               filename,
               name=None,
               leakages_dataset_name="leakages",
               values_dataset_name="values",
               batch_size=100):
        """
        export method is used to export an existing container into an Hdf5Container.

        It creates a session and use a ContainerDumpEngine to recopy the traces delivered by the original container.

        :param container: container to be exported
        :param filename: name of the Hdf5Container to vuild
        :param leakages_dataset_name:
        :param values_dataset_name:
        :param batch_size:
        :return:
        """

        leakage, value = container[0]
        out = Hdf5Container.void_container(filename,
                                           container.number_of_traces,
                                           leakage.shape, leakage.dtype,
                                           value.shape, value.dtype,
                                           leakages_dataset_name,
                                           values_dataset_name)

        from lascar import Session
        from lascar.engine import ContainerDumpEngine

        session = Session(container,
                          engine=ContainerDumpEngine(out),
                          name=name if name else 'Hdf5Container')
        session.run(batch_size)

        return out
Пример #5
0
## Launch 16 CPAs on the outputs of the sbox

from lascar.container import TraceBatchContainer
from lascar import Session, CpaEngine, ConsoleOutputMethod
from lascar.tools.aes import sbox

t = TraceBatchContainer(traces, values)

s = Session(t, output_method=ConsoleOutputMethod())
s.add_engines(
    [
        CpaEngine(f"cpa{i}", lambda v, k, z=i: sbox[v[z] ^ k], range(256))
        for i in range(16)
    ]
)
s.run()

print(s.output_method.finalize())

# Check the results :
print("Key should be : f0 33 1c e0 26 6a da ce 86 a8 a1 3b fa 14 67 40")

K = list(
    map(lambda x: int(x, 16), "f0 33 1c e0 26 6a da ce 86 a8 a1 3b fa 14 67 40".split())
)

for i, n in enumerate([f"cpa{i}" for i in range(16)]):
    print(
        hex(K[i]),
        (K[i] == np.abs(s[n]._finalize()).max(1).argmax())
        and "found !"
Пример #6
0
def selection_function(value, guess):
    return sbox[value['plaintext'][3] ^ guess] & 1


guess_range = range(256)

from lascar import DpaEngine
dpa_engine = DpaEngine('dpa', selection_function, guess_range)

# We can now create a Session, register the dpa_lsb_engine, and run it.
from lascar import Session
session = Session(container, engine=dpa_engine)
# session.add_engine( dpa_lsb_engine) # the engine can be added after the session creation

session.run(
    batch_size=100)  # the session will load traces by batches of 100 traces
"""
Now, to get the result, one solution could be to request the dpa_lsb_engine.finalize() method.
(As most of the engines, the finalize() method returns sca results)

For more option about how to manage results of sca, please follow the next step of the tutorial.

"""
results = dpa_engine.finalize()

print(results.shape)
print("Best Guess is %02X." % results.max(1).argmax())

import matplotlib.pyplot as plt
_ = plt.plot(results.T)
_ = plt.show()
Пример #7
0
Once the run() method is called, all traces are read and processed by the Engines registered by the Session.

Engines are classes dedicated to compute stuffs from side-channel traces. The Session distributes traces batches to all its Engines, for them to do their jobs.
Here a list of Engines already implemented in lascar:
- MeanEngine: compute the mean of all the traces leakages
- VarEngine: compute the varianc of all the traces leakages
- SnrEngine: compute Signal-to-Noise-Ratio from the traces leakages and a partitioning function appllied to the values.
- CpaEngine: compute Correlation Power Analysis from the traces leakages and a guess function appllied to the values.
- TTestEngine: compute Welch's T-Test from the traces leakages and a partitioning function appllied to the value
- ...


By default, a Session only registers MeanEngine and VarEngine.
The Mean/Variance of the leakage is the only thing computed in that very case:
"""

print(
    session.engines
)  # engines is a dict of all the engines registered by the Session, with key equal to the name given

session.run()

# Now that the engines has been fed with all the traces, we can access their results through their finalize() method:
mean = session.engines["mean"].finalize()
mean = session.engines["mean"].finalize()  # shortcut

variance = session["var"].finalize()

print("mean=", mean)
print("variance=", variance)