aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2019-12-21 20:30:28 +0100
committerJ08nY2019-12-21 20:55:48 +0100
commit77c3141139be0c3f851dff92f8da6f463e29d57c (patch)
tree2835dc974bba3a6afccae437e745d1bf10843952
parent4cde58b8b0826db51814fc930bfaa3ff3144bc4d (diff)
downloadpyecsca-77c3141139be0c3f851dff92f8da6f463e29d57c.tar.gz
pyecsca-77c3141139be0c3f851dff92f8da6f463e29d57c.tar.bz2
pyecsca-77c3141139be0c3f851dff92f8da6f463e29d57c.zip
Add curve parameters, improve coverage.
-rw-r--r--.coveragerc4
-rw-r--r--Makefile2
-rw-r--r--pyecsca/ec/curves.py238
-rw-r--r--test/ec/curves.py29
-rw-r--r--test/ec/test_context.py9
-rw-r--r--test/ec/test_curve.py28
-rw-r--r--test/ec/test_group.py7
-rw-r--r--test/ec/test_key_agreement.py4
-rw-r--r--test/ec/test_mult.py140
-rw-r--r--test/ec/test_op.py32
-rw-r--r--test/ec/test_point.py13
-rw-r--r--test/ec/test_signature.py4
-rw-r--r--test/sca/test_traceset.py1
13 files changed, 404 insertions, 107 deletions
diff --git a/.coveragerc b/.coveragerc
index 014d16f..fedfb33 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -6,8 +6,10 @@ omit =
[report]
exclude_lines =
+ __repr__
pragma: no cover
raise AssertionError
raise NotImplementedError
if 0:
- if __name__ == .__main__.: \ No newline at end of file
+ if __name__ == .__main__.:
+ \.\.\.$ \ No newline at end of file
diff --git a/Makefile b/Makefile
index 1d7b84d..ca481bd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
EC_TESTS = ec.test_context ec.test_curve ec.test_group ec.test_key_agreement ec.test_mod ec.test_model \
-ec.test_mult ec.test_naf ec.test_point ec.test_signature
+ec.test_mult ec.test_naf ec.test_op ec.test_point ec.test_signature
SCA_TESTS = sca.test_align sca.test_combine sca.test_edit sca.test_filter sca.test_match sca.test_process \
sca.test_sampling sca.test_test sca.test_trace sca.test_traceset
diff --git a/pyecsca/ec/curves.py b/pyecsca/ec/curves.py
new file mode 100644
index 0000000..de919b8
--- /dev/null
+++ b/pyecsca/ec/curves.py
@@ -0,0 +1,238 @@
+from public import public
+from typing import Mapping, Any
+
+from pyecsca.ec.coordinates import AffineCoordinateModel
+from pyecsca.ec.curve import EllipticCurve
+from pyecsca.ec.group import AbelianGroup
+from pyecsca.ec.mod import Mod
+from pyecsca.ec.model import (ShortWeierstrassModel, MontgomeryModel, TwistedEdwardsModel,
+ EdwardsModel)
+from pyecsca.ec.point import Point, InfinityPoint
+
+
+SHORT_WEIERSTRASS: Mapping[str, Mapping[str, Any]] = {
+ "brainpoolP160r1": {
+ "p": 0xE95E4A5F737059DC60DFC7AD95B3D8139515620F,
+ "a": 0x340E7BE2A280EB74E2BE61BADA745D97E8F7C300,
+ "b": 0x1E589A8595423412134FAA2DBDEC95C8D8675E58,
+ "g": (0xBED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3,
+ 0x1667CB477A1A8EC338F94741669C976316DA6321),
+ "n": 0xE95E4A5F737059DC60DF5991D45029409E60FC09,
+ "h": 0x1},
+ "brainpoolP192r1": {
+ "p": 0xC302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297,
+ "a": 0x6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF,
+ "b": 0x469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9,
+ "g": (0xC0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6,
+ 0x14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F),
+ "n": 0xC302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1,
+ "h": 0x1},
+ "brainpoolP224r1": {
+ "p": 0xD7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF,
+ "a": 0x68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43,
+ "b": 0x2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B,
+ "g": (0x0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D,
+ 0x58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD),
+ "n": 0xD7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F,
+ "h": 0x1},
+ "brainpoolP256r1": {
+ "p": 0xA9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377,
+ "a": 0x7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9,
+ "b": 0x26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6,
+ "g": (0x8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262,
+ 0x547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997),
+ "n": 0xA9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7,
+ "h": 0x1},
+ "brainpoolP320r1": {
+ "p": 0xD35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27,
+ "a": 0x3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4,
+ "b": 0x520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6,
+ "g": (
+ 0x43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611,
+ 0x14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1),
+ "n": 0xD35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311,
+ "h": 0x1},
+ "brainpoolP384r1": {
+ "p": 0x8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53,
+ "a": 0x7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826,
+ "b": 0x04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11,
+ "g": (
+ 0x1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E,
+ 0x8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315),
+ "n": 0x8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565,
+ "h": 0x1},
+ "brainpoolP512r1": {
+ "p": 0xAADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3,
+ "a": 0x7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA,
+ "b": 0x3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723,
+ "g": (
+ 0x81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822,
+ 0x7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892),
+ "n": 0xAADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069,
+ "h": 0x1},
+ "secp128r1": {
+ "p": 0xfffffffdffffffffffffffffffffffff,
+ "a": 0xfffffffdfffffffffffffffffffffffc,
+ "b": 0xe87579c11079f43dd824993c2cee5ed3,
+ "g": (0x161ff7528b899b2d0c28607ca52c5b86,
+ 0xcf5ac8395bafeb13c02da292dded7a83),
+ "n": 0xfffffffe0000000075a30d1b9038a115,
+ "h": 0x1},
+ "secp128r2": {
+ "p": 0xfffffffdffffffffffffffffffffffff,
+ "a": 0xd6031998d1b3bbfebf59cc9bbff9aee1,
+ "b": 0x5eeefca380d02919dc2c6558bb6d8a5d,
+ "g": (0x7b6aa5d85e572983e6fb32a7cdebc140,
+ 0x27b6916a894d3aee7106fe805fc34b44),
+ "n": 0x3fffffff7fffffffbe0024720613b5a3,
+ "h":0x4},
+ "secp160k1": {
+ "p": 0xfffffffffffffffffffffffffffffffeffffac73,
+ "a": 0x0000000000000000000000000000000000000000,
+ "b": 0x0000000000000000000000000000000000000007,
+ "g": (0x3b4c382ce37aa192a4019e763036f4f5dd4d7ebb,
+ 0x938cf935318fdced6bc28286531733c3f03c4fee),
+ "n": 0x0100000000000000000001b8fa16dfab9aca16b6b3,
+ "h": 0x1},
+ "secp160r1": {
+ "p": 0xffffffffffffffffffffffffffffffff7fffffff,
+ "a": 0xffffffffffffffffffffffffffffffff7ffffffc,
+ "b": 0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45,
+ "g": (0x4a96b5688ef573284664698968c38bb913cbfc82,
+ 0x23a628553168947d59dcc912042351377ac5fb32),
+ "n": 0x0100000000000000000001f4c8f927aed3ca752257,
+ "h": 0x1},
+ "secp160r2": {
+ "p": 0xfffffffffffffffffffffffffffffffeffffac73,
+ "a": 0xfffffffffffffffffffffffffffffffeffffac70,
+ "b": 0xb4e134d3fb59eb8bab57274904664d5af50388ba,
+ "g": (0x52dcb034293a117e1f4ff11b30f7199d3144ce6d,
+ 0xfeaffef2e331f296e071fa0df9982cfea7d43f2e),
+ "n": 0x0100000000000000000000351ee786a818f3a1a16b,
+ "h": 0x1},
+ "secp192r1": {
+ "p": 0xfffffffffffffffffffffffffffffffeffffffffffffffff,
+ "a": 0xfffffffffffffffffffffffffffffffefffffffffffffffc,
+ "b": 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1,
+ "g": (0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012,
+ 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811),
+ "n": 0xffffffffffffffffffffffff99def836146bc9b1b4d22831,
+ "h": 0x1},
+ "secp224r1": {
+ "p": 0xffffffffffffffffffffffffffffffff000000000000000000000001,
+ "a": 0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe,
+ "b": 0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4,
+ "g": (0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21,
+ 0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34),
+ "n": 0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d,
+ "h": 0x1},
+ "secp256r1": {
+ "p": 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff,
+ "a": 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc,
+ "b": 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b,
+ "g": (0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296,
+ 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5),
+ "n": 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551,
+ "h": 0x1},
+ "secp384r1": {
+ "p": 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff,
+ "a": 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc,
+ "b": 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef,
+ "g": (
+ 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7,
+ 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f),
+ "n": 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973,
+ "h": 0x1},
+ "secp521r1": {
+ "p": 0x000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff,
+ "a": 0x000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc,
+ "b": 0x00000051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00,
+ "g": (
+ 0x000000c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66,
+ 0x0000011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650),
+ "n": 0x000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409,
+ "h": 0x1}}
+
+MONTGOMERY: Mapping[str, Mapping[str, Any]] = {
+ "curve25519": {
+ "p": 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed,
+ "a": 486662,
+ "b": 1,
+ "x": 9,
+ "z": 1,
+ "n": 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED,
+ "h": 2
+ }
+}
+
+EDWARDS: Mapping[str, Mapping[str, Any]] = {
+ "ed448": {
+ "p": 2**448 - 2**224 - 1,
+ "c": 1,
+ "d": 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffff6756,
+ "g": (0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa955555555555555555555555555555555555555555555555555555555,
+ 0xae05e9634ad7048db359d6205086c2b0036ed7a035884dd7b7e36d728ad8c4b80d6565833a2a3098bbbcb2bed1cda06bdaeafbcdea9386ed),
+ "n": 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffff7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3,
+ "h": 4
+ }
+}
+
+TWISTED_EDWARDS: Mapping[str, Mapping[str, Any]] = {
+ "ed25519": {
+ "p": 2 ** 255 - 19,
+ "d": 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3,
+ "a": -1,
+ "g": (0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a,
+ 0x6666666666666666666666666666666666666666666666666666666666666658),
+ "n": 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed,
+ "h": 2
+ }
+}
+
+
+@public
+def get_curve(name: str, coords: str) -> AbelianGroup:
+ """
+ Retrieve a curve from a set of stored parameters.
+
+ :param name: The name of the curve.
+ :param coords: The name of the coordinate system to use.
+ :return: The curve.
+ """
+ if name in SHORT_WEIERSTRASS:
+ params = SHORT_WEIERSTRASS[name]
+ model = ShortWeierstrassModel()
+ coord_model = model.coordinates[coords]
+ curve = EllipticCurve(model, coord_model, params["p"], dict(a=params["a"], b=params["b"]))
+ affine = Point(AffineCoordinateModel(model), x=Mod(params["g"][0], params["p"]),
+ y=Mod(params["g"][1], params["p"]))
+ generator = Point.from_affine(coord_model, affine)
+ return AbelianGroup(curve, generator, InfinityPoint(coord_model), params["n"], params["h"])
+ elif name in MONTGOMERY:
+ params = MONTGOMERY[name]
+ model = MontgomeryModel()
+ coord_model = model.coordinates[coords]
+ curve = EllipticCurve(model, coord_model, params["p"], dict(a=params["a"], b=params["b"]))
+ generator = Point(coord_model, X=Mod(params["x"], params["p"]),
+ Z=Mod(params["z"], params["p"]))
+ return AbelianGroup(curve, generator, InfinityPoint(coord_model), params["n"], params["h"])
+ elif name in TWISTED_EDWARDS:
+ params = TWISTED_EDWARDS[name]
+ model = TwistedEdwardsModel()
+ coord_model = model.coordinates[coords]
+ curve = EllipticCurve(model, coord_model, params["p"], dict(a=params["a"], d=params["d"]))
+ affine = Point(AffineCoordinateModel(model), x=Mod(params["g"][0], params["p"]),
+ y=Mod(params["g"][1], params["p"]))
+ generator = Point.from_affine(coord_model, affine)
+ return AbelianGroup(curve, generator, InfinityPoint(coord_model), params["n"], params["h"])
+ elif name in EDWARDS:
+ params = EDWARDS[name]
+ model = EdwardsModel()
+ coord_model = model.coordinates[coords]
+ curve = EllipticCurve(model, coord_model, params["p"], dict(c=params["c"], d=params["d"]))
+ affine = Point(AffineCoordinateModel(model), x=Mod(params["g"][0], params["p"]),
+ y=Mod(params["g"][1], params["p"]))
+ generator = Point.from_affine(coord_model, affine)
+ return AbelianGroup(curve, generator, InfinityPoint(coord_model), params["n"], params["h"])
+ else:
+ raise ValueError("Unknown curve: {}".format(name))
diff --git a/test/ec/curves.py b/test/ec/curves.py
deleted file mode 100644
index c7453c7..0000000
--- a/test/ec/curves.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from pyecsca.ec.curve import EllipticCurve
-from pyecsca.ec.group import AbelianGroup
-from pyecsca.ec.mod import Mod
-from pyecsca.ec.model import ShortWeierstrassModel, MontgomeryModel
-from pyecsca.ec.point import Point, InfinityPoint
-
-
-def get_secp128r1():
- prime = 0xfffffffdffffffffffffffffffffffff
- model = ShortWeierstrassModel()
- coords = model.coordinates["projective"]
- curve = EllipticCurve(model, coords, prime, dict(a=0xfffffffdfffffffffffffffffffffffc,
- b=0xe87579c11079f43dd824993c2cee5ed3))
- return AbelianGroup(curve, Point(coords, X=Mod(0x161ff7528b899b2d0c28607ca52c5b86, prime),
- Y=Mod(0xcf5ac8395bafeb13c02da292dded7a83, prime),
- Z=Mod(1, prime)), InfinityPoint(coords),
- order=0xfffffffe0000000075a30d1b9038a115, cofactor=1)
-
-
-def get_curve25519():
- prime = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed
- model = MontgomeryModel()
- coords = model.coordinates["xz"]
- curve = EllipticCurve(model, coords, prime,
- dict(a=486662, b=1))
- return AbelianGroup(curve, Point(coords, X=Mod(9, prime), Z=Mod(1, prime)),
- InfinityPoint(coords),
- order=0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED,
- cofactor=2)
diff --git a/test/ec/test_context.py b/test/ec/test_context.py
index 1073fc0..77160cb 100644
--- a/test/ec/test_context.py
+++ b/test/ec/test_context.py
@@ -5,25 +5,24 @@ from pyecsca.ec.context import (local, DefaultContext, OpResult, NullContext, ge
setcontext,
resetcontext)
from pyecsca.ec.coordinates import AffineCoordinateModel
+from pyecsca.ec.curves import get_curve
from pyecsca.ec.mod import Mod
from pyecsca.ec.mult import LTRMultiplier
from pyecsca.ec.point import Point
-from .curves import get_secp128r1
class OpResultTests(TestCase):
- def test_repr(self):
+ def test_str(self):
for op, char in zip((ast.Add(), ast.Sub(), ast.Mult(), ast.Div()), "+-*/"):
res = OpResult("X1", Mod(0, 5), op, Mod(2, 5), Mod(3, 5))
self.assertEqual(str(res), "X1")
- self.assertEqual(repr(res), "X1 = 2{}3".format(char))
class ContextTests(TestCase):
def setUp(self):
- self.secp128r1 = get_secp128r1()
+ self.secp128r1 = get_curve("secp128r1", "projective")
self.base = self.secp128r1.generator
self.coords = self.secp128r1.curve.coordinate_model
self.mult = LTRMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
@@ -51,7 +50,7 @@ class ContextTests(TestCase):
Point(AffineCoordinateModel(self.secp128r1.curve.model),
x=Mod(1, 5), y=Mod(2, 5)))
- def test_repr(self):
+ def test_str(self):
with local(DefaultContext()) as default:
self.mult.multiply(59, self.base)
str(default)
diff --git a/test/ec/test_curve.py b/test/ec/test_curve.py
index 1adaf47..1f2ca1f 100644
--- a/test/ec/test_curve.py
+++ b/test/ec/test_curve.py
@@ -1,17 +1,19 @@
from unittest import TestCase
+from parameterized import parameterized
+
from pyecsca.ec.curve import EllipticCurve
+from pyecsca.ec.curves import get_curve
from pyecsca.ec.mod import Mod
from pyecsca.ec.model import MontgomeryModel
from pyecsca.ec.point import Point
-from .curves import get_secp128r1, get_curve25519
class CurveTests(TestCase):
def setUp(self):
- self.secp128r1 = get_secp128r1()
+ self.secp128r1 = get_curve("secp128r1", "projective")
self.base = self.secp128r1.generator
- self.curve25519 = get_curve25519()
+ self.curve25519 = get_curve("curve25519", "xz")
def test_init(self):
with self.assertRaises(ValueError):
@@ -39,10 +41,22 @@ class CurveTests(TestCase):
Z=Mod(1, self.secp128r1.curve.prime))
assert not self.secp128r1.curve.is_on_curve(other)
+ @parameterized.expand([
+ ("secp128r1","projective"),
+ ("secp256r1", "projective"),
+ ("secp521r1", "projective"),
+ ("curve25519", "xz"),
+ ("ed25519", "projective"),
+ ("ed448", "projective")
+ ])
+ def test_curve_utils(self, name, coords):
+ group = get_curve(name, coords)
+ try:
+ assert group.curve.is_on_curve(group.generator)
+ except NotImplementedError:
+ pass
+
def test_eq(self):
self.assertEqual(self.secp128r1.curve, self.secp128r1.curve)
self.assertNotEqual(self.secp128r1.curve, self.curve25519.curve)
-
- def test_repr(self):
- self.assertEqual(repr(self.secp128r1.curve),
- "EllipticCurve([a=340282366762482138434845932244680310780, b=308990863222245658030922601041482374867] on ShortWeierstrassModel() using EFDCoordinateModel(\"projective\" on short Weierstrass curves))")
+ self.assertNotEqual(self.secp128r1.curve, None)
diff --git a/test/ec/test_group.py b/test/ec/test_group.py
index e3b3a72..ca0ea91 100644
--- a/test/ec/test_group.py
+++ b/test/ec/test_group.py
@@ -1,14 +1,14 @@
from unittest import TestCase
+from pyecsca.ec.curves import get_curve
from pyecsca.ec.point import InfinityPoint
-from .curves import get_secp128r1, get_curve25519
class AbelianGroupTests(TestCase):
def setUp(self):
- self.secp128r1 = get_secp128r1()
- self.curve25519 = get_curve25519()
+ self.secp128r1 = get_curve("secp128r1", "projective")
+ self.curve25519 = get_curve("curve25519", "xz")
def test_is_neutral(self):
assert self.secp128r1.is_neutral(InfinityPoint(self.secp128r1.curve.coordinate_model))
@@ -16,3 +16,4 @@ class AbelianGroupTests(TestCase):
def test_eq(self):
self.assertEqual(self.secp128r1, self.secp128r1)
self.assertNotEqual(self.secp128r1, self.curve25519)
+ self.assertNotEqual(self.secp128r1, None)
diff --git a/test/ec/test_key_agreement.py b/test/ec/test_key_agreement.py
index f22ee75..ab009e3 100644
--- a/test/ec/test_key_agreement.py
+++ b/test/ec/test_key_agreement.py
@@ -1,14 +1,14 @@
from unittest import TestCase
+from pyecsca.ec.curves import get_curve
from pyecsca.ec.key_agreement import *
from pyecsca.ec.mult import LTRMultiplier
-from .curves import get_secp128r1
class KeyAgreementTests(TestCase):
def setUp(self):
- self.secp128r1 = get_secp128r1()
+ self.secp128r1 = get_curve("secp128r1", "projective")
self.add = self.secp128r1.curve.coordinate_model.formulas["add-2007-bl"]
self.dbl = self.secp128r1.curve.coordinate_model.formulas["dbl-2007-bl"]
self.mult = LTRMultiplier(self.secp128r1, self.add, self.dbl)
diff --git a/test/ec/test_mult.py b/test/ec/test_mult.py
index c72f370..3abc72c 100644
--- a/test/ec/test_mult.py
+++ b/test/ec/test_mult.py
@@ -1,47 +1,67 @@
from unittest import TestCase
+from parameterized import parameterized
+
+from pyecsca.ec.curves import get_curve
from pyecsca.ec.mult import (LTRMultiplier, RTLMultiplier, LadderMultiplier, BinaryNAFMultiplier,
WindowNAFMultiplier, SimpleLadderMultiplier, CoronMultiplier)
from pyecsca.ec.point import InfinityPoint
-from .curves import get_secp128r1, get_curve25519
class ScalarMultiplierTests(TestCase):
def setUp(self):
- self.secp128r1 = get_secp128r1()
+ self.secp128r1 = get_curve("secp128r1", "projective")
self.base = self.secp128r1.generator
self.coords = self.secp128r1.curve.coordinate_model
- self.curve25519 = get_curve25519()
+ self.curve25519 = get_curve("curve25519", "xz")
self.base25519 = self.curve25519.generator
self.coords25519 = self.curve25519.curve.coordinate_model
- def test_rtl(self):
- mult = RTLMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
- self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"])
+ def get_formulas(self, coords, *names):
+ return [coords.formulas[name] for name in names if name is not None]
+
+ def assertPointEquality(self, one, other, scale):
+ if scale:
+ self.assertEqual(one, other)
+ else:
+ assert one.equals(other)
+
+ @parameterized.expand([
+ ("scaled", "add-1998-cmo", "dbl-1998-cmo", "z"),
+ ("none", "add-1998-cmo", "dbl-1998-cmo", None)
+ ])
+ def test_rtl(self, name, add, dbl, scale):
+ mult = RTLMultiplier(self.secp128r1, *self.get_formulas(self.coords, add, dbl, scale))
res = mult.multiply(10, self.base)
other = mult.multiply(5, self.base)
other = mult.multiply(2, other)
- self.assertEqual(res, other)
+ self.assertPointEquality(res, other, scale)
self.assertEqual(InfinityPoint(self.coords), mult.multiply(0, self.base))
- def test_ltr(self):
- mult = LTRMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
- self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"])
+ @parameterized.expand([
+ ("scaled", "add-1998-cmo", "dbl-1998-cmo", "z"),
+ ("none", "add-1998-cmo", "dbl-1998-cmo", None)
+ ])
+ def test_ltr(self, name, add, dbl, scale):
+ mult = LTRMultiplier(self.secp128r1, *self.get_formulas(self.coords, add, dbl, scale))
res = mult.multiply(10, self.base)
other = mult.multiply(5, self.base)
other = mult.multiply(2, other)
- self.assertEqual(res, other)
+ self.assertPointEquality(res, other, scale)
self.assertEqual(InfinityPoint(self.coords), mult.multiply(0, self.base))
- def test_coron(self):
- mult = CoronMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
- self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"])
+ @parameterized.expand([
+ ("scaled", "add-1998-cmo", "dbl-1998-cmo", "z"),
+ ("none", "add-1998-cmo", "dbl-1998-cmo", None)
+ ])
+ def test_coron(self, name, add, dbl, scale):
+ mult = CoronMultiplier(self.secp128r1, *self.get_formulas(self.coords, add, dbl, scale))
res = mult.multiply(10, self.base)
other = mult.multiply(5, self.base)
other = mult.multiply(2, other)
- self.assertEqual(res, other)
+ self.assertPointEquality(res, other, scale)
self.assertEqual(InfinityPoint(self.coords), mult.multiply(0, self.base))
def test_ladder(self):
@@ -54,17 +74,24 @@ class ScalarMultiplierTests(TestCase):
self.assertEqual(res, other)
self.assertEqual(InfinityPoint(self.coords25519), mult.multiply(0, self.base25519))
- def test_simple_ladder(self):
- mult = SimpleLadderMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
- self.coords.formulas["dbl-1998-cmo"],
- self.coords.formulas["z"])
+ @parameterized.expand([
+ ("scaled", "add-1998-cmo", "dbl-1998-cmo", "z"),
+ ("none", "add-1998-cmo", "dbl-1998-cmo", None)
+ ])
+ def test_simple_ladder(self, name, add, dbl, scale):
+ mult = SimpleLadderMultiplier(self.secp128r1,
+ *self.get_formulas(self.coords, add, dbl, scale))
res = mult.multiply(10, self.base)
other = mult.multiply(5, self.base)
other = mult.multiply(2, other)
- self.assertEqual(res, other)
+ self.assertPointEquality(res, other, scale)
self.assertEqual(InfinityPoint(self.coords), mult.multiply(0, self.base))
- def test_ladder_differential(self):
+ @parameterized.expand([
+ ("10", 15),
+ ("2355498743", 2355498743,)
+ ])
+ def test_ladder_differential(self, name, num):
ladder = LadderMultiplier(self.curve25519, self.coords25519.formulas["ladd-1987-m"],
self.coords25519.formulas["dbl-1987-m"],
self.coords25519.formulas["scale"])
@@ -72,45 +99,53 @@ class ScalarMultiplierTests(TestCase):
self.coords25519.formulas["dadd-1987-m"],
self.coords25519.formulas["dbl-1987-m"],
self.coords25519.formulas["scale"])
- res_ladder = ladder.multiply(15, self.base25519)
- res_differential = differential.multiply(15, self.base25519)
+ res_ladder = ladder.multiply(num, self.base25519)
+ res_differential = differential.multiply(num, self.base25519)
self.assertEqual(res_ladder, res_differential)
self.assertEqual(InfinityPoint(self.coords25519), differential.multiply(0, self.base25519))
- def test_binary_naf(self):
- mult = BinaryNAFMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
- self.coords.formulas["dbl-1998-cmo"],
- self.coords.formulas["neg"], self.coords.formulas["z"])
+ @parameterized.expand([
+ ("scaled", "add-1998-cmo", "dbl-1998-cmo", "neg", "z"),
+ ("none", "add-1998-cmo", "dbl-1998-cmo", "neg", None)
+ ])
+ def test_binary_naf(self, name, add, dbl, neg, scale):
+ mult = BinaryNAFMultiplier(self.secp128r1,
+ *self.get_formulas(self.coords, add, dbl, neg, scale))
res = mult.multiply(10, self.base)
other = mult.multiply(5, self.base)
other = mult.multiply(2, other)
- self.assertEqual(res, other)
+ self.assertPointEquality(res, other, scale)
self.assertEqual(InfinityPoint(self.coords), mult.multiply(0, self.base))
- def test_window_naf(self):
- mult = WindowNAFMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
- self.coords.formulas["dbl-1998-cmo"],
- self.coords.formulas["neg"], 3, self.coords.formulas["z"])
+ @parameterized.expand([
+ ("scaled3", "add-1998-cmo", "dbl-1998-cmo", "neg", 3, "z"),
+ ("none3", "add-1998-cmo", "dbl-1998-cmo", "neg", 3, None)
+ ])
+ def test_window_naf(self, name, add, dbl, neg, width, scale):
+ formulas = self.get_formulas(self.coords, add, dbl, neg, scale)
+ mult = WindowNAFMultiplier(self.secp128r1, *formulas[:3], width, *formulas[3:])
res = mult.multiply(10, self.base)
other = mult.multiply(5, self.base)
other = mult.multiply(2, other)
- self.assertEqual(res, other)
+ self.assertPointEquality(res, other, scale)
self.assertEqual(InfinityPoint(self.coords), mult.multiply(0, self.base))
- mult = WindowNAFMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
- self.coords.formulas["dbl-1998-cmo"],
- self.coords.formulas["neg"], 3, self.coords.formulas["z"],
+ mult = WindowNAFMultiplier(self.secp128r1, *formulas[:3], width, *formulas[3:],
precompute_negation=True)
res_precompute = mult.multiply(10, self.base)
- self.assertEqual(res_precompute, res)
+ self.assertPointEquality(res_precompute, res, scale)
- def test_basic_multipliers(self):
+ @parameterized.expand([
+ ("10", 10),
+ ("2355498743", 2355498743,)
+ ])
+ def test_basic_multipliers(self, name, num):
ltr = LTRMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"])
- res_ltr = ltr.multiply(10, self.base)
+ res_ltr = ltr.multiply(num, self.base)
rtl = RTLMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"])
- res_rtl = rtl.multiply(10, self.base)
+ res_rtl = rtl.multiply(num, self.base)
self.assertEqual(res_ltr, res_rtl)
ltr_always = LTRMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
@@ -119,31 +154,44 @@ class ScalarMultiplierTests(TestCase):
rtl_always = RTLMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"],
always=True)
- res_ltr_always = ltr_always.multiply(10, self.base)
- res_rtl_always = rtl_always.multiply(10, self.base)
+ res_ltr_always = ltr_always.multiply(num, self.base)
+ res_rtl_always = rtl_always.multiply(num, self.base)
self.assertEqual(res_ltr, res_ltr_always)
self.assertEqual(res_rtl, res_rtl_always)
bnaf = BinaryNAFMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
self.coords.formulas["dbl-1998-cmo"],
self.coords.formulas["neg"], self.coords.formulas["z"])
- res_bnaf = bnaf.multiply(10, self.base)
+ res_bnaf = bnaf.multiply(num, self.base)
self.assertEqual(res_bnaf, res_ltr)
wnaf = WindowNAFMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
self.coords.formulas["dbl-1998-cmo"],
self.coords.formulas["neg"], 3, self.coords.formulas["z"])
- res_wnaf = wnaf.multiply(10, self.base)
+ res_wnaf = wnaf.multiply(num, self.base)
self.assertEqual(res_wnaf, res_ltr)
ladder = SimpleLadderMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
self.coords.formulas["dbl-1998-cmo"],
self.coords.formulas["z"])
- res_ladder = ladder.multiply(10, self.base)
+ res_ladder = ladder.multiply(num, self.base)
self.assertEqual(res_ladder, res_ltr)
coron = CoronMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
self.coords.formulas["dbl-1998-cmo"],
self.coords.formulas["z"])
- res_coron = coron.multiply(10, self.base)
+ res_coron = coron.multiply(num, self.base)
self.assertEqual(res_coron, res_ltr)
+
+ def test_init_fail(self):
+ with self.assertRaises(ValueError):
+ SimpleLadderMultiplier(self.secp128r1,
+ self.coords25519.formulas["dadd-1987-m"],
+ self.coords25519.formulas["dbl-1987-m"],
+ self.coords25519.formulas["scale"])
+
+ def test_mult_fail(self):
+ mult = LTRMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
+ self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"])
+ with self.assertRaises(ValueError):
+ mult.multiply(15)
diff --git a/test/ec/test_op.py b/test/ec/test_op.py
new file mode 100644
index 0000000..13efc53
--- /dev/null
+++ b/test/ec/test_op.py
@@ -0,0 +1,32 @@
+from ast import parse
+from unittest import TestCase
+
+from parameterized import parameterized
+
+from pyecsca.ec.mod import Mod
+from pyecsca.ec.op import CodeOp
+
+
+class OpTests(TestCase):
+
+ @parameterized.expand([
+ ("add", "x = a+b", "x = a+b"),
+ ("sub", "x = a-b", "x = a-b"),
+ ("mul", "y = a*b", "y = a*b"),
+ ("div", "z = a/b", "z = a/b"),
+ ("pow", "b = a**d", "b = a^d")
+ ])
+ def test_str(self, name, module, result):
+ code = parse(module, mode="exec")
+ op = CodeOp(code)
+ self.assertEqual(str(op), result)
+
+ @parameterized.expand([
+ ("add", "x = a+b", {"a": Mod(5, 21), "b": Mod(7, 21)}, Mod(12, 21)),
+ ("sub", "x = a-b", {"a": Mod(7, 21), "b": Mod(5, 21)}, Mod(2, 21))
+ ])
+ def test_call(self, name, module, locals, result):
+ code = parse(module, mode="exec")
+ op = CodeOp(code)
+ res = op(**locals)
+ self.assertEqual(res, result)
diff --git a/test/ec/test_point.py b/test/ec/test_point.py
index c80d4cc..0809edc 100644
--- a/test/ec/test_point.py
+++ b/test/ec/test_point.py
@@ -1,15 +1,15 @@
from unittest import TestCase
from pyecsca.ec.coordinates import AffineCoordinateModel
+from pyecsca.ec.curves import get_curve
from pyecsca.ec.mod import Mod
from pyecsca.ec.model import ShortWeierstrassModel, MontgomeryModel
from pyecsca.ec.point import Point, InfinityPoint
-from .curves import get_secp128r1
class PointTests(TestCase):
def setUp(self):
- self.secp128r1 = get_secp128r1()
+ self.secp128r1 = get_curve("secp128r1", "projective")
self.base = self.secp128r1.generator
self.coords = self.secp128r1.curve.coordinate_model
self.affine = AffineCoordinateModel(ShortWeierstrassModel())
@@ -81,12 +81,3 @@ class PointTests(TestCase):
Z=Mod(1, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa))
assert not pt.equals(different)
self.assertNotEqual(pt, different)
-
- def test_repr(self):
- self.assertEqual(str(self.base),
- "[X=29408993404948928992877151431649155974, Y=275621562871047521857442314737465260675, Z=1]")
- self.assertEqual(repr(self.base),
- "Point([[X=29408993404948928992877151431649155974, Y=275621562871047521857442314737465260675, Z=1]] in EFDCoordinateModel(\"projective\" on short Weierstrass curves))")
- self.assertEqual(str(InfinityPoint(self.coords)), "Infinity")
- self.assertEqual(repr(InfinityPoint(self.coords)),
- "InfinityPoint(EFDCoordinateModel(\"projective\" on short Weierstrass curves))")
diff --git a/test/ec/test_signature.py b/test/ec/test_signature.py
index d9b306a..06b6123 100644
--- a/test/ec/test_signature.py
+++ b/test/ec/test_signature.py
@@ -1,15 +1,15 @@
from hashlib import sha1
from unittest import TestCase
+from pyecsca.ec.curves import get_curve
from pyecsca.ec.mult import LTRMultiplier
from pyecsca.ec.signature import *
-from .curves import get_secp128r1
class SignatureTests(TestCase):
def setUp(self):
- self.secp128r1 = get_secp128r1()
+ self.secp128r1 = get_curve("secp128r1", "projective")
self.add = self.secp128r1.curve.coordinate_model.formulas["add-2007-bl"]
self.dbl = self.secp128r1.curve.coordinate_model.formulas["dbl-2007-bl"]
self.mult = LTRMultiplier(self.secp128r1, self.add, self.dbl)
diff --git a/test/sca/test_traceset.py b/test/sca/test_traceset.py
index f12f205..6d48707 100644
--- a/test/sca/test_traceset.py
+++ b/test/sca/test_traceset.py
@@ -20,6 +20,7 @@ class InspectorTraceSetTests(TestCase):
self.assertIsNotNone(result)
self.assertEqual(result.global_title, "Example trace set")
self.assertEqual(len(result), 10)
+ self.assertEqual(len(list(result)), 10)
self.assertIn("InspectorTraceSet", str(result))
self.assertIs(result[0].trace_set, result)
self.assertEqual(result.sampling_frequency, 12500000)