Try   HackMD

Elliptic Curves over Goldilocks

TL;DR: The two elliptic curves implementation can be found here.

We aim to construct an elliptic curve satisfying the following criteria:

  • Prime order.
  • Efficient group operations.
  • Deterministc and efficient hash-to-curve encoding.
  • Security level of 128 bits.

Extension Field Selection

To achieve the target security level, we adopt an approach similar to EcGFp5. Specifically, we define the extension field

Fp5=Fp[z]/(z53) over
p=264232+1

We select the polynomial

f(z)=z53 because:

  • It has the minimal Hamming weight among irreducible polynomials.
  • It uses nonzero coefficients as close to
    ±1
    as possible.
  • A polynomial of the form
    zkc
    minimizes the computational cost of the Frobenius operator.

The following Sage script verifies that the previous claims about

z53 are true:

# Define Fp
p = 2**64 - 2**32 + 1
F = GF(p)

# Define Fp[z]
R.<z> = PolynomialRing(F)

# Polynomials of the form z⁵±c for c ∈ [0,2] are not irreducible
for i in range(3):
    assert(R(z^5+i).is_irreducible() == R(z^5-i).is_irreducible() == False)
    
# The polynomial z^5-3 is irreducible
assert(R(z^5-3).is_irreducible())

Quadratic Residuosity

To check whether an element

aFp5 is a quadratic residue, we use Euler's criterion, raising
a
to the power
(p51)/2
.

This exponentiation can be optimized by noting that:

p51=(p4+p3+p2+p+1)(p1)
which follows from the cyclotomic polynomial decomposition.

To compute

a to the power over
p4+p3+p2+p+1
, we need to efficiently compute the first and second Frobenius operator. Moreover, notice that when this exponentation is done, we get an element
bFp5
such that
bp1=1
and this can only happen when
bFp
; so the second exponentiation is over
Fp
instead.

Exponentiation by

(p1)/2 is done by observing that:
p12=263231,

and using repeated squaring.

Frobenius Operator

As we have shown in the previous section, we must be able compute the first and second Frobenius operator over an element in

Fp5 efficiently. A naive implementation would take
O(logp)=O(64)
Fp5
-operations, but we will do it much better.

Write

a as
a0+a1z+a2z2+a3z3+a4z4
, with
aiFp
. Then, we can compute the frobenius operators as follows:
ap=a0+a1γ1,1z+a2γ1,2z2+a3γ1,3z3+a4γ1,4z4,ap2=a0+a1γ2,1z+a2γ2,2z2+a3γ2,3z3+a4γ2,4z4,

with
γ1,i=3ip15
and
γ2,i=3ip215=γ1,i2
. Hence, assuming the precomputation of
γ1,i,γ2,i
for
i[4]
, we can compute
ap
and
ap2
by four multiplications each.

Expand to see the proof

Proof:
On the one hand, using Fermat's little theorem we have that

ajpi=aj.

On the other hand, notice

zp=(z5)p15z=3p15z and therefore
(zi)p=γ1,izi
, where
γ1,i=3ip15
.

Using the previous observations, we have:

ap=(a0+a1z+a2z2+a3z3+a4z4)p=a0+a1zp+a2z2p+a3z3p+a4z4p=a0+a1γ1,1z+a2γ1,2z2+a3γ1,3z3+a4γ1,4z4,
which can be computed using a few multiplications.

Similarly, notice

zp2=3p215z=(γ1,1)p+1z=γ1,12z and therefore
(zi)p2=γ2,izi
, where
γ2,i=γ1,i2
.

TODO: Develop on

γ1,i=3ip15 generating a subgroup of order
5
.

Playing a little bit, we can refine exponentiation by

p4+p3+p2+p+1:
t0:=apap2,t1:=t0p2,t2:=t0t1,t3:=at2=a0b0+3(a1b4+a2b3+a3b2+a4b1),

where
b:=t2
is viewed as a
Fp5
-element.

Square Roots

To compute the square root of an element

bFp5 we will use in our favour the fact that to check its quadratic residuosity we have to raise it to
p4+p3+p2+p+1
.

After a bit of algebra, we get the following identity:

12+p4+p3+p2+p+12=(p+12)p3+(p+12)p+1,
so we can compute the squaring by:

  • Compute the square of
    b(p4+p3+p2+p+1)
    by using any squaring algorithms over the base field (recall that when an element is raised to
    p4+p3+p2+p+1
    it gets mapped to the base field).
  • Compute the exponentiation of
    b
    by the RHS of the identity.
  • Multiply both results.

EcGFp5

Definition

Found by Thomas Pornin, the EcGFp5 curve is defined by the equation:

E/Fp5:y2=x3+ax+b
with constants:
a=6148914689804861439+263z,b=15713893096167979237+6148914689804861265z

and order
2n
for the
319
-bit prime:

n = 0x7ffffffd800000077ffffff1000000167fffffe6cfb80639e8885c39d724a09ce80fd996948bffe1

Since

n is odd, the points belonging to the subgroup of order
n
are precisely the
n
-torsion
E[n]
of the curve.

Hashing to the Curve

We follow the RFC 9380: Hashing to Elliptic Curves to get a deterministic mapping.

hash_to_curve(msg)

Input: msg, an arbitrary-length byte string.
Output: P, a point in G.

Steps:
1. u = hash_to_field(msg, 2)
2. Q0 = map_to_curve_simple_swu(u[0])
3. Q1 = map_to_curve_simple_swu(u[1])
4. R = Q0 + Q1
5. P = R + R # clear_cofactor(R)
6. return P

––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

map_to_curve_simple_swu(u)

Input: u, an element in Fp5.
Output: P, a point in E.

Steps:
1. tv1 = inv0(Z^2 * u^4 + Z * u^2)
2.  x1 = (-B / A) * (1 + tv1)
3.  If tv1 == 0, set x1 = B / (Z * A)
4. gx1 = x1^3 + A * x1 + B
5.  x2 = Z * u^2 * x1
6. gx2 = x2^3 + A * x2 + B
7.  If is_square(gx1), set x = x1 and y = sqrt(gx1)
8.  Else set x = x2 and y = sqrt(gx2)
9.  If sgn0(u) != sgn0(y), set y = -y
10. return (x, y)

EcMasFp5

Definition

We choose the short Weierstrass equation:

y2=x3+Ax+B
because assuming that
AFp
and that the cost of addition, subtraction, multiplication and division over the field is the same (something true in SNARK settings), point addition costs
10
field operations and point doubling costs
12
field operations.

Setting

AFp also restricts
B
to be from the extension field, rather from the prime field; otherwise the curve could not be of primer order.

Since

B has no impact in group operations, we perform a linear search:

# Define Fp⁵
K.<z> = GF(p^5, modulus=z^5-3)

# Perform a linear search
def find_ec_over_gfp5(initial_a = 0, initial_c = 1, attempts = 50, pol_degree = K.degree(), verbose = True):
    A = initial_a
    c = initial_c
    if verbose:
        print("· Attempting with A =", A)
    while True:
        for i in range(1, pol_degree):
            B = c * z**i
            E = EllipticCurve(K, (A, B))
            if verbose:
                print("    -",E)
            if is_prime(E.order(algorithm="pari")):
                print(f"Elliptic curve found with A = {E.a4()} and B = {E.a6()}")
                return E
        else:
            c += 1
            # If no prime order was found, reset `c` and update `A`
            if c == attempts:
                c = initial_c
                A += 1
                if verbose:
                    print("· Attempting with A =", A)
            continue

        break
        
E = find_ec_over_gfp5()

The first elliptic curve found was:

E/Fp5:y2=x3+3x+8z4,
with a
320
-bit prime order:

n = 0xfffffffb0000000effffffe20000002cffffffcc2c13f5f892042da0dfcde3fc8f4b2caf22360ee3

The name for this curve was chosen to be EcMasFp5 (Elliptic Curve for Maximum Aggregation Speed over

Fp5).

Security of the Curve

Thanks to Robin Salen for help and discussion.

We follow the criteria in Safe Curves.

Summary

Curve prime order `n`: 0xfffffffb0000000effffffe20000002cffffffcc2c13f5f892042da0dfcde3fc8f4b2caf22360ee3 (320 bits)
Curve cofactor: 1
Curve embedding degree: n-1 (320 bits)
Curve CM discriminant `D`: -0x350910d76c19ff80472df1f236bda8f251edc59a20563b4f1bcb88ad47f9892d334755425f4369e43 (323 bits)
Curve security (Pollard-Rho): 159.83 bits

Twist prime order `nt`: 0x128ad28934008b50864257bbff0983af9688b4f04ff3f024f86f (205 bits)
Twist cofactor: 0xdce68ed7aef21329a0ac97d33d76f (116 bits)
Twist embedding degree: (nt-1)/15 (201 bits)
Twist CM discriminant: D (323 bits)
Twist security (Pollard-Rho): 101.93 bits

More details are given below.

Field

Since the extension field is the same as the one in EcGFp5, we inherit by default its security. In particular, this field selection approximately achieves a

142-bit security level, well beyond the target one.

Embedding Degree

We use the following code to find the embedding degree

e:

def embedding_degree(q,n):  
    F = GF(n)  
    return F(q).multiplicative_order()

Finding that

e=n1, as large as it can possibly be, avoiding MOV-type attacks.

CM Discriminant

The CM Discriminant

D=t24q was found to be a
323
-bit integer:

D = -0x350910d76c19ff80472df1f236bda8f251edc59a20563b4f1bcb88ad47f9892d334755425f4369e43

Twist

The number

q+1+t factorizes as:

0x128ad28934008b50864257bbff0983af9688b4f04ff3f024f86f*0xdce68ed7aef21329a0ac97d33d76f

Hashing to the Curve

It is the same as the one for EcFp5 with the exception that this one does not need to clean the cofactor.

Resources