Order and Sub Groups Orders in ECC

12 min readApr 25, 2025

So, Satoshi Nakamoto selected the secp256k1 curve, and the rest is history. But, how is a curve designed? Well, in ECC, we can have an equation of y²=x³+ax+b (mod p). For a=2, b=3 and p=97, we get the possible points of [here]:

(1,54) (1,43) (3,91) (3,6) (4,47) (4,50) (10,76) (10,21) (11,17) (11,80) 
(12,94) (12,3) (17,87) (17,10) (20,34) (20,63) (21,73) (21,24) (22,92)
(22,5) (23,73) (23,24) (24,95) (24,2) (25,35) (25,62) (27,7) (27,90) (28,34)
(28,63) (29,54) (29,43) (32,7) (32,90) (37,22) (37,75) (38,7) (38,90) (39,91)
(39,6) (44,77) (44,20) (46,72) (46,25) (47,79) (47,18) (49,34) (49,63) (50,19) (50,78) (52,68) (52,29) (53,73) (53,24) (54,85) (54,12) (55,91) (55,6) (56,89) (56,8) (59,65) (59,32) (65,65) (65,32) (67,54) (67,43) (70,65) (70,32) (73,83) (73,14) (74,77) (74,20) (76,77) (76,20) (80,87) (80,10) (83,74) (83,23) (84,37) (84,60) (85,26) (85,71) (86,69) (86,28) (87,27) (87,70) (88,41) (88,56) (91,39) (91,58) (92,81) (92,16) (95,66) (95,31) (97,87) (97,10)

You can check with (1,54), as 54² (mod 97) is 6, and 1³+2 x 1 + 3 (mod 97) is also 6. For (3,91), we have 91² (mod 97) and which is 36, and 3³+ 2 x 3 + 3 (mod 97) is 36. There is no solution for x=2, and x=5. A basic plot is [here]:

For public key encryption, we must create a base point (G), and then add it n times (to get nG). The value of nG will be our public key, and the value of n will be our private key. So, let’s use Sage to determine the total number of points that are possible (the cardinality):

a = 2
b = 3
p = 97
E = EllipticCurve(GF(p), [0,0,0,a,b])
print(E)
print(E.abelian_group())
card = E.cardinality()
print("cardinality =",card)

This gives:

Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Finite Field of size 97
Additive abelian group isomorphic to Z/50 + Z/2 embedded in Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Finite Field of size 97
cardinality = 100

This means we have 100 points that form a group for the curve — and the value is known as the order of the group. Some curves contain all their points in the group, but others have subgroups and where there are a smaller number of points in each group.

Within this, there can be a number of subgroups which are cyclic. To find these, we determine the prime factors of the order, we determine:

n = h x r

and, where h is the number of subgroups (also known as the cofactor), and r is the number of points in each subgroup. The number of subgroups h holding the EC points is called cofactor. For secp256k1, we have a cofactor of 1, and which means that all of the points are in group and there are no subgroups. With Curve 25519, we have a cofactor of 8, and for Curve 448 it is 4.

100= 2x2x5x

Thus, we have cyclic subgroups are 2, 5, 25 and 50. Let’s try a base point of (3,91) [here]:

a= 2
b= 3
p= 97
n= 18
x-point= 3
P (3,91) Point is on curve
2P (80,87) Point is on curve
3P (80,10) Point is on curve
4P (3,6) Point is on curve
5P=0
6P (3,91) Point is on curve
7P (80,87) Point is on curve
8P (80,10) Point is on curve
9P (3,6) Point is on curve
10P=0
11P (3,91) Point is on curve
12P (80,87) Point is on curve
13P (80,10) Point is on curve
14P (3,6) Point is on curve
15P=0
16P (3,91) Point is on curve
17P (80,87) Point is on curve
18P (80,10) Point is on curve

We define the order of this point (N) as N=5. We define this as the subgroup generated by P has 5 points. We can check this with Sage:

b = 3
p = 97

E = EllipticCurve(GF(p), [0,0,0,a,b])
print(E)
print(E.abelian_group())

card = E.cardinality()
print("cardinality =",card)
factor(card)

G = E(3,91)
print("Generator order q=", G.order())

The result is:

Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Finite Field of size 97
Additive abelian group isomorphic to Z/50 + Z/2 embedded in Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Finite Field of size 97
cardinality = 100
Generator order q= 5

Now let’s try a base point of (1,54) [here]:

a= 2
b= 3
p= 97
n= 18
x-point= 1
P (1,54) Point is on curve
2P (92,81) Point is on curve
3P (0,87) Point is on curve
4P (21,24) Point is on curve
5P (53,24) Point is on curve
6P (65,65) Point is on curve
7P (85,71) Point is on curve
8P (46,72) Point is on curve
9P (23,73) Point is on curve
10P (3,6) Point is on curve
11P (87,70) Point is on curve
12P (52,29) Point is on curve
13P (47,18) Point is on curve
14P (74,20) Point is on curve
15P (88,41) Point is on curve
16P (32,90) Point is on curve
17P (17,87) Point is on curve
18P (95,31) Point is on curve

And we can see that (1,54) makes a much better base point, as it does not cycle for the range of n values that we have chosen. In fact, in this case, subgroup generated by P has 50 points.

We can again compute with Sage:

a = 2
b = 3
p = 97
E = EllipticCurve(GF(p), [0,0,0,a,b])
print(E)
print(E.abelian_group())
card = E.cardinality()
print("cardinality =",card)
factor(card)
G = E(1,54)
print("Generator order q=", G.order())

and which gives:

Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Finite Field of size 97
Additive abelian group isomorphic to Z/50 + Z/2 embedded in Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Finite Field of size 97
cardinality = 100
Generator order q= 50

We see here the order of the subgroup is 50. For a base point of (21,73), we get:

a= 2
b= 3
p= 97
n= 80
x-point= 21
P (21,73) Point is on curve
2P (46,25) Point is on curve
3P (52,68) Point is on curve
4P (32,7) Point is on curve
5P (80,87) Point is on curve
6P (84,37) Point is on curve
7P (24,95) Point is on curve
8P (95,31) Point is on curve
9P (74,20) Point is on curve
10P (3,6) Point is on curve
11P (65,65) Point is on curve
12P (92,81) Point is on curve
13P (92,16) Point is on curve
14P (65,32) Point is on curve
15P (3,91) Point is on curve
16P (74,77) Point is on curve
17P (95,66) Point is on curve
18P (24,2) Point is on curve
19P (84,60) Point is on curve
20P (80,10) Point is on curve
21P (32,90) Point is on curve
22P (52,29) Point is on curve
23P (46,72) Point is on curve
24P (21,24) Point is on curve
25P=0
26P (21,73) Point is on curve
27P (46,25) Point is on curve
28P (52,68) Point is on curve

and which has a subgroup order of 25. If we try:

a = 2
b = 3
p = 97


E = EllipticCurve(GF(p), [0,0,0,a,b])
print(E)
print(E.abelian_group())

card = E.cardinality()
print("cardinality =",card)
factor(card)

G = E(21,73)
print("Generator order q=", G.order())

We now get a subgroup order of 25:

Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Finite Field of size 97
Additive abelian group isomorphic to Z/50 + Z/2 embedded in Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Finite Field of size 97
cardinality = 100
Generator order q= 25

For a base point of (88,41), we get:

a= 2
b= 3
p= 97
n= 80
x-point= 88
P (88,41) Point is on curve
2P (80,87) Point is on curve
3P (53,73) Point is on curve
4P (3,6) Point is on curve
5P (30,0) Point is on curve
6P (3,91) Point is on curve
7P (53,24) Point is on curve
8P (80,10) Point is on curve
9P (88,56) Point is on curve
10P=0
11P (88,41) Point is on curve
12P (80,87) Point is on curve
13P (53,73) Point is on curve
14P (3,6) Point is on curve
15P (30,0) Point is on curve
16P (3,91) Point is on curve
17P (53,24) Point is on curve
18P (80,10) Point is on curve
19P (88,56) Point is on curve

And checking with Sage:

Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Finite Field of size 97
Additive abelian group isomorphic to Z/50 + Z/2 embedded in Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Finite Field of size 97
cardinality = 100
Generator order q= 10

We can then see, that picking the base point can have a significant effect on the size of the subgroup that we have. So now let’s create a Sage program to determine the group, and the size of each subgroup for a given base point:

a = 2
b = 3
p = 97

E = EllipticCurve(GF(p), [0,0,0,a,b])
print(E)
print(E.abelian_group())

card = E.cardinality()
print("cardinality =",card)
factor(card)

pts=E.points()
print("Points: ",pts)

for i in range(0,p):
try:
p=pts[i]
G=E(p[0],p[1])
print(f"({p[0]},{p[1]}). Generator order q=", G.order())
except:
continue

When we run we get:

Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Finite Field of size 97
Additive abelian group isomorphic to Z/50 + Z/2 embedded in Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Finite Field of size 97
cardinality = 100
Points: [(0 : 1 : 0), (0 : 10 : 1), (0 : 87 : 1), (1 : 43 : 1), (1 : 54 : 1), (3 : 6 : 1), (3 : 91 : 1), (4 : 47 : 1), (4 : 50 : 1), (10 : 21 : 1), (10 : 76 : 1), (11 : 17 : 1), (11 : 80 : 1), (12 : 3 : 1), (12 : 94 : 1), (17 : 10 : 1), (17 : 87 : 1), (20 : 34 : 1), (20 : 63 : 1), (21 : 24 : 1), (21 : 73 : 1), (22 : 5 : 1), (22 : 92 : 1), (23 : 24 : 1), (23 : 73 : 1), (24 : 2 : 1), (24 : 95 : 1), (25 : 35 : 1), (25 : 62 : 1), (27 : 7 : 1), (27 : 90 : 1), (28 : 34 : 1), (28 : 63 : 1), (29 : 43 : 1), (29 : 54 : 1), (30 : 0 : 1), (32 : 7 : 1), (32 : 90 : 1), (37 : 22 : 1), (37 : 75 : 1), (38 : 7 : 1), (38 : 90 : 1), (39 : 6 : 1), (39 : 91 : 1), (44 : 20 : 1), (44 : 77 : 1), (46 : 25 : 1), (46 : 72 : 1), (47 : 18 : 1), (47 : 79 : 1), (49 : 34 : 1), (49 : 63 : 1), (50 : 19 : 1), (50 : 78 : 1), (52 : 29 : 1), (52 : 68 : 1), (53 : 24 : 1), (53 : 73 : 1), (54 : 12 : 1), (54 : 85 : 1), (55 : 6 : 1), (55 : 91 : 1), (56 : 8 : 1), (56 : 89 : 1), (59 : 32 : 1), (59 : 65 : 1), (65 : 32 : 1), (65 : 65 : 1), (67 : 43 : 1), (67 : 54 : 1), (68 : 0 : 1), (70 : 32 : 1), (70 : 65 : 1), (73 : 14 : 1), (73 : 83 : 1), (74 : 20 : 1), (74 : 77 : 1), (76 : 20 : 1), (76 : 77 : 1), (80 : 10 : 1), (80 : 87 : 1), (83 : 23 : 1), (83 : 74 : 1), (84 : 37 : 1), (84 : 60 : 1), (85 : 26 : 1), (85 : 71 : 1), (86 : 28 : 1), (86 : 69 : 1), (87 : 27 : 1), (87 : 70 : 1), (88 : 41 : 1), (88 : 56 : 1), (91 : 39 : 1), (91 : 58 : 1), (92 : 16 : 1), (92 : 81 : 1), (95 : 31 : 1), (95 : 66 : 1), (96 : 0 : 1)]
(0,10). Generator order q= 50
(0,87). Generator order q= 50
(1,43). Generator order q= 50
(1,54). Generator order q= 50
(3,6). Generator order q= 5
(3,91). Generator order q= 5
(4,47). Generator order q= 50
(4,50). Generator order q= 50
(10,21). Generator order q= 50
(10,76). Generator order q= 50
(11,17). Generator order q= 50
(11,80). Generator order q= 50
(12,3). Generator order q= 50
(12,94). Generator order q= 50
(17,10). Generator order q= 50
(17,87). Generator order q= 50
(20,34). Generator order q= 50
(20,63). Generator order q= 50
(21,24). Generator order q= 25
(21,73). Generator order q= 25
(22,5). Generator order q= 50
(22,92). Generator order q= 50
(23,24). Generator order q= 50
(23,73). Generator order q= 50
(24,2). Generator order q= 25
(24,95). Generator order q= 25
(25,35). Generator order q= 50
(25,62). Generator order q= 50
(27,7). Generator order q= 50
(27,90). Generator order q= 50
(28,34). Generator order q= 50
(28,63). Generator order q= 50
(29,43). Generator order q= 10
(29,54). Generator order q= 10
(30,0). Generator order q= 2
(32,7). Generator order q= 25
(32,90). Generator order q= 25
(37,22). Generator order q= 50
(37,75). Generator order q= 50
(38,7). Generator order q= 50
(38,90). Generator order q= 50
(39,6). Generator order q= 50
(39,91). Generator order q= 50
(44,20). Generator order q= 10
(44,77). Generator order q= 10
(46,25). Generator order q= 25
(46,72). Generator order q= 25
(47,18). Generator order q= 50
(47,79). Generator order q= 50
(49,34). Generator order q= 50
(49,63). Generator order q= 50
(50,19). Generator order q= 50
(50,78). Generator order q= 50
(52,29). Generator order q= 25
(52,68). Generator order q= 25
(53,24). Generator order q= 10
(53,73). Generator order q= 10
(54,12). Generator order q= 50
(54,85). Generator order q= 50
(55,6). Generator order q= 50
(55,91). Generator order q= 50
(56,8). Generator order q= 50
(56,89). Generator order q= 50
(59,32). Generator order q= 10
(59,65). Generator order q= 10
(65,32). Generator order q= 25
(65,65). Generator order q= 25
(67,43). Generator order q= 50
(67,54). Generator order q= 50
(68,0). Generator order q= 2
(70,32). Generator order q= 50
(70,65). Generator order q= 50
(73,14). Generator order q= 10
(73,83). Generator order q= 10
(74,20). Generator order q= 25
(74,77). Generator order q= 25
(76,20). Generator order q= 50
(76,77). Generator order q= 50
(80,10). Generator order q= 5
(80,87). Generator order q= 5
(83,23). Generator order q= 50
(83,74). Generator order q= 50
(84,37). Generator order q= 25
(84,60). Generator order q= 25
(85,26). Generator order q= 50
(85,71). Generator order q= 50
(86,28). Generator order q= 50
(86,69). Generator order q= 50
(87,27). Generator order q= 50
(87,70). Generator order q= 50
(88,41). Generator order q= 10
(88,56). Generator order q= 10
(91,39). Generator order q= 50
(91,58). Generator order q= 50
(92,16). Generator order q= 25
(92,81). Generator order q= 25

We can see the order of the subgroups are 2, 5, 25 and 50. For secp256k1, we do not have any subgroups:

a = 0
b = 7
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F

str=sys.argv[1]
print(str)
a=int(str.split(";")[2])
b=int(str.split(";")[3])



E = EllipticCurve(GF(p), [0,0,0,a,b])
print(E)
print(E.abelian_group())

card = E.cardinality()
print("cardinality =",card)
factor(card)

G = E(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8)
print("Generator order q=", G.order())

This gives us the same order as the number of points:

Elliptic Curve defined by y^2 = x^3 + 7 over Finite Field of size 115792089237316195423570985008687907853269984665640564039457584007908834671663
Additive abelian group isomorphic to Z/115792089237316195423570985008687907852837564279074904382605163141518161494337 embedded in Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 7 over Finite Field of size 115792089237316195423570985008687907853269984665640564039457584007908834671663
cardinality = 115792089237316195423570985008687907852837564279074904382605163141518161494337
Generator order q= 115792089237316195423570985008687907852837564279074904382605163141518161494337

If we use Curve 25519:

a = 2
b = 3
p = 97


str=sys.argv[1]
print(str)

a=(str.split(";")[2])
b=(str.split(";")[3])
p=(str.split(";")[4])


E = EllipticCurve(GF(2^255-19),[0,486662,0,1,0])

print(E)
print(E.abelian_group())

card = E.cardinality()
print("cardinality =",card)


G=E(9, 43114425171068552920764898935933967039370386198203806730763910166200978582548)
print(f"Generator order q=", G.order())

In this case we use the base point at x=9, and get:

Elliptic Curve defined by y^2 = x^3 + 486662*x^2 + x over Finite Field of size 57896044618658097711785492504343953926634992332820282019728792003956564819949
Additive abelian group isomorphic to Z/57896044618658097711785492504343953926856930875039260848015607506283634007912 embedded in Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 486662*x^2 + x over Finite Field of size 57896044618658097711785492504343953926634992332820282019728792003956564819949
cardinality = 57896044618658097711785492504343953926856930875039260848015607506283634007912
Generator order q= 7237005577332262213973186563042994240857116359379907606001950938285454250989

We see that the number of points is 57896044618658097711785492504343953926856930875039260848015607506283634007912, but the actual order is 7237005577332262213973186563042994240857116359379907606001950938285454250989. When we divide, we get a co-factor of 8:

>>> 57896044618658097711785492504343953926856930875039260848015607506283634007912/7237005577332262213973186563042994240857116359379907606001950938285454250989
8.0

There are more Sage examples here:

--

--

Prof Bill Buchanan OBE FRSE
Prof Bill Buchanan OBE FRSE

Written by Prof Bill Buchanan OBE FRSE

Professor of Cryptography. Serial innovator. Believer in fairness, justice & freedom. Based in Edinburgh. Old World Breaker. New World Creator. Building trust.

Responses (1)