diff options
| author | J08nY | 2020-06-13 01:59:22 +0200 |
|---|---|---|
| committer | J08nY | 2020-06-13 01:59:22 +0200 |
| commit | 4e17dfdb12707c814add7851c81eda4edb3dacde (patch) | |
| tree | 1f59c7adad2cc58e3a53d995b029c5a76f591411 /pyecsca/ec/curve.py | |
| parent | 23b3638a496637c1810fb5a2bd610b63b1a72521 (diff) | |
| download | pyecsca-4e17dfdb12707c814add7851c81eda4edb3dacde.tar.gz pyecsca-4e17dfdb12707c814add7851c81eda4edb3dacde.tar.zst pyecsca-4e17dfdb12707c814add7851c81eda4edb3dacde.zip | |
Diffstat (limited to 'pyecsca/ec/curve.py')
| -rw-r--r-- | pyecsca/ec/curve.py | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/pyecsca/ec/curve.py b/pyecsca/ec/curve.py index e8ae66c..a05ff3f 100644 --- a/pyecsca/ec/curve.py +++ b/pyecsca/ec/curve.py @@ -6,8 +6,8 @@ from public import public from .coordinates import CoordinateModel, AffineCoordinateModel from .mod import Mod -from .model import CurveModel -from .point import Point +from .model import CurveModel, ShortWeierstrassModel +from .point import Point, InfinityPoint @public @@ -93,17 +93,62 @@ class EllipticCurve(object): @property def neutral_is_affine(self): + """Whether the neurtal point is an affine point.""" return bool(self.model.base_neutral) def is_neutral(self, point: Point) -> bool: + """Check whether the point is the neutral point.""" return self.neutral == point def is_on_curve(self, point: Point) -> bool: + """Check whether the point is on the curve.""" if point.coordinate_model.curve_model != self.model: return False + if self.is_neutral(point): + return True loc = {**self.parameters, **point.to_affine().coords} return eval(compile(self.model.equation, "", mode="eval"), loc) + def to_affine(self) -> "EllipticCurve": + """Convert this curve into the affine coordinate model, if possible.""" + coord_model = AffineCoordinateModel(self.model) + return EllipticCurve(self.model, coord_model, self.prime, self.neutral.to_affine(), self.parameters) + + def decode_point(self, encoded: bytes) -> Point: + """Decode a point encoded as a sequence of bytes (ANSI X9.62).""" + if encoded[0] == 0x00 and len(encoded) == 1: + return InfinityPoint(self.coordinate_model) + coord_len = (self.prime.bit_length() + 7) // 8 + if encoded[0] in (0x04, 0x06): + data = encoded[1:] + if len(data) != coord_len * len(self.coordinate_model.variables): + raise ValueError("Encoded point has bad length") + coords = {} + for var in sorted(self.coordinate_model.variables): + coords[var] = Mod(int.from_bytes(data[:coord_len], "big"), self.prime) + data = data[coord_len:] + return Point(self.coordinate_model, **coords) + elif encoded[0] in (0x02, 0x03): + if isinstance(self.coordinate_model, AffineCoordinateModel) and isinstance(self.model, ShortWeierstrassModel): + data = encoded[1:] + if len(data) != coord_len: + raise ValueError("Encoded point has bad length") + x = Mod(int.from_bytes(data, "big"), self.prime) + rhs = x**3 + self.parameters["a"] * x + self.parameters["b"] + if not rhs.is_residue(): + raise ValueError("Point not on curve") + sqrt = rhs.sqrt() + yp = encoded[0] & 0x01 + if int(sqrt) & 0x01 == yp: + y = sqrt + else: + y = -sqrt + return Point(self.coordinate_model, x=x, y=y) + else: + raise NotImplementedError + else: + raise ValueError(f"Wrong encoding type: {hex(encoded[0])}, should be one of 0x04, 0x06, 0x02, 0x03 or 0x00") + def __eq__(self, other): if not isinstance(other, EllipticCurve): return False |
