From 26348c8f0ef57106acd15bed0ac212195a818061 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Thu, 25 Jun 2026 09:53:49 +0200 Subject: [PATCH] Fix TypeError when passing INFINITY to VerifyingKey.from_public_point() Passing `ellipticcurve.INFINITY` to `VerifyingKey.from_public_point()` raised a `TypeError` ('<=' not supported between instances of 'int' and 'NoneType') instead of the documented `MalformedPointError`. The root cause: `INFINITY.x()` returns `None`, and `Public_key.__init__` compared `0 <= point.x() < p` before checking for the point at infinity. `PointJacobi.from_affine(INFINITY)` also produced a PointJacobi with `x=None`, so the TypeError occurred inside `Public_key.__init__` rather than being caught and re-raised as `MalformedPointError`. Fix by adding an explicit INFINITY guard in both `Public_key.__init__` (raises `InvalidPointError`) and `VerifyingKey.from_public_point` (raises `MalformedPointError`) before any coordinate access. Fixes #341. --- src/ecdsa/ecdsa.py | 2 ++ src/ecdsa/keys.py | 2 ++ src/ecdsa/test_pyecdsa.py | 8 +++++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/ecdsa/ecdsa.py b/src/ecdsa/ecdsa.py index f7109659..4c5f16fb 100644 --- a/src/ecdsa/ecdsa.py +++ b/src/ecdsa/ecdsa.py @@ -148,6 +148,8 @@ def __init__(self, generator, point, verify=True): self.point = point n = generator.order() p = self.curve.p() + if point == ellipticcurve.INFINITY: + raise InvalidPointError("The public point is the point at infinity.") if not (0 <= point.x() < p) or not (0 <= point.y() < p): raise InvalidPointError( "The public point has x or y out of range." diff --git a/src/ecdsa/keys.py b/src/ecdsa/keys.py index f74252c7..2b74d118 100644 --- a/src/ecdsa/keys.py +++ b/src/ecdsa/keys.py @@ -162,6 +162,8 @@ def from_public_point( self = cls(_error__please_use_generate=True) if isinstance(curve.curve, CurveEdTw): raise ValueError("Method incompatible with Edwards curves") + if point == ellipticcurve.INFINITY: + raise MalformedPointError("Cannot use the point at infinity as a public key") if not isinstance(point, ellipticcurve.PointJacobi): point = ellipticcurve.PointJacobi.from_affine(point) self.curve = curve diff --git a/src/ecdsa/test_pyecdsa.py b/src/ecdsa/test_pyecdsa.py index 799e9b74..38784541 100644 --- a/src/ecdsa/test_pyecdsa.py +++ b/src/ecdsa/test_pyecdsa.py @@ -65,7 +65,7 @@ curve_brainpoolp384r1, curve_brainpoolp512r1, ) -from .ellipticcurve import Point +from .ellipticcurve import Point, INFINITY from . import der from . import rfc6979 from . import ecdsa @@ -957,6 +957,12 @@ def test_decoding_with_point_at_infinity(self): with self.assertRaises(MalformedPointError): VerifyingKey.from_string(b"\x00") + def test_from_public_point_with_infinity_raises_malformed(self): + # passing INFINITY to from_public_point must raise MalformedPointError, + # not TypeError (GitHub issue #341) + with self.assertRaises(MalformedPointError): + VerifyingKey.from_public_point(INFINITY) + def test_not_lying_on_curve(self): enc = number_to_string(NIST192p.curve.p(), NIST192p.curve.p() + 1)