Salade de fruits - FCSC2024

󰃭 2025-08-12

Problem statement

Curve isomorphism

This is a classic problem of cubic equation, it turns out that every cubic equation (that is not degenerate) is isomorphic to an elliptic curve, Sagemath has a conveniant function for that, so let’s quickly look at the isomorphism (and its inverse function) :

P = QQ["p, s, b"]
p, s, b = P.gens()

eq = p ** 3 - 94 * b ** 3 + s ** 3

f = EllipticCurve_from_cubic(eq)
print(f)
fi = f.inverse()
print(fi)

we get :

Scheme morphism:
  From: Projective Plane Curve over Rational Field defined by p^3 + s^3 - 94*b^3
  To:   Elliptic Curve defined by y^2 - 846*y = x^3 - 238572 over Rational Field
  Defn: Defined on coordinates by sending (p : s : b) to
        (-b : -3*p : -1/282*p - 1/282*s)
Scheme morphism:
  From: Elliptic Curve defined by y^2 - 846*y = x^3 - 238572 over Rational Field
  To:   Projective Plane Curve over Rational Field defined by p^3 + s^3 - 94*b^3
  Defn: Defined on coordinates by sending (x : y : z) to
        (-1/3*y : 1/3*y - 282*z : -x)

Solving the whole challenge

We want a solution with :

  • $ 1 \le p$
  • $ 1 \le s \le p$
  • $ 1 \le b \le p$

We know its easy to find and iterate over points on an elliptic curve which by isomorphism will correspond to solutions of the equation, but we have to deal with the constraints…

Well, I just iterated from a generator of the curve until I found a solution with the constrains, not sure if it would work in the general case but it’s always good to try your first idea and see what comes next, I was lucky and that was an immediate flag.

And because we’re working in the projective plane normalized in $Z$ for elliptic curves, we have to bring back the solution from $\mathbb Q$ to $\mathbb Z$ which is done by multiplying $p_s$ and $s_s$ by their corresponding lcm.

from sage.all import *
from itertools import count
from hashlib import sha256

P = QQ["p, s, b"]
p, s, b = P.gens()
eq = p ** 3 - 94 * b ** 3 + s ** 3

f = EllipticCurve_from_cubic(eq)
fi = f.inverse()

E = f.codomain()
G = E.gen(0)

for i in count(start = 1):
    ps, ss, bs = fi(i*G)
    if (ps > 0 and ss > 0 and bs > 0):
        y = lcm(ps.denom(), ss.denom())
        ps *= y
        ss *= y
        bs *= y

        h = sha256(str(bs).encode()).hexdigest()

        print(f"FCSC{{{h}}}")
        exit()

flag : FCSC{2c69e5056f2a80af36c0880a2395472e51b448730a1c5c06b2b0d8e0a3b466b6}