
Este repositorio contiene el código y los detalles de la presentación para el desafío del premio QDay de https://www.projecteleven.com/
Solucionador cuántico para el Problema del Logaritmo Discreto de Curva Elíptica (ECDLP), construido para el Q-Day Prize Challenge por Project Eleven. El objetivo: recuperar claves privadas ECC en hardware cuántico real utilizando el algoritmo de Shor.
Todas las curvas del desafío usan y^2 = x^3 + 7 sobre F_p (a = 0, b = 7), coincidiendo con la familia secp256k1. El solucionador implementa la variante de dos registros del algoritmo de Shor para ECDLP:
La clave privada d se recupera recolectando múltiples muestras (j, k) que satisfacen la misma relación lineal módulo el orden del grupo n. El solucionador admite seis estrategias de oráculo para las adiciones de puntos controladas, seleccionadas automáticamente según el tamaño de la curva o manualmente mediante .
--oracleUsada para curvas con orden de grupo de hasta ~6 bits. Implementada en projecteleven.py.
Cada adición de punto controlada "añadir S" se representa como una matriz de permutación de 2^(n+1) x 2^(n+1) aplicada mediante qc.unitary(). La matriz codifica la acción completa del grupo: el bloque superior izquierdo es identidad (control=0), el bloque inferior derecho permuta los estados base según el mapa P -> P+S (control=1).
Usada para curvas más grandes. Implementada en quantum_arithmetic.py.
En lugar de construir matrices densas, cada permutación "añadir S" se descompone en ciclos como transposiciones. Cada transposición (intercambio de dos estados base |a> <-> |b>) se implementa con:
La MCX utiliza descomposición en cadena V con (n-2) qubits ancilla dedicados, proporcionando O(n) puertas Toffoli por MCX en lugar de O(n^2) sin ancillas. Cada adición controlada se construye como un subcircuito aislado y se agrega como una sola puerta opaca, evitando el crecimiento cuadrático del DAG en Qiskit.
--oracle coordinate)Disponible para curvas de hasta ~6 bits. Implementada en quantum_oracle.py.
En lugar de codificar puntos como índices de grupo, el registro cuántico contiene coordenadas reales (x, y) de elementos de campo en binario más una bandera de identidad. El diseño del registro de punto es:
x_reg: qubits f_bits (f_bits = ceil(log2(p)))y_reg: qubits f_bitsid_flag: 1 qubit (1 = punto en el infinito)Cada "añadir S" controlado se calcula a partir de la fórmula de adición EC sobre todas las codificaciones de coordenadas válidas, produciendo una permutación en el registro de coordenadas. Esta permutación se descompone en ciclos como transposiciones utilizando la misma infraestructura de reducción CNOT + MCX que la Estrategia 2.
--oracle arithmetic)Marco para la adición de puntos con escalado polinomial. Implementada en quantum_oracle.py y quantum_arithmetic.py.
Utiliza codificación de coordenadas (igual que la Estrategia 3) con primitivas de aritmética modular basadas en QFT como componentes básicos hacia la adición de puntos completamente aritmética. El código base incluye implementaciones probadas de:
Las primitivas aritméticas logran un escalado O(n^3) por adición de punto frente a O(N*n) para el enfoque de permutación. Sin embargo, las operaciones basadas en QFT conllevan un factor constante ~150 veces mayor, lo que hace que el enfoque aritmético sea más eficiente solo para curvas por encima del orden de grupo de ~20 bits. Para los tamaños de desafío actuales (hasta 12 bits), el sumador basado en permutación sigue siendo más rápido y se utiliza por defecto.
--oracle google)Implementada en google_semiclassical.py. Inspirada en la técnica de estimación de fase con reciclaje de qubits de Griffiths & Niu (1996), aplicada a escala en Babbush et al. (2026) para estimaciones de recursos de ECDLP en secp256k1. El artículo de Babbush et al. fue publicado el 30 de marzo de 2026.
Reemplaza los dos registros de conteo multiqubit (j, k) y la QFT inversa masiva con dos qubits reciclados individuales y correcciones de fase condicionadas clásicamente. Cada bit del registro de conteo se procesa secuencialmente: preparar en |+>, aplicar adición de punto controlada, corregir fase según todos los bits medidos previamente, luego medir. Los primitivos de circuito dinámico reset + if_test en Qiskit permiten esto en hardware IBM Quantum.
El oráculo para las adiciones de puntos controladas se delega en la infraestructura existente (unitario denso para <= 6 bits, permutación eficiente para > 6 bits), por lo que el ahorro de qubits proviene completamente de eliminar los registros de conteo.
| Tamaño de curva | Qubits estándar | Qubits semiclásicos | Ahorro | Verificado en hardware |
|---|---|---|---|---|
| 4 bits (n=7) | 11 | 5 | 55% | Sí |
| 6 bits (n=31) | 17 | 7 | 59% | Sí |
| 7 bits (n=79) | 26 + anc | 14 | 46% | Sí |
| 8 bits (n=139) | 25 + anc | 10 + anc | 60% | No (sobretiempo de sincronización QPU) |
| 10 bits (n=547) | 31 + anc | 12 + anc | 61% | No (sobretiempo de sincronización QPU) |
--oracle ripple)Implementada en ripple_carry_shor.py. Utiliza sumadores ripple-carry CDKM (Cuccaro et al. 2004) para las adiciones de puntos controladas, reemplazando tanto las matrices unitarias densas como los circuitos de transposición descompuestos en ciclos.
En la codificación de índice de grupo, el punto P = kG se representa por su índice k en el grupo cíclico. Añadir S = sG se convierte en suma modular de la constante clásica s (mod n). La idea clave: cada adición de punto controlada se reduce a una única suma modular controlada de una constante conocida, implementada mediante CDKMRippleCarryAdder e IntegerComparator de Qiskit.
El oráculo consiste en 2m sumas modulares controladas (m por registro de conteo), donde cada suma modular controlada realiza:
No se utiliza conocimiento de la clave privada d en la construcción del circuito. Los índices de grupo para las potencias de G se calculan como 2^i mod n (públicos). Los índices de grupo para las potencias de Q se derivan de la enumeración pública del grupo cíclico generado por G — el punto Q se busca en esta enumeración.
| Tamaño de curva | Qubits | Puertas 2Q (transpilado) | Verificado en hardware |
|---|---|---|---|
| 4 bits (n=7) | 17 | 1,824 | Sí (simulación) |
| 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 | Sí |
| 17 bits (n=65173) | 69 | 111,816 | Sí |
| Métrica | Unitario Denso | Permutación Eficiente | Oráculo de Coordenadas | Oráculo Aritmético | PE Semiclásica | Ripple-Carry |
|---|---|---|---|---|---|---|
| Codificación de punto | Índice de grupo | Índice de grupo | (x, y, id_flag) | (x, y, id_flag) | Índice de grupo | Índice de grupo |
| Escalado por adición | O(4^n) descomp. | O(N * n) | O(N * f_bits) | O(n^3) asintótico | O(N * n) | O(m^2) |
| Qubits (4 bits) | 11 | 13 | 24 | 24 | 5 | 17 |
| Qubits (6 bits) | 17 | 21 | 36 | 36 | 9 | 25 |
| Puertas 2Q (4 bits) | 774 | ~1,200 | 6,449 | 6,449 | ~1,200 | 1,824 |
| Puertas 2Q (6 bits) | 23,471 | ~38,000 | 95,254 | 95,254 | ~38,000 | 4,582 |
| Rango práctico | <= 6 bits | <= ~16 bits | <= 6 bits | >= 20 bits (futuro) | <= ~16 bits | <= ~20 bits |
El código base incluye componentes básicos de aritmética modular basados en QFT (sumadores Beauregard/Draper, multiplicación modular cuántico-cuántico, inverso/negación modular) como base hacia la codificación de coordenadas completamente aritmética a 256 bits. Estas primitivas han sido verificadas correctas mediante simulación Statevector para primos hasta p=13.
Se recuperaron con éxito claves privadas en hardware IBM Quantum para curvas de desafío de hasta 17 bits:
| Desafío | p | n | Estrategia | Qubits | Puertas 2Q | Profundidad transpilada | Disparos | Backend | d recuperado | ID de trabajo |
|---|---|---|---|---|---|---|---|---|---|---|
| 4 bits | 13 | 7 | Unitario denso | 11 | 774 | 2,425 | 8,192 | ibm_torino | 6 | d73u28kvllmc73anvi90 |
| 4 bits | 13 | 7 | Oráculo de coordenadas | 24 | 6,449 | 13,125 | 8,192 | ibm_kingston | 6 | d74ht798qmgc73fm32c0 |
| 4 bits | 13 | 7 | Oráculo aritmético | 24 | 6,477 | 13,452 | 8,192 | ibm_torino | 6 | d75648lbjrds73ec0eng |
| 4 bits | 13 | 7 | PE semiclásica | 5 | 747 | 2,522 | 256 | ibm_kingston | 6 | d75p1ftbjrds73ecne3g |
| 6 bits | 43 | 31 | Unitario denso | 17 | 23,471 | 72,475 | 8,192 | ibm_torino | 18 | d73u2l5koquc73e24u8g |
| 6 bits | 43 | 31 | Oráculo de coordenadas | 36 | 95,254 | 169,766 | 8,192 | ibm_kingston | 18 | d74hu918qmgc73fm33g0 |
| 6 bits | 43 | 31 | PE semiclásica | 7 | 23,256 | 73,183 | 256 | ibm_kingston | 18 | d75p1unq1anc738cmr6g |
| 7 bits | 67 | 79 | PE semiclásica | 14 | 127,918 | 266,122 | 256 | ibm_kingston | 56 | d75p3sq3qcgc73fs2fpg |
| 8 bits | 163 | 139 | Permutación eficiente | 32 | 294,628 | 599,517 | 8,192 | ibm_kingston | 103 | d73ui15koquc73e25e4g |
| 9 bits | 349 | 313 | Permutación eficiente | 36 | 887,544 | 1,764,266 | 8,192 | ibm_torino | 135 | d73ua2h8qmgc73flei9g |
| 10 bits | 547 | 547 |
Todas las ejecuciones se realizaron en el plan de instancia abierta de IBM Quantum, que otorga 10 minutos de computación cuántica gratuita por mes. Los registros completos de ejecución se encuentran en la carpeta executions/.
La estrategia ripple-carry (Estrategia 6) permitió un gran salto: de 10 bits (40 qubits, 2M puertas) a 17 bits (69 qubits, 112K puertas) — un incremento de 7 bits en el tamaño de clave con una reducción de 18x en el recuento de puertas de dos qubits. La estructura de puertas de vecino más cercano del sumador CDKM se mapea eficientemente a la topología heavy-hex de IBM, manteniendo la sobrecarga de enrutamiento cerca de 1x.
La estrategia semiclásica (--oracle google) recuperó con éxito claves a 4, 6 y 7 bits utilizando circuitos dinámicos (reset en medio del circuito, puertas p condicionadas clásicamente mediante if_test) en procesadores IBM Heron r2. A 7 bits, el circuito utiliza solo 14 qubits (frente a 26 para el enfoque de permutación estándar) mientras produce recuentos de puertas 2Q comparables después de la transpilación.
A 8 bits y más, el enfoque semiclásico se vuelve impracticable en el hardware actual de IBM. Aunque if_else y reset son compatibles en Heron r2 (confirmado mediante inspección del backend objetivo), cada punto de retroalimentación clásica requiere una sincronización completa de la QPU — los 156 qubits físicos deben estar inactivos mientras el controlador clásico procesa la condicional para los ~16 qubits activos. Con ~295K puertas CZ divididas en 16+ puntos de retroalimentación, la sobrecarga de ejecución por disparo hace que los trabajos excedan el presupuesto de tiempo de la QPU. El enfoque de permutación estándar, que ejecuta el mismo recuento de puertas como un solo lote continuo sin circuitos dinámicos, se completa con éxito a esta escala.
Una truncación aproximada de QFT (parámetro max_corrections) reduce el número de bloques if_else de O(n^2) a O(n) al retener solo las k correcciones de fase más cercanas por paso de medición (los ángulos más allá de k contribuyen < pi/2^{k+1}, por debajo del piso de ruido del hardware). Con max_corrections=1, el circuito de 8 bits tiene 16 bloques if_else — aún suficiente para causar tiempo de espera en hardware IBM con este recuento de puertas.
Suponiendo una fidelidad típica de puerta de dos qubits (CX) de ~99.5% en IBM Quantum, la fidelidad estimada del circuito cae exponencialmente con el recuento de puertas:
| Desafío | Estrategia | Puertas 2Q | Fid. Est. del Circuito | Resultados Únicos | Disparos Totales | Régimen de Señal |
|---|---|---|---|---|---|---|
| 4 bits | Denso | 774 | ~2.1% | 1,869 / 2,048 | 8,192 | Señal débil |
| 6 bits | Denso | 23,471 | ~10^{-51} | 3,776 / 131,072 | 8,192 | Dominado por ruido |
| 8 bits | Permutación | 294,628 | ~10^{-644} | 8,128 / 4.3B | 8,192 | Dominado por ruido |
| 9 bits | Permutación | 887,544 | ~10^{-1,939} | 8,168 / 68.7B | 8,192 | Dominado por ruido |
| 10 bits | Permutación | 2,049,138 | ~10^{-4,477} | 1,024 / 1.1T | 1,024 | Dominado por ruido |
| 16 bits | Ripple-carry | 98,049 | ~10^{-214} | 20,000 / 2^65 | 20,000 | Dominado por ruido |
| 17 bits | Ripple-carry | 111,816 | ~10^{-244} | 20,000 / 2^69 | 20,000 | Dominado por ruido |
La fidelidad del circuito se calcula como F ≈ (0.995)^{CX_count}. Para todo más allá de 4 bits, la fidelidad estimada es astronómicamente pequeña — la distribución de salida está abrumadoramente dominada por ruido.
Para 8 bits y más, cada disparo produce una cadena de bits casi única (8,128 resultados únicos de 8,192 disparos a 8 bits; los 20,000 únicos a 16 y 17 bits). La salida es indistinguible de un muestreo aleatorio uniforme a nivel de cadena de bits. Sin embargo, el algoritmo aún recupera la clave privada correcta.
La idea clave es que el postprocesamiento de Shor es robusto al ruido de una manera que el análisis bruto de cadenas de bits no lo es. Cada disparo produce un triple de medición (j, k, r). La extracción calcula d_cand = (r - j) · k^{-1} mod n y verifica mediante d_cand · G == Q. Solo la verdadera d pasa la verificación EC, por lo que incluso un único candidato correcto entre miles de disparos ruidosos es suficiente.
Un triple (j, k, r) puramente aleatorio produce el d_cand correcto con probabilidad ~1/n. Con S disparos, el número esperado de aciertos verificados del ruido solo es ~S/n. A 17 bits (n=65,173, S=20,000), esto da ~0.3 aciertos de ruido esperados — cualquier recuperación exitosa a esta escala proporciona evidencia de señal cuántica más allá del piso de ruido clásico.
Para las curvas más pequeñas donde disparos >> n (por ejemplo, 10 bits con n=547 y 1,024 disparos), el piso de ruido es ~1,024/547 ≈ 1.9 votos por candidato. Incluso un puñado de disparos que contienen señal empuja la d correcta por encima del piso de ruido. Esto explica cómo el algoritmo tiene éxito a pesar de fidelidades de circuito que harían parecer imposible la computación.
A escala de juguete, el paso de verificación de la extracción (d_cand * G == Q) actúa como un filtro que acepta solo la d verdadera. Esto significa que incluso los triples (j, k, r) puramente aleatorios producirán candidatos válidos a una tasa de aproximadamente disparos / n por ejecución. Cuando disparos >> n, el ruido aleatorio solo puede recuperar d con alta probabilidad.
Para probar si el circuito cuántico contribuye con señal más allá de este piso de ruido clásico, ejecutamos el desafío de 6 bits (n=31) con solo 8 disparos (muy por debajo del orden del grupo) 10 veces en ibm_kingston:
| Ejecución | ID de trabajo | Resultado |
|---|---|---|
| 1 | d75qrrq3qcgc73fs4hn0 | FALLO |
| 2 | d75qs3e8faus73f0ep6g | FALLO |
| 3 | d75qsafq1anc738coujg | FALLO |
| 4 | d75qsie8faus73f0eplg | d = 18 |
| 5 | d75qsq23qcgc73fs4ing | d = 18 |
| 6 | d75qt168faus73f0eq50 | FALLO |
| 7 | d75qt7vq1anc738covf0 | d = 18 |
| 8 | d75qthu8faus73f0eqmg | FALLO |
| 9 | d75qtodbjrds73ecpk80 | d = 18 |
| 10 | d75qtvi3qcgc73fs4jsg | FALLO |
Resultado: 4/10 éxitos (40%) frente a una línea base de ruido clásico de ~20% (calculada mediante simulación Monte Carlo: 8 cadenas de bits aleatorias con (r-j)*k_inv mod 31 filtradas por verificación). Prueba binomial de una cola: P(X >= 4 | n=10, p=0.20) = 0.121, indicando una mejora de 2x sobre el piso de ruido. Aunque no es estadísticamente significativa individualmente a p < 0.05 (que requeriría 5+ éxitos), la tasa observada es consistente con una señal cuántica que contribuye aproximadamente 1-2 pares (j, k) adicionales válidos por ejecución más allá de lo que proporciona el azar.
Este resultado se sitúa entre el piso de ruido clásico y el régimen de ventaja cuántica teórica. En tamaños de curva más grandes donde n >> disparos, la línea base de ruido cae por debajo del 1% y cualquier recuperación exitosa de clave se convierte en evidencia sólida de computación cuántica.
git clone https://github.com/GiancarloLelli/quantum.git cd quantum
python -m venv . Scripts\Activate.ps1 # For Windows only
pip install -r requirements.txt
### Cómo ejecutar
Necesitas una cuenta de [IBM Quantum](https://quantum.ibm.com/). Proporciona tu token de API en la primera ejecución y se guardará localmente:```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
| Bandera | Descripción | Por defecto |
|---|---|---|
--challenge N | Resuelve la curva de desafío de N bits de input_curves.json | — |
--curve NAME | Usa una curva de prueba incorporada (curve_4) | — |
--token TOKEN | Token de API de IBM Quantum (guardado localmente en el primer uso) | — |
--backend NAME | Backend de IBM Quantum | ibm_marrakesh |
--instance ID | Instancia de IBM Quantum | open-instance |
--shots N | Número de disparos de medición | 8192 |
--oracle TYPE | Estrategia de oráculo: dense, permutation, coordinate, arithmetic, google o ripple | auto |
--optimization-level N | Nivel de optimización de transpilación de Qiskit (0-3) | 3 |
--d N | Clave secreta conocida para pruebas (con --curve) | — |
--verify-only | Valida los parámetros de la curva y sale | — |
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
## Referencias
- P. Shor, ["Algoritmos para Computación Cuántica: Logaritmos Discretos y Factorización"](https://arxiv.org/abs/quant-ph/9508027) (1994)
- S. Beauregard, ["Circuito para el algoritmo de Shor usando 2n+3 qubits"](https://arxiv.org/abs/quant-ph/0205095) (2003)
- S. A. Cuccaro, T. G. Draper, S. A. Kutin, D. P. Moulton, ["Un nuevo circuito cuántico de suma ripple-carry"](https://arxiv.org/abs/quant-ph/0410184) (2004)
- M. Roetteler, M. Naehrig, K. Svore, K. Lauter, ["Estimaciones de recursos cuánticos para el cálculo de logaritmos discretos en curvas elípticas"](https://arxiv.org/abs/1706.06752) (2017)
- R. Griffiths, C.-S. Niu, ["Transformada de Fourier Semiclásica para Computación Cuántica"](https://arxiv.org/abs/quant-ph/9511007) (1996)
- R. Babbush et al., ["Asegurando Criptomonedas de Curva Elíptica contra Vulnerabilidades Cuánticas: Estimaciones de Recursos y Mitigaciones"](https://quantumai.google/static/site-assets/downloads/cryptocurrency-whitepaper.pdf) (2026)
## Licencia
Este proyecto es una presentación al desafío Q-Day Prize, publicado bajo [LICENCIA MIT](https://github.com/giancarlolelli/quantum/blob/main/LICENSE)
| Permutación eficiente |
| 40 |
| 2,049,138 |
| 3,948,250 |
| 1,024 |
| ibm_torino |
| 165 |
| d752vfu8faus73evhovg |
| 16 bits | 32,803 | 32,497 | Ripple-carry | 65 | 98,049 | 202,994 | 20,000 | ibm_fez | 20,248 | d790j2hq1efs73d2979g |
| 17 bits | 65,647 | 65,173 | Ripple-carry | 69 | 111,816 | 231,475 | 20,000 | ibm_fez | 1,441 | d790krrc6das739idasg |