Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

The given elliptic curve is one of the shape $y^2 + xy = x^3 +x^2 +b$ where $b$ is a multiplicative generator of the field GF( 2**p ) for the prime p = 163.

A part of the question was strictly "how to make the code run without error". Here is a piece of code that does the job in a similar more pacific situation.

First, we will construct such a situation over a smaller field. For this, we search for a smaller $p$, such that a corresponding polynomial $X^p + X^7 + X^6 + X^3 + 1$ is irreducible in $\mathbb{F}_2[X]$ . The code is:

F = GF(2)
R.<X> = PolynomialRing( F ) 
k = 7; n = 10                        # later: x = a^k, y = a^n
powers   = [ 2*k, 3*k, 2*n, k+n ]    # later: xx, xxx, yy, xy
minpower = min( powers )

for p in primes( 10000 ):
    if p < 11:    continue
    P = X^p + sum( [ X^(power - minpower) for power in powers ] )
    if P.is_irreducible() :
        print "p = %4s . The polynomial %s is irreducible over GF(2)[X]." % ( p, P )

And we get:

p =   13 . The polynomial X^13 + X^7 + X^6 + X^3 + 1 is irreducible over GF(2)[X].
p =   37 . The polynomial X^37 + X^7 + X^6 + X^3 + 1 is irreducible over GF(2)[X].
p =  163 . The polynomial X^163 + X^7 + X^6 + X^3 + 1 is irreducible over GF(2)[X].
p =  787 . The polynomial X^787 + X^7 + X^6 + X^3 + 1 is irreducible over GF(2)[X].
p = 3037 . The polynomial X^3037 + X^7 + X^6 + X^3 + 1 is irreducible over GF(2)[X].

So instead of 163 we take the 37 and the following code

R.<x> = PolynomialRing( GF(2) )
p     = 37    # one of 13, 37, 163, 787, 3037, ...
K.<a> = GF( 2**p, name='a', modulus=x^p + x^7 + x^6 + x^3 + 1 )
E = EllipticCurve( K, [1, 1, 0, 0, a^( p + minpower ) ] )

P = E.point( (a^7, a^10) )    # ( a^k, a^n ) is a point on the curve

Porder = P.order()
Eorder = E.order()

print "E has E( GF(2^%s) ) with order:   %s = %s" % ( p, Eorder.factor(), Eorder )
print "Let P be (a^7, a^10). P has order %s = %s" % ( Porder.factor(), Porder )

delivers:

E has E( GF(2^37) ) with order:   2 * 3 * 29 * 257 * 3073451 = 137438581818
Let P be (a^7, a^10). P has order 2 * 3 * 29 * 257 * 3073451 = 137438581818

Of course, p = 163 is too much, if we do not implement code especially for the situation. (And even if we manage to do it, next day we have the question related to p = 787 instead.)

The given elliptic curve is one of the shape $y^2 + xy = x^3 +x^2 +b$ where $b$ is a multiplicative generator of the field GF( 2**p ) for the prime p = 163.

A part of the question was strictly "how to make the code run without error". Here is a piece of code that does the job in a similar more pacific situation.

First, we will construct such a situation over a smaller field. For this, we search for a smaller $p$, such that a corresponding polynomial $X^p + X^7 + X^6 + X^3 + 1$ is irreducible in $\mathbb{F}_2[X]$ . The code is:

F = GF(2)
R.<X> = PolynomialRing( F ) 
k = 7; n = 10                        # later: x = a^k, y = a^n
powers   = [ 2*k, 3*k, 2*n, k+n ]    # later: xx, xxx, yy, xy
minpower = min( powers )

for p in primes( 10000 ):
    if p < 11:    continue
    P = X^p + sum( [ X^(power - minpower) for power in powers ] )
    if P.is_irreducible() :
        print "p = %4s . The polynomial %s is irreducible over GF(2)[X]." % ( p, P )

And we get:

p =   13 . The polynomial X^13 + X^7 + X^6 + X^3 + 1 is irreducible over GF(2)[X].
p =   37 . The polynomial X^37 + X^7 + X^6 + X^3 + 1 is irreducible over GF(2)[X].
p =  163 . The polynomial X^163 + X^7 + X^6 + X^3 + 1 is irreducible over GF(2)[X].
p =  787 . The polynomial X^787 + X^7 + X^6 + X^3 + 1 is irreducible over GF(2)[X].
p = 3037 . The polynomial X^3037 + X^7 + X^6 + X^3 + 1 is irreducible over GF(2)[X].

So instead of 163 we take the 37 and the following code

R.<x> = PolynomialRing( GF(2) )
p     = 37    # one of 13, 37, 163, 787, 3037, ...
K.<a> = GF( 2**p, name='a', modulus=x^p + x^7 + x^6 + x^3 + 1 )
E = EllipticCurve( K, [1, 1, 0, 0, a^( p + minpower ) ] )

P = E.point( (a^7, a^10) )    # ( a^k, a^n ) is a point on the curve

Porder = P.order()
Eorder = E.order()

print "E has E( GF(2^%s) ) with order:   %s = %s" % ( p, Eorder.factor(), Eorder )
print "Let P be (a^7, a^10). P has order %s = %s" % ( Porder.factor(), Porder )

delivers:

E has E( GF(2^37) ) with order:   2 * 3 * 29 * 257 * 3073451 = 137438581818
Let P be (a^7, a^10). P has order 2 * 3 * 29 * 257 * 3073451 = 137438581818

Of course, p = 163 is too much, if we do not implement code especially for the situation. (And even if we manage to do it, next day we have the question related to p = 787 instead.)

# ========================================

Postlude, later edit:

The given curve $$ E\ :\ y^2 +xy = x^3 +x^2 + b $$ has the order twice the prime $$ 5846006549323611672814742442876390689256843201587\ .$$ In my hands, sage can only verify this order:

q = 2^163

R.<X> = PolynomialRing( GF( 2 ) )
F.<a> = GF( q, modulus = X^163 + X^7 + X^6 + X^3 + 1 )

b1 = 0x000000020A601907B8C953CA1481EB10512F78744A3205FD
b  = F( b1.digits(2) )

PRIME = 5846006549323611672814742442876390689256843201587
ORDER = 2*PRIME

print "hex( q+1 - 2sqrt(q) ) is %s" % hex( ceil( q+1 - 2*sqrt(q) ) ) 
print "hex( ORDER          ) is %s" % hex( ORDER                   ) 
print "hex( q+1 + 2sqrt(q) ) is %s" % hex( ceil( q+1 + 2*sqrt(q) ) ) 

print "\nIs PRIME = %s indeed a prime? %s" % ( PRIME, PRIME.is_prime() )
print "ORDER = 2*PRIME" 

E = EllipticCurve( [1,1,0,0,b] )
P = E.random_point()
print "\nE is the elliptic cuve for the data [1,1,0,0,b]"
print "P is a random point on E( GF(q) )"
print "ORDER * P = %s" % ( ORDER * P )

This gives:

hex( q+1 - 2sqrt(q) ) is 7fffffffffffffffffffa57d86660310cdbdd3415
hex( ORDER          ) is 80000000000000000000525fcefce182548469866
hex( q+1 + 2sqrt(q) ) is 800000000000000000005a827999fcef32422cbee

Is PRIME = 5846006549323611672814742442876390689256843201587 indeed a prime? True
ORDER = 2*PRIME

E is the elliptic cuve for the data [1,1,0,0,b]
P is a random point on E( GF(q) )
ORDER * P = (0 : 1 : 0)

As said, my sage knowledge could not help to find the order by using only sage. After some time, i tried to attack the order of the "weaker" curve $E_0$, which is a twist of $E$: $$ E_0\ :\ y^2 +xy = x^3 + b \ .$$

It is simple to check $|E(\mathbb F_q)| + |E_0(\mathbb F_q)|=2(q+1)$.

So getting the order for $E$ is equivalent to getting it for $E_0$. The situation for $E_0$ is as follows

E0 = EllipticCurve( F, [1,0,0,0,b] )
P0 = E0.random_point()

ORDER0 = 2*(q+1) - ORDER

print "\nE0 is the elliptic cuve for the data [1,1,0,0,b]"
print "E0 has order %s" % ( ORDER0.factor() )
print "Let us check this. P0 is a random point on E0( GF(q) )"
print "ORDER0 * P0 = %s" % ( ORDER0 * P0 )

This gives:

E0 is the elliptic cuve for the data [1,1,0,0,b]
E0 has order 2^2 * 31 * 907 * 18908293 * 192478327 * 28564469476693963307545101353
Let us check this. P0 is a random point on E0( GF(q) )
ORDER0 * P0 = (0 : 1 : 0)

It is simple to get some "canonical" (i.e. non-random) points on this curve, for instance $(c,c^2)$ where $c$ is a fourth root of $b$. Its order is four.

sage: c  = b^( q/4 );
sage: P1 = E0.point( (c,c^2) )
sage: P1.order()
4

Or for $c$ a cubic root of $b$ the point $(c,c)$, which generates.

c = b^( (2*(q-1)+1)/3 )
P0 = E0.point( (c,c) )

# This is a point of full order, since:

for div in ORDER0.prime_factors():
    print "Is (ORDER0 / %s ) * P0 zero? %s" % ( div, ( ZZ( ORDER0 / div ) * P0 ) .is_zero() )

Results:

Is (ORDER0 / 2 ) * P0 zero? False
Is (ORDER0 / 31 ) * P0 zero? False
Is (ORDER0 / 907 ) * P0 zero? False
Is (ORDER0 / 18908293 ) * P0 zero? False
Is (ORDER0 / 192478327 ) * P0 zero? False
Is (ORDER0 / 28564469476693963307545101353 ) * P0 zero? False

An other point on $E_0$ is $(c^2,c^3)$ where $c$ is a fifth order root of $b$ in $F$. Its order is not maximal. (It drops by the factor $31$.)

c = b^( (2*(q-1)+1)/5 )
P5 = E0.point( (c^2,c^3) )

# This is a point of full order, since:

for div in ORDER0.prime_factors():
    print "Is (ORDER0 / %s ) * P5 zero? %s" % ( div, ( ZZ( ORDER0 / div ) * P5 ) .is_zero() )

Results:

Is (ORDER0 / 2 ) * P5 zero? False
Is (ORDER0 / 31 ) * P5 zero? True
Is (ORDER0 / 907 ) * P5 zero? False
Is (ORDER0 / 18908293 ) * P5 zero? False
Is (ORDER0 / 192478327 ) * P5 zero? False
Is (ORDER0 / 28564469476693963307545101353 ) * P5 zero? False

So the "weaker" (twisted) curve is not weak enough for me.