Coding Schoof's 1985 Elliptic Curve Point Counting Algorithm in Python
World's First Polynomial Time Algorithm To Count Points On Elliptic Curves

Here’s 20% off scheduling meetings with Cal.com
Here’s 20% off Simplified’s Marketing Agent
1.0 Paper Introduction
Elliptic Curves over Finite Fields and the Computation of Square Roots mod p (Schoof, 1985)1 introduced the world’s first polynomial time algorithm to compute the number of points, denoted by #E(Fq), on an elliptic curve (Sutherland, 2025)2.
(Schoof, 1985) is canonical because it reduced the complexity of counting points on elliptic curves from exponential to polynomial-time.
The algorithm is simple: compute the trace of frobenius t modulo many small primes and use the Chinese Remainder Theorem to uniquely determine t (Sutherland, 2025):
Schoof realized that a curve’s division polynomials identified torsion points modulo small primes. Then he related this to to the frobenius endomorphism. That’s how we got a polynomial-time point counting algo!

This is part of our series on Practical Elliptic Curve Theory For Programmers:
Part 1: Hacking Dormant Bitcoin Wallets in C.
Part 2: Smart Attack on Anomalous Curves.
Part 3: Finding Anomalous Curves.
Part 4: Division Polynomials of Elliptic Curves in Python.
Part 5 (we are here): Applying Division Polynomials to Point Counting.
Part 6: Fast Point Multiplication on Curves With Efficient Endomorphisms.
2.0 Coding Schoof’s Algorithm
Code is available on GitHub and Google Colab*
*My work keeps appearing verbatim in Codex. This is theoretical math wildly outside the distribution so I know they’re training on my private repos.
This section closely follows (Dinges, 2010)3. We assume you saw the Trace of Frobenius in Part 2 and the Division Polynomials of Elliptic Curves in Part 4.
2.1 Symbolic Division Polynomials
Schoof’s algorithm works on algebraic points.
We first convert the division polynomial code from Part 4 into symbolic form using sympy:
We can verify our implementation using this example (Dinges, 2010):
In Python, the example resembles:
2.2 Frobenius Endomorphism
The Frobenius endomorphism is a mathematical shortcut for finding equivalent points on an elliptic curve by exponentiation. We’ll encounter this formal description in part 6:

In part 2 we defined the trace of frobenius as the difference between predicted count of points and actual number of points on an elliptic curve in a finite field.
Hasse’s theorem relates the trace of frobenius to the number of points on an elliptic curve as given in (Lynn, 2025)4:
Hasse’s theorem bounds the possible number of points and Python code resembles:
However, our goal is to bound the trace of frobenius and this resembles:
Schoof’s algorithm demands us loop over small values of t in the characteristic equation until we find the one that satisfies:
2.3 Tying Everything Together
(Visser, 2020)5 summarizes the exact computation performed for Schoof’s algorithm:
Note: a is used in place of t to represent the trace of frobenius
Where the sub-algorithm in Step 2 is:
Note that field operations occur in the quotient ring highlighted below (Costello, )6:
2.4 Final Python Code
Sympy can’t construct multivariate quotient rings (Sympy issue #20608, 2020)7.
This we overcome by finding a factor of the division polynomial (they tend to be reducible) then ‘lifting’ our curve to the field extension where the corresponding x-coordinate exists.
Let’s write some quick field extension arithmetic functions:
Next, we write scalar multiplication and the frobenius endomorphism that’s aware of the field extension:
Now, we find the trace of frobenius modulo 2:
Next, we compute the trace of frobenius modulo small primes.
Let’s try our code on this Sage example:
In the example above, we expect to see -6 modulo different small primes.
In Python, this resembles:
It works!
3.0 Recommended Reading
If you’ve never seen field extensions then you’d benefit from:
References
Schoof, R. (1985). Elliptic Curves over Finite Fields and the Computation of Square Roots mod p. Mathematics of Computation 44, no. 170 (1985): 483–94. PDF.



















