Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ t/
.project
.pydevproject

#vscode
.vscode

# Backup files
*.swp
*~
14 changes: 14 additions & 0 deletions src/ecdsa/ecdsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ def __init__(self, generator, point):
if point.x() < 0 or n <= point.x() or point.y() < 0 or n <= point.y():
raise RuntimeError("Generator point has x or y out of range.")

def __eq__(self, other):
if isinstance(other, Public_key):
"""Return True if the points are identical, False otherwise."""
return self.curve == other.curve \
and self.point == other.point
return NotImplemented

def verifies(self, hash, signature):
"""Verify that signature is a valid signature of hash.
Return True if the signature is valid.
Expand Down Expand Up @@ -153,6 +160,13 @@ def __init__(self, public_key, secret_multiplier):

self.public_key = public_key
self.secret_multiplier = secret_multiplier

def __eq__(self, other):
if isinstance(other, Private_key):
"""Return True if the points are identical, False otherwise."""
return self.public_key == other.public_key \
and self.secret_multiplier == other.secret_multiplier
return NotImplemented

def sign(self, hash, random_k):
"""Return a signature for the provided hash, using the provided
Expand Down
20 changes: 13 additions & 7 deletions src/ecdsa/ellipticcurve.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ def __init__(self, p, a, b):
self.__p = p
self.__a = a
self.__b = b

def __eq__(self, other):
if isinstance(other, CurveFp):
"""Return True if the curves are identical, False otherwise."""
return self.__p == other.__p \
and self.__a == other.__a \
and self.__b == other.__b
return NotImplemented

def p(self):
return self.__p
Expand Down Expand Up @@ -79,12 +87,11 @@ def __init__(self, curve, x, y, order=None):

def __eq__(self, other):
"""Return True if the points are identical, False otherwise."""
if self.__curve == other.__curve \
and self.__x == other.__x \
and self.__y == other.__y:
return True
else:
return False
if isinstance(other, Point):
return self.__curve == other.__curve \
and self.__x == other.__x \
and self.__y == other.__y
return NotImplemented

def __neg__(self):
return Point(self.__curve, self.__x, self.__curve.p() - self.__y)
Expand Down Expand Up @@ -195,4 +202,3 @@ def order(self):

# This one point is the Point At Infinity for all purposes:
INFINITY = Point(None, None, None)

15 changes: 15 additions & 0 deletions src/ecdsa/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,13 @@ def __repr__(self):
pub_key = self.to_string("compressed")
return "VerifyingKey.from_string({0!r}, {1!r}, {2})".format(
pub_key, self.curve, self.default_hashfunc().name)

def __eq__(self, other):
"""Return True if the points are identical, False otherwise."""
if isinstance(other, VerifyingKey):
return self.curve == other.curve \
and self.pubkey == other.pubkey
return NotImplemented

@classmethod
def from_public_point(cls, point, curve=NIST192p, hashfunc=sha1):
Expand Down Expand Up @@ -649,6 +656,14 @@ def __init__(self, _error__please_use_generate=None):
self.baselen = None
self.verifying_key = None
self.privkey = None

def __eq__(self, other):
"""Return True if the points are identical, False otherwise."""
if isinstance(other, SigningKey):
return self.curve == other.curve \
and self.verifying_key == other.verifying_key \
and self.privkey == other.privkey
return NotImplemented

@classmethod
def generate(cls, curve=NIST192p, entropy=None, hashfunc=sha1):
Expand Down
59 changes: 59 additions & 0 deletions src/ecdsa/test_ecdsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,65 @@ def test_rejection(self):
assert not self.pubk.verifies(self.msg - 1, self.sig)


class TestPublicKey(unittest.TestCase):

def test_equality_public_keys(self):
gen = generator_192
x = 0xc58d61f88d905293bcd4cd0080bcb1b7f811f2ffa41979f6
y = 0x8804dc7a7c4c7f8b5d437f5156f3312ca7d6de8a0e11867f
point = ellipticcurve.Point(gen.curve(), x, y)
pub_key1 = Public_key(gen, point)
pub_key2 = Public_key(gen, point)
self.assertEqual(pub_key1, pub_key2)

def test_inequality_public_key(self):
gen = generator_192
x1 = 0xc58d61f88d905293bcd4cd0080bcb1b7f811f2ffa41979f6
y1 = 0x8804dc7a7c4c7f8b5d437f5156f3312ca7d6de8a0e11867f
point1 = ellipticcurve.Point(gen.curve(), x1, y1)

x2 = 0x6a223d00bd22c52833409a163e057e5b5da1def2a197dd15
y2 = 0x7b482604199367f1f303f9ef627f922f97023e90eae08abf
point2 = ellipticcurve.Point(gen.curve(), x2, y2)

pub_key1 = Public_key(gen, point1)
pub_key2 = Public_key(gen, point2)
self.assertNotEqual(pub_key1, pub_key2)

def test_inequality_public_key_not_implemented(self):
gen = generator_192
x = 0xc58d61f88d905293bcd4cd0080bcb1b7f811f2ffa41979f6
y = 0x8804dc7a7c4c7f8b5d437f5156f3312ca7d6de8a0e11867f
point = ellipticcurve.Point(gen.curve(), x, y)
pub_key = Public_key(gen, point)
self.assertNotEqual(pub_key, None)


class TestPrivateKey(unittest.TestCase):

@classmethod
def setUpClass(cls):
gen = generator_192
x = 0xc58d61f88d905293bcd4cd0080bcb1b7f811f2ffa41979f6
y = 0x8804dc7a7c4c7f8b5d437f5156f3312ca7d6de8a0e11867f
point = ellipticcurve.Point(gen.curve(), x, y)
cls.pub_key = Public_key(gen, point)

def test_equality_private_keys(self):
pr_key1 = Private_key(self.pub_key, 100)
pr_key2 = Private_key(self.pub_key, 100)
self.assertEqual(pr_key1, pr_key2)

def test_inequality_private_keys(self):
pr_key1 = Private_key(self.pub_key, 100)
pr_key2 = Private_key(self.pub_key, 200)
self.assertNotEqual(pr_key1, pr_key2)

def test_inequality_private_keys_not_implemented(self):
pr_key = Private_key(self.pub_key, 100)
self.assertNotEqual(pr_key, None)


# Testing point validity, as per ECDSAVS.pdf B.2.2:
P192_POINTS = [
(generator_192,
Expand Down
180 changes: 111 additions & 69 deletions src/ecdsa/test_ellipticcurve.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,28 +30,11 @@
Gx = 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012
Gy = 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811


c192 = CurveFp(p, -3, b)
p192 = Point(c192, Gx, Gy, r)


def test_p192():
# Checking against some sample computations presented
# in X9.62:
d = 651056770906015076056810763456358567190100156695615665659
Q = d * p192
assert Q.x() == 0x62B12D60690CDCF330BABAB6E69763B471F994DD702D16A5

k = 6140507067065001063065065565667405560006161556565665656654
R = k * p192
assert R.x() == 0x885052380FF147B734C330C43D39B2C4A89F29B0F749FEAD \
and R.y() == 0x9CF9FA1CBEFEFB917747A3BB29C072B9289C2547884FD835

u1 = 2563697409189434185194736134579731015366492496392189760599
u2 = 6266643813348617967186477710235785849136406323338782220568
temp = u1 * p192 + u2 * Q
assert temp.x() == 0x885052380FF147B734C330C43D39B2C4A89F29B0F749FEAD \
and temp.y() == 0x9CF9FA1CBEFEFB917747A3BB29C072B9289C2547884FD835
c_23 = CurveFp(23, 1, 1)
g_23 = Point(c_23, 13, 7, 7)


@settings(**HYP_SETTINGS)
Expand All @@ -61,63 +44,16 @@ def test_p192_mult_tests(multiple):

p1 = p192 * multiple
assert p1 * inv_m == p192


def add_n_times(point, n):
ret = INFINITY
i = 0
while i <= n:
yield ret
ret = ret + point
i += 1


c_23 = CurveFp(23, 1, 1)


g_23 = Point(c_23, 13, 7, 7)


# Trivial tests from X9.62 B.3:
@pytest.mark.parametrize(
"c,x1,y1,x2,y2,x3,y3",
[(c_23, 3, 10, 9, 7, 17, 20),
(c_23, 3, 10, 3, 10, 7, 12)],
ids=["real add", "double"])
def test_add(c, x1, y1, x2, y2, x3, y3):
"""We expect that on curve c, (x1,y1) + (x2, y2 ) = (x3, y3)."""
p1 = Point(c, x1, y1)
p2 = Point(c, x2, y2)
p3 = p1 + p2
assert p3.x() == x3 and p3.y() == y3


@pytest.mark.parametrize(
"c, x1, y1, x3, y3",
[(c_23, 3, 10, 7, 12)],
ids=["real add"])
def test_double(c, x1, y1, x3, y3):
p1 = Point(c, x1, y1)
p3 = p1.double()
assert p3.x() == x3 and p3.y() == y3


def test_double_infinity():
p1 = INFINITY
p3 = p1.double()
assert p1 == p3
assert p3.x() == p1.x() and p3.y() == p3.y()


@pytest.mark.parametrize(
"c, x1, y1, m, x3, y3",
[(c_23, 3, 10, 2, 7, 12)],
ids=["multiply by 2"])
def test_multiply(c, x1, y1, m, x3, y3):
p1 = Point(c, x1, y1)
p3 = p1 * m
assert p3.x() == x3 and p3.y() == y3



# From X9.62 I.1 (p. 96):
@pytest.mark.parametrize(
Expand All @@ -126,3 +62,109 @@ def test_multiply(c, x1, y1, m, x3, y3):
ids=["g_23 test with mult {0}".format(i) for i in range(9)])
def test_add_and_mult_equivalence(p, m, check):
assert p * m == check


class TestCurve(unittest.TestCase):

@classmethod
def setUpClass(cls):
cls.c_23 = CurveFp(23, 1, 1)

def test_equality_curves(self):
self.assertEqual(self.c_23, CurveFp(23, 1, 1))

def test_inequality_curves(self):
c192 = CurveFp(p, -3, b)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the other test cases use global variables because they use the functional style and the pytest framework, this one uses the object-based approach from unittest, so I'd say that the use of global variables is less clean here...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to classes. Not sure if it is possible to convert test_p192_mult_tests preserving functionality.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, I'm fine with either approach, what I'm not a fan of is mixing them

self.assertNotEqual(self.c_23, c192)


class TestPoint(unittest.TestCase):

@classmethod
def setUpClass(cls):
cls.c_23 = CurveFp(23, 1, 1)
cls.g_23 = Point(cls.c_23, 13, 7, 7)

p = 6277101735386680763835789423207666416083908700390324961279
r = 6277101735386680763835789423176059013767194773182842284081
# s = 0x3045ae6fc8422f64ed579528d38120eae12196d5
# c = 0x3099d2bbbfcb2538542dcd5fb078b6ef5f3d6fe2c745de65
b = 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1
Gx = 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012
Gy = 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811

cls.c192 = CurveFp(p, -3, b)
cls.p192 = Point(cls.c192, Gx, Gy, r)

def test_p192(self):
# Checking against some sample computations presented
# in X9.62:
d = 651056770906015076056810763456358567190100156695615665659
Q = d * self.p192
self.assertEqual(Q.x(), 0x62B12D60690CDCF330BABAB6E69763B471F994DD702D16A5)

k = 6140507067065001063065065565667405560006161556565665656654
R = k * self.p192
self.assertEqual(R.x(), 0x885052380FF147B734C330C43D39B2C4A89F29B0F749FEAD)
self.assertEqual(R.y(), 0x9CF9FA1CBEFEFB917747A3BB29C072B9289C2547884FD835)

u1 = 2563697409189434185194736134579731015366492496392189760599
u2 = 6266643813348617967186477710235785849136406323338782220568
temp = u1 * self.p192 + u2 * Q
self.assertEqual(temp.x(), 0x885052380FF147B734C330C43D39B2C4A89F29B0F749FEAD)
self.assertEqual(temp.y(), 0x9CF9FA1CBEFEFB917747A3BB29C072B9289C2547884FD835)

def test_double_infinity(self):
p1 = INFINITY
p3 = p1.double()
self.assertEqual(p1, p3)
self.assertEqual(p3.x(), p1.x())
self.assertEqual(p3.y(), p3.y())

def test_double(self):
x1, y1, x3, y3 = (3, 10, 7, 12)

p1 = Point(self.c_23, x1, y1)
p3 = p1.double()
self.assertEqual(p3.x(), x3)
self.assertEqual(p3.y(), y3)

def test_multiply(self):
x1, y1, m, x3, y3 = (3, 10, 2, 7, 12)
p1 = Point(self.c_23, x1, y1)
p3 = p1 * m
self.assertEqual(p3.x(), x3)
self.assertEqual(p3.y(), y3)

# Trivial tests from X9.62 B.3:
def test_add(self):
"""We expect that on curve c, (x1,y1) + (x2, y2 ) = (x3, y3)."""

x1, y1, x2, y2, x3, y3 = (3, 10, 9, 7, 17, 20)
p1 = Point(self.c_23, x1, y1)
p2 = Point(self.c_23, x2, y2)
p3 = p1 + p2
self.assertEqual(p3.x(), x3)
self.assertEqual(p3.y(), y3)

def test_add_as_double(self):
"""We expect that on curve c, (x1,y1) + (x2, y2 ) = (x3, y3)."""

x1, y1, x2, y2, x3, y3 = (3, 10, 3, 10, 7, 12)
p1 = Point(self.c_23, x1, y1)
p2 = Point(self.c_23, x2, y2)
p3 = p1 + p2
self.assertEqual(p3.x(), x3)
self.assertEqual(p3.y(), y3)

def test_equality_points(self):
self.assertEqual(self.g_23, Point(self.c_23, 13, 7, 7))

def test_inequality_points(self):
c = CurveFp(100, -3, 100)
p = Point(c, 100, 100, 100)
self.assertNotEqual(self.g_23, p)

def test_inaquality_points_diff_types(self):
c = CurveFp(100, -3, 100)
self.assertNotEqual(self.g_23, c)
Loading