Skip to content

Commit

Permalink
precompute for generators
Browse files Browse the repository at this point in the history
  • Loading branch information
tomato42 committed Oct 9, 2019
1 parent fefe893 commit 412cb40
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 9 deletions.
13 changes: 7 additions & 6 deletions src/ecdsa/curves.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import division

from . import der, ecdsa
from .ellipticcurve import PointJacobi


class UnknownCurveError(Exception):
Expand All @@ -26,22 +27,22 @@ def __init__(self, name, curve, generator, oid, openssl_name=None):
self.encoded_oid = der.encode_oid(*oid)

NIST192p = Curve("NIST192p", ecdsa.curve_192,
ecdsa.generator_192,
PointJacobi.from_weierstrass(ecdsa.generator_192, True),
(1, 2, 840, 10045, 3, 1, 1), "prime192v1")
NIST224p = Curve("NIST224p", ecdsa.curve_224,
ecdsa.generator_224,
PointJacobi.from_weierstrass(ecdsa.generator_224, True),
(1, 3, 132, 0, 33), "secp224r1")
NIST256p = Curve("NIST256p", ecdsa.curve_256,
ecdsa.generator_256,
PointJacobi.from_weierstrass(ecdsa.generator_256, True),
(1, 2, 840, 10045, 3, 1, 7), "prime256v1")
NIST384p = Curve("NIST384p", ecdsa.curve_384,
ecdsa.generator_384,
PointJacobi.from_weierstrass(ecdsa.generator_384, True),
(1, 3, 132, 0, 34), "secp384r1")
NIST521p = Curve("NIST521p", ecdsa.curve_521,
ecdsa.generator_521,
PointJacobi.from_weierstrass(ecdsa.generator_521, True),
(1, 3, 132, 0, 35), "secp521r1")
SECP256k1 = Curve("SECP256k1", ecdsa.curve_secp256k1,
ecdsa.generator_secp256k1,
PointJacobi.from_weierstrass(ecdsa.generator_secp256k1, True),
(1, 3, 132, 0, 10), "secp256k1")

curves = [NIST192p, NIST224p, NIST256p, NIST384p, NIST521p, SECP256k1]
Expand Down
36 changes: 33 additions & 3 deletions src/ecdsa/ellipticcurve.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,24 @@ def __str__(self):

class PointJacobi(object):
"""Point on an elliptic curve. Uses Jacobi representation"""
def __init__(self, curve, x, y, z, order=None):
def __init__(self, curve, x, y, z, order=None, generator=False):
self.__curve = curve
self.__x = x
self.__y = y
self.__z = z
self.__order = order
self.__precompute={}
if generator:
assert order
i = 1
doubler = PointJacobi(curve, x, y, z, order)
self.__precompute[i] = doubler
doubler = doubler.double().normalise()

while i < order:
i *= 2
self.__precompute[i] = doubler
doubler = doubler.double().normalise()

def __eq__(self, other):
"""Compare two points with each-other."""
Expand Down Expand Up @@ -98,6 +110,10 @@ def y(self):
z = numbertheory.inverse_mod(self.__z, p)
return self.__y * z**3 % p

def normalise(self):
"""Return point with z == 1."""
return self.from_weierstrass(self.to_weierstrass())

def to_weierstrass(self):
"""Return point in Weierstrass form"""
p = self.__curve.p()
Expand All @@ -106,10 +122,10 @@ def to_weierstrass(self):
self.__y * z**3 % p, self.__order)

@staticmethod
def from_weierstrass(point):
def from_weierstrass(point, generator=False):
"""Create from a Weierstrass form point"""
return PointJacobi(point.curve(), point.x(), point.y(), 1,
point.order())
point.order(), generator)

def double(self):
"""Add a point to itself."""
Expand Down Expand Up @@ -225,12 +241,26 @@ def __rmul__(self, other):
"""Multiply point by an integer."""
return self * other

def _mul_precompute(self, other):
i = 1
result = None
while i <= other:
if i & other:
if result:
result = result + self.__precompute[i]
else:
result = self.__precompute[i]
i *= 2
return result

def __mul__(self, other):
"""Multiply point by an integer."""
if self.__y == 0 or other == 0:
return PointJacobi(self.__curve, 0, 0, 1)
if other == 1:
return self
if self.__precompute:
return self._mul_precompute(other)
# makes vulnerable to Minerva
#if self.__order:
# other = other % self.__order
Expand Down
11 changes: 11 additions & 0 deletions src/ecdsa/test_jacobi.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,15 @@ def test_simple_multiplications(self):
pj = pj * i

self.assertEqual((pj.x(), pj.y()), (pw.x(), pw.y()))
self.assertEqual(pj, PointJacobi.from_weierstrass(pw))

def test_precompute(self):
precomp = PointJacobi.from_weierstrass(generator_256, True)
pj = PointJacobi.from_weierstrass(generator_256)


for i in range(255):
print(i)
a = precomp * (2 << i)
b = pj * (2 << i)
self.assertEqual(precomp * (2 << i), pj * (2 << i))

0 comments on commit 412cb40

Please sign in to comment.