diff options
| author | J08nY | 2025-03-24 17:31:26 +0100 |
|---|---|---|
| committer | J08nY | 2025-04-16 12:25:06 +0200 |
| commit | 95566a5b75b58a6a3aa2d3be9527e41585e3572a (patch) | |
| tree | abc88c20f0ec097bc29cff79c86ff703985f6fe4 | |
| parent | b921927b8747ac8b66d3ccff22446b148c891f01 (diff) | |
| download | ECTester-95566a5b75b58a6a3aa2d3be9527e41585e3572a.tar.gz ECTester-95566a5b75b58a6a3aa2d3be9527e41585e3572a.tar.zst ECTester-95566a5b75b58a6a3aa2d3be9527e41585e3572a.zip | |
| -rw-r--r-- | epare/countermeasures.ipynb | 729 |
1 files changed, 629 insertions, 100 deletions
diff --git a/epare/countermeasures.ipynb b/epare/countermeasures.ipynb index 1ee3dea..b4371ce 100644 --- a/epare/countermeasures.ipynb +++ b/epare/countermeasures.ipynb @@ -10,28 +10,35 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 204, "id": "33ee6084-2ac3-4f95-9610-0fbc06026538", "metadata": {}, "outputs": [], "source": [ "import io\n", "import random\n", + "import itertools\n", + "import cypari2\n", "\n", + "from matplotlib import pyplot as plt\n", "from collections import Counter\n", "from tqdm.auto import tqdm, trange\n", "\n", - "from pyecsca.ec.mod import mod\n", + "from pyecsca.misc.utils import TaskExecutor\n", + "from pyecsca.ec.mod import mod, RandomModAction\n", "from pyecsca.ec.point import Point\n", "from pyecsca.ec.model import ShortWeierstrassModel\n", "from pyecsca.ec.params import load_params_ectester\n", "from pyecsca.ec.mult import LTRMultiplier\n", - "from pyecsca.ec.countermeasures import GroupScalarRandomization, AdditiveSplitting, MultiplicativeSplitting, EuclideanSplitting, BrumleyTuveri" + "from pyecsca.ec.context import local, DefaultContext\n", + "from pyecsca.ec.countermeasures import GroupScalarRandomization, AdditiveSplitting, MultiplicativeSplitting, EuclideanSplitting, BrumleyTuveri\n", + "\n", + "%matplotlib ipympl" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 205, "id": "b1b9596c-1eba-4ace-af84-8cb279d84cc2", "metadata": {}, "outputs": [], @@ -42,7 +49,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 206, "id": "b0afb195-8390-44c5-931e-75a70ccd4e9e", "metadata": {}, "outputs": [], @@ -54,7 +61,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 207, "id": "52c877e1-5021-4ec2-9daa-dd20bec6bcb2", "metadata": {}, "outputs": [], @@ -76,7 +83,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 208, "id": "c3088419-161b-4193-a1b6-6f623f217fcd", "metadata": {}, "outputs": [], @@ -91,7 +98,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 209, "id": "a8dde7e6-cd48-4f99-9677-23a19e4c2e5b", "metadata": {}, "outputs": [ @@ -124,7 +131,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 210, "id": "cd6f8500-7509-45b0-8b23-471ee5014f42", "metadata": {}, "outputs": [], @@ -198,14 +205,14 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 211, "id": "86532d50-2db7-4370-b449-c545b330a852", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "a645f19f86484d3f8154c39c2b851de2", + "model_id": "b0a80fc9b8f14b2992f10c7bb66a9a83", "version_major": 2, "version_minor": 0 }, @@ -220,9 +227,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "k:\t343\n", - "k + 1n:\t339\n", - "k + 2n:\t318\n" + "k:\t326\n", + "k + 1n:\t341\n", + "k + 2n:\t333\n" ] } ], @@ -240,14 +247,14 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 212, "id": "ad421630-606f-4666-9bbf-1a446eec1b59", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "1d3be2fca22c468c84b0c6fa179ba46c", + "model_id": "0d0f2e87f3044516924fbd74ba68f983", "version_major": 2, "version_minor": 0 }, @@ -262,8 +269,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "k:\t520\n", - "k + 1n:\t480\n" + "k:\t500\n", + "k + 1n:\t500\n" ] } ], @@ -281,14 +288,14 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 213, "id": "3ed5d7f3-0ba1-4b62-9635-aeb492499175", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "758e44f09b0448ba9cd2e69cf7a16691", + "model_id": "9eb1217838fa4931bb0f0f9cd86aba09", "version_major": 2, "version_minor": 0 }, @@ -303,9 +310,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "k:\t219\n", - "k + 1n:\t554\n", - "k + 2n:\t227\n" + "k:\t221\n", + "k + 1n:\t544\n", + "k + 2n:\t235\n" ] } ], @@ -323,14 +330,14 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 214, "id": "314447c6-a1fb-4d3a-8988-b34c8912dd5e", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "3eec57b52cd647e7bfc37b577ac7b6b9", + "model_id": "1c6788e6f3614ea1a7a6c8c6cd761bb5", "version_major": 2, "version_minor": 0 }, @@ -363,14 +370,14 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 215, "id": "f41dfc1d-1017-4aa0-bcd4-6569c53bf81e", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "cdb7d64c69f64a62b4b1357f06db1481", + "model_id": "9290687728e144329fd7dca7dcebabd8", "version_major": 2, "version_minor": 0 }, @@ -411,14 +418,14 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 216, "id": "7255321a-6ad6-4938-8ec9-dd8d977686db", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "828fecbd021a43b4a529e1261b4e5f5b", + "model_id": "63db299beb5b47679019f469b446d2c9", "version_major": 2, "version_minor": 0 }, @@ -433,9 +440,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "k:\t315\n", - "k + 1n:\t330\n", - "k + 2n:\t355\n" + "k:\t324\n", + "k + 1n:\t337\n", + "k + 2n:\t339\n" ] } ], @@ -453,14 +460,14 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 217, "id": "b0146a9a-0803-43c4-ab29-8ba6e15934b5", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "5d9adb2b79254271872bdfe5c38a3983", + "model_id": "639cadec2edd4719b7bcbd5f6d9b80ae", "version_major": 2, "version_minor": 0 }, @@ -475,8 +482,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "k:\t505\n", - "k + 1n:\t495\n" + "k:\t491\n", + "k + 1n:\t509\n" ] } ], @@ -494,14 +501,14 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 218, "id": "5645ae6f-f5f4-419d-ba47-248532dc2114", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "e4073f552ae248269ab0785b701bd069", + "model_id": "f3c8933bed464791b7d36ef8dbf8bf2b", "version_major": 2, "version_minor": 0 }, @@ -516,9 +523,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "k:\t345\n", - "k + 1n:\t327\n", - "k + 2n:\t328\n" + "k:\t341\n", + "k + 1n:\t308\n", + "k + 2n:\t351\n" ] } ], @@ -536,14 +543,14 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 219, "id": "c9fc4f35-1c25-4cac-bb63-8bd70263db47", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "529938c684364319be7d8ba15f68d79c", + "model_id": "85635506a91c4665b65d5377c06549b1", "version_major": 2, "version_minor": 0 }, @@ -576,14 +583,14 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 220, "id": "4fd6b288-08a9-4dbe-9145-e96401805315", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "19bdafccd4f04b42ba188598567a1e8c", + "model_id": "c46f2d9115ca4f17b229c5b0da6baf7b", "version_major": 2, "version_minor": 0 }, @@ -598,8 +605,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "k + 1n:\t35\n", - "k + 2n:\t965\n" + "k + 1n:\t36\n", + "k + 2n:\t964\n" ] } ], @@ -625,7 +632,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 221, "id": "6c46fdbb-2ffb-4169-8e00-6d93b8407ee5", "metadata": {}, "outputs": [ @@ -639,7 +646,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "a65c045d5236432aba76108115266213", + "model_id": "7561669af4664bfebcbcf2d5e5629d2e", "version_major": 2, "version_minor": 0 }, @@ -654,9 +661,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "k:\t349\n", - "k + 1n:\t300\n", - "k + 2n:\t351\n", + "k:\t340\n", + "k + 1n:\t308\n", + "k + 2n:\t352\n", "\n", "k = 1 mod 3\n" ] @@ -664,7 +671,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "475dc945b4624296817e939a7e86ca14", + "model_id": "25e114540bef47d89efe10138dbe13cf", "version_major": 2, "version_minor": 0 }, @@ -679,9 +686,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "k:\t358\n", - "k + 1n:\t329\n", - "k + 2n:\t313\n", + "k:\t325\n", + "k + 1n:\t337\n", + "k + 2n:\t338\n", "\n", "k = 2 mod 3\n" ] @@ -689,7 +696,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "a03a298fe08446b7849d02a2b7b217ca", + "model_id": "a8a2dcd9e5954ecd8a0d2f6b54f4d436", "version_major": 2, "version_minor": 0 }, @@ -704,9 +711,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "k:\t310\n", - "k + 1n:\t324\n", - "k + 2n:\t366\n" + "k:\t312\n", + "k + 1n:\t356\n", + "k + 2n:\t332\n" ] } ], @@ -724,7 +731,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 222, "id": "344a4f90-3470-40e9-a75f-b925a88c2480", "metadata": {}, "outputs": [ @@ -738,7 +745,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "5c77bfdf86864a76ab849f5379f44248", + "model_id": "bc8d0b7c8f414943af7d3f133e43bd78", "version_major": 2, "version_minor": 0 }, @@ -753,8 +760,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "k:\t513\n", - "k + 1n:\t487\n", + "k:\t482\n", + "k + 1n:\t518\n", "\n", "k = 1 mod 3\n" ] @@ -762,7 +769,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "e98ab853babf4a3ba962d72e19b69dd3", + "model_id": "df03bde64059413fbe6a5208c458f5f9", "version_major": 2, "version_minor": 0 }, @@ -777,8 +784,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "k:\t484\n", - "k + 1n:\t516\n", + "k:\t513\n", + "k + 1n:\t487\n", "\n", "k = 2 mod 3\n" ] @@ -786,7 +793,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "6e6ebc6372ad45758f30937a6ac3c291", + "model_id": "d953bea042794219bf4aa32c1d16ad92", "version_major": 2, "version_minor": 0 }, @@ -801,8 +808,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "k:\t518\n", - "k + 1n:\t482\n" + "k:\t497\n", + "k + 1n:\t503\n" ] } ], @@ -820,7 +827,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 223, "id": "616a7726-01e6-4e9c-b7f2-fe8f14b60071", "metadata": {}, "outputs": [ @@ -834,7 +841,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "fcc70a8e56bc4e19baac2065827fe431", + "model_id": "4f329714588d4127bd4273dda2695222", "version_major": 2, "version_minor": 0 }, @@ -849,9 +856,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "k:\t564\n", - "k + 1n:\t213\n", - "k + 2n:\t223\n", + "k:\t563\n", + "k + 1n:\t225\n", + "k + 2n:\t212\n", "\n", "k = 1 mod 3\n" ] @@ -859,7 +866,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "8401c46897fe47739342c17404fe0774", + "model_id": "5f8e4efe89454eb5817d889b2fe77210", "version_major": 2, "version_minor": 0 }, @@ -874,9 +881,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "k:\t216\n", - "k + 1n:\t209\n", - "k + 2n:\t575\n", + "k:\t234\n", + "k + 1n:\t221\n", + "k + 2n:\t545\n", "\n", "k = 2 mod 3\n" ] @@ -884,7 +891,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "700a89093d19425d8b8a4d3418af215b", + "model_id": "0712286b1d8242c7ae0ea2255eda2f37", "version_major": 2, "version_minor": 0 }, @@ -899,9 +906,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "k:\t231\n", - "k + 1n:\t564\n", - "k + 2n:\t205\n" + "k:\t210\n", + "k + 1n:\t578\n", + "k + 2n:\t212\n" ] } ], @@ -919,7 +926,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 224, "id": "adced4e4-37a7-43ed-97b5-01cb5d274d6b", "metadata": {}, "outputs": [ @@ -933,7 +940,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "c314c4a285634a6eaaabc93bbd7aa60f", + "model_id": "9588400d40a041e088d86352e7512a06", "version_major": 2, "version_minor": 0 }, @@ -956,7 +963,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "7134985a8cdf4d1f8cecce1bbfb31f9a", + "model_id": "e3014e90730b44209d9bf87cd89598a3", "version_major": 2, "version_minor": 0 }, @@ -979,7 +986,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "45bc4b1be69c4d918f821e5c3cfde87f", + "model_id": "1fe4739a9dd3482a9e0f1e7d379c57b3", "version_major": 2, "version_minor": 0 }, @@ -1012,7 +1019,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 225, "id": "fe8d8295-3e69-4b60-b8c3-5710deaeb0b3", "metadata": {}, "outputs": [ @@ -1026,7 +1033,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "8a13b1ee1a9e448cbcfc95b94efa4254", + "model_id": "2101fd299ebd49358729bf7dc7aa204a", "version_major": 2, "version_minor": 0 }, @@ -1041,8 +1048,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "k + 1n:\t51\n", - "k + 2n:\t949\n", + "k + 1n:\t39\n", + "k + 2n:\t961\n", "\n", "k = 1 mod 3\n" ] @@ -1050,7 +1057,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "a7db0f83dcd54e92b9b7e3360e255aec", + "model_id": "ae5b94fb0d5b4395b98a6f905ea29a80", "version_major": 2, "version_minor": 0 }, @@ -1065,8 +1072,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "k + 1n:\t39\n", - "k + 2n:\t961\n", + "k + 1n:\t29\n", + "k + 2n:\t971\n", "\n", "k = 2 mod 3\n" ] @@ -1074,7 +1081,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "63a961fdb65e4223bde808fed8f4abbc", + "model_id": "b3155abae413412bae324c579e5c7de5", "version_major": 2, "version_minor": 0 }, @@ -1089,8 +1096,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "k + 1n:\t37\n", - "k + 2n:\t963\n" + "k + 1n:\t33\n", + "k + 2n:\t967\n" ] } ], @@ -1099,12 +1106,534 @@ ] }, { + "cell_type": "markdown", + "id": "43b309af-5683-4384-9623-d7633723177c", + "metadata": {}, + "source": [ + "## Mask recovery\n", + "Using a composite order curve we can recover the size and the actual mask values (in a known key scenario) in both GSR and multiplicative splitting. However, real-world targets do not like composite order curves and may either check the order or otherwise fail to compute on such curves. Thus, we lie to them and set the order to the next-prime of the true order, in this case $n + 92$." + ] + }, + { + "cell_type": "code", + "execution_count": 226, + "id": "20a26f27-620d-4d7f-92bd-b949482b5c9a", + "metadata": {}, + "outputs": [], + "source": [ + "pari = cypari2.Pari(256_000_000, 2_000_000_000)" + ] + }, + { "cell_type": "code", - "execution_count": null, - "id": "b1b0bfd6-70f9-4822-b964-0c6ab097b498", + "execution_count": 227, + "id": "144340bd-5372-4beb-a46e-fd60c596b254", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "real_n = 0xa9fa3419aca88bade2cba14e317816c6828910c6ce04fcd2a2e857d25df50775\n", + "# = 2898786277 * 2916913393 * 3067509271 * 3248233993 * 3894099889 * 4099407227 * 4101666977 * 13936975277\n", + "real_n_facts = pari.factor(real_n)\n", + "params92pn = load_params_ectester(io.BytesIO(b\"0xa9fa3419aca88bade2cba14e317816c79d52481d463dc9bcb12c37f45aa3b4e1,0x2ea3bfe6659f8e035735349b91fbfa2baf0cf8e640315f0fe03c1136813dec99,0x2b07c518e04b02158651e3dbbef7720015dd496bf15af02f8439f8e1503b8370,0x90fb04b1af19e8e20396ac052f260a9fb5f736b97e3cd4af08fe81a1e75dac6d,0x2302bcf700d3d5899f04d0c7441f5017c9758bfafd6ce15dbe36fb4eea76baec,0xa9fa3419aca88bade2cba14e317816c6828910c6ce04fcd2a2e857d25df507d1,0x01\"), \"projective\")\n", + "e = pari.ellinit([int(params92pn.curve.parameters[\"a\"]), int(params92pn.curve.parameters[\"b\"])], int(params92pn.curve.prime))\n", + "e[15][0] = real_n" + ] + }, + { + "cell_type": "code", + "execution_count": 228, + "id": "f103129c-17d3-4217-999b-94ecb4ec523d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "prime:\t0xa9fa3419aca88bade2cba14e317816c79d52481d463dc9bcb12c37f45aa3b4e1\n", + "a:\t0x2ea3bfe6659f8e035735349b91fbfa2baf0cf8e640315f0fe03c1136813dec99\n", + "b:\t0x2b07c518e04b02158651e3dbbef7720015dd496bf15af02f8439f8e1503b8370\n", + "G:\t[0x90fb04b1af19e8e20396ac052f260a9fb5f736b97e3cd4af08fe81a1e75dac6d,\n", + "\t 0x2302bcf700d3d5899f04d0c7441f5017c9758bfafd6ce15dbe36fb4eea76baec]\n", + "n+92:\t0xa9fa3419aca88bade2cba14e317816c6828910c6ce04fcd2a2e857d25df507d1 (fake order, given to the target, prime)\n", + "n:\t0xa9fa3419aca88bade2cba14e317816c6828910c6ce04fcd2a2e857d25df50775 (real order, composite)\n" + ] + } + ], + "source": [ + "print(f\"prime:\\t0x{params92pn.curve.prime:x}\")\n", + "print(f\"a:\\t0x{params92pn.curve.parameters['a']:x}\")\n", + "print(f\"b:\\t0x{params92pn.curve.parameters['b']:x}\")\n", + "print(f\"G:\\t[0x{params92pn.generator.X:x},\\n\\t 0x{params92pn.generator.Y:x}]\")\n", + "print(f\"n+92:\\t0x{params92pn.order:x} (fake order, given to the target, prime)\")\n", + "print(f\"n:\\t0x{real_n:x} (real order, composite)\")" + ] + }, + { + "cell_type": "markdown", + "id": "322d2e68-5259-4ea6-9748-2b0aa21b557f", + "metadata": {}, + "source": [ + "### Group scalar randomization\n", + "In GSR getting the mask out this way is quite simple. The target believes it is operating on a curve of order $n+92$ so it will use that value multiplied with the mask to randomize the scalar. Thus as a result we get:\n", + "$$ P = [k + r(n + 92)]G $$\n", + "\n", + "However, the curve is truly of order $n$, thus arithmetic on its group will make this equal to: \n", + "$$ P = [k + r 92]G $$\n", + "\n", + "Since this is a composite order curve, we can solve the dlog and obtain $k + r 92$ and since we assume we know $k$ we can easily compute both the mask size and mask value $r$." + ] + }, + { + "cell_type": "code", + "execution_count": 229, + "id": "08d99bd5-2b87-4a04-995d-7a87f9b67102", + "metadata": {}, + "outputs": [], + "source": [ + "key = 0x20959f2b437de1e522baf6d814911938157390d3ea5118660b852ab0d5387006 # any key works ofc\n", + "gsr.init(params92pn, params92pn.generator)\n", + "res = gsr.multiply(key)" + ] + }, + { + "cell_type": "code", + "execution_count": 230, + "id": "2a869bed-8e21-46af-8f70-065f4afd6a82", + "metadata": {}, + "outputs": [], + "source": [ + "affine_gen = params92pn.generator.to_affine()\n", + "affine_res = res.to_affine()" + ] + }, + { + "cell_type": "code", + "execution_count": 231, + "id": "e440399a-bc01-488b-8822-08cc0bf1672d", + "metadata": {}, + "outputs": [], + "source": [ + "dlog = pari.elllog(e,\n", + " [int(affine_res.x), int(affine_res.y)],\n", + " [int(affine_gen.x), int(affine_gen.y)],\n", + " real_n)" + ] + }, + { + "cell_type": "code", + "execution_count": 232, + "id": "7ea6d6ae-a6f5-4b53-8c40-787d79970cb6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3752128619\n", + "32\n" + ] + } + ], + "source": [ + "mask = int((dlog - key) / 92)\n", + "mask_len = mask.bit_length()\n", + "print(mask)\n", + "print(mask_len)" + ] + }, + { + "cell_type": "markdown", + "id": "d40ec035-0656-4eda-8ef4-c14f9d53f49f", + "metadata": {}, + "source": [ + "### Multiplicative splitting\n", + "In multiplicative splitting the situation is a bit more complicated. Doing the same computation, where the target thinks the curve order is $n+92$ leads to:\n", + "$$ P = [k r^{-1} \\mod (n+92)][r \\mod n]G $$\n", + "\n", + "Since the curve is composite order we can easily compute the dlog $d$ of P to G, we get:\n", + "$$ d = k r r^{-1} = k + s (n + 92) $$\n", + "\n", + "However, the dlog is computed $\\mod n$ so we really get: $ d = k + s 92$. We extract the $s$ out of this.\n", + "Note that $s$ will have roughly the same size as the mask $r$, so at this point we have recovered the mask size.\n", + "However, $s$ is always smaller than $r$, sometimes also in bitsize.\n", + "\n", + "Now that we have $s$ we can go back to the original equation and get:\n", + "$$ k r r^{-1} = k + s (n + 92) $$\n", + "\n", + "We can then factor this value and look for divisors that are larger than $s$ but smaller than the mask length\n", + "that we recovered before. There may be multiple candidates here and we don't know how to distinguoish between\n", + "them. However, sometimes there is only one candidate, which is equal to the true mask value $r$." + ] + }, + { + "cell_type": "code", + "execution_count": 233, + "id": "b5f398fc-90d7-455e-97bd-62b682d55961", + "metadata": {}, + "outputs": [], + "source": [ + "def divisors(primes, powers):\n", + " for comb in itertools.product(*[range(power+1) for power in powers]):\n", + " value = 1\n", + " for prime, power in zip(primes, comb):\n", + " value *= prime**power\n", + " yield value\n", + "\n", + "def pari_factor(number):\n", + " pari = cypari2.Pari(256_000_000, 2_000_000_000)\n", + " factors = pari.factor(number)\n", + " primes = list(map(int, factors[0]))\n", + " powers = list(map(int, factors[1]))\n", + " return primes, powers\n", + "\n", + "def pari_dlog(params, P, G, real_n, facts_str):\n", + " pari = cypari2.Pari(256_000_000, 2_000_000_000)\n", + " e = pari.ellinit([int(params.curve.parameters[\"a\"]), int(params.curve.parameters[\"b\"])], int(params.curve.prime))\n", + " e[15][0] = real_n\n", + " facts = pari(facts_str)\n", + " dlog = pari.elllog(e, P, G, facts)\n", + " return int(dlog)" + ] + }, + { + "cell_type": "code", + "execution_count": 234, + "id": "5f03e586-33df-4525-a722-f5f63d6ca28d", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e4879058a89a44af9abf2e7a58b1022f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Collecting scalarmults: 0%| | 0/1000 [00:00<?, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "69ff8872b4454bacb5f1c4a7503e6d3b", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Computing dlogs: 0%| | 0/1000 [00:00<?, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "32\n" + ] + } + ], + "source": [ + "key = 0x20959f2b437de1e522baf6d814911938157390d3ea5118660b852ab0d5387006 # any key works\n", + "msplit = MultiplicativeSplitting(mult, rand_bits=32) # change the mask size here to your liking\n", + "tries = 1000\n", + "\n", + "blens = [None for _ in range(tries)]\n", + "ss = [None for _ in range(tries)]\n", + "\n", + "results = []\n", + "rs = []\n", + "\n", + "with TaskExecutor(max_workers=num_workers) as pool:\n", + " for i in trange(tries, desc=\"Collecting scalarmults\"):\n", + " msplit.init(params92pn, params92pn.generator)\n", + " with local(DefaultContext()) as ctx:\n", + " res = msplit.multiply(key)\n", + " \n", + " affine_res = res.to_affine()\n", + " affine_gen = params92pn.generator.to_affine()\n", + " results.append(affine_res)\n", + " ctx.actions[0].walk(lambda action: rs.append(int(action.result)) if isinstance(action, RandomModAction) else None)\n", + " \n", + " pool.submit_task(i,\n", + " pari_dlog,\n", + " params92pn,\n", + " [int(affine_res.x), int(affine_res.y)],\n", + " [int(affine_gen.x), int(affine_gen.y)],\n", + " real_n,\n", + " repr(real_n_facts))\n", + " \n", + " for i, future in tqdm(pool.as_completed(), desc=\"Computing dlogs\", total=len(pool.tasks)):\n", + " dlog = future.result()\n", + " s = int((dlog - key) / 92)\n", + " ss[i] = s\n", + " blens[i] = s.bit_length()\n", + "\n", + "mask_len = max(blens)\n", + "print(mask_len)" + ] + }, + { + "cell_type": "code", + "execution_count": 235, + "id": "5fbf8a38-983d-49a6-9cac-5350f960dc3e", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "89d1369c99644e88bd73b6230963716a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Factoring: 0%| | 0/1000 [00:00<?, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "num_workers = 25\n", + "\n", + "with TaskExecutor(max_workers=num_workers) as pool:\n", + " for s in ss:\n", + " full = s * (real_n + 92) + key\n", + " pool.submit_task(s,\n", + " pari_factor,\n", + " full)\n", + " facts = [None for _ in ss]\n", + " for s, future in tqdm(pool.as_completed(), desc=\"Factoring\", total=len(ss)):\n", + " result = future.result()\n", + " facts[ss.index(s)] = result" + ] + }, + { + "cell_type": "code", + "execution_count": 236, + "id": "0973fe4b-cdf5-4e91-850b-25375eeabb7e", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Only one candidate, we got the mask: 3223834487 True\n", + "Only one candidate, we got the mask: 2377873873 True\n", + "Only one candidate, we got the mask: 2549271668 True\n", + "Only one candidate, we got the mask: 2536406777 True\n", + "Only one candidate, we got the mask: 3474268328 True\n", + "Only one candidate, we got the mask: 3550639425 True\n", + "Only one candidate, we got the mask: 3814005975 True\n", + "Only one candidate, we got the mask: 4238733795 True\n", + "Only one candidate, we got the mask: 4168083955 True\n", + "Only one candidate, we got the mask: 2761553491 True\n", + "Only one candidate, we got the mask: 3411331906 True\n", + "Only one candidate, we got the mask: 789326198 True\n", + "Only one candidate, we got the mask: 2285458765 True\n", + "Only one candidate, we got the mask: 774733453 True\n", + "Only one candidate, we got the mask: 3283055299 True\n", + "Only one candidate, we got the mask: 2838749009 True\n", + "Only one candidate, we got the mask: 3276117366 True\n", + "Only one candidate, we got the mask: 860570263 True\n", + "Only one candidate, we got the mask: 981664829 True\n", + "Only one candidate, we got the mask: 4134679928 True\n", + "Only one candidate, we got the mask: 3988645114 True\n", + "Only one candidate, we got the mask: 2280222647 True\n", + "Only one candidate, we got the mask: 3577824626 True\n", + "Only one candidate, we got the mask: 3679892960 True\n", + "Only one candidate, we got the mask: 1774221601 True\n", + "Only one candidate, we got the mask: 2623580147 True\n", + "Only one candidate, we got the mask: 1702008059 True\n", + "Only one candidate, we got the mask: 3933544069 True\n", + "Only one candidate, we got the mask: 3999529804 True\n", + "Only one candidate, we got the mask: 3480801033 True\n", + "Only one candidate, we got the mask: 3813421579 True\n", + "Only one candidate, we got the mask: 3417626666 True\n", + "Only one candidate, we got the mask: 4170438661 True\n", + "Only one candidate, we got the mask: 3502288943 True\n", + "Only one candidate, we got the mask: 2786122643 True\n", + "Only one candidate, we got the mask: 2127512283 True\n", + "Only one candidate, we got the mask: 2531786983 True\n", + "Only one candidate, we got the mask: 3983366093 True\n", + "Only one candidate, we got the mask: 2379294079 True\n", + "Only one candidate, we got the mask: 2930272946 True\n", + "Only one candidate, we got the mask: 2500319501 True\n", + "Only one candidate, we got the mask: 2947684105 True\n", + "Only one candidate, we got the mask: 3995028346 True\n", + "Only one candidate, we got the mask: 3421022802 True\n", + "Only one candidate, we got the mask: 3953171129 True\n", + "Only one candidate, we got the mask: 2982511438 True\n", + "Only one candidate, we got the mask: 2830285508 True\n", + "Only one candidate, we got the mask: 277646521 True\n", + "Only one candidate, we got the mask: 3775642326 True\n", + "Only one candidate, we got the mask: 3528903061 True\n", + "Only one candidate, we got the mask: 2433595133 True\n", + "Only one candidate, we got the mask: 2809043104 True\n", + "Only one candidate, we got the mask: 3918854258 True\n", + "Only one candidate, we got the mask: 2172498737 True\n", + "Only one candidate, we got the mask: 2614989645 True\n", + "Only one candidate, we got the mask: 3881796054 True\n", + "Only one candidate, we got the mask: 3763131597 True\n", + "Only one candidate, we got the mask: 3333059164 True\n", + "Only one candidate, we got the mask: 781918702 True\n", + "Only one candidate, we got the mask: 3898624034 True\n", + "Only one candidate, we got the mask: 2695908441 True\n", + "Only one candidate, we got the mask: 2428288661 True\n", + "Only one candidate, we got the mask: 380310234 True\n", + "Only one candidate, we got the mask: 3806008683 True\n", + "Only one candidate, we got the mask: 1583055543 True\n", + "Only one candidate, we got the mask: 3071695987 True\n", + "Only one candidate, we got the mask: 2466420323 True\n", + "Only one candidate, we got the mask: 3668827111 True\n", + "Only one candidate, we got the mask: 3030308051 True\n", + "Only one candidate, we got the mask: 4178268350 True\n", + "Only one candidate, we got the mask: 601467334 True\n", + "Only one candidate, we got the mask: 1756886305 True\n", + "Only one candidate, we got the mask: 3789366239 True\n", + "Only one candidate, we got the mask: 1709528826 True\n", + "Only one candidate, we got the mask: 4179236943 True\n", + "Only one candidate, we got the mask: 3246542896 True\n", + "Only one candidate, we got the mask: 1036989838 True\n", + "Only one candidate, we got the mask: 2843879303 True\n", + "Only one candidate, we got the mask: 2943368159 True\n", + "Only one candidate, we got the mask: 3694910341 True\n", + "Only one candidate, we got the mask: 3509390042 True\n", + "Only one candidate, we got the mask: 3797507269 True\n", + "Only one candidate, we got the mask: 3948777957 True\n", + "Only one candidate, we got the mask: 3649873740 True\n", + "Only one candidate, we got the mask: 2612080546 True\n", + "Only one candidate, we got the mask: 3671883118 True\n", + "Only one candidate, we got the mask: 2973101524 True\n", + "Only one candidate, we got the mask: 3724708289 True\n", + "Only one candidate, we got the mask: 4134344947 True\n", + "Only one candidate, we got the mask: 3489598522 True\n", + "Only one candidate, we got the mask: 3984902078 True\n", + "Only one candidate, we got the mask: 4259116327 True\n", + "Only one candidate, we got the mask: 3389988907 True\n", + "Only one candidate, we got the mask: 868217594 True\n", + "Only one candidate, we got the mask: 3729431567 True\n", + "Only one candidate, we got the mask: 3542657779 True\n", + "Only one candidate, we got the mask: 2695799377 True\n", + "Only one candidate, we got the mask: 3972219937 True\n", + "Only one candidate, we got the mask: 2701111433 True\n", + "Only one candidate, we got the mask: 3806713198 True\n", + "Only one candidate, we got the mask: 3503145915 True\n", + "Only one candidate, we got the mask: 2397268241 True\n", + "Only one candidate, we got the mask: 2919558765 True\n", + "Only one candidate, we got the mask: 543703399 True\n", + "Total recovered masks: 104 out of 1000\n" + ] + } + ], + "source": [ + "candidate_amounts = []\n", + "for s, blen, r, (primes, powers), result in zip(ss, blens, rs, facts, results):\n", + " #print(primes, powers)\n", + " #print(s, blen, r, r.bit_length())\n", + " candidates = set()\n", + " for divisor in divisors(primes, powers):\n", + " if blen <= divisor.bit_length() <= mask_len and divisor > s:\n", + " candidates.add(divisor)\n", + " #print(f\"Candidates: {len(candidates)}, {r in candidates}\")\n", + " candidate_amounts.append(len(candidates))\n", + " if len(candidates) == 1:\n", + " candidate = candidates.pop()\n", + " print(\"Only one candidate, we got the mask:\", candidate, candidate == r)\n", + " #print(\"--\")\n", + "print(f\"Total recovered masks: {len(list(filter(lambda a: a == 1, candidate_amounts)))} out of {tries}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 237, + "id": "6274ff91-325f-4c6b-a4d7-d66b994d730f", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d557894c3fbd4543b9fd6c240b676212", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "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3LlauHCh3WpI0iOPPKLMzEytXLlSe/fu1cCBAxUXF6fjx4/XabyrHWtz587Vyy+/rKVLl2rnzp1q3ry54uPj9dNPP9ll/LKyMvXr10/PPfdcneZ/tRrnzp1Tbm6uUlNTlZubq3feeUcHDhzQ0KFD7VZDkjp37qxFixZp7969+vTTTxUSEqKBAwfq5MmTdqtx0fr167Vjxw4FBATUah9qWmPQoEGVjpe33nrLbuMfPnxY/fr1U9euXbV161Z9+eWXSk1NrfHjx2pS45dzLygo0GuvvSaLxaL77rvPbjWSk5OVkZGhVatWaf/+/Zo0aZLGjRunDRs22KWGYRhKSEjQv/71L7377rvas2ePgoODFRcXV+PPqZp8zk2ePFnvvfee1q1bp23btunEiRO69957a7wPTZqBWuvTp48xduxY288VFRVGQECAkZaW5pB6koz169c7ZOyLiouLDUnGtm3bHFrnxhtvNF599VW7j3vmzBkjNDTUyMzMNPr3729MnDjRbmPPmjXLCA8Pt9t4l5oyZYrRr18/h41flYkTJxo33XSTYbVa7TbmkCFDjIcffrhS27333muMHDnSbjXOnTtnODs7Gxs3bqzU3qtXL+PJJ5+85vEvPdasVqvh7+9vPP/887a206dPG+7u7sZbb711zeP/0pEjRwxJxp49e2o9bk1rXLRr1y5DknH06FGH1SgpKTEkGZs3b7ZrjX//+99Gu3btjH379hnBwcHGiy++WKfxq6uRlJRk3HPPPXUe82rjJyYmGr/97W/tMn51NS51zz33GHfeeadda3Tv3t344x//WKntWo7DS2scOHDAkGTs27fP1lZRUWG0bt3aWL58eZ1qXPo5d/r0acPV1dVYt26drc/+/fsNSUZ2dnadajQlrADW0vnz55WTk6O4uDhbm5OTk+Li4pSdnd2AM7s2JSUlkuSwL8auqKjQmjVrVFZW5pCv2hs7dqyGDBlS6f8Xezp06JACAgLUsWNHjRw5slana65mw4YNioqK0v333682bdrolltu0fLly+02/qXOnz+vVatW6eGHH5bFYrHbuLGxscrKytLBgwclSV988YU+/fRTDR482G41/vOf/6iiouKy1RJPT0+7rspedOTIERUWFlb678rHx0fR0dFN/ni3WCxq0aKFQ8Y/f/68li1bJh8fH4WHh9ttXKvVqgcffFApKSnq3r273ca91NatW9WmTRt16dJFv/vd7/Tdd9/ZZVyr1apNmzapc+fOio+PV5s2bRQdHW33S3x+qaioSJs2bdKYMWPsOm5sbKw2bNig48ePyzAMbdmyRQcPHtTAgQPtMn55ebkkVTrWnZyc5O7uXudj/dLPuZycHF24cKHS8d21a1cFBQU16eO7pgiAtXTq1ClVVFTYvoHkIj8/PxUWFjbQrK6N1WrVpEmT1Ldv30rflGIPe/fu1Q033CB3d3c99thjWr9+vbp162bXGmvWrFFubq7tawDtLTo6Wm+88YYyMjK0ZMkSHTlyRLfddpvOnDljl/H/9a9/acmSJQoNDdWHH36o3/3ud5owYYL+8pe/2GX8S6Wnp+v06dN66KGH7Dru1KlTNXz4cHXt2lWurq665ZZbNGnSJI0cOdJuNby8vBQTE6M//elPOnHihCoqKrRq1SplZ2eroKDAbnUuunhMX0/H+08//aQpU6ZoxIgR8vb2tuvYGzdu1A033CAPDw+9+OKLyszMlK+vr93Gf+655+Ti4qIJEybYbcxLDRo0SG+++aaysrL03HPPadu2bRo8eLAqKiqueezi4mKdPXtWc+bM0aBBg/TRRx9p2LBhuvfee7Vt2zY7zP5yf/nLX+Tl5WX305oLFy5Ut27d1L59e7m5uWnQoEFavHixbr/9druMfzGITZs2TT/88IPOnz+v5557Tv/+97/rdKxX9TlXWFgoNze3y/4h1JSP79poMl8FB8cZO3as9u3b55AVlC5duigvL08lJSX629/+pqSkJG3bts1uIfDYsWOaOHGiMjMza3UNTW38cgWrZ8+eio6OVnBwsN5++227/KvaarUqKipKzz77rCTplltu0b59+7R06VIlJSVd8/iXWrFihQYPHlyn66eu5O2339Zf//pXrV69Wt27d1deXp4mTZqkgIAAu+7HypUr9fDDD6tdu3ZydnZWr169NGLECOXk5NitxvXqwoULeuCBB2QYhpYsWWL38e+44w7l5eXp1KlTWr58uR544AHt3LlTbdq0ueaxc3Jy9NJLLyk3N9euK9eXGj58uO3PYWFh6tmzp2666SZt3bpVAwYMuKaxrVarJOmee+7R5MmTJUkRERHavn27li5dqv79+1/T+FV57bXXNHLkSLv//bhw4ULt2LFDGzZsUHBwsD7++GONHTtWAQEBdjkT4+rq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h4SEaMGCBVfcxmKxKD093aHzakxq8jsBAL4KDkCT9fnnn6t58+Z2HfOpp55Senq68vLy7DouADQmBEAATVbr1q0begoA0CRxChhArVmtVs2dO1edOnWSu7u7goKC9Mwzz9jenzJlijp37qxmzZqpY8eOSk1N1YULF2zvP/XUU4qIiNDKlSsVEhIiHx8fDR8+XGfOnLH1KSsr06hRo3TDDTeobdu2VX6p/aWnOw8dOqTbb79dHh4e6tatmzIzMy/b5kpze+ONNzR79mx98cUXslgsslgseuONNyRJp0+f1iOPPKLWrVvL29tbd955p7744otqf0fffvutLBaL3n77bd12223y9PRU7969dfDgQX3++eeKiorSDTfcoMGDB+vkyZO27T7//HP9+te/lq+vr3x8fNS/f3/l5uba3jcMQ0899ZSCgoLk7u6ugIAATZgwodp5vPrqq2rRooWysrIkSX/7298UFhYmT09PtWrVSnFxcSorK6t2ewDXJ1YAAdTatGnTtHz5cr344ovq16+fCgoK9M0339je9/Ly0htvvKGAgADt3btXjz76qLy8vPTEE0/Y+hw+fFjp6enauHGjfvjhBz3wwAOaM2eOLUimpKRo27Ztevfdd9WmTRtNnz5dubm5ioiIqHJOVqtV9957r/z8/LRz506VlJRUul6wJnNLTEzUvn37lJGRoc2bN0uSfHx8JEn333+/PD099cEHH8jHx0evvPKKBgwYoIMHD6ply5bV/q5mzZqlBQsWKCgoSA8//LD++7//W15eXnrppZfUrFkzPfDAA5o5c6aWLFkiSTpz5oySkpK0cOFCGYahefPm6a677tKhQ4fk5eWlv//973rxxRe1Zs0ade/eXYWFhdUG0blz52ru3Ln66KOP1KdPHxUUFGjEiBGaO3euhg0bpjNnzuiTTz4RXwkPmJABALVQWlpquLu7G8uXL6/xNs8//7wRGRlp+3nWrFlGs2bNjNLSUltbSkqKER0dbRiGYZw5c8Zwc3Mz3n77bdv73333neHp6WlMnDjR1hYcHGy8+OKLhmEYxocffmi4uLgYx48ft73/wQcfGJKM9evX12pu4eHhlfp88sknhre3t/HTTz9Var/pppuMV155pcpxjxw5YkgyXn31VVvbW2+9ZUgysrKybG1paWlGly5dqp1fRUWF4eXlZbz33nuGYRjGvHnzjM6dOxvnz5+vsv/F38kTTzxhtG3b1ti3b5/tvZycHEOS8e2331ZbD4A5sAIIoFb279+v8vJyDRgwoNo+a9eu1csvv6zDhw/r7Nmz+s9//iNvb+9KfUJCQuTl5WX7uW3btiouLpb08+rg+fPnFR0dbXu/ZcuW6tKlyxXnFRgYqICAAFtbTExMneZ2qS+++EJnz55Vq1atKrX/+OOPOnz48BW37dmzp+3Pfn5+kqSwsLBKbRf3W5KKioo0Y8YMbd26VcXFxaqoqNC5c+eUn58v6eeVyAULFqhjx44aNGiQ7rrrLt19991ycfn/v87nzZunsrIy7d69Wx07drS1h4eHa8CAAQoLC1N8fLwGDhyo3/zmN7rxxhuvuA8Arj9cAwigVjw9Pa/4fnZ2tkaOHKm77rpLGzdu1J49e/Tkk0/q/Pnzlfq5urpW+tlischqtdp9vnWZ26XOnj2rtm3bKi8vr9LrwIEDSklJueK2v9xPi8VSZdsv9zspKUl5eXl66aWXtH37duXl5alVq1a2OQYGBurAgQP685//LE9PT/3+97/X7bffXukay9tuu00VFRV6++23K83F2dlZmZmZ+uCDD9StWzctXLhQXbp00ZEjR67ymwNwvSEAAqiV0NBQeXp62m4quNT27dsVHBysJ598UlFRUQoNDdXRo0drVeOmm26Sq6urdu7caWv74YcfdPDgwWq3ufnmm3Xs2DEVFBTY2nbs2FHrubm5uamioqJSW69evVRYWCgXFxd16tSp0svX17dW+3Y1n332mSZMmKC77rpL3bt3l7u7u06dOlWpj6enp+6++269/PLL2rp1q7Kzs7V3717b+3369NEHH3ygZ599Vi+88EKlbS0Wi/r27avZs2drz549cnNz0/r16+26DwAaP04BA6gVDw8PTZkyRU888YTc3NzUt29fnTx5Ul999ZXGjBmj0NBQ5efna82aNerdu7c2bdpU64Bxww03aMyYMUpJSVGrVq3Upk0bPfnkk3Jyqv7frHFxcercubOSkpL0/PPPq7S0VE8++WSlPjWZW0hIiI4cOaK8vDy1b99eXl5eiouLU0xMjBISEjR37lx17txZJ06c0KZNmzRs2DBFRUXVav+uJDQ0VCtXrlRUVJRKS0uVkpJSadX1jTfeUEVFhaKjo9WsWTOtWrVKnp6eCg4OrjRObGys3n//fQ0ePFguLi6aNGmSdu7cqaysLA0cOFBt2rTRzp07dfLkSd188812mz+ApoEVQAC1lpqaqscff1wzZ87UzTffrMTERNt1bEOHDtXkyZM1btw4RUREaPv27UpNTa11jeeff1633Xab7r77bsXFxalfv36KjIystr+Tk5PWr1+vH3/8UX369NEjjzxS6dE0NZ3bfffdp0GDBumOO+5Q69at9dZbb8lisej999/X7bffrtGjR6tz584aPny4jh49aruuz15WrFihH374Qb169dKDDz6oCRMmqE2bNrb3W7RooeXLl6tv377q2bOnNm/erPfee++y6xMlqV+/ftq0aZNmzJihhQsXytvbWx9//LHuuusude7cWTNmzNC8efM0ePBgu+4DgMbPYhjc/w8AAGAmrAACAACYDAEQAADAZAiAAAAAJkMABAAAMBkCIAAAgMkQAAEAAEyGAAgAAGAyBEAAAACTIQACAACYDAEQAADAZAiAAAAAJkMABAAAMJn/A1cXgnhL9+q3AAAAAElFTkSuQmCC", + "text/html": [ + "\n", + " <div style=\"display: inline-block;\">\n", + " <div class=\"jupyter-widgets widget-label\" style=\"text-align: center;\">\n", + " Figure\n", + " </div>\n", + " <img src='data:image/png;base64,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3LlauHCh3WpI0iOPPKLMzEytXLlSe/fu1cCBAxUXF6fjx4/XabyrHWtz587Vyy+/rKVLl2rnzp1q3ry54uPj9dNPP9ll/LKyMvXr10/PPfdcneZ/tRrnzp1Tbm6uUlNTlZubq3feeUcHDhzQ0KFD7VZDkjp37qxFixZp7969+vTTTxUSEqKBAwfq5MmTdqtx0fr167Vjxw4FBATUah9qWmPQoEGVjpe33nrLbuMfPnxY/fr1U9euXbV161Z9+eWXSk1NrfHjx2pS45dzLygo0GuvvSaLxaL77rvPbjWSk5OVkZGhVatWaf/+/Zo0aZLGjRunDRs22KWGYRhKSEjQv/71L7377rvas2ePgoODFRcXV+PPqZp8zk2ePFnvvfee1q1bp23btunEiRO69957a7wPTZqBWuvTp48xduxY288VFRVGQECAkZaW5pB6koz169c7ZOyLiouLDUnGtm3bHFrnxhtvNF599VW7j3vmzBkjNDTUyMzMNPr3729MnDjRbmPPmjXLCA8Pt9t4l5oyZYrRr18/h41flYkTJxo33XSTYbVa7TbmkCFDjIcffrhS27333muMHDnSbjXOnTtnODs7Gxs3bqzU3qtXL+PJJ5+85vEvPdasVqvh7+9vPP/887a206dPG+7u7sZbb711zeP/0pEjRwxJxp49e2o9bk1rXLRr1y5DknH06FGH1SgpKTEkGZs3b7ZrjX//+99Gu3btjH379hnBwcHGiy++WKfxq6uRlJRk3HPPPXUe82rjJyYmGr/97W/tMn51NS51zz33GHfeeadda3Tv3t344x//WKntWo7DS2scOHDAkGTs27fP1lZRUWG0bt3aWL58eZ1qXPo5d/r0acPV1dVYt26drc/+/fsNSUZ2dnadajQlrADW0vnz55WTk6O4uDhbm5OTk+Li4pSdnd2AM7s2JSUlkuSwL8auqKjQmjVrVFZW5pCv2hs7dqyGDBlS6f8Xezp06JACAgLUsWNHjRw5slana65mw4YNioqK0v333682bdrolltu0fLly+02/qXOnz+vVatW6eGHH5bFYrHbuLGxscrKytLBgwclSV988YU+/fRTDR482G41/vOf/6iiouKy1RJPT0+7rspedOTIERUWFlb678rHx0fR0dFN/ni3WCxq0aKFQ8Y/f/68li1bJh8fH4WHh9ttXKvVqgcffFApKSnq3r273ca91NatW9WmTRt16dJFv/vd7/Tdd9/ZZVyr1apNmzapc+fOio+PV5s2bRQdHW33S3x+qaioSJs2bdKYMWPsOm5sbKw2bNig48ePyzAMbdmyRQcPHtTAgQPtMn55ebkkVTrWnZyc5O7uXudj/dLPuZycHF24cKHS8d21a1cFBQU16eO7pgiAtXTq1ClVVFTYvoHkIj8/PxUWFjbQrK6N1WrVpEmT1Ldv30rflGIPe/fu1Q033CB3d3c99thjWr9+vbp162bXGmvWrFFubq7tawDtLTo6Wm+88YYyMjK0ZMkSHTlyRLfddpvOnDljl/H/9a9/acmSJQoNDdWHH36o3/3ud5owYYL+8pe/2GX8S6Wnp+v06dN66KGH7Dru1KlTNXz4cHXt2lWurq665ZZbNGnSJI0cOdJuNby8vBQTE6M//elPOnHihCoqKrRq1SplZ2eroKDAbnUuunhMX0/H+08//aQpU6ZoxIgR8vb2tuvYGzdu1A033CAPDw+9+OKLyszMlK+vr93Gf+655+Ti4qIJEybYbcxLDRo0SG+++aaysrL03HPPadu2bRo8eLAqKiqueezi4mKdPXtWc+bM0aBBg/TRRx9p2LBhuvfee7Vt2zY7zP5yf/nLX+Tl5WX305oLFy5Ut27d1L59e7m5uWnQoEFavHixbr/9druMfzGITZs2TT/88IPOnz+v5557Tv/+97/rdKxX9TlXWFgoNze3y/4h1JSP79poMl8FB8cZO3as9u3b55AVlC5duigvL08lJSX629/+pqSkJG3bts1uIfDYsWOaOHGiMjMza3UNTW38cgWrZ8+eio6OVnBwsN5++227/KvaarUqKipKzz77rCTplltu0b59+7R06VIlJSVd8/iXWrFihQYPHlyn66eu5O2339Zf//pXrV69Wt27d1deXp4mTZqkgIAAu+7HypUr9fDDD6tdu3ZydnZWr169NGLECOXk5NitxvXqwoULeuCBB2QYhpYsWWL38e+44w7l5eXp1KlTWr58uR544AHt3LlTbdq0ueaxc3Jy9NJLLyk3N9euK9eXGj58uO3PYWFh6tmzp2666SZt3bpVAwYMuKaxrVarJOmee+7R5MmTJUkRERHavn27li5dqv79+1/T+FV57bXXNHLkSLv//bhw4ULt2LFDGzZsUHBwsD7++GONHTtWAQEBdjkT4+rq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h4SEaMGCBVfcxmKxKD093aHzakxq8jsBAL4KDkCT9fnnn6t58+Z2HfOpp55Senq68vLy7DouADQmBEAATVbr1q0begoA0CRxChhArVmtVs2dO1edOnWSu7u7goKC9Mwzz9jenzJlijp37qxmzZqpY8eOSk1N1YULF2zvP/XUU4qIiNDKlSsVEhIiHx8fDR8+XGfOnLH1KSsr06hRo3TDDTeobdu2VX6p/aWnOw8dOqTbb79dHh4e6tatmzIzMy/b5kpze+ONNzR79mx98cUXslgsslgseuONNyRJp0+f1iOPPKLWrVvL29tbd955p7744otqf0fffvutLBaL3n77bd12223y9PRU7969dfDgQX3++eeKiorSDTfcoMGDB+vkyZO27T7//HP9+te/lq+vr3x8fNS/f3/l5uba3jcMQ0899ZSCgoLk7u6ugIAATZgwodp5vPrqq2rRooWysrIkSX/7298UFhYmT09PtWrVSnFxcSorK6t2ewDXJ1YAAdTatGnTtHz5cr344ovq16+fCgoK9M0339je9/Ly0htvvKGAgADt3btXjz76qLy8vPTEE0/Y+hw+fFjp6enauHGjfvjhBz3wwAOaM2eOLUimpKRo27Ztevfdd9WmTRtNnz5dubm5ioiIqHJOVqtV9957r/z8/LRz506VlJRUul6wJnNLTEzUvn37lJGRoc2bN0uSfHx8JEn333+/PD099cEHH8jHx0evvPKKBgwYoIMHD6ply5bV/q5mzZqlBQsWKCgoSA8//LD++7//W15eXnrppZfUrFkzPfDAA5o5c6aWLFkiSTpz5oySkpK0cOFCGYahefPm6a677tKhQ4fk5eWlv//973rxxRe1Zs0ade/eXYWFhdUG0blz52ru3Ln66KOP1KdPHxUUFGjEiBGaO3euhg0bpjNnzuiTTz4RXwkPmJABALVQWlpquLu7G8uXL6/xNs8//7wRGRlp+3nWrFlGs2bNjNLSUltbSkqKER0dbRiGYZw5c8Zwc3Mz3n77bdv73333neHp6WlMnDjR1hYcHGy8+OKLhmEYxocffmi4uLgYx48ft73/wQcfGJKM9evX12pu4eHhlfp88sknhre3t/HTTz9Var/pppuMV155pcpxjxw5YkgyXn31VVvbW2+9ZUgysrKybG1paWlGly5dqp1fRUWF4eXlZbz33nuGYRjGvHnzjM6dOxvnz5+vsv/F38kTTzxhtG3b1ti3b5/tvZycHEOS8e2331ZbD4A5sAIIoFb279+v8vJyDRgwoNo+a9eu1csvv6zDhw/r7Nmz+s9//iNvb+9KfUJCQuTl5WX7uW3btiouLpb08+rg+fPnFR0dbXu/ZcuW6tKlyxXnFRgYqICAAFtbTExMneZ2qS+++EJnz55Vq1atKrX/+OOPOnz48BW37dmzp+3Pfn5+kqSwsLBKbRf3W5KKioo0Y8YMbd26VcXFxaqoqNC5c+eUn58v6eeVyAULFqhjx44aNGiQ7rrrLt19991ycfn/v87nzZunsrIy7d69Wx07drS1h4eHa8CAAQoLC1N8fLwGDhyo3/zmN7rxxhuvuA8Arj9cAwigVjw9Pa/4fnZ2tkaOHKm77rpLGzdu1J49e/Tkk0/q/Pnzlfq5urpW+tlischqtdp9vnWZ26XOnj2rtm3bKi8vr9LrwIEDSklJueK2v9xPi8VSZdsv9zspKUl5eXl66aWXtH37duXl5alVq1a2OQYGBurAgQP685//LE9PT/3+97/X7bffXukay9tuu00VFRV6++23K83F2dlZmZmZ+uCDD9StWzctXLhQXbp00ZEjR67ymwNwvSEAAqiV0NBQeXp62m4quNT27dsVHBysJ598UlFRUQoNDdXRo0drVeOmm26Sq6urdu7caWv74YcfdPDgwWq3ufnmm3Xs2DEVFBTY2nbs2FHrubm5uamioqJSW69evVRYWCgXFxd16tSp0svX17dW+3Y1n332mSZMmKC77rpL3bt3l7u7u06dOlWpj6enp+6++269/PLL2rp1q7Kzs7V3717b+3369NEHH3ygZ599Vi+88EKlbS0Wi/r27avZs2drz549cnNz0/r16+26DwAaP04BA6gVDw8PTZkyRU888YTc3NzUt29fnTx5Ul999ZXGjBmj0NBQ5efna82aNerdu7c2bdpU64Bxww03aMyYMUpJSVGrVq3Upk0bPfnkk3Jyqv7frHFxcercubOSkpL0/PPPq7S0VE8++WSlPjWZW0hIiI4cOaK8vDy1b99eXl5eiouLU0xMjBISEjR37lx17txZJ06c0KZNmzRs2DBFRUXVav+uJDQ0VCtXrlRUVJRKS0uVkpJSadX1jTfeUEVFhaKjo9WsWTOtWrVKnp6eCg4OrjRObGys3n//fQ0ePFguLi6aNGmSdu7cqaysLA0cOFBt2rTRzp07dfLkSd188812mz+ApoEVQAC1lpqaqscff1wzZ87UzTffrMTERNt1bEOHDtXkyZM1btw4RUREaPv27UpNTa11jeeff1633Xab7r77bsXFxalfv36KjIystr+Tk5PWr1+vH3/8UX369NEjjzxS6dE0NZ3bfffdp0GDBumOO+5Q69at9dZbb8lisej999/X7bffrtGjR6tz584aPny4jh49aruuz15WrFihH374Qb169dKDDz6oCRMmqE2bNrb3W7RooeXLl6tv377q2bOnNm/erPfee++y6xMlqV+/ftq0aZNmzJihhQsXytvbWx9//LHuuusude7cWTNmzNC8efM0ePBgu+4DgMbPYhjc/w8AAGAmrAACAACYDAEQAADAZAiAAAAAJkMABAAAMBkCIAAAgMkQAAEAAEyGAAgAAGAyBEAAAACTIQACAACYDAEQAADAZAiAAAAAJkMABAAAMJn/A1cXgnhL9+q3AAAAAElFTkSuQmCC' width=640.0/>\n", + " </div>\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "max_amount = max(candidate_amounts)\n", + "fig = plt.subplots()\n", + "plt.hist(candidate_amounts, range=(1, max_amount), align=\"left\", density=True, bins=range(1, max_amount))#, bins=list(range(20)) + list(range(20, 100, 5)) + list(range(100, max(candidate_amounts), 10)))\n", + "plt.xlabel(\"candidate masks\")\n", + "plt.ylabel(\"proportion\")\n", + "plt.xticks(range(max_amount))\n", + "plt.xlim(0, 20);\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 238, + "id": "9f22ca9d-bdc2-4ea5-b2bc-249a256bb8ad", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c64139ea7ed94a1ea0e153e7728d34eb", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "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XAoICDinPCAgwH0ZtjFycnKUnZ2tpKQkJScna+HChaqtrdWYMWMkSaNHj1bnzp2Vn58vSZo4caIGDx6s+fPna9iwYSooKNDOnTu1fPlyd5u5ubnKysrSLbfcoh/+8IfasGGDXnnlFW3evPnSJg0AANDKefUM4I9+9CNNnDhRhw4dcpcdPHhQkydP1q233trodrKysvT4449r1qxZSkhI0K5du7Rhwwb3gx4VFRU6fPiwu35aWppWrlyp5cuXq1+/fvrrX/+qwsJC9enTx11nxIgRWrZsmebNm6f4+Hg9++yz+tvf/qZBgwY1wcwBAABaL6++B/DAgQMaPny4PvzwQ/fDEgcOHFCfPn308ssv65prrvFW182C9wACAOB7eA+gly8Bx8TEqLS0VK+//ro+/vhjSd88aJGenu7NbgEAAHAeXg2AkuRwOPTjH/9YP/7xj73dFQAAABrB6y+CLioq0k9+8hNdd911uu666/STn/xEr7/+ure7BQAAQAO8GgCffvppDRkyRO3bt9fEiRM1ceJEhYaGaujQoVqyZIk3uwYAAEADvHoJ+NFHH9UTTzyhcePGucsmTJiggQMH6tFHH9UDDzzgze4BAABQD6+eATx+/LiGDBlyTvltt92mmpoab3YNAACABng1AA4fPlxr1qw5p/wf//iHfvKTn3izawAAADTAq5eAe/furTlz5mjz5s3uP8O2detWvfvuu3rwwQf11FNPues29m8DAwAA4NJ49UXQ3bp1a9wgHA59+umn3hqG1/AiaAAAfA8vgvbyGcB9+/Z5s3kAAABcBK+/B/AsY4y8eLIRAAAAjeT1APj8888rPj5eISEhCgkJUd++ffXCCy94u1sAAAA0wKuXgBcsWKC8vDyNGzdOAwcOlCS98847uv/++3X06FFNnjzZm90DAACgHl4NgIsWLdLSpUs1evRod9nw4cN1ww036OGHHyYAAgAAtACvXgI+fPiw0tLSzilPS0vT4cOHvdk1AAAAGuDVANi9e3e99NJL55SvWrVKcXFx3uwaAAAADfDqJeBHHnlEWVlZeuutt9z3AL777rsqKiqqNxgCAADA+7x6BvDOO+/U9u3bFRERocLCQhUWFioiIkLbt2/XiBEjvNk1AAAAGuC1M4BnzpzRf//3fysvL08rVqzwVjcAAAC4QF47AxgQEKC//e1v3moeAAAAF8mr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qICAAI/13r17tyoqKtzrnZqaqg8++MDjl8nGjRsVGhp6zhev7W699VZ98MEH2rVrl3tLSkrSqFGj3D+z3k1r4MCB57zaaM+ePerataskqVu3boqKivJYc6fTqW3btnms+fHjx1VSUuKu88Ybb8jlciklJaUZZuFbvvjiC/n5eX51tmnTRi6XSxJr7m1Ntb6pqal66623dObMGXedjRs3qkePHlZc/pXEa2Bam4KCAhMUFGSee+45869//cv86le/MuHh4R5PRaJxfv3rX5uwsDCzefNmc/jwYff2xRdfuOvcf//9pkuXLuaNN94wO3fuNKmpqSY1NdW9/+xrSW677Taza9cus2HDBnP11VfzWpJG+vZTwMaw3k1t+/btxt/f38yZM8fs3bvX/OUvfzFt27Y1K1ascNeZO3euCQ8PN//4xz/M+++/b37605/W+8qMG2+80Wzbts288847Ji4ujleSNCA7O9t07tzZ/RqYv//97yYiIsI89NBD7jqs+aU5ceKEKSsrM2VlZUaSWbBggSkrKzP79+83xjTN+h4/ftxERkaae++915SXl5uCggLTtm1bXgODlrVo0SLTpUsXExgYaJKTk83WrVtbekg+SVK925///Gd3nS+//NL85je/MVdeeaVp27atGTFihDl8+LBHO5999pm5/fbbTUhIiImIiDAPPvigOXPmTDPPxjd9NwCy3k3vlVdeMX369DFBQUGmZ8+eZvny5R77XS6XycvLM5GRkSYoKMjceuutZvfu3R51/u///s+MHDnStGvXzoSGhpoxY8aYEydONOc0fIbT6TQTJ040Xbp0McHBwebaa681M2bM8HidCGt+aTZt2lTv7+7s7GxjTNOt73vvvWcGDRpkgoKCTOfOnc3cuXOba4qtgsOYb72+HAAAAJc97gEEAACwDAEQAADAMgRAAAAAyxAAAQAALEMABAAAsAwBEAAAwDIEQAAAAMsQAAH4jB/84AeaNGmS+3NsbKwWLlx43mMcDocKCwu9Oq7WpDFrAgD+LT0AALhYO3bs0BVXXNGkbT788MMqLCzUrl27mrRdAGhNCIAAfNbVV1/d0kMAAJ/EJWAAF8zlcmnevHnq3r27goKC1KVLF82ZM8e9f8qUKbr++uvVtm1bXXvttcrLy9OZM2fc+x9++GElJCTohRdeUGxsrMLCwnTPPffoxIkT7jq1tbUaPXq02rVrp06dOmn+/PnnjOO7lzv37t2rW265RcHBwerdu7c2btx4zjHnG9tzzz2nRx55RO+9954cDoccDoeee+45SdLx48f1y1/+UldffbVCQ0P1ox/9SO+9916Da/TZZ5/J4XDopZde0s0336yQkBANGDBAe/bs0Y4dO5SUlKR27drp9ttv15EjR9zH7dixQz/+8Y8VERGhsLAwDR48WKWlpe79xhg9/PDD6tKli4KCghQdHa0JEyY0OI5nn31W4eHhKioqkiT99a9/VXx8vEJCQtShQwelp6ertra2weMBXJ44Awjggk2bNk3PPPOMnnjiCQ0aNEiHDx/Wxx9/7N7fvn17Pffcc4qOjtYHH3yg++67T+3bt9dDDz3krvPJJ5+osLBQa9eu1eeff667775bc+fOdQfJ3Nxcvfnmm/rHP/6hjh07avr06SotLVVCQkK9Y3K5XPrZz36myMhIbdu2TTU1NR73CzZmbFlZWSovL9eGDRv0+uuvS5LCwsIkSXfddZdCQkL06quvKiwsTH/4wx906623as+ePbrqqqsaXKvZs2dr4cKF6tKli37xi1/oP/7jP9S+fXs9+eSTatu2re6++27NmjVLS5culSSdOHFC2dnZWrRokYwxmj9/voYOHaq9e/eqffv2+tvf/qYnnnhCBQUFuuGGG1RZWdlgEJ03b57mzZun1157TcnJyTp8+LBGjhypefPmacSIETpx4oTefvtt8SfhAQsZALgATqfTBAUFmWeeeabRxzz22GMmMTHR/Xn27Nmmbdu2xul0ustyc3NNSkqKMcaYEydOmMDAQPPSSy+59//f//2fCQkJMRMnTnSXde3a1TzxxBPGGGP++c9/Gn9/f3Pw4EH3/ldffdVIMmvWrLmgsfXr18+jzttvv21CQ0PNV1995VF+3XXXmT/84Q/1trtv3z4jyTz77LPushdffNFIMkVFRe6y/Px806NHjwbHV1dXZ9q3b29eeeUVY4wx8+fPN9dff705ffp0vfXPrslDDz1kOnXqZMrLy937SkpKjCTz2WefNdgfADtwBhDABfnoo4906tQp3XrrrQ3WWbVqlZ566il98sknOnnypL7++muFhoZ61ImNjVX79u3dnzt16qTq6mpJ35wdPH36tFJSUtz7r7rqKvXo0eO844qJiVF0dLS7LDU19aLG9l3vvfeeTp48qQ4dOniUf/nll/rkk0/Oe2zfvn3dP0dGRkqS4uPjPcrOzluSqqqqNHPmTG3evFnV1dWqq6vTF198oYqKCknfnIlcuHChrr32Wg0ZMkRDhw7VHXfcIX//f/86nz9/vmpra7Vz505de+217vJ+/frp1ltvVXx8vDIyMnTbbbfp5z//ua688srzzgHA5Yd7AAFckJCQkPPuLy4u1qhRozR06FCtXbtWZWVlmjFjhk6fPu1RLyAgwOOzw+GQy+Vq8vFezNi+6+TJk+rUqZN27drlse3evVu5ubnnPfbb83Q4HPWWfXve2dnZ2rVrl5588klt2bJFu3btUocOHdxjjImJ0e7du/X0008rJCREv/nNb3TLLbd43GN58803q66uTi+99JLHWNq0aaONGzfq1VdfVe/evbVo0SL16NFD+/bt+56VA3C5IQACuCBxcXEKCQlxP1TwXVu2bFHXrl01Y8YMJSUlKS4uTvv377+gPq677joFBARo27Zt7rLPP/9ce/bsafCYXr166cCBAzp8+LC7bOvWrRc8tsDAQNXV1XmU9e/fX5WVlfL391f37t09toiIiAua2/d59913NWHCBA0dOlQ33HCDgoKCdPToUY86ISEhuuOOO/TUU09p8+bNKi4u1gcffODen5ycrFdffVWPPvqoHn/8cY9jHQ6HBg4cqEceeURlZWUKDAzUmjVrmnQOAFo/LgEDuCDBwcGaMmWKHnroIQUGBmrgwIE6cuSIPvzwQ40dO1ZxcXGqqKhQQUGBBgwYoHXr1l1wwGjXrp3Gjh2r3NxcdejQQR07dtSMGTPk59fwf7Omp6fr+uuvV3Z2th577DE5nU7NmDHDo05jxhYbG6t9+/Zp165duuaaa9S+fXulp6crNTVVmZmZmjdvnq6//nodOnRI69at04gRI5SUlHRB8zufuLg4vfDCC0pKSpLT6VRubq7HWdfnnntOdXV1SklJUdu2bbVixQqFhISoa9euHu2kpaVp/fr1uv322+Xv769JkyZp27ZtKioq0m233aaOHTtq27ZtOnLkiHr16tVk4wfgGzgDCOCC5eXl6cEHH9SsWbPUq1cvZWVlue9jGz58uCZPnqxx48YpISFBW7ZsUV5e3gX38dhjj+nmm2/WHXfcofT0dA0aNEiJiYkN1vfz89OaNWv05ZdfKjk5Wb/85S89Xk3T2LHdeeedGjJkiH74wx/q6quv1osvviiHw6H169frlltu0ZgxY3T99dfrnnvu0f79+9339TWVP/7xj/r888/Vv39/3XvvvZowYYI6duzo3h8eHq5nnnlGAwcOVN++ffX666/rlVdeOef+REkaNGiQ1q1bp5kzZ2rRokUKDQ3VW2+9paFDh+r666/XzJkzNX/+fN1+++1NOgcArZ/DGJ7/BwAAsAlnAAEAACxDAAQAALAMARAAAMAyBEAAAADLEAABAAAsQwAEAACwDAEQAADAMgRAAAAAyxAAAQAALEMABAAAsAwBEAAAwDIEQAAAAMv8fwxUUx3rxqQ1AAAAAElFTkSuQmCC", + "text/html": [ + "\n", + " <div style=\"display: inline-block;\">\n", + " <div class=\"jupyter-widgets widget-label\" style=\"text-align: center;\">\n", + " Figure\n", + " </div>\n", + " <img src='data:image/png;base64,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XAoICDinPCAgwH0ZtjFycnKUnZ2tpKQkJScna+HChaqtrdWYMWMkSaNHj1bnzp2Vn58vSZo4caIGDx6s+fPna9iwYSooKNDOnTu1fPlyd5u5ubnKysrSLbfcoh/+8IfasGGDXnnlFW3evPnSJg0AANDKefUM4I9+9CNNnDhRhw4dcpcdPHhQkydP1q233trodrKysvT4449r1qxZSkhI0K5du7Rhwwb3gx4VFRU6fPiwu35aWppWrlyp5cuXq1+/fvrrX/+qwsJC9enTx11nxIgRWrZsmebNm6f4+Hg9++yz+tvf/qZBgwY1wcwBAABaL6++B/DAgQMaPny4PvzwQ/fDEgcOHFCfPn308ssv65prrvFW182C9wACAOB7eA+gly8Bx8TEqLS0VK+//ro+/vhjSd88aJGenu7NbgEAAHAeXg2AkuRwOPTjH/9YP/7xj73dFQAAABrB6y+CLioq0k9+8hNdd911uu666/STn/xEr7/+ure7BQAAQAO8GgCffvppDRkyRO3bt9fEiRM1ceJEhYaGaujQoVqyZIk3uwYAAEADvHoJ+NFHH9UTTzyhcePGucsmTJiggQMH6tFHH9UDDzzgze4BAABQD6+eATx+/LiGDBlyTvltt92mmpoab3YNAACABng1AA4fPlxr1qw5p/wf//iHfvKTn3izawAAADTAq5eAe/furTlz5mjz5s3uP8O2detWvfvuu3rwwQf11FNPues29m8DAwAA4NJ49UXQ3bp1a9wgHA59+umn3hqG1/AiaAAAfA8vgvbyGcB9+/Z5s3kAAABcBK+/B/AsY4y8eLIRAAAAjeT1APj8888rPj5eISEhCgkJUd++ffXCCy94u1sAAAA0wKuXgBcsWKC8vDyNGzdOAwcOlCS98847uv/++3X06FFNnjzZm90DAACgHl4NgIsWLdLSpUs1evRod9nw4cN1ww036OGHHyYAAgAAtACvXgI+fPiw0tLSzilPS0vT4cOHvdk1AAAAGuDVANi9e3e99NJL55SvWrVKcXFx3uwaAAAADfDqJeBHHnlEWVlZeuutt9z3AL777rsqKiqqNxgCAADA+7x6BvDOO+/U9u3bFRERocLCQhUWFioiIkLbt2/XiBEjvNk1AAAAGuC1M4BnzpzRf//3fysvL08rVqzwVjcAAAC4QF47AxgQEKC//e1v3moeAAAAF8mr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qICAAI/13r17tyoqKtzrnZqaqg8++MDjl8nGjRsVGhp6zhev7W699VZ98MEH2rVrl3tLSkrSqFGj3D+z3k1r4MCB57zaaM+ePerataskqVu3boqKivJYc6fTqW3btnms+fHjx1VSUuKu88Ybb8jlciklJaUZZuFbvvjiC/n5eX51tmnTRi6XSxJr7m1Ntb6pqal66623dObMGXedjRs3qkePHlZc/pXEa2Bam4KCAhMUFGSee+45869//cv86le/MuHh4R5PRaJxfv3rX5uwsDCzefNmc/jwYff2xRdfuOvcf//9pkuXLuaNN94wO3fuNKmpqSY1NdW9/+xrSW677Taza9cus2HDBnP11VfzWpJG+vZTwMaw3k1t+/btxt/f38yZM8fs3bvX/OUvfzFt27Y1K1ascNeZO3euCQ8PN//4xz/M+++/b37605/W+8qMG2+80Wzbts288847Ji4ujleSNCA7O9t07tzZ/RqYv//97yYiIsI89NBD7jqs+aU5ceKEKSsrM2VlZUaSWbBggSkrKzP79+83xjTN+h4/ftxERkaae++915SXl5uCggLTtm1bXgODlrVo0SLTpUsXExgYaJKTk83WrVtbekg+SVK925///Gd3nS+//NL85je/MVdeeaVp27atGTFihDl8+LBHO5999pm5/fbbTUhIiImIiDAPPvigOXPmTDPPxjd9NwCy3k3vlVdeMX369DFBQUGmZ8+eZvny5R77XS6XycvLM5GRkSYoKMjceuutZvfu3R51/u///s+MHDnStGvXzoSGhpoxY8aYEydONOc0fIbT6TQTJ040Xbp0McHBwebaa681M2bM8HidCGt+aTZt2lTv7+7s7GxjTNOt73vvvWcGDRpkgoKCTOfOnc3cuXOba4qtgsOYb72+HAAAAJc97gEEAACwDAEQAADAMgRAAAAAyxAAAQAALEMABAAAsAwBEAAAwDIEQAAAAMsQAAH4jB/84AeaNGmS+3NsbKwWLlx43mMcDocKCwu9Oq7WpDFrAgD+LT0AALhYO3bs0BVXXNGkbT788MMqLCzUrl27mrRdAGhNCIAAfNbVV1/d0kMAAJ/EJWAAF8zlcmnevHnq3r27goKC1KVLF82ZM8e9f8qUKbr++uvVtm1bXXvttcrLy9OZM2fc+x9++GElJCTohRdeUGxsrMLCwnTPPffoxIkT7jq1tbUaPXq02rVrp06dOmn+/PnnjOO7lzv37t2rW265RcHBwerdu7c2btx4zjHnG9tzzz2nRx55RO+9954cDoccDoeee+45SdLx48f1y1/+UldffbVCQ0P1ox/9SO+9916Da/TZZ5/J4XDopZde0s0336yQkBANGDBAe/bs0Y4dO5SUlKR27drp9ttv15EjR9zH7dixQz/+8Y8VERGhsLAwDR48WKWlpe79xhg9/PDD6tKli4KCghQdHa0JEyY0OI5nn31W4eHhKioqkiT99a9/VXx8vEJCQtShQwelp6ertra2weMBXJ44Awjggk2bNk3PPPOMnnjiCQ0aNEiHDx/Wxx9/7N7fvn17Pffcc4qOjtYHH3yg++67T+3bt9dDDz3krvPJJ5+osLBQa9eu1eeff667775bc+fOdQfJ3Nxcvfnmm/rHP/6hjh07avr06SotLVVCQkK9Y3K5XPrZz36myMhIbdu2TTU1NR73CzZmbFlZWSovL9eGDRv0+uuvS5LCwsIkSXfddZdCQkL06quvKiwsTH/4wx906623as+ePbrqqqsaXKvZs2dr4cKF6tKli37xi1/oP/7jP9S+fXs9+eSTatu2re6++27NmjVLS5culSSdOHFC2dnZWrRokYwxmj9/voYOHaq9e/eqffv2+tvf/qYnnnhCBQUFuuGGG1RZWdlgEJ03b57mzZun1157TcnJyTp8+LBGjhypefPmacSIETpx4oTefvtt8SfhAQsZALgATqfTBAUFmWeeeabRxzz22GMmMTHR/Xn27Nmmbdu2xul0ustyc3NNSkqKMcaYEydOmMDAQPPSSy+59//f//2fCQkJMRMnTnSXde3a1TzxxBPGGGP++c9/Gn9/f3Pw4EH3/ldffdVIMmvWrLmgsfXr18+jzttvv21CQ0PNV1995VF+3XXXmT/84Q/1trtv3z4jyTz77LPushdffNFIMkVFRe6y/Px806NHjwbHV1dXZ9q3b29eeeUVY4wx8+fPN9dff705ffp0vfXPrslDDz1kOnXqZMrLy937SkpKjCTz2WefNdgfADtwBhDABfnoo4906tQp3XrrrQ3WWbVqlZ566il98sknOnnypL7++muFhoZ61ImNjVX79u3dnzt16qTq6mpJ35wdPH36tFJSUtz7r7rqKvXo0eO844qJiVF0dLS7LDU19aLG9l3vvfeeTp48qQ4dOniUf/nll/rkk0/Oe2zfvn3dP0dGRkqS4uPjPcrOzluSqqqqNHPmTG3evFnV1dWqq6vTF198oYqKCknfnIlcuHChrr32Wg0ZMkRDhw7VHXfcIX//f/86nz9/vmpra7Vz505de+217vJ+/frp1ltvVXx8vDIyMnTbbbfp5z//ua688srzzgHA5Yd7AAFckJCQkPPuLy4u1qhRozR06FCtXbtWZWVlmjFjhk6fPu1RLyAgwOOzw+GQy+Vq8vFezNi+6+TJk+rUqZN27drlse3evVu5ubnnPfbb83Q4HPWWfXve2dnZ2rVrl5588klt2bJFu3btUocOHdxjjImJ0e7du/X0008rJCREv/nNb3TLLbd43GN58803q66uTi+99JLHWNq0aaONGzfq1VdfVe/evbVo0SL16NFD+/bt+56VA3C5IQACuCBxcXEKCQlxP1TwXVu2bFHXrl01Y8YMJSUlKS4uTvv377+gPq677joFBARo27Zt7rLPP/9ce/bsafCYXr166cCBAzp8+LC7bOvWrRc8tsDAQNXV1XmU9e/fX5WVlfL391f37t09toiIiAua2/d59913NWHCBA0dOlQ33HCDgoKCdPToUY86ISEhuuOOO/TUU09p8+bNKi4u1gcffODen5ycrFdffVWPPvqoHn/8cY9jHQ6HBg4cqEceeURlZWUKDAzUmjVrmnQOAFo/LgEDuCDBwcGaMmWKHnroIQUGBmrgwIE6cuSIPvzwQ40dO1ZxcXGqqKhQQUGBBgwYoHXr1l1wwGjXrp3Gjh2r3NxcdejQQR07dtSMGTPk59fwf7Omp6fr+uuvV3Z2th577DE5nU7NmDHDo05jxhYbG6t9+/Zp165duuaaa9S+fXulp6crNTVVmZmZmjdvnq6//nodOnRI69at04gRI5SUlHRB8zufuLg4vfDCC0pKSpLT6VRubq7HWdfnnntOdXV1SklJUdu2bbVixQqFhISoa9euHu2kpaVp/fr1uv322+Xv769JkyZp27ZtKioq0m233aaOHTtq27ZtOnLkiHr16tVk4wfgGzgDCOCC5eXl6cEHH9SsWbPUq1cvZWVlue9jGz58uCZPnqxx48YpISFBW7ZsUV5e3gX38dhjj+nmm2/WHXfcofT0dA0aNEiJiYkN1vfz89OaNWv05ZdfKjk5Wb/85S89Xk3T2LHdeeedGjJkiH74wx/q6quv1osvviiHw6H169frlltu0ZgxY3T99dfrnnvu0f79+9339TWVP/7xj/r888/Vv39/3XvvvZowYYI6duzo3h8eHq5nnnlGAwcOVN++ffX666/rlVdeOef+REkaNGiQ1q1bp5kzZ2rRokUKDQ3VW2+9paFDh+r666/XzJkzNX/+fN1+++1NOgcArZ/DGJ7/BwAAsAlnAAEAACxDAAQAALAMARAAAMAyBEAAAADLEAABAAAsQwAEAACwDAEQAADAMgRAAAAAyxAAAQAALEMABAAAsAwBEAAAwDIEQAAAAMv8fwxUUx3rxqQ1AAAAAElFTkSuQmCC' width=640.0/>\n", + " </div>\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "max_amount = max(candidate_amounts)\n", + "fig = plt.subplots()\n", + "plt.hist(candidate_amounts, range=(1, max_amount), align=\"left\", density=True, bins=range(1, max_amount))#, bins=list(range(20)) + list(range(20, 100, 5)) + list(range(100, max(candidate_amounts), 10)))\n", + "plt.xlabel(\"candidate masks\")\n", + "plt.ylabel(\"proportion\")\n", + "plt.show()" + ] } ], "metadata": { |
