aboutsummaryrefslogtreecommitdiff
path: root/analysis/countermeasures/visualize.ipynb
diff options
context:
space:
mode:
Diffstat (limited to 'analysis/countermeasures/visualize.ipynb')
-rw-r--r--analysis/countermeasures/visualize.ipynb406
1 files changed, 406 insertions, 0 deletions
diff --git a/analysis/countermeasures/visualize.ipynb b/analysis/countermeasures/visualize.ipynb
new file mode 100644
index 0000000..709e566
--- /dev/null
+++ b/analysis/countermeasures/visualize.ipynb
@@ -0,0 +1,406 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "52a95c74-8fc0-4021-a8e9-8587ff6f1d9e",
+ "metadata": {},
+ "source": [
+ "# Visualizing prob-maps"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3232df80-2a65-47ce-bc77-6a64f44d2404",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pickle\n",
+ "import itertools\n",
+ "import glob\n",
+ "import gc\n",
+ "\n",
+ "import matplotlib\n",
+ "import matplotlib.pyplot as plt\n",
+ "import numpy as np\n",
+ "\n",
+ "from tqdm.auto import tqdm, trange\n",
+ "from statsmodels.stats.proportion import proportion_confint\n",
+ "\n",
+ "from pyecsca.ec.mult import *\n",
+ "from pyecsca.misc.utils import TaskExecutor\n",
+ "\n",
+ "from common import *\n",
+ "\n",
+ "%matplotlib ipympl"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4273bd5e-0ec6-4e5c-b63e-74cc325a8ece",
+ "metadata": {},
+ "source": [
+ "## Setup\n",
+ "Setup some plotting and the computations of prob-maps out of the small scalar data and divisors."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e89e66dc-4a9b-4320-8612-a8fa9af04b69",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Setup the ticks and colors deterministically.\n",
+ "mult_klasses = sorted(list(set(map(lambda mult: mult.klass, all_mults))), key=lambda klass: klass.__name__)\n",
+ "mult_kwarg_map = {klass: 0 for klass in mult_klasses}\n",
+ "mult_cm_map = {mult: 0 for mult in all_mults}\n",
+ "mult_colors = matplotlib.cm.tab20(range(len(mult_klasses)))\n",
+ "mult_styles = ['-', '--', '-.', ':', (5, (10, 3)), (0, (5, 1)), (0, (3, 1, 1, 1, 1, 1)), (0, (3, 1, 1, 1)), (0, (1, 1)), (0, (3, 10, 1, 10))]\n",
+ "mult_markers = [None, \"o\", \"+\", \"*\", \"^\", \"s\"]\n",
+ "colors = {}\n",
+ "styles = {}\n",
+ "markers = {}\n",
+ "for mult in all_mults:\n",
+ " color = mult_colors[mult_klasses.index(mult.klass) % len(mult_colors)]\n",
+ " style = mult_styles[mult_kwarg_map[mult.klass] % len(mult_styles)]\n",
+ " mult_kwarg_map[mult.klass] += 1\n",
+ " for cm in (None, \"gsr\", \"additive\", \"multiplicative\", \"euclidean\", \"bt\"):\n",
+ " mwc = mult.with_countermeasure(cm)\n",
+ " colors[mwc] = color\n",
+ " styles[mwc] = style\n",
+ " markers[mwc] = mult_markers[mult_cm_map[mult] % len(mult_markers)]\n",
+ " mult_cm_map[mult] += 1\n",
+ "\n",
+ "majticks = np.arange(0, 1, 0.1)\n",
+ "minticks = np.arange(0, 1, 0.05)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2596562f-8a6a-4a25-ae82-a6b9562d8a40",
+ "metadata": {},
+ "source": [
+ "## Divisors\n",
+ "The cell below contains some interesting divisors for distinguishing scalarmults."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bab2a086-8b3d-4e76-bf5c-46ea2b617708",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from common import divisor_map\n",
+ "for d, ds in divisor_map.items():\n",
+ " print(f\"{d:<27}\", ds[:3], \"...\", ds[-1:])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "638f8634-1f6e-4844-a796-096611dfbac2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bits = 256\n",
+ "num_workers = 28"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8b008248-a0aa-41fa-933c-f325f8eec31b",
+ "metadata": {},
+ "source": [
+ "## Configuration\n",
+ "Select the mults you want to compute the prob-maps for here as well as a set of divisors. It is good to set `all` here, compute the prob-maps for all the divisors, save them and they continue with visualizing them on subsets of divisors."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4d2a0f19-8275-4db8-b3fc-c930d8ba2177",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "selected_mults = all_mults\n",
+ "divisor_name = \"all\"\n",
+ "kind = \"precomp+necessary\"\n",
+ "showci = False\n",
+ "selected_divisors = divisor_map[divisor_name]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "19d986ab-5fe7-4dd6-b5b5-4e75307217d6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Optionally, load\n",
+ "with open(f\"{divisor_name}_{kind}_distrs.pickle\", \"rb\") as f:\n",
+ " distributions_mults = pickle.load(f)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ef5b7a43-74b4-4e72-a3a1-955e175f5297",
+ "metadata": {},
+ "source": [
+ "Now, go over all the divisor sets and visualize them (without the combs) into PNGs in the graphs/ directory."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5ccc28f6-3994-4a0d-8639-2f6df4dddd26",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for mult, probmap in distributions_mults.items():\n",
+ " for divisor in sorted(divisor_map[divisor_name]):\n",
+ " if divisor not in probmap.probs:\n",
+ " print(f\"Missing {mult}, {divisor}\")\n",
+ " if probmap.kind is not None and probmap.kind != kind:\n",
+ " print(\"Bad kind! Did you forget to load?\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9b6f169b-07b3-4b27-ba36-8b90418cd072",
+ "metadata": {},
+ "source": [
+ "## Plots (nocomb)\n",
+ "Let's visualize all the divisor groups while looking at the multipliers and countermeasures except the comb-like ones."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "906b5d78-b3a4-4cbb-8051-092d411ba735",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for divisor_name in divisor_map:\n",
+ " plot_mults = list(filter(lambda mult: mult in distributions_mults and mult.klass not in (CombMultiplier, BGMWMultiplier), all_mults_with_ctr))\n",
+ " print(divisor_name, \"nocomb\")\n",
+ " plot_divisors = sorted(divisor_map[divisor_name])\n",
+ " L = len(plot_divisors)\n",
+ " N = len(plot_mults)\n",
+ " x = list(range(L))\n",
+ " \n",
+ " fig = plt.figure(figsize=(L/4+10, 24))\n",
+ " ax = plt.subplot(111)\n",
+ " \n",
+ " vals = np.zeros((N, L))\n",
+ " n_samples = 0\n",
+ " for i, mult in enumerate(plot_mults):\n",
+ " probmap = distributions_mults[mult]\n",
+ " y_values = [probmap[l] for l in plot_divisors]\n",
+ " vals[i,] = y_values\n",
+ " ax.plot(x, y_values,\n",
+ " color=colors[mult],\n",
+ " linestyle=styles[mult],\n",
+ " marker=markers[mult],\n",
+ " label=str(mult) if mult.countermeasure is None else \"_nolegend_\")\n",
+ " if showci:\n",
+ " cis = [conf_interval(p, probmap.samples) for p in y_values]\n",
+ " ci_low = [ci[0] for ci in cis]\n",
+ " ci_high = [ci[1] for ci in cis]\n",
+ " ax.fill_between(x, ci_low, ci_high, color=\"black\", alpha=0.1)\n",
+ " n_samples += probmap.samples\n",
+ " \n",
+ " ax.set_title(f\"{divisor_name} ({kind})\\nSamples: \" + str(n_samples//N))\n",
+ " \n",
+ " #var = np.var(vals, axis=0)\n",
+ " #ax.plot(x, var / np.max(var), label=\"cross-mult variance (normalized)\", ls=\"--\", lw=2, color=\"black\")\n",
+ " \n",
+ " ax.set_xlabel(\"divisors\")\n",
+ " ax.set_ylabel(\"error probability\")\n",
+ " ax.set_yticks(majticks)\n",
+ " ax.set_yticks(minticks, minor=True)\n",
+ " ax.set_xticks(x, plot_divisors, rotation=90)\n",
+ " \n",
+ " ax.grid(axis=\"y\", which=\"major\", alpha=0.7)\n",
+ " ax.grid(axis=\"y\", which=\"minor\", alpha=0.3)\n",
+ " ax.grid(axis=\"x\", alpha=0.7)\n",
+ " plt.tight_layout()\n",
+ " box = ax.get_position()\n",
+ " ax.set_position([box.x0, box.y0, box.width * 0.9, box.height])\n",
+ " \n",
+ " ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n",
+ "\n",
+ " fig.savefig(f\"graphs/{kind}-kind/{divisor_name}-nocomb{'+ci' if showci else ''}.pdf\");\n",
+ " plt.close()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4068e7d0-addb-45d0-ba87-e572d4c82fbd",
+ "metadata": {},
+ "source": [
+ "## Plots (allmults)\n",
+ "Now, lets also do plots with allmults for all divisor groups."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9b9aa7a8-0d9d-4ce3-a936-8ced2948f562",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for divisor_name in divisor_map:\n",
+ " plot_mults = list(filter(lambda mult: mult in distributions_mults, all_mults_with_ctr))\n",
+ " print(divisor_name, \"allmults\")\n",
+ " plot_divisors = sorted(divisor_map[divisor_name])\n",
+ " L = len(plot_divisors)\n",
+ " N = len(plot_mults)\n",
+ " x = list(range(L))\n",
+ " \n",
+ " fig = plt.figure(figsize=(L/4+10, 26))\n",
+ " ax = plt.subplot(111)\n",
+ " \n",
+ " vals = np.zeros((N, L))\n",
+ " n_samples = 0\n",
+ " for i, mult in enumerate(plot_mults):\n",
+ " probmap = distributions_mults[mult]\n",
+ " y_values = [probmap[l] for l in plot_divisors]\n",
+ " vals[i,] = y_values\n",
+ " ax.plot(x, y_values,\n",
+ " color=colors[mult],\n",
+ " linestyle=styles[mult],\n",
+ " marker=markers[mult],\n",
+ " label=str(mult) if mult.countermeasure is None else \"_nolegend_\")\n",
+ " if showci:\n",
+ " cis = [conf_interval(p, probmap.samples) for p in y_values]\n",
+ " ci_low = [ci[0] for ci in cis]\n",
+ " ci_high = [ci[1] for ci in cis]\n",
+ " ax.fill_between(x, ci_low, ci_high, color=\"black\", alpha=0.1)\n",
+ " n_samples += probmap.samples\n",
+ " \n",
+ " ax.set_title(f\"{divisor_name} ({kind})\\nSamples(avg): \" + str(n_samples//N))\n",
+ " \n",
+ " #var = np.var(vals, axis=0)\n",
+ " #ax.plot(x, var / np.max(var), label=\"cross-mult variance (normalized)\", ls=\"--\", lw=2, color=\"black\")\n",
+ " \n",
+ " ax.set_xlabel(\"divisors\")\n",
+ " ax.set_ylabel(\"error probability\")\n",
+ " ax.set_yticks(majticks)\n",
+ " ax.set_yticks(minticks, minor=True)\n",
+ " ax.set_xticks(x, plot_divisors, rotation=90)\n",
+ " \n",
+ " ax.grid(axis=\"y\", which=\"major\", alpha=0.7)\n",
+ " ax.grid(axis=\"y\", which=\"minor\", alpha=0.3)\n",
+ " ax.grid(axis=\"x\", alpha=0.7)\n",
+ " plt.tight_layout()\n",
+ " box = ax.get_position()\n",
+ " ax.set_position([box.x0, box.y0, box.width * 0.9, box.height])\n",
+ " \n",
+ " ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n",
+ "\n",
+ " fig.savefig(f\"graphs/{kind}-kind/{divisor_name}-allmults{'+ci' if showci else ''}.pdf\")\n",
+ " plt.close()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "df2e236a-4540-4677-a7f1-563c4cc37a3e",
+ "metadata": {},
+ "source": [
+ "## Interactive plot\n",
+ "Below you can choose a concrete divisor set and visualize it with all the mults, or just some to your liking."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b464865d-b169-446e-a9e7-0cead699aee1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#divisor_name = \"powers_of_2_large\"\n",
+ "divisor_name = \"feature\"\n",
+ "plot_mults = list(filter(lambda mult: mult in distributions_mults, all_mults_with_ctr))\n",
+ "#plot_divisors = (61, 65, 111, 165, 1536, 12288) \n",
+ "plot_divisors = (55, 65, 165, 248, 3072)\n",
+ "L = len(plot_divisors)\n",
+ "N = len(plot_mults)\n",
+ "x = list(range(L))\n",
+ "\n",
+ "fig = plt.figure(figsize=(L/4+15, 24))\n",
+ "ax = plt.subplot(111)\n",
+ "\n",
+ "vals = np.zeros((N, L))\n",
+ "n_samples = 0\n",
+ "for i, mult in enumerate(plot_mults):\n",
+ " probmap = distributions_mults[mult]\n",
+ " y_values = [probmap[l] for l in plot_divisors]\n",
+ " vals[i,] = y_values\n",
+ " ax.plot(x, y_values,\n",
+ " color=colors[mult],\n",
+ " linestyle=styles[mult],\n",
+ " marker=markers[mult],\n",
+ " label=str(mult) if mult.countermeasure is None else \"_nolegend_\")\n",
+ " if showci:\n",
+ " cis = [conf_interval(p, probmap.samples) for p in y_values]\n",
+ " ci_low = [ci[0] for ci in cis]\n",
+ " ci_high = [ci[1] for ci in cis]\n",
+ " ax.fill_between(x, ci_low, ci_high, color=\"black\", alpha=0.1)\n",
+ " n_samples += probmap.samples\n",
+ "\n",
+ "ax.set_title(f\"{divisor_name} ({kind})\\nSamples(avg): \" + str(n_samples//N))\n",
+ "\n",
+ "#var = np.var(vals, axis=0)\n",
+ "#ax.plot(x, var / np.max(var), label=\"cross-mult variance (normalized)\", ls=\"--\", lw=2, color=\"black\")\n",
+ "\n",
+ "ax.set_xlabel(\"divisors\")\n",
+ "ax.set_ylabel(\"error probability\")\n",
+ "ax.set_yticks(majticks)\n",
+ "ax.set_yticks(minticks, minor=True)\n",
+ "ax.set_xticks(x, plot_divisors, rotation=90)\n",
+ "\n",
+ "ax.grid(axis=\"y\", which=\"major\", alpha=0.7)\n",
+ "ax.grid(axis=\"y\", which=\"minor\", alpha=0.3)\n",
+ "ax.grid(axis=\"x\", alpha=0.7)\n",
+ "plt.tight_layout()\n",
+ "box = ax.get_position()\n",
+ "ax.set_position([box.x0, box.y0, box.width * 0.7, box.height])\n",
+ "\n",
+ "# Put a legend to the right of the current axis\n",
+ "ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d68f0bfc-cdf1-4891-b0e5-0b6d1b02ded7",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}