aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2025-03-15 00:52:44 +0100
committerJ08nY2025-04-16 12:25:06 +0200
commitd1e7eae1889a054d2aca398c0b8537de94263556 (patch)
tree4c06e567c91dce77657e108a19d4b7ed123a6f09
parentd32571bf09da8963b3597dca95818f300c96223d (diff)
downloadECTester-d1e7eae1889a054d2aca398c0b8537de94263556.tar.gz
ECTester-d1e7eae1889a054d2aca398c0b8537de94263556.tar.zst
ECTester-d1e7eae1889a054d2aca398c0b8537de94263556.zip
-rw-r--r--epare/collect_leia.ipynb230
-rw-r--r--epare/simulate.ipynb17
-rw-r--r--epare/visualize.ipynb680
3 files changed, 367 insertions, 560 deletions
diff --git a/epare/collect_leia.ipynb b/epare/collect_leia.ipynb
index e54e643..00d2efc 100644
--- a/epare/collect_leia.ipynb
+++ b/epare/collect_leia.ipynb
@@ -1,6 +1,14 @@
{
"cells": [
{
+ "cell_type": "markdown",
+ "id": "fde96d6a-0281-4ba2-ae2f-447cb6a625f0",
+ "metadata": {},
+ "source": [
+ "# Power-tracing smartcards using LEIA"
+ ]
+ },
+ {
"cell_type": "code",
"execution_count": null,
"id": "eab24cb8-af40-4cc1-be5f-f120fe9932ee",
@@ -11,7 +19,7 @@
"from pyecsca.ec.params import load_params_ectester\n",
"from pyecsca.sca.scope.picoscope_sdk import PS6000Scope\n",
"from pyecsca.sca.trace import Trace\n",
- "from pyecsca.sca.trace.plot import plot_trace\n",
+ "from pyecsca.sca.trace.plot import plot_trace, plot_traces\n",
"from pyecsca.sca.scope import SampleType\n",
"\n",
"import numpy as np\n",
@@ -21,7 +29,7 @@
"import holoviews as hv\n",
"\n",
"hv.extension(\"bokeh\")\n",
- "%opts RGB [height=600, responsive=True]"
+ "%opts RGB [height=700, responsive=True]"
]
},
{
@@ -31,73 +39,132 @@
"metadata": {},
"outputs": [],
"source": [
- "sl = LEIA()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "885fba43-7546-48ba-bff4-b6314fd642e6",
- "metadata": {},
- "outputs": [],
- "source": [
+ "sl = LEIA()\n",
"ectester = ECTesterTargetLEIA(sl)"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "8c33b783-7a7e-45f4-9e91-d3df54e1abe0",
+ "id": "07369045-7eee-4e85-ac4e-37e5396fd880",
"metadata": {},
"outputs": [],
"source": [
- "scope = PS6000Scope()"
+ "ectester.connect()"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "729688c3-d448-4d1a-80c4-666680fcca35",
+ "id": "89ed5db7-fbbb-4b32-89a5-6486204feed6",
"metadata": {},
"outputs": [],
"source": [
- "scope.open()"
+ "atr = ectester.atr\n",
+ "print(atr, atr.hex())\n",
+ "card_map = {\n",
+ " \"3bd518ff8191fe1fc38073c8211309\": \"A1\",\n",
+ " \"3bb89600c00831fe45ffff1154305023006a\": \"I1\",\n",
+ " \"3bfe1800008031fe45803180664090a5102e1083019000f2\": \"I2\",\n",
+ " \"3bf81800ff8131fe454a434f507632343143\": \"N1\",\n",
+ " \"3bf81300008131fe454a434f5076323431b7\": \"N2N9\",\n",
+ " \"3b9495810146545601c4\": \"N4\",\n",
+ " \"3bd518ff8191fe1fc38073c821100a\": \"N6\",\n",
+ "}\n",
+ "card = card_map[atr.hex()]\n",
+ "print(card)"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "23037143-e39c-4dd6-bf65-9cdcb0d7b266",
+ "id": "8c33b783-7a7e-45f4-9e91-d3df54e1abe0",
"metadata": {},
"outputs": [],
"source": [
- "print(scope.get_variant())\n",
- "actual_freq, n_samples = scope.setup_frequency(frequency=250_000_000, pretrig=0, posttrig=150_000_000)\n",
- "scope.setup_channel(channel=\"A\", coupling=\"DC\", range=1, offset=0, enable=True)\n",
- "scope.setup_channel(channel=\"B\", coupling=\"DC\", range=0.1, offset=-0.4, enable=True)\n",
- "scope.setup_trigger(channel=\"A\", threshold=0.2, direction=\"rising\", delay=0, timeout=5000, enable=True)\n",
- "scope.setup_capture(channel=\"B\", enable=True)\n",
- "print(actual_freq, n_samples)"
+ "scope = PS6000Scope()"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "07369045-7eee-4e85-ac4e-37e5396fd880",
+ "id": "729688c3-d448-4d1a-80c4-666680fcca35",
"metadata": {},
"outputs": [],
"source": [
- "ectester.connect()"
+ "scope.open()"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "89ed5db7-fbbb-4b32-89a5-6486204feed6",
+ "id": "23037143-e39c-4dd6-bf65-9cdcb0d7b266",
"metadata": {},
"outputs": [],
"source": [
- "ectester.atr"
+ "print(scope.get_variant())\n",
+ "if card == \"A1\":\n",
+ " # Athena IDProtect\n",
+ " # 35M for keygen\n",
+ " # 13M for ecdh\n",
+ " actual_freq, n_samples = scope.setup_frequency(frequency=50_000_000, pretrig=0, posttrig=35_000_000)\n",
+ " scope.setup_channel(channel=\"A\", coupling=\"DC\", range=1, offset=0, enable=True)\n",
+ " scope.setup_channel(channel=\"B\", coupling=\"DC_50\", range=0.2, offset=-0.24, enable=True)\n",
+ " scope.setup_trigger(channel=\"A\", threshold=0.2, direction=\"rising\", delay=0, timeout=5000, enable=True)\n",
+ " scope.setup_capture(channel=\"B\", enable=True)\n",
+ "elif card == \"I1\":\n",
+ " # Infineon SECORA\n",
+ " # 6M for keygen\n",
+ " # 3M for ecdh\n",
+ " actual_freq, n_samples = scope.setup_frequency(frequency=50_000_000, pretrig=0, posttrig=6_000_000)\n",
+ " scope.setup_channel(channel=\"A\", coupling=\"DC\", range=1, offset=0, enable=True)\n",
+ " scope.setup_channel(channel=\"B\", coupling=\"DC_50\", range=0.2, offset=-0.25, enable=True)\n",
+ " scope.setup_trigger(channel=\"A\", threshold=0.2, direction=\"rising\", delay=0, timeout=5000, enable=True)\n",
+ " scope.setup_capture(channel=\"B\", enable=True)\n",
+ "elif card == \"I2\":\n",
+ " # Infineon CJTOP SLJ 52GLA0890AL M84\n",
+ " actual_freq, n_samples = scope.setup_frequency(frequency=50_000_000, pretrig=0, posttrig=15_000_000)\n",
+ " scope.setup_channel(channel=\"A\", coupling=\"DC\", range=1, offset=0, enable=True)\n",
+ " scope.setup_channel(channel=\"B\", coupling=\"DC_50\", range=0.1, offset=-0.15, enable=True)\n",
+ " scope.setup_trigger(channel=\"A\", threshold=0.2, direction=\"rising\", delay=0, timeout=5000, enable=True)\n",
+ " scope.setup_capture(channel=\"B\", enable=True)\n",
+ "elif card == \"N1\":\n",
+ " # NXP J3A081\n",
+ " # 30M for keygen (first), then 10M for subsequent\n",
+ " # 10M for ecdh\n",
+ " actual_freq, n_samples = scope.setup_frequency(frequency=50_000_000, pretrig=0, posttrig=30_000_000)\n",
+ " scope.setup_channel(channel=\"A\", coupling=\"DC\", range=1, offset=0, enable=True)\n",
+ " scope.setup_channel(channel=\"B\", coupling=\"DC_50\", range=0.05, offset=-0.18, enable=True)\n",
+ " scope.setup_trigger(channel=\"A\", threshold=0.2, direction=\"rising\", delay=0, timeout=5000, enable=True)\n",
+ " scope.setup_capture(channel=\"B\", enable=True)\n",
+ "elif card == \"N2N9\":\n",
+ " # NXP JCOP v2.4.1R3\n",
+ " actual_freq, n_samples = scope.setup_frequency(frequency=50_000_000, pretrig=0, posttrig=30_000_000)\n",
+ " scope.setup_channel(channel=\"A\", coupling=\"DC\", range=1, offset=0, enable=True)\n",
+ " scope.setup_channel(channel=\"B\", coupling=\"DC_50\", range=0.05, offset=-0.280, enable=True)\n",
+ " scope.setup_trigger(channel=\"A\", threshold=0.2, direction=\"rising\", delay=0, timeout=5000, enable=True)\n",
+ " scope.setup_capture(channel=\"B\", enable=True)\n",
+ "elif card == \"N4\":\n",
+ " # NXP J3H145\n",
+ " # 15M for keygen\n",
+ " # 10M for ecdh\n",
+ " actual_freq, n_samples = scope.setup_frequency(frequency=50_000_000, pretrig=0, posttrig=5_000_000)\n",
+ " scope.setup_channel(channel=\"A\", coupling=\"DC\", range=1, offset=0, enable=True)\n",
+ " scope.setup_channel(channel=\"B\", coupling=\"DC_50\", range=0.2, offset=-0.160, enable=True)\n",
+ " scope.setup_trigger(channel=\"A\", threshold=0.2, direction=\"rising\", delay=0, timeout=5000, enable=True)\n",
+ " scope.setup_capture(channel=\"B\", enable=True)\n",
+ "elif card == \"N6\":\n",
+ " # NXP JCOP4\n",
+ " # 3M for keygen\n",
+ " # 3M for ECDH\n",
+ " actual_freq, n_samples = scope.setup_frequency(frequency=50_000_000, pretrig=0, posttrig=3_000_000)\n",
+ " scope.setup_channel(channel=\"A\", coupling=\"DC\", range=1, offset=0, enable=True)\n",
+ " scope.setup_channel(channel=\"B\", coupling=\"DC_50\", range=0.2, offset=-0.170, enable=True)\n",
+ " scope.setup_trigger(channel=\"A\", threshold=0.2, direction=\"rising\", delay=0, timeout=5000, enable=True)\n",
+ " scope.setup_capture(channel=\"B\", enable=True)\n",
+ "\n",
+ "\n",
+ "print(actual_freq, n_samples)"
]
},
{
@@ -128,7 +195,7 @@
"outputs": [],
"source": [
"ectester.allocate(KeypairEnum.KEYPAIR_LOCAL,\n",
- " KeyBuildEnum.BUILD_KEYPAIR,\n",
+ " KeyBuildEnum.BUILD_KEYBUILDER | KeyBuildEnum.BUILD_KEYPAIR,\n",
" 256,\n",
" KeyClassEnum.ALG_EC_FP)"
]
@@ -150,7 +217,7 @@
"metadata": {},
"outputs": [],
"source": [
- "params = load_params_ectester(\"../common/src/main/resources/cz/crcs/ectester/data/secg/secp256r1.csv\", \"affine\")"
+ "params = load_params_ectester(\"curves/curves_full_order/cofactor256p313_full.csv\", \"affine\")"
]
},
{
@@ -214,7 +281,7 @@
"metadata": {},
"outputs": [],
"source": [
- "trace_gen = scope.retrieve(\"B\", SampleType.Volt)"
+ "trace_gen = scope.retrieve(\"B\", SampleType.Raw)"
]
},
{
@@ -241,6 +308,22 @@
{
"cell_type": "code",
"execution_count": null,
+ "id": "f4c1df63-4da3-4693-9aaa-217e4a9314f5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"curves/cofactor_points/point_313.csv\", \"r\") as f:\n",
+ " line = f.read()\n",
+ " sx, sy = line.split(\",\")\n",
+ " bx = bytes.fromhex(sx[2:])\n",
+ " by = bytes.fromhex(sy[2:])\n",
+ " point = bytes([0x04]) + bx + by\n",
+ " print(point.hex())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
"id": "ad17301a-902f-48e9-936e-f553a1a8f006",
"metadata": {},
"outputs": [],
@@ -249,7 +332,7 @@
" True,\n",
" TransformationEnum.NONE,\n",
" KeyAgreementEnum.ALG_EC_SVDP_DH,\n",
- " bytes.fromhex(\"046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5\")) # pubkey as bytes"
+ " point) # pubkey as bytes"
]
},
{
@@ -285,6 +368,77 @@
{
"cell_type": "code",
"execution_count": null,
+ "id": "6c46be4f-8901-4b29-a30e-71ac28bafcd9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from pyecsca.sca.trace.edit import pad, trim"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1d4b775e-fa7d-48aa-bb24-bec7450c8114",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "trim?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7164dab5-090f-4a6a-9ce6-8e252e71af76",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_traces(ecdh_ok, pad(trim(trace_ecdh, 0, len(trace_ecdh) -363700), (363700, 0)))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "0395b2aa-3c00-4068-8179-039e7e5ad039",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from scipy import signal\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1b63e6d3-8488-4c13-91fa-388318e8e1bc",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "corr = signal.correlate(trace_ecdh.samples, trace_ecdh.samples, mode=\"full\")\n",
+ "lags = signal.correlation_lags(trace_ecdh.samples.size, trace_ecdh.samples.size, mode=\"full\")\n",
+ "lag = lags[np.argmax(corr)]\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f6fbd522-c9db-4dbc-bd05-109ba3d3fdf9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_trace(Trace(corr))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5a910cc9-80bd-4c74-a36a-56804aea42e1",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
"id": "195ed167-8925-44c9-b0fb-6e207f8fdf8a",
"metadata": {},
"outputs": [],
@@ -326,7 +480,17 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "2c62eccf-eae1-48be-b562-222504e8e6cf",
+ "id": "d93ce9cd-1516-4e32-9fed-94a19fac23f4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from pyecsca.sca.trace.plot import plot_trace, plot_traces"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "45f2a8ab-af15-46f9-904e-76e5eeb08978",
"metadata": {},
"outputs": [],
"source": []
diff --git a/epare/simulate.ipynb b/epare/simulate.ipynb
index 4a0a07a..89a5533 100644
--- a/epare/simulate.ipynb
+++ b/epare/simulate.ipynb
@@ -89,10 +89,11 @@
"def get_small_scalar_multiples(mult: MultIdent,\n",
" params: DomainParameters,\n",
" bits: int,\n",
- " samples: int = 1000,\n",
+ " samples: int = 100,\n",
" use_init: bool = True,\n",
" use_multiply: bool = True,\n",
- " seed: bytes | None = None) -> MultResults:\n",
+ " seed: bytes | None = None,\n",
+ " kind: str = \"precomp+necessary\") -> MultResults:\n",
" from pyecsca.sca.re.rpa import multiples_computed\n",
" import random\n",
" \n",
@@ -110,7 +111,7 @@
"\n",
" for scalar in scalars:\n",
" # Use a list for less memory usage.\n",
- " results.append(list(multiples_computed(scalar, params, mult.klass, mult.partial, use_init, use_multiply)))\n",
+ " results.append(list(multiples_computed(scalar, params, mult.klass, mult.partial, use_init, use_multiply, kind=kind)))\n",
" return MultResults(results, samples)"
]
},
@@ -134,7 +135,7 @@
"params = get_params(category, curve, \"projective\")\n",
"num_workers = 20\n",
"bits = params.order.bit_length()\n",
- "samples = 1000\n",
+ "samples = 100\n",
"selected_mults = all_mults"
]
},
@@ -166,7 +167,7 @@
" for mult, future in tqdm(pool.as_completed(), desc=\"Computing small scalar distributions.\", total=len(pool.tasks)):\n",
" print(f\"Got {mult}.\")\n",
" if error := future.exception():\n",
- " print(error)\n",
+ " print(\"Error!\", error)\n",
" continue\n",
" res = future.result()\n",
" if mult not in multiples_mults:\n",
@@ -188,7 +189,9 @@
"metadata": {},
"source": [
"### Load\n",
- "Beware, the following load with try to load all chunks into memory, that will be very large."
+ "**Beware**, the following load with try to load all chunks into memory, that will be very large.\n",
+ "\n",
+ "You probably dont want to run this."
]
},
{
@@ -212,7 +215,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "264385f2-0f58-4f18-bfc2-61f2c5b6e5c8",
+ "id": "11b447f2-71ab-417e-a856-1724788cfc91",
"metadata": {},
"outputs": [],
"source": []
diff --git a/epare/visualize.ipynb b/epare/visualize.ipynb
index 4b74e30..743c35f 100644
--- a/epare/visualize.ipynb
+++ b/epare/visualize.ipynb
@@ -1,6 +1,14 @@
{
"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",
@@ -33,6 +41,15 @@
]
},
{
+ "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",
@@ -42,14 +59,23 @@
"# 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\", \"+\", \"*\", \"^\"]\n",
"colors = {}\n",
"styles = {}\n",
+ "markers = {}\n",
"for mult in all_mults:\n",
- " colors[mult] = mult_colors[mult_klasses.index(mult.klass)]\n",
- " styles[mult] = mult_styles[mult_kwarg_map[mult.klass]]\n",
- " mult_kwarg_map[mult.klass] += 1"
+ " 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\"):\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"
]
},
{
@@ -67,13 +93,30 @@
"\n",
"def process_small_scalars(scalar_results: MultResults, divisors: set[int]) -> ProbMap:\n",
" result = {}\n",
- " for divisor in tqdm(divisors, leave=False):\n",
+ " for divisor in divisors:\n",
" count = 0\n",
" for smult in scalar_results.multiplications:\n",
" if divides_any(divisor, smult):\n",
" count += 1\n",
" result[divisor] = count / scalar_results.samples\n",
- " return ProbMap(result, scalar_results.samples)"
+ " return ProbMap(result, scalar_results.samples)\n",
+ "\n",
+ "def load_chunk(fname: str, divisors: set[int]) -> dict[MultIdent, ProbMap]:\n",
+ " with open(fname, \"rb\") as f:\n",
+ " multiples = pickle.load(f)\n",
+ " res = {}\n",
+ " for mult, results in multiples.items():\n",
+ " res[mult] = process_small_scalars(results, divisors)\n",
+ " return res"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2596562f-8a6a-4a25-ae82-a6b9562d8a40",
+ "metadata": {},
+ "source": [
+ "## Divisors\n",
+ "The cell below contains some interesting divisors for distinguishing scalarmults."
]
},
{
@@ -106,11 +149,24 @@
" \"all_even\": all_even,\n",
" \"all_odd\": all_odd,\n",
" \"powers_of_2\": powers_of(2),\n",
- " \"powers_of_2_large\": powers_of(2, 130),\n",
- " \"powers_of_2_large_p1\": [i+1 for i in powers_of(2, 130)],\n",
+ " \"powers_of_2_large\": powers_of(2, 140),\n",
+ " \"powers_of_2_large_3\": [i * 3 for i in powers_of(2, 140)],\n",
+ " \"powers_of_2_large_p1\": [i + 1 for i in powers_of(2, 140)],\n",
+ " \"powers_of_2_large_m1\": [i - 1 for i in powers_of(2, 140)],\n",
+ " \"powers_of_2_large_pmautobus\": sorted(set([i+j for i in powers_of(2, 140) for j in range(-8,8) if i+j > 0])),\n",
" \"powers_of_3\": powers_of(3),\n",
"}\n",
- "divisor_map[\"all\"] = list(sorted(set().union(*[v for v in divisor_map.values()])))"
+ "divisor_map[\"all\"] = list(sorted(set().union(*[v for v in divisor_map.values()])))\n",
+ "for d, ds in divisor_map.items():\n",
+ " print(d, len(ds))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "51aa1d77-2ea5-49b4-8d2b-c73b88947430",
+ "metadata": {},
+ "source": [
+ "Even though we list `secp256r1` here, it is only an API choice, the curve is not used for anything. The number 256 might as well be in its place."
]
},
{
@@ -124,7 +180,15 @@
"curve = \"secp256r1\"\n",
"params = get_params(category, curve, \"projective\")\n",
"bits = params.order.bit_length()\n",
- "num_workers = 10"
+ "num_workers = 28"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5b427252-a3ff-4a55-940c-3c8659caa799",
+ "metadata": {},
+ "source": [
+ "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."
]
},
{
@@ -135,7 +199,7 @@
"outputs": [],
"source": [
"selected_mults = all_mults\n",
- "divisor_name = \"powers_of_2_large_p1\"\n",
+ "divisor_name = \"all\"\n",
"selected_divisors = divisor_map[divisor_name]"
]
},
@@ -147,571 +211,147 @@
"outputs": [],
"source": [
"distributions_mults = {}\n",
- "files = tqdm(glob.glob(f\"multiples_{category}_{curve}_{bits}_chunk*.pickle\"))\n",
+ "files = sorted(glob.glob(f\"multiples_{category}_{curve}_{bits}_ctr_chunk*.pickle\"))\n",
"with TaskExecutor(max_workers=num_workers) as pool:\n",
" for fname in files:\n",
- " files.set_postfix_str(fname)\n",
- " with open(fname, \"rb\") as f:\n",
- " multiples_loaded = pickle.load(f)\n",
- " for mult, results in multiples_loaded.items():\n",
- " pool.submit_task(mult,\n",
- " process_small_scalars,\n",
- " results, selected_divisors)\n",
- " for mult, future in tqdm(pool.as_completed(), leave=False, total=len(pool.tasks)):\n",
- " prob_map = future.result()\n",
+ " pool.submit_task(fname,\n",
+ " load_chunk,\n",
+ " fname, selected_divisors)\n",
+ " for fname, future in tqdm(pool.as_completed(), leave=False, total=len(pool.tasks), smoothing=0):\n",
+ " if error := future.exception():\n",
+ " print(f\"Error {fname}, {error}\")\n",
+ " continue\n",
+ " new_distrs = future.result()\n",
+ " for mult, prob_map in new_distrs.items():\n",
" if mult in distributions_mults:\n",
" distributions_mults[mult].merge(prob_map)\n",
" else:\n",
" distributions_mults[mult] = prob_map\n",
- " del multiples_loaded\n",
- " gc.collect()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "906b5d78-b3a4-4cbb-8051-092d411ba735",
- "metadata": {},
- "outputs": [],
- "source": [
- "plot_mults = selected_mults\n",
- "plot_divisors = selected_divisors\n",
- "\n",
- "fig = plt.figure(figsize=(58, 12))\n",
- "ax = plt.subplot(111)\n",
- "\n",
- "L = len(plot_divisors)\n",
- "N = len(plot_mults)\n",
- "plot_divisors = sorted(plot_divisors)\n",
- "vals = np.zeros((N, L))\n",
- "for i, mult in enumerate(plot_mults):\n",
- " y_values = [distributions_mults[mult][l] for l in plot_divisors]\n",
- " vals[i,] = y_values\n",
- " ax.plot(list(range(L)), y_values, color=colors[mult], linestyle=styles[mult], label=str(mult))\n",
- " ax.set_title(divisor_name + \"\\nSamples: \" + str(distributions_mults[mult].samples))\n",
- "\n",
- "var = np.var(vals, axis=0)\n",
- "#ax.plot(list(range(L)), 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_xticks(list(range(L)), plot_divisors, rotation=90)\n",
- "\n",
- "ax.grid()\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",
- "# 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()\n",
- "fig.savefig(f\"graphs/{divisor_name}.png\",dpi=300);"
+ "# Save\n",
+ "with open(f\"{divisor_name}_distrs.pickle\", \"wb\") as f:\n",
+ " pickle.dump(distributions_mults, f)"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "8454cb7a-5308-43c6-9cd0-5de7946ec72a",
+ "id": "19d986ab-5fe7-4dd6-b5b5-4e75307217d6",
"metadata": {},
"outputs": [],
"source": [
- "# general_distributions = get_general_distributions(selected_divisors, bits, samples)\n",
- "# general_n_distributions = get_general_n_distributions(selected_divisors, bits, 256, samples)"
+ "# Optionally, load\n",
+ "with open(f\"{divisor_name}_distrs.pickle\", \"rb\") as f:\n",
+ " distributions_mults = pickle.load(f)"
]
},
{
- "cell_type": "code",
- "execution_count": null,
- "id": "90a654f0-accc-4bb9-be2d-5f03e2d1e543",
- "metadata": {},
- "outputs": [],
- "source": [
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "b7fcd473-6cde-4913-9274-ff02f5ddb786",
- "metadata": {},
- "outputs": [],
- "source": [
- "plot_mults = [mult for mult in selected_mults if mult.klass not in (CombMultiplier, BGMWMultiplier)]\n",
- "plot_divisors = selected_divisors\n",
- "\n",
- "colors = {mult:matplotlib.cm.tab20(range(len(plot_mults)))[i] for i,mult in enumerate(plot_mults)}\n",
- "\n",
- "fig = plt.subplots(figsize=(36, 12))\n",
- "\n",
- "L = len(plot_divisors)\n",
- "N = len(plot_mults)\n",
- "plot_divisors = sorted(plot_divisors)\n",
- "vals = np.zeros((N, L))\n",
- "for i, mult in enumerate(plot_mults):\n",
- " for j, m in enumerate(plot_divisors):\n",
- " y = distributions_mults[mult][m]\n",
- " vals[i, j] = y\n",
- "var = np.var(vals, axis=0)\n",
- "plt.plot(list(range(L)), var, label=\"cross-mult variance\", ls=\"--\", lw=2, color=\"black\")\n",
- "\n",
- "plt.xlabel(\"divisors\")\n",
- "plt.ylabel(\"variance\")\n",
- "plt.xticks(list(range(L)), plot_divisors, rotation=90)\n",
- "\n",
- "plt.grid()\n",
- "plt.legend()\n",
- "plt.show() \n",
- "fig[0].savefig(f\"graphs/cross_var.png\",dpi=300)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "8eae8df8-0bf8-4a9d-a55e-deea6a9d6b07",
- "metadata": {},
- "outputs": [],
- "source": [
- "\n",
- "selected_mults = all_mults#window_mults[0:1]+window_mults[5:6]+naf_mults[1:2]#[mult for mult in all_mults if not mult in comb_mults]\n",
- "selected_divisors = all_divisors\n",
- "colors = {mult:matplotlib.cm.tab20(range(len(distributions_mults_10k)))[i] for i,mult in enumerate(distributions_mults_10k)}\n",
- "\n",
- "\n",
- "fig = plt.subplots(figsize =(36, 12)) \n",
- "\n",
- "L = len(selected_divisors)\n",
- "selected_divisors = sorted(selected_divisors)\n",
- "for mult in distributions_mults_10k:\n",
- " y_values = [distributions_mults_10k[mult][l] for l in selected_divisors]\n",
- " plt.plot([l for l in range(L)],y_values,color = colors[mult], label = mult_label(mult))\n",
- "\n",
- "# mult = list(fixedwindow_dist.keys())[0]\n",
- "# plt.plot([l for l in range(L)],[fixedwindow_dist[l] for l in selected_divisors],color = \"pink\", label = mult_label(mult))\n",
- "\n",
- "# measured_dist = measured_distribution(library,selected_divisors)\n",
- "# mes_x, mes_y = [],[]\n",
- "# for i,l in enumerate(selected_divisors):\n",
- "# if l in measured_dist:\n",
- "# mes_y.append(measured_dist[l])\n",
- "# mes_x.append(i)\n",
- "# plt.scatter(mes_x,mes_y,color = \"black\", label = library)\n",
- "\n",
- "#attempts = 0\n",
- "#fails =0\n",
- "#for i in range(51):\n",
- "# with open(f\"cards/jcop/199_{i}.txt\") as f:\n",
- "# attempts += f.read().count(\"ALG_EC_SVDP_DH of remote pubkey and local privkey\")+1\n",
- "# fails += 1\n",
- "#plt.scatter([selected_divisors.index(199)],[fails/attempts],s=[40],color = \"black\", label = \"jcop\")\n",
- "\n",
- "#plt.plot([l for l in range(L)],[general_distributions[l] for l in selected_divisors],color = \"black\", label = \"prime-distribution\")\n",
- "\n",
- "\n",
- "plt.xlabel('divisors') \n",
- "plt.ylabel(\"prob\") \n",
- "plt.xticks([r for r in range(L)], selected_divisors)\n",
- "\n",
- "plt.legend()\n",
- "plt.show() \n",
- "fig[0].savefig(f\"graphs/re.png\",dpi=300)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "d240059f-9ed6-4864-b4bf-525de576272f",
+ "cell_type": "markdown",
+ "id": "ef5b7a43-74b4-4e72-a3a1-955e175f5297",
"metadata": {},
- "outputs": [],
"source": [
- "selected_mults = with_precomputation\n",
- "selected_divisors = all_divisors\n",
- "colors = {mult:matplotlib.cm.tab20(range(len(selected_mults)))[i] for i,mult in enumerate(selected_mults)}\n",
- "\n",
- "\n",
- "fig = plt.subplots(figsize =(24, 12)) \n",
- "\n",
- "L = len(selected_divisors)\n",
- "selected_divisors = sorted(selected_divisors)\n",
- "for mult in selected_mults:\n",
- " plt.plot([l for l in range(L)],[distributions_mults_precomp[mult][l] for l in selected_divisors],color = colors[mult], label = mult_label(mult))\n",
- "\n",
- "\n",
- "#measured_dist = measured_distribution(library,selected_divisors)\n",
- "#mes_x, mes_y = [],[]\n",
- "#for i,l in enumerate(selected_divisors):\n",
- "# if l in measured_dist:\n",
- "# mes_y.append(measured_dist[l])\n",
- "# mes_x.append(i)\n",
- "#plt.scatter(mes_x,mes_y,color = \"black\", label = library)\n",
- "\n",
- "\n",
- "plt.xlabel('divisors') \n",
- "plt.ylabel(\"prob\") \n",
- "plt.xticks([r for r in range(L)], selected_divisors)\n",
- "\n",
- "plt.legend()\n",
- "plt.show() "
+ "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": "0da0eed4-a5dc-4dde-9bd1-8b519d02375e",
+ "id": "906b5d78-b3a4-4cbb-8051-092d411ba735",
"metadata": {},
"outputs": [],
"source": [
- "def nok_ecdh(line):\n",
- " return int(line.split(\";\")[-1].strip(),16)==0\n",
- "\n",
- "def measured_distribution(library, selected_divisors):\n",
- " measured_distribution = {}\n",
- " counts = {order:0 for order in selected_divisors}\n",
- " for div in selected_divisors:\n",
- " errors = 0\n",
- " with open(f\"./ecdh/{library}/ecdh_{div}.txt\") as f:\n",
- " for line in f.readlines()[1:]:\n",
- " if nok_ecdh(line):\n",
- " errors+=1\n",
- " counts[div]+=1\n",
- " measured_distribution[div] = errors\n",
+ "for divisor_name in divisor_map:\n",
+ " plot_mults = [mult.with_countermeasure(cm) for mult in selected_mults for cm in (None, \"gsr\", \"additive\", \"multiplicative\", \"euclidean\") if mult.klass not in (BGMWMultiplier, CombMultiplier)]\n",
+ " print(divisor_name)\n",
+ " plot_divisors = sorted(divisor_map[divisor_name])\n",
+ " L = len(plot_divisors)\n",
+ " N = len(plot_mults)\n",
" \n",
- " for o,v in measured_distribution.items():\n",
- " if counts[o]!=0:\n",
- " measured_distribution[o] = v/counts[o]\n",
- " return measured_distribution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "6f8b83e3-7e2e-409a-82bd-7d44316236c6",
- "metadata": {},
- "outputs": [],
- "source": [
- "selected_mults = other_mults[:1]+binary_mults[:1]+comb_mults[:1]+window_mults[:1]\n",
- "selected_divisors = small_primes#all_divisors\n",
- "library = \"tomcrypt\"\n",
- "colors = {mult:matplotlib.cm.tab20(range(len(selected_mults)))[i] for i,mult in enumerate(selected_mults)}\n",
- "\n",
- "fig = plt.subplots(figsize =(24, 12)) \n",
- "\n",
- "L = len(selected_divisors)\n",
- "selected_divisors = sorted(selected_divisors)\n",
- "for mult in selected_mults:\n",
- " plt.plot([l for l in range(L)],[distributions_mults[mult][l] for l in selected_divisors],color = colors[mult], label = mult_label(mult))\n",
- "\n",
- "\n",
- "measured_dist = measured_distribution(library,selected_divisors)\n",
- "mes_x, mes_y = [],[]\n",
- "for i,l in enumerate(selected_divisors):\n",
- " if l in measured_dist:\n",
- " mes_y.append(measured_dist[l])\n",
- " mes_x.append(i)\n",
- "plt.scatter(mes_x,mes_y,color = \"black\", label = library)\n",
- "\n",
- "\n",
- "plt.xlabel('divisors') \n",
- "plt.ylabel(\"prob\") \n",
- "plt.xticks([r for r in range(L)], selected_divisors)\n",
- "plt.legend(loc=\"upper right\")\n",
- "plt.show() \n",
- "fig[0].savefig(f\"graphs/{library}/re.png\",dpi=300)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "b7936e5b-76d2-410f-82b1-36333071bd12",
- "metadata": {},
- "outputs": [],
- "source": [
- "selected_mults = [mult for mult in with_precomputation if mult in comb_mults]\n",
- "selected_divisors = small_primes#all_divisors\n",
- "library = \"mbedtls\"\n",
- "colors = {mult:matplotlib.cm.tab20(range(len(selected_mults)))[i] for i,mult in enumerate(selected_mults)}\n",
- "\n",
- "fig = plt.subplots(figsize =(24, 12)) \n",
- "\n",
- "L = len(selected_divisors)\n",
- "selected_divisors = sorted(selected_divisors)\n",
- "for mult in selected_mults:\n",
- " plt.plot([l for l in range(L)],[distributions_mults_precomp[mult][l] for l in selected_divisors],color = colors[mult], label = mult_label(mult))\n",
- "\n",
- "\n",
- "measured_dist = measured_distribution(library,selected_divisors)\n",
- "mes_x, mes_y = [],[]\n",
- "for i,l in enumerate(selected_divisors):\n",
- " if l in measured_dist:\n",
- " mes_y.append(measured_dist[l])\n",
- " mes_x.append(i)\n",
- "plt.scatter(mes_x,mes_y,color = \"black\", label = library)\n",
- "\n",
- "plt.xlabel('divisors') \n",
- "plt.ylabel(\"prob\") \n",
- "plt.xticks([r for r in range(L)], selected_divisors)\n",
- "plt.legend()\n",
- "plt.show() \n",
- "fig[0].savefig(f\"graphs/{library}/re.png\",dpi=300)"
+ " 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",
+ " y_values = [distributions_mults[mult][l] for l in plot_divisors]\n",
+ " vals[i,] = y_values\n",
+ " ax.plot(list(range(L)), y_values, color=colors[mult], linestyle=styles[mult], marker=markers[mult], label=str(mult))\n",
+ " n_samples += distributions_mults[mult].samples\n",
+ " \n",
+ " ax.set_title(divisor_name + \"\\nSamples(avg): \" + str(n_samples//N))\n",
+ " \n",
+ " var = np.var(vals, axis=0)\n",
+ " ax.plot(list(range(L)), 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_xticks(list(range(L)), plot_divisors, rotation=90)\n",
+ " \n",
+ " ax.grid()\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), prop={'size': 6})\n",
+ " plt.close()\n",
+ " fig.savefig(f\"graphs/{divisor_name}_nocomb.png\",dpi=300);"
]
},
{
"cell_type": "markdown",
- "id": "dbdd0219-3937-4ef3-8cb3-b90f03af9977",
- "metadata": {},
- "source": [
- "BouncyCastle\n",
- " - WindowBooth-5?\n",
- "\n",
- "Mbedtls\n",
- " - CombMultiplier-4\n",
- " - confirmed in library\n",
- " \n",
- "tomcrypt\n",
- " - ladder or coron\n",
- " - ladder confirmed in library\n",
- "\n",
- "OpenSSL, LibreSSL, Botan, Crypto++ and IPPCP followed the general distribution of divisibility by the primes. So they have some countermeasure.\n",
- "\n",
- "Note that some libraries for some orders output \"Invalid algorithm parameter: Not supported.\". For libcrypt, SunEC and Nettle it happened for all orders.\n",
- "BoringSSL\n",
- " - \"Invalid algorithm parameter: Error creating EC_GROUP, EC_GROUP_set_generator.\"\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "34609ae2-fa8c-4437-a601-cd25a0708a19",
+ "id": "df2e236a-4540-4677-a7f1-563c4cc37a3e",
"metadata": {},
- "outputs": [],
"source": [
- "def scatter(library, color):\n",
- " measured_dist = measured_distribution(library,selected_divisors)\n",
- " mes_x, mes_y = [],[]\n",
- " for i,l in enumerate(selected_divisors):\n",
- " if l in measured_dist:\n",
- " mes_y.append(measured_dist[l])\n",
- " mes_x.append(i)\n",
- " plt.scatter(mes_x,mes_y,color = color, label = library)\n",
- "\n",
- "selected_divisors = small_primes#all_divisors\n",
- "\n",
- "fig = plt.subplots(figsize =(24, 12)) \n",
- "\n",
- "L = len(selected_divisors)\n",
- "\n",
- "colors = matplotlib.cm.tab20(range(6))\n",
- "scatter(\"openssl\",colors[0])\n",
- "scatter(\"libressl\",colors[1])\n",
- "scatter(\"botan\",colors[2])\n",
- "scatter(\"Crypto++\",colors[3])\n",
- "scatter(\"ippcp\",colors[4])\n",
- "\n",
- "plt.plot([l for l in range(L)],[general_distributions[l] for l in selected_divisors],color = colors[5], label = \"prime-distribution\")\n",
- "\n",
- "plt.xlabel('divisors') \n",
- "plt.ylabel(\"prob\") \n",
- "plt.xticks([r for r in range(L)], selected_divisors)\n",
- "plt.legend()\n",
- "plt.show() \n",
- "fig[0].savefig(f\"graphs/resistant.png\",dpi=300)"
+ "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": "1f403fa3-880d-45a8-aaf3-964b0fbc38d7",
+ "id": "b464865d-b169-446e-a9e7-0cead699aee1",
"metadata": {},
"outputs": [],
"source": [
- "def scatter(library, color):\n",
- " measured_dist = measured_distribution(library,selected_divisors)\n",
- " mes_x, mes_y = [],[]\n",
- " for i,l in enumerate(selected_divisors):\n",
- " if l in measured_dist:\n",
- " mes_y.append(measured_dist[l])\n",
- " mes_x.append(i)\n",
- " # plt.scatter(mes_x,mes_y,color = color, label = library)\n",
- " plt.plot(mes_x,mes_y,color = color, linewidth = 1, label = library)\n",
- "\n",
- "selected_divisors = small_primes[:12]#all_divisors\n",
- "\n",
- "fig = plt.subplots(figsize =(10, 4)) \n",
- "\n",
- "L = len(selected_divisors)\n",
- "\n",
- "colors = matplotlib.cm.tab20(range(9))\n",
- "scatter(\"openssl\",colors[0])\n",
- "scatter(\"libressl\",colors[1])\n",
- "scatter(\"botan\",colors[2])\n",
- "scatter(\"Crypto++\",colors[3])\n",
- "scatter(\"mbedtls\",colors[4])\n",
- "scatter(\"libressl\",colors[5])\n",
- "scatter(\"BouncyCastle\",colors[6])\n",
- "scatter(\"tomcrypt\",colors[7])\n",
- "scatter(\"ippcp\",colors[8])\n",
- "\n",
- "\n",
- "# plt.plot([l for l in range(L)],[general_distributions[l] for l in selected_divisors],color = colors[9], label = \"divison-distribution\")\n",
- "\n",
- "plt.xlabel('Input point order',fontsize=15) \n",
- "plt.ylabel(\"Error rate\",fontsize=15) \n",
- "plt.xticks([r for r in range(L)], [v if i%1==0 else \"\" for i,v in enumerate(selected_divisors)])\n",
- "plt.legend(loc=\"center right\",prop={'size': 11})\n",
- "plt.tight_layout()\n",
- "plt.show() \n",
- "fig[0].savefig(f\"graphs/lib_dists.png\",dpi=300)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "a0415861-c9ee-4420-bb82-6fda216d401c",
- "metadata": {},
- "outputs": [],
- "source": [
- "def bars(library, color,shift,width):\n",
- " measured_dist = measured_distribution(library,selected_divisors)\n",
- " mes_x, mes_y = [],[]\n",
- " for i,l in enumerate(selected_divisors):\n",
- " offset = width*shift\n",
- " if l in measured_dist:\n",
- " mes_y.append(measured_dist[l])\n",
- " mes_x.append(2*i+offset)\n",
- " plt.bar(mes_x,mes_y,width=0.1,color = color,align ='center', label = labels.get(library,library))\n",
- "\n",
- "selected_divisors = small_primes[:12]#all_divisors\n",
+ "divisor_name = \"powers_of_2_large_3\"\n",
+ "plot_mults = [mult.with_countermeasure(cm) for mult in selected_mults for cm in (None, \"gsr\", \"additive\", \"multiplicative\", \"euclidean\")]\n",
+ "plot_divisors = sorted(divisor_map[divisor_name])#[-200:]\n",
+ "L = len(plot_divisors)\n",
+ "N = len(plot_mults)\n",
"\n",
- "fig = plt.subplots(figsize =(10, 4)) \n",
+ "fig = plt.figure(figsize=(L/4+5, 24))\n",
+ "ax = plt.subplot(111)\n",
"\n",
- "L = len(selected_divisors)\n",
+ "vals = np.zeros((N, L))\n",
+ "n_samples = 0\n",
+ "for i, mult in enumerate(plot_mults):\n",
+ " y_values = [distributions_mults[mult][l] for l in plot_divisors]\n",
+ " vals[i,] = y_values\n",
+ " ax.plot(list(range(L)), y_values, color=colors[mult], linestyle=styles[mult], marker=markers[mult], label=str(mult))\n",
+ " n_samples += distributions_mults[mult].samples\n",
"\n",
- "colors = matplotlib.cm.tab20(range(9))\n",
- "width = 0.2\n",
- "for i,lib in enumerate((\"openssl\",\"libressl\",\"botan\",\"Crypto++\",\"mbedtls\",\"BouncyCastle\",\"tomcrypt\",\"ippcp\")):\n",
- " bars(lib,colors[i],i,width)\n",
+ "ax.set_title(divisor_name + \"\\nSamples(avg): \" + str(n_samples//N))\n",
"\n",
+ "var = np.var(vals, axis=0)\n",
+ "ax.plot(list(range(L)), var / np.max(var), label=\"cross-mult variance (normalized)\", ls=\"--\", lw=2, color=\"black\")\n",
"\n",
- "plt.plot([2*l+4*width for l in range(L)],[general_distributions[l] for l in selected_divisors],color = colors[8], label = \"expected distribution\")\n",
+ "ax.set_xlabel(\"divisors\") \n",
+ "ax.set_ylabel(\"error probability\")\n",
+ "ax.set_xticks(list(range(L)), plot_divisors, rotation=90)\n",
"\n",
- "plt.xlabel('Input point order',fontsize=15) \n",
- "plt.ylabel(\"Error rate\",fontsize=15) \n",
- "plt.xticks([2*r+4*width for r in range(L)], [v if i%1==0 else \"\" for i,v in enumerate(selected_divisors)])\n",
- "plt.legend(loc=\"upper right\",prop={'size': 11})\n",
+ "ax.grid()\n",
"plt.tight_layout()\n",
- "plt.show() \n",
- "fig[0].savefig(f\"graphs/lib_dists.png\",dpi=300)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "e5f036c8-3d47-4105-9a67-79b2b8e1ecdb",
- "metadata": {},
- "outputs": [],
- "source": [
- "from math import sqrt\n",
- "\n",
- "selected_mults = all_mults#window_mults[0:1]+window_mults[5:6]+naf_mults[1:2]#[mult for mult in all_mults if not mult in comb_mults]\n",
- "selected_divisors = small_primes#ll_divisors\n",
- "colors = {mult:matplotlib.cm.tab20(range(len(selected_mults)))[i] for i,mult in enumerate(selected_mults)}\n",
- "\n",
- "\n",
- "fig = plt.subplots(figsize =(30, 20)) \n",
- "\n",
- "L = len(selected_divisors)\n",
- "selected_divisors = sorted(selected_divisors)\n",
- "for mult in selected_mults:\n",
- " y_values,y_values_mstd, y_values_pstd = [],[],[]\n",
- " for l in selected_divisors:\n",
- " p = distributions_mults[mult][l]\n",
- " y_values.append(1/p)\n",
- " y_values_mstd.append(1/p-sqrt((1-p)/p**2))\n",
- " y_values_pstd.append(1/p+sqrt((1-p)/p**2))\n",
- " plt.plot([l for l in range(L)],y_values,color = colors[mult], label = mult_label(mult))\n",
- " plt.fill_between([l for l in range(L)], y_values_mstd , y_values_pstd, alpha = 0.1, color = colors[mult])\n",
- " \n",
- "# mult = list(fixedwindow_dist.keys())[0]\n",
- "# plt.plot([l for l in range(L)],[fixedwindow_dist[l] for l in selected_divisors],color = \"pink\", label = mult_label(mult))\n",
- "\n",
- "# measured_dist = measured_distribution(library,selected_divisors)\n",
- "# mes_x, mes_y = [],[]\n",
- "# for i,l in enumerate(selected_divisors):\n",
- "# if l in measured_dist:\n",
- "# mes_y.append(measured_dist[l])\n",
- "# mes_x.append(i)\n",
- "# plt.scatter(mes_x,mes_y,color = \"black\", label = library)\n",
- "\n",
- "plt.plot([l for l in range(L)],[1/general_distributions[l] for l in selected_divisors],color = \"black\", label = \"prime-distribution\")\n",
- "\n",
- "steps_dist = {}\n",
- "for i in range(51):\n",
- " with open(f\"cards/jcop/199_{i}.txt\") as f:\n",
- " steps = f.read().count(\"ALG_EC_SVDP_DH of remote pubkey and local privkey\")\n",
- " if not steps in steps_dist:\n",
- " steps_dist[steps] = 0\n",
- " steps_dist[steps]+=1\n",
- "ys = sorted(list(steps_dist.keys()))\n",
- "plt.scatter([selected_divisors.index(199)]*len(ys),ys, s=[steps_dist[y]*20 for y in ys],color=\"black\")\n",
- "for i, y in enumerate(ys):\n",
- " plt.annotate(str(steps_dist[y]), (selected_divisors.index(199)-1, y))\n",
- "avg = 0\n",
- "for s,c in steps_dist.items():\n",
- " avg+=s*c\n",
- "avg = avg/sum(steps_dist.values())\n",
- "plt.scatter([selected_divisors.index(199)],[avg], s=[30],color=\"yellow\")\n",
- " \n",
- "plt.xlabel('divisors') \n",
- "plt.ylabel(\"prob\") \n",
- "plt.yticks(range(12))\n",
- "plt.xticks([r for r in range(L)], selected_divisors)\n",
+ "box = ax.get_position()\n",
+ "ax.set_position([box.x0, box.y0, box.width * 0.9, box.height])\n",
"\n",
- "plt.legend()\n",
- "plt.show() \n",
- "fig[0].savefig(f\"graphs/re.png\",dpi=300)"
+ "# Put a legend to the right of the current axis\n",
+ "ax.legend(loc='center left', bbox_to_anchor=(1, 0.5), prop={'size': 5})\n",
+ "plt.show()\n",
+ "fig.savefig(f\"graphs/{divisor_name}.png\",dpi=300);"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "24adaa81-df58-47a9-bdea-0b373be4368a",
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "ae10629c-72f7-4a66-8495-8302ffa61887",
+ "id": "1b9f5231-b168-4ddf-89a2-53f975788e09",
"metadata": {},
"outputs": [],
"source": []