Grover 1/2 (Quantique) - 404CTF2025

Principe:
Comprendre l'ordre des portes et des qbits pour préparer trois fonctions quantiques

Infos (cf menu latéral):
🚩 Flaggué! +342 points gagnés — 💾 Téléchargez les fichiers du challenge
404CTF{z0r_oU_XoR?_j3_N3_m_En_sOr_pLU5}

Le challenge

L'énoncé du challenge

Un notebook Jupyter

Le challenge nous donne un pynb (notebook Jupyter)

Le nom du dossier est normal: je ne suis déjà pas fan de Python, mais Jupyter peut souvent être encore pire à utiliser 😄

On va créer un environnement virtuel pour installer tout ça, histoire de ne pas pourrir la machine

On appréciera au passage la quantité de trucs téléchargés pour faire tourner ce Jupyter Notebook 😉

Impossible d'installer, via le gestionnaire poetry, le notebook… ça commence bien!
Le notebook seul ne suffit pas: les informations de poetry sont dans le pyproject, il faut donc bien avoir tous les fichiers dans le même dossier pour que cela fonctionne
Là, ça passe

On appréciera au passage la nouvelle quantité de trucs téléchargés encore une fois!

On peut lancer le notebook
💡 En pratique, on aurait pu faire sans le notebook, puisque le challenge n'est jamais qu'un code python classique

Apprenons l'algo quantique

Il ne reste plus qu'à dérouler le notebook, bloc par bloc (les blocs de code sont exécutables)

Quand on lance un notebook, notre machine va démarrer un serveur local et y accéder via le navigateur. Le reste du challenge se fera donc dans Firefox.

Apprenons d'abord Jupyter!

Sauf que le premier bloc n'affiche rien!
En allant voir le script Python associé, on remarque que les dessins sont fait en plusieurs mode. On va se contenter d'un print à la place
On kill et relance le notebook

On peut aussi faire un 'Reload Kernel' depuis le notebook lui-même

Et là, on a bien un output! Ce sera important pour débugger la suite…

Fonction f1

Pour créer la porte, qui à qbit0 associe 'not(qbit0)', on pourrait être tenté de cloner le qbit0 puis de l'inverser. Or, si c'est possible en informatique classique, ce n'est pas faisable en informatique quantique!

Pas de clonage de qbits! Il faut une autre idée…
Un premier essai consiste à mettre une porte qbit1 = CXNOT(qbit0) donc cx(0,1)

L'affichage peut être trompeur: il indique que pour l'entrée _0 (qbit0 = 0), on a la sortie '0' avec une probabilité de 1.0. Dis autrement, le qbit0 (entrée) de valeur 0 va donner un qbit1 (sortie) de valeur 0 100% du temps (et même principe pour un qbit0 de 1).
Pour rappel, le qbit1 (sortie, d'où le _) est à gauche (inversion de l'ordre).

Il ne reste donc plus qu'à inverser (XNOT) le qbit1 et voilà!

On a bien 0 -> '1' dans 100% des cas ; 1 -> '0' dans 100% des cas

Simplification?

Je trouvais le CXNOT-XNOT un peu étrange, et j'ai cherché à le simplifier
Mais il ne semble pas y avoir plus simple
D'autres tentatives de simplification automatique nécessitaient une lib…
Celle-ci ne s'installant pas (à cause du fichier projet qui ne lui plait pas), j'ai lâché l'affaire

Fonction f2

Pour f2, on constate que le premier qbit n'a aucune influence sur la sortie demandée: on reprend la même fonction que f1
Chose amusante, anarchiquement, des bouts du Notebook ont planté et ont affiché du Latex source… tant pis!
Mais échec quand on essaie de la valider (en fin de challenge)!

En fait, j'ai simplement oublié que l'ordre des bits est inversé… Le qbit0 et le qbit1 sont donc inversés dans la bonne réponse (cf archive).

Fonction f3

La fonction f3 nous est déjà donnée, on va donc juste tester ce que create_zf donne comme sortie: raté, je suis à l'envers, les portes devraient être sur qbit0 et non qbit1!
L'ordre des paramètres était donc incorrect: on fixe
On affiche le vecteur…
… qu'on obtient sous forme de texte
On le compare à l'énoncé
Et on voit que le signe est bon

On souhaite maintenant appliquer H2 x Zor x H2 à Zf3, soit H2(Zor(H2(Zf3))) Or, le circuit se lit de gauche à droite (quand on le print). Il faut donc d'abord que les qbits passent dans Zf3 (la fonction 'la plus imbriquée') puis dans H2, puis Zor

On compose les fonctions, en affichant le vecteur d'état quantique associé pour confirmer qu'on obtient un seul résultat (le 'flag').
Et en soumettant nos trois fonctions, on obtient le flag de Grover 1!

Flag: 404CTF{z0r_oU_XoR?_j3_N3_m_En_sOr_pLU5}