
Ce dépôt contient le code et les détails de soumission pour le défi du prix QDay par https://www.projecteleven.com/
Solveur quantique pour le problème du logarithme discret sur courbe elliptique (ECDLP), construit pour le Q-Day Prize Challenge par Project Eleven. L'objectif : récupérer des clés privées ECC sur du matériel quantique réel en utilisant l'algorithme de Shor.
Toutes les courbes du défi utilisent y^2 = x^3 + 7 sur F_p (a = 0, b = 7), correspondant à la famille secp256k1. Le solveur implémente la variante à deux registres de l'algorithme de Shor pour l'ECDLP :
La clé privée d est récupérée en collectant plusieurs échantillons (j, k) qui satisfont la même relation linéaire modulo l'ordre du groupe n. Le solveur prend en charge six stratégies d'oracle pour les additions de points contrôlées, sélectionnées automatiquement en fonction de la taille de la courbe ou manuellement via --oracle.
Utilisée pour les courbes avec un ordre de groupe jusqu'à ~6 bits. Implémentée dans projecteleven.py.
Chaque addition de point contrôlée "add S" est représentée comme une matrice de permutation 2^(n+1) x 2^(n+1) appliquée via qc.unitary(). La matrice encode l'action complète du groupe : le bloc supérieur gauche est l'identité (contrôle=0), le bloc inférieur droit permute les états de base selon l'application P -> P+S (contrôle=1).
Utilisée pour les courbes plus grandes. Implémentée dans quantum_arithmetic.py.
Au lieu de construire des matrices denses, chaque permutation "add S" est décomposée en cycles, puis en transpositions. Chaque transposition (échange de deux états de base |a> <-> |b>) est implémentée avec :
Le MCX utilise une décomposition en chaîne en V avec (n-2) qubits ancilla dédiés, donnant O(n) portes Toffoli par MCX au lieu de O(n^2) sans ancillas. Chaque addition contrôlée est construite comme un sous-circuit isolé et ajoutée comme une porte opaque unique, évitant une croissance quadratique du DAG dans Qiskit.
--oracle coordinate)Disponible pour les courbes jusqu'à ~6 bits. Implémentée dans quantum_oracle.py.
Au lieu d'encoder les points comme des indices de groupe, le registre quantique contient les coordonnées de champ (x, y) réelles en binaire plus un indicateur d'identité. La disposition du registre de points est :
x_reg : f_bits qubits (f_bits = ceil(log2(p)))y_reg : f_bits qubitsid_flag : 1 qubit (1 = point à l'infini)Chaque "add S" contrôlé est calculé à partir de la formule d'addition EC sur tous les encodages de coordonnées valides, produisant une permutation sur le registre de coordonnées. Cette permutation est décomposée en cycles puis en transpositions en utilisant la même infrastructure de réduction CNOT + MCX que la Stratégie 2.
--oracle arithmetic)Cadre pour l'addition de points à mise à l'échelle polynomiale. Implémentée dans quantum_oracle.py et quantum_arithmetic.py.
Utilise l'encodage par coordonnées (identique à la Stratégie 3) avec des primitives arithmétiques modulaires basées sur la QFT comme éléments de base pour l'addition de points entièrement arithmétique. La base de code comprend des implémentations testées de :
Les primitives arithmétiques atteignent une mise à l'échelle O(n^3) par addition de point contre O(N*n) pour l'approche par permutation. Cependant, les opérations basées sur la QFT ont un facteur constant environ 150 fois plus grand, rendant l'approche arithmétique plus efficace uniquement pour les courbes au-delà de ~20 bits d'ordre de groupe. Pour les tailles de défi actuelles (jusqu'à 12 bits), l'additionneur par permutation reste plus rapide et est utilisé par défaut.
--oracle google)Implémentée dans google_semiclassical.py. Inspirée de la technique d'estimation de phase à recyclage de qubits de Griffiths & Niu (1996), appliquée à grande échelle dans Babbush et al. (2026) pour les estimations de ressources ECDLP secp256k1. L'article de Babbush et al. a été publié le 30 mars 2026.
Remplace les deux registres de comptage multi-qubits (j, k) et la QFT inverse globale par deux qubits recyclés uniques et des corrections de phase conditionnées classiquement. Chaque bit du registre de comptage est traité séquentiellement : préparer en |+>, appliquer l'addition de point contrôlée, corriger la phase en fonction de tous les bits précédemment mesurés, puis mesurer. Les primitives de circuit dynamique reset + if_test dans Qiskit permettent cela sur le matériel IBM Quantum.
L'oracle pour les additions de points contrôlées est délégué à l'infrastructure existante (unitaire dense pour <= 6 bits, permutation efficace pour > 6 bits), donc les économies de qubits proviennent entièrement de la suppression des registres de comptage.
--oracle ripple)Implémentée dans ripple_carry_shor.py. Utilise des additionneurs à propagation de retenue CDKM (Cuccaro et al. 2004) pour les additions de points contrôlées, remplaçant à la fois les matrices unitaires denses et les circuits de transposition décomposés en cycles.
Dans l'encodage par indice de groupe, le point P = kG est représenté par son indice k dans le groupe cyclique. Ajouter S = sG devient une addition modulaire de la constante classique s (mod n). L'idée clé : chaque addition de point contrôlée se réduit à une unique addition modulaire contrôlée d'une constante connue, implémentée via CDKMRippleCarryAdder et IntegerComparator de Qiskit.
L'oracle consiste en 2m additions modulaires contrôlées (m par registre de comptage), où chaque addition modulaire contrôlée effectue :
Aucune connaissance de la clé privée d n'est utilisée dans la construction du circuit. Les indices de groupe pour les puissances de G sont calculés comme 2^i mod n (publics). Les indices de groupe pour les puissances de Q sont dérivés de l'énumération publique du groupe cyclique généré par G — le point Q est recherché dans cette énumération.
La base de code inclut des blocs de construction arithmétiques modulaires basés sur la QFT (additionneurs Beauregard/Draper, multiplication modulaire quantique-quantique, inverse/négation modulaire) en tant que base vers un encodage par coordonnées entièrement arithmétique à 256 bits. Ces primitives ont été vérifiées correctes via simulation Statevector pour des nombres premiers jusqu'à p=13.
Clés privées récupérées avec succès sur du matériel quantique IBM pour des courbes du défi jusqu'à 17 bits :
Toutes les exécutions ont été effectuées sur le plan open-instance d'IBM Quantum, qui accorde 10 minutes de calcul quantique gratuit par mois. Les journaux d'exécution complets se trouvent dans le dossier executions/.
La stratégie de propagation de retenue (Stratégie 6) a permis un bond majeur : de 10 bits (40 qubits, 2M portes) à 17 bits (69 qubits, 112K portes) — une augmentation de 7 bits de la taille de clé avec une réduction de 18x du nombre de portes deux-qubits. La structure de portes voisines les plus proches de l'additionneur CDKM se mappe efficacement sur la topologie heavy-hex d'IBM, maintenant la surcharge de routage près de 1x.
La stratégie semi-classique (--oracle google) a récupéré avec succès des clés à 4, 6 et 7 bits en utilisant des circuits dynamiques (reset en cours de circuit, portes p conditionnées classiquement via if_test) sur les processeurs IBM Heron r2. À 7 bits, le circuit n'utilise que 14 qubits (contre 26 pour l'approche par permutation standard) tout en produisant des nombres de portes 2Q comparables après transpilation.
À 8 bits et au-delà, l'approche semi-classique devient impraticable sur le matériel IBM actuel. Bien que if_else et reset soient supportés sur Heron r2 (confirmé par inspection de la cible du backend), chaque point de retour classique nécessite une synchronisation complète du QPU — les 156 qubits physiques doivent être inactifs pendant que le contrôleur classique traite le conditionnel pour les ~16 qubits actifs. Avec ~295K portes CZ réparties sur 16+ points de retour, la surcharge d'exécution par shot dépasse le budget de temps QPU. L'approche par permutation standard, qui exécute le même nombre de portes en un seul lot continu sans circuits dynamiques, se termine avec succès à cette échelle.
Une troncature approximative de la QFT (paramètre max_corrections) réduit le nombre de blocs if_else de O(n^2) à O(n) en ne conservant que les k corrections de phase les plus proches par étape de mesure (les angles au-delà de k contribuent < pi/2^{k+1}, en dessous du plancher de bruit matériel). Avec max_corrections=1, le circuit 8 bits a 16 blocs if_else — encore suffisant pour provoquer un dépassement de temps sur le matériel IBM à ce nombre de portes.
En supposant une fidélité typique de porte deux-qubits (CX) IBM Quantum d'environ 99,5 %, la fidélité estimée du circuit décroît exponentiellement avec le nombre de portes :
La fidélité du circuit est calculée comme F ≈ (0,995)^{CX_count}. Au-delà de 4 bits, la fidélité estimée est astronomiquement faible — la distribution de sortie est massivement dominée par le bruit.
Pour 8 bits et plus, chaque shot produit un bitstring quasi unique (8 128 résultats uniques sur 8 192 shots à 8 bits ; les 20 000 uniques à 16 et 17 bits). La sortie est indiscernable d'un échantillonnage aléatoire uniforme au niveau du bitstring. Pourtant, l'algorithme récupère toujours la clé privée correcte.
L'idée clé est que le post-traitement de Shor est robuste au bruit d'une manière que l'analyse brute des bitstrings ne l'est pas. Chaque shot produit un triplet de mesure (j, k, r). L'extraction calcule d_cand = (r - j) · k^{-1} mod n et vérifie via d_cand · G == Q. Seul le vrai d passe la vérification EC, donc même un seul candidat correct parmi des milliers de shots bruités suffit.
Un triplet (j, k, r) purement aléatoire produit le d_cand correct avec une probabilité d'environ 1/n. Avec S shots, le nombre attendu de coups vérifiés provenant uniquement du bruit est d'environ S/n. À 17 bits (n=65 173, S=20 000), cela donne environ 0,3 coup de bruit attendu — toute récupération réussie à cette échelle fournit une preuve de signal quantique au-delà du plancher de bruit classique.
Pour les courbes plus petites où shots >> n (par exemple, 10 bits avec n=547 et 1 024 shots), le plancher de bruit est d'environ 1 024/547 ≈ 1,9 votes par candidat. Même une poignée de shots porteurs de signal pousse le d correct au-dessus du plancher de bruit. Cela explique comment l'algorithme réussit malgré des fidélités de circuit qui sembleraient rendre le calcul impossible.
À l'échelle de jouet, l'étape de vérification de l'extraction (d_cand * G == Q) agit comme un filtre qui n'accepte que le vrai d. Cela signifie que même des triplets (j, k, r) purement aléatoires produiront des candidats valides à un taux d'environ shots / n par exécution. Lorsque shots >> n, le bruit aléatoire seul peut récupérer d avec une probabilité élevée.
Pour tester si le circuit quantique contribue un signal au-delà de ce plancher de bruit classique, nous avons exécuté le défi 6 bits (n=31) avec seulement 8 shots (bien en dessous de l'ordre du groupe) 10 fois sur ibm_kingston :
Résultat : 4/10 succès (40 %) contre une ligne de base de bruit classique d'environ 20 % (calculée par simulation Monte Carlo : 8 bitstrings aléatoires avec (r-j)*k_inv mod 31 filtrés par vérification). Test binomial unilatéral : P(X >= 4 | n=10, p=0,20) = 0,121, indiquant une amélioration de 2x par rapport au plancher de bruit. Bien que non statistiquement significatif individuellement à p < 0,05 (ce qui nécessiterait 5+ succès), le taux observé est cohérent avec un signal quantique contribuant environ 1-2 paires (j, k) valides supplémentaires par exécution par rapport à ce que le hasard fournirait.
Ce résultat se situe entre le plancher de bruit classique et le régime d'avantage quantique théorique. Pour des tailles de courbe plus grandes où n >> shots, la ligne de base de bruit tombe en dessous de 1 % et toute récupération réussie de clé devient une preuve solide de calcul quantique.
git clone https://github.com/GiancarloLelli/quantum.git cd quantum
python -m venv . Scripts\Activate.ps1 # For Windows only
pip install -r requirements.txt
### Comment exécuter
Vous avez besoin d'un compte [IBM Quantum](https://quantum.ibm.com/). Passez votre jeton API lors de la première exécution et il sera sauvegardé localement :```bash
# Solve the 4-bit challenge curve:
python projecteleven.py --challenge 4 --token YOUR_IBM_TOKEN --backend ibm_marrakesh
# Subsequent runs (token already saved):
python projecteleven.py --challenge 4 --backend ibm_marrakesh
# Use the coordinate-based quantum oracle:
python projecteleven.py --challenge 4 --oracle coordinate --backend ibm_marrakesh
# Use the arithmetic oracle (coordinate encoding + QFT primitives):
python projecteleven.py --challenge 4 --oracle arithmetic --backend ibm_marrakesh
# Use ripple-carry modular addition (CDKM — best for 8-bit+):
python projecteleven.py --challenge 16 --oracle ripple --backend ibm_fez --shots 20000
# Use Google semiclassical phase estimation (qubit-recycled):
python projecteleven.py --challenge 4 --oracle google --backend ibm_marrakesh
# Use a specific IBM Quantum instance:
python projecteleven.py --challenge 4 --instance ibm-q/open/main --backend ibm_marrakesh
# Verify curve parameters without quantum execution:
python projecteleven.py --curve curve_4 --verify-only
projecteleven.py # Shor solver — dense unitary approach + CLI entry point quantum_arithmetic.py # Efficient permutation decomposition + QFT arithmetic primitives quantum_oracle.py # Coordinate-based oracle + arithmetic oracle framework google_semiclassical.py # Google semiclassical PE — qubit-recycled phase estimation ripple_carry_shor.py # Ripple-carry modular addition oracle (CDKM) — best for 8-bit+ input_curves.json # Challenge curves (4-bit to 30-bit) problem/curves.py # Curve generation utility requirements.txt # qiskit, qiskit-ibm-runtime
## Références
- P. Shor, ["Algorithmes pour le calcul quantique : logarithmes discrets et factorisation"](https://arxiv.org/abs/quant-ph/9508027) (1994)
- S. Beauregard, ["Circuit pour l'algorithme de Shor utilisant 2n+3 qubits"](https://arxiv.org/abs/quant-ph/0205095) (2003)
- S. A. Cuccaro, T. G. Draper, S. A. Kutin, D. P. Moulton, ["Un nouveau circuit d'addition par ripple-carry quantique"](https://arxiv.org/abs/quant-ph/0410184) (2004)
- M. Roetteler, M. Naehrig, K. Svore, K. Lauter, ["Estimations de ressources quantiques pour le calcul de logarithmes discrets sur courbes elliptiques"](https://arxiv.org/abs/1706.06752) (2017)
- R. Griffiths, C.-S. Niu, ["Transformée de Fourier semi-classique pour le calcul quantique"](https://arxiv.org/abs/quant-ph/9511007) (1996)
- R. Babbush et al., ["Sécuriser les cryptomonnaies à courbe elliptique contre les vulnérabilités quantiques : estimations de ressources et atténuations"](https://quantumai.google/static/site-assets/downloads/cryptocurrency-whitepaper.pdf) (2026)
## Licence
Ce projet est une soumission au Q-Day Prize Challenge publié sous [MIT LICENSE](https://github.com/giancarlolelli/quantum/blob/HEAD/LICENSE)
| Taille de courbe | Qubits standard | Qubits semi-classiques | Économie | Vérifié sur matériel |
|---|
| 4 bits (n=7) | 11 | 5 | 55% | Oui |
| 6 bits (n=31) | 17 | 7 | 59% | Oui |
| 7 bits (n=79) | 26 + anc | 14 | 46% | Oui |
| 8 bits (n=139) | 25 + anc | 10 + anc | 60% | Non (surcharge de synchronisation QPU) |
| 10 bits (n=547) | 31 + anc | 12 + anc | 61% | Non (surcharge de synchronisation QPU) |
| Taille de courbe | Qubits | Portes 2Q (transpilées) | Vérifié sur matériel |
|---|
| 4 bits (n=7) | 17 | 1 824 | Oui (simulation) |
| 8 bits (n=139) | 37 | 11 224 | — |
| 10 bits (n=547) | 45 | 17 204 | — |
| 12 bits (n=2143) | 53 | 24 304 | — |
| 16 bits (n=32497) | 65 | 98 049 | Oui |
| 17 bits (n=65173) | 69 | 111 816 | Oui |
| Métrique | Unitaire dense | Permutation efficace | Oracle coordonnées | Oracle arithmétique | PE semi-classique | Propagation retenue |
|---|
| Encodage des points | Indice de groupe | Indice de groupe | (x, y, id_flag) | (x, y, id_flag) | Indice de groupe | Indice de groupe |
| Mise à l'échelle par addition | O(4^n) décomp. | O(N * n) | O(N * f_bits) | O(n^3) asymptotique | O(N * n) | O(m^2) |
| Qubits (4 bits) | 11 | 13 | 24 | 24 | 5 | 17 |
| Qubits (6 bits) | 17 | 21 | 36 | 36 | 9 | 25 |
| Portes 2Q (4 bits) | 774 | ~1 200 | 6 449 | 6 449 | ~1 200 | 1 824 |
| Portes 2Q (6 bits) | 23 471 | ~38 000 | 95 254 | 95 254 | ~38 000 | 4 582 |
| Plage pratique | <= 6 bits | <= ~16 bits | <= 6 bits | >= 20 bits (futur) | <= ~16 bits | <= ~20 bits |
| Défi | p | n | Stratégie | Qubits | Portes 2Q | Profondeur transpilée | Shots | Backend | d récupéré | Job ID |
|---|
| 4 bits | 13 | 7 | Unitaire dense | 11 | 774 | 2 425 | 8 192 | ibm_torino | 6 | d73u28kvllmc73anvi90 |
| 4 bits | 13 | 7 | Oracle coordonnées | 24 | 6 449 | 13 125 | 8 192 | ibm_kingston | 6 | d74ht798qmgc73fm32c0 |
| 4 bits | 13 | 7 | Oracle arithmétique | 24 | 6 477 | 13 452 | 8 192 | ibm_torino | 6 | d75648lbjrds73ec0eng |
| 4 bits | 13 | 7 | PE semi-classique | 5 | 747 | 2 522 | 256 | ibm_kingston | 6 | d75p1ftbjrds73ecne3g |
| 6 bits | 43 | 31 | Unitaire dense | 17 | 23 471 | 72 475 | 8 192 | ibm_torino | 18 | d73u2l5koquc73e24u8g |
| 6 bits | 43 | 31 | Oracle coordonnées | 36 | 95 254 | 169 766 | 8 192 | ibm_kingston | 18 | d74hu918qmgc73fm33g0 |
| 6 bits | 43 | 31 | PE semi-classique | 7 | 23 256 | 73 183 | 256 | ibm_kingston | 18 | d75p1unq1anc738cmr6g |
| 7 bits | 67 | 79 | PE semi-classique | 14 | 127 918 | 266 122 | 256 | ibm_kingston | 56 | d75p3sq3qcgc73fs2fpg |
| 8 bits | 163 | 139 | Permutation efficace | 32 | 294 628 | 599 517 | 8 192 | ibm_kingston | 103 | d73ui15koquc73e25e4g |
| 9 bits | 349 | 313 | Permutation efficace | 36 | 887 544 | 1 764 266 | 8 192 | ibm_torino | 135 | d73ua2h8qmgc73flei9g |
| 10 bits | 547 | 547 | Permutation efficace | 40 | 2 049 138 | 3 948 250 | 1 024 | ibm_torino | 165 | d752vfu8faus73evhovg |
| 16 bits | 32 803 | 32 497 | Propagation retenue | 65 | 98 049 | 202 994 | 20 000 | ibm_fez | 20 248 | d790j2hq1efs73d2979g |
| 17 bits | 65 647 | 65 173 | Propagation retenue | 69 | 111 816 | 231 475 | 20 000 | ibm_fez | 1 441 | d790krrc6das739idasg |
| Défi | Stratégie | Portes 2Q | Fidélité circ. estimée | Résultats uniques | Shots totaux | Régime de signal |
|---|
| 4 bits | Dense | 774 | ~2,1% | 1 869 / 2 048 | 8 192 | Signal faible |
| 6 bits | Dense | 23 471 | ~10^{-51} | 3 776 / 131 072 | 8 192 | Dominé par le bruit |
| 8 bits | Permutation | 294 628 | ~10^{-644} | 8 128 / 4,3B | 8 192 | Dominé par le bruit |
| 9 bits | Permutation | 887 544 | ~10^{-1 939} | 8 168 / 68,7B | 8 192 | Dominé par le bruit |
| 10 bits | Permutation | 2 049 138 | ~10^{-4 477} | 1 024 / 1,1T | 1 024 | Dominé par le bruit |
| 16 bits | Propagation retenue | 98 049 | ~10^{-214} | 20 000 / 2^65 | 20 000 | Dominé par le bruit |
| 17 bits | Propagation retenue | 111 816 | ~10^{-244} | 20 000 / 2^69 | 20 000 | Dominé par le bruit |
| Exécution | Job ID | Résultat |
|---|
| 1 | d75qrrq3qcgc73fs4hn0 | ÉCHEC |
| 2 | d75qs3e8faus73f0ep6g | ÉCHEC |
| 3 | d75qsafq1anc738coujg | ÉCHEC |
| 4 | d75qsie8faus73f0eplg | d = 18 |
| 5 | d75qsq23qcgc73fs4ing | d = 18 |
| 6 | d75qt168faus73f0eq50 | ÉCHEC |
| 7 | d75qt7vq1anc738covf0 | d = 18 |
| 8 | d75qthu8faus73f0eqmg | ÉCHEC |
| 9 | d75qtodbjrds73ecpk80 | d = 18 |
| 10 | d75qtvi3qcgc73fs4jsg | ÉCHEC |
| Drapeau | Description | Par défaut |
|---|
--challenge N | Résolvez la courbe de défi à N bits à partir de input_curves.json | — |
--curve NAME | Utilisez une courbe de test intégrée (curve_4) | — |
--token TOKEN | Jeton API IBM Quantum (enregistré localement lors de la première utilisation) | — |
--backend NAME | Backend IBM Quantum | ibm_marrakesh |
--instance ID | Instance IBM Quantum | open-instance |
--shots N | Nombre de mesures | 8192 |
--oracle TYPE | Stratégie Oracle : dense, permutation, coordinate, arithmetic, google ou ripple | auto |
--optimization-level N | Niveau d'optimisation de la transpilation Qiskit (0-3) | 3 |
--d N | Clé secrète connue pour les tests (avec --curve) | — |
--verify-only | Valider les paramètres de la courbe et quitter | — |