aboutsummaryrefslogtreecommitdiffhomepage
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Configuration space\n",
    "This notebook explores the configuration space of Elliptic Curve crypto\n",
    "implementations.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "An ECC implementation configuration in **pyecsca** has the following attributes: "
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "from typing import get_args\n",
    "from pyecsca.ec.configuration import Configuration\n",
    "from dataclasses import fields\n",
    "\n",
    "for field in fields(Configuration):\n",
    "\tname = field.name\n",
    "\ttp = field.type\n",
    "\tdoc = tp.__doc__\n",
    "\tif get_args(field.type):\n",
    "\t\tdoc = get_args(field.type)[0].__doc__\n",
    "\tprint(name, tp)\n",
    "\tprint(\"   \", doc.strip().split(\"\\n\")[0])\n",
    "\tif hasattr(tp, \"names\"):\n",
    "\t\tfor enum_name in tp.names():\n",
    "\t\t\tprint(\"       \", enum_name)\n",
    "\tprint()"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "It is represented by the [Configuration](../api/pyecsca.ec.configuration.rst#pyecsca.ec.configuration.Configuration) class."
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Enumerating configurations\n",
    "\n",
    "The possible configurations can be generated using the [all_configurations()](../api/pyecsca.ec.configuration.rst#pyecsca.ec.configuration.all_configurations) function.\n",
    "The whole space of configurations is quite huge.\n",
    "\n",
    "<div class=\"alert alert-warning\">\n",
    "\n",
    "Note that the amount of possible parametrizations of some scalar multipliers is very large (e.g. window size) so **pyecsca** has\n",
    "to restrict this to a reasonable selection. Specifically the function below only considers a few options for window size and\n",
    "similar parameters. **Even then, the cell below takes roughly 10 minutes to run.**\n",
    "\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "from pyecsca.ec.configuration import all_configurations\n",
    "\n",
    "total = sum(1 for _ in all_configurations())\n",
    "print(total)"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A large part of the configuration space is due to the independent options which consist of:\n",
    " \n",
    " - `hash_type` of type `HashType` $*6$\n",
    " - `mod_rand` of type `RandomMod` $*2$\n",
    " - `mult` of type `Multiplication` $*4$\n",
    " - `sqr` of type `Squaring` $*4$\n",
    " - `red` of type `Reduction` $*3$\n",
    " - `inv` of type `Inversion` $*2$\n",
    "\n",
    "Without these, the space is somewhat smaller:"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "no_hash_and_rand = (4*4*3*2)\n",
    "no_ff = (6*2)\n",
    "no_indep = no_ff * no_hash_and_rand"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "print(total // no_indep)"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To restrict the generated configurations, pass keyword arguments to the\n",
    "`all_configurations` matching the names of the attributes of the `Configuration` object."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "from pyecsca.ec.configuration import HashType, RandomMod, Multiplication, Squaring, Reduction, Inversion\n",
    "from pyecsca.ec.model import ShortWeierstrassModel\n",
    "from pyecsca.ec.mult import LTRMultiplier\n",
    "\n",
    "model = ShortWeierstrassModel()\n",
    "coords = model.coordinates[\"projective\"]\n",
    "scalarmult = LTRMultiplier\n",
    "independent_opts = {\n",
    "\t\"hash_type\": HashType.SHA256,\n",
    "\t\"mod_rand\": RandomMod.SAMPLE,\n",
    "\t\"mult\": Multiplication.KARATSUBA,\n",
    "\t\"sqr\": Squaring.KARATSUBA,\n",
    "\t\"red\": Reduction.MONTGOMERY,\n",
    "    \"inv\": Inversion.GCD\n",
    "}\n",
    "\n",
    "configs = list(all_configurations(model=model, coords=coords, scalarmult=scalarmult,\n",
    "\t\t\t\t\t\t\t \t  **independent_opts))\n",
    "print(len(configs))"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We see that when we fixed all parameters except for the scalar multiplier arguments \n",
    "(see the [LTRMultiplier](../api/pyecsca.ec.mult.binary.rst#pyecsca.ec.mult.binary.LTRMultiplier) constructor) we obtained 1280 configurations. That number expresses all of the possible ways to use addition formulas for the `projective` coordinate system in the binary left-to-right multiplier as well as internal options of that multiplier:\n",
    "\n",
    " - whether it is \"complete\" in a sense that it starts processing at a constant bit (the bit-length od the order)\n",
    " - whether it is \"double-and-add-always\"\n",
    " - whether it \"short-circuits\" the formulas, i.e. detects that an exceptional point was input into them and returns correctly\n",
    "   without executing them."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Models"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can explore the number of configurations for each of the supported curve models."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "from IPython.display import HTML, display\n",
    "import tabulate\n",
    "from pyecsca.ec.model import *\n",
    "from pyecsca.ec.mult import ProcessingDirection, AccumulationOrder\n",
    "\n",
    "model_counts = [[\"Model\", \"All\", \"Without independent options\", \"Without independent options and scaling\", \"Without independent options and scalarmult options\"]]\n",
    "totals = [\"Total\", 0, 0, 0, 0]\n",
    "for model in (ShortWeierstrassModel(), MontgomeryModel(), EdwardsModel(), TwistedEdwardsModel()):\n",
    "\tname = model.__class__.__name__\n",
    "\tcount = sum(1 for _ in all_configurations(model=model, **independent_opts))\n",
    "\tcount_no_scl = sum(1 for _ in all_configurations(model=model, **independent_opts, scalarmult={\"scl\": None}))\n",
    "\tcount_no_opts = sum(1 for _ in all_configurations(model=model, **independent_opts, scalarmult={\"scl\": None, \"always\": True, \"short_circuit\": True, \"complete\": False, \"precompute_negation\": True, \"width\": 3, \"m\": 3, \"direction\": ProcessingDirection.LTR, \"accumulation_order\": AccumulationOrder.PeqPR, \"recoding_direction\": ProcessingDirection.LTR}))\n",
    "\tmodel_counts.append([name, count * no_ff, count, count_no_scl, count_no_opts])\n",
    "\ttotals[1] += count * no_ff\n",
    "\ttotals[2] += count\n",
    "\ttotals[3] += count_no_scl\n",
    "\ttotals[4] += count_no_opts\n",
    "model_counts.append(totals)\n",
    "display(HTML(tabulate.tabulate(model_counts, tablefmt=\"html\", headers=\"firstrow\")))"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Coordinate systems"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's now look at the configuration split for coordinate systems:"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "coords_counts = [[\"Model\", \"Coords\", \"All\", \"Without independent options\", \"Without independent options and scaling\", \"Without independent options and scalarmult options\"]]\n",
    "for model in (ShortWeierstrassModel(), MontgomeryModel(), EdwardsModel(), TwistedEdwardsModel()):\n",
    "\tmodel_name = model.__class__.__name__\n",
    "\tcoords_counts.append([model_name, \"\", \"\", \"\", \"\", \"\"])\n",
    "\tfor coords in sorted(model.coordinates.values(), key=lambda c: c.name):\n",
    "\t\tcoords_name = coords.name\n",
    "\t\tcount = sum(1 for _ in all_configurations(model=model, coords=coords, **independent_opts))\n",
    "\t\tcount_no_scl = sum(1 for _ in all_configurations(model=model, coords=coords, **independent_opts, scalarmult={\"scl\": None}))\n",
    "\t\tcount_no_opts = sum(1 for _ in all_configurations(model=model, coords=coords, **independent_opts, scalarmult={\"scl\": None, \"always\": True, \"short_circuit\": True, \"complete\": False, \"precompute_negation\": True, \"width\": 3, \"m\": 3, \"direction\": ProcessingDirection.LTR, \"accumulation_order\": AccumulationOrder.PeqPR, \"recoding_direction\": ProcessingDirection.LTR}))\n",
    "\t\tcoords_counts.append([\"\", coords_name, count * no_ff, count, count_no_scl, count_no_opts])\n",
    "display(HTML(tabulate.tabulate(coords_counts, tablefmt=\"html\", headers=\"firstrow\")))"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "### Scalar multipliers"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "Let's examine the split between different scalar multipliers."
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "from pyecsca.ec.mult import ScalarMultiplier\n",
    "\n",
    "def leaf_subclasses(cls):\n",
    "    subs = cls.__subclasses__()\n",
    "    result = set()\n",
    "    for subclass in subs:\n",
    "        if subclass.__subclasses__():\n",
    "            result.update(leaf_subclasses(subclass))\n",
    "        else:\n",
    "            result.add(subclass)\n",
    "    return result\n",
    "\n",
    "mult_counts = [[\"ScalarMultiplier\", \"All\", \"Without independent options\", \"Without independent options and scaling\", \"Without independent options and scalarmult options\"]]\n",
    "for mult_cls in leaf_subclasses(ScalarMultiplier):\n",
    "\tcount = sum(1 for _ in all_configurations(**independent_opts, scalarmult=mult_cls))\n",
    "\tcount_no_scl = sum(1 for _ in all_configurations(**independent_opts, scalarmult={\"cls\": mult_cls, \"scl\": None}))\n",
    "\tcount_no_opts = sum(1 for _ in all_configurations(**independent_opts, scalarmult={\"cls\": mult_cls, \"scl\": None, \"always\": True, \"short_circuit\": True, \"complete\": False, \"precompute_negation\": True, \"width\": 3, \"m\": 3, \"direction\": ProcessingDirection.LTR, \"accumulation_order\": AccumulationOrder.PeqPR, \"recoding_direction\": ProcessingDirection.LTR}))\n",
    "\tmult_counts.append([mult_cls.__name__, count * no_ff, count, count_no_scl, count_no_opts])\n",
    "display(HTML(tabulate.tabulate(mult_counts, tablefmt=\"html\", headers=\"firstrow\")))\n"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [],
   "outputs": [],
   "execution_count": null
  }
 ],
 "metadata": {
  "@webio": {
   "lastCommId": "cde560b9f2c044d9845711a0a2b208b6",
   "lastKernelId": "fb83e665-19e4-4332-b620-9e2ea7aa7c62"
  },
  "hide_input": false,
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.4"
  },
  "latex_envs": {
   "LaTeX_envs_menu_present": true,
   "autoclose": false,
   "autocomplete": true,
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 1,
   "hotkeys": {
    "equation": "Ctrl-E",
    "itemize": "Ctrl-I"
   },
   "labels_anchors": false,
   "latex_user_defs": false,
   "report_style_numbering": false,
   "user_envs_cfg": false
  },
  "pycharm": {
   "stem_cell": {
    "cell_type": "raw",
    "metadata": {
     "collapsed": false
    },
    "source": []
   }
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}