{ "cells": [ { "cell_type": "markdown", "id": "3ff024c8-7e90-4094-ab07-a051a601d9cd", "metadata": {}, "source": [ "# ZVP-based reverse-engineering\n", "This notebook showcases the ZVP-based reverse-engineering technique for addition formulas.\n", "\n", " - [Exploration](#Exploration)\n", " - [Reverse-engineering](#Reverse-engineering)\n", " - [Computing addition chains](#Computing-addition-chains)\n", " - [Loading the formulas](#Loading-the-formulas)\n", " - [Computing the factor sets](#Computing-the-factor-sets)\n", " - [Accumulating polynomials](#Accumulating-polynomials)\n", " - [Computing ZVP points](#Computing-ZVP-points)\n", " - [Remapping](#Remapping)\n", " - [Distinguishing map and distinguishing tree building](#Distinguishing-map-and-distinguishing-tree-building)\n", " - [Evaluation](#Evaluation)\n" ] }, { "cell_type": "code", "id": "17a9e580-5f1e-45c9-8afd-fc35e833b0b0", "metadata": {}, "source": [ "import io\n", "import holoviews as hv\n", "import pickle\n", "import multiprocessing\n", "import inspect\n", "import tempfile\n", "import sys\n", "import re\n", "from collections import Counter\n", "from matplotlib import pyplot as plt\n", "from sympy import FF, ZZ, symbols, Poly\n", "from contextlib import contextmanager\n", "from importlib import import_module, invalidate_caches\n", "from pathlib import Path\n", "from itertools import product\n", "from IPython.display import display\n", "from tqdm.notebook import tqdm, trange\n", "from anytree import LevelOrderIter, PreOrderIter\n", "\n", "\n", "from pyecsca.ec.model import ShortWeierstrassModel\n", "from pyecsca.ec.coordinates import AffineCoordinateModel\n", "from pyecsca.ec.curve import EllipticCurve\n", "from pyecsca.ec.params import DomainParameters, load_params_ecgen\n", "from pyecsca.ec.formula import AdditionFormula, DoublingFormula\n", "from pyecsca.ec.point import Point\n", "from pyecsca.ec.mod import mod, SymbolicMod\n", "from pyecsca.ec.mult import LTRMultiplier, AccumulationOrder\n", "from pyecsca.ec.error import UnsatisfiedAssumptionError\n", "from pyecsca.sca.re.tree import Map, Tree\n", "from pyecsca.sca.re.zvp import zvp_points, compute_factor_set, addition_chain, eliminate_y\n", "from pyecsca.misc.cfg import getconfig\n", "from pyecsca.misc.utils import TaskExecutor\n", "\n", "from eval import (eval_tree_symmetric1, eval_tree_asymmetric1, eval_tree_binomial1,\n", " success_rate_symmetric, success_rate_asymmetric, success_rate_binomial,\n", " query_rate_symmetric, query_rate_asymmetric, query_rate_binomial,\n", " amount_rate_symmetric, amount_rate_asymmetric, amount_rate_binomial,\n", " precise_rate_symmetric, precise_rate_asymmetric, precise_rate_binomial,\n", " success_rate_vs_majority_symmetric, success_rate_vs_majority_asymmetric,\n", " success_rate_vs_query_rate_symmetric, load, store)\n", "\n", "\n", "# Allow to use \"spawn\" multiprocessing method for function defined in a Jupyter notebook.\n", "# https://neuromancer.sk/article/35\n", "@contextmanager\n", "def enable_spawn(func):\n", " invalidate_caches()\n", " source = inspect.getsource(func)\n", " with tempfile.NamedTemporaryFile(suffix=\".py\", mode=\"w\") as f:\n", " f.write(source)\n", " f.flush()\n", " path = Path(f.name)\n", " directory = str(path.parent)\n", " sys.path.append(directory)\n", " module = import_module(str(path.stem))\n", " yield getattr(module, func.__name__)\n", " sys.path.remove(directory)\n", "\n", "spawn_context = multiprocessing.get_context(\"spawn\")\n", "\n", "%matplotlib ipympl\n", "hv.extension(\"bokeh\")" ], "outputs": [], "execution_count": null }, { "cell_type": "code", "id": "faca31e8-fe51-4017-a41d-ba31b15c548d", "metadata": {}, "source": [ "model = ShortWeierstrassModel()\n", "coordsaff = AffineCoordinateModel(model)" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "id": "60547b40-9b8e-409b-8b7e-b3dc266c01d4", "metadata": {}, "source": [ "## Exploration\n", "First lets explore the behavior of addition formulas. The following two cells pick a coordinate model along with some formulas and symbolically unroll a scalar multiplication (assuming a simple LTR multiplier)." ] }, { "cell_type": "code", "id": "8de124f1-9498-4e55-8b7f-1bd291ccf3fe", "metadata": {}, "source": [ "which = \"jacobian\"\n", "coords = model.coordinates[which]" ], "outputs": [], "execution_count": null }, { "cell_type": "code", "id": "2193ab53-9dc9-4ba4-89d3-e331e5cc20de", "metadata": {}, "source": [ "getconfig().ec.mod_implementation = \"symbolic\"\n", "x, y, z = symbols(\"x y z\")\n", "\n", "# A 64-bit prime order curve for testing things out\n", "p = 0xc50de883f0e7b167\n", "field = FF(p)\n", "a = SymbolicMod(Poly(0x4833d7aa73fa6694, x, y, z, domain=field), p)\n", "b = SymbolicMod(Poly(0xa6c44a61c5323f6a, x, y, z, domain=field), p)\n", "gx = SymbolicMod(Poly(0x5fd1f7d38d4f2333, x, y, z, domain=field), p)\n", "gy = SymbolicMod(Poly(0x21f43957d7e20ceb, x, y, z, domain=field), p)\n", "n = 0xc50de885003b80eb\n", "h = 1\n", "\n", "infty = Point(coords, X=mod(0, p), Y=mod(1, p), Z=mod(0, p))\n", "g = Point(coords, X=gx, Y=gy, Z=mod(1, p))\n", "\n", "curve = EllipticCurve(model, coords, p, infty, dict(a=a,b=b))\n", "params = DomainParameters(curve, g, n, h)\n", "\n", "\n", "add = coords.formulas[\"add-2007-bl\"]\n", "dbl = coords.formulas[\"dbl-2007-bl\"]\n", "mult = LTRMultiplier(add, dbl, None, False, AccumulationOrder.PeqRP, True, True)\n", "\n", "\n", "point = Point(coords,\n", " X=SymbolicMod(Poly(x, x, y, z, domain=field), params.curve.prime),\n", " Y=SymbolicMod(Poly(y, x, y, z, domain=field), params.curve.prime),\n", " Z=SymbolicMod(Poly(z, x, y, z, domain=field), params.curve.prime))\n", "mult.init(params, point)\n", "res = mult.multiply(5)\n", "\n", "x_poly = Poly(res.X.x, domain=field)\n", "y_poly = Poly(res.Y.x, domain=field)\n", "z_poly = Poly(res.Z.x, domain=field)\n", "display(x_poly, y_poly, z_poly)" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "id": "0bcc8b9e-39ad-4b53-8f45-a7552b05baa2", "metadata": {}, "source": [ "The result is a Point with coordinates that are polynomials in the input coordinates and curve parameters. We now switch back to concrete representation." ] }, { "cell_type": "code", "id": "d8ea0c4d-86e1-46af-ac20-569e6ef5439d", "metadata": {}, "source": [ "cfg = getconfig()\n", "cfg.ec.mod_implementation = \"gmp\"" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "id": "c3b3ae94-242b-4f36-81e3-e8a64b5af33c", "metadata": {}, "source": [ "## Reverse-engineering\n", "Now, lets look at using the ZVP attack for reverse-engineering. First pick 10 curves per group, some random some with $a \\in \\{0, -1, -3 \\}$. The curves are otherwise not special in any way and just serve to randomize the process, as the existence of ZVP points for a given intermediate value polynomial depends on the curve." ] }, { "cell_type": "code", "id": "0252f8fa-012c-453c-ba23-b40f9686fcce", "metadata": {}, "source": [ "curves = list(map(lambda spec: load_params_ecgen(io.BytesIO(spec.encode()), \"affine\"), [\n", " # Random\n", " \"\"\"[{\"field\":{\"p\":\"0xddf438409fc35161\"},\"a\":\"0x94d919b72f7dc6d8\",\"b\":\"0x9f39032abb23f62a\",\"order\":\"0xddf4383ffa8e6de7\",\"subgroups\":[{\"x\":\"0xd5673b3fe176fc6b\",\"y\":\"0x2d5b0a5bb2141317\",\"order\":\"0xddf4383ffa8e6de7\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0xd5673b3fe176fc6b\",\"y\":\"0x2d5b0a5bb2141317\",\"order\":\"0xddf4383ffa8e6de7\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xa42c1467a1ed04f3\"},\"a\":\"0x55d07340a4572f2d\",\"b\":\"0x0a938c37dfb0b6d5\",\"order\":\"0xa42c14689284d3a7\",\"subgroups\":[{\"x\":\"0x8633981c83ed43a2\",\"y\":\"0x7b5374e9d7997199\",\"order\":\"0xa42c14689284d3a7\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x8633981c83ed43a2\",\"y\":\"0x7b5374e9d7997199\",\"order\":\"0xa42c14689284d3a7\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xea0d9cead19016ab\"},\"a\":\"0xcbbfe501c4ef6d92\",\"b\":\"0x5762de777a6d9178\",\"order\":\"0xea0d9cea8cd2c857\",\"subgroups\":[{\"x\":\"0xe7daa3e061c3111b\",\"y\":\"0x56ee59a6845c5e93\",\"order\":\"0xea0d9cea8cd2c857\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0xe7daa3e061c3111b\",\"y\":\"0x56ee59a6845c5e93\",\"order\":\"0xea0d9cea8cd2c857\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0x9c7e7216decb71a7\"},\"a\":\"0x324ef48887401a87\",\"b\":\"0x3ce6f35a00280102\",\"order\":\"0x9c7e72175ebfe709\",\"subgroups\":[{\"x\":\"0x34683229b405418d\",\"y\":\"0x308c923cae004514\",\"order\":\"0x9c7e72175ebfe709\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x34683229b405418d\",\"y\":\"0x308c923cae004514\",\"order\":\"0x9c7e72175ebfe709\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xeb5779f0bbf1ef5b\"},\"a\":\"0x2419e8bbc7b5f8f2\",\"b\":\"0xe74e5d3064a4f2e3\",\"order\":\"0xeb5779f21320c2e9\",\"subgroups\":[{\"x\":\"0x3b6c269560abeb00\",\"y\":\"0x29d157628e75e1c0\",\"order\":\"0xeb5779f21320c2e9\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x3b6c269560abeb00\",\"y\":\"0x29d157628e75e1c0\",\"order\":\"0xeb5779f21320c2e9\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0x97b6ea097868b95d\"},\"a\":\"0x550a41d65e4bcd13\",\"b\":\"0x47c5e527113b261c\",\"order\":\"0x97b6ea094947a76b\",\"subgroups\":[{\"x\":\"0x1e669fe19c865bd9\",\"y\":\"0x05a6bb891920440f\",\"order\":\"0x97b6ea094947a76b\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x1e669fe19c865bd9\",\"y\":\"0x05a6bb891920440f\",\"order\":\"0x97b6ea094947a76b\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xa00629e6522032f7\"},\"a\":\"0x896f04a7ae302922\",\"b\":\"0x6bc03365b1f1cb50\",\"order\":\"0xa00629e5c03cf913\",\"subgroups\":[{\"x\":\"0x14b7b48954936d4e\",\"y\":\"0x670dc776273bf899\",\"order\":\"0xa00629e5c03cf913\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x14b7b48954936d4e\",\"y\":\"0x670dc776273bf899\",\"order\":\"0xa00629e5c03cf913\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xd47ec1d03a62686d\"},\"a\":\"0xd00a3ee0f5c86b02\",\"b\":\"0x457a5b6c47db38d8\",\"order\":\"0xd47ec1d107db7d6f\",\"subgroups\":[{\"x\":\"0x41ebc3b763f3cd1b\",\"y\":\"0x3d6925f214620e0c\",\"order\":\"0xd47ec1d107db7d6f\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x41ebc3b763f3cd1b\",\"y\":\"0x3d6925f214620e0c\",\"order\":\"0xd47ec1d107db7d6f\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xb1c9115c6f40d755\"},\"a\":\"0x79d3ceefafc44ce9\",\"b\":\"0x8316af84264df42b\",\"order\":\"0xb1c9115d17f84a45\",\"subgroups\":[{\"x\":\"0x8b0a274089b53fe5\",\"y\":\"0x3508d33c4beba5ad\",\"order\":\"0xb1c9115d17f84a45\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x8b0a274089b53fe5\",\"y\":\"0x3508d33c4beba5ad\",\"order\":\"0xb1c9115d17f84a45\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0x8f738fda18cd5dff\"},\"a\":\"0x4747f2f9b8628cbf\",\"b\":\"0x586cdb9378a1389f\",\"order\":\"0x8f738fd8fc7ebed3\",\"subgroups\":[{\"x\":\"0x7ad306c73b64c1b5\",\"y\":\"0x69e3ca555190da4b\",\"order\":\"0x8f738fd8fc7ebed3\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x7ad306c73b64c1b5\",\"y\":\"0x69e3ca555190da4b\",\"order\":\"0x8f738fd8fc7ebed3\"}]}]}]\"\"\",\n", " # a = -1\n", " \"\"\"[{\"field\":{\"p\":\"0xcfef393139c3007f\"},\"a\":\"0xcfef393139c3007e\",\"b\":\"0x950312812acb155f\",\"order\":\"0xcfef39320179387b\",\"subgroups\":[{\"x\":\"0xae2d2f58ca5b5cf7\",\"y\":\"0xc3a4bf3a1dc10005\",\"order\":\"0xcfef39320179387b\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0xae2d2f58ca5b5cf7\",\"y\":\"0xc3a4bf3a1dc10005\",\"order\":\"0xcfef39320179387b\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xb0461c0e4946cbd5\"},\"a\":\"0xb0461c0e4946cbd4\",\"b\":\"0x082c3722016def51\",\"order\":\"0xb0461c0e07e3e1bf\",\"subgroups\":[{\"x\":\"0x5142200263be1fe3\",\"y\":\"0x14984b7551ed21a9\",\"order\":\"0xb0461c0e07e3e1bf\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x5142200263be1fe3\",\"y\":\"0x14984b7551ed21a9\",\"order\":\"0xb0461c0e07e3e1bf\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xeff607c2dc4f278b\"},\"a\":\"0xeff607c2dc4f278a\",\"b\":\"0x26fd03674f5092d2\",\"order\":\"0xeff607c30ab8c50d\",\"subgroups\":[{\"x\":\"0x004d4a5a9bb849fe\",\"y\":\"0x80eb7ef89110c149\",\"order\":\"0xeff607c30ab8c50d\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x004d4a5a9bb849fe\",\"y\":\"0x80eb7ef89110c149\",\"order\":\"0xeff607c30ab8c50d\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xedc14fda51686379\"},\"a\":\"0xedc14fda51686378\",\"b\":\"0xb3973a86901e3364\",\"order\":\"0xedc14fda0cdbc199\",\"subgroups\":[{\"x\":\"0xc76f0776feb59336\",\"y\":\"0x625adaf0fb44ab9f\",\"order\":\"0xedc14fda0cdbc199\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0xc76f0776feb59336\",\"y\":\"0x625adaf0fb44ab9f\",\"order\":\"0xedc14fda0cdbc199\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xfc6ee07288f1b78f\"},\"a\":\"0xfc6ee07288f1b78e\",\"b\":\"0xe18821a83ca2ca30\",\"order\":\"0xfc6ee0713e07f37f\",\"subgroups\":[{\"x\":\"0x339d01a4b0db428e\",\"y\":\"0x68100d42e5ffd979\",\"order\":\"0xfc6ee0713e07f37f\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x339d01a4b0db428e\",\"y\":\"0x68100d42e5ffd979\",\"order\":\"0xfc6ee0713e07f37f\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xa03c03a0072f69b3\"},\"a\":\"0xa03c03a0072f69b2\",\"b\":\"0x3208ecebb633b82c\",\"order\":\"0xa03c039ff31e37a7\",\"subgroups\":[{\"x\":\"0x8134208d53e6f6c0\",\"y\":\"0x6245db54032630a6\",\"order\":\"0xa03c039ff31e37a7\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x8134208d53e6f6c0\",\"y\":\"0x6245db54032630a6\",\"order\":\"0xa03c039ff31e37a7\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xbc8c6e7ce26746d9\"},\"a\":\"0xbc8c6e7ce26746d8\",\"b\":\"0xb7e2b4fb2d769c4e\",\"order\":\"0xbc8c6e7ba032dda7\",\"subgroups\":[{\"x\":\"0x8e3c9cd771e7ffd8\",\"y\":\"0x4dd02403ca890c5a\",\"order\":\"0xbc8c6e7ba032dda7\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x8e3c9cd771e7ffd8\",\"y\":\"0x4dd02403ca890c5a\",\"order\":\"0xbc8c6e7ba032dda7\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0x9ccda4c062b95787\"},\"a\":\"0x9ccda4c062b95786\",\"b\":\"0x31fcbb278951e3b9\",\"order\":\"0x9ccda4bfae73e4f5\",\"subgroups\":[{\"x\":\"0x303ac583c81644e3\",\"y\":\"0x76713f6f470e94a0\",\"order\":\"0x9ccda4bfae73e4f5\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x303ac583c81644e3\",\"y\":\"0x76713f6f470e94a0\",\"order\":\"0x9ccda4bfae73e4f5\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xa339e3745518416f\"},\"a\":\"0xa339e3745518416e\",\"b\":\"0x52d39a67f2401673\",\"order\":\"0xa339e3743950389b\",\"subgroups\":[{\"x\":\"0x6b8986f706afac58\",\"y\":\"0x5c901b1afa0b64da\",\"order\":\"0xa339e3743950389b\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x6b8986f706afac58\",\"y\":\"0x5c901b1afa0b64da\",\"order\":\"0xa339e3743950389b\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0x8b7d2baee4e47311\"},\"a\":\"0x8b7d2baee4e47310\",\"b\":\"0x21ab23afb5a9e2ca\",\"order\":\"0x8b7d2baf201f2bdd\",\"subgroups\":[{\"x\":\"0x797c1dec0d73ec64\",\"y\":\"0x28f90926ea9c6b33\",\"order\":\"0x8b7d2baf201f2bdd\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x797c1dec0d73ec64\",\"y\":\"0x28f90926ea9c6b33\",\"order\":\"0x8b7d2baf201f2bdd\"}]}]}]\"\"\",\n", " # a = -3\n", " \"\"\"[{\"field\":{\"p\":\"0x8d79ca36cee026a7\"},\"a\":\"0x8d79ca36cee026a4\",\"b\":\"0x0478c1f80ce2c9c6\",\"order\":\"0x8d79ca35a428c76f\",\"subgroups\":[{\"x\":\"0x2e94a3e38f8b345e\",\"y\":\"0x83e6c6f0cb8f69c4\",\"order\":\"0x8d79ca35a428c76f\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x2e94a3e38f8b345e\",\"y\":\"0x83e6c6f0cb8f69c4\",\"order\":\"0x8d79ca35a428c76f\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0x48e1a125250323a7\"},\"a\":\"0x48e1a125250323a4\",\"b\":\"0x02a4d99f41d23210\",\"order\":\"0x48e1a124f895db6d\",\"subgroups\":[{\"x\":\"0x409e15d65fcae55a\",\"y\":\"0x207e142056d62d07\",\"order\":\"0x48e1a124f895db6d\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x409e15d65fcae55a\",\"y\":\"0x207e142056d62d07\",\"order\":\"0x48e1a124f895db6d\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xcb5aa8a7a10aa06b\"},\"a\":\"0xcb5aa8a7a10aa068\",\"b\":\"0x31fe9c57c570174f\",\"order\":\"0xcb5aa8a6cf812191\",\"subgroups\":[{\"x\":\"0x84c75d46fc687ff1\",\"y\":\"0x7424362ac73df187\",\"order\":\"0xcb5aa8a6cf812191\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x84c75d46fc687ff1\",\"y\":\"0x7424362ac73df187\",\"order\":\"0xcb5aa8a6cf812191\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xba965ca9c8aa0a1b\"},\"a\":\"0xba965ca9c8aa0a18\",\"b\":\"0x676535a1eaf5c605\",\"order\":\"0xba965caae5741b6f\",\"subgroups\":[{\"x\":\"0x313d58c47b8ed95f\",\"y\":\"0x991ba98cbbb0fe9f\",\"order\":\"0xba965caae5741b6f\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x313d58c47b8ed95f\",\"y\":\"0x991ba98cbbb0fe9f\",\"order\":\"0xba965caae5741b6f\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xbfb7747454a17d15\"},\"a\":\"0xbfb7747454a17d12\",\"b\":\"0x611b69881db4ce69\",\"order\":\"0xbfb7747547fd57d3\",\"subgroups\":[{\"x\":\"0x3385044d698640fc\",\"y\":\"0x50cee623251b559e\",\"order\":\"0xbfb7747547fd57d3\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x3385044d698640fc\",\"y\":\"0x50cee623251b559e\",\"order\":\"0xbfb7747547fd57d3\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0x99235f1ed44b3959\"},\"a\":\"0x99235f1ed44b3956\",\"b\":\"0x5d8dda19dbe804d4\",\"order\":\"0x99235f1d975f376d\",\"subgroups\":[{\"x\":\"0x4fed262974c1d800\",\"y\":\"0x27590c454edd59ca\",\"order\":\"0x99235f1d975f376d\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x4fed262974c1d800\",\"y\":\"0x27590c454edd59ca\",\"order\":\"0x99235f1d975f376d\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xa7ff74a0dc8c161d\"},\"a\":\"0xa7ff74a0dc8c161a\",\"b\":\"0x583b968bb611b284\",\"order\":\"0xa7ff74a06811ee75\",\"subgroups\":[{\"x\":\"0x5f5c76454edf12e7\",\"y\":\"0x4c73cbfc44f41508\",\"order\":\"0xa7ff74a06811ee75\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x5f5c76454edf12e7\",\"y\":\"0x4c73cbfc44f41508\",\"order\":\"0xa7ff74a06811ee75\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xb52c62ca8703a063\"},\"a\":\"0xb52c62ca8703a060\",\"b\":\"0x0baec43a07b54c21\",\"order\":\"0xb52c62c963037121\",\"subgroups\":[{\"x\":\"0x6fe4a521a29bc1ab\",\"y\":\"0x3fca7180021f8f0f\",\"order\":\"0xb52c62c963037121\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x6fe4a521a29bc1ab\",\"y\":\"0x3fca7180021f8f0f\",\"order\":\"0xb52c62c963037121\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xb8921f25b6ce5267\"},\"a\":\"0xb8921f25b6ce5264\",\"b\":\"0xa575c9f97563265d\",\"order\":\"0xb8921f2592b6b39f\",\"subgroups\":[{\"x\":\"0x7eb120fada47765c\",\"y\":\"0x64ef4e51d4159304\",\"order\":\"0xb8921f2592b6b39f\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x7eb120fada47765c\",\"y\":\"0x64ef4e51d4159304\",\"order\":\"0xb8921f2592b6b39f\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xc591b8c4df0afc19\"},\"a\":\"0xc591b8c4df0afc16\",\"b\":\"0x0a1eb46a6e647f0a\",\"order\":\"0xc591b8c3eb07239f\",\"subgroups\":[{\"x\":\"0x1963bfb862cb0bf3\",\"y\":\"0x30da8bb7fa77277d\",\"order\":\"0xc591b8c3eb07239f\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x1963bfb862cb0bf3\",\"y\":\"0x30da8bb7fa77277d\",\"order\":\"0xc591b8c3eb07239f\"}]}]}]\"\"\",\n", " # a = 0\n", " \"\"\"[{\"field\":{\"p\":\"0xceaf446a53f14bc1\"},\"a\":\"0x0000000000000000\",\"b\":\"0x326539376260f173\",\"order\":\"0xceaf446aae275419\",\"subgroups\":[{\"x\":\"0x98fe44948c3f8678\",\"y\":\"0x3d440ee959a912d7\",\"order\":\"0xceaf446aae275419\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x98fe44948c3f8678\",\"y\":\"0x3d440ee959a912d7\",\"order\":\"0xceaf446aae275419\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xb3c2beca75d66de3\"},\"a\":\"0x0000000000000000\",\"b\":\"0x46069225826b51aa\",\"order\":\"0xb3c2bec95881b695\",\"subgroups\":[{\"x\":\"0x81500c226efa0d5a\",\"y\":\"0x674e09d296452eee\",\"order\":\"0xb3c2bec95881b695\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x81500c226efa0d5a\",\"y\":\"0x674e09d296452eee\",\"order\":\"0xb3c2bec95881b695\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xd6097c1ce207aae7\"},\"a\":\"0x0000000000000000\",\"b\":\"0x7adaab54e7dfd564\",\"order\":\"0xd6097c1b407eb413\",\"subgroups\":[{\"x\":\"0x151da8fb1f83201e\",\"y\":\"0x8bfeb90ec1177a91\",\"order\":\"0xd6097c1b407eb413\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x151da8fb1f83201e\",\"y\":\"0x8bfeb90ec1177a91\",\"order\":\"0xd6097c1b407eb413\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0x97a3e2d617a2309d\"},\"a\":\"0x0000000000000000\",\"b\":\"0x7f311cba46652247\",\"order\":\"0x97a3e2d712ffd715\",\"subgroups\":[{\"x\":\"0x46d725812af15870\",\"y\":\"0x727f88365dbd0e80\",\"order\":\"0x97a3e2d712ffd715\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x46d725812af15870\",\"y\":\"0x727f88365dbd0e80\",\"order\":\"0x97a3e2d712ffd715\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xd8d7f39f545a5da7\"},\"a\":\"0x0000000000000000\",\"b\":\"0x09097ddcd4be8d55\",\"order\":\"0xd8d7f3a0c4115b4b\",\"subgroups\":[{\"x\":\"0xc5c771a9827a3251\",\"y\":\"0x64bf52041ac05b23\",\"order\":\"0xd8d7f3a0c4115b4b\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0xc5c771a9827a3251\",\"y\":\"0x64bf52041ac05b23\",\"order\":\"0xd8d7f3a0c4115b4b\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0x847de883ab4fbf4d\"},\"a\":\"0x0000000000000000\",\"b\":\"0x09866366b3b45c2d\",\"order\":\"0x847de8837e6d4477\",\"subgroups\":[{\"x\":\"0x62fd7b4bc7c9acb4\",\"y\":\"0x2d0942774607106b\",\"order\":\"0x847de8837e6d4477\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x62fd7b4bc7c9acb4\",\"y\":\"0x2d0942774607106b\",\"order\":\"0x847de8837e6d4477\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xf0d617c3c47b7c77\"},\"a\":\"0x0000000000000000\",\"b\":\"0xd856b3dcb95764a2\",\"order\":\"0xf0d617c5512cec85\",\"subgroups\":[{\"x\":\"0xeaf9b352a3daac45\",\"y\":\"0x4e4e557f9fc3febc\",\"order\":\"0xf0d617c5512cec85\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0xeaf9b352a3daac45\",\"y\":\"0x4e4e557f9fc3febc\",\"order\":\"0xf0d617c5512cec85\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xce920b656c80b373\"},\"a\":\"0x0000000000000000\",\"b\":\"0xb4a07dfae71ddc62\",\"order\":\"0xce920b65eee38015\",\"subgroups\":[{\"x\":\"0x7895c02b3c5205b5\",\"y\":\"0x2926be6446b98d62\",\"order\":\"0xce920b65eee38015\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x7895c02b3c5205b5\",\"y\":\"0x2926be6446b98d62\",\"order\":\"0xce920b65eee38015\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xb6d4e25f76cc9df7\"},\"a\":\"0x0000000000000000\",\"b\":\"0x18e95a2283692623\",\"order\":\"0xb6d4e25ea270ed03\",\"subgroups\":[{\"x\":\"0x2da7a97d5d899bc5\",\"y\":\"0x17d27fd34562e3d9\",\"order\":\"0xb6d4e25ea270ed03\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x2da7a97d5d899bc5\",\"y\":\"0x17d27fd34562e3d9\",\"order\":\"0xb6d4e25ea270ed03\"}]}]}]\"\"\",\n", " \"\"\"[{\"field\":{\"p\":\"0xe7cd1979ebed69ed\"},\"a\":\"0x0000000000000000\",\"b\":\"0x278e92b83191a7da\",\"order\":\"0xe7cd197966893365\",\"subgroups\":[{\"x\":\"0xc4de44402da5b9a6\",\"y\":\"0x2b45e7f32e3701ba\",\"order\":\"0xe7cd197966893365\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0xc4de44402da5b9a6\",\"y\":\"0x2b45e7f32e3701ba\",\"order\":\"0xe7cd197966893365\"}]}]}]\"\"\"\n", " # b = 0 (causes more issues than gain) but the (w12-0) coords actually require it...\n", " #\"\"\"[{\"field\":{\"p\":\"0x9d9119957f02fe3f\"},\"a\":\"0x0106903196d88df9\",\"b\":\"0x0000000000000000\",\"order\":\"0x9d9119957f02fe40\",\"subgroups\":[{\"x\":\"0x191a36b9cd81de96\",\"y\":\"0x10f2c6bded391aa9\",\"order\":\"0x9d9119957f02fe40\",\"cofactor\":\"0x1\",\"points\":[{\"x\":\"0x0000000000000000\",\"y\":\"0x0000000000000000\",\"order\":\"0x2\"},{\"x\":\"0x95913fae9065da0f\",\"y\":\"0x5eeddeee7152d6fb\",\"order\":\"0x276446655fc0bf9\"}]}]}]\"\"\"\n", "]))\n", "\n", "for i, params in enumerate(curves):\n", " curve = params.curve\n", " if curve.parameters[\"a\"] == -3:\n", " params.name = \"a=-3\"\n", " elif curve.parameters[\"a\"] == -1:\n", " params.name = \"a=-1\"\n", " elif curve.parameters[\"a\"] == 0:\n", " params.name = \"a=0\"\n", " else:\n", " params.name = \"random\"\n", " params.name += f\"[{i}]\"" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "id": "4276de4c-78f4-4cdb-b60e-8c24eabfa00d", "metadata": {}, "source": [ "### Computing addition chains\n", "\n", "First lets fix some scalars, go over the curves and compute the addition chain to obtain information about which multiples of the input point will go into the formulas. The i-th scalar will be used with the i-th curve as defined above. There are 10 unique scalars, so each curve group will share those." ] }, { "cell_type": "code", "id": "7ab00a5c-2873-40c0-a81c-873350897e46", "metadata": {}, "source": [ "scalars = [0b1111110, 0b1011101, 0b110110, 0b100100, 0b1000110, 0b1001101, 0b101001, 0b1100100, 0b1010110, 0b101010] * 4\n", "\n", "chains = []\n", "scalar_map = {}\n", "chain_map = {}\n", "ops = set()\n", "for scalar, params in zip(scalars, curves):\n", " chain = addition_chain(scalar, params, LTRMultiplier, lambda add,dbl: LTRMultiplier(add, dbl, None, False, AccumulationOrder.PeqRP, True, True))\n", " chains.append(chain)\n", " scalar_map[params] = scalar\n", " chain_map[params] = chain\n", " ops.update(chain)\n", "print(sorted(list(ops)))" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "id": "8d1df0a5-ac90-45ee-b54a-1fa25dd86c74", "metadata": {}, "source": [ "### Loading the formulas\n", "\n", "Now lets load the formulas, either just those from the EFD or also load the expanded library formulas if they are available. See the [formulas](formulas.ipynb) notebook." ] }, { "cell_type": "code", "id": "da4e2981-cf3d-40ea-9d1e-9b6c57a6e01d", "metadata": {}, "source": [ "load_expanded = False\n", "\n", "formula_classes = [AdditionFormula, DoublingFormula]\n", "formula_groups = {}\n", "for coord_name, coords in tqdm(model.coordinates.items(), desc=f\"Loading {'expanded' if load_expanded else 'EFD'} formulas\"):\n", " groups = []\n", " for formula_class in formula_classes:\n", " expanded_path = Path(f\"sw_{coord_name}_{formula_class.shortname}s.pickle\")\n", " if load_expanded:\n", " if not expanded_path.exists():\n", " raise ValueError(f\"Expanded formulas do not exist {expanded_path}.\")\n", " with expanded_path.open(\"rb\") as f:\n", " expanded = pickle.load(f)\n", " formula_group = list(expanded)\n", " else:\n", " formula_group = list(filter(lambda formula: isinstance(formula, formula_class) and (formula.name.startswith(\"add\") or formula.name.startswith(\"dbl\")), coords.formulas.values()))\n", " groups.append(formula_group)\n", " formula_groups[coords] = groups\n", "\n", "print(f\"Loaded {sum(sum(len(group) for group in pair) for pair in formula_groups.values())} formulas.\")" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "id": "12646534-8ca5-48c1-a4ae-1ad62575821f", "metadata": {}, "source": [ "### Computing the factor sets\n", "\n", "Now, compute the factor sets of the formulas **in parallel**. There are two options available. `xonly_fsets` builds the factor sets \"x\"-only by eliminating y-coords using the curve equation. `filter_nonhomo` specifies whether to filter out non-homogenous polynomials.\n", "\n", "