aboutsummaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/ec/test_configuration.py2
-rw-r--r--test/ec/test_formula.py426
-rw-r--r--test/ec/test_mult.py343
-rw-r--r--test/ec/test_scalar.py26
-rw-r--r--test/sca/test_rpa.py90
-rw-r--r--test/sca/test_structural.py315
6 files changed, 735 insertions, 467 deletions
diff --git a/test/ec/test_configuration.py b/test/ec/test_configuration.py
index 54cc53a..15c9471 100644
--- a/test/ec/test_configuration.py
+++ b/test/ec/test_configuration.py
@@ -33,7 +33,7 @@ def test_weierstrass_projective(base_independents):
coords = model.coordinates["projective"]
configs = list(all_configurations(model=model, coords=coords, **base_independents))
assert len(set(map(lambda cfg: cfg.scalarmult, configs))) == len(configs)
- assert len(configs) == 11360
+ assert len(configs) == 12640
def test_mult_class(base_independents):
diff --git a/test/ec/test_formula.py b/test/ec/test_formula.py
index bb3d123..3f8d45c 100644
--- a/test/ec/test_formula.py
+++ b/test/ec/test_formula.py
@@ -1,13 +1,39 @@
import pickle
+from operator import itemgetter
+from typing import Tuple
import pytest
from sympy import FF, symbols
-
+from importlib_resources import files, as_file
+import test.data.formulas
+from pyecsca.ec.formula.expand import expand_formula_list
+from pyecsca.ec.formula.fliparoo import generate_fliparood_formulas
+from pyecsca.ec.formula.graph import rename_ivs
+from pyecsca.ec.formula.metrics import (
+ formula_similarity,
+ formula_similarity_abs,
+ formula_similarity_fuzz,
+)
+from pyecsca.ec.formula.partitions import (
+ reduce_all_adds,
+ expand_all_muls,
+ expand_all_nopower2_muls,
+ generate_partitioned_formulas,
+)
+from pyecsca.ec.formula.switch_sign import generate_switched_formulas
from pyecsca.ec.mod import SymbolicMod, Mod
from pyecsca.misc.cfg import TemporaryConfig
from pyecsca.ec.error import UnsatisfiedAssumptionError
-from pyecsca.ec.params import get_params
+from pyecsca.ec.params import get_params, DomainParameters
from pyecsca.ec.point import Point
+from pyecsca.ec.model import ShortWeierstrassModel, MontgomeryModel, TwistedEdwardsModel
+from pyecsca.ec.formula.efd import (
+ AdditionEFDFormula,
+ DoublingEFDFormula,
+ LadderEFDFormula,
+ EFDFormula,
+)
+from pyecsca.ec.formula import AdditionFormula, DoublingFormula, LadderFormula
@pytest.fixture()
@@ -62,39 +88,27 @@ def test_num_ops(add):
def test_assumptions(secp128r1, mdbl):
- res = mdbl(
- secp128r1.curve.prime,
- secp128r1.generator,
- **secp128r1.curve.parameters
- )
+ res = mdbl(secp128r1.curve.prime, secp128r1.generator, **secp128r1.curve.parameters)
assert res is not None
- coords = {
- name: value * 5 for name, value in secp128r1.generator.coords.items()
- }
+ coords = {name: value * 5 for name, value in secp128r1.generator.coords.items()}
other = Point(secp128r1.generator.coordinate_model, **coords)
with pytest.raises(UnsatisfiedAssumptionError):
- mdbl(
- secp128r1.curve.prime, other, **secp128r1.curve.parameters
- )
+ mdbl(secp128r1.curve.prime, other, **secp128r1.curve.parameters)
with TemporaryConfig() as cfg:
cfg.ec.unsatisfied_formula_assumption_action = "ignore"
- pt = mdbl(
- secp128r1.curve.prime, other, **secp128r1.curve.parameters
- )
+ pt = mdbl(secp128r1.curve.prime, other, **secp128r1.curve.parameters)
assert pt is not None
def test_parameters():
jac_secp128r1 = get_params("secg", "secp128r1", "jacobian")
- jac_dbl = jac_secp128r1.curve.coordinate_model.formulas[
- "dbl-1998-hnm"
- ]
+ jac_dbl = jac_secp128r1.curve.coordinate_model.formulas["dbl-1998-hnm"]
res = jac_dbl(
jac_secp128r1.curve.prime,
jac_secp128r1.generator,
- **jac_secp128r1.curve.parameters
+ **jac_secp128r1.curve.parameters,
)
assert res is not None
@@ -111,9 +125,7 @@ def test_symbolic(secp128r1, dbl):
coords, **{key: SymbolicMod(symbols(key), p) for key in coords.variables}
)
symbolic_double = dbl(p, symbolic_point, **sympy_params)[0]
- generator_double = dbl(
- p, secp128r1.generator, **secp128r1.curve.parameters
- )[0]
+ generator_double = dbl(p, secp128r1.generator, **secp128r1.curve.parameters)[0]
for outer_var in coords.variables:
symbolic_val = getattr(symbolic_double, outer_var).x
generator_val = getattr(generator_double, outer_var).x
@@ -126,3 +138,371 @@ def test_symbolic(secp128r1, dbl):
def test_pickle(add, dbl):
assert add == pickle.loads(pickle.dumps(add))
+
+
+def test_formula_similarity(secp128r1):
+ add_bl = secp128r1.curve.coordinate_model.formulas["add-2007-bl"]
+ add_rcb = secp128r1.curve.coordinate_model.formulas["add-2015-rcb"]
+ out = formula_similarity(add_bl, add_rcb)
+ assert out["output"] == 0
+ assert out["ivs"] < 0.5
+ out_abs = formula_similarity_abs(add_bl, add_rcb)
+ assert out_abs["output"] == 0
+ assert out_abs["ivs"] < 0.5
+ out_fuzz = formula_similarity_fuzz(add_bl, add_rcb, secp128r1.curve, samples=100)
+ assert out_fuzz["output"] == 0
+ assert out_fuzz["ivs"] < 0.5
+ out_same = formula_similarity(add_bl, add_bl)
+ assert out_same["output"] == 1
+ assert out_same["ivs"] == 1
+
+
+LIBRARY_FORMULAS = [
+ [
+ "add-bc-r1rv76-jac",
+ ShortWeierstrassModel,
+ "jacobian",
+ ("secg", "secp128r1"),
+ AdditionEFDFormula,
+ ],
+ [
+ "add-bc-r1rv76-mod",
+ ShortWeierstrassModel,
+ "modified",
+ ("secg", "secp128r1"),
+ AdditionEFDFormula,
+ ],
+ [
+ "dbl-bc-r1rv76-jac",
+ ShortWeierstrassModel,
+ "jacobian",
+ ("secg", "secp128r1"),
+ DoublingEFDFormula,
+ ],
+ [
+ "dbl-bc-r1rv76-mod",
+ ShortWeierstrassModel,
+ "modified",
+ ("secg", "secp128r1"),
+ DoublingEFDFormula,
+ ],
+ [
+ "dbl-bc-r1rv76-x25519",
+ MontgomeryModel,
+ "xz",
+ ("other", "Curve25519"),
+ DoublingEFDFormula,
+ ],
+ [
+ "ladd-bc-r1rv76-x25519",
+ MontgomeryModel,
+ "xz",
+ ("other", "Curve25519"),
+ LadderEFDFormula,
+ ],
+ [
+ "dbl-boringssl-p224",
+ ShortWeierstrassModel,
+ "jacobian-3",
+ ("secg", "secp224r1"),
+ DoublingEFDFormula,
+ ],
+ [
+ "add-boringssl-p224",
+ ShortWeierstrassModel,
+ "jacobian-3",
+ ("secg", "secp224r1"),
+ AdditionEFDFormula,
+ ],
+ [
+ "add-libressl-v382",
+ ShortWeierstrassModel,
+ "jacobian",
+ ("secg", "secp128r1"),
+ AdditionEFDFormula,
+ ],
+ [
+ "dbl-libressl-v382",
+ ShortWeierstrassModel,
+ "jacobian",
+ ("secg", "secp128r1"),
+ DoublingEFDFormula,
+ ],
+ [
+ "dbl-secp256k1-v040",
+ ShortWeierstrassModel,
+ "jacobian",
+ ("secg", "secp256k1"),
+ DoublingEFDFormula,
+ ],
+ [
+ "add-openssl-z256",
+ ShortWeierstrassModel,
+ "jacobian-3",
+ ("secg", "secp256r1"),
+ AdditionEFDFormula,
+ ],
+ [
+ "add-openssl-z256a",
+ ShortWeierstrassModel,
+ "jacobian-3",
+ ("secg", "secp256r1"),
+ AdditionEFDFormula,
+ ],
+ [
+ "ladd-openssl-x25519",
+ MontgomeryModel,
+ "xz",
+ ("other", "Curve25519"),
+ LadderEFDFormula,
+ ],
+ [
+ "ladd-hacl-x25519",
+ MontgomeryModel,
+ "xz",
+ ("other", "Curve25519"),
+ LadderEFDFormula,
+ ],
+ [
+ "dbl-hacl-x25519",
+ MontgomeryModel,
+ "xz",
+ ("other", "Curve25519"),
+ DoublingEFDFormula,
+ ],
+ [
+ "dbl-sunec-v21",
+ ShortWeierstrassModel,
+ "projective-3",
+ ("secg", "secp256r1"),
+ DoublingEFDFormula,
+ ],
+ [
+ "add-sunec-v21",
+ ShortWeierstrassModel,
+ "projective-3",
+ ("secg", "secp256r1"),
+ AdditionEFDFormula,
+ ],
+ [
+ "add-sunec-v21-ed25519",
+ TwistedEdwardsModel,
+ "extended",
+ ("other", "Ed25519"),
+ AdditionEFDFormula,
+ ],
+ [
+ "dbl-sunec-v21-ed25519",
+ TwistedEdwardsModel,
+ "extended",
+ ("other", "Ed25519"),
+ DoublingEFDFormula,
+ ],
+ [
+ "ladd-rfc7748",
+ MontgomeryModel,
+ "xz",
+ ("other", "Curve25519"),
+ LadderEFDFormula,
+ ],
+ [
+ "add-bearssl-v06",
+ ShortWeierstrassModel,
+ "jacobian",
+ ("secg", "secp256r1"),
+ AdditionEFDFormula,
+ ],
+ [
+ "dbl-bearssl-v06",
+ ShortWeierstrassModel,
+ "jacobian",
+ ("secg", "secp256r1"),
+ DoublingEFDFormula,
+ ],
+ [
+ "add-libgcrypt-v1102",
+ ShortWeierstrassModel,
+ "jacobian",
+ ("secg", "secp256r1"),
+ AdditionEFDFormula,
+ ],
+ [
+ "dbl-libgcrypt-v1102",
+ ShortWeierstrassModel,
+ "jacobian",
+ ("secg", "secp256r1"),
+ DoublingEFDFormula,
+ ],
+ [
+ "ladd-go-1214",
+ MontgomeryModel,
+ "xz",
+ ("other", "Curve25519"),
+ LadderEFDFormula,
+ ],
+ [
+ "add-gecc-322",
+ ShortWeierstrassModel,
+ "jacobian-3",
+ ("secg", "secp256r1"),
+ AdditionEFDFormula,
+ ],
+ [
+ "dbl-gecc-321",
+ ShortWeierstrassModel,
+ "jacobian-3",
+ ("secg", "secp256r1"),
+ DoublingEFDFormula,
+ ],
+ [
+ "ladd-boringssl-x25519",
+ MontgomeryModel,
+ "xz",
+ ("other", "Curve25519"),
+ LadderEFDFormula,
+ ],
+ [
+ "dbl-ipp-x25519",
+ MontgomeryModel,
+ "xz",
+ ("other", "Curve25519"),
+ DoublingEFDFormula,
+ ],
+ [
+ "ladd-botan-x25519",
+ MontgomeryModel,
+ "xz",
+ ("other", "Curve25519"),
+ LadderEFDFormula,
+ ],
+]
+
+
+@pytest.fixture(params=LIBRARY_FORMULAS, ids=list(map(itemgetter(0), LIBRARY_FORMULAS)))
+def library_formula_params(request) -> Tuple[EFDFormula, DomainParameters]:
+ name, model, coords_name, param_spec, formula_type = request.param
+ model = model()
+ coordinate_model = model.coordinates[coords_name]
+ with as_file(files(test.data.formulas).joinpath(name)) as meta_path, as_file(
+ files(test.data.formulas).joinpath(name + ".op3")
+ ) as op3_path:
+ formula = formula_type(meta_path, op3_path, name, coordinate_model)
+ params = get_params(*param_spec, coords_name)
+ return formula, params
+
+
+def test_formula_graph(library_formula_params):
+ formula, params = library_formula_params
+ do_test_formula(rename_ivs(formula), params)
+
+
+def test_switch_sign(library_formula_params):
+ formula, params = library_formula_params
+ for switch_formula in generate_switched_formulas(formula):
+ do_test_formula(switch_formula, params)
+
+
+def test_fliparood_formula(library_formula_params):
+ formula, params = library_formula_params
+ for fliparood in generate_fliparood_formulas(formula):
+ do_test_formula(fliparood, params)
+
+
+def test_partition_formula_single(library_formula_params):
+ formula, params = library_formula_params
+ try:
+ next(iter(generate_partitioned_formulas(formula)))
+ except StopIteration:
+ pass
+
+
+@pytest.mark.slow
+def test_partition_formula(library_formula_params):
+ formula, params = library_formula_params
+ for partitioned in generate_partitioned_formulas(formula):
+ do_test_formula(partitioned, params)
+
+
+def test_reductions(library_formula_params):
+ formula, params = library_formula_params
+ do_test_formula(reduce_all_adds(formula), params)
+
+
+def test_expansions(library_formula_params):
+ formula, params = library_formula_params
+ do_test_formula(expand_all_muls(formula), params)
+ do_test_formula(expand_all_nopower2_muls(formula), params)
+
+
+def do_test_formula(formula, params):
+ coordinate_model = formula.coordinate_model
+ scale = coordinate_model.formulas.get("z", None)
+ if scale is None:
+ scale = coordinate_model.formulas.get("scale", None)
+
+ formula_type = formula.__class__
+ for _ in range(10):
+ Paff = params.curve.affine_random()
+ P2aff = params.curve.affine_double(Paff)
+ Qaff = params.curve.affine_random()
+ Q2aff = params.curve.affine_double(Qaff)
+ Raff = params.curve.affine_add(Paff, Qaff)
+ R2aff = params.curve.affine_double(Raff)
+ QRaff = params.curve.affine_add(Qaff, Raff)
+ P = Paff.to_model(coordinate_model, params.curve)
+ P2 = P2aff.to_model(coordinate_model, params.curve)
+ Q = Qaff.to_model(coordinate_model, params.curve)
+ Q2 = Q2aff.to_model(coordinate_model, params.curve)
+ R = Raff.to_model(coordinate_model, params.curve)
+ R2 = R2aff.to_model(coordinate_model, params.curve) # noqa
+ QR = QRaff.to_model(coordinate_model, params.curve)
+ inputs = (P, Q, R)[: formula.num_inputs]
+ res = formula(params.curve.prime, *inputs, **params.curve.parameters)
+ if issubclass(formula_type, AdditionFormula):
+ try:
+ assert res[0].to_affine() == Raff
+ except NotImplementedError:
+ assert (
+ scale(params.curve.prime, res[0], **params.curve.parameters)[0] == R
+ )
+ elif issubclass(formula_type, DoublingFormula):
+ try:
+ assert res[0].to_affine() == P2aff
+ except NotImplementedError:
+ assert (
+ scale(params.curve.prime, res[0], **params.curve.parameters)[0]
+ == P2
+ )
+ elif issubclass(formula_type, LadderFormula):
+ try:
+ assert res[0].to_affine() == Q2aff
+ assert res[1].to_affine() == QRaff
+ except NotImplementedError:
+ # print(scale(params.curve.prime, res[0], **params.curve.parameters)[0])
+ # print(scale(params.curve.prime, res[1], **params.curve.parameters)[0])
+ # print(P)
+ # print(Q)
+ # print(R)
+ # print(P2)
+ # print(Q2)
+ # print(R2)
+ # print(QR)
+ # print("------------------------------------")
+ assert (
+ scale(params.curve.prime, res[1], **params.curve.parameters)[0]
+ == QR
+ )
+ assert (
+ scale(params.curve.prime, res[0], **params.curve.parameters)[0]
+ == Q2
+ )
+
+
+def test_formula_correctness(library_formula_params):
+ formula, params = library_formula_params
+ do_test_formula(formula, params)
+
+
+def test_formula_expand(add):
+ res = expand_formula_list([add])
+ assert len(res) > 1
diff --git a/test/ec/test_mult.py b/test/ec/test_mult.py
index 20e1c95..d5e3146 100644
--- a/test/ec/test_mult.py
+++ b/test/ec/test_mult.py
@@ -20,6 +20,7 @@ from pyecsca.ec.mult import (
SlidingWindowMultiplier,
BGMWMultiplier,
CombMultiplier,
+ WindowBoothMultiplier,
)
from pyecsca.ec.mult.fixed import FullPrecompMultiplier
from pyecsca.ec.point import InfinityPoint, Point
@@ -36,12 +37,9 @@ def assert_pt_equality(one: Point, other: Point, scale):
assert one.equals(other)
-def do_basic_test(
- mult_class, params, base, add, dbl, scale, neg=None, **kwargs
-):
+def do_basic_test(mult_class, params, base, add, dbl, scale, neg=None, **kwargs):
mult = mult_class(
- *get_formulas(params.curve.coordinate_model, add, dbl, neg, scale),
- **kwargs
+ *get_formulas(params.curve.coordinate_model, add, dbl, neg, scale), **kwargs
)
mult.init(params, base)
res = mult.multiply(314)
@@ -59,26 +57,28 @@ def do_basic_test(
return res
-@pytest.mark.parametrize("add,dbl,scale",
- [
- ("add-1998-cmo-2", "dbl-1998-cmo-2", "z"),
- ("add-2015-rcb", "dbl-2015-rcb", None),
- ("add-1998-cmo-2", "dbl-1998-cmo-2", None),
- ])
+@pytest.mark.parametrize(
+ "add,dbl,scale",
+ [
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", "z"),
+ ("add-2015-rcb", "dbl-2015-rcb", None),
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", None),
+ ],
+)
def test_rtl(secp128r1, add, dbl, scale):
do_basic_test(RTLMultiplier, secp128r1, secp128r1.generator, add, dbl, scale)
-@pytest.mark.parametrize("add,dbl,scale",
- [
- ("add-1998-cmo-2", "dbl-1998-cmo-2", "z"),
- ("add-2015-rcb", "dbl-2015-rcb", None),
- ("add-1998-cmo-2", "dbl-1998-cmo-2", None),
- ])
+@pytest.mark.parametrize(
+ "add,dbl,scale",
+ [
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", "z"),
+ ("add-2015-rcb", "dbl-2015-rcb", None),
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", None),
+ ],
+)
def test_ltr(secp128r1, add, dbl, scale):
- a = do_basic_test(
- LTRMultiplier, secp128r1, secp128r1.generator, add, dbl, scale
- )
+ a = do_basic_test(LTRMultiplier, secp128r1, secp128r1.generator, add, dbl, scale)
b = do_basic_test(
LTRMultiplier, secp128r1, secp128r1.generator, add, dbl, scale, always=True
)
@@ -100,22 +100,35 @@ def test_ltr(secp128r1, add, dbl, scale):
assert_pt_equality(c, d, scale)
-@pytest.mark.parametrize("add,dbl,scale",
- [
- ("add-1998-cmo-2", "dbl-1998-cmo-2", "z"),
- ("add-2015-rcb", "dbl-2015-rcb", None),
- ("add-1998-cmo-2", "dbl-1998-cmo-2", None),
- ])
+@pytest.mark.parametrize(
+ "add,dbl,scale",
+ [
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", "z"),
+ ("add-2015-rcb", "dbl-2015-rcb", None),
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", None),
+ ],
+)
def test_doubleandadd(secp128r1, add, dbl, scale):
a = do_basic_test(
DoubleAndAddMultiplier, secp128r1, secp128r1.generator, add, dbl, scale
)
b = do_basic_test(
- DoubleAndAddMultiplier, secp128r1, secp128r1.generator, add, dbl, scale, direction=ProcessingDirection.RTL
+ DoubleAndAddMultiplier,
+ secp128r1,
+ secp128r1.generator,
+ add,
+ dbl,
+ scale,
+ direction=ProcessingDirection.RTL,
)
c = do_basic_test(
- DoubleAndAddMultiplier, secp128r1, secp128r1.generator, add, dbl, scale,
- accumulation_order=AccumulationOrder.PeqPR
+ DoubleAndAddMultiplier,
+ secp128r1,
+ secp128r1.generator,
+ add,
+ dbl,
+ scale,
+ accumulation_order=AccumulationOrder.PeqPR,
)
d = do_basic_test(
DoubleAndAddMultiplier,
@@ -132,13 +145,14 @@ def test_doubleandadd(secp128r1, add, dbl, scale):
assert_pt_equality(c, d, scale)
-@pytest.mark.parametrize("add,dbl,scale",
- [
- ("add-1998-cmo-2", "dbl-1998-cmo-2", "z"),
- ("add-2015-rcb", "dbl-2015-rcb", None),
- ("add-1998-cmo-2", "dbl-1998-cmo-2", None),
- ]
- )
+@pytest.mark.parametrize(
+ "add,dbl,scale",
+ [
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", "z"),
+ ("add-2015-rcb", "dbl-2015-rcb", None),
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", None),
+ ],
+)
def test_coron(secp128r1, add, dbl, scale):
do_basic_test(CoronMultiplier, secp128r1, secp128r1.generator, add, dbl, scale)
@@ -164,27 +178,31 @@ def test_ladder(curve25519):
assert_pt_equality(a, b, True)
-@pytest.mark.parametrize("add,dbl,scale",
- [
- ("add-1998-cmo-2", "dbl-1998-cmo-2", "z"),
- ("add-2015-rcb", "dbl-2015-rcb", None),
- ("add-1998-cmo-2", "dbl-1998-cmo-2", None),
- ])
+@pytest.mark.parametrize(
+ "add,dbl,scale",
+ [
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", "z"),
+ ("add-2015-rcb", "dbl-2015-rcb", None),
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", None),
+ ],
+)
def test_simple_ladder(secp128r1, add, dbl, scale):
do_basic_test(
SimpleLadderMultiplier, secp128r1, secp128r1.generator, add, dbl, scale
)
-@pytest.mark.parametrize("num,complete",
- [
- (15, True),
- (15, False),
- (2355498743, True),
- (2355498743, False),
- (325385790209017329644351321912443757746, True),
- (325385790209017329644351321912443757746, False),
- ])
+@pytest.mark.parametrize(
+ "num,complete",
+ [
+ (15, True),
+ (15, False),
+ (2355498743, True),
+ (2355498743, False),
+ (325385790209017329644351321912443757746, True),
+ (325385790209017329644351321912443757746, False),
+ ],
+)
def test_ladder_differential(curve25519, num, complete):
ladder = LadderMultiplier(
curve25519.curve.coordinate_model.formulas["ladd-1987-m"],
@@ -206,27 +224,31 @@ def test_ladder_differential(curve25519, num, complete):
assert InfinityPoint(curve25519.curve.coordinate_model) == differential.multiply(0)
-@pytest.mark.parametrize("add,dbl,neg,scale",
- [
- ("add-1998-cmo-2", "dbl-1998-cmo-2", "neg", "z"),
- ("add-2015-rcb", "dbl-2015-rcb", "neg", None),
- ("add-1998-cmo-2", "dbl-1998-cmo-2", "neg", None),
- ])
+@pytest.mark.parametrize(
+ "add,dbl,neg,scale",
+ [
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", "neg", "z"),
+ ("add-2015-rcb", "dbl-2015-rcb", "neg", None),
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", "neg", None),
+ ],
+)
def test_binary_naf(secp128r1, add, dbl, neg, scale):
do_basic_test(
BinaryNAFMultiplier, secp128r1, secp128r1.generator, add, dbl, scale, neg
)
-@pytest.mark.parametrize("add,dbl,neg,width,scale",
- [
- ("add-1998-cmo-2", "dbl-1998-cmo-2", "neg", 3, "z"),
- ("add-1998-cmo-2", "dbl-1998-cmo-2", "neg", 3, None),
- ("add-2015-rcb", "dbl-2015-rcb", "neg", 3, None),
- ("add-1998-cmo-2", "dbl-1998-cmo-2", "neg", 5, "z"),
- ("add-1998-cmo-2", "dbl-1998-cmo-2", "neg", 5, None),
- ("add-2015-rcb", "dbl-2015-rcb", "neg", 5, None),
- ])
+@pytest.mark.parametrize(
+ "add,dbl,neg,width,scale",
+ [
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", "neg", 3, "z"),
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", "neg", 3, None),
+ ("add-2015-rcb", "dbl-2015-rcb", "neg", 3, None),
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", "neg", 5, "z"),
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", "neg", 5, None),
+ ("add-2015-rcb", "dbl-2015-rcb", "neg", 5, None),
+ ],
+)
def test_window_naf(secp128r1, add, dbl, neg, width, scale):
formulas = get_formulas(secp128r1.curve.coordinate_model, add, dbl, neg, scale)
mult = WindowNAFMultiplier(*formulas[:3], width, *formulas[3:])
@@ -247,12 +269,14 @@ def test_window_naf(secp128r1, add, dbl, neg, width, scale):
assert_pt_equality(res_precompute, res, scale)
-@pytest.mark.parametrize("add,dbl,width,scale",
- [
- ("add-1998-cmo-2", "dbl-1998-cmo-2", 5, "z"),
- ("add-2015-rcb", "dbl-2015-rcb", 5, None),
- ("add-1998-cmo-2", "dbl-1998-cmo-2", 5, None),
- ])
+@pytest.mark.parametrize(
+ "add,dbl,width,scale",
+ [
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", 5, "z"),
+ ("add-2015-rcb", "dbl-2015-rcb", 5, None),
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", 5, None),
+ ],
+)
def test_fixed_window(secp128r1, add, dbl, width, scale):
formulas = get_formulas(secp128r1.curve.coordinate_model, add, dbl, scale)
mult = FixedWindowLTRMultiplier(*formulas[:2], width, *formulas[2:])
@@ -266,6 +290,27 @@ def test_fixed_window(secp128r1, add, dbl, width, scale):
assert InfinityPoint(secp128r1.curve.coordinate_model) == mult.multiply(0)
+@pytest.mark.parametrize(
+ "add,dbl,neg,width,scale",
+ [
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", "neg", 5, "z"),
+ ("add-2015-rcb", "dbl-2015-rcb", "neg", 5, None),
+ ("add-1998-cmo-2", "dbl-1998-cmo-2", "neg", 5, None),
+ ],
+)
+def test_booth_window(secp128r1, add, dbl, neg, width, scale):
+ formulas = get_formulas(secp128r1.curve.coordinate_model, add, dbl, neg, scale)
+ mult = WindowBoothMultiplier(*formulas[:3], width, *formulas[3:])
+ mult.init(secp128r1, secp128r1.generator)
+ res = mult.multiply(157 * 789)
+ other = mult.multiply(157)
+ mult.init(secp128r1, other)
+ other = mult.multiply(789)
+ assert_pt_equality(res, other, scale)
+ mult.init(secp128r1, secp128r1.generator)
+ assert InfinityPoint(secp128r1.curve.coordinate_model) == mult.multiply(0)
+
+
@pytest.fixture(params=["add-1998-cmo-2", "add-2015-rcb"])
def add(secp128r1, request):
return secp128r1.curve.coordinate_model.formulas[request.param]
@@ -276,53 +321,137 @@ def dbl(secp128r1, request):
return secp128r1.curve.coordinate_model.formulas[request.param]
-@pytest.mark.parametrize("num", [10, 2355498743, 325385790209017329644351321912443757746])
+@pytest.mark.parametrize(
+ "num", [10, 2355498743, 325385790209017329644351321912443757746]
+)
def test_basic_multipliers(secp128r1, num, add, dbl):
neg = secp128r1.curve.coordinate_model.formulas["neg"]
scale = secp128r1.curve.coordinate_model.formulas["z"]
- ltr_options = {"always": (True, False),
- "complete": (True, False),
- "accumulation_order": tuple(AccumulationOrder)}
- ltrs = [LTRMultiplier(add, dbl, scale, **dict(zip(ltr_options.keys(), combination))) for combination in product(*ltr_options.values())]
+ ltr_options = {
+ "always": (True, False),
+ "complete": (True, False),
+ "accumulation_order": tuple(AccumulationOrder),
+ }
+ ltrs = [
+ LTRMultiplier(add, dbl, scale, **dict(zip(ltr_options.keys(), combination)))
+ for combination in product(*ltr_options.values())
+ ]
rtl_options = ltr_options
- rtls = [RTLMultiplier(add, dbl, scale, **dict(zip(rtl_options.keys(), combination))) for combination in product(*rtl_options.values())]
- bnaf_options = {"direction": tuple(ProcessingDirection),
- "accumulation_order": tuple(AccumulationOrder)}
- bnafs = [BinaryNAFMultiplier(add, dbl, neg, scale, **dict(zip(bnaf_options.keys(), combination))) for combination in product(*bnaf_options.values())]
- wnaf_options = {"precompute_negation": (True, False),
- "width": (3, 5),
- "accumulation_order": tuple(AccumulationOrder)}
- wnafs = [WindowNAFMultiplier(add, dbl, neg, scl=scale, **dict(zip(wnaf_options.keys(), combination))) for combination in product(*wnaf_options.values())]
+ rtls = [
+ RTLMultiplier(add, dbl, scale, **dict(zip(rtl_options.keys(), combination)))
+ for combination in product(*rtl_options.values())
+ ]
+ bnaf_options = {
+ "direction": tuple(ProcessingDirection),
+ "accumulation_order": tuple(AccumulationOrder),
+ }
+ bnafs = [
+ BinaryNAFMultiplier(
+ add, dbl, neg, scale, **dict(zip(bnaf_options.keys(), combination))
+ )
+ for combination in product(*bnaf_options.values())
+ ]
+ wnaf_options = {
+ "precompute_negation": (True, False),
+ "width": (3, 5),
+ "accumulation_order": tuple(AccumulationOrder),
+ }
+ wnafs = [
+ WindowNAFMultiplier(
+ add, dbl, neg, scl=scale, **dict(zip(wnaf_options.keys(), combination))
+ )
+ for combination in product(*wnaf_options.values())
+ ]
+ booth_options = {
+ "precompute_negation": (True, False),
+ "width": (3, 5),
+ "accumulation_order": tuple(AccumulationOrder),
+ }
+ booths = [
+ WindowBoothMultiplier(
+ add, dbl, neg, scl=scale, **dict(zip(booth_options.keys(), combination))
+ )
+ for combination in product(*booth_options.values())
+ ]
ladder_options = {"complete": (True, False)}
- ladders = [SimpleLadderMultiplier(add, dbl, scale, **dict(zip(ladder_options.keys(), combination))) for combination in product(*ladder_options.values())]
- fixed_options = {"m": (5, 8),
- "accumulation_order": tuple(AccumulationOrder)}
- fixeds = [FixedWindowLTRMultiplier(add, dbl, scl=scale, **dict(zip(fixed_options.keys(), combination))) for combination in product(*fixed_options.values())]
- sliding_options = {"width": (3, 5),
- "recoding_direction": tuple(ProcessingDirection),
- "accumulation_order": tuple(AccumulationOrder)}
- slides = [SlidingWindowMultiplier(add, dbl, scl=scale, **dict(zip(sliding_options.keys(), combination))) for combination in product(*sliding_options.values())]
- precomp_options = {"always": (True, False),
- "complete": (True, False),
- "direction": tuple(ProcessingDirection),
- "accumulation_order": tuple(AccumulationOrder)}
- precomps = [FullPrecompMultiplier(add, dbl, scl=scale, **dict(zip(precomp_options.keys(), combination))) for combination in product(*precomp_options.values())]
- bgmw_options = {"width": (3, 5),
- "direction": tuple(ProcessingDirection),
- "accumulation_order": tuple(AccumulationOrder)}
- bgmws = [BGMWMultiplier(add, dbl, scl=scale, **dict(zip(bgmw_options.keys(), combination))) for combination in product(*bgmw_options.values())]
- comb_options = {"width": (2, 3, 5),
- "accumulation_order": tuple(AccumulationOrder)}
- combs = [CombMultiplier(add, dbl, scl=scale, **dict(zip(comb_options.keys(), combination))) for combination in product(*comb_options.values())]
+ ladders = [
+ SimpleLadderMultiplier(
+ add, dbl, scale, **dict(zip(ladder_options.keys(), combination))
+ )
+ for combination in product(*ladder_options.values())
+ ]
+ fixed_options = {"m": (5, 8), "accumulation_order": tuple(AccumulationOrder)}
+ fixeds = [
+ FixedWindowLTRMultiplier(
+ add, dbl, scl=scale, **dict(zip(fixed_options.keys(), combination))
+ )
+ for combination in product(*fixed_options.values())
+ ]
+ sliding_options = {
+ "width": (3, 5),
+ "recoding_direction": tuple(ProcessingDirection),
+ "accumulation_order": tuple(AccumulationOrder),
+ }
+ slides = [
+ SlidingWindowMultiplier(
+ add, dbl, scl=scale, **dict(zip(sliding_options.keys(), combination))
+ )
+ for combination in product(*sliding_options.values())
+ ]
+ precomp_options = {
+ "always": (True, False),
+ "complete": (True, False),
+ "direction": tuple(ProcessingDirection),
+ "accumulation_order": tuple(AccumulationOrder),
+ }
+ precomps = [
+ FullPrecompMultiplier(
+ add, dbl, scl=scale, **dict(zip(precomp_options.keys(), combination))
+ )
+ for combination in product(*precomp_options.values())
+ ]
+ bgmw_options = {
+ "width": (3, 5),
+ "direction": tuple(ProcessingDirection),
+ "accumulation_order": tuple(AccumulationOrder),
+ }
+ bgmws = [
+ BGMWMultiplier(
+ add, dbl, scl=scale, **dict(zip(bgmw_options.keys(), combination))
+ )
+ for combination in product(*bgmw_options.values())
+ ]
+ comb_options = {"width": (2, 3, 5), "accumulation_order": tuple(AccumulationOrder)}
+ combs = [
+ CombMultiplier(
+ add, dbl, scl=scale, **dict(zip(comb_options.keys(), combination))
+ )
+ for combination in product(*comb_options.values())
+ ]
- mults: Sequence[ScalarMultiplier] = ltrs + rtls + bnafs + wnafs + [CoronMultiplier(add, dbl, scale)] + ladders + fixeds + slides + precomps + bgmws + combs
+ mults: Sequence[ScalarMultiplier] = (
+ ltrs
+ + rtls
+ + bnafs
+ + wnafs
+ + booths
+ + [CoronMultiplier(add, dbl, scale)]
+ + ladders
+ + fixeds
+ + slides
+ + precomps
+ + bgmws
+ + combs
+ )
results = []
for mult in mults:
mult.init(secp128r1, secp128r1.generator)
res = mult.multiply(num)
if results:
- assert res == results[-1], f"Points not equal {res} != {results[-1]} for mult = {mult}"
+ assert (
+ res == results[-1]
+ ), f"Points not equal {res} != {results[-1]} for mult = {mult}"
results.append(res)
diff --git a/test/ec/test_scalar.py b/test/ec/test_scalar.py
index 493690a..9c6cb60 100644
--- a/test/ec/test_scalar.py
+++ b/test/ec/test_scalar.py
@@ -1,4 +1,13 @@
-from pyecsca.ec.scalar import convert_base, sliding_window_ltr, sliding_window_rtl, wnaf, naf
+from pyecsca.ec.scalar import (
+ convert_base,
+ sliding_window_ltr,
+ sliding_window_rtl,
+ wnaf,
+ naf,
+ booth,
+ booth_word,
+ booth_window,
+)
def test_convert():
@@ -14,3 +23,18 @@ def test_sliding_window():
def test_nafs():
i = 0b1100110101001101011011
assert naf(i) == wnaf(i, 2)
+
+
+def test_booth():
+ assert booth(0b101) == [-1, 1, -1, 1]
+ for i in range(2**6):
+ bw = booth_word(i, 5)
+ # verified with BoringSSL recoding impl. (ec_GFp_nistp_recode_scalar_bits)
+ if i <= 31:
+ assert bw == (i + 1) // 2
+ else:
+ assert bw == -((64 - i) // 2)
+ s = 0x12345678123456781234567812345678123456781234567812345678
+ bw = booth_window(s, 5, 224)
+ # verified with BoringSSL ec_GFp_nistp224_point_mul
+ assert bw == [1, 4, 13, 3, -10, 15, 0, 9, 3, 9, -10, -12, -8, 2, 9, -6, 5, 13, -2, 1, -14, 7, -15, 11, 8, -16, 5, -14, -12, 11, -6, -4, 1, 4, 13, 3, -10, 15, 0, 9, 3, 9, -10, -12, -8]
diff --git a/test/sca/test_rpa.py b/test/sca/test_rpa.py
index f09a1a1..39c281d 100644
--- a/test/sca/test_rpa.py
+++ b/test/sca/test_rpa.py
@@ -12,12 +12,24 @@ from pyecsca.ec.mult import (
RTLMultiplier,
BinaryNAFMultiplier,
WindowNAFMultiplier,
- SimpleLadderMultiplier, AccumulationOrder, ProcessingDirection, SlidingWindowMultiplier, FixedWindowLTRMultiplier,
- FullPrecompMultiplier, BGMWMultiplier, CombMultiplier,
+ SimpleLadderMultiplier,
+ AccumulationOrder,
+ ProcessingDirection,
+ SlidingWindowMultiplier,
+ FixedWindowLTRMultiplier,
+ FullPrecompMultiplier,
+ BGMWMultiplier,
+ CombMultiplier,
+ WindowBoothMultiplier,
)
from pyecsca.ec.params import DomainParameters
from pyecsca.ec.point import Point
-from pyecsca.sca.re.rpa import MultipleContext, rpa_point_0y, rpa_point_x0, rpa_distinguish
+from pyecsca.sca.re.rpa import (
+ MultipleContext,
+ rpa_point_0y,
+ rpa_point_x0,
+ rpa_distinguish,
+)
@pytest.fixture()
@@ -47,18 +59,18 @@ def neg(coords):
@pytest.fixture()
def rpa_params(model, coords):
- p = 0x85d265945a4f5681
- a = Mod(0x7fc57b4110698bc0, p)
- b = Mod(0x37113ea591b04527, p)
- gx = Mod(0x80d2d78fddb97597, p)
- gy = Mod(0x5586d818b7910930, p)
+ p = 0x85D265945A4F5681
+ a = Mod(0x7FC57B4110698BC0, p)
+ b = Mod(0x37113EA591B04527, p)
+ gx = Mod(0x80D2D78FDDB97597, p)
+ gy = Mod(0x5586D818B7910930, p)
# (0x4880bcf620852a54, 0) RPA point
# (0, 0x6bed3155c9ada064) RPA point
infty = Point(coords, X=Mod(0, p), Y=Mod(1, p), Z=Mod(0, p))
g = Point(coords, X=gx, Y=gy, Z=Mod(1, p))
curve = EllipticCurve(model, coords, p, infty, dict(a=a, b=b))
- return DomainParameters(curve, g, 0x85d265932d90785c, 1)
+ return DomainParameters(curve, g, 0x85D265932D90785C, 1)
def test_x0_point(rpa_params):
@@ -80,25 +92,63 @@ def test_distinguish(secp128r1, add, dbl, neg):
RTLMultiplier(add, dbl, None, False, AccumulationOrder.PeqPR, True),
RTLMultiplier(add, dbl, None, True, AccumulationOrder.PeqPR, False),
SimpleLadderMultiplier(add, dbl, None, True, True),
- BinaryNAFMultiplier(add, dbl, neg, None, ProcessingDirection.LTR, AccumulationOrder.PeqPR, True),
- WindowNAFMultiplier(add, dbl, neg, 3, None, AccumulationOrder.PeqPR, True, True),
- WindowNAFMultiplier(add, dbl, neg, 4, None, AccumulationOrder.PeqPR, True, True),
+ BinaryNAFMultiplier(
+ add, dbl, neg, None, ProcessingDirection.LTR, AccumulationOrder.PeqPR, True
+ ),
+ WindowNAFMultiplier(
+ add, dbl, neg, 3, None, AccumulationOrder.PeqPR, True, True
+ ),
+ WindowNAFMultiplier(
+ add, dbl, neg, 4, None, AccumulationOrder.PeqPR, True, True
+ ),
+ WindowBoothMultiplier(
+ add, dbl, neg, 4, None, AccumulationOrder.PeqPR, True, True
+ ),
# WindowNAFMultiplier(add, dbl, neg, 4, None, AccumulationOrder.PeqPR, False, True),
- SlidingWindowMultiplier(add, dbl, 3, None, ProcessingDirection.LTR, AccumulationOrder.PeqPR, True),
- SlidingWindowMultiplier(add, dbl, 5, None, ProcessingDirection.LTR, AccumulationOrder.PeqPR, True),
+ SlidingWindowMultiplier(
+ add, dbl, 3, None, ProcessingDirection.LTR, AccumulationOrder.PeqPR, True
+ ),
+ SlidingWindowMultiplier(
+ add, dbl, 5, None, ProcessingDirection.LTR, AccumulationOrder.PeqPR, True
+ ),
FixedWindowLTRMultiplier(add, dbl, 4, None, AccumulationOrder.PeqPR, True),
FixedWindowLTRMultiplier(add, dbl, 5, None, AccumulationOrder.PeqPR, True),
- FullPrecompMultiplier(add, dbl, None, True, ProcessingDirection.LTR, AccumulationOrder.PeqPR, True, True),
- FullPrecompMultiplier(add, dbl, None, False, ProcessingDirection.LTR, AccumulationOrder.PeqPR, True, True),
+ FullPrecompMultiplier(
+ add,
+ dbl,
+ None,
+ True,
+ ProcessingDirection.LTR,
+ AccumulationOrder.PeqPR,
+ True,
+ True,
+ ),
+ FullPrecompMultiplier(
+ add,
+ dbl,
+ None,
+ False,
+ ProcessingDirection.LTR,
+ AccumulationOrder.PeqPR,
+ True,
+ True,
+ ),
# FullPrecompMultiplier(add, dbl, None, False, ProcessingDirection.RTL, AccumulationOrder.PeqPR, True, True),
- BGMWMultiplier(add, dbl, 3, None, ProcessingDirection.LTR, AccumulationOrder.PeqPR, True),
- BGMWMultiplier(add, dbl, 5, None, ProcessingDirection.LTR, AccumulationOrder.PeqPR, True),
+ BGMWMultiplier(
+ add, dbl, 3, None, ProcessingDirection.LTR, AccumulationOrder.PeqPR, True
+ ),
+ BGMWMultiplier(
+ add, dbl, 5, None, ProcessingDirection.LTR, AccumulationOrder.PeqPR, True
+ ),
CombMultiplier(add, dbl, 3, None, AccumulationOrder.PeqPR, True),
- CombMultiplier(add, dbl, 5, None, AccumulationOrder.PeqPR, True)
+ CombMultiplier(add, dbl, 5, None, AccumulationOrder.PeqPR, True),
]
for real_mult in multipliers:
+
def simulated_oracle(scalar, affine_point):
- point = affine_point.to_model(secp128r1.curve.coordinate_model, secp128r1.curve)
+ point = affine_point.to_model(
+ secp128r1.curve.coordinate_model, secp128r1.curve
+ )
with local(MultipleContext()) as ctx:
real_mult.init(secp128r1, point)
real_mult.multiply(scalar)
diff --git a/test/sca/test_structural.py b/test/sca/test_structural.py
deleted file mode 100644
index 970e4fc..0000000
--- a/test/sca/test_structural.py
+++ /dev/null
@@ -1,315 +0,0 @@
-import pytest
-from importlib_resources import files, as_file
-import test.data.formulas
-from pyecsca.ec.formula import (
- AdditionEFDFormula,
- LadderEFDFormula,
- DoublingEFDFormula,
- AdditionFormula,
- DoublingFormula,
- LadderFormula,
-)
-from pyecsca.ec.model import ShortWeierstrassModel, MontgomeryModel, TwistedEdwardsModel
-from pyecsca.ec.params import get_params
-from pyecsca.sca.re.structural import formula_similarity
-
-
-def test_formula_similarity(secp128r1):
- add_bl = secp128r1.curve.coordinate_model.formulas["add-2007-bl"]
- add_rcb = secp128r1.curve.coordinate_model.formulas["add-2015-rcb"]
- out = formula_similarity(add_bl, add_rcb)
- assert out["output"] == 0
- assert out["ivs"] < 0.5
- out_same = formula_similarity(add_bl, add_bl)
- assert out_same["output"] == 1
- assert out_same["ivs"] == 1
-
-
-@pytest.mark.parametrize(
- "name,model,coords,param_spec,formula_type",
- [
- [
- "add-bc-r1rv76-jac",
- ShortWeierstrassModel,
- "jacobian",
- ("secg", "secp128r1"),
- AdditionEFDFormula,
- ],
- [
- "add-bc-r1rv76-mod",
- ShortWeierstrassModel,
- "modified",
- ("secg", "secp128r1"),
- AdditionEFDFormula,
- ],
- [
- "dbl-bc-r1rv76-jac",
- ShortWeierstrassModel,
- "jacobian",
- ("secg", "secp128r1"),
- DoublingEFDFormula,
- ],
- [
- "dbl-bc-r1rv76-mod",
- ShortWeierstrassModel,
- "modified",
- ("secg", "secp128r1"),
- DoublingEFDFormula,
- ],
- [
- "dbl-bc-r1rv76-x25519",
- MontgomeryModel,
- "xz",
- ("other", "Curve25519"),
- DoublingEFDFormula,
- ],
- [
- "ladd-bc-r1rv76-x25519",
- MontgomeryModel,
- "xz",
- ("other", "Curve25519"),
- LadderEFDFormula,
- ],
- [
- "dbl-boringssl-p224",
- ShortWeierstrassModel,
- "jacobian-3",
- ("secg", "secp224r1"),
- DoublingEFDFormula,
- ],
- [
- "add-boringssl-p224",
- ShortWeierstrassModel,
- "jacobian-3",
- ("secg", "secp224r1"),
- AdditionEFDFormula,
- ],
- [
- "add-libressl-v382",
- ShortWeierstrassModel,
- "jacobian",
- ("secg", "secp128r1"),
- AdditionEFDFormula,
- ],
- [
- "dbl-libressl-v382",
- ShortWeierstrassModel,
- "jacobian",
- ("secg", "secp128r1"),
- DoublingEFDFormula,
- ],
- [
- "dbl-secp256k1-v040",
- ShortWeierstrassModel,
- "jacobian",
- ("secg", "secp256k1"),
- DoublingEFDFormula,
- ],
- [
- "add-openssl-z256",
- ShortWeierstrassModel,
- "jacobian-3",
- ("secg", "secp256r1"),
- AdditionEFDFormula,
- ],
- [
- "add-openssl-z256a",
- ShortWeierstrassModel,
- "jacobian-3",
- ("secg", "secp256r1"),
- AdditionEFDFormula,
- ],
- [
- "ladd-openssl-x25519",
- MontgomeryModel,
- "xz",
- ("other", "Curve25519"),
- LadderEFDFormula,
- ],
- [
- "ladd-hacl-x25519",
- MontgomeryModel,
- "xz",
- ("other", "Curve25519"),
- LadderEFDFormula,
- ],
- [
- "dbl-hacl-x25519",
- MontgomeryModel,
- "xz",
- ("other", "Curve25519"),
- DoublingEFDFormula,
- ],
- [
- "dbl-sunec-v21",
- ShortWeierstrassModel,
- "projective-3",
- ("secg", "secp256r1"),
- DoublingEFDFormula,
- ],
- [
- "add-sunec-v21",
- ShortWeierstrassModel,
- "projective-3",
- ("secg", "secp256r1"),
- AdditionEFDFormula,
- ],
- [
- "add-sunec-v21-ed25519",
- TwistedEdwardsModel,
- "extended",
- ("other", "Ed25519"),
- AdditionEFDFormula,
- ],
- [
- "dbl-sunec-v21-ed25519",
- TwistedEdwardsModel,
- "extended",
- ("other", "Ed25519"),
- DoublingEFDFormula,
- ],
- [
- "ladd-rfc7748",
- MontgomeryModel,
- "xz",
- ("other", "Curve25519"),
- LadderEFDFormula,
- ],
- [
- "add-bearssl-v06",
- ShortWeierstrassModel,
- "jacobian",
- ("secg", "secp256r1"),
- AdditionEFDFormula,
- ],
- [
- "dbl-bearssl-v06",
- ShortWeierstrassModel,
- "jacobian",
- ("secg", "secp256r1"),
- DoublingEFDFormula,
- ],
- [
- "add-libgcrypt-v1102",
- ShortWeierstrassModel,
- "jacobian",
- ("secg", "secp256r1"),
- AdditionEFDFormula,
- ],
- [
- "dbl-libgcrypt-v1102",
- ShortWeierstrassModel,
- "jacobian",
- ("secg", "secp256r1"),
- DoublingEFDFormula,
- ],
- [
- "ladd-go-1214",
- MontgomeryModel,
- "xz",
- ("other", "Curve25519"),
- LadderEFDFormula,
- ],
- [
- "add-gecc-322",
- ShortWeierstrassModel,
- "jacobian-3",
- ("secg", "secp256r1"),
- AdditionEFDFormula,
- ],
- [
- "dbl-gecc-321",
- ShortWeierstrassModel,
- "jacobian-3",
- ("secg", "secp256r1"),
- DoublingEFDFormula,
- ],
- [
- "ladd-boringssl-x25519",
- MontgomeryModel,
- "xz",
- ("other", "Curve25519"),
- LadderEFDFormula,
- ],
- [
- "dbl-ipp-x25519",
- MontgomeryModel,
- "xz",
- ("other", "Curve25519"),
- DoublingEFDFormula,
- ],
- [
- "ladd-botan-x25519",
- MontgomeryModel,
- "xz",
- ("other", "Curve25519"),
- LadderEFDFormula,
- ],
- ],
-)
-def test_formula_correctness(name, model, coords, param_spec, formula_type):
- model = model()
- coordinate_model = model.coordinates[coords]
- with as_file(files(test.data.formulas).joinpath(name)) as meta_path, as_file(
- files(test.data.formulas).joinpath(name + ".op3")
- ) as op3_path:
- formula = formula_type(meta_path, op3_path, name, coordinate_model)
- params = get_params(*param_spec, coords)
- scale = coordinate_model.formulas.get("z", None)
- if scale is None:
- scale = coordinate_model.formulas.get("scale", None)
- for _ in range(10):
- Paff = params.curve.affine_random()
- P2aff = params.curve.affine_double(Paff)
- Qaff = params.curve.affine_random()
- Q2aff = params.curve.affine_double(Qaff)
- Raff = params.curve.affine_add(Paff, Qaff)
- R2aff = params.curve.affine_double(Raff)
- QRaff = params.curve.affine_add(Qaff, Raff)
- P = Paff.to_model(coordinate_model, params.curve)
- P2 = P2aff.to_model(coordinate_model, params.curve)
- Q = Qaff.to_model(coordinate_model, params.curve)
- Q2 = Q2aff.to_model(coordinate_model, params.curve)
- R = Raff.to_model(coordinate_model, params.curve)
- R2 = R2aff.to_model(coordinate_model, params.curve) # noqa
- QR = QRaff.to_model(coordinate_model, params.curve)
- inputs = (P, Q, R)[: formula.num_inputs]
- res = formula(params.curve.prime, *inputs, **params.curve.parameters)
- if issubclass(formula_type, AdditionFormula):
- try:
- assert res[0].to_affine() == Raff
- except NotImplementedError:
- assert (
- scale(params.curve.prime, res[0], **params.curve.parameters)[0] == R
- )
- elif issubclass(formula_type, DoublingFormula):
- try:
- assert res[0].to_affine() == P2aff
- except NotImplementedError:
- assert (
- scale(params.curve.prime, res[0], **params.curve.parameters)[0]
- == P2
- )
- elif issubclass(formula_type, LadderFormula):
- try:
- assert res[0].to_affine() == Q2aff
- assert res[1].to_affine() == QRaff
- except NotImplementedError:
- # print(scale(params.curve.prime, res[0], **params.curve.parameters)[0])
- # print(scale(params.curve.prime, res[1], **params.curve.parameters)[0])
- # print(P)
- # print(Q)
- # print(R)
- # print(P2)
- # print(Q2)
- # print(R2)
- # print(QR)
- # print("------------------------------------")
- assert (
- scale(params.curve.prime, res[1], **params.curve.parameters)[0]
- == QR
- )
- assert (
- scale(params.curve.prime, res[0], **params.curve.parameters)[0]
- == Q2
- )