I’ve written about elliptic curve and alluded to the fact that there’s a special kind of addition for points on the curve. But I haven’t gone into details because it’s more complicated than I wanted to get into.

However, there’s a special case where the details are not complicated, the so called Edwards curves. I’ll look briefly at Edwards curves in general, then focus on Curve1174, a particular Edwards curve used in cryptography.

The example here could be used in an introductory group theory course with no reference to elliptic curves. Just think of it as a funny way to add pairs of integers.

## Addition on Edwards curves

For a particular class of elliptic curve, Edwards curves, the addition formula is simpler than usual. As mentioned a few days ago, an Edwards curve has the form

*x*² + *y*² = 1 + *d* *x*² *y*²

where *d* is not 0 or 1 in the underlying finite field. Then addition on the curve is given by

When *d* is a square, there are some exceptions. When *d* is not a square, as will be the case in our application, the denominators are never zero, and so the formula above is all there is to the addition rule.

Note that the division in the formula above is division in the underlying finite field, i.e. multiplication by the multiplicative inverse.

## Curve1174

We’re interested in Curve1174, a particular elliptic curve used in cryptography. The underlying field is GF(*p*), the integers modulo the prime *p* = 2^{251} – 9. Also, *d* = -1174, from whence the curve takes its name.

The plot above shows what Curve1174 looks like over the real numbers, though we’re interested in the curve over the integers mod *p*. (By the way, if *d* > 0 you get a curve that looks like a squircle.)

We consider the pairs of integers (*x, **y*) that lie on the curve, i.e. those that satisfy

*x*² + *y*² = 1 + *d* *x*² *y*² mod *p*.

You can show that the sum of two points on the curve is another point on the curve, if you define addition with the formula above. The identity element for addition is the pair (0, 1). The additive inverse of a point (*x*, *y*) is the point (-*x*, *y*). So we have a group. Addition is commutative, and so in fact we have an Abelian group.

## Python code

We can implement addition on Curve1174 in a few lines of Python.

from sympy import mod_inverse def divide(a, b, p): "Compute a/b in GF(p)" return (a*mod_inverse(b, p))%p def group_add(x1, y1, x2, y2, p, d): x3 = divide(x1*y2 + x2*y1, 1 + d*x1*x2*y1*y2, p) y3 = divide(y1*y2 - x1*x2, 1 - d*x1*x2*y1*y2, p) return (x3, y3)

The only thing we needed SymPy for was the `mod_inverse`

function. It wouldn’t take much work to write your own `mod_inverse`

function from scratch using the method outlined here using a variation on the Euclidean algorithm.

It’s clear that (1, 0) is a point on the curve, and so we can add it to itself with the code

p = 2**251 - 9 d = -1174 print(group_add(1, 0, 1, 0, p, d))

and find that it equals

(0, 3618502788666131106986593281521497120414687020801267626233049500247285301238),

which may come as a bit of a surprise. Arithmetic here is not intuitive; it scrambles up points well, which hints at why the curve is useful in cryptography.

Let’s find another point on the curve. Let’s set *x* = 2019 and see what *y* is. When we come up with the equation *y* must satisfy, the Jacobi symbol shows there is no solution.

When *x* = 2025 there is a solution, and we can compute it using `sqrt_mod`

from `sympy.ntheory`

.

x = 2025 k = divide(1 - x*x, 1 - d*x*x, p) y = sqrt_mod(k, p)

This says the point

(2025, 588747530266665079407582947937120321357732884331117971504880828350684014295)

is on Curve1174. And since *x* and *y* only appear as squares in the equation defining the curve, once we find an (*x*, *y*) pair on the curve, the points (±*x*, ±*y*) are also on the curve.

## Number of points on Curve1174

In general it can be hard to compute how many point lie on an elliptic curve, but in the case of Curve 1174 the number of points is known. Bernstein et al computed that the number of points on Curve1174 is *p* + 1 – *t* where *t* is a big number, but much smaller than *p*, on the order of the square root of *p*. Specifically,

*t* = 45330879683285730139092453152713398836.

Why not just absorb the 1 into *t*? This was done to match the notation in Hasse’s theorem. See the footnote here.