Périmètre

Épreuve cryptographie du FCSC 2026 (ANSSI), challenge en ligne dans un cadre explicitement autorisé. Reproduction à fins pédagogiques.

Le challenge fournit un script de génération et une liste de points de courbe. Chaque caractère du flag est transformé en ord(c) * G sur la courbe française FRP256v1, et seules les coordonnées des points résultants sont publiées.

Objectif

Inverser l'encodage : retrouver, pour chaque point publié, le scalaire qui l'a produit, c'est-à-dire résoudre un log discret elliptique rendu trivial par la petite taille des scalaires.

1 · Le générateur

Le script encode le flag caractère par caractère :

Encodage côté challenge
for f in FLAG:
pt = ord(f) * G
print(hex(pt.x), hex(pt.y))

La sécurité d'ECC repose sur la difficulté du log discret (retrouver k à partir de k·G). Ici, la faille est l'espace des scalaires : ord(f) est un octet ASCII, donc k < 128. L'espace est minuscule.

2 · Cassage par énumération

On précalcule k·G pour tout k de 1 à 127, on indexe par coordonnée x, puis on retrouve chaque caractère par simple lookup.

Récupération du flag
lookup = {}
for k in range(1, 128):
lookup[(k * G).x()] = k

flag = "".join(chr(lookup[x]) for x in cipherpoints_x)
[+] flag = FCSC{…}

Les points dupliqués dans la sortie (mêmes x) correspondent simplement à des caractères répétés du flag, un indice supplémentaire que l'encodage est déterministe et sans masque.

Côté défense
  • Ne jamais encoder un message via m·G : la confidentialité repose alors sur la taille de m, pas sur l'ECDLP.
  • Un chiffrement à courbe elliptique correct (ECIES, par exemple) combine échange de clés et chiffrement symétrique avec aléa.
  • Tout schéma dont l'espace des secrets est énumérable en pratique est cassé, indépendamment de la courbe.