From 5222ce8f6989de61a0a4a8ed7fa3dc7c6f575dfb Mon Sep 17 00:00:00 2001 From: J08nY Date: Thu, 30 May 2024 18:24:43 +0200 Subject: Improve doc coverage and cleanup public functions. --- pyecsca/ec/formula/code.py | 11 ++++++++++- pyecsca/ec/formula/efd.py | 3 ++- pyecsca/ec/formula/expand.py | 11 +++++++++++ pyecsca/ec/formula/fake.py | 6 +++++- pyecsca/ec/formula/fliparoo.py | 9 +++++++++ pyecsca/ec/formula/graph.py | 6 ++++++ pyecsca/ec/formula/metrics.py | 22 ++++++++++++++++++++++ pyecsca/ec/formula/partitions.py | 5 +++++ pyecsca/ec/formula/switch_sign.py | 2 ++ pyecsca/ec/formula/unroll.py | 2 ++ 10 files changed, 74 insertions(+), 3 deletions(-) diff --git a/pyecsca/ec/formula/code.py b/pyecsca/ec/formula/code.py index 9d2d7d6..8309bb8 100644 --- a/pyecsca/ec/formula/code.py +++ b/pyecsca/ec/formula/code.py @@ -1,7 +1,8 @@ -"""Provides a concrete class of a formula that has a constructor.""" +"""Provides a concrete class of a formula that has a constructor and some code.""" from typing import List, Any from ast import Expression from astunparse import unparse +from public import public from .base import ( Formula, @@ -17,6 +18,7 @@ from ..op import CodeOp from ...misc.utils import peval +@public class CodeFormula(Formula): """A basic formula class that can be directly initialized with the code and other attributes.""" @@ -71,29 +73,36 @@ class CodeFormula(Formula): self.__dict__.update(state) +@public class CodeAdditionFormula(AdditionFormula, CodeFormula): pass +@public class CodeDoublingFormula(DoublingFormula, CodeFormula): pass +@public class CodeLadderFormula(LadderFormula, CodeFormula): pass +@public class CodeTriplingFormula(TriplingFormula, CodeFormula): pass +@public class CodeNegationFormula(NegationFormula, CodeFormula): pass +@public class CodeScalingFormula(ScalingFormula, CodeFormula): pass +@public class CodeDifferentialAdditionFormula(DifferentialAdditionFormula, CodeFormula): pass diff --git a/pyecsca/ec/formula/efd.py b/pyecsca/ec/formula/efd.py index 0f2aa98..a56eb47 100644 --- a/pyecsca/ec/formula/efd.py +++ b/pyecsca/ec/formula/efd.py @@ -1,4 +1,4 @@ -"""""" +"""Provides formulas wrapping the [EFD]_.""" from copy import copy from public import public @@ -22,6 +22,7 @@ from .base import ( from ...misc.utils import pexec, peval +@public class EFDFormula(Formula): """Formula from the [EFD]_.""" diff --git a/pyecsca/ec/formula/expand.py b/pyecsca/ec/formula/expand.py index acaf7ea..f3c9a56 100644 --- a/pyecsca/ec/formula/expand.py +++ b/pyecsca/ec/formula/expand.py @@ -1,3 +1,4 @@ +"""Provides a formula expansion function.""" from typing import Set, Callable, Any from public import public @@ -25,6 +26,16 @@ def reduce_with_similarity(formulas: Set[Formula], norm: Callable[[Formula], Any def expand_formula_set( formulas: Set[Formula], norm: Callable[[Formula], Any] = ivs_norm ) -> Set[Formula]: + """ + Expand a set of formulas by using transformations: + - Fliparoos + - Sign switching + - Associativity and Commutativity + + :param formulas: + :param norm: + :return: + """ extended = reduce_with_similarity(formulas, norm) fliparood: Set[Formula] = set().union(*map(recursive_fliparoo, extended)) diff --git a/pyecsca/ec/formula/fake.py b/pyecsca/ec/formula/fake.py index cc52740..5c20dfb 100644 --- a/pyecsca/ec/formula/fake.py +++ b/pyecsca/ec/formula/fake.py @@ -1,3 +1,4 @@ +"""Provides "fake" formulas.""" from abc import ABC from typing import Any, Tuple @@ -18,9 +19,10 @@ from ..mod import Mod, Undefined from ..point import Point +@public class FakeFormula(Formula, ABC): """ - No matter what the input point is it just returns the right amount of FakePoints. + No matter what the input point is, it just returns the right amount of FakePoints. Useful for computing with the scalar multipliers without having concrete formulas and points (for example to get the addition chain via the MultipleContext). @@ -77,6 +79,8 @@ class FakeLadderFormula(FakeFormula, LadderFormula): @public class FakePoint(Point): + """Just a fake point.""" + def __init__(self, model): coords = {key: Undefined() for key in model.variables} super().__init__(model, **coords) diff --git a/pyecsca/ec/formula/fliparoo.py b/pyecsca/ec/formula/fliparoo.py index 7338b24..6665e1e 100644 --- a/pyecsca/ec/formula/fliparoo.py +++ b/pyecsca/ec/formula/fliparoo.py @@ -1,10 +1,13 @@ +"""Provides a way to Fliparoo formulas.""" from ast import parse from typing import Iterator, List, Type, Optional, Set +from public import public from ..op import OpType from .base import Formula from .graph import FormulaGraph, Node, CodeOpNode, CodeOp, CodeFormula +@public class Fliparoo: """ Fliparoo is a chain of nodes N1->N2->...->Nk in FormulaGraph for k>=2 such that: @@ -79,6 +82,7 @@ class Fliparoo: return self.__class__(self.nodes[i:j], self.graph) +@public class MulFliparoo(Fliparoo): def __init__(self, chain: List[CodeOpNode], graph: FormulaGraph): super().__init__(chain, graph) @@ -88,6 +92,7 @@ class MulFliparoo(Fliparoo): self.operator = OpType.Mult +@public class AddSubFliparoo(Fliparoo): def __init__(self, chain: List[CodeOpNode], graph: FormulaGraph): super().__init__(chain, graph) @@ -96,6 +101,7 @@ class AddSubFliparoo(Fliparoo): raise BadFliparoo +@public class AddFliparoo(Fliparoo): def __init__(self, chain: List[CodeOpNode], graph: FormulaGraph): super().__init__(chain, graph) @@ -105,6 +111,7 @@ class AddFliparoo(Fliparoo): self.operator = OpType.Add +@public class BadFliparoo(Exception): pass @@ -238,6 +245,7 @@ class DummyNode(Node): return None +@public def generate_fliparood_formulas( formula: Formula, rename: bool = True ) -> Iterator[CodeFormula]: @@ -370,6 +378,7 @@ def combine_signed_nodes( subgraph.add_node(new_node) +@public def recursive_fliparoo(formula: Formula, depth: int = 2) -> Set[Formula]: all_fliparoos = {0: {formula}} counter = 0 diff --git a/pyecsca/ec/formula/graph.py b/pyecsca/ec/formula/graph.py index 59b51dd..c7886bd 100644 --- a/pyecsca/ec/formula/graph.py +++ b/pyecsca/ec/formula/graph.py @@ -1,3 +1,4 @@ +"""Provides tools for working with formulas as graphs.""" from .base import Formula from .code import CodeFormula from ..op import CodeOp, OpType @@ -6,9 +7,11 @@ import networkx as nx from ast import parse, Expression from typing import Dict, List, Tuple, Set, Optional, MutableMapping, Any from copy import deepcopy +from public import public from abc import ABC, abstractmethod +@public class Node(ABC): def __init__(self): self.incoming_nodes = [] @@ -75,6 +78,7 @@ class Node(ABC): destination.outgoing_nodes.append(out) +@public class ConstantNode(Node): color = "#b41f44" @@ -170,6 +174,7 @@ class CodeOpNode(Node): return f"Node({self.op})" +@public class InputNode(Node): color = "#b41f44" @@ -198,6 +203,7 @@ def formula_input_variables(formula: Formula) -> List[str]: ) +@public class FormulaGraph: coordinate_model: Any name: str diff --git a/pyecsca/ec/formula/metrics.py b/pyecsca/ec/formula/metrics.py index 9b521c4..f3c8487 100644 --- a/pyecsca/ec/formula/metrics.py +++ b/pyecsca/ec/formula/metrics.py @@ -1,3 +1,4 @@ +"""Provides metrics for comparing formulas.""" from public import public from .unroll import unroll_formula from .base import Formula @@ -26,6 +27,13 @@ def ivs_norm(one: Formula): @public def formula_similarity(one: Formula, other: Formula) -> Dict[str, float]: + """ + Formula similarity based on symbolic intermediate value sets. + + :param one: + :param other: + :return: + """ if one.coordinate_model != other.coordinate_model: warnings.warn("Mismatched coordinate model.") @@ -41,6 +49,13 @@ def formula_similarity(one: Formula, other: Formula) -> Dict[str, float]: @public def formula_similarity_abs(one: Formula, other: Formula) -> Dict[str, float]: + """ + Formula similarity based on symbolic intermediate value sets (absolute value) + + :param one: + :param other: + :return: + """ if one.coordinate_model != other.coordinate_model: warnings.warn("Mismatched coordinate model.") @@ -64,6 +79,13 @@ def formula_similarity_abs(one: Formula, other: Formula) -> Dict[str, float]: def formula_similarity_fuzz( one: Formula, other: Formula, curve: EllipticCurve, samples: int = 1000 ) -> Dict[str, float]: + """ + Formula similarity based on random computation. + + :param one: + :param other: + :return: + """ if one.coordinate_model != other.coordinate_model: raise ValueError("Mismatched coordinate model.") diff --git a/pyecsca/ec/formula/partitions.py b/pyecsca/ec/formula/partitions.py index 4f44631..adfb4f8 100644 --- a/pyecsca/ec/formula/partitions.py +++ b/pyecsca/ec/formula/partitions.py @@ -1,5 +1,6 @@ from typing import List, Any, Generator from ast import parse +from public import public from .base import Formula from ..op import OpType, CodeOp from .graph import FormulaGraph, CodeOpNode, ConstantNode, Node, CodeFormula @@ -7,6 +8,7 @@ from .fliparoo import find_fliparoos, AddFliparoo, MulFliparoo from copy import deepcopy +@public def reduce_all_adds(formula: Formula, rename=True) -> CodeFormula: graph = FormulaGraph(formula, rename=rename) add_fliparoos = find_single_input_add_fliparoos(graph) @@ -19,6 +21,7 @@ def reduce_all_adds(formula: Formula, rename=True) -> CodeFormula: return graph.to_formula("reduce_add") +@public def expand_all_muls(formula: Formula, rename=True) -> CodeFormula: graph = FormulaGraph(formula, rename) enodes = find_expansion_nodes(graph) @@ -27,6 +30,7 @@ def expand_all_muls(formula: Formula, rename=True) -> CodeFormula: return graph.to_formula("expand_mul") +@public def expand_all_nopower2_muls(formula: Formula, rename=True) -> CodeFormula: graph = FormulaGraph(formula, rename) enodes = find_expansion_nodes(graph, nopower2=True) @@ -275,6 +279,7 @@ def compute_partitions(n: int) -> List[Partition]: return result +@public def generate_partitioned_formulas(formula: Formula, rename=True): graph = FormulaGraph(formula, rename) enodes = find_expansion_nodes(graph) diff --git a/pyecsca/ec/formula/switch_sign.py b/pyecsca/ec/formula/switch_sign.py index b0efb56..f860c95 100644 --- a/pyecsca/ec/formula/switch_sign.py +++ b/pyecsca/ec/formula/switch_sign.py @@ -1,5 +1,6 @@ from typing import Dict, Iterator, List, Any from ast import parse +from public import public from ..op import OpType, CodeOp from .base import Formula from .graph import FormulaGraph, ConstantNode, CodeOpNode, CodeFormula @@ -8,6 +9,7 @@ from ..point import Point from ..mod import Mod +@public def generate_switched_formulas( formula: Formula, rename=True ) -> Iterator[CodeFormula]: diff --git a/pyecsca/ec/formula/unroll.py b/pyecsca/ec/formula/unroll.py index 84d0901..3b83e96 100644 --- a/pyecsca/ec/formula/unroll.py +++ b/pyecsca/ec/formula/unroll.py @@ -1,3 +1,5 @@ +"""Provides functions for unrolling formula intermediate values symvolically.""" + from typing import List, Tuple from astunparse import unparse -- cgit v1.3.1