1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-04 13:02:47 -05:00

numbertheory.py: generalise SqrtModP to do other roots.

I'm about to want to solve quartics mod a prime, which means I'll need
to be able to take cube roots mod p as well as square roots.

This commit introduces a more general class which can take rth roots
for any prime r, and moreover, it can do it in a general cyclic group.
(You have to tell it the group's order and give it some primitives for
doing arithmetic, plus a way of iterating over the group elements that
it can use to look for a non-rth-power and roots of unity.)

That system makes it nicely easy to test, because you can give it a
cyclic group represented as the integers under _addition_, and then
you obviously know what all the right answers are. So I've also added
a unit test system checking that.
This commit is contained in:
Simon Tatham
2020-02-28 20:14:28 +00:00
parent 7be2e16023
commit 072d3c665a
2 changed files with 148 additions and 50 deletions

View File

@ -111,9 +111,9 @@ class WeierstrassCurve(CurveBase):
def cpoint(self, x, yparity=0):
if not hasattr(self, 'sqrtmodp'):
self.sqrtmodp = SqrtModP(self.p)
self.sqrtmodp = RootModP(2, self.p)
rhs = x**3 + self.a.n * x + self.b.n
y = self.sqrtmodp.sqrt(rhs)
y = self.sqrtmodp.root(rhs)
if (y - yparity) % 2:
y = -y
return self.point(x, y)
@ -157,9 +157,9 @@ class MontgomeryCurve(CurveBase):
def cpoint(self, x, yparity=0):
if not hasattr(self, 'sqrtmodp'):
self.sqrtmodp = SqrtModP(self.p)
self.sqrtmodp = RootModP(2, self.p)
rhs = (x**3 + self.a.n * x**2 + x) / self.b
y = self.sqrtmodp.sqrt(int(rhs))
y = self.sqrtmodp.root(int(rhs))
if (y - yparity) % 2:
y = -y
return self.point(x, y)
@ -198,11 +198,11 @@ class TwistedEdwardsCurve(CurveBase):
def cpoint(self, y, xparity=0):
if not hasattr(self, 'sqrtmodp'):
self.sqrtmodp = SqrtModP(self.p)
self.sqrtmodp = RootModP(self.p)
y = ModP(self.p, y)
y2 = y**2
radicand = (y2 - 1) / (self.d * y2 - self.a)
x = self.sqrtmodp.sqrt(radicand.n)
x = self.sqrtmodp.root(radicand.n)
if (x - xparity) % 2:
x = -x
return self.point(x, y)